diff --git a/action.c b/action.c index 42c96df..2281629 100644 --- a/action.c +++ b/action.c @@ -112,3 +112,17 @@ void action_fullscreen(void *data, int num, client *cli) client_update_border(cli); client_raise_family(cli); } + +void action_maximize_vert(void *data, int num, client *cli) +{ + if (!cli) return; + cli->maxv = client_toggle_state(cli, atoms[_NET_WM_STATE_MAXIMIZE_VERT]); + client_place_spot(cli, cli->spot, cli->monitor, 1); +} + +void action_maximize_horz(void *data, int num, client *cli) +{ + if (!cli) return; + cli->maxh = client_toggle_state(cli, atoms[_NET_WM_STATE_MAXIMIZE_HORZ]); + client_place_spot(cli, cli->spot, cli->monitor, 1); +} \ No newline at end of file diff --git a/atom.c b/atom.c index ce1b3ea..300c1a5 100644 --- a/atom.c +++ b/atom.c @@ -49,6 +49,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. X(_NET_WM_WINDOW_TYPE_DIALOG),\ X(_NET_WM_STATE),\ X(_NET_WM_STATE_FULLSCREEN),\ + X(_NET_WM_STATE_MAXIMIZE_VERT),\ + X(_NET_WM_STATE_MAXIMIZE_HORZ),\ X(_NET_WM_STATE_DEMANDS_ATTENTION),\ X(WM_NAME),\ X(WM_DELETE_WINDOW),\ diff --git a/client.c b/client.c index 6aec31e..87e1414 100644 --- a/client.c +++ b/client.c @@ -70,6 +70,7 @@ client* window_build_client(Window win) && c->type != atoms[_NET_WM_WINDOW_TYPE_SPLASH] ? 1:0; + // detect our own title bars for_monitors(i, m) for_spots(j) if (m->bars[j] && m->bars[j]->window == c->window) { c->ours = 1; c->manage = 0; break; } @@ -92,8 +93,23 @@ client* window_build_client(Window win) { if (!GETPROP_ATOM(c->window, atoms[_NET_WM_STATE], c->states, ATOMLIST)) memset(c->states, 0, sizeof(Atom) * ATOMLIST); + c->urgent = client_has_state(c, atoms[_NET_WM_STATE_DEMANDS_ATTENTION]); c->full = client_has_state(c, atoms[_NET_WM_STATE_FULLSCREEN]); + c->maxv = client_has_state(c, atoms[_NET_WM_STATE_MAXIMIZE_VERT]); + c->maxh = client_has_state(c, atoms[_NET_WM_STATE_MAXIMIZE_HORZ]); + + // _NET_WM_STATE_MAXIMIZE_VERT may apply to spot2 windows. Detect... + if (c->maxv && c->type != atoms[_NET_WM_WINDOW_TYPE_DIALOG] + && INTERSECT(m->spots[SPOT2].x, m->spots[SPOT2].y, m->spots[SPOT2].w, m->spots[SPOT2].h, + c->attr.x + c->attr.width/10, c->attr.y + c->attr.height/10, c->attr.width - c->attr.width/10, c->attr.height - c->attr.height/10)) + c->spot = SPOT2; + + // _NET_WM_STATE_MAXIMIZE_HORZ may apply to spot3 windows. Detect... + if (c->maxh && c->type != atoms[_NET_WM_WINDOW_TYPE_DIALOG] + && INTERSECT(m->spots[SPOT3].x, m->spots[SPOT3].y, m->spots[SPOT3].w, m->spots[SPOT3].h, + c->attr.x + c->attr.width/10, c->attr.y + c->attr.height/10, c->attr.width - c->attr.width/10, c->attr.height - c->attr.height/10)) + c->spot = SPOT3; if ((hints = XGetWMHints(display, c->window))) { @@ -179,6 +195,19 @@ void client_place_spot(client *c, int spot, int mon, int force) XMoveResizeWindow(display, c->window, m->x, m->y, m->w, m->h); return; } + else + // _NET_WM_STATE_MAXIMIZE_VERT may apply to a window in spot2 + if (c->maxv && spot == SPOT2) + { + h = m->h - y; + } + else + // _NET_WM_STATE_MAXIMIZE_HORZ may apply to a window in spot3 + if (c->maxh && spot == SPOT3) + { + w = m->w; + } + w -= BORDER*2; h -= BORDER*2; int sw = w, sh = h; long sr; XSizeHints size; @@ -242,8 +271,19 @@ void client_raise_family(client *c) c = family.clients[family.depth++] = o; client_stack_family(c, &raise); + + if (!c->full) + { + // raise spot's title bar in case some other fullscreen or max v/h window has obscured + monitor *m = &monitors[c->monitor]; + raise.windows[raise.depth] = m->bars[c->spot]->window; + raise.clients[raise.depth] = NULL; + raise.depth++; + } + XRaiseWindow(display, raise.windows[0]); XRestackWindows(display, raise.windows, raise.depth); + STACK_FREE(&family); } diff --git a/config.h b/config.h index 7dd230b..db16440 100644 --- a/config.h +++ b/config.h @@ -7,7 +7,7 @@ #define GAP 2 // Title bar xft font -#define TITLE "sans:bold:size=10" +#define TITLE "sans:size=8" #define TITLE_BLUR "Black" #define TITLE_FOCUS "White" #define TITLE_ELLIPSIS 30 @@ -62,6 +62,8 @@ // action_move_monitor // action_focus_monitor // action_fullscreen +// action_maximize_vert +// action_maximize_horz // If you use "AnyModifier" place those keys at the end of the array. binding keys[] = { @@ -100,6 +102,8 @@ binding keys[] = { // Toggle current window full screen. { .mod = Mod4Mask, .key = XK_f, .act = action_fullscreen }, + { .mod = Mod4Mask, .key = XK_v, .act = action_maximize_vert }, + { .mod = Mod4Mask, .key = XK_h, .act = action_maximize_horz }, // Switch focus between monitors. { .mod = Mod4Mask, .key = XK_Next, .act = action_focus_monitor, .num = +1 }, diff --git a/xoat.c b/xoat.c index dfa09ae..0a0f77f 100644 --- a/xoat.c +++ b/xoat.c @@ -75,7 +75,7 @@ typedef struct { XWindowAttributes attr; Window transient, leader; Atom type, states[ATOMLIST+1]; - short monitor, visible, manage, input, urgent, full, ours; + short monitor, visible, manage, input, urgent, full, ours, maxv, maxh; unsigned long spot; char *class; } client; @@ -108,7 +108,8 @@ void action_find_or_start(void*, int, client*); void action_move_monitor(void*, int, client*); void action_focus_monitor(void*, int, client*); void action_fullscreen(void*, int, client*); -void action_above(void*, int, client*); +void action_maximize_vert(void*, int, client*); +void action_maximize_horz(void*, int, client*); #include "config.h"