From 3ed0ddb242a4804cd7fcfcfcf39a47766eaa816d Mon Sep 17 00:00:00 2001 From: raveit65 Date: Sat, 10 Apr 2021 16:37:40 +0200 Subject: 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 origin commit: https://gitlab.gnome.org/GNOME/metacity/commit/922de13 --- src/core/atomnames.h | 1 + src/core/boxes.c | 22 +++++++++++-- src/core/testboxes.c | 6 +++- src/core/window-props.c | 1 + src/core/window.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++ src/core/workspace.c | 6 ++-- src/include/boxes.h | 18 +++++----- 7 files changed, 129 insertions(+), 13 deletions(-) diff --git a/src/core/atomnames.h b/src/core/atomnames.h index 059594d3..cea869d0 100644 --- a/src/core/atomnames.h +++ b/src/core/atomnames.h @@ -65,6 +65,7 @@ item(_GTK_WORKAREAS) item(_MATE_PANEL_ACTION) item(_MATE_PANEL_ACTION_MAIN_MENU) item(_MATE_PANEL_ACTION_RUN_DIALOG) +item(_GNOME_WM_STRUT_AREA) item(_MARCO_SENTINEL) item(_MARCO_VERSION) item(WM_CLIENT_MACHINE) diff --git a/src/core/boxes.c b/src/core/boxes.c index 49c82ccc..a9006ede 100644 --- a/src/core/boxes.c +++ b/src/core/boxes.c @@ -522,7 +522,9 @@ 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 @@ -583,7 +585,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_XINERAMA) + { + 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 fecca881..ecf35f2f 100644 --- a/src/core/testboxes.c +++ b/src/core/testboxes.c @@ -66,6 +66,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; } @@ -294,7 +295,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 2004c6a0..fb8ac4c1 100644 --- a/src/core/window-props.c +++ b/src/core/window-props.c @@ -1593,6 +1593,7 @@ meta_display_init_window_prop_hooks (MetaDisplay *display) { display->atom__NET_WM_DESKTOP, META_PROP_VALUE_CARDINAL, reload_net_wm_desktop }, { display->atom__NET_WM_STRUT, META_PROP_VALUE_INVALID, reload_struts }, { display->atom__NET_WM_STRUT_PARTIAL, META_PROP_VALUE_INVALID, reload_struts }, + { display->atom__GNOME_WM_STRUT_AREA, META_PROP_VALUE_INVALID, reload_struts }, { display->atom__NET_STARTUP_ID, META_PROP_VALUE_UTF8, reload_net_startup_id }, { display->atom__NET_WM_SYNC_REQUEST_COUNTER, META_PROP_VALUE_SYNC_COUNTER, reload_update_counter }, { XA_WM_NORMAL_HINTS, META_PROP_VALUE_SIZE_HINTS, reload_normal_hints }, diff --git a/src/core/window.c b/src/core/window.c index add00789..55badf54 100644 --- a/src/core/window.c +++ b/src/core/window.c @@ -6239,6 +6239,91 @@ meta_window_update_struts (MetaWindow *window) new_struts = NULL; 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_xinerama_infos; i++) + { + MetaRectangle monitor; + + monitor = window->screen->xinerama_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_XINERAMA; + + 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)) @@ -6264,6 +6349,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) { @@ -6327,6 +6413,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) { @@ -6370,6 +6457,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 620184f9..ce6080ba 100644 --- a/src/core/workspace.c +++ b/src/core/workspace.c @@ -635,12 +635,14 @@ ensure_work_areas_validated (MetaWorkspace *workspace) workspace->xinerama_region[i] = meta_rectangle_get_minimal_spanning_set_for_region ( &workspace->screen->xinerama_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 * xineramas. diff --git a/src/include/boxes.h b/src/include/boxes.h index 87cc68f2..fabacb1e 100644 --- a/src/include/boxes.h +++ b/src/include/boxes.h @@ -27,6 +27,13 @@ #include #include "common.h" +typedef enum +{ + META_EDGE_WINDOW, + META_EDGE_XINERAMA, + META_EDGE_SCREEN +} MetaEdgeType; + typedef struct _MetaRectangle MetaRectangle; struct _MetaRectangle { @@ -41,6 +48,7 @@ struct _MetaStrut { MetaRectangle rect; MetaSide side; + MetaEdgeType edge; }; #define BOX_LEFT(box) ((box).x) /* Leftmost pixel of rect */ @@ -55,13 +63,6 @@ typedef enum FIXED_DIRECTION_Y = 1 << 1, } FixedDirections; -typedef enum -{ - META_EDGE_WINDOW, - META_EDGE_XINERAMA, - META_EDGE_SCREEN -} MetaEdgeType; - typedef struct _MetaEdge MetaEdge; struct _MetaEdge { @@ -158,7 +159,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, -- cgit v1.2.1