diff --git a/src/backends/meta-logical-monitor.h b/src/backends/meta-logical-monitor.h index 543f35be6..a6a664d9f 100644 --- a/src/backends/meta-logical-monitor.h +++ b/src/backends/meta-logical-monitor.h @@ -55,7 +55,6 @@ struct _MetaLogicalMonitor */ glong winsys_id; - int monitor_winsys_xid; int n_outputs; MetaOutput *outputs[META_MAX_OUTPUTS_PER_MONITOR]; diff --git a/src/backends/meta-monitor-manager-private.h b/src/backends/meta-monitor-manager-private.h index e27107b54..bc902bc83 100644 --- a/src/backends/meta-monitor-manager-private.h +++ b/src/backends/meta-monitor-manager-private.h @@ -319,11 +319,11 @@ struct _MetaMonitorManagerClass unsigned short *, unsigned short *); - void (*add_monitor) (MetaMonitorManager *, - MetaLogicalMonitor *); + void (*tiled_monitor_added) (MetaMonitorManager *, + MetaMonitor *); - void (*delete_monitor) (MetaMonitorManager *, - int monitor_winsys_xid); + void (*tiled_monitor_removed) (MetaMonitorManager *, + MetaMonitor *); }; @@ -394,6 +394,11 @@ gboolean meta_monitor_manager_get_monitor_matrix (MetaMonitorManager * MetaOutput *output, gfloat matrix[6]); +void meta_monitor_manager_tiled_monitor_added (MetaMonitorManager *manager, + MetaMonitor *monitor); +void meta_monitor_manager_tiled_monitor_removed (MetaMonitorManager *manager, + MetaMonitor *monitor); + void meta_monitor_manager_clear_output (MetaOutput *output); void meta_monitor_manager_clear_mode (MetaCrtcMode *mode); void meta_monitor_manager_clear_crtc (MetaCrtc *crtc); diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c index 98dd7de76..951cba16d 100644 --- a/src/backends/meta-monitor-manager.c +++ b/src/backends/meta-monitor-manager.c @@ -122,7 +122,6 @@ derive_monitor_position (MetaMonitor *monitor, static void make_logical_config (MetaMonitorManager *manager) { - MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_GET_CLASS (manager); GList *logical_monitors = NULL; GList *l; int monitor_number; @@ -174,18 +173,6 @@ make_logical_config (MetaMonitorManager *manager) meta_monitor_manager_set_primary_logical_monitor (manager, primary_logical_monitor); - - if (manager_class->add_monitor) - { - GList *l; - - for (l = logical_monitors; l; l = l->next) - { - MetaLogicalMonitor *logical_monitor = l->data; - - manager_class->add_monitor (manager, logical_monitor); - } - } } static void @@ -1412,6 +1399,28 @@ rebuild_monitors (MetaMonitorManager *manager) } } +void +meta_monitor_manager_tiled_monitor_added (MetaMonitorManager *manager, + MetaMonitor *monitor) +{ + MetaMonitorManagerClass *manager_class = + META_MONITOR_MANAGER_GET_CLASS (manager); + + if (manager_class->tiled_monitor_added) + manager_class->tiled_monitor_added (manager, monitor); +} + +void +meta_monitor_manager_tiled_monitor_removed (MetaMonitorManager *manager, + MetaMonitor *monitor) +{ + MetaMonitorManagerClass *manager_class = + META_MONITOR_MANAGER_GET_CLASS (manager); + + if (manager_class->tiled_monitor_removed) + manager_class->tiled_monitor_removed (manager, monitor); +} + void meta_monitor_manager_read_current_config (MetaMonitorManager *manager) { @@ -1444,9 +1453,7 @@ void meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager) { MetaBackend *backend = meta_get_backend (); - MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_GET_CLASS (manager); GList *old_logical_monitors; - GList *old_l; if (manager->in_init) return; @@ -1455,36 +1462,6 @@ meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager) make_logical_config (manager); - if (manager_class->delete_monitor) - { - for (old_l = old_logical_monitors; old_l; old_l = old_l->next) - { - MetaLogicalMonitor *old_logical_monitor = old_l->data; - int old_monitor_winsys_xid; - gboolean delete_mon; - GList *new_l; - - delete_mon = TRUE; - old_monitor_winsys_xid = old_logical_monitor->monitor_winsys_xid; - - for (new_l = manager->logical_monitors; new_l; new_l = new_l->next) - { - MetaLogicalMonitor *new_logical_monitor = new_l->data; - int new_monitor_winsys_xid; - - new_monitor_winsys_xid = new_logical_monitor->monitor_winsys_xid; - - if (new_monitor_winsys_xid == old_monitor_winsys_xid) - { - delete_mon = FALSE; - break; - } - } - if (delete_mon) - manager_class->delete_monitor (manager, old_monitor_winsys_xid); - } - } - /* Tell the backend about that the monitors changed before emitting the * signal, so that the backend can prepare itself before all the signal * consumers. diff --git a/src/backends/meta-monitor.c b/src/backends/meta-monitor.c index 177dc7ce0..32c0fcf96 100644 --- a/src/backends/meta-monitor.c +++ b/src/backends/meta-monitor.c @@ -23,6 +23,7 @@ #include "backends/meta-monitor.h" +#include "backends/meta-backend-private.h" #include "backends/meta-monitor-manager-private.h" typedef struct _MetaMonitorPrivate @@ -115,6 +116,15 @@ meta_monitor_get_physical_dimensions (MetaMonitor *monitor, *height_mm = output->height_mm; } +const char * +meta_monitor_get_product (MetaMonitor *monitor) +{ + MetaOutput *output; + + output = meta_monitor_get_main_output (monitor); + return output->product; +} + static void meta_monitor_finalize (GObject *object) { @@ -188,6 +198,12 @@ meta_monitor_normal_class_init (MetaMonitorNormalClass *klass) monitor_class->get_dimensions = meta_monitor_normal_get_dimensions; } +uint32_t +meta_monitor_tiled_get_tile_group_id (MetaMonitorTiled *monitor_tiled) +{ + return monitor_tiled->tile_group_id; +} + static void add_tiled_monitor_outputs (MetaMonitorManager *monitor_manager, MetaMonitorTiled *monitor_tiled) @@ -224,6 +240,9 @@ meta_monitor_tiled_new (MetaMonitorManager *monitor_manager, add_tiled_monitor_outputs (monitor_manager, monitor_tiled); monitor_tiled->main_output = output; + meta_monitor_manager_tiled_monitor_added (monitor_manager, + META_MONITOR (monitor_tiled)); + return monitor_tiled; } @@ -263,6 +282,18 @@ meta_monitor_tiled_get_dimensions (MetaMonitor *monitor, *out_height = height; } +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)); +} + static void meta_monitor_tiled_init (MetaMonitorTiled *monitor) { @@ -271,8 +302,11 @@ meta_monitor_tiled_init (MetaMonitorTiled *monitor) static void meta_monitor_tiled_class_init (MetaMonitorTiledClass *klass) { + GObjectClass *object_class = G_OBJECT_CLASS (klass); MetaMonitorClass *monitor_class = META_MONITOR_CLASS (klass); + object_class->finalize = meta_monitor_tiled_finalize; + monitor_class->get_main_output = meta_monitor_tiled_get_main_output; monitor_class->get_dimensions = meta_monitor_tiled_get_dimensions; } diff --git a/src/backends/meta-monitor.h b/src/backends/meta-monitor.h index d19c75edb..50d51050b 100644 --- a/src/backends/meta-monitor.h +++ b/src/backends/meta-monitor.h @@ -70,4 +70,8 @@ void meta_monitor_get_physical_dimensions (MetaMonitor *monitor, int *width_mm, int *height_mm); +const char * meta_monitor_get_product (MetaMonitor *monitor); + +uint32_t meta_monitor_tiled_get_tile_group_id (MetaMonitorTiled *monitor_tiled); + #endif /* META_MONITOR_H */ diff --git a/src/backends/x11/meta-monitor-manager-xrandr.c b/src/backends/x11/meta-monitor-manager-xrandr.c index ec4ccd5fa..d77661a33 100644 --- a/src/backends/x11/meta-monitor-manager-xrandr.c +++ b/src/backends/x11/meta-monitor-manager-xrandr.c @@ -60,6 +60,10 @@ struct _MetaMonitorManagerXrandr int rr_event_base; int rr_error_base; gboolean has_randr15; + +#ifdef HAVE_XRANDR15 + GHashTable *tiled_monitor_atoms; +#endif /* HAVE_XRANDR15 */ }; struct _MetaMonitorManagerXrandrClass @@ -69,6 +73,15 @@ struct _MetaMonitorManagerXrandrClass G_DEFINE_TYPE (MetaMonitorManagerXrandr, meta_monitor_manager_xrandr, META_TYPE_MONITOR_MANAGER); +#ifdef HAVE_XRANDR15 +typedef struct _MetaMonitorXrandrData +{ + Atom xrandr_name; +} MetaMonitorXrandrData; + +GQuark quark_meta_monitor_xrandr_data; +#endif /* HAVE_RANDR15 */ + static MetaMonitorTransform meta_monitor_transform_from_xrandr (Rotation rotation) { @@ -1332,61 +1345,138 @@ meta_monitor_manager_xrandr_set_crtc_gamma (MetaMonitorManager *manager, } #ifdef HAVE_XRANDR15 -static void -meta_monitor_manager_xrandr_add_monitor (MetaMonitorManager *manager, - MetaLogicalMonitor *logical_monitor) +static MetaMonitorXrandrData * +meta_monitor_xrandr_data_from_monitor (MetaMonitor *monitor) { - MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager); - XRRMonitorInfo *m; - int o; - Atom name; - char name_buf[40]; + MetaMonitorXrandrData *monitor_xrandr_data; - if (manager_xrandr->has_randr15 == FALSE) - return; + monitor_xrandr_data = g_object_get_qdata (G_OBJECT (monitor), + quark_meta_monitor_xrandr_data); + if (monitor_xrandr_data) + return monitor_xrandr_data; - if (logical_monitor->n_outputs <= 1) - return; + monitor_xrandr_data = g_new0 (MetaMonitorXrandrData, 1); + g_object_set_qdata_full (G_OBJECT (monitor), + quark_meta_monitor_xrandr_data, + monitor_xrandr_data, + g_free); - if (logical_monitor->outputs[0]->product) - snprintf (name_buf, 40, "%s-%d", - logical_monitor->outputs[0]->product, - logical_monitor->outputs[0]->tile_info.group_id); - else - snprintf (name_buf, 40, "Tiled-%d", - logical_monitor->outputs[0]->tile_info.group_id); - - name = XInternAtom (manager_xrandr->xdisplay, name_buf, False); - logical_monitor->monitor_winsys_xid = name; - m = XRRAllocateMonitor (manager_xrandr->xdisplay, - logical_monitor->n_outputs); - if (!m) - return; - m->name = name; - m->primary = logical_monitor->is_primary; - m->automatic = True; - - for (o = 0; o < logical_monitor->n_outputs; o++) { - MetaOutput *output = logical_monitor->outputs[o]; - m->outputs[o] = output->winsys_id; - } - XRRSetMonitor (manager_xrandr->xdisplay, - DefaultRootWindow (manager_xrandr->xdisplay), - m); - XRRFreeMonitors (m); + return monitor_xrandr_data; } static void -meta_monitor_manager_xrandr_delete_monitor (MetaMonitorManager *manager, - int monitor_winsys_xid) +meta_monitor_manager_xrandr_increase_monitor_count (MetaMonitorManagerXrandr *manager_xrandr, + Atom name_atom) +{ + int count; + + count = + GPOINTER_TO_INT (g_hash_table_lookup (manager_xrandr->tiled_monitor_atoms, + GSIZE_TO_POINTER (name_atom))); + + count++; + g_hash_table_insert (manager_xrandr->tiled_monitor_atoms, + GSIZE_TO_POINTER (name_atom), + GINT_TO_POINTER (count)); +} + +static int +meta_monitor_manager_xrandr_decrease_monitor_count (MetaMonitorManagerXrandr *manager_xrandr, + Atom name_atom) +{ + int count; + + count = + GPOINTER_TO_SIZE (g_hash_table_lookup (manager_xrandr->tiled_monitor_atoms, + GSIZE_TO_POINTER (name_atom))); + g_assert (count > 0); + + count--; + g_hash_table_insert (manager_xrandr->tiled_monitor_atoms, + GSIZE_TO_POINTER (name_atom), + GINT_TO_POINTER (count)); + + return count; +} + +static void +meta_monitor_manager_xrandr_tiled_monitor_added (MetaMonitorManager *manager, + MetaMonitor *monitor) { MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager); + MetaMonitorTiled *monitor_tiled = META_MONITOR_TILED (monitor); + const char *product; + char *name; + uint32_t tile_group_id; + MetaMonitorXrandrData *monitor_xrandr_data; + Atom name_atom; + XRRMonitorInfo *xrandr_monitor_info; + GList *outputs; + GList *l; + int i; if (manager_xrandr->has_randr15 == FALSE) return; - XRRDeleteMonitor (manager_xrandr->xdisplay, - DefaultRootWindow (manager_xrandr->xdisplay), - monitor_winsys_xid); + + product = meta_monitor_get_product (monitor); + tile_group_id = meta_monitor_tiled_get_tile_group_id (monitor_tiled); + + if (product) + name = g_strdup_printf ("%s-%d", product, tile_group_id); + else + name = g_strdup_printf ("Tiled-%d", tile_group_id); + + name_atom = XInternAtom (manager_xrandr->xdisplay, name, False); + g_free (name); + + monitor_xrandr_data = meta_monitor_xrandr_data_from_monitor (monitor); + monitor_xrandr_data->xrandr_name = name_atom; + + meta_monitor_manager_xrandr_increase_monitor_count (manager_xrandr, + name_atom); + + outputs = meta_monitor_get_outputs (monitor); + xrandr_monitor_info = XRRAllocateMonitor (manager_xrandr->xdisplay, + g_list_length (outputs)); + xrandr_monitor_info->name = name_atom; + xrandr_monitor_info->primary = meta_monitor_is_primary (monitor); + xrandr_monitor_info->automatic = True; + for (l = outputs, i = 0; l; l = l->next, i++) + { + MetaOutput *output = l->data; + + xrandr_monitor_info->outputs[i] = output->winsys_id; + } + + XRRSetMonitor (manager_xrandr->xdisplay, + DefaultRootWindow (manager_xrandr->xdisplay), + xrandr_monitor_info); + XRRFreeMonitors (xrandr_monitor_info); +} + +static void +meta_monitor_manager_xrandr_tiled_monitor_removed (MetaMonitorManager *manager, + MetaMonitor *monitor) +{ + MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager); + MetaMonitorXrandrData *monitor_xrandr_data; + Atom monitor_name; + + int monitor_count; + + if (manager_xrandr->has_randr15 == FALSE) + return; + + monitor_xrandr_data = meta_monitor_xrandr_data_from_monitor (monitor); + monitor_name = monitor_xrandr_data->xrandr_name; + monitor_count = + meta_monitor_manager_xrandr_decrease_monitor_count (manager_xrandr, + monitor_name); + + if (monitor_count == 0) + XRRDeleteMonitor (manager_xrandr->xdisplay, + DefaultRootWindow (manager_xrandr->xdisplay), + monitor_name); } static void @@ -1448,7 +1538,10 @@ meta_monitor_manager_xrandr_init (MetaMonitorManagerXrandr *manager_xrandr) if (major_version > 1 || (major_version == 1 && minor_version >= 5)) - manager_xrandr->has_randr15 = TRUE; + { + manager_xrandr->has_randr15 = TRUE; + manager_xrandr->tiled_monitor_atoms = g_hash_table_new (NULL, NULL); + } meta_monitor_manager_xrandr_init_monitors (manager_xrandr); #endif } @@ -1463,6 +1556,8 @@ meta_monitor_manager_xrandr_finalize (GObject *object) XRRFreeScreenResources (manager_xrandr->resources); manager_xrandr->resources = NULL; + g_hash_table_destroy (manager_xrandr->tiled_monitor_atoms); + G_OBJECT_CLASS (meta_monitor_manager_xrandr_parent_class)->finalize (object); } @@ -1482,9 +1577,12 @@ meta_monitor_manager_xrandr_class_init (MetaMonitorManagerXrandrClass *klass) 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; + manager_class->tiled_monitor_added = meta_monitor_manager_xrandr_tiled_monitor_added; + manager_class->tiled_monitor_removed = meta_monitor_manager_xrandr_tiled_monitor_removed; #endif + + quark_meta_monitor_xrandr_data = + g_quark_from_static_string ("-meta-monitor-xrandr-data"); } gboolean