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