Blob Blame History Raw
From 85484d8f5d75764ab74308da7b21411c3fe4a2da Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Wed, 3 Oct 2018 10:50:47 +0200
Subject: [PATCH 2/2] monitor-manager/xrandr: Create dummy screen sized monitor
 if no RANDR

When there is no RANDR support enabled in the X server, we wont get
notified of any monitors, resulting in mutter believing we're being
headless. To get at least something working, although with no way
configuration ability, lets pretend the whole screen is just a single
monitor with a single output, crtc and mode.
---
 src/backends/x11/meta-gpu-xrandr.c            | 60 +++++++++++++++++++
 .../x11/meta-monitor-manager-xrandr.c         | 22 ++++++-
 .../x11/meta-monitor-manager-xrandr.h         |  4 ++
 3 files changed, 85 insertions(+), 1 deletion(-)

diff --git a/src/backends/x11/meta-gpu-xrandr.c b/src/backends/x11/meta-gpu-xrandr.c
index 1884278ca..22e7e70e0 100644
--- a/src/backends/x11/meta-gpu-xrandr.c
+++ b/src/backends/x11/meta-gpu-xrandr.c
@@ -115,6 +115,63 @@ update_screen_size (MetaGpuXrandr *gpu_xrandr)
   monitor_manager->screen_height = HeightOfScreen (screen);
 }
 
+static gboolean
+read_current_fallback (MetaGpuXrandr            *gpu_xrandr,
+                       MetaMonitorManagerXrandr *monitor_manager_xrandr)
+{
+  MetaGpu *gpu = META_GPU (gpu_xrandr);
+  MetaMonitorManager *monitor_manager =
+    META_MONITOR_MANAGER (monitor_manager_xrandr);
+  MetaCrtcMode *mode;
+  MetaCrtc *crtc;
+  MetaOutput *output;
+
+  meta_monitor_manager_xrandr_update_dpms_state (monitor_manager_xrandr);
+  update_screen_size (gpu_xrandr);
+
+  mode = g_object_new (META_TYPE_CRTC_MODE, NULL);
+  mode->mode_id = 0;
+  mode->width = monitor_manager->screen_width;
+  mode->height = monitor_manager->screen_height;
+  mode->refresh_rate = 60.0;
+  mode->name = g_strdup_printf ("%dx%d", mode->width, mode->height);
+
+  meta_gpu_take_modes (gpu, g_list_prepend (NULL, mode));
+
+  crtc = g_object_new (META_TYPE_CRTC, NULL);
+  crtc->gpu = gpu;
+  crtc->crtc_id = 0;
+  crtc->rect = (MetaRectangle) { .width = mode->width, .height = mode->height };
+  crtc->current_mode = mode;
+
+  meta_gpu_take_crtcs (gpu, g_list_prepend (NULL, crtc));
+
+  output = g_object_new (META_TYPE_OUTPUT, NULL);
+  output->gpu = gpu;
+  output->winsys_id = 0;
+  output->name = g_strdup ("X11 Screen");
+  output->vendor = g_strdup ("unknown");
+  output->product = g_strdup ("unknown");
+  output->serial = g_strdup ("unknown");
+  output->hotplug_mode_update = TRUE;
+  output->suggested_x = -1;
+  output->suggested_y = -1;
+  output->connector_type = META_CONNECTOR_TYPE_Unknown;
+  output->modes = g_new0 (MetaCrtcMode *, 1);
+  output->modes[0] = mode;
+  output->n_modes = 1;
+  output->preferred_mode = mode;
+  output->possible_crtcs = g_new0 (MetaCrtc *, 1);
+  output->possible_crtcs[0] = crtc;
+  output->n_possible_crtcs = 1;
+  meta_output_assign_crtc (output, crtc);
+  output->is_primary = TRUE;
+
+  meta_gpu_take_outputs (gpu, g_list_prepend (NULL, output));
+
+  return TRUE;
+}
+
 static gboolean
 meta_gpu_xrandr_read_current (MetaGpu  *gpu,
                               GError  **error)
