backend: Create the stage in the backend, rather than the compositor

This allows creating the stage much earlier than it otherwise would have
been. Our initialization sequence has always been a bit haphazard, with
first the MetaBackend created, then the MetaDisplay, and inside of that,
the MetaScreen and MetaCompositor.

Refactor this out so that the MetaBackend creates the Clutter
stage. Besides the clarity of early initialization, we now have much
easier access to the stage, allowing us to use it for things such as
key focus and beyond.
This commit is contained in:
Jasper St. Pierre 2014-08-13 19:46:32 -04:00
parent e935b52e51
commit 467465c99c
12 changed files with 125 additions and 109 deletions

View File

@ -69,6 +69,8 @@ libmutter_la_SOURCES = \
backends/meta-monitor-manager.h \
backends/meta-monitor-manager-dummy.c \
backends/meta-monitor-manager-dummy.h \
backends/meta-stage.h \
backends/meta-stage.c \
backends/edid-parse.c \
backends/edid.h \
backends/x11/meta-backend-x11.c \
@ -115,8 +117,6 @@ libmutter_la_SOURCES = \
compositor/meta-surface-actor-x11.h \
compositor/meta-surface-actor-wayland.c \
compositor/meta-surface-actor-wayland.h \
compositor/meta-stage.h \
compositor/meta-stage.c \
compositor/meta-texture-rectangle.c \
compositor/meta-texture-rectangle.h \
compositor/meta-texture-tower.c \

View File

@ -84,6 +84,9 @@ struct _MetaBackendClass
void (* lock_layout_group) (MetaBackend *backend,
guint idx);
void (* update_screen_size) (MetaBackend *backend, int width, int height);
void (* select_stage_events) (MetaBackend *backend);
};
MetaIdleMonitor * meta_backend_get_idle_monitor (MetaBackend *backend,

View File

@ -27,9 +27,8 @@
#include <meta/meta-backend.h>
#include "meta-backend-private.h"
#include <clutter/clutter.h>
#include "backends/x11/meta-backend-x11.h"
#include "meta-stage.h"
#ifdef HAVE_NATIVE_BACKEND
#include "backends/native/meta-backend-native.h"
@ -54,6 +53,8 @@ struct _MetaBackendPrivate
{
MetaMonitorManager *monitor_manager;
MetaCursorRenderer *cursor_renderer;
ClutterActor *stage;
};
typedef struct _MetaBackendPrivate MetaBackendPrivate;
@ -77,12 +78,40 @@ meta_backend_finalize (GObject *object)
G_OBJECT_CLASS (meta_backend_parent_class)->finalize (object);
}
static void
meta_backend_sync_screen_size (MetaBackend *backend)
{
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
int width, height;
meta_monitor_manager_get_screen_size (priv->monitor_manager, &width, &height);
META_BACKEND_GET_CLASS (backend)->update_screen_size (backend, width, height);
}
static void
on_monitors_changed (MetaMonitorManager *monitors,
gpointer user_data)
{
MetaBackend *backend = META_BACKEND (user_data);
meta_backend_sync_screen_size (backend);
}
static void
meta_backend_real_post_init (MetaBackend *backend)
{
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
priv->stage = meta_stage_new ();
clutter_actor_realize (priv->stage);
META_BACKEND_GET_CLASS (backend)->select_stage_events (backend);
priv->monitor_manager = META_BACKEND_GET_CLASS (backend)->create_monitor_manager (backend);
g_signal_connect (priv->monitor_manager, "monitors-changed",
G_CALLBACK (on_monitors_changed), backend);
meta_backend_sync_screen_size (backend);
priv->cursor_renderer = META_BACKEND_GET_CLASS (backend)->create_cursor_renderer (backend);
}
@ -110,6 +139,21 @@ meta_backend_real_ungrab_device (MetaBackend *backend,
return TRUE;
}
static void
meta_backend_real_update_screen_size (MetaBackend *backend,
int width, int height)
{
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
clutter_actor_set_size (priv->stage, width, height);
}
static void
meta_backend_real_select_stage_events (MetaBackend *backend)
{
/* Do nothing */
}
static void
meta_backend_class_init (MetaBackendClass *klass)
{
@ -121,6 +165,8 @@ meta_backend_class_init (MetaBackendClass *klass)
klass->create_cursor_renderer = meta_backend_real_create_cursor_renderer;
klass->grab_device = meta_backend_real_grab_device;
klass->ungrab_device = meta_backend_real_ungrab_device;
klass->update_screen_size = meta_backend_real_update_screen_size;
klass->select_stage_events = meta_backend_real_select_stage_events;
}
static void
@ -251,6 +297,21 @@ meta_backend_lock_layout_group (MetaBackend *backend,
META_BACKEND_GET_CLASS (backend)->lock_layout_group (backend, idx);
}
/**
* meta_backend_get_stage:
* @backend: A #MetaBackend
*
* Gets the global #ClutterStage that's managed by this backend.
*
* Returns: (transfer none): the #ClutterStage
*/
ClutterActor *
meta_backend_get_stage (MetaBackend *backend)
{
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
return priv->stage;
}
static GType
get_backend_type (void)
{

View File

@ -27,14 +27,15 @@
#include "meta-cursor-renderer.h"
#include "meta-cursor-private.h"
#include <meta/meta-backend.h>
#include <meta/util.h>
#include <cogl/cogl.h>
#include <cogl/cogl-wayland-server.h>
#include <clutter/clutter.h>
#include "meta-stage.h"
#include "wayland/meta-wayland-private.h"
struct _MetaCursorRendererPrivate
{
int current_x, current_y;
@ -51,8 +52,8 @@ static void
queue_redraw (MetaCursorRenderer *renderer)
{
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
ClutterActor *stage = compositor->stage;
MetaBackend *backend = meta_get_backend ();
ClutterActor *stage = meta_backend_get_stage (backend);
/* During early initialization, we can have no stage */
if (!stage)

View File

@ -101,15 +101,15 @@ session_unpause (void)
clutter_egl_thaw_master_clock ();
{
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
MetaBackend *backend = meta_get_backend ();
MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (backend);
ClutterActor *stage = meta_backend_get_stage (backend);
/* When we mode-switch back, we need to immediately queue a redraw
* in case nothing else queued one for us, and force the cursor to
* update. */
clutter_actor_queue_redraw (compositor->stage);
clutter_actor_queue_redraw (stage);
meta_cursor_renderer_native_force_update (META_CURSOR_RENDERER_NATIVE (renderer));
}
}

View File

@ -592,6 +592,40 @@ meta_backend_x11_lock_layout_group (MetaBackend *backend,
XkbLockGroup (priv->xdisplay, XkbUseCoreKbd, idx);
}
static void
meta_backend_x11_update_screen_size (MetaBackend *backend,
int width, int height)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
Window xwin = meta_backend_x11_get_xwindow (x11);
XResizeWindow (priv->xdisplay, xwin, width, height);
}
static void
meta_backend_x11_select_stage_events (MetaBackend *backend)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
Window xwin = meta_backend_x11_get_xwindow (x11);
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 (priv->xdisplay, xwin, &mask, 1);
}
static void
meta_backend_x11_class_init (MetaBackendX11Class *klass)
{
@ -601,13 +635,14 @@ meta_backend_x11_class_init (MetaBackendX11Class *klass)
backend_class->create_idle_monitor = meta_backend_x11_create_idle_monitor;
backend_class->create_monitor_manager = meta_backend_x11_create_monitor_manager;
backend_class->create_cursor_renderer = meta_backend_x11_create_cursor_renderer;
backend_class->grab_device = meta_backend_x11_grab_device;
backend_class->ungrab_device = meta_backend_x11_ungrab_device;
backend_class->warp_pointer = meta_backend_x11_warp_pointer;
backend_class->set_keymap = meta_backend_x11_set_keymap;
backend_class->get_keymap = meta_backend_x11_get_keymap;
backend_class->lock_layout_group = meta_backend_x11_lock_layout_group;
backend_class->update_screen_size = meta_backend_x11_update_screen_size;
backend_class->select_stage_events = meta_backend_x11_select_stage_events;
}
static void
@ -628,12 +663,6 @@ meta_backend_x11_get_xdisplay (MetaBackendX11 *x11)
Window
meta_backend_x11_get_xwindow (MetaBackendX11 *x11)
{
MetaDisplay *display = meta_get_display ();
MetaCompositor *compositor = display->compositor;
if (compositor == NULL)
return None;
ClutterStage *stage = CLUTTER_STAGE (compositor->stage);
return clutter_x11_get_stage_window (stage);
ClutterActor *stage = meta_backend_get_stage (META_BACKEND (x11));
return clutter_x11_get_stage_window (CLUTTER_STAGE (stage));
}

