[gtk+/events-refactor: 330/1085] Add GdkEventSource.



commit 0f527d48568a8e01a0b407cf955e36b3da188d30
Author: Carlos Garnacho <carlosg gnome org>
Date:   Wed Jun 10 21:48:37 2009 +0200

    Add GdkEventSource.
    
    This object is a GSource that generates GdkEvents from XEvents. Several
    GdkEventTranslators can be attached.
    
    This GSource is now hooked to GdkDisplayX11, and conflicting code in
    gdkevents-x11.c is ifdef'ed out.

 gdk/x11/Makefile.am      |    2 +
 gdk/x11/gdkdisplay-x11.c |   29 ++++++-
 gdk/x11/gdkevents-x11.c  |    4 +
 gdk/x11/gdkeventsource.c |  220 ++++++++++++++++++++++++++++++++++++++++++++++
 gdk/x11/gdkeventsource.h |   37 ++++++++
 5 files changed, 289 insertions(+), 3 deletions(-)
---
diff --git a/gdk/x11/Makefile.am b/gdk/x11/Makefile.am
index 60c2adc..93b18cf 100644
--- a/gdk/x11/Makefile.am
+++ b/gdk/x11/Makefile.am
@@ -30,6 +30,8 @@ libgdk_x11_la_SOURCES =    	\
 	gdkdrawable-x11.c  	\
 	gdkdrawable-x11.h	\
 	gdkevents-x11.c	   	\
+	gdkeventsource.c	\
+	gdkeventsource.h	\
 	gdkeventtranslator.c	\
 	gdkeventtranslator.h	\
 	gdkfont-x11.c	   	\
diff --git a/gdk/x11/gdkdisplay-x11.c b/gdk/x11/gdkdisplay-x11.c
index 98d8d3c..a1fa2a0 100644
--- a/gdk/x11/gdkdisplay-x11.c
+++ b/gdk/x11/gdkdisplay-x11.c
@@ -33,6 +33,7 @@
 #include "gdkx.h"
 #include "gdkdisplay.h"
 #include "gdkdisplay-x11.h"
+#include "gdkeventsource.h"
 #include "gdkeventtranslator.h"
 #include "gdkscreen.h"
 #include "gdkscreen-x11.h"
@@ -973,6 +974,23 @@ gdk_display_x11_translate_event (GdkEventTranslator *translator,
   return return_val;
 }
 
