monitor-config-store: Detect unkown layout modes based on the configuration
When there is no layout mode set in a logical monitor config, we currently just assume the configuration matches the mode that the system expects. This blows up when the layout mode expected by the system changes (eg. by turning on "scale-monitor-framebuffers" in mutter): Suddenly configs fail the validation check and get thrown away. Since we now can add one configuration for each layout mode to the config store, we can do better here: Let's only add configurations to the store where we verified beforehand that the monitor layout is compatible with that mode, either because we set it ourselves using the <layout_mode> key, or by detecting which modes the layout is compatible with. Also update monitor config ifiles to adjust for the new layout_mode, as they all are assumed to be "logical". Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3596>
This commit is contained in:
parent
becee89fb9
commit
bbb34c2a80
1 changed files with 159 additions and 99 deletions
|
@ -25,6 +25,7 @@
|
|||
#include <string.h>
|
||||
|
||||
#include "backends/meta-monitor-config-manager.h"
|
||||
#include "backends/meta-monitor-config-utils.h"
|
||||
|
||||
#define MONITORS_CONFIG_XML_FORMAT_VERSION 2
|
||||
|
||||
|
@ -651,69 +652,6 @@ handle_start_element (GMarkupParseContext *context,
|
|||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
derive_logical_monitor_layout (MetaLogicalMonitorConfig *logical_monitor_config,
|
||||
MetaLogicalMonitorLayoutMode layout_mode,
|
||||
GError **error)
|
||||
{
|
||||
MetaMonitorConfig *monitor_config;
|
||||
int mode_width, mode_height;
|
||||
int width = 0, height = 0;
|
||||
float scale;
|
||||
GList *l;
|
||||
|
||||
monitor_config = logical_monitor_config->monitor_configs->data;
|
||||
mode_width = monitor_config->mode_spec->width;
|
||||
mode_height = monitor_config->mode_spec->height;
|
||||
|
||||
for (l = logical_monitor_config->monitor_configs->next; l; l = l->next)
|
||||
{
|
||||
monitor_config = l->data;
|
||||
|
||||
if (monitor_config->mode_spec->width != mode_width ||
|
||||
monitor_config->mode_spec->height != mode_height)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Monitors in logical monitor incompatible");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (mtk_monitor_transform_is_rotated (logical_monitor_config->transform))
|
||||
{
|
||||
width = mode_height;
|
||||
height = mode_width;
|
||||
}
|
||||
else
|
||||
{
|
||||
width = mode_width;
|
||||
height = mode_height;
|
||||
}
|
||||
|
||||
scale = logical_monitor_config->scale;
|
||||
|
||||
switch (layout_mode)
|
||||
{
|
||||
case META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL:
|
||||
width = (int) roundf (width / scale);
|
||||
height = (int) roundf (height / scale);
|
||||
break;
|
||||
case META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL:
|
||||
if (!G_APPROX_VALUE (scale, roundf (scale), FLT_EPSILON))
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"A fractional scale with physical layout mode not allowed");
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
logical_monitor_config->layout.width = width;
|
||||
logical_monitor_config->layout.height = height;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
finish_monitor_spec (ConfigParser *parser)
|
||||
{
|
||||
|
@ -742,6 +680,107 @@ finish_monitor_spec (ConfigParser *parser)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
get_monitor_size_with_rotation (MetaLogicalMonitorConfig *logical_monitor_config,
|
||||
unsigned int *width_out,
|
||||
unsigned int *height_out)
|
||||
{
|
||||
MetaMonitorConfig *monitor_config =
|
||||
logical_monitor_config->monitor_configs->data;
|
||||
|
||||
if (mtk_monitor_transform_is_rotated (logical_monitor_config->transform))
|
||||
{
|
||||
*width_out = monitor_config->mode_spec->height;
|
||||
*height_out = monitor_config->mode_spec->width;
|
||||
}
|
||||
else
|
||||
{
|
||||
*width_out = monitor_config->mode_spec->width;
|
||||
*height_out = monitor_config->mode_spec->height;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
derive_logical_monitor_layouts (GList *logical_monitor_configs,
|
||||
MetaLogicalMonitorLayoutMode layout_mode)
|
||||
{
|
||||
GList *l;
|
||||
|
||||
for (l = logical_monitor_configs; l; l = l->next)
|
||||
{
|
||||
MetaLogicalMonitorConfig *logical_monitor_config = l->data;
|
||||
unsigned int width, height;
|
||||
|
||||
get_monitor_size_with_rotation (logical_monitor_config, &width, &height);
|
||||
|
||||
if (layout_mode == META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL)
|
||||
{
|
||||
width = (int) roundf (width / logical_monitor_config->scale);
|
||||
height = (int) roundf (height / logical_monitor_config->scale);
|
||||
}
|
||||
|
||||
logical_monitor_config->layout.width = width;
|
||||
logical_monitor_config->layout.height = height;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
detect_layout_mode_configs (MetaMonitorManager *monitor_manager,
|
||||
GList *logical_monitor_configs,
|
||||
GList *disabled_monitor_specs,
|
||||
MetaMonitorsConfigFlag config_flags,
|
||||
MetaMonitorsConfig **physical_layout_mode_config,
|
||||
MetaMonitorsConfig **logical_layout_mode_config,
|
||||
GError **error)
|
||||
{
|
||||
GList *logical_monitor_configs_copy, *disabled_monitor_specs_copy;
|
||||
MetaMonitorsConfig *physical_config, *logical_config;
|
||||
g_autoptr (GError) local_error_physical = NULL;
|
||||
g_autoptr (GError) local_error_logical = NULL;
|
||||
|
||||
logical_monitor_configs_copy =
|
||||
meta_clone_logical_monitor_config_list (logical_monitor_configs);
|
||||
disabled_monitor_specs_copy =
|
||||
g_list_copy_deep (disabled_monitor_specs, (GCopyFunc) meta_monitor_spec_clone, NULL);
|
||||
|
||||
derive_logical_monitor_layouts (logical_monitor_configs,
|
||||
META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL);
|
||||
physical_config =
|
||||
meta_monitors_config_new_full (g_steal_pointer (&logical_monitor_configs),
|
||||
g_steal_pointer (&disabled_monitor_specs),
|
||||
META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL,
|
||||
config_flags);
|
||||
|
||||
if (!meta_verify_monitors_config (physical_config, monitor_manager,
|
||||
&local_error_physical))
|
||||
g_clear_object (&physical_config);
|
||||
|
||||
derive_logical_monitor_layouts (logical_monitor_configs_copy,
|
||||
META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL);
|
||||
logical_config =
|
||||
meta_monitors_config_new_full (g_steal_pointer (&logical_monitor_configs_copy),
|
||||
g_steal_pointer (&disabled_monitor_specs_copy),
|
||||
META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL,
|
||||
config_flags);
|
||||
|
||||
if (!meta_verify_monitors_config (logical_config, monitor_manager,
|
||||
&local_error_logical))
|
||||
g_clear_object (&logical_config);
|
||||
|
||||
if (!physical_config && !logical_config)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Detected neither physical (%s) nor logical (%s) layout mode",
|
||||
local_error_physical->message, local_error_logical->message);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*physical_layout_mode_config = physical_config;
|
||||
*logical_layout_mode_config = logical_config;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
handle_end_element (GMarkupParseContext *context,
|
||||
const char *element_name,
|
||||
|
@ -917,51 +956,72 @@ handle_end_element (GMarkupParseContext *context,
|
|||
{
|
||||
MetaMonitorConfigStore *store = parser->config_store;
|
||||
MetaMonitorsConfig *config;
|
||||
GList *l;
|
||||
MetaLogicalMonitorLayoutMode layout_mode = parser->current_layout_mode;
|
||||
MetaMonitorsConfigFlag config_flags = META_MONITORS_CONFIG_FLAG_NONE;
|
||||
|
||||
g_assert (g_str_equal (element_name, "configuration"));
|
||||
|
||||
if (!parser->is_current_layout_mode_valid)
|
||||
layout_mode = meta_monitor_manager_get_default_layout_mode (store->monitor_manager);
|
||||
|
||||
for (l = parser->current_logical_monitor_configs; l; l = l->next)
|
||||
{
|
||||
MetaLogicalMonitorConfig *logical_monitor_config = l->data;
|
||||
|
||||
if (!derive_logical_monitor_layout (logical_monitor_config,
|
||||
layout_mode,
|
||||
error))
|
||||
return;
|
||||
|
||||
if (!meta_verify_logical_monitor_config (logical_monitor_config,
|
||||
layout_mode,
|
||||
store->monitor_manager,
|
||||
error))
|
||||
return;
|
||||
}
|
||||
|
||||
config_flags |= parser->extra_config_flags;
|
||||
|
||||
config =
|
||||
meta_monitors_config_new_full (parser->current_logical_monitor_configs,
|
||||
parser->current_disabled_monitor_specs,
|
||||
layout_mode,
|
||||
config_flags);
|
||||
|
||||
parser->current_logical_monitor_configs = NULL;
|
||||
parser->current_disabled_monitor_specs = NULL;
|
||||
|
||||
if (!meta_verify_monitors_config (config, store->monitor_manager,
|
||||
error))
|
||||
if (!parser->is_current_layout_mode_valid)
|
||||
{
|
||||
g_object_unref (config);
|
||||
return;
|
||||
}
|
||||
MetaMonitorsConfig *physical_layout_mode_config;
|
||||
MetaMonitorsConfig *logical_layout_mode_config;
|
||||
|
||||
g_hash_table_replace (parser->pending_configs,
|
||||
config->key, config);
|
||||
if (!detect_layout_mode_configs (store->monitor_manager,
|
||||
parser->current_logical_monitor_configs,
|
||||
parser->current_disabled_monitor_specs,
|
||||
config_flags,
|
||||
&physical_layout_mode_config,
|
||||
&logical_layout_mode_config,
|
||||
error))
|
||||
{
|
||||
parser->current_logical_monitor_configs = NULL;
|
||||
parser->current_disabled_monitor_specs = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
parser->current_logical_monitor_configs = NULL;
|
||||
parser->current_disabled_monitor_specs = NULL;
|
||||
|
||||
if (physical_layout_mode_config)
|
||||
{
|
||||
g_hash_table_replace (parser->pending_configs,
|
||||
physical_layout_mode_config->key,
|
||||
physical_layout_mode_config);
|
||||
}
|
||||
|
||||
if (logical_layout_mode_config)
|
||||
{
|
||||
g_hash_table_replace (parser->pending_configs,
|
||||
logical_layout_mode_config->key,
|
||||
logical_layout_mode_config);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
derive_logical_monitor_layouts (parser->current_logical_monitor_configs,
|
||||
layout_mode);
|
||||
|
||||
config =
|
||||
meta_monitors_config_new_full (parser->current_logical_monitor_configs,
|
||||
parser->current_disabled_monitor_specs,
|
||||
layout_mode,
|
||||
config_flags);
|
||||
|
||||
parser->current_logical_monitor_configs = NULL;
|
||||
parser->current_disabled_monitor_specs = NULL;
|
||||
|
||||
if (!meta_verify_monitors_config (config, store->monitor_manager,
|
||||
error))
|
||||
{
|
||||
g_object_unref (config);
|
||||
return;
|
||||
}
|
||||
|
||||
g_hash_table_replace (parser->pending_configs,
|
||||
config->key, config);
|
||||
}
|
||||
|
||||
parser->state = STATE_MONITORS;
|
||||
return;
|
||||
|
|
Loading…
Reference in a new issue