mirror of
https://github.com/gryf/wmaker.git
synced 2025-12-18 20:10:29 +01:00
support moving window between heads using keyboard
Window Maker allows to perform practically all operations with windows using only keyboard. One of the actions so far which required using mouse was dragging window from one head (monitor) to another. This patch introduces support for keyboard shortcuts. These shortcuts move windows in circular fashion (if you have 3 and more monitors). In case of 2 or 3 monitors arranged horizontally - window will just move right/left. In case of 3x3 setup - it is impossible to move window to central monitor with keyboard. - preserves window position and size (if display sizes are same) - otherwise tries to fit window to smaller display
This commit is contained in:
committed by
Carlos R. Mafra
parent
d13b78bdde
commit
8b919b0d33
@@ -148,6 +148,10 @@ static const struct {
|
||||
{ "WindowShortcut9Key", N_("Shortcut for window 9") },
|
||||
{ "WindowShortcut10Key", N_("Shortcut for window 10") },
|
||||
|
||||
/* Head Selection */
|
||||
{ "MoveTo12to6Head", N_("Move to right/bottom/left/top head") },
|
||||
{ "MoveTo6to12Head", N_("Move to left/top/right/bottom head") },
|
||||
|
||||
/* Misc. */
|
||||
{ "WindowRelaunchKey", N_("Launch new instance of application") },
|
||||
{ "ScreenSwitchKey", N_("Switch to Next Screen/Monitor") },
|
||||
|
||||
@@ -669,6 +669,91 @@ void handleMaximize(WWindow *wwin, int directions)
|
||||
}
|
||||
}
|
||||
|
||||
/* Moving window between heads
|
||||
*
|
||||
* Window is moved between all avaiable heads for current screen in
|
||||
* requested direction.
|
||||
*
|
||||
* If heads have different sizes, window position will be adjusted to be inside
|
||||
* screen. Window will be unmaximized on move, so that it can be immediately be
|
||||
* maximixed by another shortcut.
|
||||
*
|
||||
*
|
||||
* direction = 0 means move clock-wise from 12h position to 6h
|
||||
* (first try moving right, then bottom, then left, then up)
|
||||
* direction = 1 means move clock-wise from 6h position to 12h
|
||||
* (first try moving left, then up, then right, then bottom)
|
||||
*
|
||||
*
|
||||
* As side effect this mean if you have 9 monitors - you will not be able to
|
||||
* move window into central cell without mouse.
|
||||
*
|
||||
* For common cases with 1 or 2 extra monitors this should work just fine.
|
||||
*
|
||||
* */
|
||||
|
||||
void moveBetweenHeads(WWindow *wwin, int direction)
|
||||
{
|
||||
int head = wGetHeadForWindow(wwin);
|
||||
int destHead = -1;
|
||||
|
||||
unsigned int new_width, new_height;
|
||||
int offsetX, newX = 0;
|
||||
int offsetY, newY = 0;
|
||||
WArea totalArea, oldHeadArea, destHeadArea;
|
||||
WScreen *scr = wwin->screen_ptr;
|
||||
|
||||
int try_movements[2][4] = {
|
||||
{DIRECTION_RIGHT, DIRECTION_DOWN, DIRECTION_LEFT, DIRECTION_UP},
|
||||
{DIRECTION_LEFT, DIRECTION_UP, DIRECTION_RIGHT, DIRECTION_DOWN}
|
||||
};
|
||||
|
||||
/* loop through directions array and try movements until one works */
|
||||
for (int try_movement_idx = 0;
|
||||
destHead == -1 && try_movement_idx < 4; try_movement_idx++) {
|
||||
destHead = wGetHeadRelativeToCurrentHead(wwin->screen_ptr,
|
||||
head, try_movements[direction][try_movement_idx]);
|
||||
}
|
||||
|
||||
if (destHead != -1) {
|
||||
totalArea.x1 = 0;
|
||||
totalArea.y1 = 0;
|
||||
totalArea.x2 = scr->scr_width;
|
||||
totalArea.y2 = scr->scr_height;
|
||||
|
||||
oldHeadArea = wGetUsableAreaForHead(scr, head, &totalArea, True);
|
||||
destHeadArea = wGetUsableAreaForHead(scr, destHead, &totalArea, True);
|
||||
|
||||
offsetX = wwin->frame_x - oldHeadArea.x1;
|
||||
offsetY = wwin->frame_y - oldHeadArea.y1;
|
||||
|
||||
newX = destHeadArea.x1 + offsetX;
|
||||
newY = destHeadArea.y1 + offsetY;
|
||||
|
||||
new_width = wwin->client.width;
|
||||
new_height = wwin->client.height;
|
||||
|
||||
/* try to brind window inside head coordinates */
|
||||
if (newX > destHeadArea.x2)
|
||||
newX = destHeadArea.x2 - wwin->client.width;
|
||||
|
||||
if (newX < destHeadArea.x1)
|
||||
newX = destHeadArea.x1;
|
||||
|
||||
if (newY > destHeadArea.y2)
|
||||
newY = destHeadArea.y2 - wwin->client.height;
|
||||
|
||||
if (newY < destHeadArea.y1)
|
||||
newY = destHeadArea.y1;
|
||||
|
||||
/* unset maximization state */
|
||||
wwin->flags.maximized = 0;
|
||||
wWindowConfigure(wwin, newX, newY, new_width, new_height);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* the window boundary coordinates */
|
||||
typedef struct {
|
||||
int left;
|
||||
|
||||
@@ -770,6 +770,10 @@ WDefaultEntry optionList[] = {
|
||||
NULL, getKeybind, setKeyGrab, NULL, NULL},
|
||||
{"WindowShortcut10Key", "None", (void *)WKBD_WINDOW10,
|
||||
NULL, getKeybind, setKeyGrab, NULL, NULL},
|
||||
{"MoveTo12to6Head", "None", (void *)WKBD_MOVE_12_TO_6_HEAD,
|
||||
NULL, getKeybind, setKeyGrab, NULL, NULL},
|
||||
{"MoveTo6to12Head", "None", (void *)WKBD_MOVE_6_TO_12_HEAD,
|
||||
NULL, getKeybind, setKeyGrab, NULL, NULL},
|
||||
{"WindowRelaunchKey", "None", (void *)WKBD_RELAUNCH,
|
||||
NULL, getKeybind, setKeyGrab, NULL, NULL},
|
||||
{"ScreenSwitchKey", "None", (void *)WKBD_SWITCH_SCREEN,
|
||||
|
||||
@@ -1802,6 +1802,13 @@ static void handleKeyPress(XEvent * event)
|
||||
|
||||
break;
|
||||
|
||||
case WKBD_MOVE_12_TO_6_HEAD:
|
||||
case WKBD_MOVE_6_TO_12_HEAD:
|
||||
if (wwin)
|
||||
moveBetweenHeads(wwin, command - WKBD_MOVE_12_TO_6_HEAD);
|
||||
|
||||
break;
|
||||
|
||||
case WKBD_RELAUNCH:
|
||||
if (ISMAPPED(wwin) && ISFOCUSED(wwin))
|
||||
(void) RelaunchWindow(wwin);
|
||||
|
||||
@@ -132,6 +132,10 @@ enum {
|
||||
WKBD_WINDOW9,
|
||||
WKBD_WINDOW10,
|
||||
|
||||
/* shortcuts to move window between heads */
|
||||
WKBD_MOVE_12_TO_6_HEAD,
|
||||
WKBD_MOVE_6_TO_12_HEAD,
|
||||
|
||||
/* launch a new instance of the active window */
|
||||
WKBD_RELAUNCH,
|
||||
|
||||
|
||||
Reference in New Issue
Block a user