mirror of
https://github.com/brl/mutter.git
synced 2024-12-23 19:42:05 +00:00
MonitorConfig: add CRTC assignment
Ripped off libgnome-desktop, trimming the parts that checked that the configuration was plausible, as that should be done in gnome-control-center before asking mutter for a change. https://bugzilla.gnome.org/show_bug.cgi?id=705670
This commit is contained in:
parent
8f4621240a
commit
d0529b7482
@ -25,6 +25,15 @@
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Portions of this file are derived from gnome-desktop/libgnome-desktop/gnome-rr-config.c
|
||||
*
|
||||
* Copyright 2007, 2008, Red Hat, Inc.
|
||||
* Copyright 2010 Giovanni Campagna
|
||||
*
|
||||
* Author: Soren Sandmann <sandmann@redhat.com>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
@ -90,6 +99,11 @@ struct _MetaMonitorConfigClass {
|
||||
|
||||
G_DEFINE_TYPE (MetaMonitorConfig, meta_monitor_config, G_TYPE_OBJECT);
|
||||
|
||||
static gboolean meta_monitor_config_assign_crtcs (MetaConfiguration *config,
|
||||
MetaMonitorManager *manager,
|
||||
GPtrArray *crtcs,
|
||||
GPtrArray *outputs);
|
||||
|
||||
static void
|
||||
free_output_key (MetaOutputKey *key)
|
||||
{
|
||||
@ -774,35 +788,37 @@ meta_monitor_config_get_stored (MetaMonitorConfig *self,
|
||||
return stored;
|
||||
}
|
||||
|
||||
static void
|
||||
make_crtcs (MetaConfiguration *config,
|
||||
MetaMonitorManager *manager,
|
||||
GVariant **crtcs,
|
||||
GVariant **outputs)
|
||||
{
|
||||
*crtcs = NULL;
|
||||
*outputs = NULL;
|
||||
/* FIXME */
|
||||
}
|
||||
|
||||
static void
|
||||
static gboolean
|
||||
apply_configuration (MetaMonitorConfig *self,
|
||||
MetaConfiguration *config,
|
||||
MetaMonitorManager *manager,
|
||||
gboolean stored)
|
||||
{
|
||||
GVariant *crtcs, *outputs;
|
||||
GPtrArray *crtcs, *outputs;
|
||||
|
||||
make_crtcs (config, manager, &crtcs, &outputs);
|
||||
meta_monitor_manager_apply_configuration (manager, crtcs, outputs);
|
||||
crtcs = g_ptr_array_new_full (config->n_outputs, (GDestroyNotify)meta_crtc_info_free);
|
||||
outputs = g_ptr_array_new_full (config->n_outputs, (GDestroyNotify)meta_output_info_free);
|
||||
|
||||
if (!meta_monitor_config_assign_crtcs (config, manager, crtcs, outputs))
|
||||
{
|
||||
g_ptr_array_unref (crtcs);
|
||||
g_ptr_array_unref (outputs);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
meta_monitor_manager_apply_configuration (manager,
|
||||
(MetaCRTCInfo**)crtcs->pdata, crtcs->len,
|
||||
(MetaOutputInfo**)outputs->pdata, outputs->len);
|
||||
|
||||
if (self->current && !self->current_is_stored)
|
||||
config_free (self->current);
|
||||
self->current = config;
|
||||
self->current_is_stored = stored;
|
||||
|
||||
g_variant_unref (crtcs);
|
||||
g_variant_unref (outputs);
|
||||
g_ptr_array_unref (crtcs);
|
||||
g_ptr_array_unref (outputs);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
@ -818,8 +834,7 @@ meta_monitor_config_apply_stored (MetaMonitorConfig *self,
|
||||
|
||||
if (stored)
|
||||
{
|
||||
apply_configuration (self, stored, manager, TRUE);
|
||||
return TRUE;
|
||||
return apply_configuration (self, stored, manager, TRUE);
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
@ -1039,3 +1054,329 @@ meta_monitor_config_make_persistent (MetaMonitorConfig *self)
|
||||
|
||||
meta_monitor_config_save (self);
|
||||
}
|
||||
|
||||
/*
|
||||
* CRTC assignment
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
MetaConfiguration *config;
|
||||
MetaMonitorManager *manager;
|
||||
GHashTable *info;
|
||||
} CrtcAssignment;
|
||||
|
||||
static gboolean
|
||||
output_can_clone (MetaOutput *output,
|
||||
MetaOutput *clone)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < output->n_possible_clones; i++)
|
||||
if (output->possible_clones[i] == clone)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
can_clone (MetaCRTCInfo *info,
|
||||
MetaOutput *output)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < info->outputs->len; ++i)
|
||||
{
|
||||
MetaOutput *clone = info->outputs->pdata[i];
|
||||
|
||||
if (!output_can_clone (clone, output))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
crtc_can_drive_output (MetaCRTC *crtc,
|
||||
MetaOutput *output)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < output->n_possible_crtcs; i++)
|
||||
if (output->possible_crtcs[i] == crtc)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
output_supports_mode (MetaOutput *output,
|
||||
MetaMonitorMode *mode)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < output->n_modes; i++)
|
||||
if (output->modes[i] == mode)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
crtc_assignment_assign (CrtcAssignment *assign,
|
||||
MetaCRTC *crtc,
|
||||
MetaMonitorMode *mode,
|
||||
int x,
|
||||
int y,
|
||||
enum wl_output_transform transform,
|
||||
MetaOutput *output)
|
||||
{
|
||||
MetaCRTCInfo *info = g_hash_table_lookup (assign->info, crtc);
|
||||
|
||||
if (!crtc_can_drive_output (crtc, output))
|
||||
return FALSE;
|
||||
|
||||
if (!output_supports_mode (output, mode))
|
||||
return FALSE;
|
||||
|
||||
if ((crtc->all_transforms & (1 << transform)) == 0)
|
||||
return FALSE;
|
||||
|
||||
if (info)
|
||||
{
|
||||
if (!(info->mode == mode &&
|
||||
info->x == x &&
|
||||
info->y == y &&
|
||||
info->transform == transform))
|
||||
return FALSE;
|
||||
|
||||
if (!can_clone (info, output))
|
||||
return FALSE;
|
||||
|
||||
g_ptr_array_add (info->outputs, output);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
MetaCRTCInfo *info = g_slice_new0 (MetaCRTCInfo);
|
||||
|
||||
info->crtc = crtc;
|
||||
info->mode = mode;
|
||||
info->x = x;
|
||||
info->y = y;
|
||||
info->transform = transform;
|
||||
info->outputs = g_ptr_array_new ();
|
||||
|
||||
g_ptr_array_add (info->outputs, output);
|
||||
g_hash_table_insert (assign->info, crtc, info);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
crtc_assignment_unassign (CrtcAssignment *assign,
|
||||
MetaCRTC *crtc,
|
||||
MetaOutput *output)
|
||||
{
|
||||
MetaCRTCInfo *info = g_hash_table_lookup (assign->info, crtc);
|
||||
|
||||
if (info)
|
||||
{
|
||||
g_ptr_array_remove (info->outputs, output);
|
||||
|
||||
if (info->outputs->len == 0)
|
||||
g_hash_table_remove (assign->info, crtc);
|
||||
}
|
||||
}
|
||||
|
||||
static MetaOutput *
|
||||
find_output_by_key (MetaOutput *outputs,
|
||||
unsigned int n_outputs,
|
||||
MetaOutputKey *key)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < n_outputs; i++)
|
||||
{
|
||||
if (strcmp (outputs[i].name, key->connector) == 0)
|
||||
{
|
||||
/* This should be checked a lot earlier! */
|
||||
|
||||
g_warn_if_fail (strcmp (outputs[i].vendor, key->vendor) == 0 &&
|
||||
strcmp (outputs[i].product, key->product) == 0 &&
|
||||
strcmp (outputs[i].serial, key->serial) == 0);
|
||||
return &outputs[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* Just to satisfy GCC - this is a fatal error if occurs */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Check whether the given set of settings can be used
|
||||
* at the same time -- ie. whether there is an assignment
|
||||
* of CRTC's to outputs.
|
||||
*
|
||||
* Brute force - the number of objects involved is small
|
||||
* enough that it doesn't matter.
|
||||
*/
|
||||
static gboolean
|
||||
real_assign_crtcs (CrtcAssignment *assignment,
|
||||
unsigned int output_num)
|
||||
{
|
||||
MetaMonitorMode *modes;
|
||||
MetaCRTC *crtcs;
|
||||
MetaOutput *outputs;
|
||||
unsigned int n_crtcs, n_modes, n_outputs;
|
||||
MetaOutputKey *output_key;
|
||||
MetaOutputConfig *output_config;
|
||||
unsigned int i;
|
||||
gboolean success;
|
||||
|
||||
if (output_num == assignment->config->n_outputs)
|
||||
return TRUE;
|
||||
|
||||
output_key = &assignment->config->keys[output_num];
|
||||
output_config = &assignment->config->outputs[output_num];
|
||||
|
||||
/* It is always allowed for an output to be turned off */
|
||||
if (!output_config->enabled)
|
||||
return real_assign_crtcs (assignment, output_num + 1);
|
||||
|
||||
meta_monitor_manager_get_resources (assignment->manager,
|
||||
&modes, &n_modes,
|
||||
&crtcs, &n_crtcs,
|
||||
&outputs, &n_outputs);
|
||||
|
||||
success = FALSE;
|
||||
|
||||
for (i = 0; i < n_crtcs; i++)
|
||||
{
|
||||
MetaCRTC *crtc = &crtcs[i];
|
||||
unsigned int pass;
|
||||
|
||||
/* Make two passes, one where frequencies must match, then
|
||||
* one where they don't have to
|
||||
*/
|
||||
for (pass = 0; pass < 2; pass++)
|
||||
{
|
||||
MetaOutput *output = find_output_by_key (outputs, n_outputs, output_key);
|
||||
unsigned int j;
|
||||
|
||||
for (j = 0; j < n_modes; j++)
|
||||
{
|
||||
MetaMonitorMode *mode = &modes[j];
|
||||
int width, height;
|
||||
|
||||
if (meta_monitor_transform_is_rotated (output_config->transform))
|
||||
{
|
||||
width = mode->height;
|
||||
height = mode->width;
|
||||
}
|
||||
else
|
||||
{
|
||||
width = mode->width;
|
||||
height = mode->height;
|
||||
}
|
||||
|
||||
if (width == output_config->rect.width &&
|
||||
height == output_config->rect.height &&
|
||||
(pass == 1 || mode->refresh_rate == output_config->refresh_rate))
|
||||
{
|
||||
meta_verbose ("CRTC %ld: trying mode %dx%d@%fHz with output at %dx%d@%fHz (transform %d) (pass %d)\n",
|
||||
crtc->crtc_id,
|
||||
mode->width, mode->height, mode->refresh_rate,
|
||||
output_config->rect.width, output_config->rect.height, output_config->refresh_rate,
|
||||
output_config->transform,
|
||||
pass);
|
||||
|
||||
|
||||
if (crtc_assignment_assign (assignment, crtc, &modes[j],
|
||||
output_config->rect.x, output_config->rect.y,
|
||||
output_config->transform,
|
||||
output))
|
||||
{
|
||||
if (real_assign_crtcs (assignment, output_num + 1))
|
||||
{
|
||||
success = TRUE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
crtc_assignment_unassign (assignment, crtc, output);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
if (!success)
|
||||
meta_warning ("Could not assign CRTC to outputs, ignoring configuration\n");
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_monitor_config_assign_crtcs (MetaConfiguration *config,
|
||||
MetaMonitorManager *manager,
|
||||
GPtrArray *crtcs,
|
||||
GPtrArray *outputs)
|
||||
{
|
||||
CrtcAssignment assignment;
|
||||
GHashTableIter iter;
|
||||
MetaCRTC *crtc;
|
||||
MetaCRTCInfo *info;
|
||||
unsigned int i;
|
||||
MetaOutput *all_outputs;
|
||||
unsigned int n_outputs;
|
||||
|
||||
assignment.config = config;
|
||||
assignment.manager = manager;
|
||||
assignment.info = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)meta_crtc_info_free);
|
||||
|
||||
if (!real_assign_crtcs (&assignment, 0))
|
||||
{
|
||||
g_hash_table_destroy (assignment.info);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_hash_table_iter_init (&iter, assignment.info);
|
||||
while (g_hash_table_iter_next (&iter, (void**)&crtc, (void**)&info))
|
||||
{
|
||||
g_hash_table_iter_steal (&iter);
|
||||
g_ptr_array_add (crtcs, info);
|
||||
}
|
||||
|
||||
all_outputs = meta_monitor_manager_get_outputs (manager,
|
||||
&n_outputs);
|
||||
g_assert (n_outputs == config->n_outputs);
|
||||
|
||||
for (i = 0; i < n_outputs; i++)
|
||||
{
|
||||
MetaOutputInfo *output_info = g_slice_new (MetaOutputInfo);
|
||||
MetaOutputConfig *output_config = &config->outputs[0];
|
||||
|
||||
output_info->output = find_output_by_key (all_outputs, n_outputs,
|
||||
&config->keys[0]);
|
||||
output_info->is_primary = output_config->is_primary;
|
||||
output_info->is_presentation = output_config->is_presentation;
|
||||
|
||||
g_ptr_array_add (outputs, output_info);
|
||||
}
|
||||
|
||||
g_hash_table_destroy (assignment.info);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
meta_crtc_info_free (MetaCRTCInfo *info)
|
||||
{
|
||||
g_ptr_array_free (info->outputs, TRUE);
|
||||
g_slice_free (MetaCRTCInfo, info);
|
||||
}
|
||||
|
||||
void
|
||||
meta_output_info_free (MetaOutputInfo *info)
|
||||
{
|
||||
g_slice_free (MetaOutputInfo, info);
|
||||
}
|
||||
|
@ -65,6 +65,8 @@ typedef struct _MetaOutput MetaOutput;
|
||||
typedef struct _MetaCRTC MetaCRTC;
|
||||
typedef struct _MetaMonitorMode MetaMonitorMode;
|
||||
typedef struct _MetaMonitorInfo MetaMonitorInfo;
|
||||
typedef struct _MetaCRTCInfo MetaCRTCInfo;
|
||||
typedef struct _MetaOutputInfo MetaOutputInfo;
|
||||
|
||||
struct _MetaOutput
|
||||
{
|
||||
@ -161,6 +163,33 @@ struct _MetaMonitorInfo
|
||||
glong output_id;
|
||||
};
|
||||
|
||||
/*
|
||||
* MetaCRTCInfo:
|
||||
* This represents the writable part of a CRTC, as deserialized from DBus
|
||||
* or built by MetaMonitorConfig
|
||||
*
|
||||
* Note: differently from the other structures in this file, MetaCRTCInfo
|
||||
* is handled by pointer. This is to accomodate the usage in MetaMonitorConfig
|
||||
*/
|
||||
struct _MetaCRTCInfo {
|
||||
MetaCRTC *crtc;
|
||||
MetaMonitorMode *mode;
|
||||
int x;
|
||||
int y;
|
||||
enum wl_output_transform transform;
|
||||
GPtrArray *outputs;
|
||||
};
|
||||
|
||||
/*
|
||||
* MetaOutputInfo:
|
||||
* this is the same as MetaOutputInfo, but for CRTCs
|
||||
*/
|
||||
struct _MetaOutputInfo {
|
||||
MetaOutput *output;
|
||||
gboolean is_primary;
|
||||
gboolean is_presentation;
|
||||
};
|
||||
|
||||
#define META_TYPE_MONITOR_MANAGER (meta_monitor_manager_get_type ())
|
||||
#define META_MONITOR_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_MANAGER, MetaMonitorManager))
|
||||
#define META_MONITOR_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MONITOR_MANAGER, MetaMonitorManagerClass))
|
||||
@ -182,6 +211,14 @@ MetaMonitorInfo *meta_monitor_manager_get_monitor_infos (MetaMonitorManager *
|
||||
MetaOutput *meta_monitor_manager_get_outputs (MetaMonitorManager *manager,
|
||||
unsigned int *n_outputs);
|
||||
|
||||
void meta_monitor_manager_get_resources (MetaMonitorManager *manager,
|
||||
MetaMonitorMode **modes,
|
||||
unsigned int *n_modes,
|
||||
MetaCRTC **crtcs,
|
||||
unsigned int *n_crtcs,
|
||||
MetaOutput **outputs,
|
||||
unsigned int *n_outputs);
|
||||
|
||||
int meta_monitor_manager_get_primary_index (MetaMonitorManager *manager);
|
||||
|
||||
gboolean meta_monitor_manager_handle_xevent (MetaMonitorManager *manager,
|
||||
@ -192,8 +229,10 @@ void meta_monitor_manager_get_screen_size (MetaMonitorManager *
|
||||
int *height);
|
||||
|
||||
void meta_monitor_manager_apply_configuration (MetaMonitorManager *manager,
|
||||
GVariant *crtcs,
|
||||
GVariant *outputs);
|
||||
MetaCRTCInfo **crtcs,
|
||||
unsigned int n_crtcs,
|
||||
MetaOutputInfo **outputs,
|
||||
unsigned int n_outputs);
|
||||
|
||||
#define META_TYPE_MONITOR_CONFIG (meta_monitor_config_get_type ())
|
||||
#define META_MONITOR_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_CONFIG, MetaMonitorConfig))
|
||||
@ -222,6 +261,9 @@ void meta_monitor_config_update_current (MetaMonitorConfig *confi
|
||||
MetaMonitorManager *manager);
|
||||
void meta_monitor_config_make_persistent (MetaMonitorConfig *config);
|
||||
|
||||
void meta_crtc_info_free (MetaCRTCInfo *info);
|
||||
void meta_output_info_free (MetaOutputInfo *info);
|
||||
|
||||
/* Returns true if transform causes width and height to be inverted
|
||||
This is true for the odd transforms in the enum */
|
||||
static inline gboolean
|
||||
|
@ -1160,22 +1160,20 @@ wl_transform_to_xrandr (enum wl_output_transform transform)
|
||||
|
||||
static void
|
||||
apply_config_xrandr (MetaMonitorManager *manager,
|
||||
GVariantIter *crtcs,
|
||||
GVariantIter *outputs)
|
||||
MetaCRTCInfo **crtcs,
|
||||
unsigned int n_crtcs,
|
||||
MetaOutputInfo **outputs,
|
||||
unsigned int n_outputs)
|
||||
{
|
||||
GVariant *nested_outputs, *properties;
|
||||
guint crtc_id, output_id, transform;
|
||||
int new_mode, x, y;
|
||||
unsigned i;
|
||||
|
||||
while (g_variant_iter_loop (crtcs, "(uiiiu@aua{sv})",
|
||||
&crtc_id, &new_mode, &x, &y,
|
||||
&transform, &nested_outputs, NULL))
|
||||
for (i = 0; i < n_crtcs; i++)
|
||||
{
|
||||
MetaCRTC *crtc = &manager->crtcs[crtc_id];
|
||||
MetaCRTCInfo *crtc_info = crtcs[i];
|
||||
MetaCRTC *crtc = crtc_info->crtc;
|
||||
crtc->is_dirty = TRUE;
|
||||
|
||||
if (new_mode == -1)
|
||||
if (crtc_info->mode == NULL)
|
||||
{
|
||||
XRRSetCrtcConfig (manager->xdisplay,
|
||||
manager->resources,
|
||||
@ -1190,54 +1188,47 @@ apply_config_xrandr (MetaMonitorManager *manager,
|
||||
{
|
||||
MetaMonitorMode *mode;
|
||||
XID *outputs;
|
||||
int i, n_outputs;
|
||||
guint output_id;
|
||||
int j, n_outputs;
|
||||
Status ok;
|
||||
|
||||
mode = &manager->modes[new_mode];
|
||||
mode = crtc_info->mode;
|
||||
|
||||
n_outputs = g_variant_n_children (nested_outputs);
|
||||
n_outputs = crtc_info->outputs->len;
|
||||
outputs = g_new (XID, n_outputs);
|
||||
|
||||
for (i = 0; i < n_outputs; i++)
|
||||
{
|
||||
g_variant_get_child (nested_outputs, i, "u", &output_id);
|
||||
|
||||
outputs[i] = manager->outputs[output_id].output_id;
|
||||
}
|
||||
for (j = 0; j < n_outputs; j++)
|
||||
outputs[i] = ((MetaOutput**)crtc_info->outputs->pdata)[i]->output_id;
|
||||
|
||||
meta_error_trap_push (meta_get_display ());
|
||||
ok = XRRSetCrtcConfig (manager->xdisplay,
|
||||
manager->resources,
|
||||
(XID)crtc->crtc_id,
|
||||
manager->time,
|
||||
x, y,
|
||||
crtc_info->x, crtc_info->y,
|
||||
(XID)mode->mode_id,
|
||||
wl_transform_to_xrandr (transform),
|
||||
wl_transform_to_xrandr (crtc_info->transform),
|
||||
outputs, n_outputs);
|
||||
meta_error_trap_pop (meta_get_display ());
|
||||
|
||||
if (ok != Success)
|
||||
meta_warning ("Configuring CRTC %d with mode %d (%d x %d @ %f) at position %d, %d and transfrom %u failed\n",
|
||||
(unsigned)(crtc->crtc_id), (unsigned)(mode->mode_id),
|
||||
mode->width, mode->height, (float)mode->refresh_rate, x, y, transform);
|
||||
mode->width, mode->height, (float)mode->refresh_rate,
|
||||
crtc_info->x, crtc_info->y, crtc_info->transform);
|
||||
|
||||
g_free (outputs);
|
||||
}
|
||||
}
|
||||
|
||||
while (g_variant_iter_loop (outputs, "(u@a{sv})",
|
||||
&output_id, &properties))
|
||||
for (i = 0; i < n_outputs; i++)
|
||||
{
|
||||
gboolean primary;
|
||||
MetaOutputInfo *output_info = outputs[i];
|
||||
|
||||
if (g_variant_lookup (properties, "primary", "b", &primary) && primary)
|
||||
if (output_info->is_primary)
|
||||
{
|
||||
MetaOutput *output = &manager->outputs[output_id];
|
||||
|
||||
XRRSetOutputPrimary (manager->xdisplay,
|
||||
DefaultRootWindow (manager->xdisplay),
|
||||
(XID)output->output_id);
|
||||
(XID)output_info->output->output_id);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1268,23 +1259,21 @@ apply_config_xrandr (MetaMonitorManager *manager,
|
||||
|
||||
static void
|
||||
apply_config_dummy (MetaMonitorManager *manager,
|
||||
GVariantIter *crtcs,
|
||||
GVariantIter *outputs)
|
||||
MetaCRTCInfo **crtcs,
|
||||
unsigned int n_crtcs,
|
||||
MetaOutputInfo **outputs,
|
||||
unsigned int n_outputs)
|
||||
{
|
||||
GVariant *nested_outputs, *properties;
|
||||
guint crtc_id, output_id, transform;
|
||||
int new_mode, x, y;
|
||||
unsigned i;
|
||||
int screen_width = 0, screen_height = 0;
|
||||
|
||||
while (g_variant_iter_loop (crtcs, "(uiiiu@aua{sv})",
|
||||
&crtc_id, &new_mode, &x, &y,
|
||||
&transform, &nested_outputs, NULL))
|
||||
for (i = 0; i < n_crtcs; i++)
|
||||
{
|
||||
MetaCRTC *crtc = &manager->crtcs[crtc_id];
|
||||
MetaCRTCInfo *crtc_info = crtcs[i];
|
||||
MetaCRTC *crtc = crtc_info->crtc;
|
||||
crtc->is_dirty = TRUE;
|
||||
|
||||
if (new_mode == -1)
|
||||
if (crtc_info->mode == NULL)
|
||||
{
|
||||
crtc->rect.x = 0;
|
||||
crtc->rect.y = 0;
|
||||
@ -1297,12 +1286,11 @@ apply_config_dummy (MetaMonitorManager *manager,
|
||||
MetaMonitorMode *mode;
|
||||
MetaOutput *output;
|
||||
int i, n_outputs;
|
||||
guint output_id;
|
||||
int width, height;
|
||||
|
||||
mode = &manager->modes[new_mode];
|
||||
mode = crtc_info->mode;
|
||||
|
||||
if (meta_monitor_transform_is_rotated (transform))
|
||||
if (meta_monitor_transform_is_rotated (crtc_info->transform))
|
||||
{
|
||||
width = mode->height;
|
||||
height = mode->width;
|
||||
@ -1313,22 +1301,20 @@ apply_config_dummy (MetaMonitorManager *manager,
|
||||
height = mode->height;
|
||||
}
|
||||
|
||||
crtc->rect.x = x;
|
||||
crtc->rect.y = y;
|
||||
crtc->rect.x = crtc_info->x;
|
||||
crtc->rect.y = crtc_info->y;
|
||||
crtc->rect.width = width;
|
||||
crtc->rect.height = height;
|
||||
crtc->current_mode = mode;
|
||||
crtc->transform = transform;
|
||||
crtc->transform = crtc_info->transform;
|
||||
|
||||
screen_width = MAX (screen_width, x + width);
|
||||
screen_height = MAX (screen_height, y + height);
|
||||
screen_width = MAX (screen_width, crtc_info->x + width);
|
||||
screen_height = MAX (screen_height, crtc_info->y + height);
|
||||
|
||||
n_outputs = g_variant_n_children (nested_outputs);
|
||||
n_outputs = crtc_info->outputs->len;
|
||||
for (i = 0; i < n_outputs; i++)
|
||||
{
|
||||
g_variant_get_child (nested_outputs, i, "u", &output_id);
|
||||
|
||||
output = &manager->outputs[output_id];
|
||||
output = ((MetaOutput**)crtc_info->outputs->pdata)[i];
|
||||
|
||||
output->is_dirty = TRUE;
|
||||
output->crtc = crtc;
|
||||
@ -1336,17 +1322,13 @@ apply_config_dummy (MetaMonitorManager *manager,
|
||||
}
|
||||
}
|
||||
|
||||
while (g_variant_iter_loop (outputs, "(u@a{sv})",
|
||||
&output_id, &properties))
|
||||
for (i = 0; i < n_outputs; i++)
|
||||
{
|
||||
MetaOutput *output = &manager->outputs[output_id];
|
||||
gboolean primary, presentation;
|
||||
MetaOutputInfo *output_info = outputs[i];
|
||||
MetaOutput *output = output_info->output;
|
||||
|
||||
if (g_variant_lookup (properties, "primary", "b", &primary))
|
||||
output->is_primary = primary;
|
||||
|
||||
if (g_variant_lookup (properties, "presentation", "b", &presentation))
|
||||
output->is_presentation = presentation;
|
||||
output->is_primary = output_info->is_primary;
|
||||
output->is_presentation = output_info->is_presentation;
|
||||
}
|
||||
|
||||
/* Disable CRTCs not mentioned in the list */
|
||||
@ -1392,18 +1374,15 @@ apply_config_dummy (MetaMonitorManager *manager,
|
||||
|
||||
void
|
||||
meta_monitor_manager_apply_configuration (MetaMonitorManager *manager,
|
||||
GVariant *crtcs,
|
||||
GVariant *outputs)
|
||||
MetaCRTCInfo **crtcs,
|
||||
unsigned int n_crtcs,
|
||||
MetaOutputInfo **outputs,
|
||||
unsigned int n_outputs)
|
||||
{
|
||||
GVariantIter crtc_iter, output_iter;
|
||||
|
||||
g_variant_iter_init (&crtc_iter, crtcs);
|
||||
g_variant_iter_init (&output_iter, outputs);
|
||||
|
||||
if (manager->backend == META_BACKEND_XRANDR)
|
||||
apply_config_xrandr (manager, &crtc_iter, &output_iter);
|
||||
apply_config_xrandr (manager, crtcs, n_crtcs, outputs, n_outputs);
|
||||
else
|
||||
apply_config_dummy (manager, &crtc_iter, &output_iter);
|
||||
apply_config_dummy (manager, crtcs, n_crtcs, outputs, n_outputs);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -1426,10 +1405,12 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
|
||||
{
|
||||
MetaMonitorManager *manager = META_MONITOR_MANAGER (skeleton);
|
||||
GVariantIter crtc_iter, output_iter, *nested_outputs;
|
||||
GVariant *properties;
|
||||
guint crtc_id;
|
||||
int new_mode, x, y;
|
||||
guint transform;
|
||||
guint output_id;
|
||||
GPtrArray *crtc_infos, *output_infos;
|
||||
|
||||
if (serial != manager->serial)
|
||||
{
|
||||
@ -1439,17 +1420,26 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
crtc_infos = g_ptr_array_new_full (g_variant_n_children (crtcs),
|
||||
(GDestroyNotify) meta_crtc_info_free);
|
||||
output_infos = g_ptr_array_new_full (g_variant_n_children (outputs),
|
||||
(GDestroyNotify) meta_output_info_free);
|
||||
|
||||
/* Validate all arguments */
|
||||
g_variant_iter_init (&crtc_iter, crtcs);
|
||||
while (g_variant_iter_loop (&crtc_iter, "(uiiiuaua{sv})",
|
||||
&crtc_id, &new_mode, &x, &y, &transform,
|
||||
&nested_outputs, NULL))
|
||||
{
|
||||
MetaCRTCInfo *crtc_info;
|
||||
MetaOutput *first_output;
|
||||
MetaCRTC *crtc;
|
||||
MetaMonitorMode *mode;
|
||||
guint output_id;
|
||||
|
||||
crtc_info = g_slice_new (MetaCRTCInfo);
|
||||
crtc_info->outputs = g_ptr_array_new ();
|
||||
|
||||
if (crtc_id >= manager->n_crtcs)
|
||||
{
|
||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||
@ -1458,6 +1448,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
|
||||
return TRUE;
|
||||
}
|
||||
crtc = &manager->crtcs[crtc_id];
|
||||
crtc_info->crtc = crtc;
|
||||
|
||||
if (new_mode != -1 && (new_mode < 0 || (unsigned)new_mode >= manager->n_modes))
|
||||
{
|
||||
@ -1467,6 +1458,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
|
||||
return TRUE;
|
||||
}
|
||||
mode = new_mode != -1 ? &manager->modes[new_mode] : NULL;
|
||||
crtc_info->mode = mode;
|
||||
|
||||
if (mode)
|
||||
{
|
||||
@ -1494,6 +1486,8 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
crtc_info->x = x;
|
||||
crtc_info->y = y;
|
||||
|
||||
if (transform < WL_OUTPUT_TRANSFORM_NORMAL ||
|
||||
transform > WL_OUTPUT_TRANSFORM_FLIPPED_270 ||
|
||||
@ -1504,6 +1498,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
|
||||
"Invalid transform");
|
||||
return TRUE;
|
||||
}
|
||||
crtc_info->transform = transform;
|
||||
|
||||
first_output = NULL;
|
||||
while (g_variant_iter_loop (nested_outputs, "u", &output_id))
|
||||
@ -1526,6 +1521,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
|
||||
"Output cannot be assigned to this CRTC or mode");
|
||||
return TRUE;
|
||||
}
|
||||
g_ptr_array_add (crtc_info->outputs, output);
|
||||
|
||||
if (first_output)
|
||||
{
|
||||
@ -1551,8 +1547,11 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
|
||||
}
|
||||
|
||||
g_variant_iter_init (&output_iter, outputs);
|
||||
while (g_variant_iter_loop (&output_iter, "(ua{sv})", &output_id, NULL))
|
||||
while (g_variant_iter_loop (&output_iter, "(u@a{sv})", &output_id, &properties))
|
||||
{
|
||||
MetaOutputInfo *output_info;
|
||||
gboolean primary, presentation;
|
||||
|
||||
if (output_id >= manager->n_outputs)
|
||||
{
|
||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||
@ -1560,6 +1559,15 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
|
||||
"Invalid output id");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
output_info = g_slice_new0 (MetaOutputInfo);
|
||||
output_info->output = &manager->outputs[output_id];
|
||||
|
||||
if (g_variant_lookup (properties, "primary", "b", &primary))
|
||||
output_info->is_primary = primary;
|
||||
|
||||
if (g_variant_lookup (properties, "presentation", "b", &presentation))
|
||||
output_info->is_presentation = presentation;
|
||||
}
|
||||
|
||||
/* If we were in progress of making a persistent change and we see a
|
||||
@ -1572,7 +1580,14 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
|
||||
manager->persistent_timeout_id = 0;
|
||||
}
|
||||
|
||||
meta_monitor_manager_apply_configuration (manager, crtcs, outputs);
|
||||
meta_monitor_manager_apply_configuration (manager,
|
||||
(MetaCRTCInfo**)crtc_infos->pdata,
|
||||
crtc_infos->len,
|
||||
(MetaOutputInfo**)output_infos->pdata,
|
||||
output_infos->len);
|
||||
|
||||
g_ptr_array_unref (crtc_infos);
|
||||
g_ptr_array_unref (output_infos);
|
||||
|
||||
/* Update MetaMonitorConfig data structures immediately so that we
|
||||
don't revert the change at the next XRandR event, then wait 20
|
||||
@ -1671,6 +1686,23 @@ meta_monitor_manager_get_outputs (MetaMonitorManager *manager,
|
||||
return manager->outputs;
|
||||
}
|
||||
|
||||
void
|
||||
meta_monitor_manager_get_resources (MetaMonitorManager *manager,
|
||||
MetaMonitorMode **modes,
|
||||
unsigned int *n_modes,
|
||||
MetaCRTC **crtcs,
|
||||
unsigned int *n_crtcs,
|
||||
MetaOutput **outputs,
|
||||
unsigned int *n_outputs)
|
||||
{
|
||||
*modes = manager->modes;
|
||||
*n_modes = manager->n_modes;
|
||||
*crtcs = manager->crtcs;
|
||||
*n_crtcs = manager->n_crtcs;
|
||||
*outputs = manager->outputs;
|
||||
*n_outputs = manager->n_outputs;
|
||||
}
|
||||
|
||||
int
|
||||
meta_monitor_manager_get_primary_index (MetaMonitorManager *manager)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user