[gtk+/events-refactor: 1081/1085] Remove gdk/x11/gdkevents-x11.c
- From: Carlos Garnacho <carlosg src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gtk+/events-refactor: 1081/1085] Remove gdk/x11/gdkevents-x11.c
- Date: Tue, 29 Sep 2009 10:49:22 +0000 (UTC)
commit 48c9d7c722bfc6892a256cb179530a0ac67a7fa4
Author: Carlos Garnacho <carlos gnome org>
Date: Thu Sep 24 19:28:18 2009 +0200
Remove gdk/x11/gdkevents-x11.c
All remaining relevant code has been moved to wherever it made most sense.
gdk/gdk.symbols | 66 +-
gdk/x11/Makefile.am | 1 -
gdk/x11/gdkdisplay-x11.c | 216 ++++-
gdk/x11/gdkevents-x11.c | 3147 ----------------------------------------------
gdk/x11/gdkeventsource.c | 37 +
gdk/x11/gdkmain-x11.c | 11 +
gdk/x11/gdkprivate-x11.h | 3 +-
gdk/x11/gdkscreen-x11.c | 656 ++++++++++-
gdk/x11/gdkwindow-x11.c | 55 +
9 files changed, 996 insertions(+), 3196 deletions(-)
---
diff --git a/gdk/gdk.symbols b/gdk/gdk.symbols
index af37d02..0755427 100644
--- a/gdk/gdk.symbols
+++ b/gdk/gdk.symbols
@@ -19,16 +19,6 @@
#define IN_HEADER(x) 1
#endif
-#if IN_HEADER(__GDK_EVENTS_H__)
-#if IN_FILE(__GDK_EVENTS_X11_C__)
-gdk_add_client_message_filter
-#ifndef GDK_DISABLE_DEPRECATED
-gdk_event_get_graphics_expose
-#endif
-gdk_events_pending
-#endif
-#endif
-
#if IN_HEADER(__GDK_TEST_UTILS_H__)
#if IN_FILE(__GDK_TEST_UTILS_X11_C__)
gdk_test_simulate_button
@@ -61,6 +51,19 @@ gdk_setting_get
#endif
#endif
+#if IN_HEADER(__GDK_EVENTS_H__)
+#if IN_FILE(__GDK_DISPLAY_X11_C__)
+gdk_add_client_message_filter
+gdk_event_get_graphics_expose
+#endif
+#endif
+
+#if IN_HEADER(__GDK_EVENTS_H__)
+#if IN_FILE(__GDK_EVENT_SOURCE_C__)
+gdk_events_pending
+#endif
+#endif
+
#if IN_HEADER(__GDK_H__)
#if IN_FILE(__GDK_MAIN_X11_C__)
gdk_error_trap_pop
@@ -103,15 +106,10 @@ gdk_set_locale
#endif
#if IN_HEADER(__GDK_H__)
-#if IN_FILE(__GDK_EVENTS_X11_C__)
-gdk_event_send_client_message_for_display
-gdk_flush
-#endif
-#endif
-
-#if IN_HEADER(__GDK_H__)
#if IN_FILE(__GDK_DISPLAY_X11_C__)
gdk_display_list_devices
+gdk_event_send_client_message_for_display
+gdk_flush
gdk_notify_startup_complete
gdk_notify_startup_complete_with_id
#endif
@@ -406,12 +404,6 @@ gdk_input_set_extension_events
#endif
#if IN_HEADER(__GDK_DISPLAY_H__)
-#if IN_FILE(__GDK_EVENTS_X11_C__)
-gdk_display_add_client_message_filter
-#endif
-#endif
-
-#if IN_HEADER(__GDK_DISPLAY_H__)
#if IN_FILE(__GDK_DISPLAY_C__)
gdk_display_close
gdk_display_get_event
@@ -447,6 +439,7 @@ gdk_display_supports_cursor_color
#if IN_HEADER(__GDK_DISPLAY_H__)
#if IN_FILE(__GDK_DISPLAY_X11_C__)
+gdk_display_add_client_message_filter
gdk_display_beep
gdk_display_sync
gdk_display_flush
@@ -880,12 +873,6 @@ gdk_visual_get_type G_GNUC_CONST
#endif
#endif
-#if IN_HEADER(__GDK_X_H__)
-#if IN_FILE(__GDK_EVENTS_X11_C__)
-gdk_net_wm_supports
-#endif
-#endif
-
#if IN_HEADER(__GDK_PANGO_H__)
#if IN_FILE(__GDK_PANGO_C__)
gdk_pango_attr_emboss_color_new
@@ -1033,13 +1020,6 @@ gdk_screen_get_rgb_visual
#endif
#if IN_HEADER(__GDK_SCREEN_H__)
-#if IN_FILE(__GDK_EVENTS_X11_C__)
-gdk_screen_get_setting
-gdk_screen_broadcast_client_message
-#endif
-#endif
-
-#if IN_HEADER(__GDK_SCREEN_H__)
#if IN_FILE(__GDK_VISUAL_X11_C__)
gdk_screen_get_system_visual
gdk_screen_list_visuals
@@ -1054,6 +1034,7 @@ gdk_screen_get_toplevel_windows
#if IN_HEADER(__GDK_SCREEN_H__)
#if IN_FILE(__GDK_SCREEN_X11_C__)
+gdk_screen_broadcast_client_message
gdk_screen_get_display
gdk_screen_get_width
gdk_screen_get_width_mm
@@ -1061,6 +1042,7 @@ gdk_screen_get_height
gdk_screen_get_height_mm
gdk_screen_get_number
gdk_screen_get_root_window
+gdk_screen_get_setting
gdk_screen_get_default_colormap
gdk_screen_set_default_colormap
gdk_screen_get_n_monitors
@@ -1203,6 +1185,7 @@ gdk_x11_display_ungrab
gdk_x11_lookup_xdisplay
gdk_x11_display_broadcast_startup_message
gdk_x11_display_get_startup_notification_id
+gdk_x11_register_standard_event_type
#endif
#if IN_FILE(__GDK_DRAWABLE_X11_C__)
@@ -1233,22 +1216,18 @@ gdk_x11_grab_server
gdk_x11_ungrab_server
#endif
-#if IN_FILE(__GDK_EVENTS_X11_C__)
-gdk_x11_get_server_time
-gdk_x11_register_standard_event_type
-gdk_x11_screen_get_window_manager_name
-gdk_x11_screen_supports_net_wm_hint
-#endif
-
#if IN_FILE(__GDK_IMAGE_X11_C__)
gdk_x11_image_get_xdisplay
gdk_x11_image_get_ximage
#endif
#if IN_FILE(__GDK_SCREEN_X11_C__)
+gdk_net_wm_supports
gdk_x11_screen_get_screen_number
+gdk_x11_screen_get_window_manager_name
gdk_x11_screen_get_xscreen
gdk_x11_screen_get_monitor_output
+gdk_x11_screen_supports_net_wm_hint
#endif
#if IN_FILE(__GDK_VISUAL_X11_C__)
@@ -1258,6 +1237,7 @@ gdkx_visual_get
#endif
#if IN_FILE(__GDK_WINDOW_X11_C__)
+gdk_x11_get_server_time
gdk_x11_window_set_user_time
gdk_x11_window_move_to_current_desktop
#endif
diff --git a/gdk/x11/Makefile.am b/gdk/x11/Makefile.am
index 4913b8a..b6f7771 100644
--- a/gdk/x11/Makefile.am
+++ b/gdk/x11/Makefile.am
@@ -29,7 +29,6 @@ libgdk_x11_la_SOURCES = \
gdkdnd-x11.c \
gdkdrawable-x11.c \
gdkdrawable-x11.h \
- gdkevents-x11.c \
gdkeventsource.c \
gdkeventsource.h \
gdkeventtranslator.c \
diff --git a/gdk/x11/gdkdisplay-x11.c b/gdk/x11/gdkdisplay-x11.c
index 7b3ab52..be1e4e8 100644
--- a/gdk/x11/gdkdisplay-x11.c
+++ b/gdk/x11/gdkdisplay-x11.c
@@ -85,6 +85,14 @@ static void gdk_internal_connection_watch (Display *display,
XPointer *watch_data);
#endif /* HAVE_X11R6 */
+typedef struct _GdkEventTypeX11 GdkEventTypeX11;
+
+struct _GdkEventTypeX11
+{
+ gint base;
+ gint n_events;
+};
+
/* Note that we never *directly* use WM_LOCALE_NAME, WM_PROTOCOLS,
* but including them here has the side-effect of getting them
* into the internal Xlib cache
@@ -1196,8 +1204,8 @@ gdk_display_open (const gchar *display_name)
* structures in places
*/
for (i = 0; i < ScreenCount (display_x11->xdisplay); i++)
- _gdk_x11_events_init_screen (display_x11->screens[i]);
-
+ _gdk_screen_x11_events_init (display_x11->screens[i]);
+
/*set the default screen */
display_x11->default_screen = display_x11->screens[DefaultScreen (display_x11->xdisplay)];
@@ -2492,5 +2500,209 @@ gdk_display_list_devices (GdkDisplay *display)
return GDK_DISPLAY_X11 (display)->input_devices;
}
+/**
+ * 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 client message to.
+ *
+ * On X11, sends an X ClientMessage event to a given window. On
+ * Windows, sends a message registered with the name
+ * GDK_WIN32_CLIENT_MESSAGE.
+ *
+ * This could be used for communicating between different
+ * applications, though the amount of data is limited to 20 bytes on
+ * X11, and to just four bytes on Windows.
+ *
+ * Returns: non-zero on success.
+ *
+ * Since: 2.2
+ */
+gboolean
+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_XDISPLAY (display);
+ sev.xclient.format = event->client.data_format;
+ 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 (display, winid, False, NoEventMask, &sev);
+}
+
+/**
+ * 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.
+ * See gdk_window_add_filter() if you are interested in filtering other
+ * types of events.
+ *
+ * Since: 2.2
+ **/
+void
+gdk_display_add_client_message_filter (GdkDisplay *display,
+ GdkAtom message_type,
+ GdkFilterFunc func,
+ gpointer data)
+{
+ 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;
+
+ GDK_DISPLAY_X11(display)->client_filters =
+ g_list_append (GDK_DISPLAY_X11 (display)->client_filters,
+ filter);
+}
+
+/**
+ * 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);
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_flush
+ *
+ * Flushes the Xlib output buffer and then waits
+ * until all requests have been received and processed
+ * by the X server. The only real use for this function
+ * is in dealing with XShm.
+ *
+ * Arguments:
+ *
+ * Results:
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+void
+gdk_flush (void)
+{
+ GSList *tmp_list = _gdk_displays;
+
+ while (tmp_list)
+ {
+ XSync (GDK_DISPLAY_XDISPLAY (tmp_list->data), False);
+ tmp_list = tmp_list->next;
+ }
+}
+
+/**
+ * gdk_x11_register_standard_event_type:
+ * @display: a #GdkDisplay
+ * @event_base: first event type code to register
+ * @n_events: number of event type codes to register
+ *
+ * Registers interest in receiving extension events with type codes
+ * between @event_base and <literal>event_base + n_events - 1</literal>.
+ * The registered events must have the window field in the same place
+ * as core X events (this is not the case for e.g. XKB extension events).
+ *
+ * If an event type is registered, events of this type will go through
+ * global and window-specific filters (see gdk_window_add_filter()).
+ * Unregistered events will only go through global filters.
+ * GDK may register the events of some X extensions on its own.
+ *
+ * This function should only be needed in unusual circumstances, e.g.
+ * when filtering XInput extension events on the root window.
+ *
+ * Since: 2.4
+ **/
+void
+gdk_x11_register_standard_event_type (GdkDisplay *display,
+ gint event_base,
+ gint n_events)
+{
+ GdkEventTypeX11 *event_type;
+ GdkDisplayX11 *display_x11;
+
+ display_x11 = GDK_DISPLAY_X11 (display);
+ event_type = g_new (GdkEventTypeX11, 1);
+
+ event_type->base = event_base;
+ event_type->n_events = n_events;
+
+ display_x11->event_types = g_slist_prepend (display_x11->event_types, event_type);
+}
+
+static Bool
+graphics_expose_predicate (Display *display,
+ XEvent *xevent,
+ XPointer arg)
+{
+ if (xevent->xany.window == GDK_DRAWABLE_XID ((GdkDrawable *)arg) &&
+ (xevent->xany.type == GraphicsExpose ||
+ xevent->xany.type == NoExpose))
+ return True;
+ else
+ 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.
+ *
+ * Deprecated:2.18
+ **/
+GdkEvent*
+gdk_event_get_graphics_expose (GdkWindow *window)
+{
+ GdkDisplay *display;
+ XEvent xevent;
+
+ g_return_val_if_fail (window != NULL, NULL);
+
+ display = gdk_drawable_get_display (GDK_DRAWABLE (window));
+
+ XIfEvent (GDK_WINDOW_XDISPLAY (window), &xevent,
+ graphics_expose_predicate, (XPointer) window);
+
+ if (xevent.xany.type == GraphicsExpose)
+ return gdk_event_translator_translate (GDK_EVENT_TRANSLATOR (display),
+ display, &xevent);
+ return NULL;
+}
+
#define __GDK_DISPLAY_X11_C__
#include "gdkaliasdef.c"
diff --git a/gdk/x11/gdkeventsource.c b/gdk/x11/gdkeventsource.c
index c37ca34..2002152 100644
--- a/gdk/x11/gdkeventsource.c
+++ b/gdk/x11/gdkeventsource.c
@@ -20,6 +20,7 @@
#include "gdkeventsource.h"
#include "gdkinternals.h"
#include "gdkx.h"
+#include "gdkalias.h"
static gboolean gdk_event_source_prepare (GSource *source,
gint *timeout);
@@ -332,3 +333,39 @@ gdk_event_source_select_events (GdkEventSource *source,
XSelectInput (GDK_DISPLAY_XDISPLAY (source->display), window, xmask);
}
+
+/**
+ * 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)
+{
+ GList *tmp_list;
+
+ for (tmp_list = event_sources; tmp_list; tmp_list = tmp_list->next)
+ {
+ GdkEventSource *tmp_source = tmp_list->data;
+ GdkDisplay *display = tmp_source->display;
+
+ if (_gdk_event_queue_find_first (display))
+ return TRUE;
+ }
+
+ for (tmp_list = event_sources; tmp_list; tmp_list = tmp_list->next)
+ {
+ GdkEventSource *tmp_source = tmp_list->data;
+ GdkDisplay *display = tmp_source->display;
+
+ if (gdk_check_xpending (display))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+#define __GDK_EVENT_SOURCE_C__
+#include "gdkaliasdef.c"
diff --git a/gdk/x11/gdkmain-x11.c b/gdk/x11/gdkmain-x11.c
index b42dc4b..9b9721f 100644
--- a/gdk/x11/gdkmain-x11.c
+++ b/gdk/x11/gdkmain-x11.c
@@ -737,5 +737,16 @@ gdk_x11_get_default_xdisplay (void)
return GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
}
+void
+_gdk_windowing_event_data_copy (const GdkEvent *src,
+ GdkEvent *dst)
+{
+}
+
+void
+_gdk_windowing_event_data_free (GdkEvent *event)
+{
+}
+
#define __GDK_MAIN_X11_C__
#include "gdkaliasdef.c"
diff --git a/gdk/x11/gdkprivate-x11.h b/gdk/x11/gdkprivate-x11.h
index b925d19..72d2d74 100644
--- a/gdk/x11/gdkprivate-x11.h
+++ b/gdk/x11/gdkprivate-x11.h
@@ -173,8 +173,7 @@ void _gdk_x11_precache_atoms (GdkDisplay *display,
const gchar * const *atom_names,
gint n_atoms);
-void _gdk_x11_events_init_screen (GdkScreen *screen);
-void _gdk_x11_events_uninit_screen (GdkScreen *screen);
+void _gdk_screen_x11_events_init (GdkScreen *screen);
void _gdk_events_init (GdkDisplay *display);
void _gdk_events_uninit (GdkDisplay *display);
diff --git a/gdk/x11/gdkscreen-x11.c b/gdk/x11/gdkscreen-x11.c
index 1faa827..850fb59 100644
--- a/gdk/x11/gdkscreen-x11.c
+++ b/gdk/x11/gdkscreen-x11.c
@@ -51,6 +51,8 @@
#include <X11/extensions/Xfixes.h>
#endif
+#include "gdksettings.c"
+
static void gdk_screen_x11_dispose (GObject *object);
static void gdk_screen_x11_finalize (GObject *object);
static void init_randr_support (GdkScreen *screen);
@@ -66,6 +68,14 @@ static guint signals[LAST_SIGNAL] = { 0 };
G_DEFINE_TYPE (GdkScreenX11, _gdk_screen_x11, GDK_TYPE_SCREEN)
+typedef struct _NetWmSupportedAtoms NetWmSupportedAtoms;
+
+struct _NetWmSupportedAtoms
+{
+ Atom *atoms;
+ gulong n_atoms;
+};
+
struct _GdkX11Monitor
{
GdkRectangle geometry;
@@ -273,11 +283,23 @@ gdk_screen_set_default_colormap (GdkScreen *screen,
}
static void
+_gdk_screen_x11_events_uninit (GdkScreen *screen)
+{
+ GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
+
+ if (screen_x11->xsettings_client)
+ {
+ xsettings_client_destroy (screen_x11->xsettings_client);
+ screen_x11->xsettings_client = NULL;
+ }
+}
+
+static void
gdk_screen_x11_dispose (GObject *object)
{
GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (object);
- _gdk_x11_events_uninit_screen (GDK_SCREEN (object));
+ _gdk_screen_x11_events_uninit (GDK_SCREEN (object));
if (screen_x11->default_colormap)
{
@@ -1360,5 +1382,637 @@ gdk_screen_get_window_stack (GdkScreen *screen)
return ret;
}
+/* Sends a ClientMessage to all toplevel client windows */
+static gboolean
+gdk_event_send_client_message_to_all_recurse (GdkDisplay *display,
+ XEvent *xev,
+ guint32 xid,
+ guint level)
+{
+ Atom type = None;
+ int format;
+ unsigned long nitems, after;
+ unsigned char *data;
+ Window *ret_children, ret_root, ret_parent;
+ unsigned int ret_nchildren;
+ gboolean send = FALSE;
+ gboolean found = FALSE;
+ gboolean result = FALSE;
+ int i;
+
+ gdk_error_trap_push ();
+
+ if (XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), xid,
+ gdk_x11_get_xatom_by_name_for_display (display, "WM_STATE"),
+ 0, 0, False, AnyPropertyType,
+ &type, &format, &nitems, &after, &data) != Success)
+ goto out;
+
+ if (type)
+ {
+ send = TRUE;
+ XFree (data);
+ }
+ else
+ {
+ /* OK, we're all set, now let's find some windows to send this to */
+ 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 (display, xev, ret_children[i], level + 1))
+ found = TRUE;
+
+ XFree (ret_children);
+ }
+
+ if (send || (!found && (level == 1)))
+ {
+ xev->xclient.window = xid;
+ _gdk_send_xevent (display, xid, False, NoEventMask, xev);
+ }
+
+ result = 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.
+ *
+ * On X11, 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.
+ *
+ * On Windows, broadcasts a message registered with the name
+ * GDK_WIN32_CLIENT_MESSAGE to all top-level windows. The amount of
+ * data is limited to one long, i.e. four bytes.
+ *
+ * Since: 2.2
+ */
+
+void
+gdk_screen_broadcast_client_message (GdkScreen *screen,
+ GdkEvent *event)
+{
+ XEvent sev;
+ GdkWindow *root_window;
+
+ 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_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_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);
+}
+
+static gboolean
+check_transform (const gchar *xsettings_name,
+ GType src_type,
+ GType dest_type)
+{
+ if (!g_value_type_transformable (src_type, dest_type))
+ {
+ g_warning ("Cannot transform xsetting %s of type %s to type %s\n",
+ xsettings_name,
+ g_type_name (src_type),
+ g_type_name (dest_type));
+ return FALSE;
+ }
+ else
+ 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_screen_get_setting (GdkScreen *screen,
+ const gchar *name,
+ GValue *value)
+{
+
+ const char *xsettings_name = NULL;
+ XSettingsResult result;
+ XSettingsSetting *setting = NULL;
+ 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 < GDK_SETTINGS_N_ELEMENTS(); i++)
+ if (strcmp (GDK_SETTINGS_GDK_NAME (i), name) == 0)
+ {
+ xsettings_name = GDK_SETTINGS_X_NAME (i);
+ break;
+ }
+
+ if (!xsettings_name)
+ goto out;
+
+ result = xsettings_client_get_setting (screen_x11->xsettings_client,
+ xsettings_name, &setting);
+ if (result != XSETTINGS_SUCCESS)
+ goto out;
+
+ switch (setting->type)
+ {
+ case XSETTINGS_TYPE_INT:
+ if (check_transform (xsettings_name, G_TYPE_INT, G_VALUE_TYPE (value)))
+ {
+ g_value_init (&tmp_val, G_TYPE_INT);
+ g_value_set_int (&tmp_val, setting->data.v_int);
+ g_value_transform (&tmp_val, value);
+
+ success = TRUE;
+ }
+ break;
+ case XSETTINGS_TYPE_STRING:
+ if (check_transform (xsettings_name, G_TYPE_STRING, G_VALUE_TYPE (value)))
+ {
+ g_value_init (&tmp_val, G_TYPE_STRING);
+ g_value_set_string (&tmp_val, setting->data.v_string);
+ g_value_transform (&tmp_val, value);
+
+ success = TRUE;
+ }
+ break;
+ case XSETTINGS_TYPE_COLOR:
+ if (!check_transform (xsettings_name, GDK_TYPE_COLOR, G_VALUE_TYPE (value)))
+ {
+ GdkColor color;
+
+ g_value_init (&tmp_val, GDK_TYPE_COLOR);
+
+ color.pixel = 0;
+ color.red = setting->data.v_color.red;
+ color.green = setting->data.v_color.green;
+ color.blue = setting->data.v_color.blue;
+
+ g_value_set_boxed (&tmp_val, &color);
+
+ g_value_transform (&tmp_val, value);
+
+ success = TRUE;
+ }
+ break;
+ }
+
+ g_value_unset (&tmp_val);
+
+ out:
+ if (setting)
+ xsettings_setting_free (setting);
+
+ if (success)
+ return TRUE;
+ else
+ return _gdk_x11_get_xft_setting (screen, name, value);
+}
+
+static void
+cleanup_atoms(gpointer data)
+{
+ NetWmSupportedAtoms *supported_atoms = data;
+ if (supported_atoms->atoms)
+ XFree (supported_atoms->atoms);
+ g_free (supported_atoms);
+}
+
+static void
+fetch_net_wm_check_window (GdkScreen *screen)
+{
+ GdkScreenX11 *screen_x11;
+ GdkDisplay *display;
+ Atom type;
+ gint format;
+ gulong n_items;
+ gulong bytes_after;
+ guchar *data;
+ Window *xwindow;
+ GTimeVal tv;
+ gint error;
+
+ screen_x11 = GDK_SCREEN_X11 (screen);
+ display = screen_x11->display;
+
+ g_return_if_fail (GDK_DISPLAY_X11 (display)->trusted_client);
+
+ g_get_current_time (&tv);
+
+ if (ABS (tv.tv_sec - screen_x11->last_wmspec_check_time) < 15)
+ return; /* we've checked recently */
+
+ screen_x11->last_wmspec_check_time = tv.tv_sec;
+
+ data = NULL;
+ XGetWindowProperty (screen_x11->xdisplay, 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, &data);
+
+ if (type != XA_WINDOW)
+ {
+ if (data)
+ XFree (data);
+ return;
+ }
+
+ xwindow = (Window *)data;
+
+ if (screen_x11->wmspec_check_window == *xwindow)
+ {
+ XFree (xwindow);
+ return;
+ }
+
+ gdk_error_trap_push ();
+
+ /* Find out if this WM goes away, so we can reset everything. */
+ XSelectInput (screen_x11->xdisplay, *xwindow, StructureNotifyMask);
+ gdk_display_sync (display);
+
+ error = gdk_error_trap_pop ();
+ if (!error)
+ {
+ screen_x11->wmspec_check_window = *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));
+ }
+ else if (error == BadWindow)
+ {
+ /* Leftover property, try again immediately, new wm may be starting up */
+ screen_x11->last_wmspec_check_time = 0;
+ }
+
+ XFree (xwindow);
+}
+
+/**
+ * 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;
+
+ if (!G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client))
+ 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_full (G_OBJECT (screen), "gdk-net-wm-supported-atoms", supported_atoms, cleanup_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 (supported_atoms->atoms == NULL)
+ return FALSE;
+
+ 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;
+ }
+
+ 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 void
+refcounted_grab_server (Display *xdisplay)
+{
+ GdkDisplay *display = gdk_x11_lookup_xdisplay (xdisplay);
+
+ gdk_x11_display_grab (display);
+}
+
+static void
+refcounted_ungrab_server (Display *xdisplay)
+{
+ GdkDisplay *display = gdk_x11_lookup_xdisplay (xdisplay);
+
+ gdk_x11_display_ungrab (display);
+}
+
+static GdkFilterReturn
+gdk_xsettings_client_event_filter (GdkXEvent *xevent,
+ GdkEvent *event,
+ gpointer data)
+{
+ GdkScreenX11 *screen = data;
+
+ if (xsettings_client_process_event (screen->xsettings_client, (XEvent *)xevent))
+ return GDK_FILTER_REMOVE;
+ else
+ return GDK_FILTER_CONTINUE;
+}
+
+static Bool
+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);
+
+ if (is_start)
+ {
+ if (gdkwin)
+ g_object_ref (gdkwin);
+ else
+ {
+ gdkwin = gdk_window_foreign_new_for_display (gdk_screen_get_display (screen), window);
+
+ /* gdk_window_foreign_new_for_display() can fail and return NULL if the
+ * window has already been destroyed.
+ */
+ if (!gdkwin)
+ return False;
+ }
+
+ gdk_window_add_filter (gdkwin, gdk_xsettings_client_event_filter, screen);
+ }
+ else
+ {
+ if (!gdkwin)
+ {
+ /* gdkwin should not be NULL here, since if starting the watch succeeded
+ * we have a reference on the window. It might mean that the caller didn't
+ * remove the watch when it got a DestroyNotify event. Or maybe the
+ * caller ignored the return value when starting the watch failed.
+ */
+ g_warning ("gdk_xsettings_watch_cb(): Couldn't find window to unwatch");
+ return False;
+ }
+
+ gdk_window_remove_filter (gdkwin, gdk_xsettings_client_event_filter, screen);
+ g_object_unref (gdkwin);
+ }
+
+ return True;
+}
+
+static void
+gdk_xsettings_notify_cb (const char *name,
+ XSettingsAction action,
+ XSettingsSetting *setting,
+ 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 = gdk_screen_get_root_window (screen);
+ new_event.setting.send_event = FALSE;
+ new_event.setting.name = NULL;
+
+ for (i = 0; i < GDK_SETTINGS_N_ELEMENTS() ; i++)
+ if (strcmp (GDK_SETTINGS_X_NAME (i), name) == 0)
+ {
+ new_event.setting.name = (char*) GDK_SETTINGS_GDK_NAME (i);
+ break;
+ }
+
+ if (!new_event.setting.name)
+ return;
+
+ switch (action)
+ {
+ case XSETTINGS_ACTION_NEW:
+ new_event.setting.action = GDK_SETTING_ACTION_NEW;
+ break;
+ case XSETTINGS_ACTION_CHANGED:
+ new_event.setting.action = GDK_SETTING_ACTION_CHANGED;
+ break;
+ case XSETTINGS_ACTION_DELETED:
+ new_event.setting.action = GDK_SETTING_ACTION_DELETED;
+ break;
+ }
+
+ gdk_event_put (&new_event);
+}
+
+void
+_gdk_screen_x11_events_init (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_with_grab_funcs (screen_x11->xdisplay,
+ screen_x11->screen_num,
+ gdk_xsettings_notify_cb,
+ gdk_xsettings_watch_cb,
+ screen,
+ refcounted_grab_server,
+ refcounted_ungrab_server);
+ screen_x11->xsettings_in_init = FALSE;
+}
+
+/**
+ * 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 (!G_LIKELY (GDK_DISPLAY_X11 (screen_x11->display)->trusted_client))
+ return screen_x11->window_manager_name;
+
+ 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;
+ gchar *name;
+
+ name = NULL;
+
+ gdk_error_trap_push ();
+
+ 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;
+}
+
#define __GDK_SCREEN_X11_C__
#include "gdkaliasdef.c"
diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c
index 06347cc..4cf2c68 100644
--- a/gdk/x11/gdkwindow-x11.c
+++ b/gdk/x11/gdkwindow-x11.c
@@ -5608,5 +5608,60 @@ gdk_window_impl_iface_init (GdkWindowImplIface *iface)
#endif
}
+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 == gdk_x11_get_xatom_by_name_for_display (gdk_display,
+ "GDK_TIMESTAMP_PROP"))
+ return True;
+
+ return False;
+}
+
+/**
+ * gdk_x11_get_server_time:
+ * @window: a #GdkWindow, used for communication with the server.
+ * The window must have GDK_PROPERTY_CHANGE_MASK in its
+ * events mask or a hang will result.
+ *
+ * Routine to get the current X server time stamp.
+ *
+ * Return value: the time stamp.
+ **/
+guint32
+gdk_x11_get_server_time (GdkWindow *window)
+{
+ Display *xdisplay;
+ 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);
+
+ 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,
+ 8, PropModeReplace, &c, 1);
+
+ XIfEvent (xdisplay, &xevent,
+ timestamp_predicate, GUINT_TO_POINTER(xwindow));
+
+ return xevent.xproperty.time;
+}
+
#define __GDK_WINDOW_X11_C__
#include "gdkaliasdef.c"
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]