From e14765a1ec66c87ad28a95be64fdf7a1ea70cbac Mon Sep 17 00:00:00 2001 From: "P. Pronk" Date: Sat, 4 Nov 2017 17:52:57 +0100 Subject: [PATCH] tiling: Improved tiling with multiple monitors Bug: 11936 Allows to switch back from tiled state using the same keyboard shortcut and improves tiling on multiple monitors. --- src/client.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----- src/screen.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/screen.h | 10 +++++++++ 3 files changed, 138 insertions(+), 5 deletions(-) diff --git a/src/client.c b/src/client.c index 4085e75..26df8ab 100644 --- a/src/client.c +++ b/src/client.c @@ -3451,6 +3451,7 @@ clientTile (Client *c, gint cx, gint cy, tilePositionType tile, gboolean send_co XWindowChanges wc; GdkRectangle rect; unsigned long old_flags; + gboolean restore_window; g_return_val_if_fail (c != NULL, FALSE); @@ -3483,12 +3484,72 @@ clientTile (Client *c, gint cx, gint cy, tilePositionType tile, gboolean send_co c->flags = old_flags; return FALSE; } - FLAG_SET (c->flags, CLIENT_FLAG_RESTORE_SIZE_POS); - c->x = wc.x; - c->y = wc.y; - c->height = wc.height; - c->width = wc.width; + restore_window = FALSE; + + switch (tile) + { + case TILE_UP: + case TILE_DOWN: + if ((c->x == wc.x) && (c->y == wc.y) && + FLAG_TEST (old_flags, CLIENT_FLAG_MAXIMIZED_HORIZ)) + { + if ((tile == TILE_UP) && !FLAG_TEST (old_flags, CLIENT_FLAG_MAXIMIZED_VERT)) + { + return clientToggleMaximized (c, CLIENT_FLAG_MAXIMIZED, TRUE); + } + else if (tile == TILE_DOWN) + { + restore_window = TRUE; + } + } + + if (!restore_window) + { + FLAG_SET (c->flags, CLIENT_FLAG_MAXIMIZED_HORIZ | CLIENT_FLAG_RESTORE_SIZE_POS); + } + break; + case TILE_LEFT: + case TILE_RIGHT: + if ((c->x == wc.x) && (c->y == wc.y) && + FLAG_TEST (old_flags, CLIENT_FLAG_MAXIMIZED_VERT)) + { + if ((tile == TILE_LEFT) && + myScreenFindNeighbourMonitorAtPoint (screen_info, cx, cy, &rect, SCREEN_NEIGHBOUR_LEFT, TRUE)) + { + clientNewTileSize(c, &wc, &rect, TILE_RIGHT); + } + else if ((tile == TILE_RIGHT) && + myScreenFindNeighbourMonitorAtPoint (screen_info, cx, cy, &rect, SCREEN_NEIGHBOUR_RIGHT, TRUE)) + { + clientNewTileSize(c, &wc, &rect, TILE_LEFT); + } + else + { + restore_window = TRUE; + } + } + + if (!restore_window) + { + FLAG_SET (c->flags, CLIENT_FLAG_MAXIMIZED_VERT | CLIENT_FLAG_RESTORE_SIZE_POS); + } + default: + FLAG_SET (c->flags, CLIENT_FLAG_RESTORE_SIZE_POS); + break; + } + + if (restore_window) + { + clientRestoreSizePos (c); + } + else + { + c->x = wc.x; + c->y = wc.y; + c->height = wc.height; + c->width = wc.width; + } if (send_configure) { diff --git a/src/screen.c b/src/screen.c index cfb3884..dd21389 100644 --- a/src/screen.c +++ b/src/screen.c @@ -754,6 +754,67 @@ myScreenInvalidateMonitorCache (ScreenInfo *screen_info) screen_info->cache_monitor.y = -1; screen_info->cache_monitor.width = 0; screen_info->cache_monitor.height = 0; + screen_info->cache_monitor_index = -1; +} + +gboolean +myScreenFindNeighbourMonitorAtPoint(ScreenInfo *screen_info, + gint x, gint y, GdkRectangle *rect, + int direction, gboolean continious) +{ + gint num_monitors, monitor_index, gdk_monitor_index; + GdkRectangle monitor = { G_MAXINT, G_MAXINT, 0, 0 }; + + g_return_val_if_fail (screen_info != NULL, FALSE); + g_return_val_if_fail (rect != NULL, FALSE); + g_return_val_if_fail (GDK_IS_SCREEN (screen_info->gscr), FALSE); + DBG ("entering myScreenFindNeighbourMonitorAtPoint"); + + num_monitors = myScreenGetNumMonitors (screen_info); + myScreenFindMonitorAtPoint (screen_info, x, y, &monitor); + + if (screen_info->cache_monitor_index > -1) + { + if (direction == SCREEN_NEIGHBOUR_LEFT) + { + monitor_index = screen_info->cache_monitor_index - 1; + } + else if (direction == SCREEN_NEIGHBOUR_RIGHT) + { + monitor_index = screen_info->cache_monitor_index + 1; + } + + if (monitor_index < 0) + { + if (continious) + { + monitor_index = num_monitors - 1; + } + else + { + return FALSE; + } + } + else if (monitor_index > (num_monitors - 1)) + { + if (continious) + { + monitor_index = 0; + } + else + { + return FALSE; + } + } + + gdk_monitor_index = myScreenGetMonitorIndex (screen_info, monitor_index); + gdk_screen_get_monitor_geometry (screen_info->gscr, gdk_monitor_index, &monitor); + *rect = monitor; + + return TRUE; + } + + return FALSE; } /* @@ -794,6 +855,7 @@ myScreenFindMonitorAtPoint (ScreenInfo *screen_info, gint x, gint y, GdkRectangl (y >= monitor.y) && (y < (monitor.y + monitor.height))) { screen_info->cache_monitor = monitor; + screen_info->cache_monitor_index = monitor_index; *rect = screen_info->cache_monitor; return; } diff --git a/src/screen.h b/src/screen.h index e29f4e9..8e32146 100644 --- a/src/screen.h +++ b/src/screen.h @@ -129,6 +129,7 @@ struct _ScreenInfo GdkRectangle cache_monitor; gint num_monitors; GArray *monitors_index; + gint cache_monitor_index; /* Workspace definitions */ guint workspace_count; @@ -227,6 +228,9 @@ struct _ScreenInfo #endif /* HAVE_COMPOSITOR */ }; +#define SCREEN_NEIGHBOUR_LEFT (1L<<0) +#define SCREEN_NEIGHBOUR_RIGHT (1L<<1) + gboolean myScreenCheckWMAtom (ScreenInfo *, Atom atom); ScreenInfo *myScreenInit (DisplayInfo *, @@ -266,6 +270,12 @@ gint myScreenGetMonitorIndex (ScreenInfo *, gint); gboolean myScreenRebuildMonitorIndex (ScreenInfo *); void myScreenInvalidateMonitorCache (ScreenInfo *); +gboolean myScreenFindNeighbourMonitorAtPoint (ScreenInfo *, + gint, + gint, + GdkRectangle *, + gint, + gboolean); void myScreenFindMonitorAtPoint (ScreenInfo *, gint, gint, -- 2.7.4