+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:
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);
+ }
+}
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);
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);
PROP_DISPLAY,
PROP_SYNCHRONOUS,
PROP_PIXEL_ASPECT_RATIO,
- PROP_FORCE_ASPECT_RATIO
+ PROP_FORCE_ASPECT_RATIO,
+ PROP_HANDLE_EVENTS
/* FILL ME */
};
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);
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);
}
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;
}
/* =========================================== */
}
}
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;
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;
ximagesink->synchronous = FALSE;
ximagesink->keep_aspect = FALSE;
+ ximagesink->handle_events = TRUE;
}
static void
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;
* 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.
*/
gboolean synchronous;
gboolean keep_aspect;
+ gboolean handle_events;
};
struct _GstXImageSinkClass {
ARG_DISPLAY,
ARG_SYNCHRONOUS,
ARG_PIXEL_ASPECT_RATIO,
- ARG_FORCE_ASPECT_RATIO
+ ARG_FORCE_ASPECT_RATIO,
+ ARG_HANDLE_EVENTS
/* FILL ME */
};
* 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);
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);
}
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 *
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;
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;
xvimagesink->synchronous = FALSE;
xvimagesink->running = FALSE;
xvimagesink->keep_aspect = FALSE;
+ xvimagesink->handle_events = TRUE;
xvimagesink->par = NULL;
}
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;
* 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
gboolean synchronous;
gboolean keep_aspect;
+ gboolean handle_events;
gint brightness;
gint contrast;
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);
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;
}