+static void
+_gdk_event_init (GdkDisplay *display)
+{
+  GdkDisplayX11 *display_x11;
+  GdkDeviceManager *device_manager;
+
+  display_x11 = GDK_DISPLAY_X11 (display);
+  display_x11->event_source = gdk_event_source_new (display);
+
+  gdk_event_source_add_translator (display_x11->event_source,
+                                   GDK_EVENT_TRANSLATOR (display));
+
+  device_manager = gdk_device_manager_get_for_display (display);
+  gdk_event_source_add_translator (display_x11->event_source,
+                                   GDK_EVENT_TRANSLATOR (device_manager));
+}
+
 /**
  * gdk_display_open:
  * @display_name: the name of the display to open
@@ -1232,9 +1250,9 @@ gdk_display_open (const gchar *display_name)
       display_x11->use_sync = TRUE;
   }
 #endif
-  
+
+  _gdk_event_init (display);
   _gdk_windowing_image_init (display);
-  _gdk_events_init (display);
   _gdk_input_init (display);
   _gdk_dnd_init (display);
 
@@ -1650,7 +1668,12 @@ gdk_display_x11_dispose (GObject *object)
   for (i = 0; i < ScreenCount (display_x11->xdisplay); i++)
     _gdk_screen_close (display_x11->screens[i]);
 
-  _gdk_events_uninit (GDK_DISPLAY_OBJECT (object));
+  if (display_x11->event_source)
+    {
+      g_source_destroy (display_x11->event_source);
+      g_source_unref (display_x11->event_source);
+      display_x11->event_source = NULL;
+    }
 
   G_OBJECT_CLASS (_gdk_display_x11_parent_class)->dispose (object);
 }
diff --git a/gdk/x11/gdkevents-x11.c b/gdk/x11/gdkevents-x11.c
index e0cc554..d600328 100644
--- a/gdk/x11/gdkevents-x11.c
+++ b/gdk/x11/gdkevents-x11.c
@@ -205,6 +205,7 @@ _gdk_x11_events_uninit_screen (GdkScreen *screen)
     }
 }
 
+#if 0
 void 
 _gdk_events_init (GdkDisplay *display)
 {
@@ -234,6 +235,7 @@ _gdk_events_init (GdkDisplay *display)
 					 gdk_wm_protocols_filter,   
 					 NULL);
 }
+#endif
 
 void
 _gdk_events_uninit (GdkDisplay *display)
@@ -2268,6 +2270,7 @@ gdk_wm_protocols_filter (GdkXEvent *xev,
   return GDK_FILTER_CONTINUE;
 }
 
+#if 0
 void
 _gdk_events_queue (GdkDisplay *display)
 {
@@ -2325,6 +2328,7 @@ _gdk_events_queue (GdkDisplay *display)
         }
     }
 }
+#endif
 
 static gboolean  
 gdk_event_prepare (GSource  *source,
diff --git a/gdk/x11/gdkeventsource.c b/gdk/x11/gdkeventsource.c
new file mode 100644
index 0000000..1a4e886
--- /dev/null
+++ b/gdk/x11/gdkeventsource.c
@@ -0,0 +1,220 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 2009 Carlos Garnacho <carlosg gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "gdkeventsource.h"
+#include "gdkinternals.h"
+#include "gdkx.h"
+
+static gboolean gdk_event_source_prepare  (GSource     *source,
+                                           gint        *timeout);
+static gboolean gdk_event_source_check    (GSource     *source);
+static gboolean gdk_event_source_dispatch (GSource     *source,
+                                           GSourceFunc  callback,
+                                           gpointer     user_data);
+static void     gdk_event_source_finalize (GSource     *source);
+
+struct _GdkEventSource
+{
+  GSource source;
+
+  GdkDisplay *display;
+  GPollFD event_poll_fd;
+  GList *translators;
+};
+
+static GSourceFuncs event_funcs = {
+  gdk_event_source_prepare,
+  gdk_event_source_check,
+  gdk_event_source_dispatch,
+  gdk_event_source_finalize
+};
+
+static GList *event_sources = NULL;
+
+
+static GdkEvent *
+gdk_event_source_translate_event (GdkEventSource *event_source,
+                                  XEvent         *xevent)
+{
+  GdkEvent *event = NULL;
+  GList *list = event_source->translators;
+
+  while (list && !event)
+    {
+      GdkEventTranslator *translator = list->data;
+
+      list = list->next;
+      event = gdk_event_translator_translate (translator,
+                                              event_source->display,
+                                              xevent);
+    }
+
+  return event;
+}
+
+static gboolean
+gdk_check_xpending (GdkDisplay *display)
+{
+  return XPending (GDK_DISPLAY_XDISPLAY (display));
+}
+
+static gboolean
+gdk_event_source_prepare (GSource *source,
+                          gint    *timeout)
+{
+  GdkDisplay *display = ((GdkEventSource*) source)->display;
+  gboolean retval;
+
+  GDK_THREADS_ENTER ();
+
+  *timeout = -1;
+  retval = (_gdk_event_queue_find_first (display) != NULL ||
+	    gdk_check_xpending (display));
+
+  GDK_THREADS_LEAVE ();
+
+  return retval;
+}
+
+static gboolean
+gdk_event_source_check (GSource *source)
+{
+  GdkEventSource *event_source = (GdkEventSource*) source;
+  gboolean retval;
+
+  GDK_THREADS_ENTER ();
+
+  if (event_source->event_poll_fd.revents & G_IO_IN)
+    retval = (_gdk_event_queue_find_first (event_source->display) != NULL ||
+	      gdk_check_xpending (event_source->display));
+  else
+    retval = FALSE;
+
+  GDK_THREADS_LEAVE ();
+
+  return retval;
+}
+
+void
+_gdk_events_queue (GdkDisplay *display)
+{
+  GdkEvent *event;
+  XEvent xevent;
+  Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
+  GdkEventSource *event_source;
+  GdkDisplayX11 *display_x11;
+
+  display_x11 = GDK_DISPLAY_X11 (display);
+  event_source = (GdkEventSource *) display_x11->event_source;
+
+  while (!_gdk_event_queue_find_first(display) && XPending (xdisplay))
+    {
+      XNextEvent (xdisplay, &xevent);
+
+      switch (xevent.type)
+	{
+	case KeyPress:
+	case KeyRelease:
+	  break;
+	default:
+	  if (XFilterEvent (&xevent, None))
+	    continue;
+	}
+
+      event = gdk_event_source_translate_event (event_source, &xevent);
+
+      if (event)
+        _gdk_event_queue_append (display, event);
+    }
+}
+
+static gboolean
+gdk_event_source_dispatch (GSource     *source,
+                           GSourceFunc  callback,
+                           gpointer     user_data)
+{
+  GdkDisplay *display = ((GdkEventSource*) source)->display;
+  GdkEvent *event;
+
+  GDK_THREADS_ENTER ();
+
+  event = gdk_display_get_event (display);
+
+  if (event)
+    {
+      if (_gdk_event_func)
+	(*_gdk_event_func) (event, _gdk_event_data);
+
+      gdk_event_free (event);
+    }
+
+  GDK_THREADS_LEAVE ();
+
+  return TRUE;
+}
+
+static void
+gdk_event_source_finalize (GSource *source)
+{
+  event_sources = g_list_remove (event_sources, source);
+}
+
+GSource *
+gdk_event_source_new (GdkDisplay *display)
+{
+  GSource *source;
+  GdkEventSource *event_source;
+  GdkDisplayX11 *display_x11;
+  int connection_number;
+
+  source = g_source_new (&event_funcs, sizeof (GdkEventSource));
+  event_source = (GdkEventSource *) source;
+  event_source->display = display;
+
+  display_x11 = GDK_DISPLAY_X11 (display);
+  connection_number = ConnectionNumber (display_x11->xdisplay);
+
+  event_source->event_poll_fd.fd = connection_number;
+  event_source->event_poll_fd.events = G_IO_IN;
+  g_source_add_poll (source, &event_source->event_poll_fd);
+
+  g_source_set_priority (source, GDK_PRIORITY_EVENTS);
+  g_source_set_can_recurse (source, TRUE);
+  g_source_attach (source, NULL);
+
+  event_sources = g_list_prepend (event_sources, source);
+
+#if 0
+  gdk_display_add_client_message_filter (display,
+					 gdk_atom_intern_static_string ("WM_PROTOCOLS"),
+					 gdk_wm_protocols_filter,
+					 NULL);
+#endif
+
+  return source;
+}
+
+void
+gdk_event_source_add_translator (GdkEventSource     *source,
+                                 GdkEventTranslator *translator)
+{
+  g_return_if_fail (GDK_IS_EVENT_TRANSLATOR (translator));
+
+  source->translators = g_list_prepend (source->translators, translator);
+}
diff --git a/gdk/x11/gdkeventsource.h b/gdk/x11/gdkeventsource.h
new file mode 100644
index 0000000..f433759
--- /dev/null
+++ b/gdk/x11/gdkeventsource.h
@@ -0,0 +1,37 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 2009 Carlos Garnacho <carlosg gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GDK_EVENT_SOURCE_H__
+#define __GDK_EVENT_SOURCE_H__
+
+#include "gdkeventtranslator.h"
+#include "gdkprivate-x11.h"
+
+G_BEGIN_DECLS
+
+typedef struct _GdkEventSource GdkEventSource;
+
+GSource * gdk_event_source_new            (GdkDisplay *display);
+
+void      gdk_event_source_add_translator (GdkEventSource     *source,
+                                           GdkEventTranslator *translator);
+
+G_END_DECLS
+
+#endif /* __GDK_EVENT_SOURCE_H__ */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]