diff options
Diffstat (limited to 'gdk/x11/gdkevents-x11.c')
-rw-r--r-- | gdk/x11/gdkevents-x11.c | 800 |
1 files changed, 509 insertions, 291 deletions
diff --git a/gdk/x11/gdkevents-x11.c b/gdk/x11/gdkevents-x11.c index 0197c62338..1d9e57f8a6 100644 --- a/gdk/x11/gdkevents-x11.c +++ b/gdk/x11/gdkevents-x11.c @@ -28,6 +28,8 @@ #include "gdkprivate-x11.h" #include "gdkinternals.h" #include "gdkx.h" +#include "gdkscreen-x11.h" +#include "gdkdisplay-x11.h" #include "gdkkeysyms.h" @@ -50,6 +52,7 @@ typedef struct _GdkIOClosure GdkIOClosure; typedef struct _GdkEventPrivate GdkEventPrivate; +typedef struct _GdkDisplaySource GdkDisplaySource; #define DOUBLE_CLICK_TIME 250 #define TRIPLE_CLICK_TIME 500 @@ -78,6 +81,14 @@ struct _GdkEventPrivate guint flags; }; +struct _GdkDisplaySource +{ + GSource source; + + GdkDisplay *display; + GPollFD event_poll_fd; +}; + /* * Private function declarations */ @@ -85,14 +96,10 @@ struct _GdkEventPrivate static gint gdk_event_apply_filters (XEvent *xevent, GdkEvent *event, GList *filters); -static gint gdk_event_translate (GdkEvent *event, - XEvent *xevent, - gboolean return_exposes); -#if 0 -static Bool gdk_event_get_type (Display *display, - XEvent *xevent, - XPointer arg); -#endif +static gboolean gdk_event_translate (GdkDisplay *display, + GdkEvent *event, + XEvent *xevent, + gboolean return_exposes); static gboolean gdk_event_prepare (GSource *source, gint *timeout); @@ -105,6 +112,9 @@ static GdkFilterReturn gdk_wm_protocols_filter (GdkXEvent *xev, GdkEvent *event, gpointer data); +static GSource *gdk_display_source_new (GdkDisplay *display); +static gboolean gdk_check_xpending (GdkDisplay *display); + static void gdk_xsettings_watch_cb (Window window, Bool is_start, long mask, @@ -117,13 +127,7 @@ static void gdk_xsettings_notify_cb (const char *name, /* Private variable declarations */ -static int connection_number = 0; /* The file descriptor number of our - * connection to the X server. This - * is used so that we may determine - * when events are pending by using - * the "select" system call. - */ -static GList *client_filters; /* Filters for client messages */ +static GList *display_sources; static GSourceFuncs event_funcs = { gdk_event_prepare, @@ -132,86 +136,105 @@ static GSourceFuncs event_funcs = { NULL }; -static GPollFD event_poll_fd; - -static Window wmspec_check_window = None; +static GSource * +gdk_display_source_new (GdkDisplay *display) +{ + GSource *source = g_source_new (&event_funcs, sizeof (GdkDisplaySource)); + GdkDisplaySource *display_source = (GdkDisplaySource *)source; + + display_source->display = display; + + return source; +} -static XSettingsClient *xsettings_client; +static gboolean +gdk_check_xpending (GdkDisplay *display) +{ + return XPending (GDK_DISPLAY_XDISPLAY (display)); +} /********************************************* * Functions for maintaining the event queue * *********************************************/ +void +_gdk_x11_events_init_screen (GdkScreen *screen) +{ + GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen); + + screen_x11->xsettings_client = xsettings_client_new (screen_x11->xdisplay, + screen_x11->screen_num, + gdk_xsettings_notify_cb, + gdk_xsettings_watch_cb, + screen); +} + void -_gdk_events_init (void) +_gdk_events_init (GdkDisplay *display) { GSource *source; + GdkDisplaySource *display_source; + GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display); - connection_number = ConnectionNumber (gdk_display); - GDK_NOTE (MISC, - g_message ("connection number: %d", connection_number)); + int connection_number = ConnectionNumber (display_x11->xdisplay); + GDK_NOTE (MISC, g_message ("connection number: %d", connection_number)); - source = g_source_new (&event_funcs, sizeof (GSource)); + source = gdk_display_source_new (display); + display_source = (GdkDisplaySource*) source; g_source_set_priority (source, GDK_PRIORITY_EVENTS); - event_poll_fd.fd = connection_number; - event_poll_fd.events = G_IO_IN; + display_source->event_poll_fd.fd = connection_number; + display_source->event_poll_fd.events = G_IO_IN; - g_source_add_poll (source, &event_poll_fd); + g_source_add_poll (source, &display_source->event_poll_fd); g_source_set_can_recurse (source, TRUE); g_source_attach (source, NULL); - _gdk_wm_window_protocols[0] = gdk_x11_get_xatom_by_name ("WM_DELETE_WINDOW"); - _gdk_wm_window_protocols[1] = gdk_x11_get_xatom_by_name ("WM_TAKE_FOCUS"); - _gdk_wm_window_protocols[2] = gdk_x11_get_xatom_by_name ("_NET_WM_PING"); - - gdk_add_client_message_filter (gdk_atom_intern ("WM_PROTOCOLS", FALSE), - gdk_wm_protocols_filter, NULL); + display_sources = g_list_prepend (display_sources,display_source); + + gdk_display_add_client_message_filter ( + display, + gdk_atom_intern ("WM_PROTOCOLS", FALSE), + gdk_wm_protocols_filter, + NULL); - xsettings_client = xsettings_client_new (gdk_display, DefaultScreen (gdk_display), - gdk_xsettings_notify_cb, - gdk_xsettings_watch_cb, - NULL); + _gdk_x11_events_init_screen (display_x11->default_screen); } -/* - *-------------------------------------------------------------- - * gdk_events_pending - * - * Returns if events are pending on the queue. - * - * Arguments: - * - * Results: - * Returns TRUE if events are pending - * - * Side effects: - * - *-------------------------------------------------------------- - */ +/** + * gdk_events_pending: + * + * Checks if any events are ready to be processed for any display. + * + * Return value: %TRUE if any events are pending. + **/ gboolean gdk_events_pending (void) { - return (_gdk_event_queue_find_first() || XPending (gdk_display)); -} + GList *tmp_list; -/* - *-------------------------------------------------------------- - * gdk_event_get_graphics_expose - * - * Waits for a GraphicsExpose or NoExpose event - * - * Arguments: - * - * Results: - * For GraphicsExpose events, returns a pointer to the event - * converted into a GdkEvent Otherwise, returns NULL. - * - * Side effects: - * - *-------------------------------------------------------------- */ + for (tmp_list = display_sources; tmp_list; tmp_list = tmp_list->next) + { + GdkDisplaySource *tmp_source = tmp_list->data; + GdkDisplay *display = tmp_source->display; + + if (_gdk_event_queue_find_first (display)) + return TRUE; + } + + for (tmp_list = display_sources; tmp_list; tmp_list = tmp_list->next) + { + GdkDisplaySource *tmp_source = tmp_list->data; + GdkDisplay *display = tmp_source->display; + + if (gdk_check_xpending (display)) + return TRUE; + } + + return FALSE; +} static Bool graphics_expose_predicate (Display *display, @@ -226,6 +249,17 @@ graphics_expose_predicate (Display *display, return False; } +/** + * gdk_event_get_graphics_expose: + * @window: the #GdkWindow to wait for the events for. + * + * Waits for a GraphicsExpose or NoExpose event from the X server. + * This is used in the #GtkText and #GtkCList widgets in GTK+ to make sure any + * GraphicsExpose events are handled before the widget is scrolled. + * + * Return value: a #GdkEventExpose if a GraphicsExpose was received, or %NULL if a + * NoExpose event was received. + **/ GdkEvent* gdk_event_get_graphics_expose (GdkWindow *window) { @@ -234,13 +268,15 @@ gdk_event_get_graphics_expose (GdkWindow *window) g_return_val_if_fail (window != NULL, NULL); - XIfEvent (gdk_display, &xevent, graphics_expose_predicate, (XPointer) window); + XIfEvent (GDK_WINDOW_XDISPLAY (window), &xevent, + graphics_expose_predicate, (XPointer) window); if (xevent.xany.type == GraphicsExpose) { event = _gdk_event_new (); - if (gdk_event_translate (event, &xevent, TRUE)) + if (gdk_event_translate (GDK_WINDOW_DISPLAY (window), event, + &xevent, TRUE)) return event; else gdk_event_free (event); @@ -272,22 +308,56 @@ gdk_event_apply_filters (XEvent *xevent, return GDK_FILTER_CONTINUE; } +/** + * gdk_display_add_client_message_filter: + * @display: a #GdkDisplay for which this message filter applies + * @message_type: the type of ClientMessage events to receive. + * This will be checked against the @message_type field + * of the XClientMessage event struct. + * @func: the function to call to process the event. + * @data: user data to pass to @func. + * + * Adds a filter to be called when X ClientMessage events are received. + * + **/ void -gdk_add_client_message_filter (GdkAtom message_type, - GdkFilterFunc func, - gpointer data) +gdk_display_add_client_message_filter (GdkDisplay *display, + GdkAtom message_type, + GdkFilterFunc func, + gpointer data) { - GdkClientFilter *filter = g_new (GdkClientFilter, 1); + GdkClientFilter *filter; + g_return_if_fail (GDK_IS_DISPLAY (display)); + filter = g_new (GdkClientFilter, 1); filter->type = message_type; filter->function = func; filter->data = data; - client_filters = g_list_prepend (client_filters, filter); + GDK_DISPLAY_X11(display)->client_filters = + g_list_prepend (GDK_DISPLAY_X11 (display)->client_filters, + filter); } -static Atom wm_state_atom = 0; -static Atom wm_desktop_atom = 0; +/** + * gdk_add_client_message_filter: + * @message_type: the type of ClientMessage events to receive. This will be + * checked against the <structfield>message_type</structfield> field of the + * XClientMessage event struct. + * @func: the function to call to process the event. + * @data: user data to pass to @func. + * + * Adds a filter to the default display to be called when X ClientMessage events + * are received. See gdk_display_add_client_message_filter(). + **/ +void +gdk_add_client_message_filter (GdkAtom message_type, + GdkFilterFunc func, + gpointer data) +{ + gdk_display_add_client_message_filter (gdk_get_default_display (), + message_type, func, data); +} static void gdk_check_wm_state_changed (GdkWindow *window) @@ -298,37 +368,28 @@ gdk_check_wm_state_changed (GdkWindow *window) gulong bytes_after; Atom *atoms = NULL; gulong i; - Atom sticky_atom; - Atom maxvert_atom; - Atom maxhorz_atom; gboolean found_sticky, found_maxvert, found_maxhorz; GdkWindowState old_state; + GdkDisplay *display = GDK_WINDOW_DISPLAY (window); if (GDK_WINDOW_DESTROYED (window)) return; - if (wm_state_atom == 0) - wm_state_atom = gdk_x11_get_xatom_by_name ("_NET_WM_STATE"); - - if (wm_desktop_atom == 0) - wm_desktop_atom = gdk_x11_get_xatom_by_name ("_NET_WM_DESKTOP"); + found_sticky = FALSE; + found_maxvert = FALSE; + found_maxhorz = FALSE; XGetWindowProperty (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window), - wm_state_atom, 0, G_MAXLONG, - False, XA_ATOM, &type, &format, &nitems, + gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"), + 0, G_MAXLONG, False, XA_ATOM, &type, &format, &nitems, &bytes_after, (guchar **)&atoms); if (type != None) { + Atom sticky_atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_STICKY"); + Atom maxvert_atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_MAXIMIZED_VERT"); + Atom maxhorz_atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_MAXIMIZED_HORZ"); - sticky_atom = gdk_x11_get_xatom_by_name ("_NET_WM_STATE_STICKY"); - maxvert_atom = gdk_x11_get_xatom_by_name ("_NET_WM_STATE_MAXIMIZED_VERT"); - maxhorz_atom = gdk_x11_get_xatom_by_name ("_NET_WM_STATE_MAXIMIZED_HORZ"); - - found_sticky = FALSE; - found_maxvert = FALSE; - found_maxhorz = FALSE; - i = 0; while (i < nitems) { @@ -344,12 +405,6 @@ gdk_check_wm_state_changed (GdkWindow *window) XFree (atoms); } - else - { - found_sticky = FALSE; - found_maxvert = FALSE; - found_maxhorz = FALSE; - } /* For found_sticky to remain TRUE, we have to also be on desktop * 0xFFFFFFFF @@ -359,9 +414,12 @@ gdk_check_wm_state_changed (GdkWindow *window) { gulong *desktop; - XGetWindowProperty (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window), - wm_desktop_atom, 0, G_MAXLONG, - False, XA_CARDINAL, &type, &format, &nitems, + XGetWindowProperty (GDK_WINDOW_XDISPLAY (window), + GDK_WINDOW_XID (window), + gdk_x11_get_xatom_by_name_for_display + (display, "_NET_WM_DESKTOP"), + 0, G_MAXLONG, False, XA_CARDINAL, &type, + &format, &nitems, &bytes_after, (guchar **)&desktop); if (type != None) @@ -425,10 +483,11 @@ generate_focus_event (GdkWindow *window, gdk_event_put (&event); } -static gint -gdk_event_translate (GdkEvent *event, - XEvent *xevent, - gboolean return_exposes) +static gboolean +gdk_event_translate (GdkDisplay *display, + GdkEvent *event, + XEvent *xevent, + gboolean return_exposes) { GdkWindow *window; @@ -440,6 +499,9 @@ gdk_event_translate (GdkEvent *event, char buf[16]; gint return_val; gint xoffset, yoffset; + GdkScreen *screen = NULL; + GdkScreenX11 *screen_x11 = NULL; + GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display); return_val = FALSE; @@ -480,9 +542,15 @@ gdk_event_translate (GdkEvent *event, /* Find the GdkWindow that this event occurred in. */ - window = gdk_window_lookup (xevent->xany.window); + window = gdk_window_lookup_for_display (display, xevent->xany.window); window_private = (GdkWindowObject *) window; - + + if (window) + { + screen = GDK_WINDOW_SCREEN (window); + screen_x11 = GDK_SCREEN_X11 (screen); + } + if (window != NULL) { /* Window may be a pixmap, so check its type. @@ -505,7 +573,7 @@ gdk_event_translate (GdkEvent *event, xevent->xany.window = GDK_WINDOW_XID (window); break; default: - return False; + return FALSE; } } } @@ -538,11 +606,11 @@ gdk_event_translate (GdkEvent *event, } } - if (wmspec_check_window != None && - xevent->xany.window == wmspec_check_window) + if (screen_x11 && screen_x11->wmspec_check_window != None && + xevent->xany.window == screen_x11->wmspec_check_window) { if (xevent->type == DestroyNotify) - wmspec_check_window = None; + screen_x11->wmspec_check_window = None; /* Eat events on this window unless someone had wrapped * it as a foreign window @@ -555,14 +623,14 @@ gdk_event_translate (GdkEvent *event, } if (window && - _gdk_moveresize_window && (xevent->xany.type == MotionNotify || xevent->xany.type == ButtonRelease)) { - _gdk_moveresize_handle_event (xevent); - - return_val = FALSE; - goto done; + if (_gdk_moveresize_handle_event (xevent)) + { + return_val = FALSE; + goto done; + } } /* We do a "manual" conversion of the XEvent to a @@ -630,7 +698,7 @@ gdk_event_translate (GdkEvent *event, #define KEYBOARD_GROUP_SHIFT 13 #define KEYBOARD_GROUP_MASK ((1 << 13) | (1 << 14)) - event->key.group = _gdk_x11_get_group_for_state (xevent->xkey.state); + event->key.group = _gdk_x11_get_group_for_state (display, xevent->xkey.state); break; @@ -649,11 +717,11 @@ gdk_event_translate (GdkEvent *event, * keycode and timestamp, and if so, ignoring the event. */ - if (!_gdk_have_xkb_autorepeat && XPending (gdk_display)) + if (!display_x11->have_xkb_autorepeat && XPending (xevent->xkey.display)) { XEvent next_event; - XPeekEvent (gdk_display, &next_event); + XPeekEvent (xevent->xkey.display, &next_event); if (next_event.type == KeyPress && next_event.xkey.keycode == xevent->xkey.keycode && @@ -692,7 +760,7 @@ gdk_event_translate (GdkEvent *event, if (window_private == NULL || ((window_private->extension_events != 0) && - _gdk_input_ignore_core)) + display_x11->input_ignore_core)) { return_val = FALSE; break; @@ -740,7 +808,7 @@ gdk_event_translate (GdkEvent *event, event->button.button = xevent->xbutton.button; event->button.device = _gdk_core_pointer; - _gdk_event_button_generate (event); + _gdk_event_button_generate (display, event); break; } @@ -755,7 +823,7 @@ gdk_event_translate (GdkEvent *event, if (window_private == NULL || ((window_private->extension_events != 0) && - _gdk_input_ignore_core)) + display_x11->input_ignore_core)) { return_val = FALSE; break; @@ -792,7 +860,7 @@ gdk_event_translate (GdkEvent *event, if (window_private == NULL || ((window_private->extension_events != 0) && - _gdk_input_ignore_core)) + display_x11->input_ignore_core)) { return_val = FALSE; break; @@ -852,7 +920,7 @@ gdk_event_translate (GdkEvent *event, * lookup the corresponding GdkWindow. */ if (xevent->xcrossing.subwindow != None) - event->crossing.subwindow = gdk_window_lookup (xevent->xcrossing.subwindow); + event->crossing.subwindow = gdk_window_lookup_for_display (display, xevent->xcrossing.subwindow); else event->crossing.subwindow = NULL; @@ -939,7 +1007,7 @@ gdk_event_translate (GdkEvent *event, * lookup the corresponding GdkWindow. */ if (xevent->xcrossing.subwindow != None) - event->crossing.subwindow = gdk_window_lookup (xevent->xcrossing.subwindow); + event->crossing.subwindow = gdk_window_lookup_for_display (display, xevent->xcrossing.subwindow); else event->crossing.subwindow = NULL; @@ -1107,7 +1175,6 @@ gdk_event_translate (GdkEvent *event, else { _gdk_window_process_expose (window, xevent->xexpose.serial, &expose_rect); - return_val = FALSE; } @@ -1238,11 +1305,12 @@ gdk_event_translate (GdkEvent *event, return_val = window_private && !GDK_WINDOW_DESTROYED (window); - if (window && GDK_WINDOW_XID (window) != GDK_ROOT_WINDOW()) + if (window && GDK_WINDOW_XID (window) != screen_x11->xroot_window) gdk_window_destroy_notify (window); } else return_val = FALSE; + break; case UnmapNotify: @@ -1258,12 +1326,15 @@ gdk_event_translate (GdkEvent *event, * an unmap, it means we hid the window ourselves, so we * will have already flipped the iconified bit off. */ - if (window && GDK_WINDOW_IS_MAPPED (window)) - gdk_synthesize_window_state (window, - 0, - GDK_WINDOW_STATE_ICONIFIED); + if (window) + { + if (GDK_WINDOW_IS_MAPPED (window)) + gdk_synthesize_window_state (window, + 0, + GDK_WINDOW_STATE_ICONIFIED); - _gdk_xgrab_check_unmap (window, xevent->xany.serial); + _gdk_xgrab_check_unmap (window, xevent->xany.serial); + } break; @@ -1338,7 +1409,7 @@ gdk_event_translate (GdkEvent *event, gdk_error_trap_push (); if (XTranslateCoordinates (GDK_DRAWABLE_XDISPLAY (window), GDK_DRAWABLE_XID (window), - _gdk_root_window, + screen_x11->xroot_window, 0, 0, &tx, &ty, &child_window)) @@ -1365,9 +1436,8 @@ gdk_event_translate (GdkEvent *event, { window_private->resize_count -= 1; - if (window_private->resize_count == 0 && - window == _gdk_moveresize_window) - _gdk_moveresize_configure_done (); + if (window_private->resize_count == 0) + _gdk_moveresize_configure_done (display, window); } } break; @@ -1378,7 +1448,7 @@ gdk_event_translate (GdkEvent *event, xevent->xproperty.window, xevent->xproperty.atom, "\"", - gdk_x11_get_xatom_name (xevent->xproperty.atom), + gdk_x11_get_xatom_name_for_display (display, xevent->xproperty.atom), "\"")); if (window_private == NULL) @@ -1389,18 +1459,12 @@ gdk_event_translate (GdkEvent *event, event->property.type = GDK_PROPERTY_NOTIFY; event->property.window = window; - event->property.atom = gdk_x11_xatom_to_atom (xevent->xproperty.atom); + event->property.atom = gdk_x11_xatom_to_atom_for_display (display, xevent->xproperty.atom); event->property.time = xevent->xproperty.time; event->property.state = xevent->xproperty.state; - if (wm_state_atom == 0) - wm_state_atom = gdk_x11_get_xatom_by_name ("_NET_WM_STATE"); - - if (wm_desktop_atom == 0) - wm_desktop_atom = gdk_x11_get_xatom_by_name ("_NET_WM_DESKTOP"); - - if (xevent->xproperty.atom == wm_state_atom || - xevent->xproperty.atom == wm_desktop_atom) + if (xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE") || + xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP")) { /* If window state changed, then synthesize those events. */ gdk_check_wm_state_changed (event->property.window); @@ -1417,7 +1481,7 @@ gdk_event_translate (GdkEvent *event, { event->selection.type = GDK_SELECTION_CLEAR; event->selection.window = window; - event->selection.selection = gdk_x11_xatom_to_atom (xevent->xselectionclear.selection); + event->selection.selection = gdk_x11_xatom_to_atom_for_display (display, xevent->xselectionclear.selection); event->selection.time = xevent->xselectionclear.time; } else @@ -1432,9 +1496,9 @@ gdk_event_translate (GdkEvent *event, event->selection.type = GDK_SELECTION_REQUEST; event->selection.window = window; - event->selection.selection = gdk_x11_xatom_to_atom (xevent->xselectionrequest.selection); - event->selection.target = gdk_x11_xatom_to_atom (xevent->xselectionrequest.target); - event->selection.property = gdk_x11_xatom_to_atom (xevent->xselectionrequest.property); + event->selection.selection = gdk_x11_xatom_to_atom_for_display (display, xevent->xselectionrequest.selection); + event->selection.target = gdk_x11_xatom_to_atom_for_display (display, xevent->xselectionrequest.target); + event->selection.property = gdk_x11_xatom_to_atom_for_display (display, xevent->xselectionrequest.property); event->selection.requestor = xevent->xselectionrequest.requestor; event->selection.time = xevent->xselectionrequest.time; @@ -1448,9 +1512,9 @@ gdk_event_translate (GdkEvent *event, event->selection.type = GDK_SELECTION_NOTIFY; event->selection.window = window; - event->selection.selection = gdk_x11_xatom_to_atom (xevent->xselection.selection); - event->selection.target = gdk_x11_xatom_to_atom (xevent->xselection.target); - event->selection.property = gdk_x11_xatom_to_atom (xevent->xselection.property); + event->selection.selection = gdk_x11_xatom_to_atom_for_display (display, xevent->xselection.selection); + event->selection.target = gdk_x11_xatom_to_atom_for_display (display, xevent->xselection.target); + event->selection.property = gdk_x11_xatom_to_atom_for_display (display, xevent->xselection.property); event->selection.time = xevent->xselection.time; break; @@ -1468,13 +1532,13 @@ gdk_event_translate (GdkEvent *event, { GList *tmp_list; GdkFilterReturn result = GDK_FILTER_CONTINUE; - GdkAtom message_type = gdk_x11_xatom_to_atom (xevent->xclient.message_type); + GdkAtom message_type = gdk_x11_xatom_to_atom_for_display (display, xevent->xclient.message_type); GDK_NOTE (EVENTS, g_message ("client message:\twindow: %ld", xevent->xclient.window)); - tmp_list = client_filters; + tmp_list = display_x11->client_filters; while (tmp_list) { GdkClientFilter *filter = tmp_list->data; @@ -1523,25 +1587,26 @@ gdk_event_translate (GdkEvent *event, /* Let XLib know that there is a new keyboard mapping. */ XRefreshKeyboardMapping (&xevent->xmapping); - ++_gdk_keymap_serial; + ++display_x11->keymap_serial; return_val = FALSE; break; default: #ifdef HAVE_XKB - if (xevent->type == _gdk_xkb_event_type) + if (xevent->type == display_x11->xkb_event_type) { XkbEvent *xkb_event = (XkbEvent *)xevent; switch (xkb_event->any.xkb_type) { case XkbMapNotify: - ++_gdk_keymap_serial; + ++display_x11->keymap_serial; + return_val = FALSE; break; case XkbStateNotify: - _gdk_keymap_state_changed (); + _gdk_keymap_state_changed (display); break; } } @@ -1590,8 +1655,10 @@ gdk_wm_protocols_filter (GdkXEvent *xev, gpointer data) { XEvent *xevent = (XEvent *)xev; + GdkWindow *win = event->any.window; + GdkDisplay *display = GDK_WINDOW_DISPLAY (win); - if ((Atom) xevent->xclient.data.l[0] == gdk_x11_get_xatom_by_name ("WM_DELETE_WINDOW")) + if ((Atom) xevent->xclient.data.l[0] == gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW")) { /* The delete window request specifies a window * to delete. We don't actually destroy the @@ -1609,7 +1676,7 @@ gdk_wm_protocols_filter (GdkXEvent *xev, return GDK_FILTER_TRANSLATE; } - else if ((Atom) xevent->xclient.data.l[0] == gdk_x11_get_xatom_by_name ("WM_TAKE_FOCUS")) + else if ((Atom) xevent->xclient.data.l[0] == gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS")) { GdkWindow *win = event->any.window; Window focus_win = GDK_WINDOW_IMPL_X11(((GdkWindowObject *)win)->impl)->focus_window; @@ -1625,46 +1692,31 @@ gdk_wm_protocols_filter (GdkXEvent *xev, XSync (GDK_WINDOW_XDISPLAY (win), False); gdk_error_trap_pop (); } - else if ((Atom) xevent->xclient.data.l[0] == gdk_x11_get_xatom_by_name ("_NET_WM_PING")) + else if ((Atom) xevent->xclient.data.l[0] == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PING")) { XEvent xev = *xevent; - xev.xclient.window = _gdk_root_window; - XSendEvent (gdk_display, _gdk_root_window, False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); + xev.xclient.window = GDK_WINDOW_XROOTWIN (win); + XSendEvent (GDK_WINDOW_XDISPLAY (win), + xev.xclient.window, + False, + SubstructureRedirectMask | SubstructureNotifyMask, &xev); } return GDK_FILTER_REMOVE; } -#if 0 -static Bool -gdk_event_get_type (Display *display, - XEvent *xevent, - XPointer arg) -{ - GdkEvent event; - GdkPredicate *pred; - - if (gdk_event_translate (&event, xevent, FALSE)) - { - pred = (GdkPredicate*) arg; - return (* pred->func) (&event, pred->data); - } - - return FALSE; -} -#endif - void -_gdk_events_queue (void) +_gdk_events_queue (GdkDisplay *display) { GList *node; GdkEvent *event; XEvent xevent; + Display *xdisplay = GDK_DISPLAY_XDISPLAY (display); - while (!_gdk_event_queue_find_first() && XPending (gdk_display)) + while (!_gdk_event_queue_find_first(display) && XPending (xdisplay)) { - XNextEvent (gdk_display, &xevent); + XNextEvent (xdisplay, &xevent); switch (xevent.type) { @@ -1684,16 +1736,15 @@ _gdk_events_queue (void) ((GdkEventPrivate *)event)->flags |= GDK_EVENT_PENDING; - _gdk_event_queue_append (event); - node = _gdk_queued_tail; + node = _gdk_event_queue_append (display, event); - if (gdk_event_translate (event, &xevent, FALSE)) + if (gdk_event_translate (display, event, &xevent, FALSE)) { ((GdkEventPrivate *)event)->flags &= ~GDK_EVENT_PENDING; } else { - _gdk_event_queue_remove_link (node); + _gdk_event_queue_remove_link (display, node); g_list_free_1 (node); gdk_event_free (event); } @@ -1704,28 +1755,31 @@ static gboolean gdk_event_prepare (GSource *source, gint *timeout) { + GdkDisplay *display = ((GdkDisplaySource*)source)->display; gboolean retval; GDK_THREADS_ENTER (); *timeout = -1; - - retval = (_gdk_event_queue_find_first () != NULL) || XPending (gdk_display); - + retval = (_gdk_event_queue_find_first (display) != NULL || + gdk_check_xpending (display)); + GDK_THREADS_LEAVE (); return retval; } static gboolean -gdk_event_check (GSource *source) +gdk_event_check (GSource *source) { + GdkDisplaySource *display_source = (GdkDisplaySource*)source; gboolean retval; - + GDK_THREADS_ENTER (); - if (event_poll_fd.revents & G_IO_IN) - retval = (_gdk_event_queue_find_first () != NULL) || XPending (gdk_display); + if (display_source->event_poll_fd.revents & G_IO_IN) + retval = (_gdk_event_queue_find_first (display_source->display) != NULL || + gdk_check_xpending (display_source->display)); else retval = FALSE; @@ -1739,12 +1793,13 @@ gdk_event_dispatch (GSource *source, GSourceFunc callback, gpointer user_data) { + GdkDisplay *display = ((GdkDisplaySource*)source)->display; GdkEvent *event; GDK_THREADS_ENTER (); - _gdk_events_queue(); - event = _gdk_event_unqueue(); + _gdk_events_queue (display); + event = _gdk_event_unqueue (display); if (event) { @@ -1759,32 +1814,69 @@ gdk_event_dispatch (GSource *source, return TRUE; } -/* Sends a ClientMessage to all toplevel client windows */ +/** + * gdk_event_send_client_message: + * @event: the #GdkEvent to send, which should be a #GdkEventClient. + * @xid: the window to send the X ClientMessage event to. + * + * Sends an X ClientMessage event to a given window (which must be + * on the default #GdkDisplay.) + * This could be used for communicating between different applications, + * though the amount of data is limited to 20 bytes. + * + * Return value: non-zero on success. + **/ gboolean gdk_event_send_client_message (GdkEvent *event, guint32 xid) { + g_return_val_if_fail (event != NULL, FALSE); + + return gdk_event_send_client_message_for_display (gdk_get_default_display (), + event, xid); +} + +/** + * gdk_event_send_client_message_for_display : + * @display : the #GdkDisplay for the window where the message is to be sent. + * @event : the #GdkEvent to send, which should be a #GdkEventClient. + * @xid : the X window to send the X ClientMessage event to. + * + * Sends an X ClientMessage event to a given window. + * + * This could be used for communicating between different applications, + * though the amount of data is limited to 20 bytes. + * + * Returns : non-zero on success. + */ +gboolean +gdk_event_send_client_message_for_display (GdkDisplay *display, + GdkEvent *event, + guint32 xid) +{ XEvent sev; g_return_val_if_fail(event != NULL, FALSE); - + /* Set up our event to send, with the exception of its target window */ sev.xclient.type = ClientMessage; - sev.xclient.display = gdk_display; + sev.xclient.display = GDK_DISPLAY_XDISPLAY (display); sev.xclient.format = event->client.data_format; sev.xclient.window = xid; - memcpy(&sev.xclient.data, &event->client.data, sizeof(sev.xclient.data)); - sev.xclient.message_type = gdk_x11_atom_to_xatom (event->client.message_type); + memcpy(&sev.xclient.data, &event->client.data, sizeof (sev.xclient.data)); + sev.xclient.message_type = gdk_x11_atom_to_xatom_for_display (display, event->client.message_type); - return gdk_send_xevent (xid, False, NoEventMask, &sev); + return _gdk_send_xevent (display, xid, False, NoEventMask, &sev); } + + /* Sends a ClientMessage to all toplevel client windows */ gboolean -gdk_event_send_client_message_to_all_recurse (XEvent *xev, - guint32 xid, - guint level) +gdk_event_send_client_message_to_all_recurse (GdkDisplay *display, + XEvent *xev, + guint32 xid, + guint level) { - static Atom wm_state_atom = None; Atom type = None; int format; unsigned long nitems, after; @@ -1795,16 +1887,15 @@ gdk_event_send_client_message_to_all_recurse (XEvent *xev, gboolean found = FALSE; gboolean result = FALSE; int i; - - if (!wm_state_atom) - wm_state_atom = gdk_x11_get_xatom_by_name ("WM_STATE"); - + gdk_error_trap_push (); - if (XGetWindowProperty (gdk_display, xid, wm_state_atom, 0, 0, False, AnyPropertyType, + if (XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), xid, + gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"), + 0, 0, False, AnyPropertyType, &type, &format, &nitems, &after, &data) != Success) goto out; - + if (type) { send = TRUE; @@ -1813,12 +1904,13 @@ gdk_event_send_client_message_to_all_recurse (XEvent *xev, else { /* OK, we're all set, now let's find some windows to send this to */ - if (!XQueryTree (gdk_display, xid, &ret_root, &ret_parent, - &ret_children, &ret_nchildren)) + if (!XQueryTree (GDK_DISPLAY_XDISPLAY (display), xid, + &ret_root, &ret_parent, + &ret_children, &ret_nchildren)) goto out; for(i = 0; i < ret_nchildren; i++) - if (gdk_event_send_client_message_to_all_recurse (xev, ret_children[i], level + 1)) + if (gdk_event_send_client_message_to_all_recurse (display, xev, ret_children[i], level + 1)) found = TRUE; XFree (ret_children); @@ -1827,7 +1919,7 @@ gdk_event_send_client_message_to_all_recurse (XEvent *xev, if (send || (!found && (level == 1))) { xev->xclient.window = xid; - gdk_send_xevent (xid, False, NoEventMask, xev); + _gdk_send_xevent (display, xid, False, NoEventMask, xev); } result = send || found; @@ -1838,21 +1930,63 @@ gdk_event_send_client_message_to_all_recurse (XEvent *xev, return result; } +/** + * gdk_event_send_clientmessage_toall: + * @event: the #GdkEvent to send, which should be a #GdkEventClient. + * + * Sends an X ClientMessage event to all toplevel windows on the default + * #GdkScreen. + * + * Toplevel windows are determined by checking for the WM_STATE property, as + * described in the Inter-Client Communication Conventions Manual (ICCCM). + * If no windows are found with the WM_STATE property set, the message is sent + * to all children of the root window. + **/ void gdk_event_send_clientmessage_toall (GdkEvent *event) { + g_return_if_fail (event != NULL); + + gdk_screen_broadcast_client_message (gdk_get_default_screen (), event); +} + +/** + * gdk_screen_broadcast_client_message: + * @screen : the #GdkScreen where the event will be broadcasted. + * @event : the #GdkEvent. + * + * Sends an X ClientMessage event to all toplevel windows on @screen. + * + * Toplevel windows are determined by checking for the WM_STATE property, + * as described in the Inter-Client Communication Conventions Manual (ICCCM). + * If no windows are found with the WM_STATE property set, the message is + * sent to all children of the root window. + */ + +void +gdk_screen_broadcast_client_message (GdkScreen *screen, + GdkEvent *event) +{ XEvent sev; + GdkWindow *root_window; - g_return_if_fail(event != NULL); + g_return_if_fail (event != NULL); + + root_window = gdk_screen_get_root_window (screen); /* Set up our event to send, with the exception of its target window */ sev.xclient.type = ClientMessage; - sev.xclient.display = gdk_display; + sev.xclient.display = GDK_WINDOW_XDISPLAY (root_window); sev.xclient.format = event->client.data_format; - memcpy(&sev.xclient.data, &event->client.data, sizeof(sev.xclient.data)); - sev.xclient.message_type = gdk_x11_atom_to_xatom (event->client.message_type); - - gdk_event_send_client_message_to_all_recurse(&sev, _gdk_root_window, 0); + memcpy(&sev.xclient.data, &event->client.data, sizeof (sev.xclient.data)); + sev.xclient.message_type = + gdk_x11_atom_to_xatom_for_display (GDK_WINDOW_DISPLAY (root_window), + event->client.message_type); + + gdk_event_send_client_message_to_all_recurse (gdk_screen_get_display (screen), + &sev, + GDK_WINDOW_XID (root_window), + 0); } /* @@ -1876,21 +2010,27 @@ gdk_event_send_clientmessage_toall (GdkEvent *event) void gdk_flush (void) { - XSync (gdk_display, False); + GSList *tmp_list = _gdk_displays; + + while (tmp_list) + { + XSync (GDK_DISPLAY_XDISPLAY (tmp_list->data), False); + tmp_list = tmp_list->next; + } } -static Atom timestamp_prop_atom = 0; - static Bool timestamp_predicate (Display *display, XEvent *xevent, XPointer arg) { Window xwindow = GPOINTER_TO_UINT (arg); + GdkDisplay *gdk_display = gdk_x11_lookup_xdisplay (display); if (xevent->type == PropertyNotify && xevent->xproperty.window == xwindow && - xevent->xproperty.atom == timestamp_prop_atom) + xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display + (gdk_display, "GDK_TIMESTAMP_PROP")) return True; return False; @@ -1913,18 +2053,19 @@ gdk_x11_get_server_time (GdkWindow *window) Window xwindow; guchar c = 'a'; XEvent xevent; + Atom timestamp_prop_atom; g_return_val_if_fail (GDK_IS_WINDOW (window), 0); g_return_val_if_fail (!GDK_WINDOW_DESTROYED (window), 0); - if (!timestamp_prop_atom) - timestamp_prop_atom = gdk_x11_get_xatom_by_name ("GDK_TIMESTAMP_PROP"); - xdisplay = GDK_WINDOW_XDISPLAY (window); xwindow = GDK_WINDOW_XWINDOW (window); + timestamp_prop_atom = + gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window), + "GDK_TIMESTAMP_PROP"); - XChangeProperty (xdisplay, xwindow, - timestamp_prop_atom, timestamp_prop_atom, + XChangeProperty (xdisplay, xwindow, timestamp_prop_atom, + timestamp_prop_atom, 8, PropModeReplace, &c, 1); XIfEvent (xdisplay, &xevent, @@ -1933,10 +2074,18 @@ gdk_x11_get_server_time (GdkWindow *window) return xevent.xproperty.time; } +typedef struct _NetWmSupportedAtoms NetWmSupportedAtoms; + +struct _NetWmSupportedAtoms +{ + Atom *atoms; + gulong n_atoms; +}; /** - * gdk_net_wm_supports: - * @property: a property atom + * gdk_x11_screen_supports_net_wm_hint: + * @screen : the relevant #GdkScreen. + * @property: a property atom. * * This function is specific to the X11 backend of GDK, and indicates * whether the window manager supports a certain hint from the @@ -1953,42 +2102,53 @@ gdk_x11_get_server_time (GdkWindow *window) * Return value: %TRUE if the window manager supports @property **/ gboolean -gdk_net_wm_supports (GdkAtom property) +gdk_x11_screen_supports_net_wm_hint (GdkScreen *screen, + GdkAtom property) { - static Atom wmspec_check_atom = 0; - static Atom wmspec_supported_atom = 0; - static Atom *atoms = NULL; - static gulong n_atoms = 0; - Atom xproperty = gdk_x11_atom_to_xatom (property); Atom type; gint format; gulong nitems; gulong bytes_after; Window *xwindow; gulong i; + GdkScreenX11 *screen_x11; + NetWmSupportedAtoms *supported_atoms; + GdkDisplay *display; + + g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE); + + screen_x11 = GDK_SCREEN_X11 (screen); + display = screen_x11->display; - if (wmspec_check_window != None) + supported_atoms = g_object_get_data (G_OBJECT (screen), "gdk-net-wm-supported-atoms"); + if (!supported_atoms) { - if (atoms == NULL) - return FALSE; + supported_atoms = g_new0 (NetWmSupportedAtoms, 1); + g_object_set_data (G_OBJECT (screen), "net-wm-supported-atoms", supported_atoms); + } + if (screen_x11->wmspec_check_window != None) + { + if (supported_atoms->atoms == NULL) + return FALSE; + i = 0; - while (i < n_atoms) + while (i < supported_atoms->n_atoms) { - if (atoms[i] == xproperty) + if (supported_atoms->atoms[i] == gdk_x11_atom_to_xatom_for_display (display, property)) return TRUE; ++i; } - + return FALSE; } - if (atoms) - XFree (atoms); + if (supported_atoms->atoms) + XFree (supported_atoms->atoms); - atoms = NULL; - n_atoms = 0; + supported_atoms->atoms = NULL; + supported_atoms->n_atoms = 0; /* This function is very slow on every call if you are not running a * spec-supporting WM. For now not optimized, because it isn't in @@ -1998,47 +2158,59 @@ gdk_net_wm_supports (GdkAtom property) * _NET_SUPPORTING_WM_CHECK only once every 10 seconds or something. */ - if (wmspec_check_atom == 0) - wmspec_check_atom = gdk_x11_get_xatom_by_name ("_NET_SUPPORTING_WM_CHECK"); - - if (wmspec_supported_atom == 0) - wmspec_supported_atom = gdk_x11_get_xatom_by_name ("_NET_SUPPORTED"); + XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), screen_x11->xroot_window, + gdk_x11_get_xatom_by_name_for_display (display, "_NET_SUPPORTING_WM_CHECK"), + 0, G_MAXLONG, False, XA_WINDOW, &type, &format, + &nitems, &bytes_after, (guchar **) & xwindow); - XGetWindowProperty (gdk_display, _gdk_root_window, - wmspec_check_atom, 0, G_MAXLONG, - False, XA_WINDOW, &type, &format, &nitems, - &bytes_after, (guchar **)&xwindow); - if (type != XA_WINDOW) return FALSE; gdk_error_trap_push (); /* Find out if this WM goes away, so we can reset everything. */ - XSelectInput (gdk_display, *xwindow, - StructureNotifyMask); - - gdk_flush (); + XSelectInput (screen_x11->xdisplay, *xwindow, StructureNotifyMask); + + gdk_display_sync (screen_x11->display); if (gdk_error_trap_pop ()) { XFree (xwindow); return FALSE; } - - XGetWindowProperty (gdk_display, _gdk_root_window, - wmspec_supported_atom, 0, G_MAXLONG, - False, XA_ATOM, &type, &format, &n_atoms, - &bytes_after, (guchar **)&atoms); + + XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), screen_x11->xroot_window, + gdk_x11_get_xatom_by_name_for_display (display, "_NET_SUPPORTED"), + 0, G_MAXLONG, False, XA_ATOM, &type, &format, + &supported_atoms->n_atoms, &bytes_after, + (guchar **)&supported_atoms->atoms); if (type != XA_ATOM) return FALSE; - wmspec_check_window = *xwindow; + screen_x11->wmspec_check_window = *xwindow; XFree (xwindow); /* since wmspec_check_window != None this isn't infinite. ;-) */ - return gdk_net_wm_supports (property); + return gdk_x11_screen_supports_net_wm_hint (screen, property); +} + +/** + * gdk_net_wm_supports: + * @screen : the relevant #GdkScreen. + * @property: a property atom. + * + * This function is specific to the X11 backend of GDK, and indicates + * whether the window manager for the default screen supports a certain + * hint from the Extended Window Manager Hints Specification. See + * gdk_x11_screen_supports_net_wm_hint() for complete details. + * + * Return value: %TRUE if the window manager supports @property + **/ +gboolean +gdk_net_wm_supports (GdkAtom property) +{ + return gdk_x11_screen_supports_net_wm_hint (gdk_get_default_screen (), property); } static struct @@ -2060,16 +2232,17 @@ static struct }; static void -gdk_xsettings_notify_cb (const char *name, - XSettingsAction action, - XSettingsSetting *setting, - void *data) +gdk_xsettings_notify_cb (const char *name, + XSettingsAction action, + XSettingsSetting *setting, + void *data) { GdkEvent new_event; + GdkScreen *screen = data; int i; new_event.type = GDK_SETTING; - new_event.setting.window = NULL; + new_event.setting.window = gdk_screen_get_root_window (screen); new_event.setting.send_event = FALSE; new_event.setting.name = NULL; @@ -2116,16 +2289,56 @@ check_transform (const gchar *xsettings_name, return TRUE; } +/** + * gdk_setting_get: + * @name: the name of the setting. + * @value: location to store the value of the setting. + * + * Obtains a desktop-wide setting, such as the double-click time, + * for the default screen. See gdk_screen_get_setting(). + * + * Returns : %TRUE if the setting existed and a value was stored + * in @value, %FALSE otherwise. + **/ gboolean gdk_setting_get (const gchar *name, GValue *value) { + return gdk_screen_get_setting (gdk_get_default_screen (), name, value); +} + +/** + * gdk_screen_get_setting: + * @screen: the #GdkScreen where the setting is located + * @name: the name of the setting + * @value: location to store the value of the setting + * + * Retrieves a desktop-wide setting such as double-click time + * for the #GdkScreen @screen. + * + * FIXME needs a list of valid settings here, or a link to + * more information. + * + * Returns : %TRUE if the setting existed and a value was stored + * in @value, %FALSE otherwise. + **/ +gboolean +gdk_screen_get_setting (GdkScreen *screen, + const gchar *name, + GValue *value) +{ + const char *xsettings_name = NULL; XSettingsResult result; XSettingsSetting *setting; + GdkScreenX11 *screen_x11; gboolean success = FALSE; gint i; GValue tmp_val = { 0, }; + + g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE); + + screen_x11 = GDK_SCREEN_X11 (screen); for (i = 0; i < G_N_ELEMENTS (settings_map) ; i++) if (strcmp (settings_map[i].gdk_name, name) == 0) @@ -2137,7 +2350,8 @@ gdk_setting_get (const gchar *name, if (!xsettings_name) return FALSE; - result = xsettings_client_get_setting (xsettings_client, xsettings_name, &setting); + result = xsettings_client_get_setting (screen_x11->xsettings_client, + xsettings_name, &setting); if (result != XSETTINGS_SUCCESS) return FALSE; @@ -2196,23 +2410,27 @@ gdk_xsettings_client_event_filter (GdkXEvent *xevent, GdkEvent *event, gpointer data) { - if (xsettings_client_process_event (xsettings_client, (XEvent *)xevent)) + GdkScreenX11 *screen = data; + + if (xsettings_client_process_event (screen->xsettings_client, (XEvent *)xevent)) return GDK_FILTER_REMOVE; else return GDK_FILTER_CONTINUE; } static void -gdk_xsettings_watch_cb (Window window, - Bool is_start, - long mask, - void *cb_data) +gdk_xsettings_watch_cb (Window window, + Bool is_start, + long mask, + void *cb_data) { GdkWindow *gdkwin; + GdkScreen *screen = cb_data; - gdkwin = gdk_window_lookup (window); + gdkwin = gdk_window_lookup_for_display (gdk_screen_get_display (screen), window); + if (is_start) - gdk_window_add_filter (gdkwin, gdk_xsettings_client_event_filter, NULL); + gdk_window_add_filter (gdkwin, gdk_xsettings_client_event_filter, screen); else - gdk_window_remove_filter (gdkwin, gdk_xsettings_client_event_filter, NULL); + gdk_window_remove_filter (gdkwin, gdk_xsettings_client_event_filter, screen); } |