Add a method to the XOverlay interface to allow disabling of event handling in x...
authorJulien Moutte <julien@moutte.net>
Thu, 4 Jan 2007 11:30:53 +0000 (11:30 +0000)
committerJulien Moutte <julien@moutte.net>
Thu, 4 Jan 2007 11:30:53 +0000 (11:30 +0000)
Original commit message from CVS:
2007-01-04  Julien MOUTTE  <julien@moutte.net>

* gst-libs/gst/interfaces/xoverlay.c:
(gst_x_overlay_handle_events):
* gst-libs/gst/interfaces/xoverlay.h:
* sys/ximage/ximagesink.c: (gst_ximagesink_xwindow_new),
(gst_ximagesink_set_xwindow_id),
(gst_ximagesink_set_event_handling),
(gst_ximagesink_xoverlay_init), (gst_ximagesink_set_property),
(gst_ximagesink_get_property), (gst_ximagesink_init),
(gst_ximagesink_class_init):
* sys/ximage/ximagesink.h:
* sys/xvimage/xvimagesink.c: (gst_xvimagesink_xwindow_new),
(gst_xvimagesink_set_xwindow_id),
(gst_xvimagesink_set_event_handling),
(gst_xvimagesink_xoverlay_init), (gst_xvimagesink_set_property),
(gst_xvimagesink_get_property), (gst_xvimagesink_init),
(gst_xvimagesink_class_init):
* sys/xvimage/xvimagesink.h:
* tests/icles/stress-xoverlay.c: (toggle_events),
(create_window):
Add a method to the XOverlay interface to allow disabling of
event handling in x[v]imagesink elements. This will let X events
propagate to parent windows which can be usefull in some cases.
Be carefull that the application is then responsible of pushing
navigation events and expose events to the video sink.
Fixes: #387138.
ChangeLog
gst-libs/gst/interfaces/xoverlay.c
gst-libs/gst/interfaces/xoverlay.h
sys/ximage/ximagesink.c
sys/ximage/ximagesink.h
sys/xvimage/xvimagesink.c
sys/xvimage/xvimagesink.h
tests/icles/stress-xoverlay.c

index fb75e481a083c43f1f99d2a81485bd0db6b0a634..656c01a1a387ce502f624a3fde8ed1a5e50fcc35 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,30 @@
+2007-01-04  Julien MOUTTE  <julien@moutte.net>
+
+       * gst-libs/gst/interfaces/xoverlay.c:
+       (gst_x_overlay_handle_events):
+       * gst-libs/gst/interfaces/xoverlay.h:
+       * sys/ximage/ximagesink.c: (gst_ximagesink_xwindow_new),
+       (gst_ximagesink_set_xwindow_id),
+       (gst_ximagesink_set_event_handling),
+       (gst_ximagesink_xoverlay_init), (gst_ximagesink_set_property),
+       (gst_ximagesink_get_property), (gst_ximagesink_init),
+       (gst_ximagesink_class_init):
+       * sys/ximage/ximagesink.h:
+       * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xwindow_new),
+       (gst_xvimagesink_set_xwindow_id),
+       (gst_xvimagesink_set_event_handling),
+       (gst_xvimagesink_xoverlay_init), (gst_xvimagesink_set_property),
+       (gst_xvimagesink_get_property), (gst_xvimagesink_init),
+       (gst_xvimagesink_class_init):
+       * sys/xvimage/xvimagesink.h:
+       * tests/icles/stress-xoverlay.c: (toggle_events), (create_window):
+       Add a method to the XOverlay interface to allow disabling of 
+       event handling in x[v]imagesink elements. This will let X events
+       propagate to parent windows which can be usefull in some cases.
+       Be carefull that the application is then responsible of pushing
+       navigation events and expose events to the video sink.
+       Fixes: #387138.
+
 2007-01-03  Tim-Philipp Müller  <tim at centricular dot net>
 
        * gst-libs/gst/tag/gstvorbistag.c:
index 0352fe70765574e7d8d8c9ea6f0646683b23ec5b..525529a264b52a26254ff5ab04823f190244e484 100644 (file)
@@ -239,3 +239,28 @@ gst_x_overlay_expose (GstXOverlay * overlay)
     klass->expose (overlay);
   }
 }
