shod

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit fbfae8c945d25f1424687def6744be3c45b83dd9
parent 730261e6755506aac4d91d455fb7921af7c17305
Author: seninha <lucas@seninha.org>
Date:   Tue, 23 Nov 2021 15:37:31 -0300

add shaded container state

Diffstat:
Mshod.1 | 18+++++++++++++++---
Mshod.c | 154+++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
Mshodc.c | 30++++++++++++++++++++----------
3 files changed, 147 insertions(+), 55 deletions(-)

diff --git a/shod.1 b/shod.1 @@ -57,7 +57,7 @@ .br .B shodc state .RB [ \-ATR ] -.RB [ \-abfMms ] +.RB [ \-abfMmsy ] .RI [ win_id ] .SH DESCRIPTION .B shod @@ -344,13 +344,17 @@ The fifth character is to indicate that the window's container is fullscreen. .IP \(bu 2 The sixth character is +.B s +to indicate that the window's container is shaded. +.IP \(bu 2 +The seventh character is .B a to indicate that the window's container is above others, or .B b to indicate that the window's container is below others. .IP \(bu 2 -The seventh character is +The eighth character is .B u to indicate that the window has the urgency hint set, .B a @@ -359,7 +363,7 @@ or .B U to indicate that the window is both urgent and demands attention. .IP \(bu 2 -The eighth and last character is +The ninth and last character is .B a to indicate that the window is active, .B f @@ -411,6 +415,10 @@ Set state minimized. Minimize container. .TP .B \-s +Set state shaded. +The container is resized to fit its titlebars. +.TP +.B \-y Set state sticky. Stick container to the monitor. .TP @@ -670,6 +678,10 @@ Minimized containers are not shown on the screen. When a minimized container is unminimized, it goes to the focused monitor. .TP +Shaded +Shaded containers have the size of its titlebars, +so no content is shown. +.TP Sticky Sticky containers are \(lqsticked\(rq to the monitor, and they appear on the screen no matter which desktop is focused on that monitor. diff --git a/shod.c b/shod.c @@ -160,6 +160,7 @@ enum { _NET_WM_STATE_STICKY, _NET_WM_STATE_MAXIMIZED_VERT, _NET_WM_STATE_MAXIMIZED_HORZ, + _NET_WM_STATE_SHADED, _NET_WM_STATE_HIDDEN, _NET_WM_STATE_FULLSCREEN, _NET_WM_STATE_ABOVE, @@ -358,7 +359,8 @@ struct Container { Window frame; /* window to reparent the contents of the container */ Pixmap pix; /* pixmap to draw the frame */ int ncols; /* number of columns */ - int ismaximized, isminimized, issticky; /* window states */ + int ismaximized, issticky; /* window states */ + int isminimized, isshaded; /* window states */ int isfullscreen; /* whether container is fullscreen */ int ishidden; /* whether container is hidden */ int layer; /* stacking order */ @@ -602,6 +604,7 @@ xerror(Display *dpy, XErrorEvent *e) (e->request_code == X_PolyFillRectangle && e->error_code == BadDrawable) || (e->request_code == X_PolySegment && e->error_code == BadDrawable) || (e->request_code == X_ConfigureWindow && e->error_code == BadMatch) || + (e->request_code == X_ConfigureWindow && e->error_code == BadValue) || (e->request_code == X_GrabButton && e->error_code == BadAccess) || (e->request_code == X_GrabKey && e->error_code == BadAccess) || (e->request_code == X_CopyArea && e->error_code == BadDrawable) || @@ -889,6 +892,7 @@ initatoms(void) [_NET_WM_STATE_STICKY] = "_NET_WM_STATE_STICKY", [_NET_WM_STATE_MAXIMIZED_VERT] = "_NET_WM_STATE_MAXIMIZED_VERT", [_NET_WM_STATE_MAXIMIZED_HORZ] = "_NET_WM_STATE_MAXIMIZED_HORZ", + [_NET_WM_STATE_SHADED] = "_NET_WM_STATE_SHADED", [_NET_WM_STATE_HIDDEN] = "_NET_WM_STATE_HIDDEN", [_NET_WM_STATE_FULLSCREEN] = "_NET_WM_STATE_FULLSCREEN", [_NET_WM_STATE_ABOVE] = "_NET_WM_STATE_ABOVE", @@ -1698,7 +1702,7 @@ ewmhsetstate(struct Container *c) struct Row *row; struct Tab *t; struct Dialog *d; - Atom data[8]; + Atom data[9]; int n = 0; if (c == NULL) @@ -1709,6 +1713,8 @@ ewmhsetstate(struct Container *c) data[n++] = atoms[_NET_WM_STATE_FULLSCREEN]; if (c->issticky) data[n++] = atoms[_NET_WM_STATE_STICKY]; + if (c->isshaded) + data[n++] = atoms[_NET_WM_STATE_SHADED]; if (c->isminimized) data[n++] = atoms[_NET_WM_STATE_HIDDEN]; if (c->ismaximized) { @@ -1850,6 +1856,13 @@ containergetstyle(struct Container *c) return UNFOCUSED; } +/* check if container can be shaded */ +static int +containerisshaded(struct Container *c) +{ + return c->isshaded && !c->isfullscreen; +} + /* calculate size of dialogs of a tab */ static void dialogcalcsize(struct Dialog *d) @@ -1952,6 +1965,9 @@ containercalccols(struct Container *c, int recursive) c->h = c->nh; c->b = visual.border; } + if (containerisshaded(c)) { + c->h = 0; + } /* check if columns sum up the width of the container */ sumw = 0; @@ -1963,6 +1979,9 @@ containercalccols(struct Container *c, int recursive) w = c->w - 2 * c->b - (c->ncols - 1) * visual.division; x = c->b; for (i = 0, col = c->cols; col != NULL; col = col->next, i++) { + if (containerisshaded(c)) { + c->h = max(c->h, col->nrows * visual.tab); + } if (sumw != c->w) col->w = max(1, ((i + 1) * w / c->ncols) - (i * w / c->ncols)); col->x = x; @@ -1971,6 +1990,9 @@ containercalccols(struct Container *c, int recursive) colcalcrows(col, 1); } } + if (containerisshaded(c)) { + c->h += 2 * c->b; + } } /* find best position to place a container on screen */ @@ -2264,6 +2286,7 @@ containerdecorate(struct Container *c, struct Column *cdiv, struct Row *rdiv, in XGCValues val; int style; /* decoration style, used as index in the decor array */ int w, h; /* size of the edges */ + int isshaded; if (c == NULL) return; @@ -2272,6 +2295,7 @@ containerdecorate(struct Container *c, struct Column *cdiv, struct Row *rdiv, in decorp = &visual.decor[style][PRESSED]; w = c->w - visual.corner * 2; h = c->h - visual.corner * 2; + isshaded = containerisshaded(c); /* (re)create pixmap */ if (c->pw != c->w || c->ph != c->h || c->pix == None) { @@ -2285,7 +2309,22 @@ containerdecorate(struct Container *c, struct Column *cdiv, struct Row *rdiv, in val.fill_style = FillTiled; XChangeGC(dpy, gc, GCFillStyle, &val); if (c->b > 0) { - + /* draw corners */ + XCopyArea(dpy, ((o == NW || (isshaded && o & W)) ? decorp->nw : decor->nw), + c->pix, gc, 0, 0, visual.corner, visual.corner, 0, 0); + + XCopyArea(dpy, ((o == NE || (isshaded && o & E)) ? decorp->ne : decor->ne), + c->pix, gc, 0, 0, visual.corner, visual.corner, + c->w - visual.corner, 0); + + XCopyArea(dpy, ((o == SW || (isshaded && o & W)) ? decorp->sw : decor->sw), + c->pix, gc, 0, 0, visual.corner, visual.corner, + 0, c->h - visual.corner); + + XCopyArea(dpy, ((o == SE || (isshaded && o & E)) ? decorp->se : decor->se), + c->pix, gc, 0, 0, visual.corner, visual.corner, + c->w - visual.corner, c->h - visual.corner); + /* draw borders */ if (w > 0) { val.tile = (o == N) ? decorp->n : decor->n; @@ -2299,9 +2338,7 @@ containerdecorate(struct Container *c, struct Column *cdiv, struct Row *rdiv, in XCopyArea(dpy, (o == N) ? decorp->nl : decor->nl, c->pix, gc, 0, 0, visual.edge, visual.border, visual.corner + w - visual.edge, 0); - } - if (w > 0) { val.tile = (o == S) ? decorp->s : decor->s; val.ts_x_origin = 0; val.ts_y_origin = c->h - c->b; @@ -2315,48 +2352,39 @@ containerdecorate(struct Container *c, struct Column *cdiv, struct Row *rdiv, in visual.corner + w - visual.edge, c->h - visual.border); } - if (h > 0) { + if (h > 0 || isshaded) { val.tile = (o == W) ? decorp->w : decor->w; val.ts_x_origin = 0; val.ts_y_origin = 0; XChangeGC(dpy, gc, GCTile | GCTileStipYOrigin | GCTileStipXOrigin , &val); - XFillRectangle(dpy, c->pix, gc, 0, visual.corner, c->b, h); - XCopyArea(dpy, (o == W) ? decorp->wf : - decor->wf, c->pix, gc, 0, 0, visual.border, visual.edge, 0, - visual.corner); - XCopyArea(dpy, (o == W) ? decorp->wl : - decor->wl, c->pix, gc, 0, 0, visual.border, visual.edge, 0, - visual.corner + h - visual.edge); - } + if (isshaded) { + XFillRectangle(dpy, c->pix, gc, 0, visual.border, c->b, c->h - 2 * visual.border); + } else { + XFillRectangle(dpy, c->pix, gc, 0, visual.corner, c->b, h); + XCopyArea(dpy, (o == W) ? decorp->wf : + decor->wf, c->pix, gc, 0, 0, visual.border, visual.edge, 0, + visual.corner); + XCopyArea(dpy, (o == W) ? decorp->wl : + decor->wl, c->pix, gc, 0, 0, visual.border, visual.edge, 0, + visual.corner + h - visual.edge); + } - if (h > 0) { val.tile = (o == E) ? decorp->e : decor->e; val.ts_x_origin = c->w - c->b; val.ts_y_origin = 0; XChangeGC(dpy, gc, GCTile | GCTileStipYOrigin | GCTileStipXOrigin , &val); - XFillRectangle(dpy, c->pix, gc, c->w - c->b, visual.corner, c->b, h); - XCopyArea(dpy, (o == E) ? decorp->ef : - decor->ef, c->pix, gc, 0, 0, visual.border, visual.edge, - c->w - visual.border, visual.corner); - XCopyArea(dpy, (o == E) ? decorp->el : - decor->el, c->pix, gc, 0, 0, visual.border, visual.edge, - c->w - visual.border, visual.corner + h - visual.edge); + if (isshaded) { + XFillRectangle(dpy, c->pix, gc, c->w - c->b, visual.border, c->b, c->h - 2 * visual.border); + } else { + XFillRectangle(dpy, c->pix, gc, c->w - c->b, visual.corner, c->b, h); + XCopyArea(dpy, (o == E) ? decorp->ef : + decor->ef, c->pix, gc, 0, 0, visual.border, visual.edge, + c->w - visual.border, visual.corner); + XCopyArea(dpy, (o == E) ? decorp->el : + decor->el, c->pix, gc, 0, 0, visual.border, visual.edge, + c->w - visual.border, visual.corner + h - visual.edge); + } } - - XCopyArea(dpy, (o == NW) ? decorp->nw : - decor->nw, c->pix, gc, 0, 0, visual.corner, visual.corner, 0, 0); - - XCopyArea(dpy, (o == NE) ? decorp->ne : - decor->ne, c->pix, gc, 0, 0, visual.corner, visual.corner, - c->w - visual.corner, 0); - - XCopyArea(dpy, (o == SW) ? decorp->sw : - decor->sw, c->pix, gc, 0, 0, visual.corner, visual.corner, - 0, c->h - visual.corner); - - XCopyArea(dpy, (o == SE) ? decorp->se : - decor->se, c->pix, gc, 0, 0, visual.corner, visual.corner, - c->w - visual.corner, c->h - visual.corner); } /* draw background */ @@ -2377,7 +2405,7 @@ containerdecorate(struct Container *c, struct Column *cdiv, struct Row *rdiv, in XFillRectangle(dpy, c->pix, gc, col->x + col->w, c->b, visual.division, c->h - 2 * c->b); } for (row = col->rows; row != NULL; row = row->next) { - if (col->maxrow == NULL && row->next != NULL) { + if (!isshaded && col->maxrow == NULL && row->next != NULL) { val.fill_style = FillTiled; val.tile = (row == rdiv) ? decorp->s : decor->s; val.ts_x_origin = 0; @@ -2386,7 +2414,6 @@ containerdecorate(struct Container *c, struct Column *cdiv, struct Row *rdiv, in XFillRectangle(dpy, c->pix, gc, col->x, row->y + row->h, col->w, visual.division); } - /* (re)create titlebar pixmap */ if (row->pw != col->w || row->pixbar == None) { if (row->pixbar != None) @@ -2536,6 +2563,7 @@ containermoveresize(struct Container *c) struct Tab *t; struct Dialog *d; int rowy, rowh; + int isshaded; if (c == NULL) return; @@ -2548,6 +2576,7 @@ containermoveresize(struct Container *c) XMoveResizeWindow(dpy, c->curswin[BORDER_NE], c->w - visual.corner, 0, visual.corner, visual.corner); XMoveResizeWindow(dpy, c->curswin[BORDER_SW], 0, c->h - visual.corner, visual.corner, visual.corner); XMoveResizeWindow(dpy, c->curswin[BORDER_SE], c->w - visual.corner, c->h - visual.corner, visual.corner, visual.corner); + isshaded = containerisshaded(c); for (col = c->cols; col != NULL; col = col->next) { rowy = c->b; rowh = max(1, c->h - 2 * c->b - col->nrows * visual.tab); @@ -2558,17 +2587,17 @@ containermoveresize(struct Container *c) XUnmapWindow(dpy, col->div); } for (row = col->rows; row != NULL; row = row->next) { - if (row->next != NULL && col->maxrow == NULL) { + if (!isshaded && row->next != NULL && col->maxrow == NULL) { XMoveResizeWindow(dpy, row->div, col->x, row->y + row->h, col->w, visual.division); XMapWindow(dpy, row->div); } else { XUnmapWindow(dpy, row->div); } - if (col->maxrow == NULL) { /* regular row */ + if (!isshaded && col->maxrow == NULL) { /* regular row */ titlebarmoveresize(row, col->x, row->y, col->w); XMoveResizeWindow(dpy, row->frame, col->x, row->y + visual.tab, col->w, row->h - visual.tab); XMapWindow(dpy, row->frame); - } else if (row == col->maxrow) { /* maximized row */ + } else if (!isshaded && row == col->maxrow) { /* maximized row */ titlebarmoveresize(row, col->x, rowy, col->w); XMoveResizeWindow(dpy, row->frame, col->x, rowy + visual.tab, col->w, rowh); XMapWindow(dpy, row->frame); @@ -2769,6 +2798,36 @@ containermaximize(struct Container *c, int maximize) ewmhsetstate(c); } +/* shade container title bar */ +static void +containershade(struct Container *c, int shade) +{ + void tabfocus(struct Tab *t, int gotodesk); + + if (shade != REMOVE && !c->isshaded) { + c->isshaded = 1; + XDefineCursor(dpy, c->curswin[BORDER_NW], visual.cursors[CURSOR_W]); + XDefineCursor(dpy, c->curswin[BORDER_SW], visual.cursors[CURSOR_W]); + XDefineCursor(dpy, c->curswin[BORDER_NE], visual.cursors[CURSOR_E]); + XDefineCursor(dpy, c->curswin[BORDER_SE], visual.cursors[CURSOR_E]); + } else if (shade != ADD && c->isshaded) { + c->isshaded = 0; + XDefineCursor(dpy, c->curswin[BORDER_NW], visual.cursors[CURSOR_NW]); + XDefineCursor(dpy, c->curswin[BORDER_SW], visual.cursors[CURSOR_SW]); + XDefineCursor(dpy, c->curswin[BORDER_NE], visual.cursors[CURSOR_NE]); + XDefineCursor(dpy, c->curswin[BORDER_SE], visual.cursors[CURSOR_SE]); + } else { + return; + } + containercalccols(c, 1); + containermoveresize(c); + containerredecorate(c, NULL, NULL, 0); + ewmhsetstate(c); + if (c == wm.focused) { + tabfocus(c->selcol->selrow->seltab, 0); + } +} + /* stick a container on the monitor */ static void containerstick(struct Container *c, int stick) @@ -2831,6 +2890,7 @@ containernew(int x, int y, int w, int h) c->ismaximized = 0; c->isminimized = 0; c->issticky = 0; + c->isshaded = 0; c->ishidden = 0; c->layer = 0; c->desk = NULL; @@ -4703,6 +4763,14 @@ mouseresize(struct Container *c, int xroot, int yroot, enum Octant o) Time lasttime; int x, y, dx, dy; + if (containerisshaded(c)) { + if (o & W) { + o = W; + } else if (o & E) { + o = E; + } + } + switch (o) { case NW: curs = visual.cursors[CURSOR_NW]; @@ -5237,6 +5305,8 @@ xeventclientmessage(XEvent *e) for (i = 1; i < 3; i++) { if ((Atom)ev->data.l[i] == atoms[_NET_WM_STATE_FULLSCREEN]) { containerfullscreen(res.c, ev->data.l[0]); + } else if ((Atom)ev->data.l[i] == atoms[_NET_WM_STATE_SHADED]) { + containershade(res.c, ev->data.l[0]); } else if ((Atom)ev->data.l[i] == atoms[_NET_WM_STATE_STICKY]) { containerstick(res.c, ev->data.l[0]); } else if ((Atom)ev->data.l[i] == atoms[_NET_WM_STATE_HIDDEN]) { diff --git a/shodc.c b/shodc.c @@ -20,14 +20,16 @@ enum { /* long list char positions */ enum { - LIST_DIALOG = 0, - LIST_STICKY = 1, - LIST_MAXIMIZED = 2, - LIST_MINIMIZED = 3, - LIST_FULLSCREEN = 4, - LIST_LAYER = 5, - LIST_URGENCY = 6, - LIST_ACTIVE = 7 + LIST_DIALOG, + LIST_STICKY, + LIST_MAXIMIZED, + LIST_MINIMIZED, + LIST_FULLSCREEN, + LIST_SHADED, + LIST_LAYER, + LIST_URGENCY, + LIST_ACTIVE, + LIST_LAST }; /* focus relative direction */ @@ -66,6 +68,7 @@ enum { _NET_WM_STATE_MAXIMIZED_VERT, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_HIDDEN, + _NET_WM_STATE_SHADED, _NET_WM_STATE_FULLSCREEN, _NET_WM_STATE_ABOVE, _NET_WM_STATE_BELOW, @@ -310,6 +313,7 @@ initatoms(void) [_NET_WM_STATE_MAXIMIZED_VERT] = "_NET_WM_STATE_MAXIMIZED_VERT", [_NET_WM_STATE_MAXIMIZED_HORZ] = "_NET_WM_STATE_MAXIMIZED_HORZ", [_NET_WM_STATE_HIDDEN] = "_NET_WM_STATE_HIDDEN", + [_NET_WM_STATE_SHADED] = "_NET_WM_STATE_SHADED", [_NET_WM_STATE_FULLSCREEN] = "_NET_WM_STATE_FULLSCREEN", [_NET_WM_STATE_ABOVE] = "_NET_WM_STATE_ABOVE", [_NET_WM_STATE_BELOW] = "_NET_WM_STATE_BELOW", @@ -480,7 +484,7 @@ longlist(Window win) unsigned int w, h, b, du; int desk; unsigned long i, natoms, l; - char state[] = "--------"; + char state[] = "---------"; char *name; XWMHints *wmhints = NULL; Window *list = NULL; @@ -532,6 +536,8 @@ longlist(Window win) state[LIST_MAXIMIZED] = 'h'; } } else if (as[i] == atoms[_NET_WM_STATE_HIDDEN]) { + state[LIST_SHADED] = 's'; + } else if (as[i] == atoms[_NET_WM_STATE_SHADED]) { state[LIST_MINIMIZED] = 'm'; } else if (as[i] == atoms[_NET_WM_STATE_FULLSCREEN]) { state[LIST_FULLSCREEN] = 'F'; @@ -691,7 +697,7 @@ state(int argc, char *argv[]) action = TOGGLE; state1 = state2 = None; - while ((c = getopt(argc, argv, "ATRabfMms")) != -1) { + while ((c = getopt(argc, argv, "ATRabfMmsy")) != -1) { switch (c) { case 'A': action = ADD; @@ -723,6 +729,10 @@ state(int argc, char *argv[]) state2 = None; break; case 's': + state1 = atoms[_NET_WM_STATE_SHADED]; + state2 = None; + break; + case 'y': state1 = atoms[_NET_WM_STATE_STICKY]; state2 = None; break;