#include "gdkprivate-x11.h"
#include "gdkinternals.h"
#include "gdkx.h"
+#include "gdkscreen-x11.h"
+#include "gdkdisplay-x11.h"
#include "gdkkeysyms.h"
#include <X11/Xatom.h>
typedef struct _GdkIOClosure GdkIOClosure;
-typedef struct _GdkEventPrivate GdkEventPrivate;
+typedef struct _GdkDisplaySource GdkDisplaySource;
#define DOUBLE_CLICK_TIME 250
#define TRIPLE_CLICK_TIME 500
#define DOUBLE_CLICK_DIST 5
#define TRIPLE_CLICK_DIST 5
-typedef enum
-{
- /* Following flag is set for events on the event queue during
- * translation and cleared afterwards.
- */
- GDK_EVENT_PENDING = 1 << 0
-} GdkEventFlags;
-
struct _GdkIOClosure
{
GdkInputFunction function;
gpointer data;
};
-struct _GdkEventPrivate
+struct _GdkDisplaySource
{
- GdkEvent event;
- guint flags;
+ GSource source;
+
+ GdkDisplay *display;
+ GPollFD event_poll_fd;
};
/*
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);
GSourceFunc callback,
gpointer user_data);
-GdkFilterReturn gdk_wm_protocols_filter (GdkXEvent *xev,
- GdkEvent *event,
- gpointer data);
+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,
/* 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,
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);
+
+ /* Keep a flag to avoid extra notifies that we don't need
+ */
+ screen_x11->xsettings_in_init = TRUE;
+ screen_x11->xsettings_client = xsettings_client_new (screen_x11->xdisplay,
+ screen_x11->screen_num,
+ gdk_xsettings_notify_cb,
+ gdk_xsettings_watch_cb,
+ screen);
+ screen_x11->xsettings_in_init = FALSE;
+}
+
+void
+_gdk_x11_events_uninit_screen (GdkScreen *screen)
+{
+ GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
+
+ xsettings_client_destroy (screen_x11->xsettings_client);
+ screen_x11->xsettings_client = NULL;
+}
+
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 = display_x11->event_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_add_client_message_filter (gdk_wm_protocols,
- gdk_wm_protocols_filter, NULL);
+ display_sources = g_list_prepend (display_sources,display_source);
- xsettings_client = xsettings_client_new (gdk_display, DefaultScreen (gdk_display),
- gdk_xsettings_notify_cb,
- gdk_xsettings_watch_cb,
- NULL);
+ gdk_display_add_client_message_filter (
+ display,
+ gdk_atom_intern ("WM_PROTOCOLS", FALSE),
+ gdk_wm_protocols_filter,
+ NULL);
}
-/*
- *--------------------------------------------------------------
- * 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,
XEvent *xevent,
XPointer arg)
{
- if (xevent->xany.window == GDK_DRAWABLE_XID (arg) &&
+ if (xevent->xany.window == GDK_DRAWABLE_XID ((GdkDrawable *)arg) &&
(xevent->xany.type == GraphicsExpose ||
xevent->xany.type == NoExpose))
return True;
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)
{
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 ();
+ event = gdk_event_new (GDK_NOTHING);
- 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);
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.
+ *
+ * Since: 2.2
+ **/
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 GdkAtom wm_state_atom = 0;
-static GdkAtom 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_display_get_default (),
+ message_type, func, data);
+}
static void
gdk_check_wm_state_changed (GdkWindow *window)
gint format;
gulong nitems;
gulong bytes_after;
- GdkAtom *atoms = NULL;
+ Atom *atoms = NULL;
gulong i;
- GdkAtom sticky_atom;
- GdkAtom maxvert_atom;
- GdkAtom maxhorz_atom;
- gboolean found_sticky, found_maxvert, found_maxhorz;
+ gboolean found_sticky, found_maxvert, found_maxhorz, found_fullscreen;
GdkWindowState old_state;
+ GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ gdk_window_get_window_type (window) != GDK_WINDOW_TOPLEVEL)
return;
- if (wm_state_atom == 0)
- wm_state_atom = gdk_atom_intern ("_NET_WM_STATE", FALSE);
-
- if (wm_desktop_atom == 0)
- wm_desktop_atom = gdk_atom_intern ("_NET_WM_DESKTOP", FALSE);
+ found_sticky = FALSE;
+ found_maxvert = FALSE;
+ found_maxhorz = FALSE;
+ found_fullscreen = 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)
{
-
- sticky_atom = gdk_atom_intern ("_NET_WM_STATE_STICKY", FALSE);
- maxvert_atom = gdk_atom_intern ("_NET_WM_STATE_MAXIMIZED_VERT", FALSE);
- maxhorz_atom = gdk_atom_intern ("_NET_WM_STATE_MAXIMIZED_HORZ", FALSE);
-
- found_sticky = FALSE;
- found_maxvert = FALSE;
- found_maxhorz = FALSE;
-
+ 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");
+ Atom fullscreen_atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_FULLSCREEN");
+
i = 0;
while (i < nitems)
{
found_maxvert = TRUE;
else if (atoms[i] == maxhorz_atom)
found_maxhorz = TRUE;
-
+ else if (atoms[i] == fullscreen_atom)
+ found_fullscreen = TRUE;
+
++i;
}
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
{
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)
GDK_WINDOW_STATE_STICKY);
}
+ if (old_state & GDK_WINDOW_STATE_FULLSCREEN)
+ {
+ if (!found_fullscreen)
+ gdk_synthesize_window_state (window,
+ GDK_WINDOW_STATE_FULLSCREEN,
+ 0);
+ }
+ else
+ {
+ if (found_fullscreen)
+ gdk_synthesize_window_state (window,
+ 0,
+ GDK_WINDOW_STATE_FULLSCREEN);
+ }
+
/* Our "maximized" means both vertical and horizontal; if only one,
* we don't expose that via GDK
*/
gdk_event_put (&event);
}
-static gint
-gdk_event_translate (GdkEvent *event,
- XEvent *xevent,
- gboolean return_exposes)
+static void
+set_screen_from_root (GdkDisplay *display,
+ GdkEvent *event,
+ Window xrootwin)
+{
+ GdkScreen *screen;
+
+ screen = _gdk_x11_display_screen_for_xrootwin (display, xrootwin);
+ g_assert (screen);
+
+ gdk_event_set_screen (event, screen);
+}
+
+static void
+translate_key_event (GdkDisplay *display,
+ GdkEvent *event,
+ XEvent *xevent)
+{
+ GdkKeymap *keymap = gdk_keymap_get_for_display (display);
+ gunichar c = 0;
+ guchar buf[7];
+
+ event->key.type = xevent->xany.type == KeyPress ? GDK_KEY_PRESS : GDK_KEY_RELEASE;
+ event->key.time = xevent->xkey.time;
+
+ event->key.state = (GdkModifierType) xevent->xkey.state;
+ event->key.group = _gdk_x11_get_group_for_state (display, xevent->xkey.state);
+ event->key.hardware_keycode = xevent->xkey.keycode;
+
+ event->key.keyval = GDK_VoidSymbol;
+
+ gdk_keymap_translate_keyboard_state (keymap,
+ event->key.hardware_keycode,
+ event->key.state,
+ event->key.group,
+ &event->key.keyval,
+ NULL, NULL, NULL);
+
+ /* Fill in event->string crudely, since various programs
+ * depend on it.
+ */
+ event->key.string = NULL;
+
+ if (event->key.keyval != GDK_VoidSymbol)
+ c = gdk_keyval_to_unicode (event->key.keyval);
+
+ if (c)
+ {
+ gsize bytes_written;
+ gint len;
+
+ /* Apply the control key - Taken from Xlib
+ */
+ if (event->key.state & GDK_CONTROL_MASK)
+ {
+ if ((c >= '@' && c < '\177') || c == ' ') c &= 0x1F;
+ else if (c == '2')
+ {
+ event->key.string = g_memdup ("\0\0", 2);
+ event->key.length = 1;
+ buf[0] = '\0';
+ goto out;
+ }
+ else if (c >= '3' && c <= '7') c -= ('3' - '\033');
+ else if (c == '8') c = '\177';
+ else if (c == '/') c = '_' & 0x1F;
+ }
+
+ len = g_unichar_to_utf8 (c, buf);
+ buf[len] = '\0';
+
+ event->key.string = g_locale_from_utf8 (buf, len,
+ NULL, &bytes_written,
+ NULL);
+ if (event->key.string)
+ event->key.length = bytes_written;
+ }
+ else if (event->key.keyval == GDK_Escape)
+ {
+ event->key.length = 1;
+ event->key.string = g_strdup ("\033");
+ }
+ else if (event->key.keyval == GDK_Return ||
+ event->key.keyval == GDK_KP_Enter)
+ {
+ event->key.length = 1;
+ event->key.string = g_strdup ("\r");
+ }
+
+ if (!event->key.string)
+ {
+ event->key.length = 0;
+ event->key.string = g_strdup ("");
+ }
+
+ out:
+#ifdef G_ENABLE_DEBUG
+ if (_gdk_debug_flags & GDK_DEBUG_EVENTS)
+ {
+ g_message ("%s:\t\twindow: %ld key: %12s %d",
+ event->type == GDK_KEY_PRESS ? "key press " : "key release",
+ xevent->xkey.window,
+ event->key.keyval ? gdk_keyval_name (event->key.keyval) : "(none)",
+ event->key.keyval);
+
+ if (event->key.length > 0)
+ g_message ("\t\tlength: %4d string: \"%s\"",
+ event->key.length, buf);
+ }
+#endif /* G_ENABLE_DEBUG */
+}
+
+/* Return the window this has to do with, if any, rather
+ * than the frame or root window that was selecting
+ * for substructure
+ */
+static Window
+get_real_window (XEvent *event)
+{
+ switch (event->type)
+ {
+ case CreateNotify:
+ return event->xcreatewindow.window;
+
+ case DestroyNotify:
+ return event->xdestroywindow.window;
+
+ case UnmapNotify:
+ return event->xunmap.window;
+
+ case MapNotify:
+ return event->xmap.window;
+
+ case MapRequest:
+ return event->xmaprequest.window;
+
+ case ReparentNotify:
+ return event->xreparent.window;
+
+ case ConfigureNotify:
+ return event->xconfigure.window;
+
+ case ConfigureRequest:
+ return event->xconfigurerequest.window;
+
+ case GravityNotify:
+ return event->xgravity.window;
+
+ case CirculateNotify:
+ return event->xcirculate.window;
+
+ case CirculateRequest:
+ return event->xcirculaterequest.window;
+
+ default:
+ return event->xany.window;
+ }
+}
+
+#ifdef G_ENABLE_DEBUG
+static const char notify_modes[][18] = {
+ "NotifyNormal",
+ "NotifyGrab",
+ "NotifyUngrab",
+ "NotifyWhileGrabbed"
+};
+
+static const char notify_details[][22] = {
+ "NotifyAncestor",
+ "NotifyVirtual",
+ "NotifyInferior",
+ "NotifyNonlinear",
+ "NotifyNonlinearVirtual",
+ "NotifyPointer",
+ "NotifyPointerRoot",
+ "NotifyDetailNone"
+};
+#endif
+
+static gboolean
+gdk_event_translate (GdkDisplay *display,
+ GdkEvent *event,
+ XEvent *xevent,
+ gboolean return_exposes)
{
GdkWindow *window;
GdkWindowObject *window_private;
+ GdkWindow *filter_window;
GdkWindowImplX11 *window_impl = NULL;
- static XComposeStatus compose;
- KeySym keysym;
- int charcount;
- char buf[16];
gint return_val;
gint xoffset, yoffset;
+ GdkScreen *screen = NULL;
+ GdkScreenX11 *screen_x11 = NULL;
+ GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
+ Window xwindow;
return_val = FALSE;
-
- /* Find the GdkWindow that this event occurred in.
- *
- * We handle events with window=None
- * specially - they are generated by XFree86's XInput under
- * some circumstances.
- */
+
+ /* init these, since the done: block uses them */
+ window = NULL;
+ window_private = NULL;
+ event->any.window = NULL;
+
+ if (_gdk_default_filters)
+ {
+ /* Apply global filters */
+ GdkFilterReturn result;
+ result = gdk_event_apply_filters (xevent, event,
+ _gdk_default_filters);
+
+ if (result != GDK_FILTER_CONTINUE)
+ {
+ return_val = (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
+ goto done;
+ }
+ }
+
+ /* We handle events with window=None
+ * specially - they are generated by XFree86's XInput under
+ * some circumstances. This handling for obvious reasons
+ * goes before we bother to lookup the event window.
+ */
if (xevent->xany.window == None)
{
else
return_val = FALSE;
}
+
+ /* Find the GdkWindow that this event relates to.
+ * Basically this means substructure events
+ * are reported same as structure events
+ */
+ xwindow = get_real_window (xevent);
- window = gdk_window_lookup (xevent->xany.window);
+ window = gdk_window_lookup_for_display (display, xwindow);
window_private = (GdkWindowObject *) window;
- if (_gdk_moveresize_window &&
- (xevent->xany.type == MotionNotify ||
- xevent->xany.type == ButtonRelease))
+ /* We always run the filters for the window where the event
+ * is delivered, not the window that it relates to
+ */
+ if (xevent->xany.window == xwindow)
+ filter_window = window;
+ else
+ filter_window = gdk_window_lookup_for_display (display, xevent->xany.window);
+
+ if (window)
{
- _gdk_moveresize_handle_event (xevent);
- gdk_window_unref (window);
- return FALSE;
+ screen = GDK_WINDOW_SCREEN (window);
+ screen_x11 = GDK_SCREEN_X11 (screen);
}
- if (wmspec_check_window != None &&
- xevent->xany.window == wmspec_check_window)
- {
- if (xevent->type == DestroyNotify)
- wmspec_check_window = None;
-
- /* Eat events on this window unless someone had wrapped
- * it as a foreign window
- */
- if (window == NULL)
- return FALSE;
- }
-
- /* FIXME: window might be a GdkPixmap!!! */
if (window != NULL)
{
- window_impl = GDK_WINDOW_IMPL_X11 (window_private->impl);
-
- if (xevent->xany.window != GDK_WINDOW_XID (window))
- {
- g_assert (xevent->xany.window == window_impl->focus_window);
-
- switch (xevent->type)
- {
- case KeyPress:
- case KeyRelease:
- xevent->xany.window = GDK_WINDOW_XID (window);
- break;
- default:
- return False;
- }
- }
+ /* Window may be a pixmap, so check its type.
+ * (This check is probably too expensive unless
+ * GLib short-circuits an exact type match,
+ * which has been proposed)
+ */
+ if (GDK_IS_WINDOW (window))
+ {
+ window_impl = GDK_WINDOW_IMPL_X11 (window_private->impl);
+
+ /* Move key events on focus window to the real toplevel, and
+ * filter out all other events on focus window
+ */
+ if (xwindow == window_impl->focus_window)
+ {
+ switch (xevent->type)
+ {
+ case KeyPress:
+ case KeyRelease:
+ xwindow = GDK_WINDOW_XID (window);
+ xevent->xany.window = xwindow;
+ break;
+ default:
+ return FALSE;
+ }
+ }
+ }
- gdk_window_ref (window);
+ g_object_ref (window);
}
event->any.window = window;
if (window_private && GDK_WINDOW_DESTROYED (window))
{
if (xevent->type != DestroyNotify)
- return FALSE;
+ {
+ return_val = FALSE;
+ goto done;
+ }
}
- else
+ else if (filter_window)
{
- /* Check for filters for this window
- */
+ /* Apply per-window filters */
+ GdkWindowObject *filter_private = (GdkWindowObject *) filter_window;
GdkFilterReturn result;
- result = gdk_event_apply_filters (xevent, event,
- window_private
- ?window_private->filters
- :gdk_default_filters);
+
+ if (filter_private->filters)
+ {
+ g_object_ref (filter_window);
+
+ result = gdk_event_apply_filters (xevent, event,
+ filter_private->filters);
+
+ g_object_unref (filter_window);
- if (result != GDK_FILTER_CONTINUE)
+ if (result != GDK_FILTER_CONTINUE)
+ {
+ return_val = (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
+ goto done;
+ }
+ }
+ }
+
+ if (screen_x11 && screen_x11->wmspec_check_window != None &&
+ xwindow == screen_x11->wmspec_check_window)
+ {
+ if (xevent->type == DestroyNotify)
+ {
+ screen_x11->wmspec_check_window = None;
+ g_free (screen_x11->window_manager_name);
+ screen_x11->window_manager_name = g_strdup ("unknown");
+
+ /* careful, reentrancy */
+ _gdk_x11_screen_window_manager_changed (GDK_SCREEN (screen_x11));
+ }
+
+ /* Eat events on this window unless someone had wrapped
+ * it as a foreign window
+ */
+ if (window == NULL)
{
- return_val = (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
+ return_val = FALSE;
goto done;
}
}
+ if (window &&
+ (xevent->xany.type == MotionNotify ||
+ xevent->xany.type == ButtonRelease))
+ {
+ if (_gdk_moveresize_handle_event (xevent))
+ {
+ return_val = FALSE;
+ goto done;
+ }
+ }
+
/* We do a "manual" conversion of the XEvent to a
* GdkEvent. The structures are mostly the same so
* the conversion is fairly straightforward. We also
switch (xevent->type)
{
case KeyPress:
- /* Lookup the string corresponding to the given keysym.
- */
-
- charcount = XLookupString (&xevent->xkey, buf, 16,
- &keysym, &compose);
- event->key.keyval = keysym;
- event->key.hardware_keycode = xevent->xkey.keycode;
-
- if (charcount > 0 && buf[charcount-1] == '\0')
- charcount --;
- else
- buf[charcount] = '\0';
-
-#ifdef G_ENABLE_DEBUG
- if (gdk_debug_flags & GDK_DEBUG_EVENTS)
- {
- g_message ("key press:\twindow: %ld key: %12s %d",
- xevent->xkey.window,
- event->key.keyval ? XKeysymToString (event->key.keyval) : "(none)",
- event->key.keyval);
- if (charcount > 0)
- g_message ("\t\tlength: %4d string: \"%s\"",
- charcount, buf);
- }
-#endif /* G_ENABLE_DEBUG */
-
- /* bits 13 and 14 in the "state" field are the keyboard group */
-#define KEYBOARD_GROUP_SHIFT 13
-#define KEYBOARD_GROUP_MASK ((1 << 13) | (1 << 14))
-
- event->key.type = GDK_KEY_PRESS;
- event->key.window = window;
- event->key.time = xevent->xkey.time;
- event->key.state = (GdkModifierType) xevent->xkey.state;
- event->key.string = g_strdup (buf);
- event->key.length = charcount;
-
- event->key.group = (xevent->xkey.state & KEYBOARD_GROUP_MASK) >> KEYBOARD_GROUP_SHIFT;
-
+ if (window_private == NULL)
+ {
+ return_val = FALSE;
+ break;
+ }
+ translate_key_event (display, event, xevent);
break;
-
- case KeyRelease:
- /* Lookup the string corresponding to the given keysym.
- */
+ case KeyRelease:
+ if (window_private == NULL)
+ {
+ return_val = FALSE;
+ break;
+ }
+
/* Emulate detectable auto-repeat by checking to see
* if the next event is a key press with the same
* 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 &&
next_event.xkey.time == xevent->xkey.time)
- break;
+ {
+ return_val = FALSE;
+ break;
+ }
}
-
- keysym = GDK_VoidSymbol;
- charcount = XLookupString (&xevent->xkey, buf, 16,
- &keysym, &compose);
- event->key.keyval = keysym;
-
- GDK_NOTE (EVENTS,
- g_message ("key release:\t\twindow: %ld key: %12s %d",
- xevent->xkey.window,
- XKeysymToString (event->key.keyval),
- event->key.keyval));
-
- event->key.type = GDK_KEY_RELEASE;
- event->key.window = window;
- event->key.time = xevent->xkey.time;
- event->key.state = (GdkModifierType) xevent->xkey.state;
- event->key.length = 0;
- event->key.string = NULL;
-
+
+ translate_key_event (display, event, xevent);
break;
case ButtonPress:
xevent->xbutton.x, xevent->xbutton.y,
xevent->xbutton.button));
- if (window_private &&
- (window_private->extension_events != 0) &&
- gdk_input_ignore_core)
+ if (window_private == NULL ||
+ ((window_private->extension_events != 0) &&
+ display_x11->input_ignore_core))
{
return_val = FALSE;
break;
event->scroll.direction = GDK_SCROLL_RIGHT;
event->scroll.window = window;
- event->scroll.time = xevent->xbutton.x;
+ event->scroll.time = xevent->xbutton.time;
event->scroll.x = xevent->xbutton.x + xoffset;
event->scroll.y = xevent->xbutton.y + yoffset;
event->scroll.x_root = (gfloat)xevent->xbutton.x_root;
event->scroll.y_root = (gfloat)xevent->xbutton.y_root;
event->scroll.state = (GdkModifierType) xevent->xbutton.state;
- event->scroll.device = gdk_core_pointer;
+ event->scroll.device = display->core_pointer;
+
+ set_screen_from_root (display, event, xevent->xbutton.root);
+
break;
default:
event->button.axes = NULL;
event->button.state = (GdkModifierType) xevent->xbutton.state;
event->button.button = xevent->xbutton.button;
- event->button.device = gdk_core_pointer;
+ event->button.device = display->core_pointer;
- gdk_event_button_generate (event);
+ set_screen_from_root (display, event, xevent->xbutton.root);
+
+ _gdk_event_button_generate (display, event);
break;
}
xevent->xbutton.x, xevent->xbutton.y,
xevent->xbutton.button));
- if (window_private &&
- (window_private->extension_events != 0) &&
- gdk_input_ignore_core)
+ if (window_private == NULL ||
+ ((window_private->extension_events != 0) &&
+ display_x11->input_ignore_core))
{
return_val = FALSE;
break;
}
/* We treat button presses as scroll wheel events, so ignore the release */
- if (xevent->xbutton.button == 4 || xevent->xbutton.button == 5)
+ if (xevent->xbutton.button == 4 || xevent->xbutton.button == 5 ||
+ xevent->xbutton.button == 6 || xevent->xbutton.button ==7)
{
return_val = FALSE;
break;
event->button.axes = NULL;
event->button.state = (GdkModifierType) xevent->xbutton.state;
event->button.button = xevent->xbutton.button;
- event->button.device = gdk_core_pointer;
+ event->button.device = display->core_pointer;
+
+ set_screen_from_root (display, event, xevent->xbutton.root);
break;
xevent->xmotion.x, xevent->xmotion.y,
(xevent->xmotion.is_hint) ? "true" : "false"));
- if (window_private &&
- (window_private->extension_events != 0) &&
- gdk_input_ignore_core)
+ if (window_private == NULL ||
+ ((window_private->extension_events != 0) &&
+ display_x11->input_ignore_core))
{
return_val = FALSE;
break;
event->motion.axes = NULL;
event->motion.state = (GdkModifierType) xevent->xmotion.state;
event->motion.is_hint = xevent->xmotion.is_hint;
- event->motion.device = gdk_core_pointer;
+ event->motion.device = display->core_pointer;
+
+ set_screen_from_root (display, event, xevent->xmotion.root);
break;
xevent->xcrossing.window,
xevent->xcrossing.detail,
xevent->xcrossing.subwindow));
-
+
+ if (window_private == NULL)
+ {
+ return_val = FALSE;
+ break;
+ }
+
/* Handle focusing (in the case where no window manager is running */
if (window &&
GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD &&
xevent->xcrossing.detail != NotifyInferior &&
- xevent->xcrossing.focus && !window_impl->has_focus)
+ xevent->xcrossing.focus && !window_impl->has_focus_window)
{
gboolean had_focus = HAS_FOCUS (window_impl);
-
+
window_impl->has_pointer_focus = TRUE;
if (HAS_FOCUS (window_impl) != had_focus)
* 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;
event->crossing.x_root = xevent->xcrossing.x_root;
event->crossing.y_root = xevent->xcrossing.y_root;
+ set_screen_from_root (display, event, xevent->xcrossing.root);
+
/* Translate the crossing mode into Gdk terms.
*/
switch (xevent->xcrossing.mode)
g_message ("leave notify:\t\twindow: %ld detail: %d subwin: %ld",
xevent->xcrossing.window,
xevent->xcrossing.detail, xevent->xcrossing.subwindow));
+
+ if (window_private == NULL)
+ {
+ return_val = FALSE;
+ break;
+ }
/* Handle focusing (in the case where no window manager is running */
if (window &&
GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD &&
xevent->xcrossing.detail != NotifyInferior &&
- xevent->xcrossing.focus && !window_impl->has_focus)
+ xevent->xcrossing.focus && !window_impl->has_focus_window)
{
gboolean had_focus = HAS_FOCUS (window_impl);
window_impl->has_pointer_focus = FALSE;
-
+
if (HAS_FOCUS (window_impl) != had_focus)
generate_focus_event (window, FALSE);
}
* 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;
event->crossing.x_root = xevent->xcrossing.x_root;
event->crossing.y_root = xevent->xcrossing.y_root;
+ set_screen_from_root (display, event, xevent->xcrossing.root);
+
/* Translate the crossing mode into Gdk terms.
*/
switch (xevent->xcrossing.mode)
*/
case FocusIn:
GDK_NOTE (EVENTS,
- g_message ("focus in:\t\twindow: %ld", xevent->xfocus.window));
+ g_message ("focus in:\t\twindow: %ld, detail: %s, mode: %s",
+ xevent->xfocus.window,
+ notify_details[xevent->xfocus.detail],
+ notify_modes[xevent->xfocus.mode]));
if (window && GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD)
{
case NotifyNonlinear:
case NotifyVirtual:
case NotifyNonlinearVirtual:
- window_impl->has_focus = TRUE;
+ window_impl->has_focus_window = TRUE;
+ /* We pretend that the focus moves to the grab
+ * window, so we pay attention to NotifyGrab
+ * NotifyUngrab, and ignore NotifyWhileGrabbed
+ */
+ if (xevent->xfocus.mode != NotifyWhileGrabbed)
+ window_impl->has_focus = TRUE;
break;
case NotifyPointer:
- window_impl->has_pointer_focus = TRUE;
+ /* The X server sends NotifyPointer/NotifyGrab,
+ * but the pointer focus is ignored while a
+ * grab is in effect
+ */
+ if (xevent->xfocus.mode != NotifyGrab)
+ window_impl->has_pointer_focus = TRUE;
break;
case NotifyInferior:
case NotifyPointerRoot:
break;
case FocusOut:
GDK_NOTE (EVENTS,
- g_message ("focus out:\t\twindow: %ld", xevent->xfocus.window));
-
+ g_message ("focus out:\t\twindow: %ld, detail: %s, mode: %s",
+ xevent->xfocus.window,
+ notify_details[xevent->xfocus.detail],
+ notify_modes[xevent->xfocus.mode]));
+
if (window && GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD)
{
gboolean had_focus = HAS_FOCUS (window_impl);
case NotifyNonlinear:
case NotifyVirtual:
case NotifyNonlinearVirtual:
- window_impl->has_focus = FALSE;
+ window_impl->has_focus_window = FALSE;
+ if (xevent->xfocus.mode != NotifyWhileGrabbed)
+ window_impl->has_focus = FALSE;
break;
case NotifyPointer:
- window_impl->has_pointer_focus = FALSE;
+ if (xevent->xfocus.mode != NotifyUngrab)
+ window_impl->has_pointer_focus = FALSE;
break;
case NotifyInferior:
case NotifyPointerRoot:
xevent->xexpose.x, xevent->xexpose.y,
xevent->xexpose.width, xevent->xexpose.height,
event->any.send_event ? " (send)" : ""));
+
+ if (window_private == NULL)
+ {
+ return_val = FALSE;
+ break;
+ }
+
{
GdkRectangle expose_rect;
else
{
_gdk_window_process_expose (window, xevent->xexpose.serial, &expose_rect);
-
return_val = FALSE;
}
GDK_NOTE (EVENTS,
g_message ("graphics expose:\tdrawable: %ld",
xevent->xgraphicsexpose.drawable));
-
+
+ if (window_private == NULL)
+ {
+ return_val = FALSE;
+ break;
+ }
+
expose_rect.x = xevent->xgraphicsexpose.x + xoffset;
expose_rect.y = xevent->xgraphicsexpose.y + yoffset;
expose_rect.width = xevent->xgraphicsexpose.width;
case VisibilityNotify:
#ifdef G_ENABLE_DEBUG
- if (gdk_debug_flags & GDK_DEBUG_EVENTS)
+ if (_gdk_debug_flags & GDK_DEBUG_EVENTS)
switch (xevent->xvisibility.state)
{
case VisibilityFullyObscured:
}
#endif /* G_ENABLE_DEBUG */
+ if (window_private == NULL)
+ {
+ return_val = FALSE;
+ break;
+ }
+
event->visibility.type = GDK_VISIBILITY_NOTIFY;
event->visibility.window = window;
GDK_NOTE (EVENTS,
g_message ("destroy notify:\twindow: %ld",
xevent->xdestroywindow.window));
+
+ /* Ignore DestroyNotify from SubstructureNotifyMask */
+ if (xevent->xdestroywindow.window == xevent->xdestroywindow.event)
+ {
+ event->any.type = GDK_DESTROY;
+ event->any.window = window;
+
+ return_val = window_private && !GDK_WINDOW_DESTROYED (window);
+
+ if (window && GDK_WINDOW_XID (window) != screen_x11->xroot_window)
+ gdk_window_destroy_notify (window);
+ }
+ else
+ return_val = FALSE;
- event->any.type = GDK_DESTROY;
- event->any.window = window;
-
- return_val = window_private && !GDK_WINDOW_DESTROYED (window);
-
- if (window && GDK_WINDOW_XID (window) != GDK_ROOT_WINDOW())
- gdk_window_destroy_notify (window);
break;
case UnmapNotify:
* 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 (gdk_xgrab_window == window_private)
- gdk_xgrab_window = NULL;
+ 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);
+ }
break;
? " (discarding)"
: GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD
? " (discarding child)"
+ : xevent->xconfigure.event != xevent->xconfigure.window
+ ? " (discarding substructure)"
: ""));
+ if (window && GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT)
+ _gdk_x11_screen_size_changed (screen, xevent);
+
if (window &&
+ xevent->xconfigure.event == xevent->xconfigure.window &&
!GDK_WINDOW_DESTROYED (window) &&
(window_private->extension_events != 0))
_gdk_input_configure_event (&xevent->xconfigure, window);
- if (!window || GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
+ if (!window ||
+ xevent->xconfigure.event != xevent->xconfigure.window ||
+ GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD ||
+ GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT)
return_val = FALSE;
else
{
event->configure.width = xevent->xconfigure.width;
event->configure.height = xevent->xconfigure.height;
- if (!xevent->xconfigure.x &&
- !xevent->xconfigure.y &&
+ if (!xevent->xconfigure.send_event &&
!GDK_WINDOW_DESTROYED (window))
{
gint tx = 0;
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))
{
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;
case PropertyNotify:
GDK_NOTE (EVENTS,
- gchar *atom = gdk_atom_name (xevent->xproperty.atom);
g_message ("property notify:\twindow: %ld, atom(%ld): %s%s%s",
xevent->xproperty.window,
xevent->xproperty.atom,
- atom ? "\"" : "",
- atom ? atom : "unknown",
- atom ? "\"" : "");
- g_free (atom);
- );
-
- event->property.type = GDK_PROPERTY_NOTIFY;
- event->property.window = window;
- event->property.atom = xevent->xproperty.atom;
- event->property.time = xevent->xproperty.time;
- event->property.state = xevent->xproperty.state;
-
- if (wm_state_atom == 0)
- wm_state_atom = gdk_atom_intern ("_NET_WM_STATE", FALSE);
-
- if (wm_desktop_atom == 0)
- wm_desktop_atom = gdk_atom_intern ("_NET_WM_DESKTOP", FALSE);
-
- if (event->property.atom == wm_state_atom ||
- event->property.atom == wm_desktop_atom)
+ "\"",
+ gdk_x11_get_xatom_name_for_display (display, xevent->xproperty.atom),
+ "\""));
+
+ if (window_private == NULL)
+ {
+ return_val = FALSE;
+ break;
+ }
+
+ 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);
+ gdk_check_wm_state_changed (window);
}
+ if (window_private->event_mask & GDK_PROPERTY_CHANGE_MASK)
+ {
+ event->property.type = GDK_PROPERTY_NOTIFY;
+ event->property.window = window;
+ 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;
+ }
+ else
+ return_val = FALSE;
+
break;
case SelectionClear:
{
event->selection.type = GDK_SELECTION_CLEAR;
event->selection.window = window;
- event->selection.selection = xevent->xselectionclear.selection;
+ event->selection.selection = gdk_x11_xatom_to_atom_for_display (display, xevent->xselectionclear.selection);
event->selection.time = xevent->xselectionclear.time;
}
else
event->selection.type = GDK_SELECTION_REQUEST;
event->selection.window = window;
- event->selection.selection = xevent->xselectionrequest.selection;
- event->selection.target = xevent->xselectionrequest.target;
- event->selection.property = 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;
event->selection.type = GDK_SELECTION_NOTIFY;
event->selection.window = window;
- event->selection.selection = xevent->xselection.selection;
- event->selection.target = xevent->xselection.target;
- event->selection.property = 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;
{
GList *tmp_list;
GdkFilterReturn result = GDK_FILTER_CONTINUE;
+ 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;
- if (filter->type == xevent->xclient.message_type)
+ if (filter->type == message_type)
{
result = (*filter->function) (xevent, event, filter->data);
break;
break;
case GDK_FILTER_CONTINUE:
/* Send unknown ClientMessage's on to Gtk for it to use */
- event->client.type = GDK_CLIENT_EVENT;
- event->client.window = window;
- event->client.message_type = xevent->xclient.message_type;
- event->client.data_format = xevent->xclient.format;
- memcpy(&event->client.data, &xevent->xclient.data,
- sizeof(event->client.data));
- }
+ if (window_private == NULL)
+ {
+ return_val = FALSE;
+ }
+ else
+ {
+ event->client.type = GDK_CLIENT_EVENT;
+ event->client.window = window;
+ event->client.message_type = message_type;
+ event->client.data_format = xevent->xclient.format;
+ memcpy(&event->client.data, &xevent->xclient.data,
+ sizeof(event->client.data));
+ }
+ break;
+ }
}
break;
/* Let XLib know that there is a new keyboard mapping.
*/
XRefreshKeyboardMapping (&xevent->xmapping);
- ++_gdk_keymap_serial;
+ _gdk_keymap_keys_changed (display);
return_val = FALSE;
break;
-#ifdef HAVE_XKB
- case XkbMapNotify:
- ++_gdk_keymap_serial;
- return_val = FALSE;
- break;
-#endif
-
default:
- /* something else - (e.g., a Xinput event) */
-
- if (window_private &&
- !GDK_WINDOW_DESTROYED (window_private) &&
- (window_private->extension_events != 0))
- return_val = _gdk_input_other_event(event, xevent, window);
+#ifdef HAVE_XKB
+ if (xevent->type == display_x11->xkb_event_type)
+ {
+ XkbEvent *xkb_event = (XkbEvent *)xevent;
+
+ switch (xkb_event->any.xkb_type)
+ {
+ case XkbMapNotify:
+ _gdk_keymap_keys_changed (display);
+
+ return_val = FALSE;
+ break;
+
+ case XkbStateNotify:
+ _gdk_keymap_state_changed (display);
+ break;
+ }
+ }
else
- return_val = FALSE;
-
- break;
+#endif
+ {
+ /* something else - (e.g., a Xinput event) */
+
+ if (window_private &&
+ !GDK_WINDOW_DESTROYED (window_private) &&
+ (window_private->extension_events != 0))
+ return_val = _gdk_input_other_event(event, xevent, window);
+ else
+ return_val = FALSE;
+
+ break;
+ }
}
done:
if (return_val)
{
if (event->any.window)
- gdk_window_ref (event->any.window);
+ g_object_ref (event->any.window);
if (((event->any.type == GDK_ENTER_NOTIFY) ||
(event->any.type == GDK_LEAVE_NOTIFY)) &&
(event->crossing.subwindow != NULL))
- gdk_window_ref (event->crossing.subwindow);
+ g_object_ref (event->crossing.subwindow);
}
else
{
}
if (window)
- gdk_window_unref (window);
+ g_object_unref (window);
return return_val;
}
-GdkFilterReturn
+static GdkFilterReturn
gdk_wm_protocols_filter (GdkXEvent *xev,
GdkEvent *event,
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_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
return GDK_FILTER_TRANSLATE;
}
- else if ((Atom) xevent->xclient.data.l[0] == gdk_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;
XSync (GDK_WINDOW_XDISPLAY (win), False);
gdk_error_trap_pop ();
}
- else if ((Atom) xevent->xclient.data.l[0] == gdk_atom_intern ("_NET_WM_PING", FALSE))
+ 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)
{
continue;
}
- event = gdk_event_new ();
+ event = gdk_event_new (GDK_NOTHING);
- event->any.type = GDK_NOTHING;
event->any.window = NULL;
event->any.send_event = xevent.xany.send_event ? TRUE : FALSE;
((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);
}
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;
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)
{
- if (gdk_event_func)
- (*gdk_event_func) (event, gdk_event_data);
+ if (_gdk_event_func)
+ (*_gdk_event_func) (event, _gdk_event_data);
gdk_event_free (event);
}
return TRUE;
}
-/* Sends a ClientMessage to all toplevel client windows */
+/**
+ * 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.
+ * @winid: the 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.
+ *
+ * Since: 2.2
+ */
gboolean
-gdk_event_send_client_message (GdkEvent *event, guint32 xid)
+gdk_event_send_client_message_for_display (GdkDisplay *display,
+ GdkEvent *event,
+ GdkNativeWindow winid)
{
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 = event->client.message_type;
+ sev.xclient.window = winid;
+ 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, winid, 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 GdkAtom wm_state_atom = GDK_NONE;
Atom type = None;
int format;
unsigned long nitems, after;
unsigned char *data;
Window *ret_children, ret_root, ret_parent;
unsigned int ret_nchildren;
- gint old_warnings = gdk_error_warnings;
gboolean send = FALSE;
gboolean found = FALSE;
+ gboolean result = FALSE;
int i;
-
- if (!wm_state_atom)
- wm_state_atom = gdk_atom_intern ("WM_STATE", FALSE);
-
- gdk_error_warnings = FALSE;
- gdk_error_code = 0;
- XGetWindowProperty (gdk_display, xid, wm_state_atom, 0, 0, False, AnyPropertyType,
- &type, &format, &nitems, &after, &data);
-
- if (gdk_error_code)
- {
- gdk_error_warnings = old_warnings;
-
- return FALSE;
- }
-
+
+ gdk_error_trap_push ();
+
+ 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;
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) != True ||
- gdk_error_code)
- {
- gdk_error_warnings = old_warnings;
-
- return FALSE;
- }
+ 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);
if (send || (!found && (level == 1)))
{
xev->xclient.window = xid;
- gdk_send_xevent (xid, False, NoEventMask, xev);
+ _gdk_send_xevent (display, xid, False, NoEventMask, xev);
}
- gdk_error_warnings = old_warnings;
+ result = send || found;
- return (send || found);
+ out:
+ gdk_error_trap_pop ();
+
+ return result;
}
+/**
+ * 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.
+ *
+ * Since: 2.2
+ */
+
void
-gdk_event_send_clientmessage_toall (GdkEvent *event)
+gdk_screen_broadcast_client_message (GdkScreen *screen,
+ GdkEvent *event)
{
XEvent sev;
- gint old_warnings = gdk_error_warnings;
+ 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 = event->client.message_type;
-
- gdk_event_send_client_message_to_all_recurse(&sev, gdk_root_window, 0);
-
- gdk_error_warnings = old_warnings;
+ 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);
}
/*
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 GdkAtom 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;
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_atom_intern ("GDK_TIMESTAMP_PROP", FALSE);
-
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,
return xevent.xproperty.time;
}
-
-gboolean
-gdk_net_wm_supports (GdkAtom property)
+static void
+fetch_net_wm_check_window (GdkScreen *screen)
{
- static GdkAtom wmspec_check_atom = 0;
- static GdkAtom wmspec_supported_atom = 0;
- static GdkAtom *atoms = NULL;
- static gulong n_atoms = 0;
+ GdkScreenX11 *screen_x11;
+ GdkDisplay *display;
Atom type;
gint format;
- gulong nitems;
+ gulong n_items;
gulong bytes_after;
Window *xwindow;
- gulong i;
-
- if (wmspec_check_window != None)
- {
- if (atoms == NULL)
- return FALSE;
-
- i = 0;
- while (i < n_atoms)
- {
- if (atoms[i] == property)
- return TRUE;
-
- ++i;
- }
-
- return FALSE;
- }
-
- if (atoms)
- XFree (atoms);
-
- atoms = NULL;
- 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
* _NET_SUPPORTING_WM_CHECK only once every 10 seconds or something.
*/
- if (wmspec_check_atom == 0)
- wmspec_check_atom = gdk_atom_intern ("_NET_SUPPORTING_WM_CHECK", FALSE);
-
- if (wmspec_supported_atom == 0)
- wmspec_supported_atom = gdk_atom_intern ("_NET_SUPPORTED", FALSE);
+ screen_x11 = GDK_SCREEN_X11 (screen);
+ display = screen_x11->display;
+
+ if (screen_x11->wmspec_check_window != None)
+ return; /* already have it */
+
+ 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,
+ &n_items, &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;
+ return;
gdk_error_trap_push ();
-
+
/* Find out if this WM goes away, so we can reset everything. */
- XSelectInput (gdk_display, *xwindow,
- StructureNotifyMask);
+ XSelectInput (screen_x11->xdisplay, *xwindow, StructureNotifyMask);
+
+ screen_x11->wmspec_check_window = *xwindow;
+ XFree (xwindow);
+
+ screen_x11->need_refetch_net_supported = TRUE;
+ screen_x11->need_refetch_wm_name = TRUE;
- gdk_flush ();
+ /* Careful, reentrancy */
+ _gdk_x11_screen_window_manager_changed (GDK_SCREEN (screen_x11));
+}
+
+/**
+ * gdk_x11_screen_get_window_manager_name:
+ * @screen: a #GdkScreen
+ *
+ * Returns the name of the window manager for @screen.
+ *
+ * Return value: the name of the window manager screen @screen, or
+ * "unknown" if the window manager is unknown. The string is owned by GDK
+ * and should not be freed.
+ *
+ * Since: 2.2
+ **/
+const char*
+gdk_x11_screen_get_window_manager_name (GdkScreen *screen)
+{
+ GdkScreenX11 *screen_x11;
+
+ screen_x11 = GDK_SCREEN_X11 (screen);
- if (gdk_error_trap_pop ())
+ fetch_net_wm_check_window (screen);
+
+ if (screen_x11->need_refetch_wm_name)
{
- XFree (xwindow);
- return FALSE;
+ /* Get the name of the window manager */
+ screen_x11->need_refetch_wm_name = FALSE;
+
+ g_free (screen_x11->window_manager_name);
+ screen_x11->window_manager_name = g_strdup ("unknown");
+
+ if (screen_x11->wmspec_check_window != None)
+ {
+ Atom type;
+ gint format;
+ gulong n_items;
+ gulong bytes_after;
+ guchar *name;
+
+ name = NULL;
+
+ XGetWindowProperty (GDK_DISPLAY_XDISPLAY (screen_x11->display),
+ screen_x11->wmspec_check_window,
+ gdk_x11_get_xatom_by_name_for_display (screen_x11->display,
+ "_NET_WM_NAME"),
+ 0, G_MAXLONG, False,
+ gdk_x11_get_xatom_by_name_for_display (screen_x11->display,
+ "UTF8_STRING"),
+ &type, &format,
+ &n_items, &bytes_after,
+ (guchar **)&name);
+
+ gdk_display_sync (screen_x11->display);
+
+ gdk_error_trap_pop ();
+
+ if (name != NULL)
+ {
+ g_free (screen_x11->window_manager_name);
+ screen_x11->window_manager_name = g_strdup (name);
+ XFree (name);
+ }
+ }
}
+
+ return GDK_SCREEN_X11 (screen)->window_manager_name;
+}
- XGetWindowProperty (gdk_display, gdk_root_window,
- wmspec_supported_atom, 0, G_MAXLONG,
- False, XA_ATOM, &type, &format, &n_atoms,
- &bytes_after, (guchar **)&atoms);
+typedef struct _NetWmSupportedAtoms NetWmSupportedAtoms;
+
+struct _NetWmSupportedAtoms
+{
+ Atom *atoms;
+ gulong n_atoms;
+};
+
+/**
+ * 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
+ * Extended Window Manager Hints Specification. You can find this
+ * specification on
+ * <ulink url="http://www.freedesktop.org">http://www.freedesktop.org</ulink>.
+ *
+ * When using this function, keep in mind that the window manager
+ * can change over time; so you shouldn't use this function in
+ * a way that impacts persistent application state. A common bug
+ * is that your application can start up before the window manager
+ * does when the user logs in, and before the window manager starts
+ * gdk_x11_screen_supports_net_wm_hint() will return %FALSE for every property.
+ * You can monitor the window_manager_changed signal on #GdkScreen to detect
+ * a window manager change.
+ *
+ * Return value: %TRUE if the window manager supports @property
+ *
+ * Since: 2.2
+ **/
+gboolean
+gdk_x11_screen_supports_net_wm_hint (GdkScreen *screen,
+ GdkAtom property)
+{
+ 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;
+
+ supported_atoms = g_object_get_data (G_OBJECT (screen), "gdk-net-wm-supported-atoms");
+ if (!supported_atoms)
+ {
+ supported_atoms = g_new0 (NetWmSupportedAtoms, 1);
+ g_object_set_data (G_OBJECT (screen), "gdk-net-wm-supported-atoms", supported_atoms);
+ }
+
+ fetch_net_wm_check_window (screen);
+
+ if (screen_x11->wmspec_check_window == None)
+ return FALSE;
+
+ if (screen_x11->need_refetch_net_supported)
+ {
+ /* WM has changed since we last got the supported list,
+ * refetch it.
+ */
+ Atom type;
+ gint format;
+ gulong bytes_after;
+
+ screen_x11->need_refetch_net_supported = FALSE;
+
+ if (supported_atoms->atoms)
+ XFree (supported_atoms->atoms);
+
+ supported_atoms->atoms = NULL;
+ supported_atoms->n_atoms = 0;
+
+ 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;
+ }
- if (type != XA_ATOM)
+ if (supported_atoms->atoms == NULL)
return FALSE;
- wmspec_check_window = *xwindow;
- XFree (xwindow);
+ i = 0;
+ while (i < supported_atoms->n_atoms)
+ {
+ if (supported_atoms->atoms[i] == gdk_x11_atom_to_xatom_for_display (display, property))
+ return TRUE;
+
+ ++i;
+ }
- /* since wmspec_check_window != None this isn't infinite. ;-) */
- return gdk_net_wm_supports (property);
+ return FALSE;
+}
+
+/**
+ * gdk_net_wm_supports:
+ * @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_screen_get_default (), property);
}
static struct
const char *xsettings_name;
const char *gdk_name;
} settings_map[] = {
- { "Net/DoubleClickTime", "gtk-double-click-timeout" },
- { "Net/DragThreshold", "gtk-drag-threshold" },
+ { "Net/DoubleClickTime", "gtk-double-click-time" },
+ { "Net/DndDragThreshold", "gtk-dnd-drag-threshold" },
+ { "Gtk/CanChangeAccels", "gtk-can-change-accels" },
{ "Gtk/ColorPalette", "gtk-color-palette" },
+ { "Gtk/FontName", "gtk-font-name" },
+ { "Gtk/IconSizes", "gtk-icon-sizes" },
+ { "Gtk/KeyThemeName", "gtk-key-theme-name" },
{ "Gtk/ToolbarStyle", "gtk-toolbar-style" },
{ "Gtk/ToolbarIconSize", "gtk-toolbar-icon-size" },
+ { "Gtk/IMPreeditStyle", "gtk-im-preedit-style" },
+ { "Gtk/IMStatusStyle", "gtk-im-status-style" },
{ "Net/CursorBlink", "gtk-cursor-blink" },
- { "Net/CursorBlinkTime", "gtk-cursor-blink-time" }
+ { "Net/CursorBlinkTime", "gtk-cursor-blink-time" },
+ { "Net/ThemeName", "gtk-theme-name" }
};
static void
void *data)
{
GdkEvent new_event;
+ GdkScreen *screen = data;
+ GdkScreenX11 *screen_x11 = data;
int i;
+ if (screen_x11->xsettings_in_init)
+ return;
+
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;
for (i = 0; i < G_N_ELEMENTS (settings_map) ; i++)
if (strcmp (settings_map[i].xsettings_name, name) == 0)
{
- new_event.setting.name = g_strdup (settings_map[i].gdk_name);
+ new_event.setting.name = (char *)settings_map[i].gdk_name;
break;
}
+
if (!new_event.setting.name)
return;
return TRUE;
}
+/**
+ * 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.
+ *
+ * Since: 2.2
+ **/
gboolean
-gdk_setting_get (const gchar *name,
- GValue *value)
+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)
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;
return success;
}
-GdkFilterReturn
+static GdkFilterReturn
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_for_display (gdk_screen_get_display (screen), window);
- gdkwin = gdk_window_lookup (window);
if (is_start)
- gdk_window_add_filter (gdkwin, gdk_xsettings_client_event_filter, NULL);
+ {
+ if (!gdkwin)
+ gdkwin = gdk_window_foreign_new_for_display (gdk_screen_get_display (screen), window);
+ else
+ g_object_ref (gdkwin);
+
+ gdk_window_add_filter (gdkwin, gdk_xsettings_client_event_filter, screen);
+ }
else
- gdk_window_remove_filter (gdkwin, gdk_xsettings_client_event_filter, NULL);
+ {
+ g_assert (gdkwin);
+ gdk_window_remove_filter (gdkwin, gdk_xsettings_client_event_filter, screen);
+ g_object_unref (gdkwin);
+ }
}