[x11 backend] remove data duplicated between backends and stages

Make backends the canonical point of reference for the xdisplay, the xscreen
number, the x root window and the xvisinfo for creating foreign stages.
This commit is contained in:
Robert Bragg 2009-08-03 14:50:10 +01:00
parent 63414ab233
commit 3187e19642
9 changed files with 200 additions and 142 deletions

View File

@ -248,16 +248,12 @@ clutter_backend_egl_create_stage (ClutterBackend *backend,
/* copy backend data into the stage */
stage_x11 = CLUTTER_STAGE_X11 (stage);
stage_x11->xdpy = backend_x11->xdpy;
stage_x11->xwin_root = backend_x11->xwin_root;
stage_x11->xscreen = backend_x11->xscreen_num;
stage_x11->backend = backend_x11;
stage_x11->wrapper = wrapper;
CLUTTER_NOTE (MISC, "EGLX stage created (display:%p, screen:%d, root:%u)",
stage_x11->xdpy,
stage_x11->xscreen,
(unsigned int) stage_x11->xwin_root);
backend_x11->xdpy,
backend_x11->xscreen_num,
(unsigned int) backend_x11->xwin_root);
return stage;
}

View File

@ -32,6 +32,8 @@ G_DEFINE_TYPE_WITH_CODE (ClutterStageEGL,
static void
clutter_stage_egl_unrealize (ClutterStageWindow *stage_window)
{
ClutterBackend *backend = clutter_get_default_backend ();
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (stage_window);
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
@ -41,7 +43,7 @@ clutter_stage_egl_unrealize (ClutterStageWindow *stage_window)
if (!stage_x11->is_foreign_xwin && stage_x11->xwin != None)
{
XDestroyWindow (stage_x11->xdpy, stage_x11->xwin);
XDestroyWindow (backend_x11->xdpy, stage_x11->xwin);
stage_x11->xwin = None;
}
else
@ -53,7 +55,7 @@ clutter_stage_egl_unrealize (ClutterStageWindow *stage_window)
stage_egl->egl_surface = EGL_NO_SURFACE;
}
XSync (stage_x11->xdpy, False);
XSync (backend_x11->xdpy, False);
clutter_x11_untrap_x_errors ();
}
@ -149,20 +151,20 @@ clutter_stage_egl_realize (ClutterStageWindow *stage_window)
if (stage_x11->xwin == None)
stage_x11->xwin =
XCreateSimpleWindow (stage_x11->xdpy,
stage_x11->xwin_root,
XCreateSimpleWindow (backend_x11->xdpy,
backend_x11->xwin_root,
0, 0,
stage_x11->xwin_width,
stage_x11->xwin_height,
0, 0,
WhitePixel (stage_x11->xdpy,
stage_x11->xscreen));
WhitePixel (backend_x11->xdpy,
backend_x11->xscreen_num));
if (clutter_x11_has_event_retrieval ())
{
if (clutter_x11_has_xinput ())
{
XSelectInput (stage_x11->xdpy, stage_x11->xwin,
XSelectInput (backend_x11->xdpy, stage_x11->xwin,
StructureNotifyMask |
FocusChangeMask |
ExposureMask |
@ -173,7 +175,7 @@ clutter_stage_egl_realize (ClutterStageWindow *stage_window)
#endif
}
else
XSelectInput (stage_x11->xdpy, stage_x11->xwin,
XSelectInput (backend_x11->xdpy, stage_x11->xwin,
StructureNotifyMask |
FocusChangeMask |
ExposureMask |

View File

@ -354,10 +354,14 @@ clutter_backend_glx_get_features (ClutterBackend *backend)
return flags;
}
static gboolean
clutter_backend_glx_get_fbconfig (ClutterBackendX11 *backend_x11,
GLXFBConfig *config)
/* It seems the GLX spec never defined an invalid GLXFBConfig that
* we could overload as an indication of error, so we have to return
* an explicit boolean status. */
gboolean
_clutter_backend_glx_get_fbconfig (ClutterBackendGLX *backend_glx,
GLXFBConfig *config)
{
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend_glx);
int attributes[] = {
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
GLX_RENDER_TYPE, GLX_RGBA_BIT,
@ -376,6 +380,12 @@ clutter_backend_glx_get_fbconfig (ClutterBackendX11 *backend_x11,
if (backend_x11->xdpy == None || backend_x11->xscreen == None)
return FALSE;
if (backend_glx->found_fbconfig)
{
*config = backend_glx->fbconfig;
return TRUE;
}
CLUTTER_NOTE (BACKEND,
"Retrieving GL fbconfig, dpy: %p, xscreen; %p (%d)",
backend_x11->xdpy,
@ -387,12 +397,13 @@ clutter_backend_glx_get_fbconfig (ClutterBackendX11 *backend_x11,
attributes,
&n_configs);
if (configs)
*config = configs[0];
XFree (configs);
if (configs)
return TRUE;
{
*config = configs[0];
backend_glx->found_fbconfig = TRUE;
backend_glx->fbconfig = configs[0];
XFree (configs);
return TRUE;
}
else
return FALSE;
}
@ -400,9 +411,10 @@ clutter_backend_glx_get_fbconfig (ClutterBackendX11 *backend_x11,
static XVisualInfo *
clutter_backend_glx_get_visual_info (ClutterBackendX11 *backend_x11)
{
ClutterBackendGLX *backend_glx = CLUTTER_BACKEND_GLX (backend_x11);
GLXFBConfig config;
if (!clutter_backend_glx_get_fbconfig (backend_x11, &config))
if (!_clutter_backend_glx_get_fbconfig (backend_glx, &config))
return NULL;
return glXGetVisualFromFBConfig (backend_x11->xdpy, config);
@ -420,7 +432,7 @@ clutter_backend_glx_create_context (ClutterBackend *backend,
GLXFBConfig config;
gboolean is_direct;
if (!clutter_backend_glx_get_fbconfig (backend_x11, &config))
if (!_clutter_backend_glx_get_fbconfig (backend_glx, &config))
{
g_set_error (error, CLUTTER_INIT_ERROR,
CLUTTER_INIT_ERROR_BACKEND,
@ -479,6 +491,7 @@ clutter_backend_glx_ensure_context (ClutterBackend *backend,
else
{
ClutterBackendGLX *backend_glx;
ClutterBackendX11 *backend_x11;
ClutterStageGLX *stage_glx;
ClutterStageX11 *stage_x11;
@ -491,6 +504,7 @@ clutter_backend_glx_ensure_context (ClutterBackend *backend,
stage_glx = CLUTTER_STAGE_GLX (impl);
stage_x11 = CLUTTER_STAGE_X11 (impl);
backend_glx = CLUTTER_BACKEND_GLX (backend);
backend_x11 = CLUTTER_BACKEND_X11 (backend);
/* no GL context to set */
if (backend_glx->gl_context == None)
@ -503,9 +517,6 @@ clutter_backend_glx_ensure_context (ClutterBackend *backend,
*/
if (stage_x11->xwin == None)
{
ClutterBackendX11 *backend_x11;
backend_x11 = CLUTTER_BACKEND_X11 (backend);
CLUTTER_NOTE (MULTISTAGE,
"Received a stale stage, clearing all context");
@ -515,12 +526,12 @@ clutter_backend_glx_ensure_context (ClutterBackend *backend,
{
CLUTTER_NOTE (BACKEND,
"MakeContextCurrent dpy: %p, window: 0x%x (%s), context: %p",
stage_x11->xdpy,
backend_x11->xdpy,
(int) stage_x11->xwin,
stage_x11->is_foreign_xwin ? "foreign" : "native",
backend_glx->gl_context);
glXMakeContextCurrent (stage_x11->xdpy,
glXMakeContextCurrent (backend_x11->xdpy,
stage_x11->xwin,
stage_x11->xwin,
backend_glx->gl_context);
@ -596,6 +607,7 @@ static void
clutter_backend_glx_redraw (ClutterBackend *backend,
ClutterStage *stage)
{
ClutterBackendX11 *backend_x11;
ClutterStageGLX *stage_glx;
ClutterStageX11 *stage_x11;
ClutterStageWindow *impl;
@ -609,6 +621,7 @@ clutter_backend_glx_redraw (ClutterBackend *backend,
g_assert (CLUTTER_IS_STAGE_GLX (impl));
backend_x11 = CLUTTER_BACKEND_X11 (backend);
stage_x11 = CLUTTER_STAGE_X11 (impl);
stage_glx = CLUTTER_STAGE_GLX (impl);
@ -624,9 +637,9 @@ clutter_backend_glx_redraw (ClutterBackend *backend,
/* push on the screen */
CLUTTER_NOTE (BACKEND, "glXSwapBuffers (display: %p, window: 0x%lx)",
stage_x11->xdpy,
backend_x11->xdpy,
(unsigned long) stage_x11->xwin);
glXSwapBuffers (stage_x11->xdpy, stage_x11->xwin);
glXSwapBuffers (backend_x11->xdpy, stage_x11->xwin);
}
}
@ -646,18 +659,14 @@ clutter_backend_glx_create_stage (ClutterBackend *backend,
/* copy backend data into the stage */
stage_x11 = CLUTTER_STAGE_X11 (stage_window);
stage_x11->xdpy = backend_x11->xdpy;
stage_x11->xwin_root = backend_x11->xwin_root;
stage_x11->xscreen = backend_x11->xscreen_num;
stage_x11->backend = backend_x11;
stage_x11->wrapper = wrapper;
CLUTTER_NOTE (BACKEND,
"GLX stage created[%p] (dpy:%p, screen:%d, root:%u, wrap:%p)",
stage_window,
stage_x11->xdpy,
stage_x11->xscreen,
(unsigned int) stage_x11->xwin_root,
backend_x11->xdpy,
backend_x11->xscreen_num,
(unsigned int) backend_x11->xwin_root,
wrapper);
return stage_window;

View File

@ -63,6 +63,8 @@ struct _ClutterBackendGLX
ClutterBackendX11 parent_instance;
/* Single context for all wins */
gboolean found_fbconfig;
GLXFBConfig fbconfig;
GLXContext gl_context;
/* Vblank stuff */
@ -84,6 +86,10 @@ struct _ClutterBackendGLXClass
GType clutter_backend_glx_get_type (void) G_GNUC_CONST;
gboolean
_clutter_backend_glx_get_fbconfig (ClutterBackendGLX *backend_x11,
GLXFBConfig *config);
G_END_DECLS
#endif /* __CLUTTER_BACKEND_GLX_H__ */

View File

@ -60,6 +60,8 @@ G_DEFINE_TYPE_WITH_CODE (ClutterStageGLX,
static void
clutter_stage_glx_unrealize (ClutterStageWindow *stage_window)
{
ClutterBackend *backend = clutter_get_default_backend ();
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
/* Note unrealize should free up any backend stage related resources */
@ -69,19 +71,13 @@ clutter_stage_glx_unrealize (ClutterStageWindow *stage_window)
if (!stage_x11->is_foreign_xwin && stage_x11->xwin != None)
{
XDestroyWindow (stage_x11->xdpy, stage_x11->xwin);
XDestroyWindow (backend_x11->xdpy, stage_x11->xwin);
stage_x11->xwin = None;
}
else
stage_x11->xwin = None;
if (stage_x11->xvisinfo != None)
{
XFree (stage_x11->xvisinfo);
stage_x11->xvisinfo = None;
}
XSync (stage_x11->xdpy, False);
XSync (backend_x11->xdpy, False);
clutter_x11_untrap_x_errors ();
@ -105,47 +101,55 @@ clutter_stage_glx_realize (ClutterStageWindow *stage_window)
backend_glx = CLUTTER_BACKEND_GLX (backend);
backend_x11 = CLUTTER_BACKEND_X11 (backend);
stage_x11->xvisinfo = clutter_backend_x11_get_visual_info (backend_x11);
if (stage_x11->xvisinfo == None)
{
g_critical ("Unable to find suitable GL visual.");
return FALSE;
}
if (stage_x11->xwin == None)
{
XSetWindowAttributes xattr;
unsigned long mask;
GLXFBConfig config;
XVisualInfo *xvisinfo;
CLUTTER_NOTE (MISC, "Creating stage X window");
if (!_clutter_backend_glx_get_fbconfig (backend_glx, &config))
{
g_critical ("Unable to find suitable FBConfig to realize stage.");
return FALSE;
}
xvisinfo = glXGetVisualFromFBConfig (backend_x11->xdpy, config);
if (xvisinfo == NULL)
{
g_critical ("Unable to find suitable GL visual.");
return FALSE;
}
/* window attributes */
xattr.background_pixel = WhitePixel (stage_x11->xdpy,
stage_x11->xscreen);
xattr.background_pixel = WhitePixel (backend_x11->xdpy,
backend_x11->xscreen_num);
xattr.border_pixel = 0;
xattr.colormap = XCreateColormap (stage_x11->xdpy,
stage_x11->xwin_root,
stage_x11->xvisinfo->visual,
xattr.colormap = XCreateColormap (backend_x11->xdpy,
backend_x11->xwin_root,
xvisinfo->visual,
AllocNone);
mask = CWBorderPixel | CWColormap;
stage_x11->xwin = XCreateWindow (stage_x11->xdpy,
stage_x11->xwin_root,
stage_x11->xwin = XCreateWindow (backend_x11->xdpy,
backend_x11->xwin_root,
0, 0,
stage_x11->xwin_width,
stage_x11->xwin_height,
0,
stage_x11->xvisinfo->depth,
xvisinfo->depth,
InputOutput,
stage_x11->xvisinfo->visual,
xvisinfo->visual,
mask, &xattr);
XFree (xvisinfo);
}
if (clutter_x11_has_event_retrieval())
{
if (clutter_x11_has_xinput())
{
XSelectInput (stage_x11->xdpy, stage_x11->xwin,
XSelectInput (backend_x11->xdpy, stage_x11->xwin,
StructureNotifyMask |
FocusChangeMask |
ExposureMask |
@ -157,7 +161,7 @@ clutter_stage_glx_realize (ClutterStageWindow *stage_window)
#endif
}
else
XSelectInput (stage_x11->xdpy, stage_x11->xwin,
XSelectInput (backend_x11->xdpy, stage_x11->xwin,
StructureNotifyMask |
FocusChangeMask |
ExposureMask |

View File

@ -993,3 +993,4 @@ clutter_backend_x11_get_visual_info (ClutterBackendX11 *backend_x11)
return NULL;
}

View File

@ -86,6 +86,11 @@ struct _ClutterBackendX11Class
{
ClutterBackendClass parent_class;
/*
* To support foreign stage windows the we need a way to ask for an
* XVisualInfo that may be used by toolkits to create an XWindow, and this
* may need to be handled differently for different backends.
*/
XVisualInfo *(* get_visual_info) (ClutterBackendX11 *backend);
};

View File

@ -91,8 +91,13 @@ clutter_stage_x11_fix_window_size (ClutterStageX11 *stage_x11,
gint new_width,
gint new_height)
{
ClutterBackend *backend = clutter_get_default_backend ();
ClutterBackendX11 *backend_x11;
gboolean resize;
g_return_if_fail (CLUTTER_IS_BACKEND_X11 (backend));
backend_x11 = CLUTTER_BACKEND_X11 (backend);
resize = clutter_stage_get_user_resizable (stage_x11->wrapper);
if (stage_x11->xwin != None && !stage_x11->is_foreign_xwin)
@ -134,7 +139,7 @@ clutter_stage_x11_fix_window_size (ClutterStageX11 *stage_x11,
}
}
XSetWMNormalHints (stage_x11->xdpy, stage_x11->xwin, size_hints);
XSetWMNormalHints (backend_x11->xdpy, stage_x11->xwin, size_hints);
XFree(size_hints);
}
@ -143,23 +148,32 @@ clutter_stage_x11_fix_window_size (ClutterStageX11 *stage_x11,
void
clutter_stage_x11_set_wm_protocols (ClutterStageX11 *stage_x11)
{
ClutterBackendX11 *backend_x11 = stage_x11->backend;
ClutterBackend *backend = clutter_get_default_backend ();
ClutterBackendX11 *backend_x11;
Atom protocols[2];
int n = 0;
g_return_if_fail (CLUTTER_IS_BACKEND_X11 (backend));
backend_x11 = CLUTTER_BACKEND_X11 (backend);
protocols[n++] = backend_x11->atom_WM_DELETE_WINDOW;
protocols[n++] = backend_x11->atom_NET_WM_PING;
XSetWMProtocols (stage_x11->xdpy, stage_x11->xwin, protocols, n);
XSetWMProtocols (backend_x11->xdpy, stage_x11->xwin, protocols, n);
}
static void
clutter_stage_x11_get_geometry (ClutterStageWindow *stage_window,
ClutterGeometry *geometry)
{
ClutterBackend *backend = clutter_get_default_backend ();
ClutterBackendX11 *backend_x11;
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
gboolean is_fullscreen, resize;
g_return_if_fail (CLUTTER_IS_BACKEND_X11 (backend));
backend_x11 = CLUTTER_BACKEND_X11 (backend);
is_fullscreen = FALSE;
g_object_get (G_OBJECT (stage_x11->wrapper),
"fullscreen-set", &is_fullscreen,
@ -167,8 +181,8 @@ clutter_stage_x11_get_geometry (ClutterStageWindow *stage_window,
if (is_fullscreen || stage_x11->fullscreen_on_map)
{
geometry->width = DisplayWidth (stage_x11->xdpy, stage_x11->xscreen);
geometry->height = DisplayHeight (stage_x11->xdpy, stage_x11->xscreen);
geometry->width = DisplayWidth (backend_x11->xdpy, backend_x11->xscreen_num);
geometry->height = DisplayHeight (backend_x11->xdpy, backend_x11->xscreen_num);
return;
}
@ -193,11 +207,16 @@ clutter_stage_x11_resize (ClutterStageWindow *stage_window,
gint width,
gint height)
{
ClutterBackend *backend = clutter_get_default_backend ();
ClutterBackendX11 *backend_x11;
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
gboolean resize;
resize = clutter_stage_get_user_resizable (stage_x11->wrapper);
g_return_if_fail (CLUTTER_IS_BACKEND_X11 (backend));
backend_x11 = CLUTTER_BACKEND_X11 (backend);
if (width == 0 || height == 0)
{
/* Should not happen, if this turns up we need to debug it and
@ -227,7 +246,7 @@ clutter_stage_x11_resize (ClutterStageWindow *stage_window,
CLUTTER_SET_PRIVATE_FLAGS (stage_x11->wrapper,
CLUTTER_STAGE_IN_RESIZE);
XResizeWindow (stage_x11->xdpy,
XResizeWindow (backend_x11->xdpy,
stage_x11->xwin,
stage_x11->xwin_width,
stage_x11->xwin_height);
@ -235,35 +254,28 @@ clutter_stage_x11_resize (ClutterStageWindow *stage_window,
if (!resize)
clutter_stage_x11_fix_window_size (stage_x11, width, height);
if (stage_x11->xpixmap != None)
{
/* Need to recreate to resize */
_clutter_actor_rerealize (CLUTTER_ACTOR (stage_x11->wrapper),
NULL,
NULL);
}
}
}
static inline void
set_wm_pid (ClutterStageX11 *stage_x11)
{
ClutterBackendX11 *backend_x11 = stage_x11->backend;
ClutterBackend *backend = clutter_get_default_backend ();
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
long pid;
if (stage_x11->xwin == None)
return;
/* this will take care of WM_CLIENT_MACHINE and WM_LOCALE_NAME */
XSetWMProperties (stage_x11->xdpy, stage_x11->xwin,
XSetWMProperties (backend_x11->xdpy, stage_x11->xwin,
NULL,
NULL,
NULL, 0,
NULL, NULL, NULL);
pid = getpid();
XChangeProperty (stage_x11->xdpy,
XChangeProperty (backend_x11->xdpy,
stage_x11->xwin,
backend_x11->atom_NET_WM_PID, XA_CARDINAL, 32,
PropModeReplace,
@ -273,26 +285,30 @@ set_wm_pid (ClutterStageX11 *stage_x11)
static inline void
set_wm_title (ClutterStageX11 *stage_x11)
{
ClutterBackendX11 *backend_x11 = stage_x11->backend;
ClutterBackend *backend = clutter_get_default_backend ();
ClutterBackendX11 *backend_x11;
g_return_if_fail (CLUTTER_IS_BACKEND_X11 (backend));
backend_x11 = CLUTTER_BACKEND_X11 (backend);
if (stage_x11->xwin == None)
return;
if (stage_x11->title == NULL)
{
XDeleteProperty (stage_x11->xdpy,
XDeleteProperty (backend_x11->xdpy,
stage_x11->xwin,
backend_x11->atom_NET_WM_NAME);
}
else
{
XChangeProperty (stage_x11->xdpy,
XChangeProperty (backend_x11->xdpy,
stage_x11->xwin,
backend_x11->atom_NET_WM_NAME,
backend_x11->atom_UTF8_STRING,
backend_x11->atom_NET_WM_NAME,
backend_x11->atom_UTF8_STRING,
8,
PropModeReplace,
(unsigned char *) stage_x11->title,
(unsigned char *) stage_x11->title,
(int) strlen (stage_x11->title));
}
}
@ -300,6 +316,12 @@ set_wm_title (ClutterStageX11 *stage_x11)
static inline void
set_cursor_visible (ClutterStageX11 *stage_x11)
{
ClutterBackend *backend = clutter_get_default_backend ();
ClutterBackendX11 *backend_x11;
g_return_if_fail (CLUTTER_IS_BACKEND_X11 (backend));
backend_x11 = CLUTTER_BACKEND_X11 (backend);
if (stage_x11->xwin == None)
return;
@ -310,9 +332,9 @@ set_cursor_visible (ClutterStageX11 *stage_x11)
if (stage_x11->is_cursor_visible)
{
#if 0 /* HAVE_XFIXES - seems buggy/unreliable */
XFixesShowCursor (stage_x11->xdpy, stage_x11->xwin);
XFixesShowCursor (backend_x11->xdpy, stage_x11->xwin);
#else
XUndefineCursor (stage_x11->xdpy, stage_x11->xwin);
XUndefineCursor (backend_x11->xdpy, stage_x11->xwin);
#endif /* HAVE_XFIXES */
}
else
@ -320,20 +342,20 @@ set_cursor_visible (ClutterStageX11 *stage_x11)
#if 0 /* HAVE_XFIXES - seems buggy/unreliable, check cursor in firefox
* loading page after hiding.
*/
XFixesHideCursor (stage_x11->xdpy, stage_x11->xwin);
XFixesHideCursor (backend_x11->xdpy, stage_x11->xwin);
#else
XColor col;
Pixmap pix;
Cursor curs;
pix = XCreatePixmap (stage_x11->xdpy, stage_x11->xwin, 1, 1, 1);
pix = XCreatePixmap (backend_x11->xdpy, stage_x11->xwin, 1, 1, 1);
memset (&col, 0, sizeof (col));
curs = XCreatePixmapCursor (stage_x11->xdpy,
curs = XCreatePixmapCursor (backend_x11->xdpy,
pix, pix,
&col, &col,
1, 1);
XFreePixmap (stage_x11->xdpy, pix);
XDefineCursor (stage_x11->xdpy, stage_x11->xwin, curs);
XFreePixmap (backend_x11->xdpy, pix);
XDefineCursor (backend_x11->xdpy, stage_x11->xwin, curs);
#endif /* HAVE_XFIXES */
}
}
@ -354,10 +376,14 @@ static void
clutter_stage_x11_set_fullscreen (ClutterStageWindow *stage_window,
gboolean is_fullscreen)
{
ClutterBackend *backend = clutter_get_default_backend ();
ClutterBackendX11 *backend_x11;
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
ClutterBackendX11 *backend_x11 = stage_x11->backend;
ClutterStage *stage = stage_x11->wrapper;
g_return_if_fail (CLUTTER_IS_BACKEND_X11 (backend));
backend_x11 = CLUTTER_BACKEND_X11 (backend);
if (stage == NULL)
return;
@ -372,8 +398,8 @@ clutter_stage_x11_set_fullscreen (ClutterStageWindow *stage_window,
but Metacity (at least) will fullscreen to only one of the
displays. This will cause the actor to report the wrong size
until the ConfigureNotify for the correct size is received */
width = DisplayWidth (stage_x11->xdpy, stage_x11->xscreen);
height = DisplayHeight (stage_x11->xdpy, stage_x11->xscreen);
width = DisplayWidth (backend_x11->xdpy, backend_x11->xscreen_num);
height = DisplayHeight (backend_x11->xdpy, backend_x11->xscreen_num);
/* we force the stage to the screen size here, in order to
* get the fullscreen stage size right after the call to
@ -397,7 +423,7 @@ clutter_stage_x11_set_fullscreen (ClutterStageWindow *stage_window,
if (!CLUTTER_ACTOR_IS_MAPPED (stage_x11))
{
/* FIXME: This wont work if we support more states */
XChangeProperty (stage_x11->xdpy,
XChangeProperty (backend_x11->xdpy,
stage_x11->xwin,
backend_x11->atom_NET_WM_STATE, XA_ATOM, 32,
PropModeReplace,
@ -427,7 +453,7 @@ clutter_stage_x11_set_fullscreen (ClutterStageWindow *stage_window,
if (!CLUTTER_ACTOR_IS_MAPPED (stage_x11))
{
/* FIXME: This wont work if we support more states */
XDeleteProperty (stage_x11->xdpy,
XDeleteProperty (backend_x11->xdpy,
stage_x11->xwin,
backend_x11->atom_NET_WM_STATE);
}
@ -482,15 +508,20 @@ clutter_stage_x11_set_user_resizable (ClutterStageWindow *stage_window,
static void
update_wm_hints (ClutterStageX11 *stage_x11)
{
ClutterBackend *backend = clutter_get_default_backend ();
ClutterBackendX11 *backend_x11;
XWMHints wm_hints;
g_return_if_fail (CLUTTER_IS_BACKEND_X11 (backend));
backend_x11 = CLUTTER_BACKEND_X11 (backend);
if (stage_x11->wm_state & STAGE_X11_WITHDRAWN)
return;
wm_hints.flags = StateHint;
wm_hints.initial_state = NormalState;
XSetWMHints (stage_x11->xdpy, stage_x11->xwin, &wm_hints);
XSetWMHints (backend_x11->xdpy, stage_x11->xwin, &wm_hints);
}
static void
@ -516,15 +547,20 @@ static void
clutter_stage_x11_show (ClutterStageWindow *stage_window,
gboolean do_raise)
{
ClutterBackend *backend = clutter_get_default_backend ();
ClutterBackendX11 *backend_x11;
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
g_return_if_fail (CLUTTER_IS_BACKEND_X11 (backend));
backend_x11 = CLUTTER_BACKEND_X11 (backend);
if (stage_x11->xwin != None)
{
if (do_raise)
{
CLUTTER_NOTE (BACKEND, "Raising stage[%lu]",
(unsigned long) stage_x11->xwin);
XRaiseWindow (stage_x11->xdpy, stage_x11->xwin);
XRaiseWindow (backend_x11->xdpy, stage_x11->xwin);
}
if (!STAGE_X11_IS_MAPPED (stage_x11))
@ -546,15 +582,20 @@ clutter_stage_x11_show (ClutterStageWindow *stage_window,
clutter_actor_map (CLUTTER_ACTOR (stage_x11->wrapper));
XMapWindow (stage_x11->xdpy, stage_x11->xwin);
XMapWindow (backend_x11->xdpy, stage_x11->xwin);
}
}
static void
clutter_stage_x11_hide (ClutterStageWindow *stage_window)
{
ClutterBackend *backend = clutter_get_default_backend ();
ClutterBackendX11 *backend_x11;
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
g_return_if_fail (CLUTTER_IS_BACKEND_X11 (backend));
backend_x11 = CLUTTER_BACKEND_X11 (backend);
if (stage_x11->xwin != None)
{
if (STAGE_X11_IS_MAPPED (stage_x11))
@ -564,7 +605,7 @@ clutter_stage_x11_hide (ClutterStageWindow *stage_window)
clutter_actor_unmap (CLUTTER_ACTOR (stage_x11->wrapper));
XWithdrawWindow (stage_x11->xdpy,
XWithdrawWindow (backend_x11->xdpy,
stage_x11->xwin,
0);
}
@ -604,14 +645,9 @@ clutter_stage_x11_class_init (ClutterStageX11Class *klass)
static void
clutter_stage_x11_init (ClutterStageX11 *stage)
{
stage->xdpy = NULL;
stage->xwin_root = None;
stage->xscreen = 0;
stage->xwin = None;
stage->xwin_width = 640;
stage->xwin_height = 480;
stage->xvisinfo = None;
stage->wm_state = STAGE_X11_WITHDRAWN;
@ -645,7 +681,7 @@ clutter_stage_window_iface_init (ClutterStageWindowIface *iface)
* clutter_x11_get_stage_window:
* @stage: a #ClutterStage
*
* Gets the stages X Window.
* Gets the stages X Window.
*
* Return value: An XID for the stage window.
*
@ -703,34 +739,29 @@ clutter_x11_get_stage_from_window (Window win)
* clutter_x11_get_stage_visual:
* @stage: a #ClutterStage
*
* Returns the stage XVisualInfo
* Returns an XVisualInfo suitable for creating a foreign window for the given
* stage. NOTE: It doesn't do as the name may suggest, which is return the
* XVisualInfo that was used to create an existing window for the given stage.
*
* Return value: The XVisualInfo for the stage.
* XXX: It might be best to deprecate this function and replace with something
* along the lines of clutter_backend_x11_get_foreign_visual () or perhaps
* clutter_stage_x11_get_foreign_visual ()
*
* Return value: An XVisualInfo suitable for creating a foreign stage.
* You should free this using XFree.
*
* Since: 0.4
*/
XVisualInfo *
clutter_x11_get_stage_visual (ClutterStage *stage)
{
ClutterStageWindow *impl;
ClutterStageX11 *stage_x11;
ClutterBackend *backend = clutter_get_default_backend ();
ClutterBackendX11 *backend_x11;
g_return_val_if_fail (CLUTTER_IS_STAGE (stage), NULL);
g_return_val_if_fail (CLUTTER_IS_BACKEND_X11 (backend), NULL);
backend_x11 = CLUTTER_BACKEND_X11 (backend);
impl = _clutter_stage_get_window (stage);
g_assert (CLUTTER_IS_STAGE_X11 (impl));
stage_x11 = CLUTTER_STAGE_X11 (impl);
if (stage_x11->xvisinfo == NULL)
{
ClutterBackendX11 *backend_x11 = stage_x11->backend;
stage_x11->xvisinfo =
clutter_backend_x11_get_visual_info (backend_x11);
}
return stage_x11->xvisinfo;
return clutter_backend_x11_get_visual_info (backend_x11);
}
typedef struct {
@ -745,6 +776,8 @@ set_foreign_window_callback (ClutterActor *actor,
void *data)
{
ForeignWindowData *fwd = data;
ClutterBackend *backend = clutter_get_default_backend ();
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
CLUTTER_NOTE (BACKEND, "Setting foreign window (0x%x)",
(unsigned int) fwd->xwindow);
@ -753,7 +786,7 @@ set_foreign_window_callback (ClutterActor *actor,
{
CLUTTER_NOTE (BACKEND, "Destroying previous window (0x%x)",
(unsigned int) fwd->xwindow);
XDestroyWindow (fwd->stage_x11->xdpy, fwd->stage_x11->xwin);
XDestroyWindow (backend_x11->xdpy, fwd->stage_x11->xwin);
}
fwd->stage_x11->xwin = fwd->xwindow;
@ -786,6 +819,8 @@ gboolean
clutter_x11_set_stage_foreign (ClutterStage *stage,
Window xwindow)
{
ClutterBackend *backend = clutter_get_default_backend ();
ClutterBackendX11 *backend_x11;
ClutterStageX11 *stage_x11;
ClutterStageWindow *impl;
ClutterActor *actor;
@ -794,6 +829,10 @@ clutter_x11_set_stage_foreign (ClutterStage *stage,
Window root_return;
Status status;
ForeignWindowData fwd;
XVisualInfo *xvisinfo;
g_return_val_if_fail (CLUTTER_IS_BACKEND_X11 (backend), FALSE);
backend_x11 = CLUTTER_BACKEND_X11 (backend);
g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE);
g_return_val_if_fail (xwindow != None, FALSE);
@ -803,19 +842,21 @@ clutter_x11_set_stage_foreign (ClutterStage *stage,
impl = _clutter_stage_get_window (stage);
stage_x11 = CLUTTER_STAGE_X11 (impl);
xvisinfo = clutter_backend_x11_get_visual_info (backend_x11);
clutter_x11_trap_x_errors ();
status = XGetGeometry (stage_x11->xdpy, xwindow,
status = XGetGeometry (backend_x11->xdpy, xwindow,
&root_return,
&x, &y,
&width, &height,
&border,
&depth);
if (clutter_x11_untrap_x_errors () ||
!status ||
width == 0 || height == 0 ||
depth != stage_x11->xvisinfo->depth)
depth != xvisinfo->depth)
{
g_warning ("Unable to retrieve the new window geometry");
return FALSE;

View File

@ -54,17 +54,11 @@ struct _ClutterStageX11
guint fullscreen_on_map : 1;
guint is_cursor_visible : 1;
Display *xdpy;
Window xwin_root;
int xscreen;
XVisualInfo *xvisinfo;
Window xwin;
Window xwin;
gint xwin_width;
gint xwin_height; /* FIXME target_width / height */
Pixmap xpixmap;
gchar *title;
ClutterBackendX11 *backend;
ClutterStageState state;
ClutterStageX11State wm_state;