mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 08:46:40 +00:00
sys/: When we create our own window, indicate that we handle the
Original commit message from CVS: * sys/ximage/ximagesink.c: (gst_ximagesink_ximage_put), (gst_ximagesink_xwindow_new), (gst_ximagesink_handle_xevents), (gst_ximagesink_show_frame): * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xvimage_put), (gst_xvimagesink_xwindow_new), (gst_xvimagesink_handle_xevents), (gst_xvimagesink_show_frame): When we create our own window, indicate that we handle the WM_DELETE client message from the window manager, so that it won't kill our window (and our app) along with it. Handle ClientMessage, post an error on the bus, and close the window. Further buffers arriving will result in a FlowError because the window has been destroyed. Fixes: #393975 Clean up the X event handling loop and make them the same for both xvimagesink and ximagesink while I'm at it.
This commit is contained in:
parent
a18a10e81f
commit
cbc95dfb3d
3 changed files with 205 additions and 99 deletions
20
ChangeLog
20
ChangeLog
|
@ -1,3 +1,23 @@
|
|||
2007-05-17 Jan Schmidt <thaytan@mad.scientist.com>
|
||||
|
||||
* sys/ximage/ximagesink.c: (gst_ximagesink_ximage_put),
|
||||
(gst_ximagesink_xwindow_new), (gst_ximagesink_handle_xevents),
|
||||
(gst_ximagesink_show_frame):
|
||||
* sys/xvimage/xvimagesink.c: (gst_xvimagesink_xvimage_put),
|
||||
(gst_xvimagesink_xwindow_new), (gst_xvimagesink_handle_xevents),
|
||||
(gst_xvimagesink_show_frame):
|
||||
When we create our own window, indicate that we handle the
|
||||
WM_DELETE client message from the window manager, so that it won't
|
||||
kill our window (and our app) along with it. Handle ClientMessage,
|
||||
post an error on the bus, and close the window. Further buffers
|
||||
arriving will result in a FlowError because the window has been
|
||||
destroyed.
|
||||
|
||||
Fixes: #393975
|
||||
|
||||
Clean up the X event handling loop and make them the same for
|
||||
both xvimagesink and ximagesink while I'm at it.
|
||||
|
||||
2007-05-17 Wim Taymans <wim@fluendo.com>
|
||||
|
||||
* gst/playback/gstdecodebin2.c: (gst_decode_bin_factory_filter):
|
||||
|
|
|
@ -668,13 +668,13 @@ gst_ximagesink_xwindow_draw_borders (GstXImageSink * ximagesink,
|
|||
}
|
||||
|
||||
/* This function puts a GstXImageBuffer on a GstXImageSink's window */
|
||||
static void
|
||||
static gboolean
|
||||
gst_ximagesink_ximage_put (GstXImageSink * ximagesink, GstXImageBuffer * ximage)
|
||||
{
|
||||
GstVideoRectangle src, dst, result;
|
||||
gboolean draw_border = FALSE;
|
||||
|
||||
g_return_if_fail (GST_IS_XIMAGESINK (ximagesink));
|
||||
g_return_val_if_fail (GST_IS_XIMAGESINK (ximagesink), FALSE);
|
||||
|
||||
/* We take the flow_lock. If expose is in there we don't want to run
|
||||
concurrently from the data flow thread */
|
||||
|
@ -682,7 +682,7 @@ gst_ximagesink_ximage_put (GstXImageSink * ximagesink, GstXImageBuffer * ximage)
|
|||
|
||||
if (G_UNLIKELY (ximagesink->xwindow == NULL)) {
|
||||
g_mutex_unlock (ximagesink->flow_lock);
|
||||
return;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Draw borders when displaying the first frame. After this
|
||||
|
@ -709,7 +709,7 @@ gst_ximagesink_ximage_put (GstXImageSink * ximagesink, GstXImageBuffer * ximage)
|
|||
ximage = ximagesink->cur_image;
|
||||
} else {
|
||||
g_mutex_unlock (ximagesink->flow_lock);
|
||||
return;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -754,6 +754,8 @@ gst_ximagesink_ximage_put (GstXImageSink * ximagesink, GstXImageBuffer * ximage)
|
|||
g_mutex_unlock (ximagesink->x_lock);
|
||||
|
||||
g_mutex_unlock (ximagesink->flow_lock);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@ -818,9 +820,18 @@ gst_ximagesink_xwindow_new (GstXImageSink * ximagesink, gint width, gint height)
|
|||
XSetWindowBackgroundPixmap (ximagesink->xcontext->disp, xwindow->win, None);
|
||||
|
||||
if (ximagesink->handle_events) {
|
||||
Atom wm_delete;
|
||||
|
||||
XSelectInput (ximagesink->xcontext->disp, xwindow->win, ExposureMask |
|
||||
StructureNotifyMask | PointerMotionMask | KeyPressMask |
|
||||
KeyReleaseMask | ButtonPressMask | ButtonReleaseMask);
|
||||
|
||||
/* Tell the window manager we'd like delete client messages instead of
|
||||
* being killed */
|
||||
wm_delete = XInternAtom (ximagesink->xcontext->disp,
|
||||
"WM_DELETE_WINDOW", False);
|
||||
(void) XSetWMProtocols (ximagesink->xcontext->disp, xwindow->win,
|
||||
&wm_delete, 1);
|
||||
}
|
||||
|
||||
xwindow->gc = XCreateGC (ximagesink->xcontext->disp, xwindow->win,
|
||||
|
@ -911,12 +922,11 @@ static void
|
|||
gst_ximagesink_handle_xevents (GstXImageSink * ximagesink)
|
||||
{
|
||||
XEvent e;
|
||||
|
||||
g_return_if_fail (GST_IS_XIMAGESINK (ximagesink));
|
||||
|
||||
{
|
||||
guint pointer_x = 0, pointer_y = 0;
|
||||
gboolean pointer_moved = FALSE;
|
||||
gboolean exposed = FALSE, configured = FALSE;
|
||||
|
||||
g_return_if_fail (GST_IS_XIMAGESINK (ximagesink));
|
||||
|
||||
/* Then we get all pointer motion events, only the last position is
|
||||
interesting. */
|
||||
|
@ -939,20 +949,21 @@ gst_ximagesink_handle_xevents (GstXImageSink * ximagesink)
|
|||
g_mutex_lock (ximagesink->flow_lock);
|
||||
g_mutex_lock (ximagesink->x_lock);
|
||||
}
|
||||
|
||||
if (pointer_moved) {
|
||||
g_mutex_unlock (ximagesink->x_lock);
|
||||
g_mutex_unlock (ximagesink->flow_lock);
|
||||
|
||||
if (pointer_moved) {
|
||||
GST_DEBUG ("ximagesink pointer moved over window at %d,%d",
|
||||
pointer_x, pointer_y);
|
||||
gst_navigation_send_mouse_event (GST_NAVIGATION (ximagesink),
|
||||
"mouse-move", 0, pointer_x, pointer_y);
|
||||
}
|
||||
|
||||
g_mutex_lock (ximagesink->flow_lock);
|
||||
g_mutex_lock (ximagesink->x_lock);
|
||||
}
|
||||
|
||||
/* We get all remaining events on our window to throw them upstream */
|
||||
g_mutex_lock (ximagesink->flow_lock);
|
||||
g_mutex_lock (ximagesink->x_lock);
|
||||
while (XCheckWindowEvent (ximagesink->xcontext->disp,
|
||||
ximagesink->xwindow->win,
|
||||
KeyPressMask | KeyReleaseMask |
|
||||
|
@ -1009,36 +1020,60 @@ gst_ximagesink_handle_xevents (GstXImageSink * ximagesink)
|
|||
g_mutex_lock (ximagesink->flow_lock);
|
||||
g_mutex_lock (ximagesink->x_lock);
|
||||
}
|
||||
g_mutex_unlock (ximagesink->x_lock);
|
||||
g_mutex_unlock (ximagesink->flow_lock);
|
||||
|
||||
{
|
||||
gboolean exposed = FALSE;
|
||||
|
||||
g_mutex_lock (ximagesink->flow_lock);
|
||||
g_mutex_lock (ximagesink->x_lock);
|
||||
while (XCheckWindowEvent (ximagesink->xcontext->disp,
|
||||
ximagesink->xwindow->win, ExposureMask, &e)) {
|
||||
g_mutex_unlock (ximagesink->x_lock);
|
||||
g_mutex_unlock (ximagesink->flow_lock);
|
||||
|
||||
ximagesink->xwindow->win, ExposureMask | StructureNotifyMask, &e)) {
|
||||
switch (e.type) {
|
||||
case Expose:
|
||||
exposed = TRUE;
|
||||
break;
|
||||
case ConfigureNotify:
|
||||
configured = TRUE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
g_mutex_lock (ximagesink->flow_lock);
|
||||
g_mutex_lock (ximagesink->x_lock);
|
||||
}
|
||||
|
||||
if (exposed || configured) {
|
||||
g_mutex_unlock (ximagesink->x_lock);
|
||||
g_mutex_unlock (ximagesink->flow_lock);
|
||||
|
||||
if (exposed) {
|
||||
gst_ximagesink_expose (GST_X_OVERLAY (ximagesink));
|
||||
|
||||
g_mutex_lock (ximagesink->x_lock);
|
||||
g_mutex_lock (ximagesink->flow_lock);
|
||||
}
|
||||
|
||||
/* Handle Display events */
|
||||
while (XPending (ximagesink->xcontext->disp)) {
|
||||
XNextEvent (ximagesink->xcontext->disp, &e);
|
||||
|
||||
switch (e.type) {
|
||||
case ClientMessage:{
|
||||
Atom wm_delete;
|
||||
|
||||
wm_delete = XInternAtom (ximagesink->xcontext->disp,
|
||||
"WM_DELETE_WINDOW", False);
|
||||
if (wm_delete == (Atom) e.xclient.data.l[0]) {
|
||||
/* Handle window deletion by posting an error on the bus */
|
||||
GST_ELEMENT_ERROR (ximagesink, RESOURCE, NOT_FOUND,
|
||||
("Output window was closed"), (NULL));
|
||||
|
||||
g_mutex_unlock (ximagesink->x_lock);
|
||||
gst_ximagesink_xwindow_destroy (ximagesink, ximagesink->xwindow);
|
||||
ximagesink->xwindow = NULL;
|
||||
g_mutex_lock (ximagesink->x_lock);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_mutex_unlock (ximagesink->x_lock);
|
||||
g_mutex_unlock (ximagesink->flow_lock);
|
||||
}
|
||||
|
||||
static gpointer
|
||||
|
@ -1543,7 +1578,8 @@ gst_ximagesink_show_frame (GstBaseSink * bsink, GstBuffer * buf)
|
|||
put the ximage which is in the PRIVATE pointer */
|
||||
if (GST_IS_XIMAGE_BUFFER (buf)) {
|
||||
GST_LOG_OBJECT (ximagesink, "buffer from our pool, writing directly");
|
||||
gst_ximagesink_ximage_put (ximagesink, GST_XIMAGE_BUFFER (buf));
|
||||
if (!gst_ximagesink_ximage_put (ximagesink, GST_XIMAGE_BUFFER (buf)))
|
||||
goto no_window;
|
||||
} else {
|
||||
/* Else we have to copy the data into our private image, */
|
||||
/* if we have one... */
|
||||
|
@ -1569,7 +1605,8 @@ gst_ximagesink_show_frame (GstBaseSink * bsink, GstBuffer * buf)
|
|||
}
|
||||
memcpy (GST_BUFFER_DATA (ximagesink->ximage), GST_BUFFER_DATA (buf),
|
||||
MIN (GST_BUFFER_SIZE (buf), ximagesink->ximage->size));
|
||||
gst_ximagesink_ximage_put (ximagesink, ximagesink->ximage);
|
||||
if (!gst_ximagesink_ximage_put (ximagesink, ximagesink->ximage))
|
||||
goto no_window;
|
||||
}
|
||||
|
||||
return GST_FLOW_OK;
|
||||
|
@ -1581,6 +1618,12 @@ no_ximage:
|
|||
GST_DEBUG ("could not create image");
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
no_window:
|
||||
{
|
||||
/* No Window available to put our image into */
|
||||
GST_WARNING_OBJECT (ximagesink, "could not output image - no window");
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Buffer management
|
||||
|
|
|
@ -719,15 +719,16 @@ gst_xvimagesink_xwindow_draw_borders (GstXvImageSink * xvimagesink,
|
|||
}
|
||||
}
|
||||
|
||||
/* This function puts a GstXvImage on a GstXvImageSink's window */
|
||||
static void
|
||||
/* This function puts a GstXvImage on a GstXvImageSink's window. Returns FALSE
|
||||
* if no window was available */
|
||||
static gboolean
|
||||
gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink,
|
||||
GstXvImageBuffer * xvimage)
|
||||
{
|
||||
GstVideoRectangle src, dst, result;
|
||||
gboolean draw_border = FALSE;
|
||||
|
||||
g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
|
||||
g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), FALSE);
|
||||
|
||||
/* We take the flow_lock. If expose is in there we don't want to run
|
||||
concurrently from the data flow thread */
|
||||
|
@ -735,7 +736,7 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink,
|
|||
|
||||
if (G_UNLIKELY (xvimagesink->xwindow == NULL)) {
|
||||
g_mutex_unlock (xvimagesink->flow_lock);
|
||||
return;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Draw borders when displaying the first frame. After this
|
||||
|
@ -762,7 +763,7 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink,
|
|||
xvimage = xvimagesink->cur_image;
|
||||
} else {
|
||||
g_mutex_unlock (xvimagesink->flow_lock);
|
||||
return;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -821,6 +822,8 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink,
|
|||
g_mutex_unlock (xvimagesink->x_lock);
|
||||
|
||||
g_mutex_unlock (xvimagesink->flow_lock);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@ -888,9 +891,18 @@ gst_xvimagesink_xwindow_new (GstXvImageSink * xvimagesink,
|
|||
XSetWindowBackgroundPixmap (xvimagesink->xcontext->disp, xwindow->win, None);
|
||||
|
||||
if (xvimagesink->handle_events) {
|
||||
Atom wm_delete;
|
||||
|
||||
XSelectInput (xvimagesink->xcontext->disp, xwindow->win, ExposureMask |
|
||||
StructureNotifyMask | PointerMotionMask | KeyPressMask |
|
||||
KeyReleaseMask | ButtonPressMask | ButtonReleaseMask);
|
||||
|
||||
/* Tell the window manager we'd like delete client messages instead of
|
||||
* being killed */
|
||||
wm_delete = XInternAtom (xvimagesink->xcontext->disp,
|
||||
"WM_DELETE_WINDOW", False);
|
||||
(void) XSetWMProtocols (xvimagesink->xcontext->disp, xwindow->win,
|
||||
&wm_delete, 1);
|
||||
}
|
||||
|
||||
xwindow->gc = XCreateGC (xvimagesink->xcontext->disp,
|
||||
|
@ -1048,6 +1060,7 @@ gst_xvimagesink_handle_xevents (GstXvImageSink * xvimagesink)
|
|||
XEvent e;
|
||||
guint pointer_x = 0, pointer_y = 0;
|
||||
gboolean pointer_moved = FALSE;
|
||||
gboolean exposed = FALSE, configured = FALSE;
|
||||
|
||||
g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
|
||||
|
||||
|
@ -1072,19 +1085,20 @@ gst_xvimagesink_handle_xevents (GstXvImageSink * xvimagesink)
|
|||
g_mutex_lock (xvimagesink->flow_lock);
|
||||
g_mutex_lock (xvimagesink->x_lock);
|
||||
}
|
||||
if (pointer_moved) {
|
||||
g_mutex_unlock (xvimagesink->x_lock);
|
||||
g_mutex_unlock (xvimagesink->flow_lock);
|
||||
|
||||
if (pointer_moved) {
|
||||
GST_DEBUG ("xvimagesink pointer moved over window at %d,%d",
|
||||
pointer_x, pointer_y);
|
||||
gst_navigation_send_mouse_event (GST_NAVIGATION (xvimagesink),
|
||||
"mouse-move", 0, e.xbutton.x, e.xbutton.y);
|
||||
|
||||
g_mutex_lock (xvimagesink->flow_lock);
|
||||
g_mutex_lock (xvimagesink->x_lock);
|
||||
}
|
||||
|
||||
/* We get all events on our window to throw them upstream */
|
||||
g_mutex_lock (xvimagesink->flow_lock);
|
||||
g_mutex_lock (xvimagesink->x_lock);
|
||||
while (XCheckWindowEvent (xvimagesink->xcontext->disp,
|
||||
xvimagesink->xwindow->win,
|
||||
KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask,
|
||||
|
@ -1141,40 +1155,61 @@ gst_xvimagesink_handle_xevents (GstXvImageSink * xvimagesink)
|
|||
g_mutex_lock (xvimagesink->flow_lock);
|
||||
g_mutex_lock (xvimagesink->x_lock);
|
||||
}
|
||||
g_mutex_unlock (xvimagesink->x_lock);
|
||||
g_mutex_unlock (xvimagesink->flow_lock);
|
||||
|
||||
/* Handle Expose */
|
||||
{
|
||||
gboolean exposed = FALSE, configured = FALSE;
|
||||
|
||||
g_mutex_lock (xvimagesink->flow_lock);
|
||||
g_mutex_lock (xvimagesink->x_lock);
|
||||
while (XCheckWindowEvent (xvimagesink->xcontext->disp,
|
||||
xvimagesink->xwindow->win, ExposureMask | StructureNotifyMask,
|
||||
&e)) {
|
||||
g_mutex_unlock (xvimagesink->x_lock);
|
||||
g_mutex_unlock (xvimagesink->flow_lock);
|
||||
|
||||
xvimagesink->xwindow->win, ExposureMask | StructureNotifyMask, &e)) {
|
||||
switch (e.type) {
|
||||
case Expose:
|
||||
exposed = TRUE;
|
||||
break;
|
||||
case ConfigureNotify:
|
||||
configured = TRUE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
g_mutex_lock (xvimagesink->flow_lock);
|
||||
g_mutex_lock (xvimagesink->x_lock);
|
||||
}
|
||||
|
||||
if (exposed || configured) {
|
||||
g_mutex_unlock (xvimagesink->x_lock);
|
||||
g_mutex_unlock (xvimagesink->flow_lock);
|
||||
|
||||
if (exposed || configured) {
|
||||
gst_xvimagesink_expose (GST_X_OVERLAY (xvimagesink));
|
||||
|
||||
g_mutex_lock (xvimagesink->x_lock);
|
||||
g_mutex_lock (xvimagesink->flow_lock);
|
||||
}
|
||||
|
||||
/* Handle Display events */
|
||||
while (XPending (xvimagesink->xcontext->disp)) {
|
||||
XNextEvent (xvimagesink->xcontext->disp, &e);
|
||||
|
||||
switch (e.type) {
|
||||
case ClientMessage:{
|
||||
Atom wm_delete;
|
||||
|
||||
wm_delete = XInternAtom (xvimagesink->xcontext->disp,
|
||||
"WM_DELETE_WINDOW", False);
|
||||
if (wm_delete == (Atom) e.xclient.data.l[0]) {
|
||||
/* Handle window deletion by posting an error on the bus */
|
||||
GST_ELEMENT_ERROR (xvimagesink, RESOURCE, NOT_FOUND,
|
||||
("Output window was closed"), (NULL));
|
||||
|
||||
g_mutex_unlock (xvimagesink->x_lock);
|
||||
gst_xvimagesink_xwindow_destroy (xvimagesink, xvimagesink->xwindow);
|
||||
xvimagesink->xwindow = NULL;
|
||||
g_mutex_lock (xvimagesink->x_lock);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_mutex_unlock (xvimagesink->x_lock);
|
||||
g_mutex_unlock (xvimagesink->flow_lock);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2114,7 +2149,8 @@ gst_xvimagesink_show_frame (GstBaseSink * bsink, GstBuffer * buf)
|
|||
put the ximage which is in the PRIVATE pointer */
|
||||
if (GST_IS_XVIMAGE_BUFFER (buf)) {
|
||||
GST_LOG_OBJECT (xvimagesink, "fast put of bufferpool buffer");
|
||||
gst_xvimagesink_xvimage_put (xvimagesink, GST_XVIMAGE_BUFFER (buf));
|
||||
if (!gst_xvimagesink_xvimage_put (xvimagesink, GST_XVIMAGE_BUFFER (buf)))
|
||||
goto no_window;
|
||||
} else {
|
||||
GST_LOG_OBJECT (xvimagesink, "slow copy into bufferpool buffer");
|
||||
/* Else we have to copy the data into our private image, */
|
||||
|
@ -2145,7 +2181,8 @@ gst_xvimagesink_show_frame (GstBaseSink * bsink, GstBuffer * buf)
|
|||
GST_BUFFER_DATA (buf),
|
||||
MIN (GST_BUFFER_SIZE (buf), xvimagesink->xvimage->size));
|
||||
|
||||
gst_xvimagesink_xvimage_put (xvimagesink, xvimagesink->xvimage);
|
||||
if (!gst_xvimagesink_xvimage_put (xvimagesink, xvimagesink->xvimage))
|
||||
goto no_window;
|
||||
}
|
||||
|
||||
return GST_FLOW_OK;
|
||||
|
@ -2157,6 +2194,12 @@ no_image:
|
|||
GST_WARNING_OBJECT (xvimagesink, "could not create image");
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
no_window:
|
||||
{
|
||||
/* No Window available to put our image into */
|
||||
GST_WARNING_OBJECT (xvimagesink, "could not output image - no window");
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Buffer management */
|
||||
|
|
Loading…
Reference in a new issue