[gtk+/events-refactor: 1081/1085] Remove gdk/x11/gdkevents-x11.c



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]