mirror of
https://github.com/gryf/wmaker.git
synced 2025-12-19 20:38:08 +01:00
Maximus: Tiled Maximization
This patch introduces the "tiled maximization" feature, a.k.a. Maximus. By pressing the keyboard shortcut associated with Maximus, the focused window will be maximized to the greatest area satisfying the constraint of not overlapping existing windows.
This commit is contained in:
109
src/actions.c
109
src/actions.c
@@ -60,6 +60,10 @@ extern WPreferences wPreferences;
|
||||
extern Atom _XA_WM_TAKE_FOCUS;
|
||||
|
||||
extern void ProcessPendingEvents();
|
||||
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, int *new_width, int *new_height);
|
||||
|
||||
/******* Local Variables *******/
|
||||
static struct {
|
||||
@@ -326,7 +330,7 @@ void wMaximizeWindow(WWindow * wwin, int directions)
|
||||
wUnshadeWindow(wwin);
|
||||
}
|
||||
/* Only save directions, not kbd or xinerama hints */
|
||||
directions &= (MAX_HORIZONTAL|MAX_VERTICAL|MAX_LEFTHALF|MAX_RIGHTHALF);
|
||||
directions &= (MAX_HORIZONTAL | MAX_VERTICAL | MAX_LEFTHALF | MAX_RIGHTHALF | MAX_MAXIMUS);
|
||||
|
||||
changed_h = ((wwin->flags.maximized ^ directions) & MAX_HORIZONTAL);
|
||||
changed_v = ((wwin->flags.maximized ^ directions) & MAX_VERTICAL);
|
||||
@@ -397,6 +401,9 @@ void wMaximizeWindow(WWindow * wwin, int directions)
|
||||
new_height -= wwin->frame->top_width + wwin->frame->bottom_width;
|
||||
}
|
||||
|
||||
if (directions & MAX_MAXIMUS)
|
||||
find_Maximus_geometry(wwin, usableArea, &new_x, &new_y, &new_width, &new_height);
|
||||
|
||||
wWindowConstrainSize(wwin, &new_width, &new_height);
|
||||
|
||||
wWindowCropSize(wwin, usableArea.x2 - usableArea.x1,
|
||||
@@ -409,6 +416,106 @@ void wMaximizeWindow(WWindow * wwin, int directions)
|
||||
wSoundPlay(WSOUND_MAXIMIZE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Maximus: tiled maximization (maximize without overlapping other windows)
|
||||
*
|
||||
* The window to be maximized will be denoted by w_0 (sub-index zero)
|
||||
* while the windows which will stop the maximization of w_0 are denoted by w_j.
|
||||
*/
|
||||
static void find_Maximus_geometry(WWindow *wwin, WArea usableArea, int *new_x, int *new_y,
|
||||
int *new_width, int *new_height)
|
||||
{
|
||||
WWindow *tmp;
|
||||
int x_0 = wwin->frame_x;
|
||||
int y_0 = wwin->frame_y;
|
||||
int width_0 = wwin->frame->core->width;
|
||||
int height_0 = wwin->frame->core->height;
|
||||
int botton_0 = y_0 + height_0;
|
||||
int right_border_0 = x_0 + width_0;
|
||||
int new_x_0, new_y_0, new_botton_0, new_right_border_0, new_height_0;
|
||||
int x_j, y_j, width_j, height_j, botton_j, top_j, right_border_j;
|
||||
int x_intsect, y_intsect;
|
||||
/* Assume that the window w_0 has titlebar etc */
|
||||
int has_titlebar = 1, has_resizebar = 1, has_border = 1;
|
||||
int adjust_height, adjust_width;
|
||||
|
||||
/* Try to fully maximize first, then readjust later */
|
||||
new_x_0 = usableArea.x1;
|
||||
new_y_0 = usableArea.y1;
|
||||
new_botton_0 = usableArea.y2;
|
||||
new_right_border_0 = usableArea.x2;
|
||||
|
||||
if (!HAS_TITLEBAR(wwin))
|
||||
has_titlebar = 0;
|
||||
if (!HAS_RESIZEBAR(wwin))
|
||||
has_resizebar = 0;
|
||||
if (!HAS_BORDER(wwin))
|
||||
has_border = 0;
|
||||
|
||||
/* the lengths to be subtracted if w_0 has titlebar, etc */
|
||||
adjust_height = TITLEBAR_HEIGHT * has_titlebar
|
||||
+ 2 * FRAME_BORDER_WIDTH * has_border + RESIZEBAR_HEIGHT * has_resizebar;
|
||||
adjust_width = 2 * FRAME_BORDER_WIDTH * has_border;
|
||||
|
||||
tmp = wwin;
|
||||
/* TODO: Is the focused window always the last in the list? */
|
||||
while (tmp->prev) {
|
||||
/* ignore windows in other workspaces or minimized */
|
||||
if (tmp->prev->frame->workspace != wwin->screen_ptr->current_workspace
|
||||
|| tmp->prev->flags.miniaturized) {
|
||||
tmp = tmp->prev;
|
||||
continue;
|
||||
}
|
||||
tmp = tmp->prev;
|
||||
|
||||
/* set the w_j window coordinates */
|
||||
x_j = tmp->frame_x;
|
||||
y_j = tmp->frame_y;
|
||||
width_j = tmp->frame->core->width;
|
||||
height_j = tmp->frame->core->height;
|
||||
botton_j = y_j + height_j;
|
||||
top_j = y_j;
|
||||
right_border_j = x_j + width_j;
|
||||
|
||||
/* Try to maximize in the y direction first */
|
||||
x_intsect = calcIntersectionLength(x_0, width_0, x_j, width_j);
|
||||
if (x_intsect != 0) {
|
||||
if (botton_j < y_0 && botton_j > new_y_0) {
|
||||
/* w_0 is below the botton of w_j */
|
||||
new_y_0 = botton_j;
|
||||
}
|
||||
if (botton_0 < top_j && top_j < new_botton_0) {
|
||||
/* The botton of w_0 is above the top of w_j */
|
||||
new_botton_0 = top_j;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Use the updated y coordinates from the above step to account
|
||||
* the possibility that the new value of y_0 will have different
|
||||
* intersections with w_j
|
||||
*/
|
||||
new_height_0 = new_botton_0 - new_y_0 - adjust_height;
|
||||
y_intsect = calcIntersectionLength(new_y_0, new_height_0, y_j, height_j);
|
||||
if (y_intsect != 0) {
|
||||
if (right_border_j < x_0 && right_border_j > new_x_0) {
|
||||
/* w_0 is completely to the right of w_j */
|
||||
new_x_0 = right_border_j;
|
||||
}
|
||||
if (right_border_0 < x_j && x_j < new_right_border_0) {
|
||||
/* w_0 is completely to the left of w_j */
|
||||
new_right_border_0 = x_j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
new_height_0 = new_botton_0 - new_y_0 - adjust_height;
|
||||
*new_x = new_x_0;
|
||||
*new_y = new_y_0;
|
||||
*new_height = new_height_0;
|
||||
*new_width = new_right_border_0 - new_x_0 - adjust_width;
|
||||
}
|
||||
|
||||
void wUnmaximizeWindow(WWindow * wwin)
|
||||
{
|
||||
int x, y, w, h;
|
||||
|
||||
@@ -24,12 +24,13 @@
|
||||
|
||||
#include "window.h"
|
||||
|
||||
#define MAX_HORIZONTAL 1
|
||||
#define MAX_VERTICAL 2
|
||||
#define MAX_LEFTHALF 4
|
||||
#define MAX_RIGHTHALF 8
|
||||
#define MAX_IGNORE_XINERAMA 16
|
||||
#define MAX_KEYBOARD 32
|
||||
#define MAX_HORIZONTAL (1 << 0)
|
||||
#define MAX_VERTICAL (1 << 1)
|
||||
#define MAX_LEFTHALF (1 << 2)
|
||||
#define MAX_RIGHTHALF (1 << 3)
|
||||
#define MAX_MAXIMUS (1 << 4)
|
||||
#define MAX_IGNORE_XINERAMA (1 << 5)
|
||||
#define MAX_KEYBOARD (1 << 6)
|
||||
|
||||
void wSetFocusTo(WScreen *scr, WWindow *wwin);
|
||||
|
||||
|
||||
@@ -583,6 +583,8 @@ WDefaultEntry optionList[] = {
|
||||
NULL, getKeybind, setKeyGrab},
|
||||
{"RHMaximizeKey", "None", (void*)WKBD_RHMAXIMIZE,
|
||||
NULL, getKeybind, setKeyGrab},
|
||||
{"MaximusKey", "None", (void*)WKBD_MAXIMUS,
|
||||
NULL, getKeybind, setKeyGrab},
|
||||
{"RaiseKey", "\"Meta+Up\"", (void *)WKBD_RAISE,
|
||||
NULL, getKeybind, setKeyGrab},
|
||||
{"LowerKey", "\"Meta+Down\"", (void *)WKBD_LOWER,
|
||||
|
||||
13
src/event.c
13
src/event.c
@@ -1497,6 +1497,19 @@ static void handleKeyPress(XEvent * event)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WKBD_MAXIMUS:
|
||||
if (ISMAPPED(wwin) && ISFOCUSED(wwin) && IS_RESIZABLE(wwin)) {
|
||||
int newdir = MAX_MAXIMUS;
|
||||
|
||||
CloseWindowMenu(scr);
|
||||
|
||||
if (wwin->flags.maximized == newdir) {
|
||||
wUnmaximizeWindow(wwin);
|
||||
} else {
|
||||
wMaximizeWindow(wwin, newdir|MAX_KEYBOARD);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WKBD_RAISE:
|
||||
if (ISMAPPED(wwin) && ISFOCUSED(wwin)) {
|
||||
CloseWindowMenu(scr);
|
||||
|
||||
@@ -35,6 +35,7 @@ enum {
|
||||
WKBD_HMAXIMIZE,
|
||||
WKBD_LHMAXIMIZE,
|
||||
WKBD_RHMAXIMIZE,
|
||||
WKBD_MAXIMUS,
|
||||
WKBD_SELECT,
|
||||
WKBD_RAISE,
|
||||
WKBD_LOWER,
|
||||
|
||||
@@ -234,7 +234,7 @@ void PlaceIcon(WScreen *scr, int *x_ret, int *y_ret, int head)
|
||||
}
|
||||
|
||||
/* Computes the intersecting length of two line sections */
|
||||
static int calcIntersectionLength(int p1, int l1, int p2, int l2)
|
||||
int calcIntersectionLength(int p1, int l1, int p2, int l2)
|
||||
{
|
||||
int isect;
|
||||
int tmp;
|
||||
|
||||
@@ -258,7 +258,7 @@ typedef struct WWindow {
|
||||
unsigned int miniaturized:1;
|
||||
unsigned int hidden:1;
|
||||
unsigned int shaded:1;
|
||||
unsigned int maximized:4;
|
||||
unsigned int maximized:5;
|
||||
unsigned int fullscreen:1;
|
||||
unsigned int omnipresent:1;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user