From: Jan Djärv Date: Sun, 16 Nov 2003 16:05:24 +0000 (+0000) Subject: Implement multiple display handling for GTK. X-Git-Tag: ttn-vms-21-2-B4~8357 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=810f2256ba03de93679ae73c02512f0da0fd1c7b;p=emacs.git Implement multiple display handling for GTK. --- diff --git a/src/ChangeLog b/src/ChangeLog index 41aa2cd35fa..23ccec9571f 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,55 @@ +2003-11-16 Jan Dj,Ad(Brv + + * xfns.c (x_window_to_frame, x_any_window_to_frame) + (x_non_menubar_window_to_frame, x_menubar_window_to_frame) + (x_top_window_to_frame): Add Display* argument to xg_win_to_widget. + (x_create_bitmap_mask, xg_set_icon, create_frame_xic) + (xic_set_statusarea, x_window, gif_load): Formatting adjustments. + + * xterm.h (struct x_display_info): New field xg_cursor for GTK. + + * xterm.c: Add Display * to x_window_to_scroll_bar declaration. + (XTmouse_position, handle_one_xevent): Pass Display* to + x_window_to_scroll_bar. + (x_window_to_scroll_bar): Take a Display* argument. + Check that display for frame is equal to Display* argument. + (event_handler_gdk): current_dpyinfo removed. Get dpyinfo from + x_display_info_for_display instead. Use Display in xev instead + of GDK_DISPLAY. + (x_dispatch_event): Call x_display_info_for_display. + (XTread_socket): Move GTK part out of loop. current_dpyinfo removed. + (x_connection_closed): Call xg_display_close for GTK. + (x_term_init): Call xg_display_open for additional displays. + Initiate dpyinfo->xg_cursor with call to xg_create_default_cursor + for GTK. + + * xmenu.c (single_menu_item, mouse_position_for_popup) + (x_activate_menubar): Formatting adjustments. + + * xdisp.c (update_tool_bar, redisplay_tool_bar): Formatting + adjustments. + + * gtkutil.c (xg_get_gdk_display, xg_set_screen, xg_display_open) + (xg_display_close, xg_create_default_cursor) + (xg_get_gdk_pixmap_and_mask): New functions for multiple display + handling. + (xg_left_ptr_cursor): Removed. + (xg_set_cursor): cursor changed to GdkCursor*. Do not create + cursor here. + (xg_win_to_widget): Take Display* argument, call + gdk_xid_table_lookup_for_display. + (xg_create_frame_widgets, xg_get_file_name, create_menus) + (xg_create_widget, xg_modify_menubar_widgets): Call xg_set_screen. + (xg_create_widget, xg_create_scroll_bar): Use xg_cursor + in FRAME_X_DISPLAY_INFO. + (xg_get_scroll_id_for_window): Take Display* argument. + (update_frame_tool_bar): Call xg_get_gdk_pixmap_and_mask. + (xg_initialize): xg_left_ptr_cursor removed. + + * gtkutil.h: xg_get_scroll_id_for_window, xg_win_to_widget takes + Display* argument also. Declare xg_display_open, + xg_display_close, xg_create_default_cursor. + 2003-11-14 Jan Dj,Ad(Brv * xterm.c (x_detect_focus_change): Do not change focus frame for diff --git a/src/gtkutil.c b/src/gtkutil.c index b37e69481b8..4fc3351ab7e 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -36,9 +36,128 @@ Boston, MA 02111-1307, USA. */ #include "coding.h" #include + #define FRAME_TOTAL_PIXEL_HEIGHT(f) \ (FRAME_PIXEL_HEIGHT (f) + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f)) + +/*********************************************************************** + Display handling functions + ***********************************************************************/ + +#ifdef HAVE_GTK_MULTIDISPLAY + +/* Return the GdkDisplay that corresponds to the X display DPY. */ +static GdkDisplay * +xg_get_gdk_display (dpy) + Display *dpy; +{ + return gdk_x11_lookup_xdisplay (dpy); +} + +/* When the GTK widget W is to be created on a display for F that + is not the default display, set the display for W. + W can be a GtkMenu or a GtkWindow widget. */ +static void +xg_set_screen (w, f) + GtkWidget *w; + FRAME_PTR f; +{ + if (FRAME_X_DISPLAY (f) != GDK_DISPLAY ()) + { + GdkDisplay *gdpy = gdk_x11_lookup_xdisplay (FRAME_X_DISPLAY (f)); + GdkScreen *gscreen = gdk_display_get_default_screen (gdpy); + + if (GTK_IS_MENU (w)) + gtk_menu_set_screen (GTK_MENU (w), gscreen); + else + gtk_window_set_screen (GTK_WINDOW (w), gscreen); + } +} + + +#else /* not HAVE_GTK_MULTIDISPLAY */ + +/* Make some defines so we can use the GTK 2.2 functions when + compiling with GTK 2.0. */ +#define xg_set_screen(w, f) +#define gdk_xid_table_lookup_for_display(dpy, w) gdk_xid_table_lookup (w) +#define gdk_pixmap_foreign_new_for_display(dpy, p) gdk_pixmap_foreign_new (p) +#define gdk_cursor_new_for_display(dpy, c) gdk_cursor_new (c) +#define gdk_x11_lookup_xdisplay(dpy) 0 +#define GdkDisplay void + +#endif /* not HAVE_GTK_MULTIDISPLAY */ + +/* Open a display named by DISPLAY_NAME. The display is returned in *DPY. + *DPY is set to NULL if the display can't be opened. + + Returns non-zero if display could be opened, zero if display could not + be opened, and less than zero if the GTK version doesn't support + multipe displays. */ +int +xg_display_open (display_name, dpy) + char *display_name; + Display **dpy; +{ +#ifdef HAVE_GTK_MULTIDISPLAY + GdkDisplay *gdpy; + + gdpy = gdk_display_open (display_name); + *dpy = gdpy ? GDK_DISPLAY_XDISPLAY (gdpy) : NULL; + + return gdpy != NULL; + +#else /* not HAVE_GTK_MULTIDISPLAY */ + + return -1; +#endif /* not HAVE_GTK_MULTIDISPLAY */ +} + + +void +xg_display_close (Display *dpy) +{ +#ifdef HAVE_GTK_MULTIDISPLAY + GdkDisplay *gdpy = gdk_x11_lookup_xdisplay (dpy); + + /* GTK 2.2 has a bug that makes gdk_display_close crash (bug + http://bugzilla.gnome.org/show_bug.cgi?id=85715). This way + we can continue running, but there will be memory leaks. */ + +#if GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION < 4 + + /* If this is the default display, we must change it before calling + dispose, otherwise it will crash. */ + if (gdk_display_get_default () == gdpy) + { + struct x_display_info *dpyinfo; + Display *new_dpy = 0; + GdkDisplay *gdpy_new; + + /* Find another display. */ + for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next) + if (dpyinfo->display != dpy) + { + new_dpy = dpyinfo->display; + break; + } + + if (! new_dpy) return; /* Emacs will exit anyway. */ + + gdpy_new = gdk_x11_lookup_xdisplay (new_dpy); + gdk_display_manager_set_default_display (gdk_display_manager_get (), + gdpy_new); + } + + g_object_run_dispose (G_OBJECT (gdpy)); + +#else + /* I hope this will be fixed in GTK 2.4. It is what bug 85715 says. */ + gdk_display_close (gdpy); +#endif +#endif /* HAVE_GTK_MULTIDISPLAY */ +} /*********************************************************************** @@ -48,10 +167,6 @@ Boston, MA 02111-1307, USA. */ NULL if no timer is started. */ static struct atimer *xg_timer; -/* The cursor used for scroll bars and popup menus. - We only have one cursor for all scroll bars and all popup menus. */ -static GdkCursor *xg_left_ptr_cursor; - /* The next two variables and functions are taken from lwlib. */ static widget_value *widget_value_free_list; @@ -103,24 +218,48 @@ free_widget_value (wv) } } -/* Set *CURSOR on W and all widgets W contain. We must do like this - for scroll bars and menu because they create widgets internally, - and it is those widgets that are visible. - If *CURSOR is NULL, create a GDK_LEFT_PTR cursor and set *CURSOR to - the created cursor. */ -void +/* Create and return the cursor to be used for popup menus and + scroll bars on display DPY. */ +GdkCursor * +xg_create_default_cursor (dpy) + Display *dpy; +{ + GdkDisplay *gdpy = gdk_x11_lookup_xdisplay (dpy); + return gdk_cursor_new_for_display (gdpy, GDK_LEFT_PTR); +} + +/* For the image defined in IMG, make and return a GdkPixmap for + the pixmap in *GPIX, and a GdkBitmap for the mask in *GMASK. + If IMG has no mask, *GMASK is set to NULL. + The image is defined on the display where frame F is. */ +static void +xg_get_gdk_pixmap_and_mask (f, img, gpix, gmask) + FRAME_PTR f; + struct image *img; + GdkPixmap **gpix; + GdkBitmap **gmask; +{ + GdkDisplay *gdpy = gdk_x11_lookup_xdisplay (FRAME_X_DISPLAY (f)); + + *gpix = gdk_pixmap_foreign_new_for_display (gdpy, img->pixmap); + *gmask = img->mask ? + (GdkBitmap*) gdk_pixmap_foreign_new_for_display (gdpy, img->mask) + : 0; +} + + +/* Set CURSOR on W and all widgets W contain. We must do like this + for scroll bars and menu because they create widgets internally, + and it is those widgets that are visible. */ +static void xg_set_cursor (w, cursor) GtkWidget *w; - GdkCursor **cursor; + GdkCursor *cursor; { GList *children = gdk_window_peek_children (w->window); - /* Create the cursor unless already created. */ - if (! *cursor) - *cursor = gdk_cursor_new (GDK_LEFT_PTR); - - gdk_window_set_cursor (w->window, *cursor); + gdk_window_set_cursor (w->window, cursor); /* The scroll bar widget has more than one GDK window (had to look at the source to figure this out), and there is no way to set cursor @@ -128,7 +267,7 @@ xg_set_cursor (w, cursor) Ditto for menus. */ for ( ; children; children = g_list_next (children)) - gdk_window_set_cursor (GDK_WINDOW (children->data), *cursor); + gdk_window_set_cursor (GDK_WINDOW (children->data), cursor); } /* Timer function called when a timeout occurs for xg_timer. @@ -381,20 +520,23 @@ xg_frame_set_char_size (f, cols, rows) cancel_mouse_face (f); } -/* Convert an X Window WSESC to its corresponding GtkWidget. +/* Convert an X Window WSESC on display DPY to its corresponding GtkWidget. Must be done like this, because GtkWidget:s can have "hidden" X Window that aren't accessible. Return 0 if no widget match WDESC. */ GtkWidget * -xg_win_to_widget (wdesc) +xg_win_to_widget (dpy, wdesc) + Display *dpy; Window wdesc; { gpointer gdkwin; GtkWidget *gwdesc = 0; BLOCK_INPUT; - gdkwin = gdk_xid_table_lookup (wdesc); + + gdkwin = gdk_xid_table_lookup_for_display (gdk_x11_lookup_xdisplay (dpy), + wdesc); if (gdkwin) { GdkEvent event; @@ -429,9 +571,9 @@ xg_pix_to_gcolor (w, pixel, c) Return TRUE to tell GTK that this expose event has been fully handeled and that GTK shall do nothing more with it. */ static gboolean -xg_fixed_handle_expose(GtkWidget *widget, - GdkEventExpose *event, - gpointer user_data) +xg_fixed_handle_expose (GtkWidget *widget, + GdkEventExpose *event, + gpointer user_data) { GList *iter; @@ -483,6 +625,8 @@ xg_create_frame_widgets (f) BLOCK_INPUT; wtop = gtk_window_new (GTK_WINDOW_TOPLEVEL); + xg_set_screen (wtop, f); + wvbox = gtk_vbox_new (FALSE, 0); wfixed = gtk_fixed_new (); /* Must have this to place scroll bars */ @@ -512,7 +656,8 @@ xg_create_frame_widgets (f) gtk_fixed_set_has_window (GTK_FIXED (wfixed), TRUE); - gtk_widget_set_size_request (wfixed, FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f)); + gtk_widget_set_size_request (wfixed, FRAME_PIXEL_WIDTH (f), + FRAME_PIXEL_HEIGHT (f)); gtk_container_add (GTK_CONTAINER (wtop), wvbox); gtk_box_pack_end (GTK_BOX (wvbox), wfixed, TRUE, TRUE, 0); @@ -963,6 +1108,8 @@ xg_get_file_name (f, prompt, default_filename, mustmatch_p) filewin = gtk_file_selection_new (prompt); filesel = GTK_FILE_SELECTION (filewin); + xg_set_screen (filewin, f); + gtk_widget_set_name (filewin, "emacs-filedialog"); gtk_window_set_transient_for (GTK_WINDOW (filewin), @@ -1500,7 +1647,11 @@ create_menus (data, f, select_cb, deactivate_cb, highlight_cb, if (! topmenu) { - if (! menu_bar_p) wmenu = gtk_menu_new (); + if (! menu_bar_p) + { + wmenu = gtk_menu_new (); + xg_set_screen (wmenu, f); + } else wmenu = gtk_menu_bar_new (); /* Put cl_data on the top menu for easier access. */ @@ -1618,12 +1769,11 @@ xg_create_widget (type, name, f, val, if (strcmp (type, "dialog") == 0) { w = create_dialog (val, select_cb, deactivate_cb); + xg_set_screen (w, f); gtk_window_set_transient_for (GTK_WINDOW (w), GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f))); gtk_window_set_destroy_with_parent (GTK_WINDOW (w), TRUE); - - if (w) - gtk_widget_set_name (w, "emacs-dialog"); + gtk_widget_set_name (w, "emacs-dialog"); } else if (menu_bar_p || pop_up_p) { @@ -1645,7 +1795,7 @@ xg_create_widget (type, name, f, val, { /* Must realize so the GdkWindow inside the widget is created. */ gtk_widget_realize (w); - xg_set_cursor (w, &xg_left_ptr_cursor); + xg_set_cursor (w, FRAME_X_DISPLAY_INFO (f)->xg_cursor); } } else @@ -2261,7 +2411,10 @@ xg_modify_menubar_widgets (menubar, f, val, deep_p, a new menu bar item, it has no sub menu yet. So we set the newly created sub menu under witem. */ if (newsub != sub) - gtk_menu_item_set_submenu (witem, newsub); + { + xg_set_screen (newsub, f); + gtk_menu_item_set_submenu (witem, newsub); + } } } @@ -2417,16 +2570,17 @@ xg_get_widget_from_map (idx) return 0; } -/* Return the scrollbar id for X Window WID. +/* Return the scrollbar id for X Window WID on display DPY. Return -1 if WID not in id_to_widget. */ int -xg_get_scroll_id_for_window (wid) +xg_get_scroll_id_for_window (dpy, wid) + Display *dpy; Window wid; { int idx; GtkWidget *w; - w = xg_win_to_widget (wid); + w = xg_win_to_widget (dpy, wid); if (w) { @@ -2533,7 +2687,7 @@ xg_create_scroll_bar (f, bar, scroll_callback, scroll_bar_name) wscroll, -1, -1); /* Set the cursor to an arrow. */ - xg_set_cursor (wscroll, &xg_left_ptr_cursor); + xg_set_cursor (wscroll, FRAME_X_DISPLAY_INFO (f)->xg_cursor); SET_SCROLL_BAR_X_WINDOW (bar, scroll_id); } @@ -2952,8 +3106,8 @@ xg_tool_bar_item_expose_callback (w, event, client_data) event->area.x -= width > event->area.width ? width-event->area.width : 0; event->area.y -= height > event->area.height ? height-event->area.height : 0; - event->area.x = max(0, event->area.x); - event->area.y = max(0, event->area.y); + event->area.x = max (0, event->area.x); + event->area.y = max (0, event->area.y); event->area.width = max (width, event->area.width); event->area.height = max (height, event->area.height); @@ -2975,7 +3129,7 @@ xg_tool_bar_expose_callback (w, event, client_data) GdkEventExpose *event; gpointer client_data; { - update_frame_tool_bar((FRAME_PTR)client_data); + update_frame_tool_bar ((FRAME_PTR) client_data); return FALSE; } @@ -3108,11 +3262,12 @@ update_frame_tool_bar (f) if (! wicon) { - GdkPixmap *gpix = gdk_pixmap_foreign_new (img->pixmap); - GdkBitmap *gmask = img->mask ? - (GdkBitmap*) gdk_pixmap_foreign_new (img->mask) : 0; + GdkPixmap *gpix; + GdkBitmap *gmask; + GtkWidget *w; - GtkWidget *w = gtk_image_new_from_pixmap (gpix, gmask); + xg_get_gdk_pixmap_and_mask (f, img, &gpix, &gmask); + w = gtk_image_new_from_pixmap (gpix, gmask); gtk_toolbar_append_item (GTK_TOOLBAR (x->toolbar_widget), 0, 0, 0, w, @@ -3170,10 +3325,10 @@ update_frame_tool_bar (f) if (old_img != img->pixmap) { - GdkPixmap *gpix = gdk_pixmap_foreign_new (img->pixmap); - GdkBitmap *gmask = img->mask ? - (GdkBitmap*) gdk_pixmap_foreign_new (img->mask) : 0; + GdkPixmap *gpix; + GdkBitmap *gmask; + xg_get_gdk_pixmap_and_mask (f, img, &gpix, &gmask); gtk_image_set_from_pixmap (wimage, gpix, gmask); } @@ -3241,7 +3396,6 @@ void xg_initialize () { xg_ignore_gtk_scrollbar = 0; - xg_left_ptr_cursor = 0; xg_detached_menus = 0; xg_menu_cb_list.prev = xg_menu_cb_list.next = xg_menu_item_cb_list.prev = xg_menu_item_cb_list.next = 0; diff --git a/src/gtkutil.h b/src/gtkutil.h index 5864a334edc..b31ec8c2a1f 100644 --- a/src/gtkutil.h +++ b/src/gtkutil.h @@ -152,7 +152,7 @@ extern int xg_update_frame_menubar P_ ((FRAME_PTR f)); extern int xg_have_tear_offs P_ ((void)); -extern int xg_get_scroll_id_for_window P_ ((Window wid)); +extern int xg_get_scroll_id_for_window P_ ((Display *dpy, Window wid)); extern void xg_create_scroll_bar P_ ((FRAME_PTR f, struct scroll_bar *bar, @@ -184,7 +184,12 @@ extern void xg_resize_widgets P_ ((FRAME_PTR f, int pixelheight)); extern void xg_frame_cleared P_ ((FRAME_PTR f)); extern void xg_frame_set_char_size P_ ((FRAME_PTR f, int cols, int rows)); -extern GtkWidget * xg_win_to_widget P_ ((Window)); +extern GtkWidget * xg_win_to_widget P_ ((Display *dpy, Window wdesc)); + +extern int xg_display_open P_ ((char *display_name, Display **dpy)); +extern void xg_display_close P_ ((Display *dpy)); +extern GdkCursor * xg_create_default_cursor P_ ((Display *dpy)); + extern int xg_create_frame_widgets P_ ((FRAME_PTR f)); extern void x_wm_set_size_hint P_ ((FRAME_PTR f, long flags, diff --git a/src/xdisp.c b/src/xdisp.c index e1b13323255..8b026fefa9e 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -8142,7 +8142,7 @@ update_tool_bar (f, save_match_data) int save_match_data; { #ifdef USE_GTK - int do_update = FRAME_EXTERNAL_TOOL_BAR(f); + int do_update = FRAME_EXTERNAL_TOOL_BAR (f); #else int do_update = WINDOWP (f->tool_bar_window) && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0; @@ -8539,7 +8539,7 @@ redisplay_tool_bar (f) int change_height_p = 0; #ifdef USE_GTK - if (FRAME_EXTERNAL_TOOL_BAR(f)) + if (FRAME_EXTERNAL_TOOL_BAR (f)) update_frame_tool_bar (f); return 0; #endif diff --git a/src/xfns.c b/src/xfns.c index e4742b1d36d..cd50cbbc919 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -308,7 +308,7 @@ x_window_to_frame (dpyinfo, wdesc) #ifdef USE_GTK if (f->output_data.x->edit_widget) { - GtkWidget *gwdesc = xg_win_to_widget (wdesc); + GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc); struct x_output *x = f->output_data.x; if (gwdesc != 0 && gwdesc == x->edit_widget) return f; @@ -352,7 +352,7 @@ x_any_window_to_frame (dpyinfo, wdesc) else if (x->widget) { #ifdef USE_GTK - GtkWidget *gwdesc = xg_win_to_widget (wdesc); + GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc); if (gwdesc != 0 && (gwdesc == x->widget || gwdesc == x->edit_widget @@ -404,7 +404,7 @@ x_non_menubar_window_to_frame (dpyinfo, wdesc) else if (x->widget) { #ifdef USE_GTK - GtkWidget *gwdesc = xg_win_to_widget (wdesc); + GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc); if (gwdesc != 0 && (gwdesc == x->widget || gwdesc == x->edit_widget @@ -448,7 +448,7 @@ x_menubar_window_to_frame (dpyinfo, wdesc) #ifdef USE_GTK if (x->menubar_widget) { - GtkWidget *gwdesc = xg_win_to_widget (wdesc); + GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc); int found = 0; BLOCK_INPUT; @@ -494,7 +494,7 @@ x_top_window_to_frame (dpyinfo, wdesc) { /* This frame matches if the window is its topmost widget. */ #ifdef USE_GTK - GtkWidget *gwdesc = xg_win_to_widget (wdesc); + GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc); if (gwdesc == x->widget) return f; #else @@ -762,7 +762,7 @@ static void x_destroy_x_image P_ ((XImage *ximg)); It's nicer with some borders in this context */ int -x_create_bitmap_mask(f, id) +x_create_bitmap_mask (f, id) struct frame *f; int id; { @@ -780,9 +780,9 @@ x_create_bitmap_mask(f, id) if (!(id > 0)) return -1; - pixmap = x_bitmap_pixmap(f, id); - width = x_bitmap_width(f, id); - height = x_bitmap_height(f, id); + pixmap = x_bitmap_pixmap (f, id); + width = x_bitmap_width (f, id); + height = x_bitmap_height (f, id); BLOCK_INPUT; ximg = XGetImage (FRAME_X_DISPLAY (f), pixmap, 0, 0, width, height, @@ -799,7 +799,7 @@ x_create_bitmap_mask(f, id) UNBLOCK_INPUT; if (!result) { - XDestroyImage(ximg); + XDestroyImage (ximg); return -1; } @@ -838,7 +838,7 @@ x_create_bitmap_mask(f, id) dpyinfo->bitmaps[id - 1].mask = mask; XDestroyImage (ximg); - x_destroy_x_image(mask_img); + x_destroy_x_image (mask_img); return 0; } @@ -1106,7 +1106,7 @@ static Lisp_Object x_find_image_file P_ ((Lisp_Object file)); may be any format that GdkPixbuf knows about, i.e. not just bitmaps. */ int -xg_set_icon(f, file) +xg_set_icon (f, file) FRAME_PTR f; Lisp_Object file; { @@ -2458,8 +2458,8 @@ create_frame_xic (f) xic = XCreateIC (xim, XNInputStyle, xic_style, - XNClientWindow, FRAME_X_WINDOW(f), - XNFocusWindow, FRAME_X_WINDOW(f), + XNClientWindow, FRAME_X_WINDOW (f), + XNFocusWindow, FRAME_X_WINDOW (f), XNStatusAttributes, status_attr, XNPreeditAttributes, preedit_attr, NULL); @@ -2550,7 +2550,7 @@ xic_set_statusarea (f) XFree (needed); attr = XVaCreateNestedList (0, XNArea, &area, NULL); - XSetICValues(xic, XNStatusAttributes, attr, NULL); + XSetICValues (xic, XNStatusAttributes, attr, NULL); XFree (attr); } @@ -2793,7 +2793,7 @@ x_window (f, window_prompting, minibuffer_only) { /* XIM server might require some X events. */ unsigned long fevent = NoEventMask; - XGetICValues(FRAME_XIC (f), XNFilterEvents, &fevent, NULL); + XGetICValues (FRAME_XIC (f), XNFilterEvents, &fevent, NULL); attributes.event_mask |= fevent; } #endif /* HAVE_X_I18N */ @@ -2847,7 +2847,7 @@ if (use_xim) { /* XIM server might require some X events. */ unsigned long fevent = NoEventMask; - XGetICValues(FRAME_XIC (f), XNFilterEvents, &fevent, NULL); + XGetICValues (FRAME_XIC (f), XNFilterEvents, &fevent, NULL); if (fevent != NoEventMask) { @@ -2911,7 +2911,7 @@ x_window (f) { /* XIM server might require some X events. */ unsigned long fevent = NoEventMask; - XGetICValues(FRAME_XIC (f), XNFilterEvents, &fevent, NULL); + XGetICValues (FRAME_XIC (f), XNFilterEvents, &fevent, NULL); attributes.event_mask |= fevent; attribute_mask = CWEventMask; XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), @@ -9166,7 +9166,7 @@ gif_load (f, img) memsrc.len = SBYTES (specified_data); memsrc.index = 0; - gif = DGifOpen(&memsrc, gif_read_from_memory); + gif = DGifOpen (&memsrc, gif_read_from_memory); if (!gif) { image_error ("Cannot open memory source `%s'", img->spec, Qnil); diff --git a/src/xmenu.c b/src/xmenu.c index 14f7485759b..3e99a1c506d 100644 --- a/src/xmenu.c +++ b/src/xmenu.c @@ -610,7 +610,7 @@ single_menu_item (key, item, dummy, skp_v) #endif /* not HAVE_BOXES */ #if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK) - if (!NILP(map)) + if (!NILP (map)) /* Indicate visually that this is a submenu. */ item_string = concat2 (item_string, build_string (" >")); #endif @@ -696,7 +696,7 @@ list_of_items (pane) the scroll bar or the edit window. Fx_popup_menu needs to be sure it is the edit window. */ static void -mouse_position_for_popup(f, x, y) +mouse_position_for_popup (f, x, y) FRAME_PTR f; int *x; int *y; @@ -1217,7 +1217,8 @@ x_activate_menubar (f) return; #ifdef USE_GTK - if (! xg_win_to_widget (f->output_data.x->saved_menu_event->xany.window)) + if (! xg_win_to_widget (FRAME_X_DISPLAY (f), + f->output_data.x->saved_menu_event->xany.window)) return; #endif 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, - ¤t_finish); + + if (! dpyinfo) + current_finish = X_EVENT_NORMAL; + else + current_count += handle_one_xevent (dpyinfo, + xev, + current_bufp, + current_numcharsp, + ¤t_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); diff --git a/src/xterm.h b/src/xterm.h index fbd268abda2..104f5f8d76e 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -189,6 +189,11 @@ struct x_display_info /* The cursor to use for vertical scroll bars. */ Cursor vertical_scroll_bar_cursor; +#ifdef USE_GTK + /* The GDK cursor for scroll bars and popup menus. */ + GdkCursor *xg_cursor; +#endif + /* X Resource data base */ XrmDatabase xrdb;