From 3187e1964279b3fb93703fe6c67df5b6025729c9 Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Mon, 3 Aug 2009 14:50:10 +0100 Subject: [PATCH] [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. --- clutter/eglx/clutter-backend-egl.c | 10 +- clutter/eglx/clutter-stage-egl.c | 18 +-- clutter/glx/clutter-backend-glx.c | 59 ++++++---- clutter/glx/clutter-backend-glx.h | 6 + clutter/glx/clutter-stage-glx.c | 58 +++++----- clutter/x11/clutter-backend-x11.c | 1 + clutter/x11/clutter-backend-x11.h | 5 + clutter/x11/clutter-stage-x11.c | 177 ++++++++++++++++++----------- clutter/x11/clutter-stage-x11.h | 8 +- 9 files changed, 200 insertions(+), 142 deletions(-) diff --git a/clutter/eglx/clutter-backend-egl.c b/clutter/eglx/clutter-backend-egl.c index a95c2930d..cfae3fc51 100644 --- a/clutter/eglx/clutter-backend-egl.c +++ b/clutter/eglx/clutter-backend-egl.c @@ -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; } diff --git a/clutter/eglx/clutter-stage-egl.c b/clutter/eglx/clutter-stage-egl.c index 772403ef8..d4ac583a8 100644 --- a/clutter/eglx/clutter-stage-egl.c +++ b/clutter/eglx/clutter-stage-egl.c @@ -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 | diff --git a/clutter/glx/clutter-backend-glx.c b/clutter/glx/clutter-backend-glx.c index 0ffc57867..8870037b3 100644 --- a/clutter/glx/clutter-backend-glx.c +++ b/clutter/glx/clutter-backend-glx.c @@ -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; diff --git a/clutter/glx/clutter-backend-glx.h b/clutter/glx/clutter-backend-glx.h index df93f979e..2bd380813 100644 --- a/clutter/glx/clutter-backend-glx.h +++ b/clutter/glx/clutter-backend-glx.h @@ -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__ */ diff --git a/clutter/glx/clutter-stage-glx.c b/clutter/glx/clutter-stage-glx.c index f3aca4d40..9c1105b2e 100644 --- a/clutter/glx/clutter-stage-glx.c +++ b/clutter/glx/clutter-stage-glx.c @@ -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 | diff --git a/clutter/x11/clutter-backend-x11.c b/clutter/x11/clutter-backend-x11.c index 73fa18f17..ae6ff824c 100644 --- a/clutter/x11/clutter-backend-x11.c +++ b/clutter/x11/clutter-backend-x11.c @@ -993,3 +993,4 @@ clutter_backend_x11_get_visual_info (ClutterBackendX11 *backend_x11) return NULL; } + diff --git a/clutter/x11/clutter-backend-x11.h b/clutter/x11/clutter-backend-x11.h index b44007afc..0958eb4cf 100644 --- a/clutter/x11/clutter-backend-x11.h +++ b/clutter/x11/clutter-backend-x11.h @@ -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); }; diff --git a/clutter/x11/clutter-stage-x11.c b/clutter/x11/clutter-stage-x11.c index 376beb3b3..074595f9f 100644 --- a/clutter/x11/clutter-stage-x11.c +++ b/clutter/x11/clutter-stage-x11.c @@ -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; diff --git a/clutter/x11/clutter-stage-x11.h b/clutter/x11/clutter-stage-x11.h index 7c71e48c7..0929094bc 100644 --- a/clutter/x11/clutter-stage-x11.h +++ b/clutter/x11/clutter-stage-x11.h @@ -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;