summaryrefslogtreecommitdiff
path: root/src/xterm.c
diff options
context:
space:
mode:
authorJan Djärv <jan.h.d@swipnet.se>2003-11-16 16:05:24 +0000
committerJan Djärv <jan.h.d@swipnet.se>2003-11-16 16:05:24 +0000
commit810f2256ba03de93679ae73c02512f0da0fd1c7b (patch)
tree7d140900a63b082cbfb00d296c3b5eb30e398080 /src/xterm.c
parent0bdd0f79978c5f7e6a94cde0e5fc94040de3ca66 (diff)
downloademacs-810f2256ba03de93679ae73c02512f0da0fd1c7b.tar.gz
Implement multiple display handling for GTK.
Diffstat (limited to 'src/xterm.c')
-rw-r--r--src/xterm.c212
1 files changed, 123 insertions, 89 deletions
diff --git a/src/xterm.c b/src/xterm.c
index 85beb00eb52..a5f6c959cec 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -357,7 +357,7 @@ static void x_flush P_ ((struct frame *f));
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 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
/* 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 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
/* 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 @@ x_window_to_scroll_bar (window_id)
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 @@ x_filter_event (dpyinfo, event)
#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 @@ event_handler_gdk (gxev, ev, data)
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 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
/* 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 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
/* 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 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
{
#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 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
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 @@ x_dispatch_event (event, display)
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 @@ XTread_socket (sd, bufp, numchars, expected)
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 @@ XTread_socket (sd, bufp, numchars, expected)
if (finish == X_EVENT_GOTO_OUT)
goto out;
}
-#endif /* USE_GTK */
+#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 @@ x_bitmap_icon (f, file)
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 @@ x_bitmap_icon (f, file)
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 @@ x_connection_closed (dpy, error_message)
}
#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 @@ x_term_init (display_name, xrm_option, resource_name)
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;
+ 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
+ {
+ for (argc = 0; argc < NUM_ARGV; ++argc)
+ argv[argc] = 0;
- argc = 0;
- argv[argc++] = initial_argv[0];
+ argc = 0;
+ argv[argc++] = initial_argv[0];
- if (! NILP (display_name))
- {
- argv[argc++] = "--display";
- argv[argc++] = SDATA (display_name);
- }
+ if (! NILP (display_name))
+ {
+ argv[argc++] = "--display";
+ argv[argc++] = SDATA (display_name);
+ }
- argv[argc++] = "--name";
- argv[argc++] = resource_name;
+ argv[argc++] = "--name";
+ argv[argc++] = resource_name;
#ifdef HAVE_X11R5
- XSetLocaleModifiers ("");
+ XSetLocaleModifiers ("");
#endif
- gtk_init (&argc, &argv2);
+ gtk_init (&argc, &argv2);
- /* gtk_init does set_locale. We must fix locale after calling it. */
- fixup_locale ();
- xg_initialize ();
+ /* gtk_init does set_locale. We must fix locale after calling it. */
+ fixup_locale ();
+ xg_initialize ();
- dpy = GDK_DISPLAY ();
+ dpy = GDK_DISPLAY ();
- /* NULL window -> events for all windows go to our function */
- gdk_window_add_filter (NULL, event_handler_gdk, NULL);
+ /* 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;
+ /* 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);
+ 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));
+ if (! NILP (abs_file) && !NILP (Ffile_readable_p (abs_file)))
+ gtk_rc_parse (SDATA (abs_file));
- UNGCPRO;
- }
+ UNGCPRO;
+ }
- XSetErrorHandler (x_error_handler);
- XSetIOErrorHandler (x_io_error_quitter);
+ XSetErrorHandler (x_error_handler);
+ XSetIOErrorHandler (x_io_error_quitter);
+ }
}
#else /* not USE_GTK */
#ifdef USE_X_TOOLKIT
@@ -10385,6 +10414,11 @@ x_term_init (display_name, xrm_option, resource_name)
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);