summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlberts Muktupāvels <alberts.muktupavels@gmail.com>2020-01-30 16:48:28 +0200
committerAlberts Muktupāvels <alberts.muktupavels@gmail.com>2020-01-30 16:48:28 +0200
commit922de13cbd51b38110cf3571131aef6ca6fa6a3a (patch)
treefd7aa30d7cbc43104cae4e673c4aee7863c97db0
parent3d8b03dc68774e35d80bdb6eebba2cce75551933 (diff)
downloadmetacity-922de13cbd51b38110cf3571131aef6ca6fa6a3a.tar.gz
window: add support for _GNOME_WM_STRUT_AREA
In addition to existing properties use also new _GNOME_WM_STRUT_AREA property that allows creating struts between monitors. https://mail.gnome.org/archives/wm-spec-list/2018-December/msg00000.html https://gitlab.freedesktop.org/xdg/xdg-specs/merge_requests/22
-rw-r--r--src/core/atomnames.h1
-rw-r--r--src/core/boxes.c21
-rw-r--r--src/core/testboxes.c6
-rw-r--r--src/core/window-props.c6
-rw-r--r--src/core/window.c88
-rw-r--r--src/core/workspace.c6
-rw-r--r--src/include/boxes.h18
7 files changed, 133 insertions, 13 deletions
diff --git a/src/core/atomnames.h b/src/core/atomnames.h
index 8e2b4593..aacd2285 100644
--- a/src/core/atomnames.h
+++ b/src/core/atomnames.h
@@ -64,6 +64,7 @@ item(_GTK_WORKAREAS)
item(_GNOME_PANEL_ACTION)
item(_GNOME_PANEL_ACTION_MAIN_MENU)
item(_GNOME_PANEL_ACTION_RUN_DIALOG)
+item(_GNOME_WM_STRUT_AREA)
item(_METACITY_TIMESTAMP_PING)
item(_METACITY_FOCUS_SET)
item(_METACITY_SENTINEL)
diff --git a/src/core/boxes.c b/src/core/boxes.c
index 1c2905e8..d77b6baf 100644
--- a/src/core/boxes.c
+++ b/src/core/boxes.c
@@ -518,7 +518,8 @@ compare_rect_areas (gconstpointer a, gconstpointer b)
GList*
meta_rectangle_get_minimal_spanning_set_for_region (
const MetaRectangle *basic_rect,
- const GSList *all_struts)
+ const GSList *all_struts,
+ gboolean skip_middle_struts)
{
/* NOTE FOR OPTIMIZERS: This function *might* be somewhat slow,
* especially due to the call to merge_spanning_rects_in_region() (which
@@ -580,7 +581,23 @@ meta_rectangle_get_minimal_spanning_set_for_region (
for (strut_iter = all_struts; strut_iter; strut_iter = strut_iter->next)
{
GList *rect_iter;
- MetaRectangle *strut_rect = &((MetaStrut*)strut_iter->data)->rect;
+ MetaStrut *strut = (MetaStrut *) strut_iter->data;
+ MetaRectangle *strut_rect = &strut->rect;
+
+ if (skip_middle_struts && strut->edge == META_EDGE_MONITOR)
+ {
+ if ((strut->side == META_SIDE_LEFT &&
+ strut_rect->x != basic_rect->x) ||
+ (strut->side == META_SIDE_RIGHT &&
+ strut_rect->x + strut_rect->width != basic_rect->width) ||
+ (strut->side == META_SIDE_TOP &&
+ strut_rect->y != basic_rect->y) ||
+ (strut->side == META_SIDE_BOTTOM &&
+ strut_rect->y + strut_rect->height != basic_rect->height))
+ {
+ continue;
+ }
+ }
tmp_list = ret;
ret = NULL;
diff --git a/src/core/testboxes.c b/src/core/testboxes.c
index f1ae214e..f4cd3a50 100644
--- a/src/core/testboxes.c
+++ b/src/core/testboxes.c
@@ -63,6 +63,7 @@ new_meta_strut (int x, int y, int width, int height, int side)
temporary = g_new (MetaStrut, 1);
temporary->rect = meta_rect(x, y, width, height);
temporary->side = side;
+ temporary->edge = META_EDGE_SCREEN;
return temporary;
}
@@ -297,7 +298,10 @@ get_screen_region (int which)
ret = NULL;
struts = get_strut_list (which);
- ret = meta_rectangle_get_minimal_spanning_set_for_region (&basic_rect, struts);
+ ret = meta_rectangle_get_minimal_spanning_set_for_region (&basic_rect,
+ struts,
+ FALSE);
+
free_strut_list (struts);
return ret;
diff --git a/src/core/window-props.c b/src/core/window-props.c
index ef877f24..466c06f0 100644
--- a/src/core/window-props.c
+++ b/src/core/window-props.c
@@ -1968,6 +1968,12 @@ meta_display_init_window_prop_hooks (MetaDisplay *display)
NONE
},
{
+ display->atom__GNOME_WM_STRUT_AREA,
+ META_PROP_VALUE_INVALID,
+ reload_struts,
+ NONE
+ },
+ {
display->atom__NET_WM_WINDOW_OPACITY,
META_PROP_VALUE_CARDINAL,
reload_window_opacity,
diff --git a/src/core/window.c b/src/core/window.c
index 3539c316..c2d294ac 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -6386,6 +6386,91 @@ meta_window_update_struts (MetaWindow *window)
if (meta_prop_get_cardinal_list (window->display,
window->xwindow,
+ window->display->atom__GNOME_WM_STRUT_AREA,
+ &struts, &nitems))
+ {
+ if (nitems != 4)
+ {
+ meta_verbose ("_GNOME_WM_STRUT_AREA on %s has %d values instead of 4\n",
+ window->desc, nitems);
+ }
+ else
+ {
+ MetaStrut *temp;
+ MetaSide side;
+ gboolean valid;
+ int i;
+
+ temp = g_new (MetaStrut, 1);
+
+ temp->rect.x = struts[0];
+ temp->rect.y = struts[1];
+ temp->rect.width = struts[2];
+ temp->rect.height = struts[3];
+
+ side = META_SIDE_LEFT;
+ valid = FALSE;
+
+ for (i = 0; i < window->screen->n_monitor_infos; i++)
+ {
+ MetaRectangle monitor;
+
+ monitor = window->screen->monitor_infos[i].rect;
+ if (!meta_rectangle_contains_rect (&monitor, &temp->rect))
+ continue;
+
+ if (temp->rect.height > temp->rect.width)
+ {
+ if (temp->rect.x == monitor.x)
+ {
+ side = META_SIDE_LEFT;
+ valid = TRUE;
+ }
+ else if (temp->rect.x + temp->rect.width == monitor.x + monitor.width)
+ {
+ side = META_SIDE_RIGHT;
+ valid = TRUE;
+ }
+ }
+ else
+ {
+ if (temp->rect.y == monitor.y)
+ {
+ side = META_SIDE_TOP;
+ valid = TRUE;
+ }
+ else if (temp->rect.y + temp->rect.height == monitor.y + monitor.height)
+ {
+ side = META_SIDE_BOTTOM;
+ valid = TRUE;
+ }
+ }
+ }
+
+ if (valid)
+ {
+ temp->side = side;
+ temp->edge = META_EDGE_MONITOR;
+
+ new_struts = g_slist_prepend (new_struts, temp);
+ }
+ else
+ {
+ g_free (temp);
+ }
+ }
+
+ meta_XFree (struts);
+ }
+ else
+ {
+ meta_verbose ("No _GNOME_WM_STRUT_AREA property for %s\n",
+ window->desc);
+ }
+
+ if (!new_struts &&
+ meta_prop_get_cardinal_list (window->display,
+ window->xwindow,
window->display->atom__NET_WM_STRUT_PARTIAL,
&struts, &nitems))
{
@@ -6410,6 +6495,7 @@ meta_window_update_struts (MetaWindow *window)
temp = g_new (MetaStrut, 1);
temp->side = 1 << i; /* See MetaSide def. Matches nicely, eh? */
+ temp->edge = META_EDGE_SCREEN;
temp->rect = window->screen->rect;
switch (temp->side)
{
@@ -6479,6 +6565,7 @@ meta_window_update_struts (MetaWindow *window)
temp = g_new (MetaStrut, 1);
temp->side = 1 << i;
+ temp->edge = META_EDGE_SCREEN;
temp->rect = window->screen->rect;
switch (temp->side)
{
@@ -6524,6 +6611,7 @@ meta_window_update_struts (MetaWindow *window)
MetaStrut *new_strut = (MetaStrut*) new_iter->data;
if (old_strut->side != new_strut->side ||
+ old_strut->edge != new_strut->edge ||
!meta_rectangle_equal (&old_strut->rect, &new_strut->rect))
break;
diff --git a/src/core/workspace.c b/src/core/workspace.c
index da714063..19e3a9a8 100644
--- a/src/core/workspace.c
+++ b/src/core/workspace.c
@@ -646,12 +646,14 @@ ensure_work_areas_validated (MetaWorkspace *workspace)
workspace->monitor_region[i] =
meta_rectangle_get_minimal_spanning_set_for_region (
&workspace->screen->monitor_infos[i].rect,
- workspace->all_struts);
+ workspace->all_struts,
+ FALSE);
}
workspace->screen_region =
meta_rectangle_get_minimal_spanning_set_for_region (
&workspace->screen->rect,
- workspace->all_struts);
+ workspace->all_struts,
+ TRUE);
/* STEP 3: Get the work areas (region-to-maximize-to) for the screen and
* monitors.
diff --git a/src/include/boxes.h b/src/include/boxes.h
index 4b881753..387a1756 100644
--- a/src/include/boxes.h
+++ b/src/include/boxes.h
@@ -25,6 +25,13 @@
#include <glib.h>
#include "common.h"
+typedef enum
+{
+ META_EDGE_WINDOW,
+ META_EDGE_MONITOR,
+ META_EDGE_SCREEN
+} MetaEdgeType;
+
typedef struct _MetaRectangle MetaRectangle;
struct _MetaRectangle
{
@@ -39,6 +46,7 @@ struct _MetaStrut
{
MetaRectangle rect;
MetaSide side;
+ MetaEdgeType edge;
};
#define BOX_LEFT(box) ((box).x) /* Leftmost pixel of rect */
@@ -53,13 +61,6 @@ typedef enum
FIXED_DIRECTION_Y = 1 << 1,
} FixedDirections;
-typedef enum
-{
- META_EDGE_WINDOW,
- META_EDGE_MONITOR,
- META_EDGE_SCREEN
-} MetaEdgeType;
-
typedef struct _MetaEdge MetaEdge;
struct _MetaEdge
{
@@ -156,7 +157,8 @@ void meta_rectangle_resize_with_gravity (const MetaRectangle *old_rect,
*/
GList* meta_rectangle_get_minimal_spanning_set_for_region (
const MetaRectangle *basic_rect,
- const GSList *all_struts);
+ const GSList *all_struts,
+ gboolean skip_middle_struts);
/* Expand all rectangles in region by the given amount on each side */
GList* meta_rectangle_expand_region (GList *region,