From bb62d9e4b0fb1e2ec576743f78080d4ece0f4bc4 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Thu, 16 Jul 2020 13:52:39 +0200 Subject: [PATCH] backends: Add simple object to delegate logical monitor layout queries This object can be passed to random places, and be trusted to remain unchanged till replaced. Makes it an ideal replacement for MetaMonitorManager across threads. https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1403 --- src/backends/meta-monitor-manager-private.h | 3 + src/backends/meta-monitor-manager.c | 34 ++++ src/backends/meta-viewport-info.c | 189 ++++++++++++++++++++ src/backends/meta-viewport-info.h | 53 ++++++ src/meson.build | 2 + 5 files changed, 281 insertions(+) create mode 100644 src/backends/meta-viewport-info.c create mode 100644 src/backends/meta-viewport-info.h diff --git a/src/backends/meta-monitor-manager-private.h b/src/backends/meta-monitor-manager-private.h index 1b7efd261..3ba8bcfc9 100644 --- a/src/backends/meta-monitor-manager-private.h +++ b/src/backends/meta-monitor-manager-private.h @@ -31,6 +31,7 @@ #include "backends/meta-cursor.h" #include "backends/meta-display-config-shared.h" #include "backends/meta-monitor-transform.h" +#include "backends/meta-viewport-info.h" #include "core/util-private.h" #include "meta/display.h" #include "meta/meta-monitor-manager.h" @@ -405,4 +406,6 @@ meta_find_output_assignment (MetaOutputAssignment **outputs, return NULL; } +MetaViewportInfo * meta_monitor_manager_get_viewports (MetaMonitorManager *manager); + #endif /* META_MONITOR_MANAGER_PRIVATE_H */ diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c index a519442f3..b9879abdf 100644 --- a/src/backends/meta-monitor-manager.c +++ b/src/backends/meta-monitor-manager.c @@ -3175,3 +3175,37 @@ meta_monitor_manager_get_vendor_name (MetaMonitorManager *manager, return gnome_pnp_ids_get_pnp_id (manager->pnp_ids, vendor); } + +MetaViewportInfo * +meta_monitor_manager_get_viewports (MetaMonitorManager *manager) +{ + MetaViewportInfo *info; + GArray *views, *scales; + GList *logical_monitors, *l; + + views = g_array_new (FALSE, FALSE, sizeof (cairo_rectangle_int_t)); + scales = g_array_new (FALSE, FALSE, sizeof (float)); + + logical_monitors = meta_monitor_manager_get_logical_monitors (manager); + + for (l = logical_monitors; l; l = l->next) + { + MetaLogicalMonitor *logical_monitor = l->data; + cairo_rectangle_int_t rect; + float scale; + + rect = logical_monitor->rect; + g_array_append_val (views, rect); + + scale = logical_monitor->scale; + g_array_append_val (scales, scale); + } + + info = meta_viewport_info_new ((cairo_rectangle_int_t *) views->data, + (float *) scales->data, + views->len); + g_array_unref (views); + g_array_unref (scales); + + return info; +} diff --git a/src/backends/meta-viewport-info.c b/src/backends/meta-viewport-info.c new file mode 100644 index 000000000..0e50dcbfe --- /dev/null +++ b/src/backends/meta-viewport-info.c @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2020 Red Hat + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Written by: + * Carlos Garnacho + */ + +#include "config.h" + +#include "meta-viewport-info.h" +#include "core/main-private.h" +#include "core/boxes-private.h" + +typedef struct _ViewInfo ViewInfo; + +struct _ViewInfo +{ + cairo_rectangle_int_t rect; + float scale; +}; + +struct _MetaViewportInfo +{ + GObject parent_class; + GArray *views; +}; + +G_DEFINE_TYPE (MetaViewportInfo, meta_viewport_info, G_TYPE_OBJECT) + +static void +meta_viewport_info_finalize (GObject *object) +{ + MetaViewportInfo *info = META_VIEWPORT_INFO (object); + + g_array_unref (info->views); + + G_OBJECT_CLASS (meta_viewport_info_parent_class)->finalize (object); +} + +static void +meta_viewport_info_class_init (MetaViewportInfoClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = meta_viewport_info_finalize; +} + +static void +meta_viewport_info_init (MetaViewportInfo *info) +{ + info->views = g_array_new (FALSE, FALSE, sizeof (ViewInfo)); +} + +MetaViewportInfo * +meta_viewport_info_new (cairo_rectangle_int_t *views, + float *scales, + guint n_views) +{ + MetaViewportInfo *viewport_info; + int i; + + viewport_info = g_object_new (META_TYPE_VIEWPORT_INFO, NULL); + + for (i = 0; i < n_views; i++) + { + ViewInfo info; + + info.rect = views[i]; + info.scale = scales[i]; + g_array_append_val (viewport_info->views, info); + } + + return viewport_info; +} + +int +meta_viewport_info_get_view_at (MetaViewportInfo *viewport_info, + float x, + float y) +{ + int i; + + for (i = 0; i < viewport_info->views->len; i++) + { + ViewInfo *info = &g_array_index (viewport_info->views, ViewInfo, i); + + if (META_POINT_IN_RECT (x, y, info->rect)) + return i; + } + + return -1; +} + +gboolean +meta_viewport_info_get_view (MetaViewportInfo *viewport_info, + int idx, + cairo_rectangle_int_t *rect, + float *scale) +{ + ViewInfo *info; + + if (idx < 0 || idx >= viewport_info->views->len) + return FALSE; + + info = &g_array_index (viewport_info->views, ViewInfo, idx); + if (rect) + *rect = info->rect; + if (scale) + *scale = info->scale; + + return TRUE; +} + +static gboolean +view_has_neighbor (cairo_rectangle_int_t *view, + cairo_rectangle_int_t *neighbor, + MetaDisplayDirection neighbor_direction) +{ + switch (neighbor_direction) + { + case META_DISPLAY_RIGHT: + if (neighbor->x == (view->x + view->width) && + meta_rectangle_vert_overlap (neighbor, view)) + return TRUE; + break; + case META_DISPLAY_LEFT: + if (view->x == (neighbor->x + neighbor->width) && + meta_rectangle_vert_overlap (neighbor, view)) + return TRUE; + break; + case META_DISPLAY_UP: + if (view->y == (neighbor->y + neighbor->height) && + meta_rectangle_horiz_overlap (neighbor, view)) + return TRUE; + break; + case META_DISPLAY_DOWN: + if (neighbor->y == (view->y + view->height) && + meta_rectangle_horiz_overlap (neighbor, view)) + return TRUE; + break; + } + + return FALSE; +} + +int +meta_viewport_info_get_neighbor (MetaViewportInfo *viewport_info, + int idx, + MetaDisplayDirection direction) +{ + cairo_rectangle_int_t rect; + int i; + + if (!meta_viewport_info_get_view (viewport_info, idx, &rect, NULL)) + return -1; + + for (i = 0; i < viewport_info->views->len; i++) + { + ViewInfo *info = &g_array_index (viewport_info->views, ViewInfo, i); + + if (idx == i) + continue; + if (view_has_neighbor (&rect, &info->rect, direction)) + return i; + } + + return -1; +} + +int +meta_viewport_info_get_num_views (MetaViewportInfo *info) +{ + return info->views->len; +} diff --git a/src/backends/meta-viewport-info.h b/src/backends/meta-viewport-info.h new file mode 100644 index 000000000..c9a881869 --- /dev/null +++ b/src/backends/meta-viewport-info.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2020 Red Hat + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Written by: + * Carlos Garnacho + */ + +#ifndef META_VIEWPORT_INFO_H +#define META_VIEWPORT_INFO_H + +#include +#include + +#include "meta/display.h" + +#define META_TYPE_VIEWPORT_INFO (meta_viewport_info_get_type ()) +G_DECLARE_FINAL_TYPE (MetaViewportInfo, meta_viewport_info, + META, VIEWPORT_INFO, GObject) + +MetaViewportInfo * meta_viewport_info_new (cairo_rectangle_int_t *views, + float *scales, + guint n_views); + +int meta_viewport_info_get_view_at (MetaViewportInfo *info, + float x, + float y); + +gboolean meta_viewport_info_get_view (MetaViewportInfo *viewport_info, + int idx, + cairo_rectangle_int_t *rect, + float *scale); + +int meta_viewport_info_get_neighbor (MetaViewportInfo *info, + int idx, + MetaDisplayDirection direction); +int meta_viewport_info_get_num_views (MetaViewportInfo *info); + +#endif /* META_VIEWPORT_INFO_H */ diff --git a/src/meson.build b/src/meson.build index 9e7f48e17..b24f12d9c 100644 --- a/src/meson.build +++ b/src/meson.build @@ -233,6 +233,8 @@ mutter_sources = [ 'backends/meta-settings-private.h', 'backends/meta-stage.c', 'backends/meta-stage-private.h', + 'backends/meta-viewport-info.c', + 'backends/meta-viewport-info.h', 'backends/x11/cm/meta-backend-x11-cm.c', 'backends/x11/cm/meta-backend-x11-cm.h', 'backends/x11/cm/meta-cursor-sprite-xfixes.c',