From c240ee2176f1dafdf80340a0466d539a96f1109f Mon Sep 17 00:00:00 2001 From: "P. Pronk" Date: Thu, 1 Dec 2016 20:04:24 +0100 Subject: [PATCH] Improved tile support with multiple monitors --- src/client.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----- src/screen.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++- src/screen.h | 11 ++++++++++ 3 files changed, 139 insertions(+), 6 deletions(-) diff --git a/src/client.c b/src/client.c index 668c11b..2bf15b6 100644 --- a/src/client.c +++ b/src/client.c @@ -3453,6 +3453,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); @@ -3485,12 +3486,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 d5c7266..cf64172 100644 --- a/src/screen.c +++ b/src/screen.c @@ -752,6 +752,66 @@ 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_if_fail (screen_info != NULL); + g_return_if_fail (rect != NULL); + g_return_if_fail (GDK_IS_SCREEN (screen_info->gscr)); + TRACE ("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; } /* @@ -787,11 +847,12 @@ myScreenFindMonitorAtPoint (ScreenInfo *screen_info, gint x, gint y, GdkRectangl monitor_index = myScreenGetMonitorIndex (screen_info, i); gdk_screen_get_monitor_geometry (screen_info->gscr, monitor_index, &monitor); - + if ((x >= monitor.x) && (x < (monitor.x + monitor.width)) && (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 2f19057..5fab43d 100644 --- a/src/screen.h +++ b/src/screen.h @@ -127,6 +127,7 @@ struct _ScreenInfo /* Monitor search caching */ GdkRectangle cache_monitor; + gint cache_monitor_index; gint num_monitors; GArray *monitors_index; @@ -230,6 +231,10 @@ 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 *, @@ -269,6 +274,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