@@ -133,6 +190,9 @@ meta_gpu_xrandr_read_current (MetaGpu  *gpu,
   GList *modes = NULL;
   GList *crtcs = NULL;
 
+  if (!meta_monitor_manager_xrandr_has_randr (monitor_manager_xrandr))
+    return read_current_fallback (gpu_xrandr, monitor_manager_xrandr);
+
   if (gpu_xrandr->resources)
     XRRFreeScreenResources (gpu_xrandr->resources);
   gpu_xrandr->resources = NULL;
diff --git a/src/backends/x11/meta-monitor-manager-xrandr.c b/src/backends/x11/meta-monitor-manager-xrandr.c
index 7a0b43ac4..d6306faeb 100644
--- a/src/backends/x11/meta-monitor-manager-xrandr.c
+++ b/src/backends/x11/meta-monitor-manager-xrandr.c
@@ -75,6 +75,7 @@ struct _MetaMonitorManagerXrandr
   guint logind_watch_id;
   guint logind_signal_sub_id;
 
+  gboolean has_randr;
   gboolean has_randr15;
 
   /*
@@ -114,6 +115,12 @@ meta_monitor_manager_xrandr_get_xdisplay (MetaMonitorManagerXrandr *manager_xran
   return manager_xrandr->xdisplay;
 }
 
+gboolean
+meta_monitor_manager_xrandr_has_randr (MetaMonitorManagerXrandr *manager_xrandr)
+{
+  return manager_xrandr->has_randr;
+}
+
 gboolean
 meta_monitor_manager_xrandr_has_randr15 (MetaMonitorManagerXrandr *manager_xrandr)
 {
@@ -145,7 +152,7 @@ x11_dpms_state_to_power_save (CARD16 dpms_state)
     }
 }
 
-static void
+void
 meta_monitor_manager_xrandr_update_dpms_state (MetaMonitorManagerXrandr *manager_xrandr)
 {
   MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_xrandr);
@@ -637,9 +644,18 @@ meta_monitor_manager_xrandr_apply_monitors_config (MetaMonitorManager      *mana
                                                    MetaMonitorsConfigMethod method,
                                                    GError                 **error)
 {
+  MetaMonitorManagerXrandr *manager_xrandr =
+    META_MONITOR_MANAGER_XRANDR (manager);
   GPtrArray *crtc_infos;
   GPtrArray *output_infos;
 
+  if (!manager_xrandr->has_randr)
+    {
+      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                   "Tried to change configuration without XRANDR support");
+      return FALSE;
+    }
+
   if (!config)
     {
       meta_monitor_manager_xrandr_rebuild_derived (manager, NULL);
@@ -1105,11 +1121,15 @@ meta_monitor_manager_xrandr_constructed (GObject *object)
 			  &manager_xrandr->rr_event_base,
 			  &manager_xrandr->rr_error_base))
     {
+      g_warning ("No RANDR support, monitor configuration disabled");
       return;
     }
   else
     {
       int major_version, minor_version;
+
+      manager_xrandr->has_randr = TRUE;
+
       /* We only use ScreenChangeNotify, but GDK uses the others,
 	 and we don't want to step on its toes */
       XRRSelectInput (manager_xrandr->xdisplay,
diff --git a/src/backends/x11/meta-monitor-manager-xrandr.h b/src/backends/x11/meta-monitor-manager-xrandr.h
index d55b3d2b8..dc75134a5 100644
--- a/src/backends/x11/meta-monitor-manager-xrandr.h
+++ b/src/backends/x11/meta-monitor-manager-xrandr.h
@@ -33,9 +33,13 @@ G_DECLARE_FINAL_TYPE (MetaMonitorManagerXrandr, meta_monitor_manager_xrandr,
 
 Display * meta_monitor_manager_xrandr_get_xdisplay (MetaMonitorManagerXrandr *manager_xrandr);
 
+gboolean meta_monitor_manager_xrandr_has_randr (MetaMonitorManagerXrandr *manager_xrandr);
+
 gboolean meta_monitor_manager_xrandr_has_randr15 (MetaMonitorManagerXrandr *manager_xrandr);
 
 gboolean meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager,
                                                     XEvent                   *event);
 
+void meta_monitor_manager_xrandr_update_dpms_state (MetaMonitorManagerXrandr *manager_xrandr);
+
 #endif /* META_MONITOR_MANAGER_XRANDR_H */
-- 
2.23.0