[clutter] Adds a way for Cogl to control event_mask of foreign wins



commit 4d3bf09e60af216774d5b1ec118f420ee0b7137b
Author: Robert Bragg <robert linux intel com>
Date:   Wed May 4 17:02:04 2011 +0100

    Adds a way for Cogl to control event_mask of foreign wins
    
    This extends cogl_onscreen_x11_set_foreign_xid to take a callback to a
    function that details the event mask the Cogl requires the application
    to select on foreign windows. This is required because Cogl, for
    example, needs to track size changes of a window and may also in the
    future want other notifications such as map/unmap.
    
    Most applications wont need to use the foreign xwindow apis, but those
    that do are required to pass a valid callback and update the event mask
    of their window according to Cogl's requirements.

 clutter/cogl/cogl/cogl-framebuffer-private.h |    2 +
 clutter/cogl/cogl/cogl-framebuffer.c         |   10 ++++-
 clutter/cogl/cogl/cogl-framebuffer.h         |   58 +++++++++++++++++++++++++-
 clutter/cogl/cogl/winsys/cogl-winsys-egl.c   |   11 ++++-
 clutter/cogl/cogl/winsys/cogl-winsys-glx.c   |   11 ++++-
 clutter/cogl/examples/x11-foreign.c          |   22 +++++++++-
 clutter/glx/clutter-stage-glx.c              |    9 +++-
 clutter/x11/clutter-stage-x11.c              |   29 ++++++++-----
 clutter/x11/clutter-stage-x11.h              |   17 ++++++++
 9 files changed, 151 insertions(+), 18 deletions(-)
---
diff --git a/clutter/cogl/cogl/cogl-framebuffer-private.h b/clutter/cogl/cogl/cogl-framebuffer-private.h
index 278cd15..f48938f 100644
--- a/clutter/cogl/cogl/cogl-framebuffer-private.h
+++ b/clutter/cogl/cogl/cogl-framebuffer-private.h
@@ -118,6 +118,8 @@ struct _CoglOnscreen
 
 #ifdef COGL_HAS_X11_SUPPORT
   guint32 foreign_xid;
+  CoglOnscreenX11MaskCallback foreign_update_mask_callback;
+  void *foreign_update_mask_data;
 #endif
 
   gboolean swap_throttled;
diff --git a/clutter/cogl/cogl/cogl-framebuffer.c b/clutter/cogl/cogl/cogl-framebuffer.c
index 071b9ec..daf817a 100644
--- a/clutter/cogl/cogl/cogl-framebuffer.c
+++ b/clutter/cogl/cogl/cogl-framebuffer.c
@@ -1624,9 +1624,17 @@ cogl_framebuffer_swap_region (CoglFramebuffer *framebuffer,
 #ifdef COGL_HAS_X11_SUPPORT
 void
 cogl_onscreen_x11_set_foreign_window_xid (CoglOnscreen *onscreen,
-                                          guint32 xid)
+                                          guint32 xid,
+                                          CoglOnscreenX11MaskCallback update,
+                                          void *user_data)
 {
+  /* We don't wan't applications to get away with being lazy here and not
+   * passing an update callback... */
+  g_return_if_fail (update);
+
   onscreen->foreign_xid = xid;
+  onscreen->foreign_update_mask_callback = update;
+  onscreen->foreign_update_mask_data = user_data;
 }
 
 guint32
diff --git a/clutter/cogl/cogl/cogl-framebuffer.h b/clutter/cogl/cogl/cogl-framebuffer.h
index 3f4ecb8..b685031 100644
--- a/clutter/cogl/cogl/cogl-framebuffer.h
+++ b/clutter/cogl/cogl/cogl-framebuffer.h
@@ -86,11 +86,67 @@ CoglOnscreen *
 cogl_onscreen_new (CoglContext *context, int width, int height);
 
 #ifdef COGL_HAS_X11