+
+/**
+ * gst_x_overlay_handle_events:
+ * @overlay: a #GstXOverlay to expose.
+ * @handle_events: a #gboolean indicating if events should be handled or not.
+ *
+ * Tell an overlay that it should handle events from the window system. These
+ * events are forwared upstream as navigation events. In some window system,
+ * events are not propagated in the window hierarchy if a client is listening
+ * for them. This method allows you to disable events handling completely
+ * from the XOverlay.
+ */
+void
+gst_x_overlay_handle_events (GstXOverlay * overlay, gboolean handle_events)
+{
+  GstXOverlayClass *klass;
+
+  g_return_if_fail (overlay != NULL);
+
+  klass = GST_X_OVERLAY_GET_CLASS (overlay);
+
+  if (klass->handle_events) {
+    klass->handle_events (overlay, handle_events);
+  }
+}
index f859a8f41bc6f9715c9ac69e999a87c6cf00e102..9301d3a7e0cf27593291c8a5b265a965bf990328 100644 (file)
@@ -51,9 +51,12 @@ typedef struct _GstXOverlayClass {
                            gulong       xwindow_id);
 
   void (* expose)         (GstXOverlay *overlay);
+  
+  void (* handle_events)  (GstXOverlay *overlay,
+                           gboolean     handle_events);  
 
   /*< private >*/
-  gpointer                 _gst_reserved[GST_PADDING];
+  gpointer                 _gst_reserved[GST_PADDING - 1];
 } GstXOverlayClass;
 
 GType   gst_x_overlay_get_type          (void);
@@ -63,6 +66,9 @@ void gst_x_overlay_set_xwindow_id     (GstXOverlay *overlay, gulong xwindow_id);
 
 void gst_x_overlay_expose             (GstXOverlay *overlay);
 
+void gst_x_overlay_handle_events      (GstXOverlay *overlay,
+                                       gboolean     handle_events);
+
 /* public methods to dispatch bus messages */
 void gst_x_overlay_got_xwindow_id     (GstXOverlay *overlay, gulong xwindow_id);
 
index 9644b7c6d19e76d3126a34833e4a3e5075de852a..7ca9d6c8aa5e2354804714650eda78a6f3193db5 100644 (file)
@@ -164,7 +164,8 @@ enum
   PROP_DISPLAY,
   PROP_SYNCHRONOUS,
   PROP_PIXEL_ASPECT_RATIO,
-  PROP_FORCE_ASPECT_RATIO
+  PROP_FORCE_ASPECT_RATIO,
+  PROP_HANDLE_EVENTS
       /* FILL ME */
 };
 
@@ -771,9 +772,11 @@ gst_ximagesink_xwindow_new (GstXImageSink * ximagesink, gint width, gint height)
      ConfigureNotify. This takes away flickering of video when resizing. */
   XSetWindowBackgroundPixmap (ximagesink->xcontext->disp, xwindow->win, None);
 
-  XSelectInput (ximagesink->xcontext->disp, xwindow->win, ExposureMask |
-      StructureNotifyMask | PointerMotionMask | KeyPressMask |
-      KeyReleaseMask | ButtonPressMask | ButtonReleaseMask);
+  if (ximagesink->handle_events) {
+    XSelectInput (ximagesink->xcontext->disp, xwindow->win, ExposureMask |
+        StructureNotifyMask | PointerMotionMask | KeyPressMask |
+        KeyReleaseMask | ButtonPressMask | ButtonReleaseMask);
+  }
 
   xwindow->gc = XCreateGC (ximagesink->xcontext->disp, xwindow->win,
       0, &values);
@@ -1817,9 +1820,11 @@ gst_ximagesink_set_xwindow_id (GstXOverlay * overlay, XID xwindow_id)
     xwindow->width = attr.width;
     xwindow->height = attr.height;
     xwindow->internal = FALSE;
-    XSelectInput (ximagesink->xcontext->disp, xwindow->win, ExposureMask |
-        StructureNotifyMask | PointerMotionMask | KeyPressMask |
-        KeyReleaseMask);
+    if (ximagesink->handle_events) {
+      XSelectInput (ximagesink->xcontext->disp, xwindow->win, ExposureMask |
+          StructureNotifyMask | PointerMotionMask | KeyPressMask |
+          KeyReleaseMask);
+    }
 
     xwindow->gc = XCreateGC (ximagesink->xcontext->disp, xwindow->win, 0, NULL);
     g_mutex_unlock (ximagesink->x_lock);
