|
|
41c151 |
From 100795c2729305f919ff9611c877ea3e74d528b7 Mon Sep 17 00:00:00 2001
|
|
|
67f8b7 |
From: Rui Matos <tiagomatos@gmail.com>
|
|
|
41c151 |
Date: Mon, 4 Jun 2018 16:35:04 -0400
|
|
|
41c151 |
Subject: [PATCH] monitor-manager-xrandr: Force an update when resuming from
|
|
|
41c151 |
suspend
|
|
|
67f8b7 |
|
|
|
67f8b7 |
The stack below us isn't as reliable as we'd like and in some cases
|
|
|
67f8b7 |
doesn't generate RRScreenChangeNotify events when e.g. resuming a
|
|
|
67f8b7 |
laptop on a dock, meaning that we'd miss newly attached outputs.
|
|
|
67f8b7 |
---
|
|
|
41c151 |
src/backends/meta-gpu.c | 7 ++
|
|
|
41c151 |
src/backends/meta-gpu.h | 2 +
|
|
|
41c151 |
src/backends/x11/meta-gpu-xrandr.c | 26 ++++-
|
|
|
41c151 |
.../x11/meta-monitor-manager-xrandr.c | 96 +++++++++++++++++--
|
|
|
41c151 |
4 files changed, 121 insertions(+), 10 deletions(-)
|
|
|
67f8b7 |
|
|
|
41c151 |
diff --git a/src/backends/meta-gpu.c b/src/backends/meta-gpu.c
|
|
|
41c151 |
index 3577391e5..946f72387 100644
|
|
|
41c151 |
--- a/src/backends/meta-gpu.c
|
|
|
41c151 |
+++ b/src/backends/meta-gpu.c
|
|
|
41c151 |
@@ -37,60 +37,67 @@ enum
|
|
|
41c151 |
static GParamSpec *obj_props[PROP_LAST];
|
|
|
67f8b7 |
|
|
|
41c151 |
typedef struct _MetaGpuPrivate
|
|
|
41c151 |
{
|
|
|
41c151 |
MetaMonitorManager *monitor_manager;
|
|
|
67f8b7 |
|
|
|
41c151 |
GList *outputs;
|
|
|
41c151 |
GList *crtcs;
|
|
|
41c151 |
GList *modes;
|
|
|
41c151 |
} MetaGpuPrivate;
|
|
|
67f8b7 |
|
|
|
41c151 |
G_DEFINE_TYPE_WITH_PRIVATE (MetaGpu, meta_gpu, G_TYPE_OBJECT)
|
|
|
41c151 |
|
|
|
41c151 |
gboolean
|
|
|
41c151 |
meta_gpu_has_hotplug_mode_update (MetaGpu *gpu)
|
|
|
41c151 |
{
|
|
|
41c151 |
MetaGpuPrivate *priv = meta_gpu_get_instance_private (gpu);
|
|
|
41c151 |
GList *l;
|
|
|
41c151 |
|
|
|
41c151 |
for (l = priv->outputs; l; l = l->next)
|
|
|
41c151 |
{
|
|
|
41c151 |
MetaOutput *output = l->data;
|
|
|
41c151 |
|
|
|
41c151 |
if (output->hotplug_mode_update)
|
|
|
41c151 |
return TRUE;
|
|
|
41c151 |
}
|
|
|
41c151 |
|
|
|
41c151 |
return FALSE;
|
|
|
67f8b7 |
}
|
|
|
67f8b7 |
|
|
|
41c151 |
+void
|
|
|
41c151 |
+meta_gpu_poll_hardware (MetaGpu *gpu)
|
|
|
67f8b7 |
+{
|
|
|
41c151 |
+ if (META_GPU_GET_CLASS (gpu)->poll_hardware)
|
|
|
41c151 |
+ META_GPU_GET_CLASS (gpu)->poll_hardware (gpu);
|
|
|
67f8b7 |
+}
|
|
|
67f8b7 |
+
|
|
|
41c151 |
gboolean
|
|
|
41c151 |
meta_gpu_read_current (MetaGpu *gpu,
|
|
|
41c151 |
GError **error)
|
|
|
41c151 |
{
|
|
|
41c151 |
MetaGpuPrivate *priv = meta_gpu_get_instance_private (gpu);
|
|
|
41c151 |
gboolean ret;
|
|
|
41c151 |
GList *old_outputs;
|
|
|
41c151 |
GList *old_crtcs;
|
|
|
41c151 |
GList *old_modes;
|
|
|
41c151 |
|
|
|
41c151 |
/* TODO: Get rid of this when objects incref:s what they need instead */
|
|
|
41c151 |
old_outputs = priv->outputs;
|
|
|
41c151 |
old_crtcs = priv->crtcs;
|
|
|
41c151 |
old_modes = priv->modes;
|
|
|
41c151 |
|
|
|
41c151 |
ret = META_GPU_GET_CLASS (gpu)->read_current (gpu, error);
|
|
|
41c151 |
|
|
|
41c151 |
g_list_free_full (old_outputs, g_object_unref);
|
|
|
41c151 |
g_list_free_full (old_modes, g_object_unref);
|
|
|
41c151 |
g_list_free_full (old_crtcs, g_object_unref);
|
|
|
41c151 |
|
|
|
41c151 |
return ret;
|
|
|
41c151 |
}
|
|
|
41c151 |
|
|
|
41c151 |
MetaMonitorManager *
|
|
|
41c151 |
meta_gpu_get_monitor_manager (MetaGpu *gpu)
|
|
|
41c151 |
{
|
|
|
41c151 |
MetaGpuPrivate *priv = meta_gpu_get_instance_private (gpu);
|
|
|
41c151 |
|
|
|
41c151 |
return priv->monitor_manager;
|
|
|
41c151 |
diff --git a/src/backends/meta-gpu.h b/src/backends/meta-gpu.h
|
|
|
41c151 |
index 4badcbd26..3cec8e5b0 100644
|
|
|
41c151 |
--- a/src/backends/meta-gpu.h
|
|
|
41c151 |
+++ b/src/backends/meta-gpu.h
|
|
|
41c151 |
@@ -8,59 +8,61 @@
|
|
|
41c151 |
* published by the Free Software Foundation; either version 2 of the
|
|
|
41c151 |
* License, or (at your option) any later version.
|
|
|
41c151 |
*
|
|
|
41c151 |
* This program is distributed in the hope that it will be useful, but
|
|
|
41c151 |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
41c151 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
41c151 |
* General Public License for more details.
|
|
|
41c151 |
*
|
|
|
41c151 |
* You should have received a copy of the GNU General Public License
|
|
|
41c151 |
* along with this program; if not, write to the Free Software
|
|
|
41c151 |
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
|
41c151 |
* 02111-1307, USA.
|
|
|
41c151 |
*/
|
|
|
41c151 |
|
|
|
41c151 |
#ifndef META_GPU_H
|
|
|
41c151 |
#define META_GPU_H
|
|
|
41c151 |
|
|
|
41c151 |
#include <glib-object.h>
|
|
|
41c151 |
|
|
|
41c151 |
#include "backends/meta-monitor-manager-private.h"
|
|
|
41c151 |
|
|
|
41c151 |
#define META_TYPE_GPU (meta_gpu_get_type ())
|
|
|
41c151 |
G_DECLARE_DERIVABLE_TYPE (MetaGpu, meta_gpu, META, GPU, GObject)
|
|
|
41c151 |
|
|
|
41c151 |
struct _MetaGpuClass
|
|
|
41c151 |
{
|
|
|
41c151 |
GObjectClass parent_class;
|
|
|
41c151 |
|
|
|
41c151 |
gboolean (* read_current) (MetaGpu *gpu,
|
|
|
41c151 |
GError **error);
|
|
|
41c151 |
+ void (* poll_hardware) (MetaGpu *gpu);
|
|
|
41c151 |
};
|
|
|
41c151 |
|
|
|
41c151 |
int meta_gpu_get_kms_fd (MetaGpu *gpu);
|
|
|
41c151 |
|
|
|
41c151 |
const char * meta_gpu_get_kms_file_path (MetaGpu *gpu);
|
|
|
41c151 |
|
|
|
41c151 |
+void meta_gpu_poll_hardware (MetaGpu *gpu);
|
|
|
41c151 |
gboolean meta_gpu_read_current (MetaGpu *gpu,
|
|
|
41c151 |
GError **error);
|
|
|
41c151 |
|
|
|
41c151 |
gboolean meta_gpu_has_hotplug_mode_update (MetaGpu *gpu);
|
|
|
41c151 |
|
|
|
41c151 |
MetaMonitorManager * meta_gpu_get_monitor_manager (MetaGpu *gpu);
|
|
|
41c151 |
|
|
|
41c151 |
GList * meta_gpu_get_outputs (MetaGpu *gpu);
|
|
|
41c151 |
|
|
|
41c151 |
GList * meta_gpu_get_crtcs (MetaGpu *gpu);
|
|
|
41c151 |
|
|
|
41c151 |
GList * meta_gpu_get_modes (MetaGpu *gpu);
|
|
|
41c151 |
|
|
|
41c151 |
void meta_gpu_take_outputs (MetaGpu *gpu,
|
|
|
41c151 |
GList *outputs);
|
|
|
41c151 |
|
|
|
41c151 |
void meta_gpu_take_crtcs (MetaGpu *gpu,
|
|
|
41c151 |
GList *crtcs);
|
|
|
41c151 |
|
|
|
41c151 |
void meta_gpu_take_modes (MetaGpu *gpu,
|
|
|
41c151 |
GList *modes);
|
|
|
41c151 |
|
|
|
41c151 |
#endif /* META_GPU_H */
|
|
|
41c151 |
diff --git a/src/backends/x11/meta-gpu-xrandr.c b/src/backends/x11/meta-gpu-xrandr.c
|
|
|
41c151 |
index 14b46d530..add80c0d2 100644
|
|
|
41c151 |
--- a/src/backends/x11/meta-gpu-xrandr.c
|
|
|
41c151 |
+++ b/src/backends/x11/meta-gpu-xrandr.c
|
|
|
41c151 |
@@ -17,97 +17,107 @@
|
|
|
41c151 |
* This program is distributed in the hope that it will be useful, but
|
|
|
41c151 |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
41c151 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
41c151 |
* General Public License for more details.
|
|
|
41c151 |
*
|
|
|
41c151 |
* You should have received a copy of the GNU General Public License
|
|
|
41c151 |
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
|
41c151 |
*/
|
|
|
41c151 |
|
|
|
41c151 |
#include "config.h"
|
|
|
41c151 |
|
|
|
41c151 |
#include "backends/x11/meta-gpu-xrandr.h"
|
|
|
41c151 |
|
|
|
41c151 |
#include <string.h>
|
|
|
41c151 |
#include <X11/extensions/dpms.h>
|
|
|
41c151 |
#include <X11/Xlibint.h>
|
|
|
41c151 |
|
|
|
41c151 |
#include "backends/meta-output.h"
|
|
|
41c151 |
#include "backends/x11/meta-crtc-xrandr.h"
|
|
|
41c151 |
#include "backends/x11/meta-monitor-manager-xrandr.h"
|
|
|
41c151 |
#include "backends/x11/meta-output-xrandr.h"
|
|
|
41c151 |
|
|
|
41c151 |
struct _MetaGpuXrandr
|
|
|
41c151 |
{
|
|
|
41c151 |
MetaGpu parent;
|
|
|
41c151 |
|
|
|
41c151 |
XRRScreenResources *resources;
|
|
|
41c151 |
|
|
|
41c151 |
int max_screen_width;
|
|
|
41c151 |
int max_screen_height;
|
|
|
41c151 |
+
|
|
|
41c151 |
+ gboolean need_hardware_poll;
|
|
|
41c151 |
};
|
|
|
41c151 |
|
|
|
41c151 |
G_DEFINE_TYPE (MetaGpuXrandr, meta_gpu_xrandr, META_TYPE_GPU)
|
|
|
41c151 |
|
|
|
41c151 |
XRRScreenResources *
|
|
|
41c151 |
meta_gpu_xrandr_get_resources (MetaGpuXrandr *gpu_xrandr)
|
|
|
41c151 |
{
|
|
|
41c151 |
return gpu_xrandr->resources;
|
|
|
41c151 |
}
|
|
|
41c151 |
|
|
|
41c151 |
void
|
|
|
41c151 |
meta_gpu_xrandr_get_max_screen_size (MetaGpuXrandr *gpu_xrandr,
|
|
|
41c151 |
int *max_width,
|
|
|
41c151 |
int *max_height)
|
|
|
41c151 |
{
|
|
|
41c151 |
*max_width = gpu_xrandr->max_screen_width;
|
|
|
41c151 |
*max_height = gpu_xrandr->max_screen_height;
|
|
|
41c151 |
}
|
|
|
41c151 |
|
|
|
41c151 |
static int
|
|
|
41c151 |
compare_outputs (const void *one,
|
|
|
41c151 |
const void *two)
|
|
|
41c151 |
{
|
|
|
41c151 |
const MetaOutput *o_one = one, *o_two = two;
|
|
|
41c151 |
|
|
|
41c151 |
return strcmp (o_one->name, o_two->name);
|
|
|
41c151 |
}
|
|
|
41c151 |
|
|
|
41c151 |
static char *
|
|
|
41c151 |
get_xmode_name (XRRModeInfo *xmode)
|
|
|
41c151 |
{
|
|
|
41c151 |
int width = xmode->width;
|
|
|
41c151 |
int height = xmode->height;
|
|
|
41c151 |
|
|
|
41c151 |
return g_strdup_printf ("%dx%d", width, height);
|
|
|
41c151 |
}
|
|
|
41c151 |
|
|
|
67f8b7 |
+static void
|
|
|
41c151 |
+meta_gpu_xrandr_poll_hardware (MetaGpu *gpu)
|
|
|
67f8b7 |
+{
|
|
|
41c151 |
+ MetaGpuXrandr *gpu_xrandr = META_GPU_XRANDR (gpu);
|
|
|
67f8b7 |
+
|
|
|
41c151 |
+ gpu_xrandr->need_hardware_poll = TRUE;
|
|
|
41c151 |
+}
|
|
|
67f8b7 |
+
|
|
|
41c151 |
static gboolean
|
|
|
41c151 |
meta_gpu_xrandr_read_current (MetaGpu *gpu,
|
|
|
41c151 |
GError **error)
|
|
|
41c151 |
{
|
|
|
41c151 |
MetaGpuXrandr *gpu_xrandr = META_GPU_XRANDR (gpu);
|
|
|
41c151 |
MetaMonitorManager *monitor_manager = meta_gpu_get_monitor_manager (gpu);
|
|
|
41c151 |
MetaMonitorManagerXrandr *monitor_manager_xrandr =
|
|
|
41c151 |
META_MONITOR_MANAGER_XRANDR (monitor_manager);
|
|
|
41c151 |
Display *xdisplay =
|
|
|
41c151 |
meta_monitor_manager_xrandr_get_xdisplay (monitor_manager_xrandr);
|
|
|
41c151 |
XRRScreenResources *resources;
|
|
|
41c151 |
RROutput primary_output;
|
|
|
41c151 |
unsigned int i, j;
|
|
|
41c151 |
GList *l;
|
|
|
41c151 |
int min_width, min_height;
|
|
|
41c151 |
Screen *screen;
|
|
|
41c151 |
BOOL dpms_capable, dpms_enabled;
|
|
|
41c151 |
CARD16 dpms_state;
|
|
|
41c151 |
GList *outputs = NULL;
|
|
|
41c151 |
GList *modes = NULL;
|
|
|
41c151 |
GList *crtcs = NULL;
|
|
|
41c151 |
|
|
|
41c151 |
if (gpu_xrandr->resources)
|
|
|
41c151 |
XRRFreeScreenResources (gpu_xrandr->resources);
|
|
|
41c151 |
gpu_xrandr->resources = NULL;
|
|
|
41c151 |
|
|
|
41c151 |
dpms_capable = DPMSCapable (xdisplay);
|
|
|
41c151 |
|
|
|
41c151 |
if (dpms_capable &&
|
|
|
41c151 |
DPMSInfo (xdisplay, &dpms_state, &dpms_enabled) &&
|
|
|
41c151 |
@@ -121,62 +131,72 @@ meta_gpu_xrandr_read_current (MetaGpu *gpu,
|
|
|
41c151 |
case DPMSModeStandby:
|
|
|
41c151 |
monitor_manager->power_save_mode = META_POWER_SAVE_STANDBY;
|
|
|
41c151 |
break;
|
|
|
41c151 |
case DPMSModeSuspend:
|
|
|
41c151 |
monitor_manager->power_save_mode = META_POWER_SAVE_SUSPEND;
|
|
|
41c151 |
break;
|
|
|
41c151 |
case DPMSModeOff:
|
|
|
41c151 |
monitor_manager->power_save_mode = META_POWER_SAVE_OFF;
|
|
|
41c151 |
break;
|
|
|
41c151 |
default:
|
|
|
41c151 |
monitor_manager->power_save_mode = META_POWER_SAVE_UNSUPPORTED;
|
|
|
41c151 |
break;
|
|
|
41c151 |
}
|
|
|
41c151 |
}
|
|
|
41c151 |
else
|
|
|
41c151 |
{
|
|
|
41c151 |
monitor_manager->power_save_mode = META_POWER_SAVE_UNSUPPORTED;
|
|
|
41c151 |
}
|
|
|
41c151 |
|
|
|
41c151 |
XRRGetScreenSizeRange (xdisplay, DefaultRootWindow (xdisplay),
|
|
|
41c151 |
&min_width,
|
|
|
41c151 |
&min_height,
|
|
|
41c151 |
&gpu_xrandr->max_screen_width,
|
|
|
41c151 |
&gpu_xrandr->max_screen_height);
|
|
|
41c151 |
|
|
|
41c151 |
screen = ScreenOfDisplay (xdisplay, DefaultScreen (xdisplay));
|
|
|
41c151 |
/* This is updated because we called XRRUpdateConfiguration. */
|
|
|
41c151 |
monitor_manager->screen_width = WidthOfScreen (screen);
|
|
|
41c151 |
monitor_manager->screen_height = HeightOfScreen (screen);
|
|
|
41c151 |
|
|
|
41c151 |
- resources = XRRGetScreenResourcesCurrent (xdisplay,
|
|
|
41c151 |
- DefaultRootWindow (xdisplay));
|
|
|
41c151 |
+ if (gpu_xrandr->need_hardware_poll)
|
|
|
67f8b7 |
+ {
|
|
|
41c151 |
+ resources = XRRGetScreenResources (xdisplay,
|
|
|
41c151 |
+ DefaultRootWindow (xdisplay));
|
|
|
41c151 |
+ gpu_xrandr->need_hardware_poll = FALSE;
|
|
|
67f8b7 |
+ }
|
|
|
67f8b7 |
+ else
|
|
|
67f8b7 |
+ {
|
|
|
41c151 |
+ resources = XRRGetScreenResourcesCurrent (xdisplay,
|
|
|
41c151 |
+ DefaultRootWindow (xdisplay));
|
|
|
41c151 |
+ }
|
|
|
e47e58 |
+
|
|
|
41c151 |
if (!resources)
|
|
|
41c151 |
{
|
|
|
41c151 |
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
|
|
41c151 |
"Failed to retrieve Xrandr screen resources");
|
|
|
41c151 |
return FALSE;
|
|
|
41c151 |
}
|
|
|
41c151 |
|
|
|
41c151 |
gpu_xrandr->resources = resources;
|
|
|
41c151 |
|
|
|
41c151 |
outputs = NULL;
|
|
|
41c151 |
modes = NULL;
|
|
|
41c151 |
crtcs = NULL;
|
|
|
41c151 |
|
|
|
41c151 |
for (i = 0; i < (unsigned)resources->nmode; i++)
|
|
|
41c151 |
{
|
|
|
41c151 |
XRRModeInfo *xmode = &resources->modes[i];
|
|
|
41c151 |
MetaCrtcMode *mode;
|
|
|
41c151 |
|
|
|
41c151 |
mode = g_object_new (META_TYPE_CRTC_MODE, NULL);
|
|
|
41c151 |
|
|
|
41c151 |
mode->mode_id = xmode->id;
|
|
|
41c151 |
mode->width = xmode->width;
|
|
|
41c151 |
mode->height = xmode->height;
|
|
|
41c151 |
mode->refresh_rate = (xmode->dotClock /
|
|
|
41c151 |
((float)xmode->hTotal * xmode->vTotal));
|
|
|
41c151 |
mode->flags = xmode->modeFlags;
|
|
|
41c151 |
mode->name = get_xmode_name (xmode);
|
|
|
41c151 |
|
|
|
41c151 |
modes = g_list_append (modes, mode);
|
|
|
41c151 |
}
|
|
|
41c151 |
@@ -255,42 +275,44 @@ meta_gpu_xrandr_read_current (MetaGpu *gpu,
|
|
|
41c151 |
}
|
|
|
41c151 |
}
|
|
|
41c151 |
}
|
|
|
41c151 |
}
|
|
|
41c151 |
|
|
|
41c151 |
return TRUE;
|
|
|
41c151 |
}
|
|
|
41c151 |
|
|
|
41c151 |
MetaGpuXrandr *
|
|
|
41c151 |
meta_gpu_xrandr_new (MetaMonitorManagerXrandr *monitor_manager_xrandr)
|
|
|
41c151 |
{
|
|
|
41c151 |
return g_object_new (META_TYPE_GPU_XRANDR,
|
|
|
41c151 |
"monitor-manager", monitor_manager_xrandr,
|
|
|
41c151 |
NULL);
|
|
|
41c151 |
}
|
|
|
41c151 |
|
|
|
41c151 |
static void
|
|
|
41c151 |
meta_gpu_xrandr_finalize (GObject *object)
|
|
|
41c151 |
{
|
|
|
41c151 |
MetaGpuXrandr *gpu_xrandr = META_GPU_XRANDR (object);
|
|
|
41c151 |
|
|
|
41c151 |
g_clear_pointer (&gpu_xrandr->resources,
|
|
|
41c151 |
XRRFreeScreenResources);
|
|
|
41c151 |
|
|
|
41c151 |
G_OBJECT_CLASS (meta_gpu_xrandr_parent_class)->finalize (object);
|
|
|
41c151 |
}
|
|
|
41c151 |
|
|
|
41c151 |
static void
|
|
|
41c151 |
meta_gpu_xrandr_init (MetaGpuXrandr *gpu_xrandr)
|
|
|
41c151 |
{
|
|
|
41c151 |
+ gpu_xrandr->need_hardware_poll = TRUE;
|
|
|
41c151 |
}
|
|
|
41c151 |
|
|
|
41c151 |
static void
|
|
|
41c151 |
meta_gpu_xrandr_class_init (MetaGpuXrandrClass *klass)
|
|
|
41c151 |
{
|
|
|
41c151 |
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
41c151 |
MetaGpuClass *gpu_class = META_GPU_CLASS (klass);
|
|
|
41c151 |
|
|
|
41c151 |
object_class->finalize = meta_gpu_xrandr_finalize;
|
|
|
41c151 |
|
|
|
41c151 |
gpu_class->read_current = meta_gpu_xrandr_read_current;
|
|
|
41c151 |
+ gpu_class->poll_hardware = meta_gpu_xrandr_poll_hardware;
|
|
|
41c151 |
}
|
|
|
41c151 |
diff --git a/src/backends/x11/meta-monitor-manager-xrandr.c b/src/backends/x11/meta-monitor-manager-xrandr.c
|
|
|
41c151 |
index 90a3952db..2d9a32339 100644
|
|
|
41c151 |
--- a/src/backends/x11/meta-monitor-manager-xrandr.c
|
|
|
41c151 |
+++ b/src/backends/x11/meta-monitor-manager-xrandr.c
|
|
|
41c151 |
@@ -33,95 +33,101 @@
|
|
|
41c151 |
#include <clutter/clutter.h>
|
|
|
41c151 |
|
|
|
41c151 |
#include <X11/Xlibint.h>
|
|
|
41c151 |
#include <X11/extensions/dpms.h>
|
|
|
41c151 |
#include <X11/Xlib-xcb.h>
|
|
|
41c151 |
#include <xcb/randr.h>
|
|
|
41c151 |
|
|
|
41c151 |
#include "meta-backend-x11.h"
|
|
|
41c151 |
#include <meta/main.h>
|
|
|
41c151 |
#include <meta/errors.h>
|
|
|
41c151 |
#include "backends/meta-crtc.h"
|
|
|
41c151 |
#include "backends/meta-monitor-config-manager.h"
|
|
|
41c151 |
#include "backends/meta-logical-monitor.h"
|
|
|
41c151 |
#include "backends/meta-output.h"
|
|
|
41c151 |
#include "backends/x11/meta-crtc-xrandr.h"
|
|
|
41c151 |
#include "backends/x11/meta-gpu-xrandr.h"
|
|
|
41c151 |
#include "backends/x11/meta-output-xrandr.h"
|
|
|
41c151 |
|
|
|
41c151 |
/* Look for DPI_FALLBACK in:
|
|
|
41c151 |
* http://git.gnome.org/browse/gnome-settings-daemon/tree/plugins/xsettings/gsd-xsettings-manager.c
|
|
|
41c151 |
* for the reasoning */
|
|
|
41c151 |
#define DPI_FALLBACK 96.0
|
|
|
41c151 |
|
|
|
41c151 |
struct _MetaMonitorManagerXrandr
|
|
|
41c151 |
{
|
|
|
41c151 |
MetaMonitorManager parent_instance;
|
|
|
41c151 |
|
|
|
41c151 |
Display *xdisplay;
|
|
|
41c151 |
int rr_event_base;
|
|
|
41c151 |
int rr_error_base;
|
|
|
e47e58 |
+
|
|
|
41c151 |
+ guint logind_watch_id;
|
|
|
41c151 |
+ guint logind_signal_sub_id;
|
|
|
e47e58 |
+
|
|
|
41c151 |
gboolean has_randr15;
|
|
|
41c151 |
|
|
|
41c151 |
/*
|
|
|
41c151 |
* The X server deals with multiple GPUs for us, soe just see what the X
|
|
|
41c151 |
* server gives us as one single GPU, even though it may actually be backed
|
|
|
41c151 |
* by multiple.
|
|
|
41c151 |
*/
|
|
|
41c151 |
MetaGpu *gpu;
|
|
|
41c151 |
|
|
|
41c151 |
xcb_timestamp_t last_xrandr_set_timestamp;
|
|
|
41c151 |
|
|
|
41c151 |
#ifdef HAVE_XRANDR15
|
|
|
41c151 |
GHashTable *tiled_monitor_atoms;
|
|
|
41c151 |
#endif /* HAVE_XRANDR15 */
|
|
|
41c151 |
|
|
|
41c151 |
float *supported_scales;
|
|
|
41c151 |
int n_supported_scales;
|
|
|
41c151 |
};
|
|
|
41c151 |
|
|
|
41c151 |
struct _MetaMonitorManagerXrandrClass
|
|
|
41c151 |
{
|
|
|
41c151 |
MetaMonitorManagerClass parent_class;
|
|
|
41c151 |
};
|
|
|
41c151 |
|
|
|
41c151 |
G_DEFINE_TYPE (MetaMonitorManagerXrandr, meta_monitor_manager_xrandr, META_TYPE_MONITOR_MANAGER);
|
|
|
41c151 |
|
|
|
41c151 |
#ifdef HAVE_XRANDR15
|
|
|
41c151 |
typedef struct _MetaMonitorXrandrData
|
|
|
41c151 |
{
|
|
|
41c151 |
Atom xrandr_name;
|
|
|
41c151 |
} MetaMonitorXrandrData;
|
|
|
41c151 |
|
|
|
41c151 |
GQuark quark_meta_monitor_xrandr_data;
|
|
|
41c151 |
#endif /* HAVE_RANDR15 */
|
|
|
41c151 |
|
|
|
41c151 |
+static void meta_monitor_manager_xrandr_update (MetaMonitorManagerXrandr *manager_xrandr);
|
|
|
67f8b7 |
+
|
|
|
41c151 |
Display *
|
|
|
41c151 |
meta_monitor_manager_xrandr_get_xdisplay (MetaMonitorManagerXrandr *manager_xrandr)
|
|
|
41c151 |
{
|
|
|
41c151 |
return manager_xrandr->xdisplay;
|
|
|
41c151 |
}
|
|
|
41c151 |
|
|
|
41c151 |
gboolean
|
|
|
41c151 |
meta_monitor_manager_xrandr_has_randr15 (MetaMonitorManagerXrandr *manager_xrandr)
|
|
|
41c151 |
{
|
|
|
41c151 |
return manager_xrandr->has_randr15;
|
|
|
41c151 |
}
|
|
|
41c151 |
|
|
|
41c151 |
static GBytes *
|
|
|
41c151 |
meta_monitor_manager_xrandr_read_edid (MetaMonitorManager *manager,
|
|
|
41c151 |
MetaOutput *output)
|
|
|
41c151 |
{
|
|
|
41c151 |
return meta_output_xrandr_read_edid (output);
|
|
|
41c151 |
}
|
|
|
41c151 |
|
|
|
41c151 |
static void
|
|
|
41c151 |
meta_monitor_manager_xrandr_set_power_save_mode (MetaMonitorManager *manager,
|
|
|
41c151 |
MetaPowerSave mode)
|
|
|
41c151 |
{
|
|
|
41c151 |
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
|
|
|
41c151 |
CARD16 state;
|
|
|
41c151 |
|
|
|
41c151 |
switch (mode) {
|
|
|
41c151 |
case META_POWER_SAVE_ON:
|
|
|
41c151 |
state = DPMSModeOn;
|
|
|
41c151 |
break;
|
|
|
41c151 |
@@ -934,198 +940,272 @@ meta_monitor_manager_xrandr_calculate_supported_scales (MetaMonitorManager
|
|
|
41c151 |
manager_xrandr->n_supported_scales * sizeof (float));
|
|
|
41c151 |
}
|
|
|
41c151 |
|
|
|
41c151 |
static MetaMonitorManagerCapability
|
|
|
41c151 |
meta_monitor_manager_xrandr_get_capabilities (MetaMonitorManager *manager)
|
|
|
41c151 |
{
|
|
|
41c151 |
return (META_MONITOR_MANAGER_CAPABILITY_MIRRORING |
|
|
|
41c151 |
META_MONITOR_MANAGER_CAPABILITY_GLOBAL_SCALE_REQUIRED);
|
|
|
41c151 |
}
|
|
|
41c151 |
|
|
|
41c151 |
static gboolean
|
|
|
41c151 |
meta_monitor_manager_xrandr_get_max_screen_size (MetaMonitorManager *manager,
|
|
|
41c151 |
int *max_width,
|
|
|
41c151 |
int *max_height)
|
|
|
41c151 |
{
|
|
|
41c151 |
MetaMonitorManagerXrandr *manager_xrandr =
|
|
|
41c151 |
META_MONITOR_MANAGER_XRANDR (manager);
|
|
|
41c151 |
|
|
|
41c151 |
meta_gpu_xrandr_get_max_screen_size (META_GPU_XRANDR (manager_xrandr->gpu),
|
|
|
41c151 |
max_width, max_height);
|
|
|
41c151 |
|
|
|
41c151 |
return TRUE;
|
|
|
41c151 |
}
|
|
|
41c151 |
|
|
|
41c151 |
static MetaLogicalMonitorLayoutMode
|
|
|
41c151 |
meta_monitor_manager_xrandr_get_default_layout_mode (MetaMonitorManager *manager)
|
|
|
41c151 |
{
|
|
|
41c151 |
return META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL;
|
|
|
41c151 |
}
|
|
|
41c151 |
|
|
|
67f8b7 |
+static void
|
|
|
67f8b7 |
+logind_signal_handler (GDBusConnection *connection,
|
|
|
67f8b7 |
+ const gchar *sender_name,
|
|
|
67f8b7 |
+ const gchar *object_path,
|
|
|
67f8b7 |
+ const gchar *interface_name,
|
|
|
67f8b7 |
+ const gchar *signal_name,
|
|
|
67f8b7 |
+ GVariant *parameters,
|
|
|
67f8b7 |
+ gpointer user_data)
|
|
|
67f8b7 |
+{
|
|
|
67f8b7 |
+ MetaMonitorManagerXrandr *manager_xrandr = user_data;
|
|
|
67f8b7 |
+ gboolean suspending;
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ if (!g_str_equal (signal_name, "PrepareForSleep"))
|
|
|
67f8b7 |
+ return;
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ g_variant_get (parameters, "(b)", &suspending);
|
|
|
67f8b7 |
+ if (!suspending)
|
|
|
67f8b7 |
+ {
|
|
|
41c151 |
+ meta_gpu_poll_hardware (manager_xrandr->gpu);
|
|
|
67f8b7 |
+ meta_monitor_manager_xrandr_update (manager_xrandr);
|
|
|
67f8b7 |
+ }
|
|
|
67f8b7 |
+}
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+static void
|
|
|
67f8b7 |
+logind_appeared (GDBusConnection *connection,
|
|
|
67f8b7 |
+ const gchar *name,
|
|
|
67f8b7 |
+ const gchar *name_owner,
|
|
|
67f8b7 |
+ gpointer user_data)
|
|
|
67f8b7 |
+{
|
|
|
67f8b7 |
+ MetaMonitorManagerXrandr *manager_xrandr = user_data;
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ manager_xrandr->logind_signal_sub_id = g_dbus_connection_signal_subscribe (connection,
|
|
|
67f8b7 |
+ "org.freedesktop.login1",
|
|
|
67f8b7 |
+ "org.freedesktop.login1.Manager",
|
|
|
67f8b7 |
+ "PrepareForSleep",
|
|
|
67f8b7 |
+ "/org/freedesktop/login1",
|
|
|
67f8b7 |
+ NULL,
|
|
|
67f8b7 |
+ G_DBUS_SIGNAL_FLAGS_NONE,
|
|
|
67f8b7 |
+ logind_signal_handler,
|
|
|
67f8b7 |
+ manager_xrandr,
|
|
|
67f8b7 |
+ NULL);
|
|
|
67f8b7 |
+}
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+static void
|
|
|
67f8b7 |
+logind_vanished (GDBusConnection *connection,
|
|
|
67f8b7 |
+ const gchar *name,
|
|
|
67f8b7 |
+ gpointer user_data)
|
|
|
67f8b7 |
+{
|
|
|
67f8b7 |
+ MetaMonitorManagerXrandr *manager_xrandr = user_data;
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ if (connection && manager_xrandr->logind_signal_sub_id > 0)
|
|
|
67f8b7 |
+ g_dbus_connection_signal_unsubscribe (connection, manager_xrandr->logind_signal_sub_id);
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ manager_xrandr->logind_signal_sub_id = 0;
|
|
|
67f8b7 |
+}
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
static void
|
|
|
41c151 |
meta_monitor_manager_xrandr_constructed (GObject *object)
|
|
|
67f8b7 |
{
|
|
|
41c151 |
MetaMonitorManagerXrandr *manager_xrandr =
|
|
|
41c151 |
META_MONITOR_MANAGER_XRANDR (object);
|
|
|
41c151 |
MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_xrandr);
|
|
|
41c151 |
MetaBackendX11 *backend =
|
|
|
41c151 |
META_BACKEND_X11 (meta_monitor_manager_get_backend (manager));
|
|
|
41c151 |
|
|
|
41c151 |
manager_xrandr->xdisplay = meta_backend_x11_get_xdisplay (backend);
|
|
|
41c151 |
|
|
|
41c151 |
manager_xrandr->gpu = META_GPU (meta_gpu_xrandr_new (manager_xrandr));
|
|
|
41c151 |
meta_monitor_manager_add_gpu (manager, manager_xrandr->gpu);
|
|
|
41c151 |
|
|
|
41c151 |
if (!XRRQueryExtension (manager_xrandr->xdisplay,
|
|
|
41c151 |
&manager_xrandr->rr_event_base,
|
|
|
41c151 |
&manager_xrandr->rr_error_base))
|
|
|
41c151 |
{
|
|
|
41c151 |
return;
|
|
|
41c151 |
}
|
|
|
41c151 |
else
|
|
|
41c151 |
{
|
|
|
41c151 |
int major_version, minor_version;
|
|
|
41c151 |
/* We only use ScreenChangeNotify, but GDK uses the others,
|
|
|
41c151 |
and we don't want to step on its toes */
|
|
|
41c151 |
XRRSelectInput (manager_xrandr->xdisplay,
|
|
|
41c151 |
DefaultRootWindow (manager_xrandr->xdisplay),
|
|
|
41c151 |
RRScreenChangeNotifyMask
|
|
|
41c151 |
| RRCrtcChangeNotifyMask
|
|
|
41c151 |
| RROutputPropertyNotifyMask);
|
|
|
41c151 |
|
|
|
41c151 |
manager_xrandr->has_randr15 = FALSE;
|
|
|
41c151 |
XRRQueryVersion (manager_xrandr->xdisplay, &major_version,
|
|
|
41c151 |
&minor_version);
|
|
|
41c151 |
#ifdef HAVE_XRANDR15
|
|
|
41c151 |
if (major_version > 1 ||
|
|
|
41c151 |
(major_version == 1 &&
|
|
|
41c151 |
minor_version >= 5))
|
|
|
41c151 |
{
|
|
|
41c151 |
manager_xrandr->has_randr15 = TRUE;
|
|
|
41c151 |
manager_xrandr->tiled_monitor_atoms = g_hash_table_new (NULL, NULL);
|
|
|
41c151 |
}
|
|
|
67f8b7 |
meta_monitor_manager_xrandr_init_monitors (manager_xrandr);
|
|
|
67f8b7 |
#endif
|
|
|
67f8b7 |
}
|
|
|
41c151 |
|
|
|
41c151 |
G_OBJECT_CLASS (meta_monitor_manager_xrandr_parent_class)->constructed (object);
|
|
|
67f8b7 |
}
|
|
|
67f8b7 |
|
|
|
67f8b7 |
static void
|
|
|
41c151 |
meta_monitor_manager_xrandr_finalize (GObject *object)
|
|
|
41c151 |
{
|
|
|
41c151 |
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (object);
|
|
|
41c151 |
|
|
|
41c151 |
g_clear_object (&manager_xrandr->gpu);
|
|
|
e47e58 |
g_hash_table_destroy (manager_xrandr->tiled_monitor_atoms);
|
|
|
e47e58 |
g_free (manager_xrandr->supported_scales);
|
|
|
67f8b7 |
|
|
|
67f8b7 |
+ if (manager_xrandr->logind_watch_id > 0)
|
|
|
67f8b7 |
+ g_bus_unwatch_name (manager_xrandr->logind_watch_id);
|
|
|
67f8b7 |
+ manager_xrandr->logind_watch_id = 0;
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
G_OBJECT_CLASS (meta_monitor_manager_xrandr_parent_class)->finalize (object);
|
|
|
67f8b7 |
}
|
|
|
67f8b7 |
|
|
|
41c151 |
static void
|
|
|
41c151 |
meta_monitor_manager_xrandr_init (MetaMonitorManagerXrandr *manager_xrandr)
|
|
|
41c151 |
{
|
|
|
41c151 |
+ manager_xrandr->logind_watch_id = g_bus_watch_name (G_BUS_TYPE_SYSTEM,
|
|
|
41c151 |
+ "org.freedesktop.login1",
|
|
|
41c151 |
+ G_BUS_NAME_WATCHER_FLAGS_NONE,
|
|
|
41c151 |
+ logind_appeared,
|
|
|
41c151 |
+ logind_vanished,
|
|
|
41c151 |
+ manager_xrandr,
|
|
|
41c151 |
+ NULL);
|
|
|
41c151 |
}
|
|
|
41c151 |
|
|
|
41c151 |
static void
|
|
|
41c151 |
meta_monitor_manager_xrandr_class_init (MetaMonitorManagerXrandrClass *klass)
|
|
|
41c151 |
{
|
|
|
41c151 |
MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_CLASS (klass);
|
|
|
41c151 |
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
41c151 |
|
|
|
41c151 |
object_class->finalize = meta_monitor_manager_xrandr_finalize;
|
|
|
41c151 |
object_class->constructed = meta_monitor_manager_xrandr_constructed;
|
|
|
41c151 |
|
|
|
41c151 |
manager_class->read_edid = meta_monitor_manager_xrandr_read_edid;
|
|
|
41c151 |
manager_class->ensure_initial_config = meta_monitor_manager_xrandr_ensure_initial_config;
|
|
|
41c151 |
manager_class->apply_monitors_config = meta_monitor_manager_xrandr_apply_monitors_config;
|
|
|
41c151 |
manager_class->set_power_save_mode = meta_monitor_manager_xrandr_set_power_save_mode;
|
|
|
41c151 |
manager_class->change_backlight = meta_monitor_manager_xrandr_change_backlight;
|
|
|
41c151 |
manager_class->get_crtc_gamma = meta_monitor_manager_xrandr_get_crtc_gamma;
|
|
|
41c151 |
manager_class->set_crtc_gamma = meta_monitor_manager_xrandr_set_crtc_gamma;
|
|
|
41c151 |
#ifdef HAVE_XRANDR15
|
|
|
41c151 |
manager_class->tiled_monitor_added = meta_monitor_manager_xrandr_tiled_monitor_added;
|
|
|
41c151 |
manager_class->tiled_monitor_removed = meta_monitor_manager_xrandr_tiled_monitor_removed;
|
|
|
41c151 |
#endif
|
|
|
41c151 |
manager_class->is_transform_handled = meta_monitor_manager_xrandr_is_transform_handled;
|
|
|
41c151 |
manager_class->calculate_monitor_mode_scale = meta_monitor_manager_xrandr_calculate_monitor_mode_scale;
|
|
|
41c151 |
manager_class->calculate_supported_scales = meta_monitor_manager_xrandr_calculate_supported_scales;
|
|
|
41c151 |
manager_class->get_capabilities = meta_monitor_manager_xrandr_get_capabilities;
|
|
|
41c151 |
manager_class->get_max_screen_size = meta_monitor_manager_xrandr_get_max_screen_size;
|
|
|
41c151 |
manager_class->get_default_layout_mode = meta_monitor_manager_xrandr_get_default_layout_mode;
|
|
|
41c151 |
|
|
|
41c151 |
quark_meta_monitor_xrandr_data =
|
|
|
e47e58 |
g_quark_from_static_string ("-meta-monitor-xrandr-data");
|
|
|
67f8b7 |
}
|
|
|
67f8b7 |
|
|
|
41c151 |
static gboolean
|
|
|
41c151 |
is_xvnc (MetaMonitorManager *manager)
|
|
|
67f8b7 |
{
|
|
|
41c151 |
MetaMonitorManagerXrandr *manager_xrandr =
|
|
|
41c151 |
META_MONITOR_MANAGER_XRANDR (manager);
|
|
|
41c151 |
GList *l;
|
|
|
67f8b7 |
|
|
|
41c151 |
for (l = meta_gpu_get_outputs (manager_xrandr->gpu); l; l = l->next)
|
|
|
41c151 |
{
|
|
|
41c151 |
MetaOutput *output = l->data;
|
|
|
67f8b7 |
|
|
|
41c151 |
if (g_str_has_prefix (output->name, "VNC-"))
|
|
|
41c151 |
return TRUE;
|
|
|
41c151 |
}
|
|
|
41c151 |
|
|
|
41c151 |
return FALSE;
|
|
|
41c151 |
}
|
|
|
41c151 |
|
|
|
41c151 |
-gboolean
|
|
|
41c151 |
-meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xrandr,
|
|
|
41c151 |
- XEvent *event)
|
|
|
41c151 |
+static void
|
|
|
41c151 |
+meta_monitor_manager_xrandr_update (MetaMonitorManagerXrandr *manager_xrandr)
|
|
|
41c151 |
{
|
|
|
41c151 |
MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_xrandr);
|
|
|
41c151 |
MetaGpuXrandr *gpu_xrandr;
|
|
|
41c151 |
XRRScreenResources *resources;
|
|
|
41c151 |
gboolean is_hotplug;
|
|
|
41c151 |
gboolean is_our_configuration;
|
|
|
41c151 |
unsigned int timestamp;
|
|
|
41c151 |
|
|
|
41c151 |
- if ((event->type - manager_xrandr->rr_event_base) != RRScreenChangeNotify)
|
|
|
41c151 |
- return FALSE;
|
|
|
e47e58 |
-
|
|
|
41c151 |
- XRRUpdateConfiguration (event);
|
|
|
e47e58 |
-
|
|
|
41c151 |
meta_monitor_manager_read_current_state (manager);
|
|
|
41c151 |
|
|
|
41c151 |
gpu_xrandr = META_GPU_XRANDR (manager_xrandr->gpu);
|
|
|
41c151 |
resources = meta_gpu_xrandr_get_resources (gpu_xrandr);
|
|
|
41c151 |
|
|
|
41c151 |
timestamp = resources->timestamp;
|
|
|
41c151 |
if (is_xvnc (manager))
|
|
|
41c151 |
timestamp += 100;
|
|
|
41c151 |
|
|
|
41c151 |
is_hotplug = timestamp < resources->configTimestamp;
|
|
|
41c151 |
is_our_configuration = (resources->timestamp ==
|
|
|
41c151 |
manager_xrandr->last_xrandr_set_timestamp);
|
|
|
41c151 |
if (is_hotplug)
|
|
|
41c151 |
{
|
|
|
41c151 |
meta_monitor_manager_on_hotplug (manager);
|
|
|
41c151 |
}
|
|
|
41c151 |
else
|
|
|
41c151 |
{
|
|
|
41c151 |
MetaMonitorsConfig *config;
|
|
|
41c151 |
|
|
|
41c151 |
if (is_our_configuration)
|
|
|
41c151 |
{
|
|
|
41c151 |
MetaMonitorConfigManager *config_manager =
|
|
|
41c151 |
meta_monitor_manager_get_config_manager (manager);
|
|
|
41c151 |
|
|
|
41c151 |
config = meta_monitor_config_manager_get_current (config_manager);
|
|
|
41c151 |
}
|
|
|
41c151 |
else
|
|
|
41c151 |
{
|
|
|
41c151 |
config = NULL;
|
|
|
41c151 |
}
|
|
|
41c151 |
|
|
|
41c151 |
meta_monitor_manager_xrandr_rebuild_derived (manager, config);
|
|
|
41c151 |
}
|
|
|
41c151 |
+}
|
|
|
41c151 |
+
|
|
|
41c151 |
+gboolean
|
|
|
41c151 |
+meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xrandr,
|
|
|
41c151 |
+ XEvent *event)
|
|
|
41c151 |
+{
|
|
|
41c151 |
+
|
|
|
41c151 |
+ if ((event->type - manager_xrandr->rr_event_base) != RRScreenChangeNotify)
|
|
|
41c151 |
+ return FALSE;
|
|
|
41c151 |
+
|
|
|
41c151 |
+ XRRUpdateConfiguration (event);
|
|
|
41c151 |
+
|
|
|
67f8b7 |
+ meta_monitor_manager_xrandr_update (manager_xrandr);
|
|
|
67f8b7 |
|
|
|
67f8b7 |
return TRUE;
|
|
|
67f8b7 |
}
|
|
|
67f8b7 |
--
|
|
|
41c151 |
2.17.1
|
|
|
67f8b7 |
|