mirror of
https://github.com/brl/mutter.git
synced 2024-11-10 07:56:14 -05:00
monitor-manager: Generate logical monitors from monitors
Instead of using crtcs and outputs to generate logical monitors, use the ready made monitor abstraction that hides irrelevant things such as monitor tiling etc. https://bugzilla.gnome.org/show_bug.cgi?id=777732
This commit is contained in:
parent
f48acd8448
commit
bf8b4e9927
@ -25,6 +25,105 @@
|
||||
|
||||
G_DEFINE_TYPE (MetaLogicalMonitor, meta_logical_monitor, G_TYPE_OBJECT)
|
||||
|
||||
MetaLogicalMonitor *
|
||||
meta_logical_monitor_new (MetaMonitor *monitor,
|
||||
int x,
|
||||
int y,
|
||||
int number)
|
||||
{
|
||||
MetaLogicalMonitor *logical_monitor;
|
||||
MetaOutput *main_output;
|
||||
GList *outputs;
|
||||
GList *l;
|
||||
gboolean is_presentation;
|
||||
int i;
|
||||
|
||||
g_assert (meta_monitor_is_active (monitor));
|
||||
|
||||
logical_monitor = g_object_new (META_TYPE_LOGICAL_MONITOR, NULL);
|
||||
|
||||
main_output = meta_monitor_get_main_output (monitor);
|
||||
logical_monitor->number = number;
|
||||
logical_monitor->refresh_rate = main_output->crtc->current_mode->refresh_rate;
|
||||
logical_monitor->width_mm = main_output->width_mm;
|
||||
logical_monitor->height_mm = main_output->height_mm;
|
||||
logical_monitor->winsys_id = main_output->winsys_id;
|
||||
logical_monitor->scale = main_output->scale;
|
||||
logical_monitor->in_fullscreen = -1;
|
||||
|
||||
logical_monitor->rect.x = x;
|
||||
logical_monitor->rect.y = y;
|
||||
meta_monitor_get_dimensions (monitor,
|
||||
&logical_monitor->rect.width,
|
||||
&logical_monitor->rect.height);
|
||||
|
||||
is_presentation = TRUE;
|
||||
outputs = meta_monitor_get_outputs (monitor);
|
||||
for (l = outputs, i = 0; l; l = l->next, i++)
|
||||
{
|
||||
MetaOutput *output = l->data;
|
||||
|
||||
output->crtc->logical_monitor = logical_monitor;
|
||||
|
||||
if (i <= META_MAX_OUTPUTS_PER_MONITOR)
|
||||
logical_monitor->outputs[i] = output;
|
||||
else
|
||||
g_warning ("Couldn't add all outputs to monitor");
|
||||
|
||||
is_presentation = is_presentation && output->is_presentation;
|
||||
}
|
||||
logical_monitor->n_outputs = MIN (i, META_MAX_OUTPUTS_PER_MONITOR);
|
||||
logical_monitor->is_presentation = is_presentation;
|
||||
|
||||
logical_monitor->monitors = g_list_append (logical_monitor->monitors,
|
||||
monitor);
|
||||
|
||||
return logical_monitor;
|
||||
}
|
||||
|
||||
void
|
||||
meta_logical_monitor_add_monitor (MetaLogicalMonitor *logical_monitor,
|
||||
MetaMonitor *monitor)
|
||||
{
|
||||
GList *outputs;
|
||||
GList *l;
|
||||
gboolean is_presentation;
|
||||
int i;
|
||||
|
||||
is_presentation = logical_monitor->is_presentation;
|
||||
logical_monitor->monitors = g_list_append (logical_monitor->monitors,
|
||||
monitor);
|
||||
|
||||
outputs = meta_monitor_get_outputs (monitor);
|
||||
for (l = outputs, i = logical_monitor->n_outputs; l; l = l->next, i++)
|
||||
{
|
||||
MetaOutput *output = l->data;
|
||||
|
||||
output->crtc->logical_monitor = logical_monitor;
|
||||
|
||||
if (i <= META_MAX_OUTPUTS_PER_MONITOR)
|
||||
logical_monitor->outputs[i] = output;
|
||||
else
|
||||
g_warning ("Couldn't add all outputs to monitor");
|
||||
|
||||
is_presentation = is_presentation && output->is_presentation;
|
||||
}
|
||||
logical_monitor->n_outputs = MIN (i, META_MAX_OUTPUTS_PER_MONITOR);
|
||||
logical_monitor->is_presentation = is_presentation;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_logical_monitor_is_primary (MetaLogicalMonitor *logical_monitor)
|
||||
{
|
||||
return logical_monitor->is_primary;
|
||||
}
|
||||
|
||||
void
|
||||
meta_logical_monitor_make_primary (MetaLogicalMonitor *logical_monitor)
|
||||
{
|
||||
logical_monitor->is_primary = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_logical_monitor_init (MetaLogicalMonitor *logical_monitor)
|
||||
{
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "backends/meta-monitor.h"
|
||||
#include "backends/meta-monitor-manager-private.h"
|
||||
#include "meta/boxes.h"
|
||||
|
||||
@ -54,11 +55,11 @@ struct _MetaLogicalMonitor
|
||||
*/
|
||||
glong winsys_id;
|
||||
|
||||
guint32 tile_group_id;
|
||||
|
||||
int monitor_winsys_xid;
|
||||
int n_outputs;
|
||||
MetaOutput *outputs[META_MAX_OUTPUTS_PER_MONITOR];
|
||||
|
||||
GList *monitors;
|
||||
};
|
||||
|
||||
#define META_TYPE_LOGICAL_MONITOR (meta_logical_monitor_get_type ())
|
||||
@ -66,4 +67,16 @@ G_DECLARE_FINAL_TYPE (MetaLogicalMonitor, meta_logical_monitor,
|
||||
META, LOGICAL_MONITOR,
|
||||
GObject)
|
||||
|
||||
MetaLogicalMonitor * meta_logical_monitor_new (MetaMonitor *monitor,
|
||||
int x,
|
||||
int y,
|
||||
int number);
|
||||
|
||||
void meta_logical_monitor_add_monitor (MetaLogicalMonitor *logical_monitor,
|
||||
MetaMonitor *monitor);
|
||||
|
||||
gboolean meta_logical_monitor_is_primary (MetaLogicalMonitor *logical_monitor);
|
||||
|
||||
void meta_logical_monitor_make_primary (MetaLogicalMonitor *logical_monitor);
|
||||
|
||||
#endif /* META_LOGICAL_MONITOR_H */
|
||||
|
@ -73,227 +73,94 @@ meta_monitor_manager_init (MetaMonitorManager *manager)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_manager_set_primary_logical_monitor (MetaMonitorManager *manager,
|
||||
MetaLogicalMonitor *logical_monitor)
|
||||
{
|
||||
manager->primary_logical_monitor = logical_monitor;
|
||||
if (logical_monitor)
|
||||
meta_logical_monitor_make_primary (logical_monitor);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_main_tiled_monitor_output (MetaOutput *output)
|
||||
{
|
||||
return output->tile_info.loc_h_tile == 0 && output->tile_info.loc_v_tile == 0;
|
||||
}
|
||||
|
||||
static void
|
||||
calculate_tiled_monitor_size (MetaMonitorManager *manager,
|
||||
uint32_t tile_group_id,
|
||||
int *out_width,
|
||||
int *out_height)
|
||||
{
|
||||
int width, height;
|
||||
unsigned int i;
|
||||
|
||||
width = 0;
|
||||
height = 0;
|
||||
for (i = 0; i < manager->n_outputs; i++)
|
||||
{
|
||||
MetaOutput *output = &manager->outputs[i];
|
||||
|
||||
if (output->tile_info.group_id != tile_group_id)
|
||||
continue;
|
||||
|
||||
if (output->tile_info.loc_v_tile == 0)
|
||||
width += output->tile_info.tile_w;
|
||||
|
||||
if (output->tile_info.loc_h_tile == 0)
|
||||
height += output->tile_info.tile_h;
|
||||
}
|
||||
|
||||
*out_width = width;
|
||||
*out_height = height;
|
||||
}
|
||||
|
||||
static void
|
||||
add_tiled_monitor_outputs (MetaMonitorManager *manager,
|
||||
MetaLogicalMonitor *logical_monitor,
|
||||
uint32_t tile_group_id)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < manager->n_outputs; i++)
|
||||
{
|
||||
MetaOutput *output = &manager->outputs[i];
|
||||
|
||||
if (output->tile_info.group_id != tile_group_id)
|
||||
continue;
|
||||
|
||||
if (logical_monitor->n_outputs > META_MAX_OUTPUTS_PER_MONITOR)
|
||||
{
|
||||
g_warning ("Couldn't add all outputs to monitor");
|
||||
return;
|
||||
}
|
||||
|
||||
logical_monitor->outputs[logical_monitor->n_outputs] = output;
|
||||
logical_monitor->n_outputs++;
|
||||
}
|
||||
}
|
||||
|
||||
static MetaLogicalMonitor *
|
||||
construct_tile_monitor (MetaMonitorManager *manager,
|
||||
MetaOutput *output,
|
||||
int monitor_number)
|
||||
logical_monitor_from_layout (MetaMonitorManager *manager,
|
||||
GList *logical_monitors,
|
||||
MetaRectangle *layout)
|
||||
{
|
||||
MetaLogicalMonitor *logical_monitor = NULL;
|
||||
|
||||
logical_monitor = g_object_new (META_TYPE_LOGICAL_MONITOR, NULL);
|
||||
|
||||
logical_monitor->tile_group_id = output->tile_info.group_id;
|
||||
logical_monitor->refresh_rate = output->crtc->current_mode->refresh_rate;
|
||||
logical_monitor->width_mm = output->width_mm;
|
||||
logical_monitor->height_mm = output->height_mm;
|
||||
logical_monitor->winsys_id = output->winsys_id;
|
||||
|
||||
logical_monitor->scale = output->scale;
|
||||
logical_monitor->rect.x = output->crtc->rect.x;
|
||||
logical_monitor->rect.y = output->crtc->rect.y;
|
||||
calculate_tiled_monitor_size (manager, output->tile_info.group_id,
|
||||
&logical_monitor->rect.width,
|
||||
&logical_monitor->rect.height);
|
||||
|
||||
add_tiled_monitor_outputs (manager, logical_monitor,
|
||||
output->tile_info.group_id);
|
||||
|
||||
return logical_monitor;
|
||||
}
|
||||
|
||||
/*
|
||||
* make_logical_config:
|
||||
*
|
||||
* Turn outputs and CRTCs into logical MetaLogicalMonitor,
|
||||
* that will be used by the core and API layer (MetaScreen
|
||||
* and friends)
|
||||
*/
|
||||
static void
|
||||
make_logical_config (MetaMonitorManager *manager)
|
||||
{
|
||||
MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_GET_CLASS (manager);
|
||||
GList *logical_monitors = NULL;
|
||||
int monitor_number;
|
||||
unsigned int i;
|
||||
|
||||
monitor_number = 0;
|
||||
|
||||
/* Walk the list of MetaCrtcs, and build a MetaLogicalMonitor
|
||||
for each of them, unless they reference a rectangle that
|
||||
is already there.
|
||||
*/
|
||||
/* for tiling we need to work out how many tiled outputs there are */
|
||||
for (i = 0; i < manager->n_outputs; i++)
|
||||
{
|
||||
MetaOutput *output = &manager->outputs[i];
|
||||
|
||||
if (!output->crtc)
|
||||
continue;
|
||||
|
||||
if (!output->tile_info.group_id)
|
||||
continue;
|
||||
|
||||
if (is_main_tiled_monitor_output (output))
|
||||
{
|
||||
MetaLogicalMonitor *logical_monitor;
|
||||
|
||||
logical_monitor = construct_tile_monitor (manager,
|
||||
output,
|
||||
monitor_number);
|
||||
|
||||
logical_monitors = g_list_append (logical_monitors, logical_monitor);
|
||||
monitor_number++;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < manager->n_crtcs; i++)
|
||||
{
|
||||
MetaCrtc *crtc = &manager->crtcs[i];
|
||||
GList *l;
|
||||
|
||||
/* Ignore CRTCs not in use */
|
||||
if (crtc->current_mode == NULL)
|
||||
continue;
|
||||
|
||||
for (l = logical_monitors; l; l = l->next)
|
||||
{
|
||||
MetaLogicalMonitor *logical_monitor = l->data;
|
||||
|
||||
if (meta_rectangle_contains_rect (&logical_monitor->rect,
|
||||
&crtc->rect))
|
||||
{
|
||||
crtc->logical_monitor = logical_monitor;
|
||||
break;
|
||||
}
|
||||
if (meta_rectangle_equal (layout, &logical_monitor->rect))
|
||||
return logical_monitor;
|
||||
}
|
||||
|
||||
if (crtc->logical_monitor == NULL)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
derive_monitor_position (MetaMonitor *monitor,
|
||||
int *x,
|
||||
int *y)
|
||||
{
|
||||
MetaOutput *main_output;
|
||||
|
||||
main_output = meta_monitor_get_main_output (monitor);
|
||||
|
||||
*x = main_output->crtc->rect.x;
|
||||
*y = main_output->crtc->rect.y;
|
||||
}
|
||||
|
||||
static void
|
||||
make_logical_config (MetaMonitorManager *manager)
|
||||
{
|
||||
MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_GET_CLASS (manager);
|
||||
GList *logical_monitors = NULL;
|
||||
GList *l;
|
||||
int monitor_number;
|
||||
MetaLogicalMonitor *primary_logical_monitor = NULL;
|
||||
|
||||
monitor_number = 0;
|
||||
|
||||
for (l = manager->monitors; l; l = l->next)
|
||||
{
|
||||
MetaMonitor *monitor = l->data;
|
||||
MetaLogicalMonitor *logical_monitor;
|
||||
MetaRectangle layout;
|
||||
|
||||
logical_monitor = g_object_new (META_TYPE_LOGICAL_MONITOR, NULL);
|
||||
if (!meta_monitor_is_active (monitor))
|
||||
continue;
|
||||
|
||||
logical_monitor->number = monitor_number;
|
||||
logical_monitor->rect = crtc->rect;
|
||||
logical_monitor->refresh_rate = crtc->current_mode->refresh_rate;
|
||||
logical_monitor->scale = 1;
|
||||
logical_monitor->is_primary = FALSE;
|
||||
/* This starts true because we want
|
||||
is_presentation only if all outputs are
|
||||
marked as such (while for primary it's enough
|
||||
that any is marked)
|
||||
*/
|
||||
logical_monitor->is_presentation = TRUE;
|
||||
logical_monitor->in_fullscreen = -1;
|
||||
derive_monitor_position (monitor, &layout.x, &layout.y);
|
||||
meta_monitor_get_dimensions (monitor, &layout.width, &layout.height);
|
||||
logical_monitor = logical_monitor_from_layout (manager, logical_monitors,
|
||||
&layout);
|
||||
if (logical_monitor)
|
||||
{
|
||||
meta_logical_monitor_add_monitor (logical_monitor, monitor);
|
||||
}
|
||||
else
|
||||
{
|
||||
int x, y;
|
||||
|
||||
derive_monitor_position (monitor, &x, &y);
|
||||
logical_monitor = meta_logical_monitor_new (monitor,
|
||||
x, y,
|
||||
monitor_number);
|
||||
logical_monitors = g_list_append (logical_monitors, logical_monitor);
|
||||
monitor_number++;
|
||||
|
||||
crtc->logical_monitor = logical_monitor;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now walk the list of outputs applying extended properties (primary
|
||||
and presentation)
|
||||
*/
|
||||
manager->primary_logical_monitor = NULL;
|
||||
for (i = 0; i < manager->n_outputs; i++)
|
||||
{
|
||||
MetaOutput *output;
|
||||
MetaLogicalMonitor *logical_monitor;
|
||||
|
||||
output = &manager->outputs[i];
|
||||
|
||||
/* Ignore outputs that are not active */
|
||||
if (output->crtc == NULL)
|
||||
continue;
|
||||
|
||||
if (output->tile_info.group_id)
|
||||
continue;
|
||||
|
||||
/* We must have a logical monitor on every CRTC at this point */
|
||||
g_assert (output->crtc->logical_monitor != NULL);
|
||||
|
||||
logical_monitor = output->crtc->logical_monitor;
|
||||
|
||||
logical_monitor->is_primary =
|
||||
logical_monitor->is_primary || output->is_primary;
|
||||
logical_monitor->is_presentation =
|
||||
logical_monitor->is_presentation && output->is_presentation;
|
||||
|
||||
logical_monitor->width_mm = output->width_mm;
|
||||
logical_monitor->height_mm = output->height_mm;
|
||||
|
||||
logical_monitor->outputs[0] = output;
|
||||
logical_monitor->n_outputs = 1;
|
||||
|
||||
logical_monitor->scale = output->scale;
|
||||
|
||||
if (output->is_primary || logical_monitor->winsys_id == 0)
|
||||
logical_monitor->winsys_id = output->winsys_id;
|
||||
|
||||
if (logical_monitor->is_primary)
|
||||
manager->primary_logical_monitor = logical_monitor;
|
||||
if (meta_monitor_is_primary (monitor))
|
||||
primary_logical_monitor = logical_monitor;
|
||||
}
|
||||
|
||||
manager->logical_monitors = logical_monitors;
|
||||
@ -302,8 +169,11 @@ make_logical_config (MetaMonitorManager *manager)
|
||||
* If no monitor was marked as primary, fall back on marking the first
|
||||
* logical monitor the primary one.
|
||||
*/
|
||||
if (!manager->primary_logical_monitor && manager->logical_monitors)
|
||||
manager->primary_logical_monitor = g_list_first (manager->logical_monitors)->data;
|
||||
if (!primary_logical_monitor && manager->logical_monitors)
|
||||
primary_logical_monitor = g_list_first (manager->logical_monitors)->data;
|
||||
|
||||
meta_monitor_manager_set_primary_logical_monitor (manager,
|
||||
primary_logical_monitor);
|
||||
|
||||
if (manager_class->add_monitor)
|
||||
{
|
||||
|
@ -69,7 +69,7 @@ meta_monitor_get_outputs (MetaMonitor *monitor)
|
||||
return priv->outputs;
|
||||
}
|
||||
|
||||
static MetaOutput *
|
||||
MetaOutput *
|
||||
meta_monitor_get_main_output (MetaMonitor *monitor)
|
||||
{
|
||||
return META_MONITOR_GET_CLASS (monitor)->get_main_output (monitor);
|
||||
@ -85,6 +85,16 @@ meta_monitor_is_active (MetaMonitor *monitor)
|
||||
return output->crtc && output->crtc->current_mode;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_monitor_is_primary (MetaMonitor *monitor)
|
||||
{
|
||||
MetaOutput *output;
|
||||
|
||||
output = meta_monitor_get_main_output (monitor);
|
||||
|
||||
return output->is_primary;
|
||||
}
|
||||
|
||||
void
|
||||
meta_monitor_get_dimensions (MetaMonitor *monitor,
|
||||
int *width,
|
||||
|
@ -56,6 +56,10 @@ MetaMonitorNormal * meta_monitor_normal_new (MetaOutput *output);
|
||||
|
||||
gboolean meta_monitor_is_active (MetaMonitor *monitor);
|
||||
|
||||
MetaOutput * meta_monitor_get_main_output (MetaMonitor *monitor);
|
||||
|
||||
gboolean meta_monitor_is_primary (MetaMonitor *monitor);
|
||||
|
||||
GList * meta_monitor_get_outputs (MetaMonitor *monitor);
|
||||
|
||||
void meta_monitor_get_dimensions (MetaMonitor *monitor,
|
||||
|
Loading…
Reference in New Issue
Block a user