2016-12-12 21:53:38 -05:00
|
|
|
/* -*- 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"
|
|
|
|
|
2016-12-13 05:58:22 -05:00
|
|
|
#include "backends/meta-backend-private.h"
|
2016-12-12 21:53:38 -05:00
|
|
|
#include "backends/meta-monitor-manager-private.h"
|
2017-04-21 05:28:22 -04:00
|
|
|
#include "backends/meta-settings-private.h"
|
2016-12-12 21:53:38 -05:00
|
|
|
|
2016-12-14 04:22:07 -05:00
|
|
|
typedef struct _MetaMonitorMode
|
|
|
|
{
|
2016-12-17 09:29:33 -05:00
|
|
|
MetaMonitorModeSpec spec;
|
2016-12-14 04:22:07 -05:00
|
|
|
MetaMonitorCrtcMode *crtc_modes;
|
|
|
|
} MetaMonitorMode;
|
|
|
|
|
2017-03-17 05:21:10 -04:00
|
|
|
typedef struct _MetaMonitorModeTiled
|
|
|
|
{
|
|
|
|
MetaMonitorMode parent;
|
|
|
|
|
|
|
|
gboolean is_tiled;
|
|
|
|
} MetaMonitorModeTiled;
|
|
|
|
|
2016-12-12 21:53:38 -05:00
|
|
|
typedef struct _MetaMonitorPrivate
|
|
|
|
{
|
|
|
|
GList *outputs;
|
2016-12-14 04:22:07 -05:00
|
|
|
GList *modes;
|
2016-12-12 21:53:38 -05:00
|
|
|
|
2016-12-17 09:32:05 -05:00
|
|
|
MetaMonitorMode *preferred_mode;
|
2016-12-22 02:22:13 -05:00
|
|
|
MetaMonitorMode *current_mode;
|
2016-12-17 09:32:05 -05:00
|
|
|
|
2016-12-17 09:34:26 -05:00
|
|
|
MetaMonitorSpec *spec;
|
|
|
|
|
2016-12-12 21:53:38 -05:00
|
|
|
/*
|
|
|
|
* 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)
|
|
|
|
|
2016-12-14 04:22:07 -05:00
|
|
|
static void
|
|
|
|
meta_monitor_mode_free (MetaMonitorMode *mode);
|
|
|
|
|
2016-12-17 09:34:26 -05:00
|
|
|
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));
|
|
|
|
}
|
|
|
|
|
2017-01-12 03:13:48 -05:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2016-12-17 09:34:26 -05:00
|
|
|
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
|
2017-04-28 03:31:03 -04:00
|
|
|
meta_monitor_generate_spec (MetaMonitor *monitor)
|
2016-12-17 09:34:26 -05:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2016-12-12 21:53:38 -05:00
|
|
|
GList *
|
|
|
|
meta_monitor_get_outputs (MetaMonitor *monitor)
|
|
|
|
{
|
|
|
|
MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor);
|
|
|
|
|
|
|
|
return priv->outputs;
|
|
|
|
}
|
|
|
|
|
2016-12-12 22:03:22 -05:00
|
|
|
MetaOutput *
|
2016-12-12 21:53:38 -05:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2016-12-12 22:03:22 -05:00
|
|
|
gboolean
|
|
|
|
meta_monitor_is_primary (MetaMonitor *monitor)
|
|
|
|
{
|
|
|
|
MetaOutput *output;
|
|
|
|
|
|
|
|
output = meta_monitor_get_main_output (monitor);
|
|
|
|
|
|
|
|
return output->is_primary;
|
|
|
|
}
|
|
|
|
|
2017-01-23 04:59:43 -05:00
|
|
|
gboolean
|
|
|
|
meta_monitor_supports_underscanning (MetaMonitor *monitor)
|
|
|
|
{
|
|
|
|
MetaOutput *output;
|
|
|
|
|
|
|
|
output = meta_monitor_get_main_output (monitor);
|
|
|
|
|
|
|
|
return output->supports_underscanning;
|
|
|
|
}
|
|
|
|
|
2017-01-16 21:59:24 -05:00
|
|
|
gboolean
|
|
|
|
meta_monitor_is_underscanning (MetaMonitor *monitor)
|
|
|
|
{
|
|
|
|
MetaOutput *output;
|
|
|
|
|
|
|
|
output = meta_monitor_get_main_output (monitor);
|
|
|
|
|
|
|
|
return output->is_underscanning;
|
|
|
|
}
|
|
|
|
|
2016-12-17 09:37:57 -05:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-12 21:53:38 -05:00
|
|
|
void
|
2017-03-06 23:34:38 -05:00
|
|
|
meta_monitor_get_current_resolution (MetaMonitor *monitor,
|
|
|
|
int *width,
|
|
|
|
int *height)
|
2016-12-12 21:53:38 -05:00
|
|
|
{
|
2017-03-06 23:34:38 -05:00
|
|
|
MetaMonitorMode *mode = meta_monitor_get_current_mode (monitor);
|
|
|
|
|
|
|
|
*width = mode->spec.width;
|
|
|
|
*height = mode->spec.height;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_monitor_derive_dimensions (MetaMonitor *monitor,
|
|
|
|
int *width,
|
|
|
|
int *height)
|
|
|
|
{
|
|
|
|
META_MONITOR_GET_CLASS (monitor)->derive_dimensions (monitor, width, height);
|
2016-12-12 21:53:38 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2016-12-22 02:16:48 -05:00
|
|
|
CoglSubpixelOrder
|
|
|
|
meta_monitor_get_subpixel_order (MetaMonitor *monitor)
|
|
|
|
{
|
|
|
|
MetaOutput *output;
|
|
|
|
|
|
|
|
output = meta_monitor_get_main_output (monitor);
|
|
|
|
return output->subpixel_order;
|
|
|
|
}
|
|
|
|
|
2017-04-06 01:14:43 -04:00
|
|
|
const char *
|
|
|
|
meta_monitor_get_connector (MetaMonitor *monitor)
|
|
|
|
{
|
|
|
|
MetaOutput *output;
|
|
|
|
|
|
|
|
output = meta_monitor_get_main_output (monitor);
|
|
|
|
return output->name;
|
|
|
|
}
|
|
|
|
|
2016-12-22 02:20:57 -05:00
|
|
|
const char *
|
|
|
|
meta_monitor_get_vendor (MetaMonitor *monitor)
|
|
|
|
{
|
|
|
|
MetaOutput *output;
|
|
|
|
|
|
|
|
output = meta_monitor_get_main_output (monitor);
|
|
|
|
return output->vendor;
|
|
|
|
}
|
|
|
|
|
2016-12-13 05:58:22 -05:00
|
|
|
const char *
|
|
|
|
meta_monitor_get_product (MetaMonitor *monitor)
|
|
|
|
{
|
|
|
|
MetaOutput *output;
|
|
|
|
|
|
|
|
output = meta_monitor_get_main_output (monitor);
|
|
|
|
return output->product;
|
|
|
|
}
|
|
|
|
|
2016-12-22 02:20:57 -05:00
|
|
|
const char *
|
|
|
|
meta_monitor_get_serial (MetaMonitor *monitor)
|
|
|
|
{
|
|
|
|
MetaOutput *output;
|
|
|
|
|
|
|
|
output = meta_monitor_get_main_output (monitor);
|
|
|
|
return output->serial;
|
|
|
|
}
|
|
|
|
|
2017-01-20 02:07:12 -05:00
|
|
|
MetaConnectorType
|
|
|
|
meta_monitor_get_connector_type (MetaMonitor *monitor)
|
|
|
|
{
|
|
|
|
MetaOutput *output;
|
|
|
|
|
|
|
|
output = meta_monitor_get_main_output (monitor);
|
|
|
|
return output->connector_type;
|
|
|
|
}
|
|
|
|
|
2016-12-12 21:53:38 -05:00
|
|
|
static void
|
|
|
|
meta_monitor_finalize (GObject *object)
|
|
|
|
{
|
|
|
|
MetaMonitor *monitor = META_MONITOR (object);
|
|
|
|
MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor);
|
|
|
|
|
2016-12-14 04:22:07 -05:00
|
|
|
g_list_free_full (priv->modes, (GDestroyNotify) meta_monitor_mode_free);
|
2016-12-12 21:53:38 -05:00
|
|
|
g_clear_pointer (&priv->outputs, g_list_free);
|
2016-12-17 09:34:26 -05:00
|
|
|
meta_monitor_spec_free (priv->spec);
|
2016-12-12 21:53:38 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2016-12-14 04:22:07 -05:00
|
|
|
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);
|
2016-12-17 09:29:33 -05:00
|
|
|
mode->spec = (MetaMonitorModeSpec) {
|
|
|
|
.width = crtc_mode->width,
|
|
|
|
.height = crtc_mode->height,
|
|
|
|
.refresh_rate = crtc_mode->refresh_rate
|
|
|
|
},
|
2016-12-14 04:22:07 -05:00
|
|
|
mode->crtc_modes = g_new (MetaMonitorCrtcMode, 1);
|
|
|
|
mode->crtc_modes[0] = (MetaMonitorCrtcMode) {
|
|
|
|
.output = output,
|
|
|
|
.crtc_mode = crtc_mode
|
|
|
|
};
|
|
|
|
|
2016-12-17 09:32:05 -05:00
|
|
|
if (crtc_mode == output->preferred_mode)
|
|
|
|
monitor_priv->preferred_mode = mode;
|
2016-12-22 02:22:13 -05:00
|
|
|
if (output->crtc && crtc_mode == output->crtc->current_mode)
|
|
|
|
monitor_priv->current_mode = mode;
|
2016-12-17 09:32:05 -05:00
|
|
|
|
2016-12-14 04:22:07 -05:00
|
|
|
monitor_priv->modes = g_list_append (monitor_priv->modes, mode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-12 21:53:38 -05:00
|
|
|
MetaMonitorNormal *
|
|
|
|
meta_monitor_normal_new (MetaOutput *output)
|
|
|
|
{
|
|
|
|
MetaMonitorNormal *monitor_normal;
|
2016-12-17 09:34:26 -05:00
|
|
|
MetaMonitor *monitor;
|
2016-12-12 21:53:38 -05:00
|
|
|
MetaMonitorPrivate *monitor_priv;
|
|
|
|
|
|
|
|
monitor_normal = g_object_new (META_TYPE_MONITOR_NORMAL, NULL);
|
2016-12-17 09:34:26 -05:00
|
|
|
monitor = META_MONITOR (monitor_normal);
|
|
|
|
monitor_priv = meta_monitor_get_instance_private (monitor);
|
2016-12-12 21:53:38 -05:00
|
|
|
|
|
|
|
monitor_priv->outputs = g_list_append (NULL, output);
|
|
|
|
monitor_priv->winsys_id = output->winsys_id;
|
2017-04-28 03:34:27 -04:00
|
|
|
meta_monitor_generate_spec (monitor);
|
2016-12-12 21:53:38 -05:00
|
|
|
|
2016-12-14 04:22:07 -05:00
|
|
|
meta_monitor_normal_generate_modes (monitor_normal);
|
|
|
|
|
2016-12-12 21:53:38 -05:00
|
|
|
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
|
2017-03-06 23:34:38 -05:00
|
|
|
meta_monitor_normal_derive_dimensions (MetaMonitor *monitor,
|
|
|
|
int *width,
|
|
|
|
int *height)
|
2016-12-12 21:53:38 -05:00
|
|
|
{
|
|
|
|
MetaOutput *output;
|
|
|
|
|
|
|
|
output = meta_monitor_get_main_output (monitor);
|
|
|
|
*width = output->crtc->rect.width;
|
|
|
|
*height = output->crtc->rect.height;
|
|
|
|
}
|
|
|
|
|
2017-03-17 05:21:10 -04:00
|
|
|
static void
|
|
|
|
meta_monitor_normal_calculate_crtc_pos (MetaMonitor *monitor,
|
|
|
|
MetaMonitorMode *monitor_mode,
|
|
|
|
MetaOutput *output,
|
2017-03-21 02:17:18 -04:00
|
|
|
MetaMonitorTransform crtc_transform,
|
2017-03-17 05:21:10 -04:00
|
|
|
int *out_x,
|
|
|
|
int *out_y)
|
|
|
|
{
|
|
|
|
*out_x = 0;
|
|
|
|
*out_y = 0;
|
|
|
|
}
|
|
|
|
|
2016-12-12 21:53:38 -05:00
|
|
|
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;
|
2017-03-06 23:34:38 -05:00
|
|
|
monitor_class->derive_dimensions = meta_monitor_normal_derive_dimensions;
|
2017-03-17 05:21:10 -04:00
|
|
|
monitor_class->calculate_crtc_pos = meta_monitor_normal_calculate_crtc_pos;
|
2016-12-12 21:53:38 -05:00
|
|
|
}
|
|
|
|
|
2016-12-13 05:58:22 -05:00
|
|
|
uint32_t
|
|
|
|
meta_monitor_tiled_get_tile_group_id (MetaMonitorTiled *monitor_tiled)
|
|
|
|
{
|
|
|
|
return monitor_tiled->tile_group_id;
|
|
|
|
}
|
|
|
|
|
2017-01-09 02:35:03 -05:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2016-12-12 21:53:38 -05:00
|
|
|
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;
|
|
|
|
|
2016-12-22 02:16:48 -05:00
|
|
|
g_warn_if_fail (output->subpixel_order ==
|
|
|
|
monitor_tiled->main_output->subpixel_order);
|
|
|
|
|
2016-12-12 21:53:38 -05:00
|
|
|
monitor_priv->outputs = g_list_append (monitor_priv->outputs, output);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-14 04:22:07 -05:00
|
|
|
static void
|
2017-03-17 05:21:10 -04:00
|
|
|
calculate_tile_coordinate (MetaMonitor *monitor,
|
|
|
|
MetaOutput *output,
|
2017-03-21 02:17:18 -04:00
|
|
|
MetaMonitorTransform crtc_transform,
|
2017-03-17 05:21:10 -04:00
|
|
|
int *out_x,
|
|
|
|
int *out_y)
|
2016-12-14 04:22:07 -05:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
|
2017-03-21 02:17:18 -04:00
|
|
|
switch (crtc_transform)
|
|
|
|
{
|
|
|
|
case META_MONITOR_TRANSFORM_NORMAL:
|
|
|
|
case META_MONITOR_TRANSFORM_FLIPPED:
|
|
|
|
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;
|
|
|
|
break;
|
|
|
|
case META_MONITOR_TRANSFORM_180:
|
|
|
|
case META_MONITOR_TRANSFORM_FLIPPED_180:
|
|
|
|
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;
|
|
|
|
break;
|
|
|
|
case META_MONITOR_TRANSFORM_270:
|
|
|
|
case META_MONITOR_TRANSFORM_FLIPPED_270:
|
|
|
|
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)
|
|
|
|
y += 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)
|
|
|
|
x += other_output->tile_info.tile_h;
|
|
|
|
break;
|
|
|
|
case META_MONITOR_TRANSFORM_90:
|
|
|
|
case META_MONITOR_TRANSFORM_FLIPPED_90:
|
|
|
|
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)
|
|
|
|
y += 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)
|
|
|
|
x += other_output->tile_info.tile_h;
|
|
|
|
break;
|
|
|
|
}
|
2016-12-14 04:22:07 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
*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;
|
|
|
|
}
|
|
|
|
|
2017-03-06 00:09:56 -05:00
|
|
|
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 (monitor_crtc_mode->crtc_mode &&
|
|
|
|
(!output->crtc ||
|
|
|
|
output->crtc->current_mode != monitor_crtc_mode->crtc_mode))
|
|
|
|
return FALSE;
|
|
|
|
else if (!monitor_crtc_mode->crtc_mode && output->crtc)
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static MetaMonitorMode *
|
|
|
|
create_tiled_monitor_mode (MetaMonitorTiled *monitor_tiled)
|
2016-12-14 04:22:07 -05:00
|
|
|
{
|
|
|
|
MetaMonitor *monitor = META_MONITOR (monitor_tiled);
|
|
|
|
MetaMonitorPrivate *monitor_priv =
|
|
|
|
meta_monitor_get_instance_private (monitor);
|
2017-03-17 05:21:10 -04:00
|
|
|
MetaMonitorModeTiled *mode;
|
2016-12-14 04:22:07 -05:00
|
|
|
GList *l;
|
|
|
|
int i;
|
|
|
|
|
2017-03-17 05:21:10 -04:00
|
|
|
mode = g_new0 (MetaMonitorModeTiled, 1);
|
|
|
|
mode->is_tiled = TRUE;
|
2016-12-14 04:22:07 -05:00
|
|
|
meta_monitor_tiled_calculate_tiled_size (monitor,
|
2017-03-17 05:21:10 -04:00
|
|
|
&mode->parent.spec.width,
|
|
|
|
&mode->parent.spec.height);
|
|
|
|
mode->parent.crtc_modes = g_new0 (MetaMonitorCrtcMode,
|
|
|
|
g_list_length (monitor_priv->outputs));
|
2016-12-14 04:22:07 -05:00
|
|
|
for (l = monitor_priv->outputs, i = 0; l; l = l->next, i++)
|
|
|
|
{
|
|
|
|
MetaOutput *output = l->data;
|
|
|
|
MetaCrtcMode *preferred_crtc_mode = output->preferred_mode;
|
|
|
|
|
2017-03-17 05:21:10 -04:00
|
|
|
mode->parent.crtc_modes[i] = (MetaMonitorCrtcMode) {
|
2016-12-14 04:22:07 -05:00
|
|
|
.output = output,
|
|
|
|
.crtc_mode = preferred_crtc_mode
|
|
|
|
};
|
|
|
|
|
2017-03-17 05:21:10 -04:00
|
|
|
g_warn_if_fail (mode->parent.spec.refresh_rate == 0.0f ||
|
|
|
|
(mode->parent.spec.refresh_rate ==
|
2016-12-17 09:29:33 -05:00
|
|
|
preferred_crtc_mode->refresh_rate));
|
2016-12-14 04:22:07 -05:00
|
|
|
|
2017-03-17 05:21:10 -04:00
|
|
|
mode->parent.spec.refresh_rate = preferred_crtc_mode->refresh_rate;
|
2017-03-06 00:09:56 -05:00
|
|
|
}
|
|
|
|
|
2017-03-17 05:21:10 -04:00
|
|
|
return &mode->parent;
|
2017-03-06 00:09:56 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static MetaMonitorMode *
|
|
|
|
create_untiled_monitor_mode (MetaMonitorTiled *monitor_tiled,
|
|
|
|
MetaOutput *main_output,
|
|
|
|
MetaCrtcMode *crtc_mode)
|
|
|
|
{
|
|
|
|
MetaMonitor *monitor = META_MONITOR (monitor_tiled);
|
|
|
|
MetaMonitorPrivate *monitor_priv =
|
|
|
|
meta_monitor_get_instance_private (monitor);
|
2017-03-17 05:21:10 -04:00
|
|
|
MetaMonitorModeTiled *mode;
|
2017-03-06 00:09:56 -05:00
|
|
|
GList *l;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Assume modes with a resolution identical to the tile sizes are tiled
|
|
|
|
* modes.
|
|
|
|
*/
|
|
|
|
if (crtc_mode->width == (int) main_output->tile_info.tile_w &&
|
|
|
|
crtc_mode->height == (int) main_output->tile_info.tile_h)
|
|
|
|
return NULL;
|
|
|
|
|
2017-03-17 05:21:10 -04:00
|
|
|
mode = g_new0 (MetaMonitorModeTiled, 1);
|
2017-03-06 00:09:56 -05:00
|
|
|
|
2017-03-17 05:21:10 -04:00
|
|
|
mode->is_tiled = FALSE;
|
|
|
|
mode->parent.spec = (MetaMonitorModeSpec) {
|
2017-03-06 00:09:56 -05:00
|
|
|
.width = crtc_mode->width,
|
|
|
|
.height = crtc_mode->height,
|
|
|
|
.refresh_rate = crtc_mode->refresh_rate
|
|
|
|
};
|
2017-03-17 05:21:10 -04:00
|
|
|
mode->parent.crtc_modes = g_new0 (MetaMonitorCrtcMode,
|
2017-03-06 00:09:56 -05:00
|
|
|
g_list_length (monitor_priv->outputs));
|
|
|
|
|
|
|
|
for (l = monitor_priv->outputs, i = 0; l; l = l->next, i++)
|
|
|
|
{
|
|
|
|
MetaOutput *output = l->data;
|
2016-12-22 02:22:13 -05:00
|
|
|
|
2017-03-06 00:09:56 -05:00
|
|
|
if (output == main_output)
|
|
|
|
{
|
2017-03-17 05:21:10 -04:00
|
|
|
mode->parent.crtc_modes[i] = (MetaMonitorCrtcMode) {
|
2017-03-06 00:09:56 -05:00
|
|
|
.output = output,
|
|
|
|
.crtc_mode = crtc_mode
|
|
|
|
};
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-03-17 05:21:10 -04:00
|
|
|
mode->parent.crtc_modes[i] = (MetaMonitorCrtcMode) {
|
2017-03-06 00:09:56 -05:00
|
|
|
.output = output,
|
|
|
|
.crtc_mode = NULL
|
|
|
|
};
|
|
|
|
}
|
2016-12-14 04:22:07 -05:00
|
|
|
}
|
|
|
|
|
2017-03-17 05:21:10 -04:00
|
|
|
return &mode->parent;
|
2017-03-06 00:09:56 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
MetaOutput *main_output;
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
mode = create_tiled_monitor_mode (monitor_tiled);
|
2016-12-14 04:22:07 -05:00
|
|
|
monitor_priv->modes = g_list_append (monitor_priv->modes, mode);
|
2017-03-06 00:09:56 -05:00
|
|
|
|
2016-12-17 09:32:05 -05:00
|
|
|
monitor_priv->preferred_mode = mode;
|
2016-12-14 04:22:07 -05:00
|
|
|
|
2017-03-06 00:09:56 -05:00
|
|
|
if (is_monitor_mode_assigned (monitor, mode))
|
2016-12-22 02:22:13 -05:00
|
|
|
monitor_priv->current_mode = mode;
|
|
|
|
|
2017-03-06 00:09:56 -05:00
|
|
|
main_output = meta_monitor_get_main_output (monitor);
|
|
|
|
for (i = 0; i < main_output->n_modes; i++)
|
|
|
|
{
|
|
|
|
MetaCrtcMode *crtc_mode = main_output->modes[i];
|
|
|
|
|
|
|
|
mode = create_untiled_monitor_mode (monitor_tiled,
|
|
|
|
main_output,
|
|
|
|
crtc_mode);
|
|
|
|
if (mode)
|
|
|
|
{
|
|
|
|
monitor_priv->modes = g_list_append (monitor_priv->modes, mode);
|
|
|
|
|
|
|
|
if (is_monitor_mode_assigned (monitor, mode))
|
|
|
|
{
|
|
|
|
g_assert (!monitor_priv->current_mode);
|
|
|
|
monitor_priv->current_mode = mode;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-12-14 04:22:07 -05:00
|
|
|
}
|
|
|
|
|
2016-12-12 21:53:38 -05:00
|
|
|
MetaMonitorTiled *
|
|
|
|
meta_monitor_tiled_new (MetaMonitorManager *monitor_manager,
|
|
|
|
MetaOutput *output)
|
|
|
|
{
|
|
|
|
MetaMonitorTiled *monitor_tiled;
|
2016-12-17 09:34:26 -05:00
|
|
|
MetaMonitor *monitor;
|
2016-12-12 21:53:38 -05:00
|
|
|
MetaMonitorPrivate *monitor_priv;
|
|
|
|
|
|
|
|
monitor_tiled = g_object_new (META_TYPE_MONITOR_TILED, NULL);
|
2016-12-17 09:34:26 -05:00
|
|
|
monitor = META_MONITOR (monitor_tiled);
|
|
|
|
monitor_priv = meta_monitor_get_instance_private (monitor);
|
2016-12-12 21:53:38 -05:00
|
|
|
|
|
|
|
monitor_tiled->tile_group_id = output->tile_info.group_id;
|
|
|
|
monitor_priv->winsys_id = output->winsys_id;
|
|
|
|
|
|
|
|
monitor_tiled->main_output = output;
|
2016-12-22 02:16:48 -05:00
|
|
|
add_tiled_monitor_outputs (monitor_manager, monitor_tiled);
|
2016-12-12 21:53:38 -05:00
|
|
|
|
2017-04-28 03:34:27 -04:00
|
|
|
meta_monitor_generate_spec (monitor);
|
|
|
|
|
2016-12-13 05:58:22 -05:00
|
|
|
meta_monitor_manager_tiled_monitor_added (monitor_manager,
|
|
|
|
META_MONITOR (monitor_tiled));
|
|
|
|
|
2016-12-14 04:22:07 -05:00
|
|
|
meta_monitor_tiled_generate_modes (monitor_tiled);
|
|
|
|
|
2016-12-12 21:53:38 -05:00
|
|
|
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
|
2017-03-06 23:34:38 -05:00
|
|
|
meta_monitor_tiled_derive_dimensions (MetaMonitor *monitor,
|
|
|
|
int *out_width,
|
|
|
|
int *out_height)
|
2016-12-12 21:53:38 -05:00
|
|
|
{
|
2017-03-06 23:34:38 -05:00
|
|
|
MetaMonitorPrivate *monitor_priv =
|
|
|
|
meta_monitor_get_instance_private (monitor);
|
|
|
|
GList *l;
|
2017-03-08 02:53:24 -05:00
|
|
|
int min_x, min_y, max_x, max_y;
|
2017-03-06 23:34:38 -05:00
|
|
|
|
2017-03-08 02:53:24 -05:00
|
|
|
min_x = INT_MAX;
|
|
|
|
min_y = INT_MAX;
|
|
|
|
max_x = 0;
|
|
|
|
max_y = 0;
|
2017-03-06 23:34:38 -05:00
|
|
|
for (l = monitor_priv->outputs; l; l = l->next)
|
|
|
|
{
|
|
|
|
MetaOutput *output = l->data;
|
|
|
|
|
|
|
|
if (!output->crtc)
|
|
|
|
continue;
|
|
|
|
|
2017-03-08 02:53:24 -05:00
|
|
|
min_x = MIN (output->crtc->rect.x, min_x);
|
|
|
|
min_y = MIN (output->crtc->rect.y, min_y);
|
|
|
|
max_x = MAX (output->crtc->rect.x + output->crtc->rect.width, max_x);
|
|
|
|
max_y = MAX (output->crtc->rect.y + output->crtc->rect.height, max_y);
|
2017-03-06 23:34:38 -05:00
|
|
|
}
|
|
|
|
|
2017-03-08 02:53:24 -05:00
|
|
|
*out_width = max_x - min_x;
|
|
|
|
*out_height = max_y - min_y;
|
2016-12-12 21:53:38 -05:00
|
|
|
}
|
|
|
|
|
2017-03-17 05:21:10 -04:00
|
|
|
static void
|
|
|
|
meta_monitor_tiled_calculate_crtc_pos (MetaMonitor *monitor,
|
|
|
|
MetaMonitorMode *monitor_mode,
|
|
|
|
MetaOutput *output,
|
2017-03-21 02:17:18 -04:00
|
|
|
MetaMonitorTransform crtc_transform,
|
2017-03-17 05:21:10 -04:00
|
|
|
int *out_x,
|
|
|
|
int *out_y)
|
|
|
|
{
|
|
|
|
MetaMonitorModeTiled *mode_tiled = (MetaMonitorModeTiled *) monitor_mode;
|
|
|
|
|
|
|
|
if (mode_tiled->is_tiled)
|
|
|
|
{
|
2017-03-21 02:17:18 -04:00
|
|
|
calculate_tile_coordinate (monitor, output, crtc_transform,
|
2017-03-17 05:21:10 -04:00
|
|
|
out_x, out_y);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*out_x = 0;
|
|
|
|
*out_y = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-13 05:58:22 -05:00
|
|
|
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));
|
|
|
|
}
|
|
|
|
|
2016-12-12 21:53:38 -05:00
|
|
|
static void
|
|
|
|
meta_monitor_tiled_init (MetaMonitorTiled *monitor)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_monitor_tiled_class_init (MetaMonitorTiledClass *klass)
|
|
|
|
{
|
2016-12-13 05:58:22 -05:00
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
2016-12-12 21:53:38 -05:00
|
|
|
MetaMonitorClass *monitor_class = META_MONITOR_CLASS (klass);
|
|
|
|
|
2016-12-13 05:58:22 -05:00
|
|
|
object_class->finalize = meta_monitor_tiled_finalize;
|
|
|
|
|
2016-12-12 21:53:38 -05:00
|
|
|
monitor_class->get_main_output = meta_monitor_tiled_get_main_output;
|
2017-03-06 23:34:38 -05:00
|
|
|
monitor_class->derive_dimensions = meta_monitor_tiled_derive_dimensions;
|
2017-03-17 05:21:10 -04:00
|
|
|
monitor_class->calculate_crtc_pos = meta_monitor_tiled_calculate_crtc_pos;
|
2016-12-12 21:53:38 -05:00
|
|
|
}
|
2016-12-14 04:22:07 -05:00
|
|
|
|
|
|
|
static void
|
|
|
|
meta_monitor_mode_free (MetaMonitorMode *monitor_mode)
|
|
|
|
{
|
|
|
|
g_free (monitor_mode->crtc_modes);
|
|
|
|
g_free (monitor_mode);
|
|
|
|
}
|
|
|
|
|
2016-12-17 09:34:26 -05:00
|
|
|
MetaMonitorSpec *
|
|
|
|
meta_monitor_get_spec (MetaMonitor *monitor)
|
|
|
|
{
|
|
|
|
MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor);
|
|
|
|
|
|
|
|
return priv->spec;
|
|
|
|
}
|
|
|
|
|
2017-01-09 01:31:18 -05:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2016-12-21 00:03:35 -05:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2016-12-17 09:32:05 -05:00
|
|
|
MetaMonitorMode *
|
|
|
|
meta_monitor_get_preferred_mode (MetaMonitor *monitor)
|
|
|
|
{
|
|
|
|
MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor);
|
|
|
|
|
|
|
|
return priv->preferred_mode;
|
|
|
|
}
|
|
|
|
|
2016-12-22 02:22:13 -05:00
|
|
|
MetaMonitorMode *
|
|
|
|
meta_monitor_get_current_mode (MetaMonitor *monitor)
|
|
|
|
{
|
|
|
|
MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor);
|
|
|
|
|
|
|
|
return priv->current_mode;
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2017-01-09 01:31:18 -05:00
|
|
|
void
|
|
|
|
meta_monitor_set_current_mode (MetaMonitor *monitor,
|
|
|
|
MetaMonitorMode *mode)
|
|
|
|
{
|
|
|
|
MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor);
|
|
|
|
|
|
|
|
priv->current_mode = mode;
|
|
|
|
}
|
|
|
|
|
2016-12-14 04:22:07 -05:00
|
|
|
GList *
|
|
|
|
meta_monitor_get_modes (MetaMonitor *monitor)
|
|
|
|
{
|
|
|
|
MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor);
|
|
|
|
|
|
|
|
return priv->modes;
|
|
|
|
}
|
|
|
|
|
2017-03-17 05:21:10 -04:00
|
|
|
void
|
|
|
|
meta_monitor_calculate_crtc_pos (MetaMonitor *monitor,
|
|
|
|
MetaMonitorMode *monitor_mode,
|
|
|
|
MetaOutput *output,
|
2017-03-21 02:17:18 -04:00
|
|
|
MetaMonitorTransform crtc_transform,
|
2017-03-17 05:21:10 -04:00
|
|
|
int *out_x,
|
|
|
|
int *out_y)
|
|
|
|
{
|
|
|
|
META_MONITOR_GET_CLASS (monitor)->calculate_crtc_pos (monitor,
|
|
|
|
monitor_mode,
|
|
|
|
output,
|
2017-03-21 02:17:18 -04:00
|
|
|
crtc_transform,
|
2017-03-17 05:21:10 -04:00
|
|
|
out_x,
|
|
|
|
out_y);
|
|
|
|
}
|
|
|
|
|
2017-04-21 05:28:22 -04:00
|
|
|
/* The minimum resolution at which we turn on a window-scale of 2 */
|
|
|
|
#define HIDPI_LIMIT 192
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The minimum screen height at which we turn on a window-scale of 2;
|
|
|
|
* below this there just isn't enough vertical real estate for GNOME
|
|
|
|
* apps to work, and it's better to just be tiny
|
|
|
|
*/
|
|
|
|
#define HIDPI_MIN_HEIGHT 1200
|
|
|
|
|
|
|
|
/* From http://en.wikipedia.org/wiki/4K_resolution#Resolutions_of_common_formats */
|
|
|
|
#define SMALLEST_4K_WIDTH 3656
|
|
|
|
|
|
|
|
static int
|
|
|
|
calculate_scale (MetaMonitor *monitor,
|
|
|
|
MetaMonitorMode *monitor_mode)
|
|
|
|
{
|
|
|
|
int resolution_width, resolution_height;
|
|
|
|
int width_mm, height_mm;
|
|
|
|
int scale;
|
|
|
|
|
|
|
|
scale = 1;
|
|
|
|
|
|
|
|
meta_monitor_mode_get_resolution (monitor_mode,
|
|
|
|
&resolution_width,
|
|
|
|
&resolution_height);
|
|
|
|
|
|
|
|
if (resolution_height < HIDPI_MIN_HEIGHT)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
/* 4K TV */
|
|
|
|
switch (meta_monitor_get_connector_type (monitor))
|
|
|
|
{
|
|
|
|
case META_CONNECTOR_TYPE_HDMIA:
|
|
|
|
case META_CONNECTOR_TYPE_HDMIB:
|
|
|
|
if (resolution_width >= SMALLEST_4K_WIDTH)
|
|
|
|
goto out;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
meta_monitor_get_physical_dimensions (monitor, &width_mm, &height_mm);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Somebody encoded the aspect ratio (16/9 or 16/10) instead of the physical
|
|
|
|
* size.
|
|
|
|
*/
|
|
|
|
if ((width_mm == 160 && height_mm == 90) ||
|
|
|
|
(width_mm == 160 && height_mm == 100) ||
|
|
|
|
(width_mm == 16 && height_mm == 9) ||
|
|
|
|
(width_mm == 16 && height_mm == 10))
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
if (width_mm > 0 && height_mm > 0)
|
|
|
|
{
|
|
|
|
double dpi_x, dpi_y;
|
|
|
|
|
|
|
|
dpi_x = (double) resolution_width / (width_mm / 25.4);
|
|
|
|
dpi_y = (double) resolution_height / (height_mm / 25.4);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We don't completely trust these values so both must be high, and never
|
|
|
|
* pick higher ratio than 2 automatically.
|
|
|
|
*/
|
|
|
|
if (dpi_x > HIDPI_LIMIT && dpi_y > HIDPI_LIMIT)
|
|
|
|
scale = 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
out:
|
|
|
|
return scale;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
meta_monitor_calculate_mode_scale (MetaMonitor *monitor,
|
|
|
|
MetaMonitorMode *monitor_mode)
|
|
|
|
{
|
|
|
|
MetaBackend *backend = meta_get_backend ();
|
|
|
|
MetaSettings *settings = meta_backend_get_settings (backend);
|
|
|
|
int global_scaling_factor;
|
|
|
|
|
|
|
|
if (meta_settings_get_global_scaling_factor (settings,
|
|
|
|
&global_scaling_factor))
|
|
|
|
return global_scaling_factor;
|
|
|
|
|
|
|
|
return calculate_scale (monitor, monitor_mode);
|
|
|
|
}
|
|
|
|
|
2016-12-17 09:29:33 -05:00
|
|
|
MetaMonitorModeSpec *
|
|
|
|
meta_monitor_mode_get_spec (MetaMonitorMode *monitor_mode)
|
|
|
|
{
|
|
|
|
return &monitor_mode->spec;
|
|
|
|
}
|
|
|
|
|
2016-12-14 04:22:07 -05:00
|
|
|
void
|
|
|
|
meta_monitor_mode_get_resolution (MetaMonitorMode *monitor_mode,
|
|
|
|
int *width,
|
|
|
|
int *height)
|
|
|
|
{
|
2016-12-17 09:29:33 -05:00
|
|
|
*width = monitor_mode->spec.width;
|
|
|
|
*height = monitor_mode->spec.height;
|
2016-12-14 04:22:07 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
float
|
|
|
|
meta_monitor_mode_get_refresh_rate (MetaMonitorMode *monitor_mode)
|
|
|
|
{
|
2016-12-17 09:29:33 -05:00
|
|
|
return monitor_mode->spec.refresh_rate;
|
2016-12-14 04:22:07 -05:00
|
|
|
}
|
|
|
|
|
2016-12-20 10:23:27 -05:00
|
|
|
gboolean
|
2016-12-14 04:22:07 -05:00
|
|
|
meta_monitor_mode_foreach_crtc (MetaMonitor *monitor,
|
|
|
|
MetaMonitorMode *mode,
|
|
|
|
MetaMonitorModeFunc func,
|
2016-12-20 10:23:27 -05:00
|
|
|
gpointer user_data,
|
|
|
|
GError **error)
|
2016-12-14 04:22:07 -05:00
|
|
|
{
|
|
|
|
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];
|
|
|
|
|
2016-12-20 10:23:27 -05:00
|
|
|
if (!func (monitor, mode, monitor_crtc_mode, user_data, error))
|
|
|
|
return FALSE;
|
2016-12-14 04:22:07 -05:00
|
|
|
}
|
2016-12-20 10:23:27 -05:00
|
|
|
|
|
|
|
return TRUE;
|
2016-12-14 04:22:07 -05:00
|
|
|
}
|