@@ -1842,11 +1847,42 @@ gst_ximagesink_expose (GstXOverlay * overlay)
   gst_ximagesink_ximage_put (ximagesink, NULL);
 }
 
+static void
+gst_ximagesink_set_event_handling (GstXOverlay * overlay,
+    gboolean handle_events)
+{
+  GstXImageSink *ximagesink = GST_XIMAGESINK (overlay);
+
+  ximagesink->handle_events = handle_events;
+
+  if (!ximagesink->xwindow)
+    return;
+
+  g_mutex_lock (ximagesink->x_lock);
+
+  if (handle_events) {
+    if (ximagesink->xwindow->internal) {
+      XSelectInput (ximagesink->xcontext->disp, ximagesink->xwindow->win,
+          ExposureMask | StructureNotifyMask | PointerMotionMask |
+          KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask);
+    } else {
+      XSelectInput (ximagesink->xcontext->disp, ximagesink->xwindow->win,
+          ExposureMask | StructureNotifyMask | PointerMotionMask |
+          KeyPressMask | KeyReleaseMask);
+    }
+  } else {
+    XSelectInput (ximagesink->xcontext->disp, ximagesink->xwindow->win, 0);
+  }
+
+  g_mutex_unlock (ximagesink->x_lock);
+}
+
 static void
 gst_ximagesink_xoverlay_init (GstXOverlayClass * iface)
 {
   iface->set_xwindow_id = gst_ximagesink_set_xwindow_id;
   iface->expose = gst_ximagesink_expose;
+  iface->handle_events = gst_ximagesink_set_event_handling;
 }
 
 /* =========================================== */
@@ -1902,6 +1938,10 @@ gst_ximagesink_set_property (GObject * object, guint prop_id,
       }
     }
       break;
+    case PROP_HANDLE_EVENTS:
+      gst_ximagesink_set_event_handling (GST_X_OVERLAY (ximagesink),
+          g_value_get_boolean (value));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -1932,6 +1972,9 @@ gst_ximagesink_get_property (GObject * object, guint prop_id,
       if (ximagesink->par)
         g_value_transform (ximagesink->par, value);
       break;
+    case PROP_HANDLE_EVENTS:
+      g_value_set_boolean (value, ximagesink->handle_events);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -1994,6 +2037,7 @@ gst_ximagesink_init (GstXImageSink * ximagesink)
 
   ximagesink->synchronous = FALSE;
   ximagesink->keep_aspect = FALSE;
+  ximagesink->handle_events = TRUE;
 }
 
 static void
@@ -2038,6 +2082,10 @@ gst_ximagesink_class_init (GstXImageSinkClass * klass)
   g_object_class_install_property (gobject_class, PROP_PIXEL_ASPECT_RATIO,
       g_param_spec_string ("pixel-aspect-ratio", "Pixel Aspect Ratio",
           "The pixel aspect ratio of the device", "1/1", G_PARAM_READWRITE));
+  g_object_class_install_property (gobject_class, PROP_HANDLE_EVENTS,
+      g_param_spec_boolean ("handle-events", "Handle XEvents",
+          "When enabled, XEvents will be selected and handled", TRUE,
+          G_PARAM_READWRITE));
 
   gstelement_class->change_state = gst_ximagesink_change_state;
 
index 5f10d8962abd7689cd727e8d3c1c9d243d2c378b..99c4f6fa09815a051f4fde0f7cfea60d1f8695c9 100644 (file)
@@ -179,6 +179,7 @@ struct _GstXImageBuffer {
  * debugging purpose only)
  * @keep_aspect: used to remember if reverse negotiation scaling should respect
  * aspect ratio
+ * @handle_events: used to know if we should handle select XEvents or not
  *
  * The #GstXImageSink data structure.
  */
