mirror of
https://github.com/gryf/wmaker.git
synced 2025-12-20 21:08:08 +01:00
More intuitive maximization handling.
Avoid some pitfalls with window maximization and make it behave more intuitively. We now treat a window's vertical and horizontal maximization as separate properties and only remember its original geometry in a particular direction when it actually changes. We also deliberately do not remember a window's geometry when it changes from one maximized state to another. As a result windows can be more reliably restored to their original size. For example the "Maximize active window" hotkey followed by the "Maximize active window vertically" hotkey will now result in the window being maximized horizontally only, whereas previously the second hotkey would have no effect because the window was already maximized vertically. In addition selecting the Unmaximize window menu in the same example will now result in the window being restored to its original size. Previously the unmaximize attempt would have no effect because the vertical maximization would have remembered the window's "original" geometry when it was fully maximized. Maximus is handled separately. The "Maximus" hotkey will now toggle Maximus mode regardless of the window's current maximization state. For example if two unmaximized windows are on screen and one is Maximusized it will fill the space left by the second window, as before. But if the first window is maximized and the "Maximus" hotkey is pressed the window will now fill the same space as if it were Maximusized from its original size. Previously the window would not change size from its fully maximized state because the Maximus algorithm would consider fully-maximized to be a valid Maximus size.
This commit is contained in:
committed by
Carlos R. Mafra
parent
e6e3e1aa49
commit
aee0ad45f2
170
src/actions.c
170
src/actions.c
@@ -58,7 +58,7 @@ extern int calcIntersectionLength(int p1, int l1, int p2, int l2);
|
||||
|
||||
static void find_Maximus_geometry(WWindow *wwin, WArea usableArea, int *new_x, int *new_y,
|
||||
unsigned int *new_width, unsigned int *new_height);
|
||||
static void save_old_geometry(WWindow *wwin);
|
||||
static void save_old_geometry(WWindow *wwin, int directions);
|
||||
|
||||
/******* Local Variables *******/
|
||||
static struct {
|
||||
@@ -284,20 +284,43 @@ void wUnshadeWindow(WWindow *wwin)
|
||||
}
|
||||
|
||||
/* Set the old coordinates using the current values */
|
||||
static void save_old_geometry(WWindow *wwin)
|
||||
static void save_old_geometry(WWindow *wwin, int directions)
|
||||
{
|
||||
if (directions & MAX_HORIZONTAL || ! wwin->old_geometry.width) {
|
||||
wwin->old_geometry.width = wwin->client.width;
|
||||
wwin->old_geometry.height = wwin->client.height;
|
||||
wwin->old_geometry.x = wwin->frame_x;
|
||||
}
|
||||
if (directions & MAX_VERTICAL || ! wwin->old_geometry.height) {
|
||||
wwin->old_geometry.height = wwin->client.height;
|
||||
wwin->old_geometry.y = wwin->frame_y;
|
||||
}
|
||||
}
|
||||
|
||||
static void remember_geometry(WWindow *wwin, int *x, int *y, int *w, int *h)
|
||||
{
|
||||
WMRect old_geom_rect;
|
||||
int old_head;
|
||||
Bool same_head;
|
||||
|
||||
old_geom_rect = wmkrect(wwin->old_geometry.x, wwin->old_geometry.y, wwin->old_geometry.width, wwin->old_geometry.height);
|
||||
old_head = wGetHeadForRect(wwin->screen_ptr, old_geom_rect);
|
||||
same_head = (wGetHeadForWindow(wwin) == old_head);
|
||||
*x = (wwin->old_geometry.x && same_head) ? wwin->old_geometry.x : wwin->frame_x;
|
||||
*y = (wwin->old_geometry.y && same_head) ? wwin->old_geometry.y : wwin->frame_y;
|
||||
*w = wwin->old_geometry.width ? wwin->old_geometry.width : wwin->client.width;
|
||||
*h = wwin->old_geometry.height ? wwin->old_geometry.height : wwin->client.height;
|
||||
}
|
||||
|
||||
#define IS_MAX_HORIZONTALLY(directions) ((directions & MAX_HORIZONTAL) | (directions & MAX_LEFTHALF) | (directions & MAX_RIGHTHALF))
|
||||
void wMaximizeWindow(WWindow *wwin, int directions)
|
||||
{
|
||||
int new_x, new_y;
|
||||
unsigned int new_width, new_height, half_scr_width;
|
||||
int maximus_x, maximus_y;
|
||||
unsigned int maximus_width, maximus_height;
|
||||
WArea usableArea, totalArea;
|
||||
Bool has_border = 1;
|
||||
int save_directions = 0;
|
||||
int adj_size;
|
||||
|
||||
if (!IS_RESIZABLE(wwin))
|
||||
@@ -309,8 +332,19 @@ void wMaximizeWindow(WWindow *wwin, int directions)
|
||||
/* the size to adjust the geometry */
|
||||
adj_size = FRAME_BORDER_WIDTH * 2 * has_border;
|
||||
|
||||
/* save old coordinates before we change the current values */
|
||||
save_old_geometry(wwin);
|
||||
/* save old coordinates before we change the current values
|
||||
* but never if the window has been Maximusized */
|
||||
if (!(wwin->flags.old_maximized & MAX_MAXIMUS)) {
|
||||
if ((directions & MAX_VERTICAL) &&
|
||||
!(wwin->flags.maximized & MAX_VERTICAL))
|
||||
save_directions |= MAX_VERTICAL;
|
||||
if (IS_MAX_HORIZONTALLY(directions) &&
|
||||
!IS_MAX_HORIZONTALLY(wwin->flags.maximized))
|
||||
save_directions |= MAX_HORIZONTAL;
|
||||
}
|
||||
if ((directions & MAX_MAXIMUS) && !wwin->flags.maximized)
|
||||
save_directions |= MAX_VERTICAL | MAX_HORIZONTAL;
|
||||
save_old_geometry(wwin, save_directions);
|
||||
|
||||
totalArea.x1 = 0;
|
||||
totalArea.y1 = 0;
|
||||
@@ -330,6 +364,10 @@ void wMaximizeWindow(WWindow *wwin, int directions)
|
||||
usableArea = wGetUsableAreaForHead(scr, head, &totalArea, True);
|
||||
}
|
||||
|
||||
/* remember Maximus geometry if we'll need it later */
|
||||
if ((wwin->flags.old_maximized & MAX_MAXIMUS) || (directions & MAX_MAXIMUS))
|
||||
find_Maximus_geometry(wwin, usableArea, &maximus_x, &maximus_y, &maximus_width, &maximus_height);
|
||||
|
||||
/* Only save directions, not kbd or xinerama hints */
|
||||
directions &= (MAX_HORIZONTAL | MAX_VERTICAL | MAX_LEFTHALF | MAX_RIGHTHALF | MAX_MAXIMUS);
|
||||
|
||||
@@ -349,10 +387,21 @@ void wMaximizeWindow(WWindow *wwin, int directions)
|
||||
} else if (directions & MAX_LEFTHALF) {
|
||||
new_width = half_scr_width - adj_size;
|
||||
new_x = usableArea.x1;
|
||||
wwin->flags.old_maximized |= MAX_LEFTHALF;
|
||||
wwin->flags.old_maximized &= ~MAX_RIGHTHALF;
|
||||
} else if (directions & MAX_RIGHTHALF) {
|
||||
new_width = half_scr_width - adj_size;
|
||||
new_x = usableArea.x1 + half_scr_width;
|
||||
wwin->flags.old_maximized |= MAX_RIGHTHALF;
|
||||
wwin->flags.old_maximized &= ~MAX_LEFTHALF;
|
||||
} else if (wwin->flags.old_maximized & MAX_MAXIMUS) {
|
||||
new_x = maximus_x;
|
||||
new_width = maximus_width - adj_size;
|
||||
} else if (IS_MAX_HORIZONTALLY(wwin->flags.maximized)) {
|
||||
new_x = (wwin->old_geometry.x) ? wwin->old_geometry.x : wwin->frame_x;
|
||||
new_width = (wwin->old_geometry.width) ? wwin->old_geometry.width : wwin->frame->core->width;
|
||||
} else {
|
||||
wwin->flags.old_maximized &= ~(MAX_LEFTHALF | MAX_RIGHTHALF);
|
||||
new_x = wwin->frame_x;
|
||||
new_width = wwin->frame->core->width;
|
||||
}
|
||||
@@ -364,6 +413,17 @@ void wMaximizeWindow(WWindow *wwin, int directions)
|
||||
new_y -= wwin->frame->top_width;
|
||||
new_height += wwin->frame->bottom_width - 1;
|
||||
}
|
||||
} else if (wwin->flags.old_maximized & MAX_MAXIMUS) {
|
||||
new_y = maximus_y;
|
||||
new_height = maximus_height - adj_size;
|
||||
/* HACK: this will be subtracted again below */
|
||||
new_height += wwin->frame->top_width + wwin->frame->bottom_width;
|
||||
} else if (wwin->flags.maximized & MAX_VERTICAL) {
|
||||
new_y = (wwin->old_geometry.y) ? wwin->old_geometry.y : wwin->frame_y;
|
||||
new_height = (wwin->old_geometry.height) ? wwin->old_geometry.height : wwin->frame->core->height;
|
||||
/* HACK: this will be subtracted again below */
|
||||
new_height += wwin->frame->top_width + wwin->frame->bottom_width;
|
||||
wwin->flags.old_maximized &= ~(MAX_LEFTHALF | MAX_RIGHTHALF);
|
||||
} else {
|
||||
new_y = wwin->frame_y;
|
||||
new_height = wwin->frame->core->height;
|
||||
@@ -374,13 +434,15 @@ void wMaximizeWindow(WWindow *wwin, int directions)
|
||||
}
|
||||
|
||||
if (directions & MAX_MAXIMUS) {
|
||||
find_Maximus_geometry(wwin, usableArea, &new_x, &new_y, &new_width, &new_height);
|
||||
new_width -= adj_size;
|
||||
new_height -= adj_size;
|
||||
new_x = maximus_x;
|
||||
new_y = maximus_y;
|
||||
new_width = maximus_width - adj_size;
|
||||
new_height = maximus_height - adj_size;
|
||||
if (WFLAGP(wwin, full_maximize) && new_y == 0) {
|
||||
new_y -= wwin->frame->top_width;
|
||||
new_height += wwin->frame->top_width - 1;
|
||||
}
|
||||
wwin->flags.old_maximized |= MAX_MAXIMUS;
|
||||
}
|
||||
|
||||
wWindowConstrainSize(wwin, &new_width, &new_height);
|
||||
@@ -395,6 +457,79 @@ void wMaximizeWindow(WWindow *wwin, int directions)
|
||||
|
||||
/* set maximization state */
|
||||
wwin->flags.maximized = directions;
|
||||
if ((wwin->flags.old_maximized & MAX_MAXIMUS) && !wwin->flags.maximized)
|
||||
wwin->flags.maximized = MAX_MAXIMUS;
|
||||
}
|
||||
|
||||
/* generic (un)maximizer */
|
||||
void handleMaximize(WWindow *wwin, int directions)
|
||||
{
|
||||
int current = wwin->flags.maximized;
|
||||
int requested = directions & (MAX_HORIZONTAL | MAX_VERTICAL | MAX_LEFTHALF | MAX_RIGHTHALF | MAX_MAXIMUS);
|
||||
int effective = requested ^ current;
|
||||
int flags = directions & ~requested;
|
||||
|
||||
if (!effective) {
|
||||
/* allow wMaximizeWindow to restore the Maximusized size */
|
||||
if ((wwin->flags.old_maximized & MAX_MAXIMUS) &&
|
||||
!(requested & MAX_MAXIMUS))
|
||||
wMaximizeWindow(wwin, flags);
|
||||
else
|
||||
wUnmaximizeWindow(wwin);
|
||||
}
|
||||
else {
|
||||
/* MAX_MAXIMUS takes precedence */
|
||||
effective &= ~MAX_MAXIMUS;
|
||||
if (requested & MAX_MAXIMUS) {
|
||||
/* window was previously Maximusized then maximized */
|
||||
if ((wwin->flags.old_maximized & MAX_MAXIMUS) && !current) {
|
||||
wUnmaximizeWindow(wwin);
|
||||
return;
|
||||
}
|
||||
else
|
||||
effective = MAX_MAXIMUS;
|
||||
}
|
||||
else if (requested == (MAX_HORIZONTAL | MAX_VERTICAL))
|
||||
effective = requested;
|
||||
else {
|
||||
/* handle MAX_HORIZONTAL -> MAX_(LEFT|RIGHT)HALF */
|
||||
if (IS_MAX_HORIZONTALLY(current)) {
|
||||
if (IS_MAX_HORIZONTALLY(requested)) {
|
||||
effective &= ~(MAX_HORIZONTAL | MAX_LEFTHALF | MAX_RIGHTHALF);
|
||||
effective |= (requested & (MAX_HORIZONTAL | MAX_LEFTHALF | MAX_RIGHTHALF));
|
||||
if (requested & MAX_HORIZONTAL) {
|
||||
/* restore to half maximization */
|
||||
if (wwin->flags.old_maximized & MAX_LEFTHALF)
|
||||
effective |= MAX_LEFTHALF;
|
||||
else if (wwin->flags.old_maximized & MAX_RIGHTHALF)
|
||||
effective |= MAX_RIGHTHALF;
|
||||
}
|
||||
/* MAX_VERTICAL is implicit with MAX_(LEFT|RIGHT)HALF */
|
||||
else
|
||||
effective |= MAX_VERTICAL;
|
||||
} else {
|
||||
/* toggling MAX_VERTICAL */
|
||||
if ((requested & MAX_VERTICAL) &&
|
||||
(current & MAX_VERTICAL)) {
|
||||
effective &= ~(MAX_LEFTHALF | MAX_RIGHTHALF | MAX_VERTICAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* handle MAX_VERTICAL -> MAX_(LEFT|RIGHT)HALF */
|
||||
if (current & MAX_VERTICAL) {
|
||||
if ((requested & MAX_LEFTHALF) ||
|
||||
(requested & MAX_RIGHTHALF)) {
|
||||
effective |= MAX_VERTICAL;
|
||||
}
|
||||
}
|
||||
/* toggling MAX_HORIZONTAL */
|
||||
if ((requested & MAX_HORIZONTAL) &&
|
||||
(current & MAX_HORIZONTAL))
|
||||
effective &= ~MAX_HORIZONTAL;
|
||||
}
|
||||
wMaximizeWindow(wwin, effective | flags);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* the window boundary coordinates */
|
||||
@@ -434,6 +569,13 @@ static void find_Maximus_geometry(WWindow *wwin, WArea usableArea, int *new_x, i
|
||||
win_coords obs, orig, new;
|
||||
|
||||
/* set the original coordinate positions of the window to be Maximumized */
|
||||
if (wwin->flags.maximized) {
|
||||
/* window is already maximized; consider original geometry */
|
||||
remember_geometry(wwin, &orig.left, &orig.top, &orig.width, &orig.height);
|
||||
orig.bottom = orig.top + orig.height;
|
||||
orig.right = orig.left + orig.width;
|
||||
}
|
||||
else
|
||||
set_window_coords(wwin, &orig);
|
||||
|
||||
/* Try to fully maximize first, then readjust later */
|
||||
@@ -520,9 +662,6 @@ static void find_Maximus_geometry(WWindow *wwin, WArea usableArea, int *new_x, i
|
||||
void wUnmaximizeWindow(WWindow *wwin)
|
||||
{
|
||||
int x, y, w, h;
|
||||
WMRect old_geom_rect;
|
||||
int old_head;
|
||||
Bool same_head;
|
||||
|
||||
if (!wwin->flags.maximized)
|
||||
return;
|
||||
@@ -532,15 +671,10 @@ void wUnmaximizeWindow(WWindow *wwin)
|
||||
wUnshadeWindow(wwin);
|
||||
}
|
||||
/* Use old coordinates if they are set, current values otherwise */
|
||||
old_geom_rect = wmkrect(wwin->old_geometry.x, wwin->old_geometry.y, wwin->old_geometry.width, wwin->old_geometry.height);
|
||||
old_head = wGetHeadForRect(wwin->screen_ptr, old_geom_rect);
|
||||
same_head = (wGetHeadForWindow(wwin) == old_head);
|
||||
x = (wwin->old_geometry.x && same_head) ? wwin->old_geometry.x : wwin->frame_x;
|
||||
y = (wwin->old_geometry.y && same_head) ? wwin->old_geometry.y : wwin->frame_y;
|
||||
w = wwin->old_geometry.width ? wwin->old_geometry.width : wwin->client.width;
|
||||
h = wwin->old_geometry.height ? wwin->old_geometry.height : wwin->client.height;
|
||||
remember_geometry(wwin, &x, &y, &w, &h);
|
||||
|
||||
wwin->flags.maximized = 0;
|
||||
wwin->flags.old_maximized = 0;
|
||||
wWindowConfigure(wwin, x, y, w, h);
|
||||
wWindowSynthConfigureNotify(wwin);
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@ void wUnselectWindows(WScreen *scr);
|
||||
|
||||
void wMaximizeWindow(WWindow *wwin, int directions);
|
||||
void wUnmaximizeWindow(WWindow *wwin);
|
||||
void handleMaximize(WWindow *wwin, int directions);
|
||||
|
||||
void wHideAll(WScreen *src);
|
||||
void wHideOtherApplications(WWindow *wwin);
|
||||
|
||||
30
src/event.c
30
src/event.c
@@ -1444,60 +1444,42 @@ static void handleKeyPress(XEvent * event)
|
||||
if (ISMAPPED(wwin) && ISFOCUSED(wwin) && IS_RESIZABLE(wwin)) {
|
||||
CloseWindowMenu(scr);
|
||||
|
||||
if (wwin->flags.maximized == (MAX_VERTICAL | MAX_HORIZONTAL))
|
||||
wUnmaximizeWindow(wwin);
|
||||
else
|
||||
wMaximizeWindow(wwin, MAX_VERTICAL | MAX_HORIZONTAL | MAX_KEYBOARD);
|
||||
handleMaximize(wwin, MAX_VERTICAL | MAX_HORIZONTAL | MAX_KEYBOARD);
|
||||
}
|
||||
break;
|
||||
case WKBD_VMAXIMIZE:
|
||||
if (ISMAPPED(wwin) && ISFOCUSED(wwin) && IS_RESIZABLE(wwin)) {
|
||||
CloseWindowMenu(scr);
|
||||
|
||||
if (wwin->flags.maximized == MAX_VERTICAL)
|
||||
wUnmaximizeWindow(wwin);
|
||||
else
|
||||
wMaximizeWindow(wwin, MAX_VERTICAL | MAX_KEYBOARD);
|
||||
handleMaximize(wwin, MAX_VERTICAL | MAX_KEYBOARD);
|
||||
}
|
||||
break;
|
||||
case WKBD_HMAXIMIZE:
|
||||
if (ISMAPPED(wwin) && ISFOCUSED(wwin) && IS_RESIZABLE(wwin)) {
|
||||
CloseWindowMenu(scr);
|
||||
|
||||
if (wwin->flags.maximized == MAX_HORIZONTAL)
|
||||
wUnmaximizeWindow(wwin);
|
||||
else
|
||||
wMaximizeWindow(wwin, MAX_HORIZONTAL | MAX_KEYBOARD);
|
||||
handleMaximize(wwin, MAX_HORIZONTAL | MAX_KEYBOARD);
|
||||
}
|
||||
break;
|
||||
case WKBD_LHMAXIMIZE:
|
||||
if (ISMAPPED(wwin) && ISFOCUSED(wwin) && IS_RESIZABLE(wwin)) {
|
||||
CloseWindowMenu(scr);
|
||||
|
||||
if (wwin->flags.maximized == (MAX_VERTICAL | MAX_LEFTHALF))
|
||||
wUnmaximizeWindow(wwin);
|
||||
else
|
||||
wMaximizeWindow(wwin, MAX_VERTICAL | MAX_LEFTHALF | MAX_KEYBOARD);
|
||||
handleMaximize(wwin, MAX_VERTICAL | MAX_LEFTHALF | MAX_KEYBOARD);
|
||||
}
|
||||
break;
|
||||
case WKBD_RHMAXIMIZE:
|
||||
if (ISMAPPED(wwin) && ISFOCUSED(wwin) && IS_RESIZABLE(wwin)) {
|
||||
CloseWindowMenu(scr);
|
||||
|
||||
if (wwin->flags.maximized == (MAX_VERTICAL | MAX_RIGHTHALF))
|
||||
wUnmaximizeWindow(wwin);
|
||||
else
|
||||
wMaximizeWindow(wwin, MAX_VERTICAL | MAX_RIGHTHALF | MAX_KEYBOARD);
|
||||
handleMaximize(wwin, MAX_VERTICAL | MAX_RIGHTHALF | MAX_KEYBOARD);
|
||||
}
|
||||
break;
|
||||
case WKBD_MAXIMUS:
|
||||
if (ISMAPPED(wwin) && ISFOCUSED(wwin) && IS_RESIZABLE(wwin)) {
|
||||
CloseWindowMenu(scr);
|
||||
|
||||
if (wwin->flags.maximized == MAX_MAXIMUS)
|
||||
wUnmaximizeWindow(wwin);
|
||||
else
|
||||
wMaximizeWindow(wwin, MAX_MAXIMUS | MAX_KEYBOARD);
|
||||
handleMaximize(wwin, MAX_MAXIMUS | MAX_KEYBOARD);
|
||||
}
|
||||
break;
|
||||
case WKBD_RAISE:
|
||||
|
||||
@@ -248,6 +248,7 @@ typedef struct WWindow {
|
||||
unsigned int hidden:1;
|
||||
unsigned int shaded:1;
|
||||
unsigned int maximized:5;
|
||||
unsigned int old_maximized:5;
|
||||
unsigned int fullscreen:1;
|
||||
unsigned int omnipresent:1;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user