+typedef void (*CoglOnscreenX11MaskCallback) (CoglOnscreen *onscreen,
+                                             guint32 event_mask,
+                                             void *user_data);
+
+/**
+ * cogl_onscreen_x11_set_foreign_window_xid:
+ * @onscreen: The unallocated framebuffer to associated with an X
+ *            window.
+ * @xid: The XID of an existing X window
+ * @update: A callback that notifies of updates to what Cogl requires
+ *          to be in the core X protocol event mask.
+ *
+ * Ideally we would recommend that you let Cogl be responsible for
+ * creating any X window required to back an onscreen framebuffer but
+ * if you really need to target a window created manually this
+ * function can be called before @onscreen has been allocated to set a
+ * foreign XID for your existing X window.
+ *
+ * Since Cogl needs, for example, to track changes to the size of an X
+ * window it requires that certain events be selected for via the core
+ * X protocol. This requirement may also be changed asynchronously so
+ * you must pass in an @update callback to inform you of Cogl's
+ * required event mask.
+ *
+ * For example if you are using Xlib you could use this API roughly
+ * as follows:
+ * [{
+ * static void
+ * my_update_cogl_x11_event_mask (CoglOnscreen *onscreen,
+ *                                guint32 event_mask,
+ *                                void *user_data)
+ * {
+ *   XSetWindowAttributes attrs;
+ *   MyData *data = user_data;
+ *   attrs.event_mask = event_mask | data->my_event_mask;
+ *   XChangeWindowAttributes (data->xdpy,
+ *                            data->xwin,
+ *                            CWEventMask,
+ *                            &attrs);
+ * }
+ *
+ * {
+ *   *snip*
+ *   cogl_onscreen_x11_set_foreign_window_xid (onscreen,
+ *                                             data->xwin,
+ *                                             my_update_cogl_x11_event_mask,
+ *                                             data);
+ *   *snip*
+ * }
+ * }]
+ *
+ * Since: 2.0
+ * Stability: Unstable
+ */
 #define cogl_onscreen_x11_set_foreign_window_xid \
   cogl_onscreen_x11_set_foreign_window_xid_EXP
 void
 cogl_onscreen_x11_set_foreign_window_xid (CoglOnscreen *onscreen,
-                                          guint32 xid);
+                                          guint32 xid,
+                                          CoglOnscreenX11MaskCallback update,
+                                          void *user_data);
 
 #define cogl_onscreen_x11_get_window_xid cogl_onscreen_x11_get_window_xid_EXP
 guint32
diff --git a/clutter/cogl/cogl/winsys/cogl-winsys-egl.c b/clutter/cogl/cogl/winsys/cogl-winsys-egl.c
index 0ffd48b..22fd611 100644
--- a/clutter/cogl/cogl/winsys/cogl-winsys-egl.c
+++ b/clutter/cogl/cogl/winsys/cogl-winsys-egl.c
@@ -68,6 +68,8 @@
 
 #ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
 #include <X11/Xlib.h>
+
+#define COGL_ONSCREEN_X11_EVENT_MASK StructureNotifyMask
 #endif
 
 typedef struct _CoglRendererEGL
@@ -922,6 +924,11 @@ _cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
 
       _cogl_framebuffer_winsys_update_size (framebuffer,
                                             attr.width, attr.height);
+
+      /* Make sure the app selects for the events we require... */
+      onscreen->foreign_update_mask_callback (onscreen,
+                                              COGL_ONSCREEN_X11_EVENT_MASK,
+                                              onscreen->foreign_update_mask_data);
     }
   else
     {
@@ -957,7 +964,9 @@ _cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
                                         DefaultRootWindow (xlib_renderer->xdpy),
                                         xvisinfo->visual,
                                         AllocNone);