View File

@ -73,7 +73,6 @@
#include <meta/meta-shadow-factory.h>
#include "meta-window-actor-private.h"
#include "meta-window-group.h"
#include "meta-stage.h"
#include "window-private.h" /* to check window->hidden */
#include "display-private.h" /* for meta_display_lookup_x_window() and meta_display_cancel_touch() */
#include "util-private.h"
@ -450,55 +449,13 @@ 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);
}
}
{
MetaBackend *backend = meta_get_backend ();
compositor->stage = meta_backend_get_stage (backend);
}
/* We use connect_after() here to accomodate code in GNOME Shell that,
* when benchmarking drawing performance, connects to ::after-paint
@ -528,8 +485,12 @@ meta_compositor_manage (MetaCompositor *compositor)
}
else
{
Window xwin;
compositor->output = screen->composite_overlay_window;
xwin = meta_backend_x11_get_xwindow (META_BACKEND_X11 (meta_get_backend ()));
XReparentWindow (xdisplay, xwin, compositor->output, 0, 0);
meta_empty_stage_input_region (screen);
@ -1021,43 +982,6 @@ meta_compositor_sync_window_geometry (MetaCompositor *compositor,
meta_window_actor_sync_actor_geometry (window_actor, did_placement);
}
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);
}
static void
frame_callback (CoglOnscreen *onscreen,
CoglFrameEvent event,

View File

@ -2522,9 +2522,6 @@ on_monitors_changed (MetaMonitorManager *manager,
&changes);
}
meta_compositor_sync_screen_size (screen->display->compositor,
screen->rect.width, screen->rect.height);
/* Queue a resize on all the windows */
meta_screen_foreach_window (screen, meta_screen_resize_func, 0);

View File

@ -109,9 +109,6 @@ void meta_compositor_queue_frame_drawn (MetaCompositor *compositor,
void meta_compositor_sync_stack (MetaCompositor *compositor,
GList *stack);
void meta_compositor_sync_screen_size (MetaCompositor *compositor,
guint width,
guint height);
void meta_compositor_flash_screen (MetaCompositor *compositor,
MetaScreen *screen);

View File

@ -27,6 +27,8 @@
#include <glib-object.h>
#include <clutter/clutter.h>
typedef struct _MetaBackend MetaBackend;
typedef struct _MetaBackendClass MetaBackendClass;
@ -42,6 +44,8 @@ void meta_backend_set_keymap (MetaBackend *backend,
void meta_backend_lock_layout_group (MetaBackend *backend,
guint idx);
ClutterActor *meta_backend_get_stage (MetaBackend *backend);
void meta_clutter_init (void);
#endif /* META_BACKEND_H */