From b8daf624c5476554a4296efd672f3fb212875e74 Mon Sep 17 00:00:00 2001 From: gb Date: Mon, 22 Mar 2010 10:51:49 +0000 Subject: [PATCH] Add gst_vaapi_window_set_fullscreen() API. --- docs/reference/libs/libs-sections.txt | 1 + gst-libs/gst/vaapi/gstvaapiwindow.c | 28 +++++- gst-libs/gst/vaapi/gstvaapiwindow.h | 5 ++ gst-libs/gst/vaapi/gstvaapiwindow_x11.c | 154 +++++++++++++++++++++++++++----- 4 files changed, 165 insertions(+), 23 deletions(-) diff --git a/docs/reference/libs/libs-sections.txt b/docs/reference/libs/libs-sections.txt index f0832fa..a6b14a3 100644 --- a/docs/reference/libs/libs-sections.txt +++ b/docs/reference/libs/libs-sections.txt @@ -161,6 +161,7 @@ GstVaapiWindow GstVaapiWindowClass gst_vaapi_window_show gst_vaapi_window_hide +gst_vaapi_window_set_fullscreen gst_vaapi_window_get_width gst_vaapi_window_get_height gst_vaapi_window_get_size diff --git a/gst-libs/gst/vaapi/gstvaapiwindow.c b/gst-libs/gst/vaapi/gstvaapiwindow.c index 0a1fa07..58121ac 100644 --- a/gst-libs/gst/vaapi/gstvaapiwindow.c +++ b/gst-libs/gst/vaapi/gstvaapiwindow.c @@ -37,9 +37,10 @@ G_DEFINE_TYPE(GstVaapiWindow, gst_vaapi_window, G_TYPE_OBJECT); GstVaapiWindowPrivate)) struct _GstVaapiWindowPrivate { - gboolean is_constructed; guint width; guint height; + gboolean is_constructed : 1; + guint is_fullscreen : 1; }; enum { @@ -179,9 +180,10 @@ gst_vaapi_window_init(GstVaapiWindow *window) GstVaapiWindowPrivate *priv = GST_VAAPI_WINDOW_GET_PRIVATE(window); window->priv = priv; - priv->is_constructed = FALSE; priv->width = 1; priv->height = 1; + priv->is_constructed = FALSE; + priv->is_fullscreen = FALSE; } /** @@ -217,6 +219,28 @@ gst_vaapi_window_hide(GstVaapiWindow *window) } /** + * gst_vaapi_window_set_fullscreen: + * @window: a #GstVaapiWindow + * @fullscreen: %TRUE to request window to get fullscreen + * + * Requests to place the @window in fullscreen or unfullscreen states. + */ +void +gst_vaapi_window_set_fullscreen(GstVaapiWindow *window, gboolean fullscreen) +{ + GstVaapiWindowClass *klass; + + g_return_if_fail(GST_VAAPI_IS_WINDOW(window)); + + klass = GST_VAAPI_WINDOW_GET_CLASS(window); + + if (window->priv->is_fullscreen != fullscreen && klass->set_fullscreen) { + klass->set_fullscreen(window, fullscreen); + window->priv->is_fullscreen = fullscreen; + } +} + +/** * gst_vaapi_window_get_width: * @window: a #GstVaapiWindow * diff --git a/gst-libs/gst/vaapi/gstvaapiwindow.h b/gst-libs/gst/vaapi/gstvaapiwindow.h index 9e3689b..804b035 100644 --- a/gst-libs/gst/vaapi/gstvaapiwindow.h +++ b/gst-libs/gst/vaapi/gstvaapiwindow.h @@ -73,6 +73,7 @@ struct _GstVaapiWindow { * @destroy: virtual function to destroy a window * @show: virtual function to show (map) a window * @hide: virtual function to hide (unmap) a window + * @set_fullscreen: virtual function to change window fullscreen state * @resize: virtual function to resize a window * @render: virtual function to render a #GstVaapiSurface into a window * @@ -87,6 +88,7 @@ struct _GstVaapiWindowClass { void (*destroy)(GstVaapiWindow *window); gboolean (*show) (GstVaapiWindow *window); gboolean (*hide) (GstVaapiWindow *window); + gboolean (*set_fullscreen)(GstVaapiWindow *window, gboolean fullscreen); gboolean (*resize) (GstVaapiWindow *window, guint width, guint height); gboolean (*render) (GstVaapiWindow *window, GstVaapiSurface *surface, @@ -104,6 +106,9 @@ gst_vaapi_window_show(GstVaapiWindow *window); void gst_vaapi_window_hide(GstVaapiWindow *window); +void +gst_vaapi_window_set_fullscreen(GstVaapiWindow *window, gboolean fullscreen); + guint gst_vaapi_window_get_width(GstVaapiWindow *window); diff --git a/gst-libs/gst/vaapi/gstvaapiwindow_x11.c b/gst-libs/gst/vaapi/gstvaapiwindow_x11.c index 6905870..c0b1f0c 100644 --- a/gst-libs/gst/vaapi/gstvaapiwindow_x11.c +++ b/gst-libs/gst/vaapi/gstvaapiwindow_x11.c @@ -24,6 +24,8 @@ */ #include "config.h" +#include +#include #include "gstvaapiwindow_x11.h" #include "gstvaapidisplay_x11.h" #include "gstvaapiutils_x11.h" @@ -41,8 +43,11 @@ G_DEFINE_TYPE(GstVaapiWindowX11, gst_vaapi_window_x11, GST_VAAPI_TYPE_WINDOW); struct _GstVaapiWindowX11Private { GstVaapiDisplay *display; Window xid; - guint create_window : 1; - guint is_visible : 1; + Atom atom_NET_WM_STATE; + Atom atom_NET_WM_STATE_FULLSCREEN; + guint create_window : 1; + guint is_mapped : 1; + guint fullscreen_on_map : 1; }; enum { @@ -52,6 +57,45 @@ enum { PROP_XID, }; +#define _NET_WM_STATE_REMOVE 0 /* remove/unset property */ +#define _NET_WM_STATE_ADD 1 /* add/set property */ +#define _NET_WM_STATE_TOGGLE 2 /* toggle property */ + +static gboolean +send_wmspec_change_state(GstVaapiWindowX11 *window, Atom state, gboolean add) +{ + GstVaapiWindowX11Private * const priv = window->priv; + Display * const dpy = GST_VAAPI_DISPLAY_XDISPLAY(priv->display); + gboolean has_errors; + XClientMessageEvent xclient; + + memset(&xclient, 0, sizeof(xclient)); + + xclient.type = ClientMessage; + xclient.window = priv->xid; + xclient.message_type = priv->atom_NET_WM_STATE; + xclient.format = 32; + + xclient.data.l[0] = add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE; + xclient.data.l[1] = state; + xclient.data.l[2] = 0; + xclient.data.l[3] = 0; + xclient.data.l[4] = 0; + + GST_VAAPI_DISPLAY_LOCK(priv->display); + x11_trap_errors(); + XSendEvent( + dpy, + DefaultRootWindow(dpy), + False, + SubstructureRedirectMask|SubstructureNotifyMask, + (XEvent *)&xclient + ); + has_errors = x11_untrap_errors() != 0; + GST_VAAPI_DISPLAY_UNLOCK(priv->display); + return !has_errors; +} + static gboolean gst_vaapi_window_x11_show(GstVaapiWindow *window) { @@ -59,7 +103,7 @@ gst_vaapi_window_x11_show(GstVaapiWindow *window) Display * const dpy = GST_VAAPI_DISPLAY_XDISPLAY(priv->display); gboolean has_errors; - if (priv->is_visible) + if (priv->is_mapped) return TRUE; GST_VAAPI_DISPLAY_LOCK(priv->display); @@ -72,7 +116,7 @@ gst_vaapi_window_x11_show(GstVaapiWindow *window) if (has_errors) return FALSE; - priv->is_visible = TRUE; + priv->is_mapped = TRUE; return TRUE; } @@ -83,7 +127,7 @@ gst_vaapi_window_x11_hide(GstVaapiWindow *window) Display * const dpy = GST_VAAPI_DISPLAY_XDISPLAY(priv->display); gboolean has_errors; - if (!priv->is_visible) + if (!priv->is_mapped) return TRUE; GST_VAAPI_DISPLAY_LOCK(priv->display); @@ -96,7 +140,7 @@ gst_vaapi_window_x11_hide(GstVaapiWindow *window) if (has_errors) return FALSE; - priv->is_visible = FALSE; + priv->is_mapped = FALSE; return TRUE; } @@ -105,8 +149,14 @@ gst_vaapi_window_x11_create(GstVaapiWindow *window, guint *width, guint *height) { GstVaapiWindowX11Private * const priv = GST_VAAPI_WINDOW_X11(window)->priv; Display * const dpy = GST_VAAPI_DISPLAY_XDISPLAY(priv->display); + Atom atoms[2]; gboolean ok; + static const char *atom_names[2] = { + "_NET_WM_STATE", + "_NET_WM_STATE_FULLSCREEN", + }; + if (!priv->create_window && priv->xid) { GST_VAAPI_DISPLAY_LOCK(priv->display); ok = x11_get_geometry(dpy, priv->xid, NULL, NULL, width, height); @@ -115,6 +165,10 @@ gst_vaapi_window_x11_create(GstVaapiWindow *window, guint *width, guint *height) } GST_VAAPI_DISPLAY_LOCK(priv->display); + XInternAtoms(dpy, (char **)atom_names, G_N_ELEMENTS(atom_names), False, atoms); + priv->atom_NET_WM_STATE = atoms[0]; + priv->atom_NET_WM_STATE_FULLSCREEN = atoms[1]; + priv->xid = x11_create_window(dpy, *width, *height); if (priv->xid) XRaiseWindow(dpy, priv->xid); @@ -144,6 +198,62 @@ gst_vaapi_window_x11_destroy(GstVaapiWindow *window) } static gboolean +gst_vaapi_window_x11_set_fullscreen(GstVaapiWindow *window, gboolean fullscreen) +{ + GstVaapiWindowX11Private * const priv = GST_VAAPI_WINDOW_X11(window)->priv; + Display * const dpy = GST_VAAPI_DISPLAY_XDISPLAY(priv->display); + gboolean has_errors; + + if (fullscreen) { + if (!priv->is_mapped) { + priv->fullscreen_on_map = TRUE; + + GST_VAAPI_DISPLAY_LOCK(priv->display); + x11_trap_errors(); + XChangeProperty( + dpy, + priv->xid, + priv->atom_NET_WM_STATE, XA_ATOM, 32, + PropModeReplace, + (unsigned char *)&priv->atom_NET_WM_STATE_FULLSCREEN, 1 + ); + has_errors = x11_untrap_errors() != 0; + GST_VAAPI_DISPLAY_UNLOCK(priv->display); + } + else { + has_errors = !send_wmspec_change_state( + GST_VAAPI_WINDOW_X11(window), + priv->atom_NET_WM_STATE_FULLSCREEN, + TRUE + ); + } + } + else { + if (!priv->is_mapped) { + priv->fullscreen_on_map = FALSE; + + GST_VAAPI_DISPLAY_LOCK(priv->display); + x11_trap_errors(); + XDeleteProperty( + dpy, + priv->xid, + priv->atom_NET_WM_STATE + ); + has_errors = x11_untrap_errors() != 0; + GST_VAAPI_DISPLAY_UNLOCK(priv->display); + } + else { + has_errors = !send_wmspec_change_state( + GST_VAAPI_WINDOW_X11(window), + priv->atom_NET_WM_STATE_FULLSCREEN, + FALSE + ); + } + } + return !has_errors; +} + +static gboolean gst_vaapi_window_x11_resize(GstVaapiWindow *window, guint width, guint height) { GstVaapiWindowX11Private * const priv = GST_VAAPI_WINDOW_X11(window)->priv; @@ -282,17 +392,18 @@ gst_vaapi_window_x11_class_init(GstVaapiWindowX11Class *klass) g_type_class_add_private(klass, sizeof(GstVaapiWindowX11Private)); - object_class->finalize = gst_vaapi_window_x11_finalize; - object_class->set_property = gst_vaapi_window_x11_set_property; - object_class->get_property = gst_vaapi_window_x11_get_property; - object_class->constructed = gst_vaapi_window_x11_constructed; + object_class->finalize = gst_vaapi_window_x11_finalize; + object_class->set_property = gst_vaapi_window_x11_set_property; + object_class->get_property = gst_vaapi_window_x11_get_property; + object_class->constructed = gst_vaapi_window_x11_constructed; - window_class->create = gst_vaapi_window_x11_create; - window_class->destroy = gst_vaapi_window_x11_destroy; - window_class->show = gst_vaapi_window_x11_show; - window_class->hide = gst_vaapi_window_x11_hide; - window_class->resize = gst_vaapi_window_x11_resize; - window_class->render = gst_vaapi_window_x11_render; + window_class->create = gst_vaapi_window_x11_create; + window_class->destroy = gst_vaapi_window_x11_destroy; + window_class->show = gst_vaapi_window_x11_show; + window_class->hide = gst_vaapi_window_x11_hide; + window_class->set_fullscreen = gst_vaapi_window_x11_set_fullscreen; + window_class->resize = gst_vaapi_window_x11_resize; + window_class->render = gst_vaapi_window_x11_render; /** * GstVaapiWindowX11:display: @@ -328,11 +439,12 @@ gst_vaapi_window_x11_init(GstVaapiWindowX11 *window) { GstVaapiWindowX11Private *priv = GST_VAAPI_WINDOW_X11_GET_PRIVATE(window); - window->priv = priv; - priv->display = NULL; - priv->xid = None; - priv->create_window = TRUE; - priv->is_visible = FALSE; + window->priv = priv; + priv->display = NULL; + priv->xid = None; + priv->create_window = TRUE; + priv->is_mapped = FALSE; + priv->fullscreen_on_map = FALSE; } /** -- 2.7.4