static Window get_output_window (MetaScreen *screen) { MetaDisplay *display = meta_screen_get_display (screen); Display *xdisplay = meta_display_get_xdisplay (display); Window output, xroot; XWindowAttributes attr; long event_mask; xroot = meta_screen_get_xroot (screen); event_mask = FocusChangeMask | ExposureMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask | PropertyChangeMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask; output = XCompositeGetOverlayWindow (xdisplay, xroot); if (XGetWindowAttributes (xdisplay, output, &attr)) { event_mask |= attr.your_event_mask; } XSelectInput (xdisplay, output, event_mask); return output; }
static void detach_pixmap (MetaSurfaceActorX11 *self) { MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); MetaDisplay *display = priv->display; Display *xdisplay = meta_display_get_xdisplay (display); MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self)); if (priv->pixmap == None) return; /* Get rid of all references to the pixmap before freeing it; it's unclear whether * you are supposed to be able to free a GLXPixmap after freeing the underlying * pixmap, but it certainly doesn't work with current DRI/Mesa */ meta_shaped_texture_set_texture (stex, NULL); cogl_flush (); meta_error_trap_push (display); XFreePixmap (xdisplay, priv->pixmap); priv->pixmap = None; meta_error_trap_pop (display); cogl_object_unref (priv->texture); priv->texture = NULL; }
void meta_compositor_sync_screen_size (MetaCompositor *compositor, MetaScreen *screen, guint width, guint height) { MetaDisplay *display = meta_screen_get_display (screen); MetaCompScreen *info = meta_screen_get_compositor_data (screen); Display *xdisplay; Window xwin; DEBUG_TRACE ("meta_compositor_sync_screen_size\n"); g_return_if_fail (info); xdisplay = meta_display_get_xdisplay (display); xwin = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage)); XResizeWindow (xdisplay, xwin, width, height); meta_background_actor_screen_size_changed (screen); meta_verbose ("Changed size for stage on screen %d to %dx%d\n", meta_screen_get_screen_number (screen), width, height); }
void meta_set_stage_input_region (MetaScreen *screen, XserverRegion region) { MetaCompScreen *info = meta_screen_get_compositor_data (screen); MetaDisplay *display = meta_screen_get_display (screen); Display *xdpy = meta_display_get_xdisplay (display); if (info->stage && info->output) { do_set_stage_input_region (screen, region); } else { /* Reset info->pending_input_region if one existed before and set the new * one to use it later. */ if (info->pending_input_region) { XFixesDestroyRegion (xdpy, info->pending_input_region); info->pending_input_region = None; } if (region != None) { info->pending_input_region = XFixesCreateRegion (xdpy, NULL, 0); XFixesCopyRegion (xdpy, info->pending_input_region, region); } } }
void meta_set_stage_input_region (MetaScreen *screen, XserverRegion region) { /* As a wayland compositor we can simply ignore all this trickery * for setting an input region on the stage for capturing events in * clutter since all input comes to us first and we get to choose * who else sees them. */ if (!meta_is_wayland_compositor ()) { MetaDisplay *display = screen->display; MetaCompositor *compositor = display->compositor; Display *xdpy = meta_display_get_xdisplay (display); Window xstage = clutter_x11_get_stage_window (CLUTTER_STAGE (compositor->stage)); XFixesSetWindowShapeRegion (xdpy, xstage, ShapeInput, 0, 0, region); /* It's generally a good heuristic that when a crossing event is generated because * we reshape the overlay, we don't want it to affect focus-follows-mouse focus - * it's not the user doing something, it's the environment changing under the user. */ meta_display_add_ignored_crossing_serial (display, XNextRequest (xdpy)); XFixesSetWindowShapeRegion (xdpy, compositor->output, ShapeInput, 0, 0, region); } }
/** * shell_global_grab_keyboard: * @global: a #ShellGlobal * * Grab the keyboard to the stage window. The stage will receive * all keyboard events until shell_global_ungrab_keyboard() is called. * This is appropriate to do when the desktop goes into a special * mode where no normal global key shortcuts or application keyboard * processing should happen. */ gboolean shell_global_grab_keyboard (ShellGlobal *global) { MetaScreen *screen = mutter_plugin_get_screen (global->plugin); MetaDisplay *display = meta_screen_get_display (screen); Display *xdisplay = meta_display_get_xdisplay (display); ClutterStage *stage = CLUTTER_STAGE (mutter_plugin_get_stage (global->plugin)); Window stagewin = clutter_x11_get_stage_window (stage); /* FIXME: we need to coordinate with the rest of Metacity or we * may grab the keyboard away from other portions of Metacity * and leave Metacity in a confused state. An X client is allowed * to overgrab itself, though not allowed to grab they keyboard * away from another applications. */ if (global->keyboard_grabbed) return FALSE; if (XGrabKeyboard (xdisplay, stagewin, False, /* owner_events - steal events from the rest of metacity */ GrabModeAsync, GrabModeAsync, CurrentTime) != Success) return FALSE; /* probably AlreadyGrabbed, some other app has a keyboard grab */ global->keyboard_grabbed = TRUE; return TRUE; }
static void create_damage (MetaSurfaceActorX11 *self) { MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); Display *xdisplay = meta_display_get_xdisplay (priv->display); Window xwindow = meta_window_x11_get_toplevel_xwindow (priv->window); priv->damage = XDamageCreate (xdisplay, xwindow, XDamageReportBoundingBox); }
void meta_compositor_unmanage_screen (MetaCompositor *compositor, MetaScreen *screen) { MetaDisplay *display = meta_screen_get_display (screen); Display *xdisplay = meta_display_get_xdisplay (display); Window xroot = meta_screen_get_xroot (screen); /* This is the most important part of cleanup - we have to do this * before giving up the window manager selection or the next * window manager won't be able to redirect subwindows */ XCompositeUnredirectSubwindows (xdisplay, xroot, CompositeRedirectManual); }
static void free_damage (MetaSurfaceActorX11 *self) { MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); MetaDisplay *display = priv->display; Display *xdisplay = meta_display_get_xdisplay (display); if (priv->damage == None) return; meta_error_trap_push (display); XDamageDestroy (xdisplay, priv->damage); priv->damage = None; meta_error_trap_pop (display); }
void meta_compositor_unmanage (MetaCompositor *compositor) { if (!meta_is_wayland_compositor ()) { MetaDisplay *display = compositor->display; Display *xdisplay = meta_display_get_xdisplay (display); Window xroot = display->screen->xroot; /* This is the most important part of cleanup - we have to do this * before giving up the window manager selection or the next * window manager won't be able to redirect subwindows */ XCompositeUnredirectSubwindows (xdisplay, xroot, CompositeRedirectManual); } }
void meta_empty_stage_input_region (MetaScreen *screen) { /* Using a static region here is a bit hacky, but Metacity never opens more than * one XDisplay, so it works fine. */ static XserverRegion region = None; if (region == None) { MetaDisplay *display = meta_screen_get_display (screen); Display *xdpy = meta_display_get_xdisplay (display); region = XFixesCreateRegion (xdpy, NULL, 0); } meta_set_stage_input_region (screen, region); }
/** * shell_global_ungrab_keyboard: * @global: a #ShellGlobal * * Undoes the effect of shell_global_grab_keyboard */ void shell_global_ungrab_keyboard (ShellGlobal *global) { MetaScreen *screen; MetaDisplay *display; Display *xdisplay; g_return_if_fail (global->keyboard_grabbed); screen = mutter_plugin_get_screen (global->plugin); display = meta_screen_get_display (screen); xdisplay = meta_display_get_xdisplay (display); XUngrabKeyboard (xdisplay, CurrentTime); global->keyboard_grabbed = FALSE; }
static void do_set_stage_input_region (MetaScreen *screen, XserverRegion region) { MetaCompScreen *info = meta_screen_get_compositor_data (screen); MetaDisplay *display = meta_screen_get_display (screen); Display *xdpy = meta_display_get_xdisplay (display); Window xstage = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage)); XFixesSetWindowShapeRegion (xdpy, xstage, ShapeInput, 0, 0, region); /* It's generally a good heuristic that when a crossing event is generated because * we reshape the overlay, we don't want it to affect focus-follows-mouse focus - * it's not the user doing something, it's the environment changing under the user. */ meta_display_add_ignored_crossing_serial (display, XNextRequest (xdpy)); XFixesSetWindowShapeRegion (xdpy, info->output, ShapeInput, 0, 0, region); }
static void update_pixmap (MetaSurfaceActorX11 *self) { MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); MetaDisplay *display = priv->display; Display *xdisplay = meta_display_get_xdisplay (display); if (priv->size_changed) { detach_pixmap (self); priv->size_changed = FALSE; } if (priv->pixmap == None) { Pixmap new_pixmap; Window xwindow = meta_window_x11_get_toplevel_xwindow (priv->window); meta_error_trap_push (display); new_pixmap = XCompositeNameWindowPixmap (xdisplay, xwindow); if (meta_error_trap_pop_with_return (display) != Success) { /* Probably a BadMatch if the window isn't viewable; we could * GrabServer/GetWindowAttributes/NameWindowPixmap/UngrabServer/Sync * to avoid this, but there's no reason to take two round trips * when one will do. (We need that Sync if we want to handle failures * for any reason other than !viewable. That's unlikely, but maybe * we'll BadAlloc or something.) */ new_pixmap = None; } if (new_pixmap == None) { meta_verbose ("Unable to get named pixmap for %s\n", meta_window_get_description (priv->window)); return; } set_pixmap (self, new_pixmap); } }
static void meta_surface_actor_x11_pre_paint (MetaSurfaceActor *actor) { MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor); MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); MetaDisplay *display = priv->display; Display *xdisplay = meta_display_get_xdisplay (display); if (priv->received_damage) { meta_error_trap_push (display); XDamageSubtract (xdisplay, priv->damage, None, None); meta_error_trap_pop (display); priv->received_damage = FALSE; } update_pixmap (self); }
static void redirect_windows (MetaScreen *screen) { MetaDisplay *display = meta_screen_get_display (screen); Display *xdisplay = meta_display_get_xdisplay (display); Window xroot = meta_screen_get_xroot (screen); int screen_number = meta_screen_get_screen_number (screen); guint n_retries; guint max_retries; if (meta_get_replace_current_wm ()) max_retries = 5; else max_retries = 1; n_retries = 0; /* Some compositors (like old versions of Mutter) might not properly unredirect * subwindows before destroying the WM selection window; so we wait a while * for such a compositor to exit before giving up. */ while (TRUE) { meta_error_trap_push (display); XCompositeRedirectSubwindows (xdisplay, xroot, CompositeRedirectManual); XSync (xdisplay, FALSE); if (!meta_error_trap_pop_with_return (display)) break; if (n_retries == max_retries) { /* This probably means that a non-WM compositor like xcompmgr is running; * we have no way to get it to exit */ meta_fatal (_("Another compositing manager is already running on screen %i on display \"%s\"."), screen_number, display->name); } n_retries++; g_usleep (G_USEC_PER_SEC); } }
/** * meta_compositor_new: (skip) * */ MetaCompositor * meta_compositor_new (MetaDisplay *display) { char *atom_names[] = { "_XROOTPMAP_ID", "_XSETROOT_ID", "_NET_WM_WINDOW_OPACITY", }; Atom atoms[G_N_ELEMENTS(atom_names)]; MetaCompositor *compositor; Display *xdisplay = meta_display_get_xdisplay (display); if (!composite_at_least_version (display, 0, 3)) return NULL; compositor = g_new0 (MetaCompositor, 1); compositor->display = display; if (g_getenv("META_DISABLE_MIPMAPS")) compositor->no_mipmaps = TRUE; meta_verbose ("Creating %d atoms\n", (int) G_N_ELEMENTS (atom_names)); XInternAtoms (xdisplay, atom_names, G_N_ELEMENTS (atom_names), False, atoms); g_signal_connect (meta_shadow_factory_get_default (), "changed", G_CALLBACK (on_shadow_factory_changed), compositor); compositor->atom_x_root_pixmap = atoms[0]; compositor->atom_x_set_root = atoms[1]; compositor->atom_net_wm_window_opacity = atoms[2]; compositor->repaint_func_id = clutter_threads_add_repaint_func (meta_repaint_func, compositor, NULL); return compositor; }
LOCAL_SYMBOL void meta_end_modal_for_plugin (MetaScreen *screen, MetaPlugin *plugin, guint32 timestamp) { MetaDisplay *display = meta_screen_get_display (screen); Display *xdpy = meta_display_get_xdisplay (display); MetaCompositor *compositor = display->compositor; g_return_if_fail (compositor->modal_plugin == plugin); XUngrabPointer (xdpy, timestamp); XUngrabKeyboard (xdpy, timestamp); display->grab_op = META_GRAB_OP_NONE; display->grab_window = NULL; display->grab_screen = NULL; display->grab_have_pointer = FALSE; display->grab_have_keyboard = FALSE; compositor->modal_plugin = NULL; }
static void sync_unredirected (MetaSurfaceActorX11 *self) { MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); MetaDisplay *display = priv->display; Display *xdisplay = meta_display_get_xdisplay (display); Window xwindow = meta_window_x11_get_toplevel_xwindow (priv->window); meta_error_trap_push (display); if (priv->unredirected) { detach_pixmap (self); XCompositeUnredirectWindow (xdisplay, xwindow, CompositeRedirectManual); } else { XCompositeRedirectWindow (xdisplay, xwindow, CompositeRedirectManual); } meta_error_trap_pop (display); }
/* * Shapes the cow so that the given window is exposed, * when metaWindow is NULL it clears the shape again */ static void meta_shape_cow_for_window (MetaScreen *screen, MetaWindow *metaWindow) { MetaCompScreen *info = meta_screen_get_compositor_data (screen); Display *xdisplay = meta_display_get_xdisplay (meta_screen_get_display (screen)); if (metaWindow == NULL) XFixesSetWindowShapeRegion (xdisplay, info->output, ShapeBounding, 0, 0, None); else { XserverRegion output_region; XRectangle screen_rect, window_bounds; int width, height; MetaRectangle rect; meta_window_get_outer_rect (metaWindow, &rect); window_bounds.x = rect.x; window_bounds.y = rect.y; window_bounds.width = rect.width; window_bounds.height = rect.height; meta_screen_get_size (screen, &width, &height); screen_rect.x = 0; screen_rect.y = 0; screen_rect.width = width; screen_rect.height = height; output_region = XFixesCreateRegion (xdisplay, &window_bounds, 1); XFixesInvertRegion (xdisplay, output_region, &screen_rect, output_region); XFixesSetWindowShapeRegion (xdisplay, info->output, ShapeBounding, 0, 0, output_region); XFixesDestroyRegion (xdisplay, output_region); } }
/** * shell_global_set_stage_input_region: * @global: the #ShellGlobal * @rectangles: (element-type Meta.Rectangle): a list of #MetaRectangle * describing the input region. * * Sets the area of the stage that is responsive to mouse clicks when * the stage mode is %SHELL_STAGE_INPUT_MODE_NORMAL (but does not change the * current stage mode). */ void shell_global_set_stage_input_region (ShellGlobal *global, GSList *rectangles) { MetaScreen *screen = mutter_plugin_get_screen (global->plugin); MetaDisplay *display = meta_screen_get_display (screen); Display *xdpy = meta_display_get_xdisplay (display); MetaRectangle *rect; XRectangle *rects; int nrects, i; GSList *r; g_return_if_fail (SHELL_IS_GLOBAL (global)); nrects = g_slist_length (rectangles); rects = g_new (XRectangle, nrects); for (r = rectangles, i = 0; r; r = r->next, i++) { rect = (MetaRectangle *)r->data; rects[i].x = rect->x; rects[i].y = rect->y; rects[i].width = rect->width; rects[i].height = rect->height; } if (global->input_region) XFixesDestroyRegion (xdpy, global->input_region); global->input_region = XFixesCreateRegion (xdpy, rects, nrects); g_free (rects); /* set_stage_input_mode() will figure out whether or not we * should actually change the input region right now. */ shell_global_set_stage_input_mode (global, global->input_mode); }
/** * meta_shape_cow_for_window: * @compositor: A #MetaCompositor * @window: (nullable): A #MetaWindow to shape the COW for * * Sets an bounding shape on the COW so that the given window * is exposed. If @window is %NULL it clears the shape again. * * Used so we can unredirect windows, by shaping away the part * of the COW, letting the raw window be seen through below. */ static void meta_shape_cow_for_window (MetaCompositor *compositor, MetaWindow *window) { MetaDisplay *display = compositor->display; Display *xdisplay = meta_display_get_xdisplay (display); if (window == NULL) XFixesSetWindowShapeRegion (xdisplay, compositor->output, ShapeBounding, 0, 0, None); else { XserverRegion output_region; XRectangle screen_rect, window_bounds; int width, height; MetaRectangle rect; meta_window_get_frame_rect (window, &rect); window_bounds.x = rect.x; window_bounds.y = rect.y; window_bounds.width = rect.width; window_bounds.height = rect.height; meta_screen_get_size (display->screen, &width, &height); screen_rect.x = 0; screen_rect.y = 0; screen_rect.width = width; screen_rect.height = height; output_region = XFixesCreateRegion (xdisplay, &window_bounds, 1); XFixesInvertRegion (xdisplay, output_region, &screen_rect, output_region); XFixesSetWindowShapeRegion (xdisplay, compositor->output, ShapeBounding, 0, 0, output_region); XFixesDestroyRegion (xdisplay, output_region); } }
void meta_compositor_sync_screen_size (MetaCompositor *compositor, guint width, guint height) { MetaDisplay *display = compositor->display; if (meta_is_wayland_compositor ()) { /* FIXME: when we support a sliced stage, this is the place to do it But! This is not the place to apply KMS config, here we only notify Clutter/Cogl/GL that the framebuffer sizes changed. And because for now clutter does not do sliced, we use one framebuffer the size of the whole screen, and when running on bare metal MetaMonitorManager will do the necessary tricks to show the right portions on the right screens. */ clutter_actor_set_size (compositor->stage, width, height); } else { Display *xdisplay; Window xwin; xdisplay = meta_display_get_xdisplay (display); xwin = clutter_x11_get_stage_window (CLUTTER_STAGE (compositor->stage)); XResizeWindow (xdisplay, xwin, width, height); } meta_verbose ("Changed size for stage on screen %d to %dx%d\n", meta_screen_get_screen_number (display->screen), width, height); }
LOCAL_SYMBOL gboolean meta_begin_modal_for_plugin (MetaScreen *screen, MetaPlugin *plugin, Window grab_window, Cursor cursor, MetaModalOptions options, guint32 timestamp) { /* To some extent this duplicates code in meta_display_begin_grab_op(), but there * are significant differences in how we handle grabs that make it difficult to * merge the two. */ MetaDisplay *display = meta_screen_get_display (screen); Display *xdpy = meta_display_get_xdisplay (display); MetaCompositor *compositor = display->compositor; gboolean pointer_grabbed = FALSE; gboolean keyboard_grabbed = FALSE; int result; if (compositor->modal_plugin != NULL || display->grab_op != META_GRAB_OP_NONE) return FALSE; if ((options & META_MODAL_POINTER_ALREADY_GRABBED) == 0) { result = XGrabPointer (xdpy, grab_window, False, /* owner_events */ (ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask), GrabModeAsync, GrabModeAsync, None, /* confine to */ cursor, timestamp); if (result != Success) goto fail; pointer_grabbed = TRUE; } if ((options & META_MODAL_KEYBOARD_ALREADY_GRABBED) == 0) { result = XGrabKeyboard (xdpy, grab_window, False, /* owner_events */ GrabModeAsync, GrabModeAsync, timestamp); if (result != Success) goto fail; keyboard_grabbed = TRUE; } display->grab_op = META_GRAB_OP_COMPOSITOR; display->grab_window = NULL; display->grab_screen = screen; display->grab_have_pointer = TRUE; display->grab_have_keyboard = TRUE; compositor->modal_plugin = plugin; return TRUE; fail: if (pointer_grabbed) XUngrabPointer (xdpy, timestamp); if (keyboard_grabbed) XUngrabKeyboard (xdpy, timestamp); return FALSE; }
/** * meta_background_actor_update: * @screen: a #MetaScreen * * Refetches the _XROOTPMAP_ID property for the root window and updates * the contents of the background actor based on that. There's no attempt * to optimize out pixmap values that don't change (since a root pixmap * could be replaced by with another pixmap with the same ID under some * circumstances), so this should only be called when we actually receive * a PropertyNotify event for the property. */ void meta_background_actor_update (MetaScreen *screen) { MetaScreenBackground *background; MetaDisplay *display; MetaCompositor *compositor; Atom type; int format; gulong nitems; gulong bytes_after; guchar *data; Pixmap root_pixmap_id; background = meta_screen_background_get (screen); display = meta_screen_get_display (screen); compositor = meta_display_get_compositor (display); root_pixmap_id = None; if (!XGetWindowProperty (meta_display_get_xdisplay (display), meta_screen_get_xroot (screen), compositor->atom_x_root_pixmap, 0, LONG_MAX, False, AnyPropertyType, &type, &format, &nitems, &bytes_after, &data) && type != None) { /* Got a property. */ if (type == XA_PIXMAP && format == 32 && nitems == 1) { /* Was what we expected. */ root_pixmap_id = *(Pixmap *)data; } XFree(data); } if (root_pixmap_id != None) { CoglHandle texture; CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); GError *error = NULL; meta_error_trap_push (display); texture = cogl_texture_pixmap_x11_new (ctx, root_pixmap_id, FALSE, &error); meta_error_trap_pop (display); if (texture != COGL_INVALID_HANDLE) { set_texture (background, texture); cogl_handle_unref (texture); background->have_pixmap = True; return; } else { g_warning ("Failed to create background texture from pixmap: %s", error->message); g_error_free (error); } } background->have_pixmap = False; set_texture_to_stage_color (background); }
void meta_compositor_manage_screen (MetaCompositor *compositor, MetaScreen *screen) { MetaCompScreen *info; MetaDisplay *display = meta_screen_get_display (screen); Display *xdisplay = meta_display_get_xdisplay (display); int screen_number = meta_screen_get_screen_number (screen); Window xroot = meta_screen_get_xroot (screen); Window xwin; gint width, height; XWindowAttributes attr; long event_mask; guint n_retries; guint max_retries; /* Check if the screen is already managed */ if (meta_screen_get_compositor_data (screen)) return; if (meta_get_replace_current_wm ()) max_retries = 5; else max_retries = 1; n_retries = 0; /* Some compositors (like old versions of Muffin) might not properly unredirect * subwindows before destroying the WM selection window; so we wait a while * for such a compositor to exit before giving up. */ while (TRUE) { meta_error_trap_push_with_return (display); XCompositeRedirectSubwindows (xdisplay, xroot, CompositeRedirectManual); XSync (xdisplay, FALSE); if (!meta_error_trap_pop_with_return (display)) break; if (n_retries == max_retries) { /* This probably means that a non-WM compositor like xcompmgr is running; * we have no way to get it to exit */ meta_fatal (_("Another compositing manager is already running on screen %i on display \"%s\"."), screen_number, display->name); } n_retries++; g_usleep (G_USEC_PER_SEC); } info = g_new0 (MetaCompScreen, 1); /* * We use an empty input region for Clutter as a default because that allows * the user to interact with all the windows displayed on the screen. * We have to initialize info->pending_input_region to an empty region explicitly, * because None value is used to mean that the whole screen is an input region. */ info->pending_input_region = XFixesCreateRegion (xdisplay, NULL, 0); info->screen = screen; meta_screen_set_compositor_data (screen, info); info->output = None; info->windows = NULL; meta_screen_set_cm_selection (screen); info->stage = clutter_stage_new (); meta_screen_get_size (screen, &width, &height); clutter_actor_realize (info->stage); xwin = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage)); XResizeWindow (xdisplay, xwin, width, height); event_mask = FocusChangeMask | ExposureMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask | PropertyChangeMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask | StructureNotifyMask; if (XGetWindowAttributes (xdisplay, xwin, &attr)) { event_mask |= attr.your_event_mask; } XSelectInput (xdisplay, xwin, event_mask); info->window_group = meta_window_group_new (screen); info->background_actor = meta_background_actor_new_for_screen (screen); info->bottom_window_group = clutter_group_new(); info->overlay_group = clutter_group_new (); info->top_window_group = meta_window_group_new (screen); info->hidden_group = clutter_group_new (); clutter_container_add (CLUTTER_CONTAINER (info->window_group), info->background_actor, NULL); clutter_container_add (CLUTTER_CONTAINER (info->stage), info->window_group, info->overlay_group, info->hidden_group, NULL); clutter_actor_hide (info->hidden_group); info->plugin_mgr = meta_plugin_manager_get (screen); meta_plugin_manager_initialize (info->plugin_mgr); /* * Delay the creation of the overlay window as long as we can, to avoid * blanking out the screen. This means that during the plugin loading, the * overlay window is not accessible; if the plugin needs to access it * directly, it should hook into the "show" signal on stage, and do * its stuff there. */ info->output = get_output_window (screen); XReparentWindow (xdisplay, xwin, info->output, 0, 0); /* Make sure there isn't any left-over output shape on the * overlay window by setting the whole screen to be an * output region. * * Note: there doesn't seem to be any real chance of that * because the X server will destroy the overlay window * when the last client using it exits. */ XFixesSetWindowShapeRegion (xdisplay, info->output, ShapeBounding, 0, 0, None); do_set_stage_input_region (screen, info->pending_input_region); if (info->pending_input_region != None) { XFixesDestroyRegion (xdisplay, info->pending_input_region); info->pending_input_region = None; } clutter_actor_show (info->overlay_group); clutter_actor_show (info->stage); }