diff src/xterm.c @ 53069:1218a42792ea

Implement multiple display handling for GTK.
author Jan Djärv <jan.h.d@swipnet.se>
date Sun, 16 Nov 2003 16:05:24 +0000
parents 4835b200fafe
children bf86de5f6d07
line wrap: on
line diff
--- a/src/xterm.c	Sun Nov 16 14:08:34 2003 +0000
+++ b/src/xterm.c	Sun Nov 16 16:05:24 2003 +0000
@@ -357,7 +357,7 @@
 static void x_update_begin P_ ((struct frame *));
 static void x_update_window_begin P_ ((struct window *));
 static void x_after_update_window_line P_ ((struct glyph_row *));
-static struct scroll_bar *x_window_to_scroll_bar P_ ((Window));
+static struct scroll_bar *x_window_to_scroll_bar P_ ((Display *, Window));
 static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *,
 					    enum scroll_bar_part *,
 					    Lisp_Object *, Lisp_Object *,
@@ -3777,7 +3777,9 @@
 	/* If not, is it one of our scroll bars?  */
 	if (! f1)
 	  {
-	    struct scroll_bar *bar = x_window_to_scroll_bar (win);
+	    struct scroll_bar *bar;
+
+            bar = x_window_to_scroll_bar (FRAME_X_DISPLAY (*fp), win);
 
 	    if (bar)
 	      {
@@ -3848,18 +3850,20 @@
 
 /* Scroll bar support.  */
 
-/* Given an X window ID, find the struct scroll_bar which manages it.
+/* Given an X window ID and a DISPLAY, find the struct scroll_bar which
+   manages it.
    This can be called in GC, so we have to make sure to strip off mark
    bits.  */
 
 static struct scroll_bar *
-x_window_to_scroll_bar (window_id)
+x_window_to_scroll_bar (display, window_id)
+     Display *display;
      Window window_id;
 {
   Lisp_Object tail;
 
 #ifdef USE_GTK
-  window_id = (Window) xg_get_scroll_id_for_window (window_id);
+  window_id = (Window) xg_get_scroll_id_for_window (display, window_id);
 #endif /* USE_GTK */
 
   for (tail = Vframe_list;
@@ -3873,6 +3877,9 @@
       if (! GC_FRAMEP (frame))
 	abort ();
 
+      if (FRAME_X_DISPLAY (XFRAME (frame)) != display)
+        continue;
+
       /* Scan this frame's scroll bar list for a scroll bar with the
          right window ID.  */
       condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
@@ -5669,7 +5676,6 @@
 #endif
 
 #ifdef USE_GTK
-static struct x_display_info *current_dpyinfo;
 static struct input_event **current_bufp;
 static int *current_numcharsp;
 static int current_count;
@@ -5684,26 +5690,34 @@
      GdkEvent *ev;
      gpointer data;
 {
-  XEvent *xev = (XEvent*)gxev;
+  XEvent *xev = (XEvent *) gxev;
 
   if (current_numcharsp)
     {
+      struct x_display_info *dpyinfo;
+
+      dpyinfo = x_display_info_for_display (xev->xany.display);
+
 #ifdef HAVE_X_I18N
       /* Filter events for the current X input method.
          GTK calls XFilterEvent but not for key press and release,
          so we do it here.  */
       if (xev->type == KeyPress || xev->type == KeyRelease)
-        if (x_filter_event (current_dpyinfo, xev))
+        if (dpyinfo && x_filter_event (dpyinfo, xev))
           return GDK_FILTER_REMOVE;
 #endif
-      current_count += handle_one_xevent (current_dpyinfo,
-                                          xev,
-                                          current_bufp,
-                                          current_numcharsp,
-                                          &current_finish);
+
+      if (! dpyinfo)
+        current_finish = X_EVENT_NORMAL;
+      else
+        current_count += handle_one_xevent (dpyinfo,
+                                            xev,
+                                            current_bufp,
+                                            current_numcharsp,
+                                            &current_finish);
     }
   else
-    current_finish = x_dispatch_event (xev, GDK_DISPLAY ());
+    current_finish = x_dispatch_event (xev, xev->xany.display);
 
   if (current_finish == X_EVENT_GOTO_OUT || current_finish == X_EVENT_DROP)
     return GDK_FILTER_REMOVE;
@@ -6043,7 +6057,8 @@
           /* Dispatch event to the widget.  */
           goto OTHER;
 #else /* not USE_TOOLKIT_SCROLL_BARS */
-          bar = x_window_to_scroll_bar (event.xexpose.window);
+          bar = x_window_to_scroll_bar (event.xexpose.display,
+                                        event.xexpose.window);
 
           if (bar)
             x_scroll_bar_expose (bar, &event);
@@ -6669,7 +6684,7 @@
                 /* Window will be selected only when it is not selected now and
                    last mouse movement event was not in it.  Minibuffer window
                    will be selected iff it is active.  */
-                if (WINDOWP(window)
+                if (WINDOWP (window)
                     && !EQ (window, last_window)
                     && !EQ (window, selected_window)
                     && numchars > 0)
@@ -6688,7 +6703,8 @@
           {
 #ifndef USE_TOOLKIT_SCROLL_BARS
             struct scroll_bar *bar
-              = x_window_to_scroll_bar (event.xmotion.window);
+              = x_window_to_scroll_bar (event.xmotion.display,
+                                        event.xmotion.window);
 
             if (bar)
               x_scroll_bar_note_movement (bar, &event);
@@ -6851,7 +6867,8 @@
         else
           {
             struct scroll_bar *bar
-              = x_window_to_scroll_bar (event.xbutton.window);
+              = x_window_to_scroll_bar (event.xbutton.display,
+                                        event.xbutton.window);
 
 #ifdef USE_TOOLKIT_SCROLL_BARS
             /* Make the "Ctrl-Mouse-2 splits window" work for toolkit
@@ -7012,9 +7029,7 @@
     EVENT_INIT (*bufpp);
   bufpp = bufp;
 
-  for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
-    if (dpyinfo->display == display)
-      break;
+  dpyinfo = x_display_info_for_display (display);
 
   if (dpyinfo)
     {
@@ -7116,30 +7131,7 @@
       UNBLOCK_INPUT;
 #endif
 
-#ifdef USE_GTK
-      /* For GTK we must use the GTK event loop.  But XEvents gets passed
-         to our filter function above, and then to the big event switch.
-         We use a bunch of globals to communicate with our filter function,
-         that is kind of ugly, but it works. */
-      current_dpyinfo = dpyinfo;
-
-      while (gtk_events_pending ())
-        {
-          current_count = count;
-          current_numcharsp = &numchars;
-          current_bufp = &bufp;
-
-          gtk_main_iteration ();
-
-          count = current_count;
-          current_bufp = 0;
-          current_numcharsp = 0;
-
-          if (current_finish == X_EVENT_GOTO_OUT)
-            goto out;
-        }
-
-#else /* not USE_GTK */
+#ifndef USE_GTK
       while (XPending (dpyinfo->display))
 	{
           int finish;
@@ -7162,8 +7154,35 @@
           if (finish == X_EVENT_GOTO_OUT)
             goto out;
         }
+#endif /* not USE_GTK */
+    }
+
+#ifdef USE_GTK
+
+  /* For GTK we must use the GTK event loop.  But XEvents gets passed
+     to our filter function above, and then to the big event switch.
+     We use a bunch of globals to communicate with our filter function,
+     that is kind of ugly, but it works.
+
+     There is no way to do one display at the time, GTK just does events
+     from all displays.  */
+
+  while (gtk_events_pending ())
+    {
+      current_count = count;
+      current_numcharsp = &numchars;
+      current_bufp = &bufp;
+
+      gtk_main_iteration ();
+
+      count = current_count;
+      current_bufp = 0;
+      current_numcharsp = 0;
+
+      if (current_finish == X_EVENT_GOTO_OUT)
+        break;
+    }
 #endif /* USE_GTK */
-    }
 
  out:;
 
@@ -7482,13 +7501,13 @@
   if (STRINGP (file))
     {
 #ifdef USE_GTK
-      /* Use gtk_window_set_icon_from_file() if available,
+      /* Use gtk_window_set_icon_from_file () if available,
 	 It's not restricted to bitmaps */
-      if (xg_set_icon(f, file))
+      if (xg_set_icon (f, file))
 	return 0;
 #endif /* USE_GTK */
       bitmap_id = x_create_bitmap_from_file (f, file);
-      x_create_bitmap_mask(f, bitmap_id);
+      x_create_bitmap_mask (f, bitmap_id);
     }
   else
     {
@@ -7498,7 +7517,7 @@
 	  FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
 	    = x_create_bitmap_from_data (f, gnu_bits,
 					 gnu_width, gnu_height);
-	  x_create_bitmap_mask(f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
+	  x_create_bitmap_mask (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
 	}
 
       /* The first time we create the GNU bitmap and mask,
@@ -7767,6 +7786,11 @@
     }
 #endif
 
+#ifdef USE_GTK
+  if (dpyinfo)
+    xg_display_close (dpyinfo->display);
+#endif
+
   /* Indicate that this display is dead.  */
   if (dpyinfo)
     dpyinfo->display = 0;
@@ -10211,60 +10235,65 @@
     char **argv2 = argv;
     GdkAtom atom;
 
-    /* GTK 2.0 can only handle one display, GTK 2.2 can handle more
-       than one, but this remains to be implemented.  */
-    if (x_initialized > 1)
-      error ("Sorry, the GTK port can only handle one display.");
-    ++x_initialized;
-
-    for (argc = 0; argc < NUM_ARGV; ++argc)
-      argv[argc] = 0;
-
-    argc = 0;
-    argv[argc++] = initial_argv[0];
-
-    if (! NILP (display_name))
+    if (x_initialized++ > 1)
+      {
+        /* Opening another display.  If xg_display_open returns less
+           than zero, we are probably on GTK 2.0, which can only handle
+           one display.  GTK 2.2 or later can handle more than one.  */
+        if (xg_display_open (SDATA (display_name), &dpy) < 0)
+          error ("Sorry, this version of GTK can only handle one display");
+     }
+    else
       {
-        argv[argc++] = "--display";
-        argv[argc++] = SDATA (display_name);
-      }
-
-    argv[argc++] = "--name";
-    argv[argc++] = resource_name;
+        for (argc = 0; argc < NUM_ARGV; ++argc)
+          argv[argc] = 0;
+
+        argc = 0;
+        argv[argc++] = initial_argv[0];
+
+        if (! NILP (display_name))
+          {
+            argv[argc++] = "--display";
+            argv[argc++] = SDATA (display_name);
+          }
+
+        argv[argc++] = "--name";
+        argv[argc++] = resource_name;
 
 #ifdef HAVE_X11R5
-    XSetLocaleModifiers ("");
-#endif
-
-    gtk_init (&argc, &argv2);
-
-    /* gtk_init does set_locale.  We must fix locale after calling it.  */
-    fixup_locale ();
-    xg_initialize ();
-
-    dpy = GDK_DISPLAY ();
-
-    /* NULL window -> events for all windows go to our function */
-    gdk_window_add_filter (NULL, event_handler_gdk, NULL);
-
-    /* Load our own gtkrc if it exists.  */
-    {
-      struct gcpro gcpro1, gcpro2;
-      char *file = "~/.emacs.d/gtkrc";
-      Lisp_Object s, abs_file;
-
-      GCPRO2 (s, abs_file);
-      s = make_string (file, strlen (file));
-      abs_file = Fexpand_file_name(s, Qnil);
-
-      if (! NILP (abs_file) && !NILP (Ffile_readable_p (abs_file)))
-        gtk_rc_parse (SDATA (abs_file));
-
-      UNGCPRO;
-    }
-
-    XSetErrorHandler (x_error_handler);
-    XSetIOErrorHandler (x_io_error_quitter);
+        XSetLocaleModifiers ("");
+#endif
+
+        gtk_init (&argc, &argv2);
+
+        /* gtk_init does set_locale.  We must fix locale after calling it.  */
+        fixup_locale ();
+        xg_initialize ();
+
+        dpy = GDK_DISPLAY ();
+
+        /* NULL window -> events for all windows go to our function */
+        gdk_window_add_filter (NULL, event_handler_gdk, NULL);
+
+        /* Load our own gtkrc if it exists.  */
+        {
+          struct gcpro gcpro1, gcpro2;
+          char *file = "~/.emacs.d/gtkrc";
+          Lisp_Object s, abs_file;
+
+          GCPRO2 (s, abs_file);
+          s = make_string (file, strlen (file));
+          abs_file = Fexpand_file_name (s, Qnil);
+
+          if (! NILP (abs_file) && !NILP (Ffile_readable_p (abs_file)))
+            gtk_rc_parse (SDATA (abs_file));
+
+          UNGCPRO;
+        }
+
+        XSetErrorHandler (x_error_handler);
+        XSetIOErrorHandler (x_io_error_quitter);
+      }
   }
 #else /* not USE_GTK */
 #ifdef USE_X_TOOLKIT
@@ -10385,6 +10414,11 @@
   x_find_modifier_meanings (dpyinfo);
 
   /* Get the scroll bar cursor.  */
+#ifdef USE_GTK
+  /* We must create a GTK cursor, it is required for GTK widgets.  */
+  dpyinfo->xg_cursor = xg_create_default_cursor (dpyinfo->display);
+#endif /* USE_GTK */
+
   dpyinfo->vertical_scroll_bar_cursor
     = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);