mirror of
https://github.com/brl/mutter.git
synced 2024-11-28 02:50:41 -05:00
e8197e8e05
Set the underscanning state via the monitor config struct so that it can be configured. https://bugzilla.gnome.org/show_bug.cgi?id=777732
790 lines
20 KiB
C
790 lines
20 KiB
C
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
|
|
/*
|
|
* Copyright (C) 2016 Red Hat
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License as
|
|
* published by the Free Software Foundation; either version 2 of the
|
|
* License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
* 02111-1307, USA.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include "backends/meta-monitor.h"
|
|
|
|
#include "backends/meta-backend-private.h"
|
|
#include "backends/meta-monitor-manager-private.h"
|
|
|
|
typedef struct _MetaMonitorMode
|
|
{
|
|
MetaMonitorModeSpec spec;
|
|
MetaMonitorCrtcMode *crtc_modes;
|
|
} MetaMonitorMode;
|
|
|
|
typedef struct _MetaMonitorPrivate
|
|
{
|
|
GList *outputs;
|
|
GList *modes;
|
|
|
|
MetaMonitorMode *preferred_mode;
|
|
MetaMonitorMode *current_mode;
|
|
|
|
MetaMonitorSpec *spec;
|
|
|
|
/*
|
|
* The primary or first output for this monitor, 0 if we can't figure out.
|
|
* It can be matched to a winsys_id of a MetaOutput.
|
|
*
|
|
* This is used as an opaque token on reconfiguration when switching from
|
|
* clone to extened, to decide on what output the windows should go next
|
|
* (it's an attempt to keep windows on the same monitor, and preferably on
|
|
* the primary one).
|
|
*/
|
|
long winsys_id;
|
|
} MetaMonitorPrivate;
|
|
|
|
G_DEFINE_TYPE_WITH_PRIVATE (MetaMonitor, meta_monitor, G_TYPE_OBJECT)
|
|
|
|
struct _MetaMonitorNormal
|
|
{
|
|
MetaMonitor parent;
|
|
};
|
|
|
|
G_DEFINE_TYPE (MetaMonitorNormal, meta_monitor_normal, META_TYPE_MONITOR)
|
|
|
|
struct _MetaMonitorTiled
|
|
{
|
|
MetaMonitor parent;
|
|
|
|
uint32_t tile_group_id;
|
|
|
|
MetaOutput *main_output;
|
|
};
|
|
|
|
G_DEFINE_TYPE (MetaMonitorTiled, meta_monitor_tiled, META_TYPE_MONITOR)
|
|
|
|
static void
|
|
meta_monitor_mode_free (MetaMonitorMode *mode);
|
|
|
|
MetaMonitorSpec *
|
|
meta_monitor_spec_clone (MetaMonitorSpec *monitor_spec)
|
|
{
|
|
MetaMonitorSpec *new_monitor_spec;
|
|
|
|
new_monitor_spec = g_new0 (MetaMonitorSpec, 1);
|
|
*new_monitor_spec = (MetaMonitorSpec) {
|
|
.connector = g_strdup (monitor_spec->connector),
|
|
.vendor = g_strdup (monitor_spec->vendor),
|
|
.product = g_strdup (monitor_spec->product),
|
|
.serial = g_strdup (monitor_spec->serial),
|
|
};
|
|
|
|
return new_monitor_spec;
|
|
}
|
|
|
|
gboolean
|
|
meta_monitor_spec_equals (MetaMonitorSpec *monitor_spec,
|
|
MetaMonitorSpec *other_monitor_spec)
|
|
{
|
|
return (g_str_equal (monitor_spec->connector, other_monitor_spec->connector) &&
|
|
g_str_equal (monitor_spec->vendor, other_monitor_spec->vendor) &&
|
|
g_str_equal (monitor_spec->product, other_monitor_spec->product) &&
|
|
g_str_equal (monitor_spec->serial, other_monitor_spec->serial));
|
|
}
|
|
|
|
int
|
|
meta_monitor_spec_compare (MetaMonitorSpec *monitor_spec_a,
|
|
MetaMonitorSpec *monitor_spec_b)
|
|
{
|
|
int ret;
|
|
|
|
ret = strcmp (monitor_spec_a->connector, monitor_spec_b->connector);
|
|
if (ret != 0)
|
|
return ret;
|
|
|
|
ret = strcmp (monitor_spec_a->vendor, monitor_spec_b->vendor);
|
|
if (ret != 0)
|
|
return ret;
|
|
|
|
ret = strcmp (monitor_spec_a->product, monitor_spec_b->product);
|
|
if (ret != 0)
|
|
return ret;
|
|
|
|
return strcmp (monitor_spec_a->serial, monitor_spec_b->serial);
|
|
}
|
|
|
|
void
|
|
meta_monitor_spec_free (MetaMonitorSpec *monitor_spec)
|
|
{
|
|
g_free (monitor_spec->connector);
|
|
g_free (monitor_spec->vendor);
|
|
g_free (monitor_spec->product);
|
|
g_free (monitor_spec->serial);
|
|
g_free (monitor_spec);
|
|
}
|
|
|
|
static void
|
|
meta_monitor_generate_id (MetaMonitor *monitor)
|
|
{
|
|
MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor);
|
|
MetaOutput *output = meta_monitor_get_main_output (monitor);
|
|
MetaMonitorSpec *monitor_spec;
|
|
|
|
monitor_spec = g_new0 (MetaMonitorSpec, 1);
|
|
*monitor_spec = (MetaMonitorSpec) {
|
|
.connector = g_strdup (output->name),
|
|
.vendor = g_strdup (output->vendor),
|
|
.product = g_strdup (output->product),
|
|
.serial = g_strdup (output->serial),
|
|
};
|
|
|
|
priv->spec = monitor_spec;
|
|
}
|
|
|
|
GList *
|
|
meta_monitor_get_outputs (MetaMonitor *monitor)
|
|
{
|
|
MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor);
|
|
|
|
return priv->outputs;
|
|
}
|
|
|
|
MetaOutput *
|
|
meta_monitor_get_main_output (MetaMonitor *monitor)
|
|
{
|
|
return META_MONITOR_GET_CLASS (monitor)->get_main_output (monitor);
|
|
}
|
|
|
|
gboolean
|
|
meta_monitor_is_active (MetaMonitor *monitor)
|
|
{
|
|
MetaOutput *output;
|
|
|
|
output = meta_monitor_get_main_output (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;
|
|
}
|
|
|
|
gboolean
|
|
meta_monitor_is_underscanning (MetaMonitor *monitor)
|
|
{
|
|
MetaOutput *output;
|
|
|
|
output = meta_monitor_get_main_output (monitor);
|
|
|
|
return output->is_underscanning;
|
|
}
|
|
|
|
gboolean
|
|
meta_monitor_is_laptop_panel (MetaMonitor *monitor)
|
|
{
|
|
MetaOutput *output;
|
|
|
|
output = meta_monitor_get_main_output (monitor);
|
|
|
|
switch (output->connector_type)
|
|
{
|
|
case META_CONNECTOR_TYPE_eDP:
|
|
case META_CONNECTOR_TYPE_LVDS:
|
|
case META_CONNECTOR_TYPE_DSI:
|
|
return TRUE;
|
|
default:
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
void
|
|
meta_monitor_get_dimensions (MetaMonitor *monitor,
|
|
int *width,
|
|
int *height)
|
|
{
|
|
META_MONITOR_GET_CLASS (monitor)->get_dimensions (monitor, width, height);
|
|
}
|
|
|
|
void
|
|
meta_monitor_get_physical_dimensions (MetaMonitor *monitor,
|
|
int *width_mm,
|
|
int *height_mm)
|
|
{
|
|
MetaOutput *output;
|
|
|
|
output = meta_monitor_get_main_output (monitor);
|
|
*width_mm = output->width_mm;
|
|
*height_mm = output->height_mm;
|
|
}
|
|
|
|
CoglSubpixelOrder
|
|
meta_monitor_get_subpixel_order (MetaMonitor *monitor)
|
|
{
|
|
MetaOutput *output;
|
|
|
|
output = meta_monitor_get_main_output (monitor);
|
|
return output->subpixel_order;
|
|
}
|
|
|
|
const char *
|
|
meta_monitor_get_vendor (MetaMonitor *monitor)
|
|
{
|
|
MetaOutput *output;
|
|
|
|
output = meta_monitor_get_main_output (monitor);
|
|
return output->vendor;
|
|
}
|
|
|
|
const char *
|
|
meta_monitor_get_product (MetaMonitor *monitor)
|
|
{
|
|
MetaOutput *output;
|
|
|
|
output = meta_monitor_get_main_output (monitor);
|
|
return output->product;
|
|
}
|
|
|
|
const char *
|
|
meta_monitor_get_serial (MetaMonitor *monitor)
|
|
{
|
|
MetaOutput *output;
|
|
|
|
output = meta_monitor_get_main_output (monitor);
|
|
return output->serial;
|
|
}
|
|
|
|
static void
|
|
meta_monitor_finalize (GObject *object)
|
|
{
|
|
MetaMonitor *monitor = META_MONITOR (object);
|
|
MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor);
|
|
|
|
g_list_free_full (priv->modes, (GDestroyNotify) meta_monitor_mode_free);
|
|
g_clear_pointer (&priv->outputs, g_list_free);
|
|
meta_monitor_spec_free (priv->spec);
|
|
}
|
|
|
|
static void
|
|
meta_monitor_init (MetaMonitor *monitor)
|
|
{
|
|
}
|
|
|
|
static void
|
|
meta_monitor_class_init (MetaMonitorClass *klass)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
object_class->finalize = meta_monitor_finalize;
|
|
}
|
|
|
|
static void
|
|
meta_monitor_normal_generate_modes (MetaMonitorNormal *monitor_normal)
|
|
{
|
|
MetaMonitor *monitor = META_MONITOR (monitor_normal);
|
|
MetaMonitorPrivate *monitor_priv =
|
|
meta_monitor_get_instance_private (monitor);
|
|
MetaOutput *output;
|
|
unsigned int i;
|
|
|
|
output = meta_monitor_get_main_output (monitor);
|
|
for (i = 0; i < output->n_modes; i++)
|
|
{
|
|
MetaCrtcMode *crtc_mode = output->modes[i];
|
|
MetaMonitorMode *mode;
|
|
|
|
mode = g_new0 (MetaMonitorMode, 1);
|
|
mode->spec = (MetaMonitorModeSpec) {
|
|
.width = crtc_mode->width,
|
|
.height = crtc_mode->height,
|
|
.refresh_rate = crtc_mode->refresh_rate
|
|
},
|
|
mode->crtc_modes = g_new (MetaMonitorCrtcMode, 1);
|
|
mode->crtc_modes[0] = (MetaMonitorCrtcMode) {
|
|
.x = 0,
|
|
.y = 0,
|
|
.output = output,
|
|
.crtc_mode = crtc_mode
|
|
};
|
|
|
|
if (crtc_mode == output->preferred_mode)
|
|
monitor_priv->preferred_mode = mode;
|
|
if (output->crtc && crtc_mode == output->crtc->current_mode)
|
|
monitor_priv->current_mode = mode;
|
|
|
|
monitor_priv->modes = g_list_append (monitor_priv->modes, mode);
|
|
}
|
|
}
|
|
|
|
MetaMonitorNormal *
|
|
meta_monitor_normal_new (MetaOutput *output)
|
|
{
|
|
MetaMonitorNormal *monitor_normal;
|
|
MetaMonitor *monitor;
|
|
MetaMonitorPrivate *monitor_priv;
|
|
|
|
monitor_normal = g_object_new (META_TYPE_MONITOR_NORMAL, NULL);
|
|
monitor = META_MONITOR (monitor_normal);
|
|
monitor_priv = meta_monitor_get_instance_private (monitor);
|
|
|
|
monitor_priv->outputs = g_list_append (NULL, output);
|
|
monitor_priv->winsys_id = output->winsys_id;
|
|
|
|
meta_monitor_normal_generate_modes (monitor_normal);
|
|
meta_monitor_generate_id (monitor);
|
|
|
|
return monitor_normal;
|
|
}
|
|
|
|
static MetaOutput *
|
|
meta_monitor_normal_get_main_output (MetaMonitor *monitor)
|
|
{
|
|
MetaMonitorPrivate *monitor_priv =
|
|
meta_monitor_get_instance_private (monitor);
|
|
|
|
return monitor_priv->outputs->data;
|
|
}
|
|
|
|
static void
|
|
meta_monitor_normal_get_dimensions (MetaMonitor *monitor,
|
|
int *width,
|
|
int *height)
|
|
{
|
|
MetaOutput *output;
|
|
|
|
output = meta_monitor_get_main_output (monitor);
|
|
*width = output->crtc->rect.width;
|
|
*height = output->crtc->rect.height;
|
|
}
|
|
|
|
static void
|
|
meta_monitor_normal_init (MetaMonitorNormal *monitor)
|
|
{
|
|
}
|
|
|
|
static void
|
|
meta_monitor_normal_class_init (MetaMonitorNormalClass *klass)
|
|
{
|
|
MetaMonitorClass *monitor_class = META_MONITOR_CLASS (klass);
|
|
|
|
monitor_class->get_main_output = meta_monitor_normal_get_main_output;
|
|
monitor_class->get_dimensions = meta_monitor_normal_get_dimensions;
|
|
}
|
|
|
|
uint32_t
|
|
meta_monitor_tiled_get_tile_group_id (MetaMonitorTiled *monitor_tiled)
|
|
{
|
|
return monitor_tiled->tile_group_id;
|
|
}
|
|
|
|
gboolean
|
|
meta_monitor_get_suggested_position (MetaMonitor *monitor,
|
|
int *x,
|
|
int *y)
|
|
{
|
|
MetaOutput *main_output;
|
|
|
|
main_output = meta_monitor_get_main_output (monitor);
|
|
if (main_output->suggested_x < 0 && main_output->suggested_y < 0)
|
|
return FALSE;
|
|
|
|
*x = main_output->suggested_x;
|
|
*y = main_output->suggested_y;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
add_tiled_monitor_outputs (MetaMonitorManager *monitor_manager,
|
|
MetaMonitorTiled *monitor_tiled)
|
|
{
|
|
MetaMonitorPrivate *monitor_priv =
|
|
meta_monitor_get_instance_private (META_MONITOR (monitor_tiled));
|
|
unsigned int i;
|
|
|
|
for (i = 0; i < monitor_manager->n_outputs; i++)
|
|
{
|
|
MetaOutput *output = &monitor_manager->outputs[i];
|
|
|
|
if (output->tile_info.group_id != monitor_tiled->tile_group_id)
|
|
continue;
|
|
|
|
g_warn_if_fail (output->subpixel_order ==
|
|
monitor_tiled->main_output->subpixel_order);
|
|
|
|
monitor_priv->outputs = g_list_append (monitor_priv->outputs, output);
|
|
}
|
|
}
|
|
|
|
static void
|
|
calculate_tile_coordinate (MetaMonitor *monitor,
|
|
MetaOutput *output,
|
|
int *out_x,
|
|
int *out_y)
|
|
{
|
|
MetaMonitorPrivate *monitor_priv =
|
|
meta_monitor_get_instance_private (monitor);
|
|
GList *l;
|
|
int x = 0;
|
|
int y = 0;
|
|
|
|
for (l = monitor_priv->outputs; l; l = l->next)
|
|
{
|
|
MetaOutput *other_output = l->data;
|
|
|
|
if (other_output->tile_info.loc_v_tile == output->tile_info.loc_v_tile &&
|
|
other_output->tile_info.loc_h_tile < output->tile_info.loc_h_tile)
|
|
x += other_output->tile_info.tile_w;
|
|
if (other_output->tile_info.loc_h_tile == output->tile_info.loc_h_tile &&
|
|
other_output->tile_info.loc_v_tile < output->tile_info.loc_v_tile)
|
|
y += other_output->tile_info.tile_h;
|
|
}
|
|
|
|
*out_x = x;
|
|
*out_y = y;
|
|
}
|
|
|
|
static void
|
|
meta_monitor_tiled_calculate_tiled_size (MetaMonitor *monitor,
|
|
int *out_width,
|
|
int *out_height)
|
|
{
|
|
MetaMonitorPrivate *monitor_priv =
|
|
meta_monitor_get_instance_private (monitor);
|
|
GList *l;
|
|
int width;
|
|
int height;
|
|
|
|
width = 0;
|
|
height = 0;
|
|
for (l = monitor_priv->outputs; l; l = l->next)
|
|
{
|
|
MetaOutput *output = l->data;
|
|
|
|
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
|
|
meta_monitor_tiled_generate_modes (MetaMonitorTiled *monitor_tiled)
|
|
{
|
|
MetaMonitor *monitor = META_MONITOR (monitor_tiled);
|
|
MetaMonitorPrivate *monitor_priv =
|
|
meta_monitor_get_instance_private (monitor);
|
|
MetaMonitorMode *mode;
|
|
gboolean preferred_mode_is_current;
|
|
GList *l;
|
|
int i;
|
|
|
|
mode = g_new0 (MetaMonitorMode, 1);
|
|
meta_monitor_tiled_calculate_tiled_size (monitor,
|
|
&mode->spec.width,
|
|
&mode->spec.height);
|
|
mode->crtc_modes = g_new (MetaMonitorCrtcMode,
|
|
g_list_length (monitor_priv->outputs));
|
|
preferred_mode_is_current = TRUE;
|
|
for (l = monitor_priv->outputs, i = 0; l; l = l->next, i++)
|
|
{
|
|
MetaOutput *output = l->data;
|
|
MetaCrtcMode *preferred_crtc_mode = output->preferred_mode;
|
|
int x;
|
|
int y;
|
|
|
|
calculate_tile_coordinate (monitor, output, &x, &y);
|
|
|
|
mode->crtc_modes[i] = (MetaMonitorCrtcMode) {
|
|
.x = x,
|
|
.y = y,
|
|
.output = output,
|
|
.crtc_mode = preferred_crtc_mode
|
|
};
|
|
|
|
g_warn_if_fail (mode->spec.refresh_rate == 0.0f ||
|
|
(mode->spec.refresh_rate ==
|
|
preferred_crtc_mode->refresh_rate));
|
|
|
|
mode->spec.refresh_rate = preferred_crtc_mode->refresh_rate;
|
|
|
|
if (!output->crtc ||
|
|
mode->crtc_modes[i].crtc_mode != output->crtc->current_mode)
|
|
preferred_mode_is_current = FALSE;
|
|
}
|
|
|
|
monitor_priv->modes = g_list_append (monitor_priv->modes, mode);
|
|
monitor_priv->preferred_mode = mode;
|
|
|
|
if (preferred_mode_is_current)
|
|
monitor_priv->current_mode = mode;
|
|
|
|
/* TODO: Add single tile modes */
|
|
}
|
|
|
|
MetaMonitorTiled *
|
|
meta_monitor_tiled_new (MetaMonitorManager *monitor_manager,
|
|
MetaOutput *output)
|
|
{
|
|
MetaMonitorTiled *monitor_tiled;
|
|
MetaMonitor *monitor;
|
|
MetaMonitorPrivate *monitor_priv;
|
|
|
|
monitor_tiled = g_object_new (META_TYPE_MONITOR_TILED, NULL);
|
|
monitor = META_MONITOR (monitor_tiled);
|
|
monitor_priv = meta_monitor_get_instance_private (monitor);
|
|
|
|
monitor_tiled->tile_group_id = output->tile_info.group_id;
|
|
monitor_priv->winsys_id = output->winsys_id;
|
|
|
|
monitor_tiled->main_output = output;
|
|
add_tiled_monitor_outputs (monitor_manager, monitor_tiled);
|
|
|
|
meta_monitor_manager_tiled_monitor_added (monitor_manager,
|
|
META_MONITOR (monitor_tiled));
|
|
|
|
meta_monitor_tiled_generate_modes (monitor_tiled);
|
|
meta_monitor_generate_id (monitor);
|
|
|
|
return monitor_tiled;
|
|
}
|
|
|
|
static MetaOutput *
|
|
meta_monitor_tiled_get_main_output (MetaMonitor *monitor)
|
|
{
|
|
MetaMonitorTiled *monitor_tiled = META_MONITOR_TILED (monitor);
|
|
|
|
return monitor_tiled->main_output;
|
|
}
|
|
|
|
static void
|
|
meta_monitor_tiled_get_dimensions (MetaMonitor *monitor,
|
|
int *width,
|
|
int *height)
|
|
{
|
|
meta_monitor_tiled_calculate_tiled_size (monitor, width, height);
|
|
}
|
|
|
|
static void
|
|
meta_monitor_tiled_finalize (GObject *object)
|
|
{
|
|
MetaMonitorTiled *monitor_tiled = META_MONITOR_TILED (object);
|
|
MetaBackend *backend = meta_get_backend ();
|
|
MetaMonitorManager *monitor_manager =
|
|
meta_backend_get_monitor_manager (backend);
|
|
|
|
meta_monitor_manager_tiled_monitor_removed (monitor_manager,
|
|
META_MONITOR (monitor_tiled));
|
|
}
|
|
|
|
static void
|
|
meta_monitor_tiled_init (MetaMonitorTiled *monitor)
|
|
{
|
|
}
|
|
|
|
static void
|
|
meta_monitor_tiled_class_init (MetaMonitorTiledClass *klass)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
MetaMonitorClass *monitor_class = META_MONITOR_CLASS (klass);
|
|
|
|
object_class->finalize = meta_monitor_tiled_finalize;
|
|
|
|
monitor_class->get_main_output = meta_monitor_tiled_get_main_output;
|
|
monitor_class->get_dimensions = meta_monitor_tiled_get_dimensions;
|
|
}
|
|
|
|
static void
|
|
meta_monitor_mode_free (MetaMonitorMode *monitor_mode)
|
|
{
|
|
g_free (monitor_mode->crtc_modes);
|
|
g_free (monitor_mode);
|
|
}
|
|
|
|
MetaMonitorSpec *
|
|
meta_monitor_get_spec (MetaMonitor *monitor)
|
|
{
|
|
MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor);
|
|
|
|
return priv->spec;
|
|
}
|
|
|
|
MetaLogicalMonitor *
|
|
meta_monitor_get_logical_monitor (MetaMonitor *monitor)
|
|
{
|
|
MetaOutput *output = meta_monitor_get_main_output (monitor);
|
|
|
|
if (output->crtc)
|
|
return output->crtc->logical_monitor;
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
static gboolean
|
|
meta_monitor_mode_spec_equals (MetaMonitorModeSpec *monitor_mode_spec,
|
|
MetaMonitorModeSpec *other_monitor_mode_spec)
|
|
{
|
|
return (monitor_mode_spec->width == other_monitor_mode_spec->width &&
|
|
monitor_mode_spec->height == other_monitor_mode_spec->height &&
|
|
(monitor_mode_spec->refresh_rate ==
|
|
other_monitor_mode_spec->refresh_rate));
|
|
}
|
|
|
|
MetaMonitorMode *
|
|
meta_monitor_get_mode_from_spec (MetaMonitor *monitor,
|
|
MetaMonitorModeSpec *monitor_mode_spec)
|
|
{
|
|
MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor);
|
|
GList *l;
|
|
|
|
for (l = priv->modes; l; l = l->next)
|
|
{
|
|
MetaMonitorMode *monitor_mode = l->data;
|
|
|
|
if (meta_monitor_mode_spec_equals (monitor_mode_spec,
|
|
&monitor_mode->spec))
|
|
return monitor_mode;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
MetaMonitorMode *
|
|
meta_monitor_get_preferred_mode (MetaMonitor *monitor)
|
|
{
|
|
MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor);
|
|
|
|
return priv->preferred_mode;
|
|
}
|
|
|
|
MetaMonitorMode *
|
|
meta_monitor_get_current_mode (MetaMonitor *monitor)
|
|
{
|
|
MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor);
|
|
|
|
return priv->current_mode;
|
|
}
|
|
|
|
static gboolean
|
|
is_monitor_mode_assigned (MetaMonitor *monitor,
|
|
MetaMonitorMode *mode)
|
|
{
|
|
MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor);
|
|
GList *l;
|
|
int i;
|
|
|
|
for (l = priv->outputs, i = 0; l; l = l->next, i++)
|
|
{
|
|
MetaOutput *output = l->data;
|
|
MetaMonitorCrtcMode *monitor_crtc_mode = &mode->crtc_modes[i];
|
|
|
|
if (!output->crtc ||
|
|
output->crtc->current_mode != monitor_crtc_mode->crtc_mode)
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
meta_monitor_derive_current_mode (MetaMonitor *monitor)
|
|
{
|
|
MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor);
|
|
MetaMonitorMode *current_mode = NULL;
|
|
GList *l;
|
|
|
|
for (l = priv->modes; l; l = l->next)
|
|
{
|
|
MetaMonitorMode *mode = l->data;
|
|
|
|
if (is_monitor_mode_assigned (monitor, mode))
|
|
{
|
|
current_mode = mode;
|
|
break;
|
|
}
|
|
}
|
|
|
|
priv->current_mode = current_mode;
|
|
}
|
|
|
|
void
|
|
meta_monitor_set_current_mode (MetaMonitor *monitor,
|
|
MetaMonitorMode *mode)
|
|
{
|
|
MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor);
|
|
|
|
priv->current_mode = mode;
|
|
}
|
|
|
|
GList *
|
|
meta_monitor_get_modes (MetaMonitor *monitor)
|
|
{
|
|
MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor);
|
|
|
|
return priv->modes;
|
|
}
|
|
|
|
MetaMonitorModeSpec *
|
|
meta_monitor_mode_get_spec (MetaMonitorMode *monitor_mode)
|
|
{
|
|
return &monitor_mode->spec;
|
|
}
|
|
|
|
void
|
|
meta_monitor_mode_get_resolution (MetaMonitorMode *monitor_mode,
|
|
int *width,
|
|
int *height)
|
|
{
|
|
*width = monitor_mode->spec.width;
|
|
*height = monitor_mode->spec.height;
|
|
}
|
|
|
|
float
|
|
meta_monitor_mode_get_refresh_rate (MetaMonitorMode *monitor_mode)
|
|
{
|
|
return monitor_mode->spec.refresh_rate;
|
|
}
|
|
|
|
gboolean
|
|
meta_monitor_mode_foreach_crtc (MetaMonitor *monitor,
|
|
MetaMonitorMode *mode,
|
|
MetaMonitorModeFunc func,
|
|
gpointer user_data,
|
|
GError **error)
|
|
{
|
|
MetaMonitorPrivate *monitor_priv =
|
|
meta_monitor_get_instance_private (monitor);
|
|
GList *l;
|
|
int i;
|
|
|
|
for (l = monitor_priv->outputs, i = 0; l; l = l->next, i++)
|
|
{
|
|
MetaMonitorCrtcMode *monitor_crtc_mode = &mode->crtc_modes[i];
|
|
|
|
if (!func (monitor, mode, monitor_crtc_mode, user_data, error))
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|