-      mask = CWBorderPixel | CWColormap;
+      attr.event_mask = COGL_ONSCREEN_X11_EVENT_MASK;
+
+      mask = CWBorderPixel | CWColormap | CWEventMask;
 
       xwin = XCreateWindow (xlib_renderer->xdpy,
                             DefaultRootWindow (xlib_renderer->xdpy),
diff --git a/clutter/cogl/cogl/winsys/cogl-winsys-glx.c b/clutter/cogl/cogl/winsys/cogl-winsys-glx.c
index 47a207f..5948dde 100644
--- a/clutter/cogl/cogl/winsys/cogl-winsys-glx.c
+++ b/clutter/cogl/cogl/winsys/cogl-winsys-glx.c
@@ -64,6 +64,8 @@ typedef CoglFuncPtr (*GLXGetProcAddressProc) (const GLubyte *procName);
 #include <errno.h>
 #endif
 
+#define COGL_ONSCREEN_X11_EVENT_MASK StructureNotifyMask
+
 typedef struct _CoglContextGLX
 {
   GLXDrawable current_drawable;
@@ -756,6 +758,11 @@ _cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
 
       _cogl_framebuffer_winsys_update_size (framebuffer,
                                             attr.width, attr.height);
+
+      /* Make sure the app selects for the events we require... */
+      onscreen->foreign_update_mask_callback (onscreen,
+                                              COGL_ONSCREEN_X11_EVENT_MASK,
+                                              onscreen->foreign_update_mask_data);
     }
   else
     {
@@ -792,7 +799,9 @@ _cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
                                         DefaultRootWindow (xlib_renderer->xdpy),
                                         xvisinfo->visual,
                                         AllocNone);
-      mask = CWBorderPixel | CWColormap;
+      xattr.event_mask = COGL_ONSCREEN_X11_EVENT_MASK;
+
+      mask = CWBorderPixel | CWColormap | CWEventMask;
 
       xwin = XCreateWindow (xlib_renderer->xdpy,
                             DefaultRootWindow (xlib_renderer->xdpy),
diff --git a/clutter/cogl/examples/x11-foreign.c b/clutter/cogl/examples/x11-foreign.c
index d82e838..7012562 100644
--- a/clutter/cogl/examples/x11-foreign.c
+++ b/clutter/cogl/examples/x11-foreign.c
@@ -5,6 +5,24 @@
 #include <X11/Xlib.h>
 #include <X11/Xutil.h>
 
+static void
+update_cogl_x11_event_mask (CoglOnscreen *onscreen,
+                            guint32 event_mask,
+                            void *user_data)
+{
+  XDisplay *xdpy = user_data;
+  XSetWindowAttributes attrs;
+  guint32 xwin;
+
+  attrs.event_mask = event_mask;
+  xwin = cogl_onscreen_x11_get_window_xid (onscreen);
+
+  XChangeWindowAttributes (xdpy,
+                           (Window)xwin,
+                           CWEventMask,
+                           &attrs);
+}
+
 int
 main (int argc, char **argv)
 {
@@ -110,7 +128,9 @@ main (int argc, char **argv)
 
   XFree (xvisinfo);
 
-  cogl_onscreen_x11_set_foreign_window_xid (onscreen, xwin);
+  cogl_onscreen_x11_set_foreign_window_xid (onscreen, xwin,
+                                            update_cogl_x11_event_mask,
+                                            xdpy);
 
   fb = COGL_FRAMEBUFFER (onscreen);
   /* Eventually there will be an implicit allocate on first use so this
diff --git a/clutter/glx/clutter-stage-glx.c b/clutter/glx/clutter-stage-glx.c
index 0c0ab01..8a7a414 100644
--- a/clutter/glx/clutter-stage-glx.c
+++ b/clutter/glx/clutter-stage-glx.c
@@ -121,8 +121,13 @@ clutter_stage_glx_realize (ClutterStageWindow *stage_window)
   stage_glx->onscreen = cogl_onscreen_new (backend->cogl_context,
                                            width, height);
   if (stage_x11->xwin != None)
-    cogl_onscreen_x11_set_foreign_window_xid (stage_glx->onscreen,
-                                              stage_x11->xwin);
+    {
+      cogl_onscreen_x11_set_foreign_window_xid (
+                                  stage_glx->onscreen,
+                                  stage_x11->xwin,
+                                  _clutter_stage_x11_update_foreign_event_mask,
+                                  stage_x11);
+    }
 
   clutter_vblank = _clutter_backend_glx_get_vblank ();
   if (clutter_vblank && strcmp (clutter_vblank, "none") == 0)
diff --git a/clutter/x11/clutter-stage-x11.c b/clutter/x11/clutter-stage-x11.c
index d0553b0..ab877b9 100644
--- a/clutter/x11/clutter-stage-x11.c
+++ b/clutter/x11/clutter-stage-x11.c
@@ -387,6 +387,23 @@ clutter_stage_x11_unrealize (ClutterStageWindow *stage_window)
     }
 }
 
+void
+_clutter_stage_x11_update_foreign_event_mask (CoglOnscreen *onscreen,
+                                              guint32 event_mask,
+                                              void *user_data)
+{
+  ClutterStageX11 *stage_x11 = user_data;
+  ClutterBackendX11 *backend_x11 = stage_x11->backend;
+  XSetWindowAttributes attrs;
+
+  attrs.event_mask = event_mask | CLUTTER_STAGE_X11_EVENT_MASK;
+
+  XChangeWindowAttributes (backend_x11->xdpy,
+                           stage_x11->xwin,
+                           CWEventMask,
+                           &attrs);
+}
+
 static gboolean
 clutter_stage_x11_realize (ClutterStageWindow *stage_window)
 {
@@ -412,17 +429,7 @@ clutter_stage_x11_realize (ClutterStageWindow *stage_window)
    * because key events are broken with that extension, and will
    * be fixed by XI2
    */
-  event_flags = StructureNotifyMask
-              | FocusChangeMask
-              | ExposureMask
-              | PropertyChangeMask
-              | EnterWindowMask
-              | LeaveWindowMask
-              | KeyPressMask
-              | KeyReleaseMask
-              | ButtonPressMask
-              | ButtonReleaseMask
-              | PointerMotionMask;
+  event_flags = CLUTTER_STAGE_X11_EVENT_MASK;
 
   /* we unconditionally select input events even with event retrieval
    * disabled because we need to guarantee that the Clutter internal
diff --git a/clutter/x11/clutter-stage-x11.h b/clutter/x11/clutter-stage-x11.h
index 71732f5..a070c58 100644
--- a/clutter/x11/clutter-stage-x11.h
+++ b/clutter/x11/clutter-stage-x11.h
@@ -78,8 +78,25 @@ struct _ClutterStageX11Class
   GObjectClass parent_class;
 };
 
+#define CLUTTER_STAGE_X11_EVENT_MASK \
+  StructureNotifyMask | \
+  FocusChangeMask | \
+  ExposureMask | \
+  PropertyChangeMask | \
+  EnterWindowMask | \
+  LeaveWindowMask | \
+  KeyPressMask | \
+  KeyReleaseMask | \
+  ButtonPressMask | \
+  ButtonReleaseMask | \
+  PointerMotionMask;
+
 GType _clutter_stage_x11_get_type (void) G_GNUC_CONST;
 
+void  _clutter_stage_x11_update_foreign_event_mask (CoglOnscreen *onscreen,
+                                                    guint32 event_mask,
+                                                    void *user_data);
+
 /* Private to subclasses */
 void            _clutter_stage_x11_set_user_time                (ClutterStageX11 *stage_x11,
                                                                  guint32          user_time);



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