[cogl/cogl-1.16] win32: Automatically process windows messages when using a GMainLoop



commit 4543ed6ac3af2522beb3a4983bd3a3f7bd2c8c22
Author: Neil Roberts <neil linux intel com>
Date:   Tue May 14 15:43:04 2013 +0100

    win32: Automatically process windows messages when using a GMainLoop
    
    Previously the WGL winsys was expecting the application to send all
    windows messages to Cogl via the cogl_win32_renderer_handle_event
    function. When using a GLib main loop we can make this work
    transparently to the application with a GSource for the magic
    G_WIN32_MSG_HANDLE file descriptor. That causes the GMainLoop to wake
    up whenever a message is available.
    
    This patch makes the WGL winsys add that magic value as a source fd.
    This will only have any meaning if the application is using glib, but
    it shouldn't matter because the cogl_poll_renderer_get_info function
    is documented to only work on Unix-based winsys's anyway.
    
    This patch is an API break because by default Cogl will now start
    stealing all of the Windows messages. Something like Clutter that wants to handle
    its own event retrieval would now need to call
    cogl_win32_renderer_set_event_retrieval_enabled to stop Cogl from
    stealing the events.
    
    Reviewed-by: Robert Bragg <robert linux intel com>
    
    (cherry picked from commit 99a7f84d7149f24f3e86c5d3562f9f2632ff6df8)

 cogl/cogl-renderer-private.h                       |    4 ++
 cogl/cogl-renderer.c                               |    4 ++
 cogl/cogl-win32-renderer.c                         |   10 +++++
 cogl/cogl-win32-renderer.h                         |   19 +++++++++
 cogl/winsys/cogl-winsys-wgl.c                      |   42 ++++++++++++++++++++
 .../cogl-2.0-experimental-sections.txt             |    1 +
 6 files changed, 80 insertions(+), 0 deletions(-)
---
diff --git a/cogl/cogl-renderer-private.h b/cogl/cogl-renderer-private.h
index e71e8b9..62aca7e 100644
--- a/cogl/cogl-renderer-private.h
+++ b/cogl/cogl-renderer-private.h
@@ -65,6 +65,10 @@ struct _CoglRenderer
   CoglBool xlib_enable_event_retrieval;
 #endif
 
+#ifdef COGL_HAS_WIN32_SUPPORT
+  CoglBool win32_enable_event_retrieval;
+#endif
+
   CoglDriver driver;
 #ifndef HAVE_DIRECTLY_LINKED_GL_LIBRARY
   GModule *libgl_module;
diff --git a/cogl/cogl-renderer.c b/cogl/cogl-renderer.c
index bcdbd10..1e34714 100644
--- a/cogl/cogl-renderer.c
+++ b/cogl/cogl-renderer.c
@@ -193,6 +193,10 @@ cogl_renderer_new (void)
   renderer->xlib_enable_event_retrieval = TRUE;
 #endif
 
+#ifdef COGL_HAS_WIN32_SUPPORT
+  renderer->win32_enable_event_retrieval = TRUE;
+#endif
+
   return _cogl_renderer_object_new (renderer);
 }
 
diff --git a/cogl/cogl-win32-renderer.c b/cogl/cogl-win32-renderer.c
index ad7e791..89094cb 100644
--- a/cogl/cogl-win32-renderer.c
+++ b/cogl/cogl-win32-renderer.c
@@ -56,3 +56,13 @@ cogl_win32_renderer_remove_filter (CoglRenderer *renderer,
                                        (CoglNativeFilterFunc)func, data);
 }
 
+void
+cogl_win32_renderer_set_event_retrieval_enabled (CoglRenderer *renderer,
+                                                 CoglBool enable)
+{
+  _COGL_RETURN_IF_FAIL (cogl_is_renderer (renderer));
+  /* NB: Renderers are considered immutable once connected */
+  _COGL_RETURN_IF_FAIL (!renderer->connected);
+
+  renderer->win32_enable_event_retrieval = enable;
+}
diff --git a/cogl/cogl-win32-renderer.h b/cogl/cogl-win32-renderer.h
index e9747da..a144c74 100644
--- a/cogl/cogl-win32-renderer.h
+++ b/cogl/cogl-win32-renderer.h
@@ -94,6 +94,25 @@ cogl_win32_renderer_remove_filter (CoglRenderer *renderer,
                                    CoglWin32FilterFunc func,
                                    void *data);
 
