From 9f65edd4f547f056ebaf1e5a144097390147f042 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 31 Mar 2015 11:11:12 +1000 Subject: [PATCH] backend/x11: add support for setting randr 1.5 monitors This interface allows us to propogate back the constructed monitors to randr using the randr 1.5 protocol. Apps should pick it up from there. --- src/backends/meta-monitor-manager-private.h | 7 ++ src/backends/meta-monitor-manager.c | 27 +++++- .../x11/meta-monitor-manager-xrandr.c | 87 +++++++++++++++++++ 3 files changed, 120 insertions(+), 1 deletion(-) diff --git a/src/backends/meta-monitor-manager-private.h b/src/backends/meta-monitor-manager-private.h index c5444d623..d21888ed6 100644 --- a/src/backends/meta-monitor-manager-private.h +++ b/src/backends/meta-monitor-manager-private.h @@ -349,6 +349,13 @@ struct _MetaMonitorManagerClass unsigned short *, unsigned short *, unsigned short *); + + void (*add_monitor) (MetaMonitorManager *, + MetaMonitorInfo *); + + void (*delete_monitor) (MetaMonitorManager *, + int monitor_winsys_xid); + }; void meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager); diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c index 89efaca82..21ab21583 100644 --- a/src/backends/meta-monitor-manager.c +++ b/src/backends/meta-monitor-manager.c @@ -173,6 +173,7 @@ construct_tile_monitor (MetaMonitorManager *manager, static void make_logical_config (MetaMonitorManager *manager) { + MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_GET_CLASS (manager); GArray *monitor_infos; unsigned int i, j; @@ -277,6 +278,10 @@ make_logical_config (MetaMonitorManager *manager) manager->n_monitor_infos = monitor_infos->len; manager->monitor_infos = (void*)g_array_free (monitor_infos, FALSE); + + if (manager_class->add_monitor) + for (i = 0; i < manager->n_monitor_infos; i++) + manager_class->add_monitor (manager, &manager->monitor_infos[i]); } static void @@ -1356,15 +1361,35 @@ meta_monitor_manager_read_current_config (MetaMonitorManager *manager) void meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager) { + MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_GET_CLASS (manager); MetaMonitorInfo *old_monitor_infos; - + unsigned old_n_monitor_infos; + unsigned i, j; old_monitor_infos = manager->monitor_infos; + old_n_monitor_infos = manager->n_monitor_infos; if (manager->in_init) return; make_logical_config (manager); + if (manager_class->delete_monitor) + { + for (i = 0; i < old_n_monitor_infos; i++) + { + gboolean delete_mon = TRUE; + for (j = 0; j < manager->n_monitor_infos; j++) + { + if (manager->monitor_infos[j].monitor_winsys_xid == old_monitor_infos[i].monitor_winsys_xid) + { + delete_mon = FALSE; + break; + } + } + if (delete_mon) + manager_class->delete_monitor (manager, old_monitor_infos[i].monitor_winsys_xid); + } + } g_signal_emit_by_name (manager, "monitors-changed"); g_free (old_monitor_infos); diff --git a/src/backends/x11/meta-monitor-manager-xrandr.c b/src/backends/x11/meta-monitor-manager-xrandr.c index 81948e6e5..3e52679cc 100644 --- a/src/backends/x11/meta-monitor-manager-xrandr.c +++ b/src/backends/x11/meta-monitor-manager-xrandr.c @@ -1251,6 +1251,88 @@ meta_monitor_manager_xrandr_set_crtc_gamma (MetaMonitorManager *manager, XRRFreeGamma (gamma); } +#ifdef HAVE_XRANDR15 +static void +meta_monitor_manager_xrandr_add_monitor(MetaMonitorManager *manager, + MetaMonitorInfo *monitor) +{ + MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager); + XRRMonitorInfo *m; + int o; + Atom name; + char name_buf[40]; + + if (manager_xrandr->has_randr15 == FALSE) + return; + + if (monitor->n_outputs <= 1) + return; + + if (monitor->outputs[0]->product) + snprintf (name_buf, 40, "%s-%d", monitor->outputs[0]->product, monitor->outputs[0]->tile_info.group_id); + else + snprintf (name_buf, 40, "Tiled-%d", monitor->outputs[0]->tile_info.group_id); + + name = XInternAtom (manager_xrandr->xdisplay, name_buf, False); + monitor->monitor_winsys_xid = name; + m = XRRAllocateMonitor (manager_xrandr->xdisplay, monitor->n_outputs); + if (!m) + return; + m->name = name; + m->primary = monitor->is_primary; + m->automatic = True; + + for (o = 0; o < monitor->n_outputs; o++) { + MetaOutput *output = monitor->outputs[o]; + m->outputs[o] = output->winsys_id; + } + XRRSetMonitor (manager_xrandr->xdisplay, + DefaultRootWindow (manager_xrandr->xdisplay), + m); + XRRFreeMonitors (m); +} + +static void +meta_monitor_manager_xrandr_delete_monitor(MetaMonitorManager *manager, + int monitor_winsys_xid) +{ + MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager); + + if (manager_xrandr->has_randr15 == FALSE) + return; + XRRDeleteMonitor (manager_xrandr->xdisplay, + DefaultRootWindow (manager_xrandr->xdisplay), + monitor_winsys_xid); +} + +static void +meta_monitor_manager_xrandr_init_monitors(MetaMonitorManagerXrandr *manager_xrandr) +{ + XRRMonitorInfo *m; + int n, i; + + if (manager_xrandr->has_randr15 == FALSE) + return; + + /* delete any tiled monitors setup, as mutter will want to recreate + things in its image */ + m = XRRGetMonitors (manager_xrandr->xdisplay, + DefaultRootWindow (manager_xrandr->xdisplay), + FALSE, &n); + if (n == -1) + return; + + for (i = 0; i < n; i++) + { + if (m[i].noutput > 1) + XRRDeleteMonitor (manager_xrandr->xdisplay, + DefaultRootWindow (manager_xrandr->xdisplay), + m[i].name); + } + XRRFreeMonitors (m); +} +#endif + static void meta_monitor_manager_xrandr_init (MetaMonitorManagerXrandr *manager_xrandr) { @@ -1283,6 +1365,7 @@ meta_monitor_manager_xrandr_init (MetaMonitorManagerXrandr *manager_xrandr) (major_version == 1 && minor_version >= 5)) manager_xrandr->has_randr15 = TRUE; + meta_monitor_manager_xrandr_init_monitors (manager_xrandr); #endif } } @@ -1314,6 +1397,10 @@ meta_monitor_manager_xrandr_class_init (MetaMonitorManagerXrandrClass *klass) manager_class->change_backlight = meta_monitor_manager_xrandr_change_backlight; manager_class->get_crtc_gamma = meta_monitor_manager_xrandr_get_crtc_gamma; manager_class->set_crtc_gamma = meta_monitor_manager_xrandr_set_crtc_gamma; +#ifdef HAVE_XRANDR15 + manager_class->add_monitor = meta_monitor_manager_xrandr_add_monitor; + manager_class->delete_monitor = meta_monitor_manager_xrandr_delete_monitor; +#endif } gboolean