@@ -211,6 +212,7 @@ struct _GstXImageSink {
 
   gboolean synchronous;
   gboolean keep_aspect;
+  gboolean handle_events;
 };
 
 struct _GstXImageSinkClass {
index 34eb74fbbb5abf8742ab16929438473fee3bc59e..01efd4b02f6f881a469cd8f2acf087804be5af32 100644 (file)
@@ -188,7 +188,8 @@ enum
   ARG_DISPLAY,
   ARG_SYNCHRONOUS,
   ARG_PIXEL_ASPECT_RATIO,
-  ARG_FORCE_ASPECT_RATIO
+  ARG_FORCE_ASPECT_RATIO,
+  ARG_HANDLE_EVENTS
       /* FILL ME */
 };
 
@@ -829,9 +830,11 @@ gst_xvimagesink_xwindow_new (GstXvImageSink * xvimagesink,
    * ConfigureNotify. This takes away flickering of video when resizing. */
   XSetWindowBackgroundPixmap (xvimagesink->xcontext->disp, xwindow->win, None);
 
-  XSelectInput (xvimagesink->xcontext->disp, xwindow->win, ExposureMask |
-      StructureNotifyMask | PointerMotionMask | KeyPressMask |
-      KeyReleaseMask | ButtonPressMask | ButtonReleaseMask);
+  if (xvimagesink->handle_events) {
+    XSelectInput (xvimagesink->xcontext->disp, xwindow->win, ExposureMask |
+        StructureNotifyMask | PointerMotionMask | KeyPressMask |
+        KeyReleaseMask | ButtonPressMask | ButtonReleaseMask);
+  }
 
   xwindow->gc = XCreateGC (xvimagesink->xcontext->disp,
       xwindow->win, 0, &values);
@@ -2374,9 +2377,11 @@ gst_xvimagesink_set_xwindow_id (GstXOverlay * overlay, XID xwindow_id)
     xwindow->width = attr.width;
     xwindow->height = attr.height;
     xwindow->internal = FALSE;
-    XSelectInput (xvimagesink->xcontext->disp, xwindow->win, ExposureMask |
-        StructureNotifyMask | PointerMotionMask | KeyPressMask |
-        KeyReleaseMask);
+    if (xvimagesink->handle_events) {
+      XSelectInput (xvimagesink->xcontext->disp, xwindow->win, ExposureMask |
+          StructureNotifyMask | PointerMotionMask | KeyPressMask |
+          KeyReleaseMask);
+    }
 
     xwindow->gc = XCreateGC (xvimagesink->xcontext->disp,
         xwindow->win, 0, NULL);
@@ -2400,11 +2405,42 @@ gst_xvimagesink_expose (GstXOverlay * overlay)
   gst_xvimagesink_xvimage_put (xvimagesink, NULL);
 }
 
+static void
+gst_xvimagesink_set_event_handling (GstXOverlay * overlay,
+    gboolean handle_events)
+{
+  GstXvImageSink *xvimagesink = GST_XVIMAGESINK (overlay);
+
+  xvimagesink->handle_events = handle_events;
+
+  if (!xvimagesink->xwindow)
+    return;
+
+  g_mutex_lock (xvimagesink->x_lock);
+
+  if (handle_events) {
+    if (xvimagesink->xwindow->internal) {
+      XSelectInput (xvimagesink->xcontext->disp, xvimagesink->xwindow->win,
+          ExposureMask | StructureNotifyMask | PointerMotionMask |
+          KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask);
+    } else {
+      XSelectInput (xvimagesink->xcontext->disp, xvimagesink->xwindow->win,
+          ExposureMask | StructureNotifyMask | PointerMotionMask |
+          KeyPressMask | KeyReleaseMask);
+    }
+  } else {
+    XSelectInput (xvimagesink->xcontext->disp, xvimagesink->xwindow->win, 0);
+  }
+
+  g_mutex_unlock (xvimagesink->x_lock);
+}
+
 static void
 gst_xvimagesink_xoverlay_init (GstXOverlayClass * iface)
 {
   iface->set_xwindow_id = gst_xvimagesink_set_xwindow_id;
   iface->expose = gst_xvimagesink_expose;
+  iface->handle_events = gst_xvimagesink_set_event_handling;
 }
 
 static const GList *