+/**
+ * cogl_win32_renderer_set_event_retrieval_enabled:
+ * @renderer: a #CoglRenderer
+ * @enable: The new value
+ *
+ * Sets whether Cogl should automatically retrieve messages from
+ * Windows. It defaults to %TRUE. It can be set to %FALSE if the
+ * application wants to handle its own message retrieval. Note that
+ * Cogl still needs to see all of the messages to function properly so
+ * the application should call cogl_win32_renderer_handle_event() for
+ * each message if it disables automatic event retrieval.
+ *
+ * Since: 1.16
+ * Stability: unstable
+ */
+void
+cogl_win32_renderer_set_event_retrieval_enabled (CoglRenderer *renderer,
+                                                 CoglBool enable);
+
 COGL_END_DECLS
 
 #endif /* __COGL_WIN32_RENDERER_H__ */
diff --git a/cogl/winsys/cogl-winsys-wgl.c b/cogl/winsys/cogl-winsys-wgl.c
index ce2e97c..b0b1b9a 100644
--- a/cogl/winsys/cogl-winsys-wgl.c
+++ b/cogl/winsys/cogl-winsys-wgl.c
@@ -46,6 +46,11 @@
 #include "cogl-win32-renderer.h"
 #include "cogl-winsys-wgl-private.h"
 #include "cogl-error-private.h"
+#include "cogl-poll-private.h"
+
+/* This magic handle will cause g_poll to wakeup when there is a
+ * pending message */
+#define WIN32_MSG_HANDLE 19981206
 
 typedef struct _CoglRendererWgl
 {
@@ -161,6 +166,9 @@ _cogl_winsys_renderer_disconnect (CoglRenderer *renderer)
 {
   CoglRendererWgl *wgl_renderer = renderer->winsys;
 
+  if (renderer->win32_enable_event_retrieval)
+    _cogl_poll_renderer_remove_fd (renderer, WIN32_MSG_HANDLE);
+
   if (wgl_renderer->gl_module)
     g_module_close (wgl_renderer->gl_module);
 
@@ -232,11 +240,45 @@ win32_event_filter_cb (MSG *msg, void *data)
 }
 
 static CoglBool
+check_messages (void *user_data)
+{
+  MSG msg;
+
+  return PeekMessageW (&msg, NULL, 0, 0, PM_NOREMOVE) ? TRUE : FALSE;
+}
+
+static void
+dispatch_messages (void *user_data)
+{
+  MSG msg;
+
+  while (PeekMessageW (&msg, NULL, 0, 0, PM_REMOVE))
+    /* This should cause the message to be sent to our window proc */
+    DispatchMessageW (&msg);
+}
+
+static CoglBool
 _cogl_winsys_renderer_connect (CoglRenderer *renderer,
                                CoglError **error)
 {
   renderer->winsys = g_slice_new0 (CoglRendererWgl);
 
+  if (renderer->win32_enable_event_retrieval)
+    {
+      /* We'll add a magic handle that will cause a GLib main loop to
+       * wake up when there are messages. This will only work if the
+       * application is using GLib but it shouldn't matter if it
+       * doesn't work in other cases because the application shouldn't
+       * be using the cogl_poll_* functions on non-Unix systems
+       * anyway */
+      _cogl_poll_renderer_add_fd (renderer,
+                                  WIN32_MSG_HANDLE,
+                                  COGL_POLL_FD_EVENT_IN,
+                                  check_messages,
+                                  dispatch_messages,
+                                  renderer);
+    }
+
   return TRUE;
 }
 
diff --git a/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-sections.txt 
b/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-sections.txt
index 7a94695..e97ea21 100644
--- a/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-sections.txt
+++ b/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-sections.txt
@@ -85,6 +85,7 @@ CoglWin32FilterFunc
 cogl_win32_renderer_add_filter
 cogl_win32_renderer_remove_filter
 cogl_win32_renderer_handle_event
+cogl_win32_renderer_set_event_retrieval_enabled
 
 <SUBSECTION>
 cogl_wayland_renderer_set_foreign_display


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