diff options
author | Alberts Muktupāvels <alberts.muktupavels@gmail.com> | 2020-01-30 16:48:28 +0200 |
---|---|---|
committer | Alberts Muktupāvels <alberts.muktupavels@gmail.com> | 2020-01-30 16:48:28 +0200 |
commit | 922de13cbd51b38110cf3571131aef6ca6fa6a3a (patch) | |
tree | fd7aa30d7cbc43104cae4e673c4aee7863c97db0 | |
parent | 3d8b03dc68774e35d80bdb6eebba2cce75551933 (diff) | |
download | metacity-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.h | 1 | ||||
-rw-r--r-- | src/core/boxes.c | 21 | ||||
-rw-r--r-- | src/core/testboxes.c | 6 | ||||
-rw-r--r-- | src/core/window-props.c | 6 | ||||
-rw-r--r-- | src/core/window.c | 88 | ||||
-rw-r--r-- | src/core/workspace.c | 6 | ||||
-rw-r--r-- | src/include/boxes.h | 18 |
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, |