@@ -2552,6 +2588,10 @@ gst_xvimagesink_set_property (GObject * object, guint prop_id,
     case ARG_FORCE_ASPECT_RATIO:
       xvimagesink->keep_aspect = g_value_get_boolean (value);
       break;
+    case ARG_HANDLE_EVENTS:
+      gst_xvimagesink_set_event_handling (GST_X_OVERLAY (xvimagesink),
+          g_value_get_boolean (value));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -2594,6 +2634,9 @@ gst_xvimagesink_get_property (GObject * object, guint prop_id,
     case ARG_FORCE_ASPECT_RATIO:
       g_value_set_boolean (value, xvimagesink->keep_aspect);
       break;
+    case ARG_HANDLE_EVENTS:
+      g_value_set_boolean (value, xvimagesink->handle_events);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -2662,6 +2705,7 @@ gst_xvimagesink_init (GstXvImageSink * xvimagesink)
   xvimagesink->synchronous = FALSE;
   xvimagesink->running = FALSE;
   xvimagesink->keep_aspect = FALSE;
+  xvimagesink->handle_events = TRUE;
   xvimagesink->par = NULL;
 }
 
@@ -2719,6 +2763,10 @@ gst_xvimagesink_class_init (GstXvImageSinkClass * klass)
       g_param_spec_boolean ("force-aspect-ratio", "Force aspect ratio",
           "When enabled, scaling will respect original aspect ratio", FALSE,
           G_PARAM_READWRITE));
+  g_object_class_install_property (gobject_class, ARG_HANDLE_EVENTS,
+      g_param_spec_boolean ("handle-events", "Handle XEvents",
+          "When enabled, XEvents will be selected and handled", TRUE,
+          G_PARAM_READWRITE));
 
   gobject_class->finalize = gst_xvimagesink_finalize;
 
index e59e96108a9cdc00540410360e363b8a596da60d..6872dc5ba61cc751fb11ba34f20d307134a7f974 100644 (file)
@@ -209,6 +209,7 @@ struct _GstXvImageBuffer {
  * debugging purpose only)
  * @keep_aspect: used to remember if reverse negotiation scaling should respect
  * aspect ratio
+ * @handle_events: used to know if we should handle select XEvents or not
  * @brightness: used to store the user settings for color balance brightness
  * @contrast: used to store the user settings for color balance contrast
  * @hue: used to store the user settings for color balance hue
@@ -247,6 +248,7 @@ struct _GstXvImageSink {
   
   gboolean synchronous;
   gboolean keep_aspect;
+  gboolean handle_events;
   
   gint brightness;
   gint contrast;
index b26bb993ff90d0489bddacad4683a1ec64ce8fa1..63d8bb06c508ee8690503f42785725c893d78992 100644 (file)
@@ -93,17 +93,38 @@ move_window (GstPipeline * pipeline)
   return TRUE;
 }
 
+static gboolean
+toggle_events (GstXOverlay * ov)
+{
+  static gboolean events_toggled;
+
+  gst_x_overlay_handle_events (ov, events_toggled);
+
+  if (events_toggled) {
+    g_print ("Events are handled\n");
+    events_toggled = FALSE;
+  } else {
+    g_print ("Events are NOT handled\n");
+    events_toggled = TRUE;
+  }
+
+  return TRUE;
+}
+
 static GstBusSyncReply
 create_window (GstBus * bus, GstMessage * message, GstPipeline * pipeline)
 {
   XGCValues values;
   const GstStructure *s;
+  GstXOverlay *ov = NULL;
 
   s = gst_message_get_structure (message);
   if (!gst_structure_has_name (s, "prepare-xwindow-id")) {
     return GST_BUS_PASS;
   }
 
+  ov = GST_X_OVERLAY (GST_MESSAGE_SRC (message));
+
   g_print ("Creating our own window\n");
 
   win = XCreateSimpleWindow (disp, root, 0, 0, width, height, 0, 0, 0);
@@ -116,10 +137,11 @@ create_window (GstBus * bus, GstMessage * message, GstPipeline * pipeline)
 
   XSync (disp, FALSE);
 
-  gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (GST_MESSAGE_SRC (message)), win);
+  gst_x_overlay_set_xwindow_id (ov, win);
 
   g_timeout_add (50, (GSourceFunc) resize_window, pipeline);
   g_timeout_add (50, (GSourceFunc) move_window, pipeline);
+  g_timeout_add (2000, (GSourceFunc) toggle_events, ov);
 
   return GST_BUS_DROP;
 }