static void meta_background_actor_get_preferred_height (ClutterActor *actor, gfloat for_width, gfloat *min_height_p, gfloat *natural_height_p) { MetaBackgroundActor *self = META_BACKGROUND_ACTOR (actor); MetaBackgroundActorPrivate *priv = self->priv; int width, height; meta_screen_get_size (priv->background->screen, &width, &height); if (min_height_p) *min_height_p = height; if (natural_height_p) *natural_height_p = height; }
static void reposition_switcher(MetaSwitcher* self) { MetaSwitcherPrivate* priv = self->priv; MetaScreen* screen = meta_plugin_get_screen(priv->plugin); gint screen_width = 0, screen_height = 0; meta_screen_get_size(screen, &screen_width, &screen_height); clutter_actor_save_easing_state(priv->top); clutter_actor_set_easing_duration(priv->top, 400); clutter_actor_set_easing_mode(priv->top, CLUTTER_LINEAR); gfloat w = clutter_actor_get_width(priv->top), h = clutter_actor_get_height(priv->top), tx = (screen_width - w)/2, ty = (screen_height - h)/2; clutter_actor_set_position(priv->top, tx, ty); clutter_actor_restore_easing_state(priv->top); }
gboolean meta_switcher_show(MetaSwitcher* self) { MetaSwitcherPrivate* priv = self->priv; int screen_width, screen_height; MetaScreen* screen = meta_plugin_get_screen(priv->plugin); priv->workspace = meta_screen_get_active_workspace(screen); meta_screen_get_size(screen, &screen_width, &screen_height); meta_switcher_present_list(self); if (priv->apps == NULL || priv->apps->len == 0) goto _end; _capture_desktop(self); clutter_content_invalidate(clutter_actor_get_content(priv->top)); ClutterActor* stage = meta_get_stage_for_screen(screen); clutter_actor_insert_child_above(stage, priv->top, NULL); clutter_actor_show(priv->top); if (!meta_plugin_begin_modal(priv->plugin, 0, clutter_get_current_event_time())) { if (!meta_plugin_begin_modal(priv->plugin, META_MODAL_POINTER_ALREADY_GRABBED, clutter_get_current_event_time())) { g_warning("can not be modal"); goto _end; } } meta_disable_unredirect_for_screen(screen); priv->modaled = TRUE; priv->previous_focused = clutter_stage_get_key_focus(CLUTTER_STAGE(stage)); if (priv->previous_focused == stage) priv->previous_focused = NULL; clutter_stage_set_key_focus(CLUTTER_STAGE(stage), priv->top); clutter_actor_grab_key_focus(priv->top); return TRUE; _end: clutter_actor_hide(priv->top); return FALSE; }
static void update_wrap_mode (MetaScreenBackground *background) { GSList *l; int width, height; meta_screen_get_size (background->screen, &width, &height); /* We turn off repeating when we have a full-screen pixmap to keep from * getting artifacts from one side of the image sneaking into the other * side of the image via bilinear filtering. */ if (width == background->texture_width && height == background->texture_height) background->wrap_mode = COGL_MATERIAL_WRAP_MODE_CLAMP_TO_EDGE; else background->wrap_mode = COGL_MATERIAL_WRAP_MODE_REPEAT; for (l = background->actors; l; l = l->next) update_wrap_mode_of_actor (l->data); }
static ClutterActor* load_icon_for_window(MetaSwitcher* self, MetaWindow* window) { MetaSwitcherPrivate *priv = self->priv; MetaScreen *screen = meta_plugin_get_screen(priv->plugin); ShellWindowTracker* tracker = shell_window_tracker_get_default(); ShellApp* app = shell_window_tracker_get_window_app(tracker, window); gint screen_width, screen_height, app_icon_size = APP_ICON_SIZE; /* TODO: @sonald scale app icon size at first */ meta_screen_get_size(screen, &screen_width, &screen_height); if (priv->apps->len) app_icon_size = (screen_width - priv->apps->len * APP_ICON_PADDING ) / priv->apps->len; if (app_icon_size > APP_ICON_SIZE) app_icon_size = APP_ICON_SIZE; if (app) return shell_app_create_icon_texture(app, app_icon_size); return NULL; }
/** * 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); } }
/* * 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); } }
static void meta_window_group_paint (ClutterActor *actor) { cairo_region_t *clip_region; cairo_region_t *unobscured_region; cairo_rectangle_int_t visible_rect, clip_rect; int paint_x_origin, paint_y_origin; int screen_width, screen_height; MetaWindowGroup *window_group = META_WINDOW_GROUP (actor); ClutterActor *stage = clutter_actor_get_stage (actor); meta_screen_get_size (window_group->screen, &screen_width, &screen_height); /* Normally we expect an actor to be drawn at it's position on the screen. * However, if we're inside the paint of a ClutterClone, that won't be the * case and we need to compensate. We look at the position of the window * group under the current model-view matrix and the position of the actor. * If they are both simply integer translations, then we can compensate * easily, otherwise we give up. * * Possible cleanup: work entirely in paint space - we can compute the * combination of the model-view matrix with the local matrix for each child * actor and get a total transformation for that actor for how we are * painting currently, and never worry about how actors are positioned * on the stage. */ if (!meta_actor_painting_untransformed (screen_width, screen_height, &paint_x_origin, &paint_y_origin) || !meta_actor_is_untransformed (actor, NULL, NULL)) { CLUTTER_ACTOR_CLASS (meta_window_group_parent_class)->paint (actor); return; } visible_rect.x = visible_rect.y = 0; visible_rect.width = clutter_actor_get_width (CLUTTER_ACTOR (stage)); visible_rect.height = clutter_actor_get_height (CLUTTER_ACTOR (stage)); unobscured_region = cairo_region_create_rectangle (&visible_rect); /* Get the clipped redraw bounds from Clutter so that we can avoid * painting shadows on windows that don't need to be painted in this * frame. In the case of a multihead setup with mismatched monitor * sizes, we could intersect this with an accurate union of the * monitors to avoid painting shadows that are visible only in the * holes. */ clutter_stage_get_redraw_clip_bounds (CLUTTER_STAGE (stage), &clip_rect); clip_region = cairo_region_create_rectangle (&clip_rect); cairo_region_translate (clip_region, -paint_x_origin, -paint_y_origin); meta_cullable_cull_out (META_CULLABLE (window_group), unobscured_region, clip_region); cairo_region_destroy (unobscured_region); cairo_region_destroy (clip_region); CLUTTER_ACTOR_CLASS (meta_window_group_parent_class)->paint (actor); meta_cullable_reset_culling (META_CULLABLE (window_group)); }
static void switch_workspace (MetaPlugin *plugin, gint from, gint to, MetaMotionDirection direction) { MetaScreen *screen; MetaDefaultPluginPrivate *priv = META_DEFAULT_PLUGIN (plugin)->priv; GList *l; ClutterActor *workspace0 = clutter_group_new (); ClutterActor *workspace1 = clutter_group_new (); ClutterActor *stage; int screen_width, screen_height; ClutterAnimation *animation; screen = meta_plugin_get_screen (plugin); stage = meta_get_stage_for_screen (screen); meta_screen_get_size (screen, &screen_width, &screen_height); clutter_actor_set_anchor_point (workspace1, screen_width, screen_height); clutter_actor_set_position (workspace1, screen_width, screen_height); clutter_actor_set_scale (workspace1, 0.0, 0.0); clutter_container_add_actor (CLUTTER_CONTAINER (stage), workspace1); clutter_container_add_actor (CLUTTER_CONTAINER (stage), workspace0); if (from == to) { meta_plugin_switch_workspace_completed (plugin); return; } l = g_list_last (meta_get_window_actors (screen)); while (l) { MetaWindowActor *window_actor = l->data; MetaWindow *window = meta_window_actor_get_meta_window (window_actor); MetaWorkspace *workspace; ActorPrivate *apriv = get_actor_private (window_actor); ClutterActor *actor = CLUTTER_ACTOR (window_actor); gint win_workspace; workspace = meta_window_get_workspace (window); win_workspace = meta_workspace_index (workspace); if (win_workspace == to || win_workspace == from) { apriv->orig_parent = clutter_actor_get_parent (actor); clutter_actor_reparent (actor, win_workspace == to ? workspace1 : workspace0); clutter_actor_show_all (actor); clutter_actor_raise_top (actor); } else if (win_workspace < 0) { /* Sticky window */ apriv->orig_parent = NULL; } else { /* Window on some other desktop */ clutter_actor_hide (actor); apriv->orig_parent = NULL; } l = l->prev; } priv->desktop1 = workspace0; priv->desktop2 = workspace1; animation = clutter_actor_animate (workspace0, CLUTTER_EASE_IN_SINE, SWITCH_TIMEOUT, "scale-x", 1.0, "scale-y", 1.0, NULL); priv->tml_switch_workspace1 = clutter_animation_get_timeline (animation); g_signal_connect (priv->tml_switch_workspace1, "completed", G_CALLBACK (on_switch_workspace_effect_complete), plugin); animation = clutter_actor_animate (workspace1, CLUTTER_EASE_IN_SINE, SWITCH_TIMEOUT, "scale-x", 0.0, "scale-y", 0.0, NULL); priv->tml_switch_workspace2 = clutter_animation_get_timeline (animation); }
static void grab_screenshot (ClutterActor *stage, _screenshot_data *screenshot_data) { MetaScreen *screen = shell_global_get_screen (screenshot_data->screenshot->global); MetaCursorTracker *tracker; int width, height; GSimpleAsyncResult *result; GSettings *settings; meta_screen_get_size (screen, &width, &height); do_grab_screenshot (screenshot_data, 0, 0, width, height); if (meta_screen_get_n_monitors (screen) > 1) { cairo_region_t *screen_region = cairo_region_create (); cairo_region_t *stage_region; MetaRectangle monitor_rect; cairo_rectangle_int_t stage_rect; int i; cairo_t *cr; for (i = meta_screen_get_n_monitors (screen) - 1; i >= 0; i--) { meta_screen_get_monitor_geometry (screen, i, &monitor_rect); cairo_region_union_rectangle (screen_region, (const cairo_rectangle_int_t *) &monitor_rect); } stage_rect.x = 0; stage_rect.y = 0; stage_rect.width = width; stage_rect.height = height; stage_region = cairo_region_create_rectangle ((const cairo_rectangle_int_t *) &stage_rect); cairo_region_xor (stage_region, screen_region); cairo_region_destroy (screen_region); cr = cairo_create (screenshot_data->image); for (i = 0; i < cairo_region_num_rectangles (stage_region); i++) { cairo_rectangle_int_t rect; cairo_region_get_rectangle (stage_region, i, &rect); cairo_rectangle (cr, (double) rect.x, (double) rect.y, (double) rect.width, (double) rect.height); cairo_fill (cr); } cairo_destroy (cr); cairo_region_destroy (stage_region); } screenshot_data->screenshot_area.x = 0; screenshot_data->screenshot_area.y = 0; screenshot_data->screenshot_area.width = width; screenshot_data->screenshot_area.height = height; settings = g_settings_new (A11Y_APPS_SCHEMA); if (screenshot_data->include_cursor && !g_settings_get_boolean (settings, MAGNIFIER_ACTIVE_KEY)) { tracker = meta_cursor_tracker_get_for_screen (screen); _draw_cursor_image (tracker, screenshot_data->image, screenshot_data->screenshot_area); } g_object_unref (settings); g_signal_handlers_disconnect_by_func (stage, (void *)grab_screenshot, (gpointer)screenshot_data); result = g_simple_async_result_new (NULL, on_screenshot_written, (gpointer)screenshot_data, grab_screenshot); g_simple_async_result_run_in_thread (result, write_screenshot_thread, G_PRIORITY_DEFAULT, NULL); g_object_unref (result); }
static void _add_app(MetaSwitcher* self, MetaWindow* app, gint* x, gint* y) { MetaSwitcherPrivate* priv = self->priv; if (!priv->icons) priv->icons = g_hash_table_new(NULL, NULL); // container ClutterActor* actor = clutter_actor_new(); WindowPrivate* win_priv = get_window_private(actor); win_priv->window = app; win_priv->highlight = FALSE; g_hash_table_insert(priv->icons, app, actor); gint w = APP_ACTOR_WIDTH, h = APP_ACTOR_HEIGHT, screen_width, screen_height; /* TODO: @sonald scale app actor width */ MetaScreen *screen = meta_plugin_get_screen(priv->plugin); meta_screen_get_size(screen, &screen_width, &screen_height); if (priv->apps->len) w = (screen_width - priv->apps->len * APP_ICON_PADDING) / priv->apps->len; if (w > APP_ACTOR_WIDTH) w = APP_ACTOR_WIDTH; // add children ClutterContent* canvas = clutter_canvas_new(); g_signal_connect(canvas, "draw", G_CALLBACK(on_icon_background_draw), actor); clutter_canvas_set_size(CLUTTER_CANVAS(canvas), w, h); ClutterActor* bg = clutter_actor_new(); clutter_actor_set_name(bg, "bg"); clutter_actor_set_content(bg, canvas); g_object_unref(canvas); clutter_actor_set_size(bg, w, h); g_object_set(bg, "x-expand", TRUE, "y-expand", TRUE, "x-align", CLUTTER_ACTOR_ALIGN_FILL, "y-align", CLUTTER_ACTOR_ALIGN_FILL, NULL); clutter_actor_add_child(actor, bg); ClutterActor* icon = load_icon_for_window(self, app); if (icon) clutter_actor_add_child(actor, icon); ClutterActor* label = clutter_text_new(); clutter_actor_add_child(actor, label); clutter_text_set_text(CLUTTER_TEXT(label), meta_window_get_title(app)); clutter_text_set_font_name(CLUTTER_TEXT(label), "Sans 10"); ClutterColor clr = {0xff, 0xff, 0xff, 0xff}; clutter_text_set_color(CLUTTER_TEXT(label), &clr); clutter_text_set_ellipsize(CLUTTER_TEXT(label), PANGO_ELLIPSIZE_END); g_object_set(label, "x-align", CLUTTER_ACTOR_ALIGN_CENTER, "y-align", CLUTTER_ACTOR_ALIGN_CENTER, NULL); gfloat pref_width = clutter_actor_get_width(label); if (pref_width > w - 10) { pref_width = w - 10; clutter_actor_set_width(label, pref_width); } /* TODO: @sonald adjust app title position */ clutter_actor_set_position(label, (w - pref_width) / 2, APP_ICON_SIZE + 2); g_debug("%s: size: %d, %d", __func__, w, h); clutter_actor_show(actor); clutter_actor_add_child(priv->top, actor); *x += w; }
/* * This is the Metacity entry point for the effect. */ void mnb_switch_zones_effect (MetaPlugin *plugin, gint from, gint to, MetaMotionDirection direction) { GList *w; gint width, height; MetaScreen *screen; ClutterActor *window_group; if (running++) { /* * We have been called while the effect is already in progress; we need to * mutter know that we completed the previous run. */ if (--running < 0) { g_warning (G_STRLOC ": error in running effect accounting!"); running = 0; } meta_plugin_switch_workspace_completed (plugin); } if ((from == to) && !zones_preview) { if (--running < 0) { g_warning (G_STRLOC ": error in running effect accounting!"); running = 0; } meta_plugin_switch_workspace_completed (plugin); return; } screen = meta_plugin_get_screen (plugin); if (!zones_preview) { ClutterActor *stage; /* Construct the zones preview actor */ zones_preview = mnb_zones_preview_new (); g_object_set (G_OBJECT (zones_preview), "workspace", (gdouble)from, NULL); /* Add it to the stage */ stage = meta_get_stage_for_screen (screen); clutter_container_add_actor (CLUTTER_CONTAINER (stage), zones_preview); /* Attach to completed signal */ g_signal_connect (zones_preview, "switch-completed", G_CALLBACK (mnb_switch_zones_completed_cb), plugin); } meta_screen_get_size (screen, &width, &height); g_object_set (G_OBJECT (zones_preview), "workspace-width", (guint)width, "workspace-height", (guint)height, NULL); mnb_zones_preview_clear (MNB_ZONES_PREVIEW (zones_preview)); mnb_zones_preview_set_n_workspaces (MNB_ZONES_PREVIEW (zones_preview), meta_screen_get_n_workspaces (screen)); /* Add windows to zone preview actor */ for (w = meta_get_window_actors (screen); w; w = w->next) { MetaWindowActor *window_actor = w->data; gint workspace = meta_window_actor_get_workspace (window_actor); MetaWindow *window = meta_window_actor_get_meta_window (window_actor); MetaWindowType type = meta_window_get_window_type (window); /* * Only show regular windows that are not sticky (getting stacking order * right for sticky windows would be really hard, and since they appear * on each workspace, they do not help in identifying which workspace * it is). */ if ((workspace < 0) || meta_window_actor_is_override_redirect (window_actor) || (type != META_WINDOW_NORMAL)) continue; mnb_zones_preview_add_window (MNB_ZONES_PREVIEW (zones_preview), window_actor); } /* Make sure it's on top */ window_group = meta_get_window_group_for_screen (screen); clutter_actor_raise (zones_preview, window_group); /* Initiate animation */ mnb_zones_preview_change_workspace (MNB_ZONES_PREVIEW (zones_preview), to); }
void meta_compositor_manage (MetaCompositor *compositor) { MetaDisplay *display = compositor->display; Display *xdisplay = display->xdisplay; MetaScreen *screen = display->screen; Window xwin = 0; gint width, height; meta_screen_set_cm_selection (display->screen); if (meta_is_wayland_compositor ()) { MetaWaylandCompositor *wayland_compositor = meta_wayland_compositor_get_default (); compositor->stage = meta_stage_new (); wayland_compositor->stage = compositor->stage; meta_screen_get_size (screen, &width, &height); clutter_actor_set_size (compositor->stage, width, height); clutter_actor_show (compositor->stage); } else { compositor->stage = clutter_stage_new (); meta_screen_get_size (screen, &width, &height); clutter_actor_realize (compositor->stage); xwin = clutter_x11_get_stage_window (CLUTTER_STAGE (compositor->stage)); XResizeWindow (xdisplay, xwin, width, height); { MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ()); Display *backend_xdisplay = meta_backend_x11_get_xdisplay (backend); unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 }; XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits }; XISetMask (mask.mask, XI_KeyPress); XISetMask (mask.mask, XI_KeyRelease); XISetMask (mask.mask, XI_ButtonPress); XISetMask (mask.mask, XI_ButtonRelease); XISetMask (mask.mask, XI_Enter); XISetMask (mask.mask, XI_Leave); XISetMask (mask.mask, XI_FocusIn); XISetMask (mask.mask, XI_FocusOut); XISetMask (mask.mask, XI_Motion); XIClearMask (mask.mask, XI_TouchBegin); XIClearMask (mask.mask, XI_TouchEnd); XIClearMask (mask.mask, XI_TouchUpdate); XISelectEvents (backend_xdisplay, xwin, &mask, 1); } } /* We use connect_after() here to accomodate code in GNOME Shell that, * when benchmarking drawing performance, connects to ::after-paint * and calls glFinish(). The timing information from that will be * more accurate if we hold off until that completes before we signal * apps to begin drawing the next frame. If there are no other * connections to ::after-paint, connect() vs. connect_after() doesn't * matter. */ g_signal_connect_after (CLUTTER_STAGE (compositor->stage), "after-paint", G_CALLBACK (after_stage_paint), compositor); clutter_stage_set_sync_delay (CLUTTER_STAGE (compositor->stage), META_SYNC_DELAY); compositor->window_group = meta_window_group_new (screen); compositor->top_window_group = meta_window_group_new (screen); clutter_actor_add_child (compositor->stage, compositor->window_group); clutter_actor_add_child (compositor->stage, compositor->top_window_group); if (meta_is_wayland_compositor ()) { /* NB: When running as a wayland compositor we don't need an X * composite overlay window, and we don't need to play any input * region tricks to redirect events into clutter. */ compositor->output = None; } else { compositor->output = screen->composite_overlay_window; XReparentWindow (xdisplay, xwin, compositor->output, 0, 0); meta_empty_stage_input_region (screen); /* 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, compositor->output, ShapeBounding, 0, 0, None); /* Map overlay window before redirecting windows offscreen so we catch their * contents until we show the stage. */ XMapWindow (xdisplay, compositor->output); } redirect_windows (display->screen); compositor->plugin_mgr = meta_plugin_manager_new (compositor); }
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); }