mirror of
https://github.com/brl/mutter.git
synced 2024-11-26 10:00:45 -05:00
Integrate the monitor manager with wayland
Use the right backend when running as a wayland compositor, export the data to wayland clients, and use it to keep the stage appropriately sized.
This commit is contained in:
parent
aa15c09d54
commit
9a4783e364
@ -668,6 +668,9 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
|
|||||||
{
|
{
|
||||||
wayland_compositor = meta_wayland_compositor_get_default ();
|
wayland_compositor = meta_wayland_compositor_get_default ();
|
||||||
info->stage = wayland_compositor->stage;
|
info->stage = wayland_compositor->stage;
|
||||||
|
|
||||||
|
meta_screen_get_size (screen, &width, &height);
|
||||||
|
clutter_actor_set_size (info->stage, width, height);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1416,18 +1419,25 @@ meta_compositor_sync_screen_size (MetaCompositor *compositor,
|
|||||||
guint width,
|
guint width,
|
||||||
guint height)
|
guint height)
|
||||||
{
|
{
|
||||||
|
MetaDisplay *display = meta_screen_get_display (screen);
|
||||||
|
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||||
|
|
||||||
if (meta_is_wayland_compositor ())
|
if (meta_is_wayland_compositor ())
|
||||||
{
|
{
|
||||||
/* It's not clear at the moment how we will be dealing with screen
|
/* FIXME: when we support a sliced stage, this is the place to do it
|
||||||
* resizing as a Wayland compositor so for now just abort if we
|
But! This is not the place to apply KMS config, here we only
|
||||||
* hit this code. */
|
notify Clutter/Cogl/GL that the framebuffer sizes changed.
|
||||||
g_critical ("Unexpected call to meta_compositor_sync_screen_size() "
|
|
||||||
"when running as a wayland compositor");
|
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 (info->stage, width, height);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MetaDisplay *display = meta_screen_get_display (screen);
|
|
||||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
|
||||||
Display *xdisplay;
|
Display *xdisplay;
|
||||||
Window xwin;
|
Window xwin;
|
||||||
|
|
||||||
@ -1438,12 +1448,12 @@ meta_compositor_sync_screen_size (MetaCompositor *compositor,
|
|||||||
xwin = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));
|
xwin = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));
|
||||||
|
|
||||||
XResizeWindow (xdisplay, xwin, width, height);
|
XResizeWindow (xdisplay, xwin, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
meta_verbose ("Changed size for stage on screen %d to %dx%d\n",
|
meta_verbose ("Changed size for stage on screen %d to %dx%d\n",
|
||||||
meta_screen_get_screen_number (screen),
|
meta_screen_get_screen_number (screen),
|
||||||
width, height);
|
width, height);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
frame_callback (CoglOnscreen *onscreen,
|
frame_callback (CoglOnscreen *onscreen,
|
||||||
|
@ -474,6 +474,15 @@ make_logical_config (MetaMonitorManager *manager)
|
|||||||
manager->monitor_infos = (void*)g_array_free (monitor_infos, FALSE);
|
manager->monitor_infos = (void*)g_array_free (monitor_infos, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GType
|
||||||
|
get_default_backend (void)
|
||||||
|
{
|
||||||
|
if (meta_is_wayland_compositor ())
|
||||||
|
return META_TYPE_MONITOR_MANAGER; /* FIXME: KMS */
|
||||||
|
else
|
||||||
|
return META_TYPE_MONITOR_MANAGER_XRANDR;
|
||||||
|
}
|
||||||
|
|
||||||
static MetaMonitorManager *
|
static MetaMonitorManager *
|
||||||
meta_monitor_manager_new (void)
|
meta_monitor_manager_new (void)
|
||||||
{
|
{
|
||||||
@ -483,7 +492,7 @@ meta_monitor_manager_new (void)
|
|||||||
env = g_getenv ("META_DEBUG_MULTIMONITOR");
|
env = g_getenv ("META_DEBUG_MULTIMONITOR");
|
||||||
|
|
||||||
if (env == NULL)
|
if (env == NULL)
|
||||||
type = META_TYPE_MONITOR_MANAGER_XRANDR;
|
type = get_default_backend ();
|
||||||
else if (strcmp (env, "xrandr") == 0)
|
else if (strcmp (env, "xrandr") == 0)
|
||||||
type = META_TYPE_MONITOR_MANAGER_XRANDR;
|
type = META_TYPE_MONITOR_MANAGER_XRANDR;
|
||||||
else
|
else
|
||||||
|
@ -676,6 +676,7 @@ meta_screen_new (MetaDisplay *display,
|
|||||||
screen->xroot = xroot;
|
screen->xroot = xroot;
|
||||||
screen->rect.x = screen->rect.y = 0;
|
screen->rect.x = screen->rect.y = 0;
|
||||||
|
|
||||||
|
if (!meta_is_wayland_compositor ())
|
||||||
meta_monitor_manager_initialize ();
|
meta_monitor_manager_initialize ();
|
||||||
|
|
||||||
manager = meta_monitor_manager_get ();
|
manager = meta_monitor_manager_get ();
|
||||||
|
@ -112,26 +112,6 @@ typedef struct
|
|||||||
struct wl_listener surface_destroy_listener;
|
struct wl_listener surface_destroy_listener;
|
||||||
} MetaWaylandShellSurface;
|
} MetaWaylandShellSurface;
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
guint32 flags;
|
|
||||||
int width;
|
|
||||||
int height;
|
|
||||||
int refresh;
|
|
||||||
} MetaWaylandMode;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
struct wl_object wayland_output;
|
|
||||||
int x;
|
|
||||||
int y;
|
|
||||||
int width_mm;
|
|
||||||
int height_mm;
|
|
||||||
/* XXX: with sliced stages we'd reference a CoglFramebuffer here. */
|
|
||||||
|
|
||||||
GList *modes;
|
|
||||||
} MetaWaylandOutput;
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
GSource source;
|
GSource source;
|
||||||
@ -155,7 +135,7 @@ struct _MetaWaylandCompositor
|
|||||||
struct wl_event_loop *wayland_loop;
|
struct wl_event_loop *wayland_loop;
|
||||||
GMainLoop *init_loop;
|
GMainLoop *init_loop;
|
||||||
ClutterActor *stage;
|
ClutterActor *stage;
|
||||||
GList *outputs;
|
GHashTable *outputs;
|
||||||
GSource *wayland_event_source;
|
GSource *wayland_event_source;
|
||||||
GList *surfaces;
|
GList *surfaces;
|
||||||
struct wl_list frame_callbacks;
|
struct wl_list frame_callbacks;
|
||||||
|
@ -55,6 +55,7 @@ meta_wayland_stage_class_init (MetaWaylandStageClass *klass)
|
|||||||
static void
|
static void
|
||||||
meta_wayland_stage_init (MetaWaylandStage *self)
|
meta_wayland_stage_init (MetaWaylandStage *self)
|
||||||
{
|
{
|
||||||
|
clutter_stage_set_user_resizable (CLUTTER_STAGE (self), FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
ClutterActor *
|
ClutterActor *
|
||||||
|
@ -50,6 +50,7 @@
|
|||||||
#include <meta/main.h>
|
#include <meta/main.h>
|
||||||
#include "frame.h"
|
#include "frame.h"
|
||||||
#include "meta-idle-monitor-private.h"
|
#include "meta-idle-monitor-private.h"
|
||||||
|
#include "monitor-private.h"
|
||||||
|
|
||||||
static MetaWaylandCompositor _meta_wayland_compositor;
|
static MetaWaylandCompositor _meta_wayland_compositor;
|
||||||
|
|
||||||
@ -629,84 +630,186 @@ meta_wayland_compositor_create_region (struct wl_client *wayland_client,
|
|||||||
region->region = cairo_region_create ();
|
region->region = cairo_region_create ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
MetaOutput *output;
|
||||||
|
struct wl_global *global;
|
||||||
|
int x, y;
|
||||||
|
enum wl_output_transform transform;
|
||||||
|
|
||||||
|
GList *resources;
|
||||||
|
} MetaWaylandOutput;
|
||||||
|
|
||||||
|
static void
|
||||||
|
output_resource_destroy (struct wl_resource *res)
|
||||||
|
{
|
||||||
|
MetaWaylandOutput *wayland_output;
|
||||||
|
|
||||||
|
wayland_output = wl_resource_get_user_data (res);
|
||||||
|
wayland_output->resources = g_list_remove (wayland_output->resources, res);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bind_output (struct wl_client *client,
|
bind_output (struct wl_client *client,
|
||||||
void *data,
|
void *data,
|
||||||
guint32 version,
|
guint32 version,
|
||||||
guint32 id)
|
guint32 id)
|
||||||
{
|
{
|
||||||
MetaWaylandOutput *output = data;
|
MetaWaylandOutput *wayland_output = data;
|
||||||
struct wl_resource *resource =
|
MetaOutput *output = wayland_output->output;
|
||||||
wl_resource_create (client, &wl_output_interface, version, id);
|
struct wl_resource *resource;
|
||||||
GList *l;
|
guint mode_flags;
|
||||||
|
|
||||||
|
resource = wl_resource_create (client, &wl_output_interface, version, id);
|
||||||
|
wayland_output->resources = g_list_prepend (wayland_output->resources, resource);
|
||||||
|
|
||||||
|
wl_resource_set_user_data (resource, wayland_output);
|
||||||
|
wl_resource_set_destructor (resource, output_resource_destroy);
|
||||||
|
|
||||||
|
meta_verbose ("Binding output %p/%s (%u, %u, %u, %u) x %f\n",
|
||||||
|
output, output->name,
|
||||||
|
output->crtc->rect.x, output->crtc->rect.y,
|
||||||
|
output->crtc->rect.width, output->crtc->rect.height,
|
||||||
|
output->crtc->current_mode->refresh_rate);
|
||||||
|
|
||||||
wl_resource_post_event (resource,
|
wl_resource_post_event (resource,
|
||||||
WL_OUTPUT_GEOMETRY,
|
WL_OUTPUT_GEOMETRY,
|
||||||
output->x, output->y,
|
(int)output->crtc->rect.x,
|
||||||
|
(int)output->crtc->rect.y,
|
||||||
output->width_mm,
|
output->width_mm,
|
||||||
output->height_mm,
|
output->height_mm,
|
||||||
0, /* subpixel: unknown */
|
/* Cogl values reflect XRandR values,
|
||||||
"unknown", /* make */
|
and so does wayland */
|
||||||
"unknown"); /* model */
|
output->subpixel_order,
|
||||||
|
output->vendor,
|
||||||
|
output->product,
|
||||||
|
output->crtc->transform);
|
||||||
|
|
||||||
|
g_assert (output->crtc->current_mode != NULL);
|
||||||
|
|
||||||
|
mode_flags = WL_OUTPUT_MODE_CURRENT;
|
||||||
|
if (output->crtc->current_mode == output->preferred_mode)
|
||||||
|
mode_flags |= WL_OUTPUT_MODE_PREFERRED;
|
||||||
|
|
||||||
for (l = output->modes; l; l = l->next)
|
|
||||||
{
|
|
||||||
MetaWaylandMode *mode = l->data;
|
|
||||||
wl_resource_post_event (resource,
|
wl_resource_post_event (resource,
|
||||||
WL_OUTPUT_MODE,
|
WL_OUTPUT_MODE,
|
||||||
mode->flags,
|
mode_flags,
|
||||||
mode->width,
|
(int)output->crtc->current_mode->width,
|
||||||
mode->height,
|
(int)output->crtc->current_mode->height,
|
||||||
mode->refresh);
|
(int)output->crtc->current_mode->refresh_rate);
|
||||||
}
|
|
||||||
|
if (version >= 2)
|
||||||
|
wl_resource_post_event (resource,
|
||||||
|
WL_OUTPUT_DONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_wayland_compositor_create_output (MetaWaylandCompositor *compositor,
|
wayland_output_destroy_notify (gpointer data)
|
||||||
int x,
|
|
||||||
int y,
|
|
||||||
int width,
|
|
||||||
int height,
|
|
||||||
int width_mm,
|
|
||||||
int height_mm)
|
|
||||||
{
|
{
|
||||||
MetaWaylandOutput *output = g_slice_new0 (MetaWaylandOutput);
|
MetaWaylandOutput *wayland_output = data;
|
||||||
MetaWaylandMode *mode;
|
GList *resources;
|
||||||
float final_width, final_height;
|
|
||||||
|
|
||||||
/* XXX: eventually we will support sliced stages and an output should
|
/* Make sure the destructors don't mess with the list */
|
||||||
* correspond to a slice/CoglFramebuffer, but for now we only support
|
resources = wayland_output->resources;
|
||||||
* one output so we make sure it always matches the size of the stage
|
wayland_output->resources = NULL;
|
||||||
*/
|
|
||||||
clutter_actor_set_size (compositor->stage, width, height);
|
|
||||||
|
|
||||||
/* Read back the actual size we were given.
|
wl_global_destroy (wayland_output->global);
|
||||||
* XXX: This really needs re-thinking later though so we know the
|
g_list_free (resources);
|
||||||
* correct output geometry to use. */
|
|
||||||
clutter_actor_get_size (compositor->stage, &final_width, &final_height);
|
|
||||||
width = final_width;
|
|
||||||
height = final_height;
|
|
||||||
|
|
||||||
output->wayland_output.interface = &wl_output_interface;
|
g_slice_free (MetaWaylandOutput, wayland_output);
|
||||||
|
}
|
||||||
|
|
||||||
output->x = x;
|
static void
|
||||||
output->y = y;
|
wayland_output_update_for_output (MetaWaylandOutput *wayland_output,
|
||||||
output->width_mm = width_mm;
|
MetaOutput *output)
|
||||||
output->height_mm = height_mm;
|
{
|
||||||
|
GList *iter;
|
||||||
|
guint mode_flags;
|
||||||
|
|
||||||
wl_global_create (compositor->wayland_display,
|
g_assert (output->crtc->current_mode != NULL);
|
||||||
|
|
||||||
|
mode_flags = WL_OUTPUT_MODE_CURRENT;
|
||||||
|
if (output->crtc->current_mode == output->preferred_mode)
|
||||||
|
mode_flags |= WL_OUTPUT_MODE_PREFERRED;
|
||||||
|
|
||||||
|
for (iter = wayland_output->resources; iter; iter = iter->next)
|
||||||
|
{
|
||||||
|
struct wl_resource *resource = iter->data;
|
||||||
|
|
||||||
|
if (wayland_output->x != output->crtc->rect.x ||
|
||||||
|
wayland_output->y != output->crtc->rect.y ||
|
||||||
|
wayland_output->transform != output->crtc->transform)
|
||||||
|
{
|
||||||
|
wl_resource_post_event (resource,
|
||||||
|
WL_OUTPUT_GEOMETRY,
|
||||||
|
(int)output->crtc->rect.x,
|
||||||
|
(int)output->crtc->rect.y,
|
||||||
|
output->width_mm,
|
||||||
|
output->height_mm,
|
||||||
|
output->subpixel_order,
|
||||||
|
output->vendor,
|
||||||
|
output->product,
|
||||||
|
output->crtc->transform);
|
||||||
|
}
|
||||||
|
|
||||||
|
wl_resource_post_event (resource,
|
||||||
|
WL_OUTPUT_MODE,
|
||||||
|
mode_flags,
|
||||||
|
(int)output->crtc->current_mode->width,
|
||||||
|
(int)output->crtc->current_mode->height,
|
||||||
|
(int)output->crtc->current_mode->refresh_rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* It's very important that we change the output pointer here, as
|
||||||
|
the old structure is about to be freed by MetaMonitorManager */
|
||||||
|
wayland_output->output = output;
|
||||||
|
wayland_output->x = output->crtc->rect.x;
|
||||||
|
wayland_output->y = output->crtc->rect.y;
|
||||||
|
wayland_output->transform = output->crtc->transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GHashTable *
|
||||||
|
meta_wayland_compositor_update_outputs (MetaWaylandCompositor *compositor,
|
||||||
|
MetaMonitorManager *monitors)
|
||||||
|
{
|
||||||
|
MetaOutput *outputs;
|
||||||
|
unsigned int i, n_outputs;
|
||||||
|
GHashTable *new_table;
|
||||||
|
|
||||||
|
outputs = meta_monitor_manager_get_outputs (monitors, &n_outputs);
|
||||||
|
new_table = g_hash_table_new_full (NULL, NULL, NULL, wayland_output_destroy_notify);
|
||||||
|
|
||||||
|
for (i = 0; i < n_outputs; i++)
|
||||||
|
{
|
||||||
|
MetaOutput *output = &outputs[i];
|
||||||
|
MetaWaylandOutput *wayland_output;
|
||||||
|
|
||||||
|
/* wayland does not expose disabled outputs */
|
||||||
|
if (output->crtc == NULL)
|
||||||
|
{
|
||||||
|
g_hash_table_remove (compositor->outputs, GSIZE_TO_POINTER (output->output_id));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
wayland_output = g_hash_table_lookup (compositor->outputs, GSIZE_TO_POINTER (output->output_id));
|
||||||
|
|
||||||
|
if (wayland_output)
|
||||||
|
{
|
||||||
|
g_hash_table_steal (compositor->outputs, GSIZE_TO_POINTER (output->output_id));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wayland_output = g_slice_new0 (MetaWaylandOutput);
|
||||||
|
wayland_output->global = wl_global_create (compositor->wayland_display,
|
||||||
&wl_output_interface, 2,
|
&wl_output_interface, 2,
|
||||||
output, bind_output);
|
wayland_output, bind_output);
|
||||||
|
}
|
||||||
|
|
||||||
mode = g_slice_new0 (MetaWaylandMode);
|
wayland_output_update_for_output (wayland_output, output);
|
||||||
mode->flags = WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
|
g_hash_table_insert (new_table, GSIZE_TO_POINTER (output->output_id), wayland_output);
|
||||||
mode->width = width;
|
}
|
||||||
mode->height = height;
|
|
||||||
mode->refresh = 60;
|
|
||||||
|
|
||||||
output->modes = g_list_prepend (output->modes, mode);
|
g_hash_table_destroy (compositor->outputs);
|
||||||
|
return new_table;
|
||||||
compositor->outputs = g_list_prepend (compositor->outputs, output);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const static struct wl_compositor_interface meta_wayland_compositor_interface = {
|
const static struct wl_compositor_interface meta_wayland_compositor_interface = {
|
||||||
@ -1413,11 +1516,19 @@ event_emission_hook_cb (GSignalInvocationHint *ihint,
|
|||||||
return TRUE /* stay connected */;
|
return TRUE /* stay connected */;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_monitors_changed (MetaMonitorManager *monitors,
|
||||||
|
MetaWaylandCompositor *compositor)
|
||||||
|
{
|
||||||
|
compositor->outputs = meta_wayland_compositor_update_outputs (compositor, monitors);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_wayland_init (void)
|
meta_wayland_init (void)
|
||||||
{
|
{
|
||||||
MetaWaylandCompositor *compositor = &_meta_wayland_compositor;
|
MetaWaylandCompositor *compositor = &_meta_wayland_compositor;
|
||||||
guint event_signal;
|
guint event_signal;
|
||||||
|
MetaMonitorManager *monitors;
|
||||||
|
|
||||||
memset (compositor, 0, sizeof (MetaWaylandCompositor));
|
memset (compositor, 0, sizeof (MetaWaylandCompositor));
|
||||||
|
|
||||||
@ -1457,8 +1568,15 @@ meta_wayland_init (void)
|
|||||||
if (clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS)
|
if (clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS)
|
||||||
g_error ("Failed to initialize Clutter");
|
g_error ("Failed to initialize Clutter");
|
||||||
|
|
||||||
|
meta_monitor_manager_initialize ();
|
||||||
|
monitors = meta_monitor_manager_get ();
|
||||||
|
g_signal_connect (monitors, "monitors-changed",
|
||||||
|
G_CALLBACK (on_monitors_changed), compositor);
|
||||||
|
|
||||||
|
compositor->outputs = g_hash_table_new_full (NULL, NULL, NULL, wayland_output_destroy_notify);
|
||||||
|
compositor->outputs = meta_wayland_compositor_update_outputs (compositor, monitors);
|
||||||
|
|
||||||
compositor->stage = meta_wayland_stage_new ();
|
compositor->stage = meta_wayland_stage_new ();
|
||||||
clutter_stage_set_user_resizable (CLUTTER_STAGE (compositor->stage), FALSE);
|
|
||||||
g_signal_connect_after (compositor->stage, "paint",
|
g_signal_connect_after (compositor->stage, "paint",
|
||||||
G_CALLBACK (paint_finished_cb), compositor);
|
G_CALLBACK (paint_finished_cb), compositor);
|
||||||
g_signal_connect (compositor->stage, "destroy",
|
g_signal_connect (compositor->stage, "destroy",
|
||||||
@ -1483,8 +1601,6 @@ meta_wayland_init (void)
|
|||||||
compositor, /* hook_data */
|
compositor, /* hook_data */
|
||||||
NULL /* data_destroy */);
|
NULL /* data_destroy */);
|
||||||
|
|
||||||
meta_wayland_compositor_create_output (compositor, 0, 0, 1024, 600, 222, 125);
|
|
||||||
|
|
||||||
if (wl_global_create (compositor->wayland_display,
|
if (wl_global_create (compositor->wayland_display,
|
||||||
&wl_shell_interface, 1,
|
&wl_shell_interface, 1,
|
||||||
compositor, bind_shell) == NULL)
|
compositor, bind_shell) == NULL)
|
||||||
|
Loading…
Reference in New Issue
Block a user