#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);
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,
/* 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_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);
- 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,
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 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_display_get_default (),
+ message_type, func, data);
+}
static void
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;
+ 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_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;
+ 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_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;
-
+ 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;
window = NULL;
window_private = NULL;
event->any.window = NULL;
-
+
if (_gdk_default_filters)
{
/* Apply global filters */
return_val = FALSE;
}
- /* Find the GdkWindow that this event occurred in. */
+ /* 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;
-
+
+ /* 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)
+ {
+ screen = GDK_WINDOW_SCREEN (window);
+ screen_x11 = GDK_SCREEN_X11 (screen);
+ }
+
if (window != NULL)
{
/* Window may be a pixmap, so check its type.
if (GDK_IS_WINDOW (window))
{
window_impl = GDK_WINDOW_IMPL_X11 (window_private->impl);
-
- if (xevent->xany.window != GDK_WINDOW_XID (window))
+
+ /* 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)
{
- g_assert (xevent->xany.window == window_impl->focus_window);
-
switch (xevent->type)
{
case KeyPress:
case KeyRelease:
- xevent->xany.window = GDK_WINDOW_XID (window);
+ xwindow = GDK_WINDOW_XID (window);
+ xevent->xany.window = xwindow;
break;
default:
- return False;
+ return FALSE;
}
}
}
- g_object_ref (G_OBJECT (window));
+ g_object_ref (window);
}
event->any.window = window;
goto done;
}
}
- else if (window_private)
+ else if (filter_window)
{
/* Apply per-window filters */
+ GdkWindowObject *filter_private = (GdkWindowObject *) filter_window;
GdkFilterReturn result;
- result = gdk_event_apply_filters (xevent, event,
- window_private->filters);
-
- if (result != GDK_FILTER_CONTINUE)
+
+ if (filter_private->filters)
{
- return_val = (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
- goto done;
+ 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)
+ {
+ return_val = (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
+ goto done;
+ }
}
}
- if (wmspec_check_window != None &&
- xevent->xany.window == wmspec_check_window)
+ if (screen_x11 && screen_x11->wmspec_check_window != None &&
+ xwindow == screen_x11->wmspec_check_window)
{
if (xevent->type == DestroyNotify)
- wmspec_check_window = None;
+ {
+ 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 &&
- _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
xoffset = 0;
yoffset = 0;
}
-
+
switch (xevent->type)
{
case KeyPress:
return_val = FALSE;
break;
}
-
- /* 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;
-
+ translate_key_event (display, event, xevent);
break;
-
+
case KeyRelease:
if (window_private == NULL)
{
break;
}
- /* Lookup the string corresponding to the given keysym.
- */
-
/* 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;
-
- event->key.group = (xevent->xkey.state & KEYBOARD_GROUP_MASK) >> KEYBOARD_GROUP_SHIFT;
+ translate_key_event (display, event, xevent);
break;
case ButtonPress:
if (window_private == NULL ||
((window_private->extension_events != 0) &&
- _gdk_input_ignore_core))
+ 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;
}
if (window_private == NULL ||
((window_private->extension_events != 0) &&
- _gdk_input_ignore_core))
+ display_x11->input_ignore_core))
{
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;
if (window_private == NULL ||
((window_private->extension_events != 0) &&
- _gdk_input_ignore_core))
+ 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;
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)
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:
else
{
_gdk_window_process_expose (window, xevent->xexpose.serial, &expose_rect);
-
return_val = FALSE;
}
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:
* 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 ||
+ xevent->xconfigure.event != xevent->xconfigure.window ||
GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD ||
GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT)
return_val = FALSE;
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;
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)
{
- return_val = FALSE;
+ return_val = FALSE;
break;
}
- event->property.type = GDK_PROPERTY_NOTIFY;
- event->property.window = window;
- event->property.atom = gdk_x11_xatom_to_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_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);
+ 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 = 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
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;
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;
{
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;
/* 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;
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;
+ _gdk_keymap_keys_changed (display);
+
return_val = FALSE;
break;
case XkbStateNotify:
- _gdk_keymap_state_changed ();
+ _gdk_keymap_state_changed (display);
break;
}
}
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;
}
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
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;
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)
{
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)
{
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 = gdk_x11_atom_to_xatom (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 Atom wm_state_atom = None;
Atom type = None;
int format;
unsigned long nitems, after;
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;
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);
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;
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;
+ 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);
}
/*
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;
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,
return xevent.xproperty.time;
}
+static void
+fetch_net_wm_check_window (GdkScreen *screen)
+{
+ GdkScreenX11 *screen_x11;
+ GdkDisplay *display;
+ Atom type;
+ gint format;
+ gulong n_items;
+ gulong bytes_after;
+ Window *xwindow;
+
+ /* 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
+ * any critical code paths, but if you used it somewhere that had to
+ * be fast you want to avoid "GTK is slow with old WMs" complaints.
+ * Probably at that point the function should be changed to query
+ * _NET_SUPPORTING_WM_CHECK only once every 10 seconds or something.
+ */
+
+ 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);
+
+ if (type != XA_WINDOW)
+ return;
+
+ gdk_error_trap_push ();
+
+ /* Find out if this WM goes away, so we can reset everything. */
+ 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;
+
+ /* Careful, reentrancy */
+ _gdk_x11_screen_window_manager_changed (GDK_SCREEN (screen_x11));
+}
/**
- * gdk_net_wm_supports:
- * @property: a property atom
+ * 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);
+
+ fetch_net_wm_check_window (screen);
+
+ if (screen_x11->need_refetch_wm_name)
+ {
+ /* 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;
+}
+
+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 http://www.freedesktop.org.
+ * 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_net_wm_supports() will return %FALSE for every property.
+ * 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_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;
- if (wmspec_check_window != None)
- {
- if (atoms == NULL)
- return FALSE;
-
- i = 0;
- while (i < n_atoms)
- {
- if (atoms[i] == xproperty)
- return TRUE;
-
- ++i;
- }
+ g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
+
+ screen_x11 = GDK_SCREEN_X11 (screen);
+ display = screen_x11->display;
- return FALSE;
+ 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);
}
- if (atoms)
- XFree (atoms);
+ fetch_net_wm_check_window (screen);
- 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
- * any critical code paths, but if you used it somewhere that had to
- * be fast you want to avoid "GTK is slow with old WMs" complaints.
- * Probably at that point the function should be changed to query
- * _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, _gdk_root_window,
- wmspec_check_atom, 0, G_MAXLONG,
- False, XA_WINDOW, &type, &format, &nitems,
- &bytes_after, (guchar **)&xwindow);
-
- if (type != XA_WINDOW)
+ if (screen_x11->wmspec_check_window == None)
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 ();
- if (gdk_error_trap_pop ())
+ if (screen_x11->need_refetch_net_supported)
{
- XFree (xwindow);
- return FALSE;
- }
+ /* WM has changed since we last got the supported list,
+ * refetch it.
+ */
+ Atom type;
+ gint format;
+ gulong bytes_after;
- XGetWindowProperty (gdk_display, _gdk_root_window,
- wmspec_supported_atom, 0, G_MAXLONG,
- False, XA_ATOM, &type, &format, &n_atoms,
- &bytes_after, (guchar **)&atoms);
+ 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
{ "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/ThemeName", "gtk-theme-name" },
- { "Gtk/KeyThemeName", "gtk-key-theme-name" }
+ { "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;
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);
+ }
}