shod

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

commit 70ff3a796becdc442cb4eb30439687d14bc2333e
parent 3fd41bc28a28f75c9d3e9f2dadb7105a910753a6
Author: seninha <lucas@seninha.org>
Date:   Sat, 17 Sep 2022 09:07:25 -0300

add stretched dock feature

Diffstat:
Mshod.1 | 20+++++++++++++++-----
Mshod.h | 2++
Mxdock.c | 198++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
Mxdraw.c | 73++++++++++++++++++++++++++++++++++++++++++++++---------------------------
Mxevents.c | 9+++++++--
5 files changed, 237 insertions(+), 65 deletions(-)

diff --git a/shod.1 b/shod.1 @@ -638,14 +638,21 @@ The background color and border color for the dock. The placement of the dock described with up to two uppercase letters. The first letter .Ns ( Cm "E" Ns , Cm "N" Ns , Cm "W" Ns " or" Cm "S" Ns ) -defines in which edge of the screen (East, North, West or South) to allign the dock. +defines in which edge of the monitor (East, North, West or South) to allign the dock. The optional second letter -.Ns (also Cm "E" Ns , Cm "N" Ns , Cm "W" Ns " or" Cm "S" Ns ) -defines in which corner of that edge of the screen to allign the dock. +.Ns ( Cm "E" Ns , Cm "N" Ns , Cm "W" Ns , Cm "S" Ns , Cm "C" Ns " or" Cm "F" Ns ) +defines in which corner of that edge of the monitor to allign the dock; an +.Cm "C" +means that the dock should centered on that edge; an +.Cm "F" +means that the dock should stretched to fill that edge. If no second letter is supplied, the dock is centered on that edge. For example, for a value of .Cm NE , -a horizontal dock will be placed in the north edge of the screen, alligned to the northeast corner. +a horizontal dock will be placed in the north edge of the monitor, alligned to the northeast corner. +And for a value of +.Cm EF , +a vertical dock will be placed in the east edge of the monitor, stretched to the full hight of the monitor. .It Ic "shod.dockWidth" The width (for vertical docks) or height (for horizontal docks) of the dock in pixels. @@ -717,7 +724,10 @@ and .Cm sticky . .It Ic shod.CLASS.NAME.ROLE.dockpos Define the position in the dock of a docked application matching the given class, name and role. -Its value should be a number, starting from position 0. +Its value should be a number, starting from position 1. +If the value is followed by an asterisk +.Pq "*" , +the docked application will be stretched to fill the dock. .El .Sh ENVIRONMENT The following environment variables affect the execution of diff --git a/shod.h b/shod.h @@ -495,6 +495,8 @@ struct Dockapp { int x, y, w, h; /* dockapp position and size */ int ignoreunmap; /* number of unmap requests to ignore */ int dockpos; /* position of the dockapp in the dock */ + int extend; /* whether to maximize dockapp size to fit dock */ + int slotsize; /* size of the slot the dockapp is in */ }; struct Splash { diff --git a/xdock.c b/xdock.c @@ -26,67 +26,70 @@ dockappnew(Window win, int w, int h, int dockpos, int ignoreunmap) .w = w, .h = h, .ignoreunmap = ignoreunmap, - .dockpos = dockpos, + .dockpos = abs(dockpos), + .extend = dockpos < 0, }; TAILQ_FOREACH_REVERSE(prev, &dock.dappq, Queue, entry) - if (((struct Dockapp *)prev)->dockpos <= dockpos) + if (((struct Dockapp *)prev)->dockpos <= dapp->dockpos) break; if (prev != NULL) { TAILQ_INSERT_AFTER(&dock.dappq, prev, (struct Object *)dapp, entry); } else { TAILQ_INSERT_HEAD(&dock.dappq, (struct Object *)dapp, entry); } + switch (config.dockgravity[0]) { + case 'N': + dapp->slotsize = dapp->w / config.dockspace + (dapp->w % config.dockspace ? 1 : 0); + dapp->h = min(config.dockwidth, dapp->h); + break; + case 'S': + dapp->slotsize = dapp->w / config.dockspace + (dapp->w % config.dockspace ? 1 : 0); + dapp->h = min(config.dockwidth, dapp->h); + break; + case 'W': + dapp->slotsize = dapp->h / config.dockspace + (dapp->h % config.dockspace ? 1 : 0); + dapp->w = min(config.dockwidth, dapp->w); + break; + case 'E': + default: + dapp->slotsize = dapp->h / config.dockspace + (dapp->h % config.dockspace ? 1 : 0); + dapp->w = min(config.dockwidth, dapp->w); + break; + } + dapp->slotsize *= config.dockspace; } /* update dock position; create it, if necessary */ void -dockupdate(void) +dockupdateresizeable(void) { struct Object *p; struct Dockapp *dapp; - Window wins[2]; int size; - int n; size = 0; TAILQ_FOREACH(p, &dock.dappq, entry) { dapp = (struct Dockapp *)p; switch (config.dockgravity[0]) { case 'N': - dapp->x = DOCKBORDER + size; - dapp->y = DOCKBORDER; - n = dapp->w / config.dockspace + (dapp->w % config.dockspace ? 1 : 0); - n *= config.dockspace; - dapp->x += max(0, (n - dapp->w) / 2); - dapp->y += max(0, (config.dockwidth - dapp->h) / 2); + dapp->x = DOCKBORDER + size + max(0, (dapp->slotsize - dapp->w) / 2); + dapp->y = DOCKBORDER + max(0, (config.dockwidth - dapp->h) / 2); break; case 'S': - dapp->x = DOCKBORDER + size; - dapp->y = DOCKBORDER; - n = dapp->w / config.dockspace + (dapp->w % config.dockspace ? 1 : 0); - n *= config.dockspace; - dapp->x += max(0, (n - dapp->w) / 2); - dapp->y += max(0, (config.dockwidth - dapp->h) / 2); + dapp->x = DOCKBORDER + size + max(0, (dapp->slotsize - dapp->w) / 2); + dapp->y = DOCKBORDER + max(0, (config.dockwidth - dapp->h) / 2); break; case 'W': - dapp->x = DOCKBORDER; - dapp->y = DOCKBORDER + size; - n = dapp->h / config.dockspace + (dapp->h % config.dockspace ? 1 : 0); - n *= config.dockspace; - dapp->x += max(0, (config.dockwidth - dapp->w) / 2); - dapp->y += max(0, (n - dapp->h) / 2); + dapp->x = DOCKBORDER + max(0, (config.dockwidth - dapp->w) / 2); + dapp->y = DOCKBORDER + size + max(0, (dapp->slotsize - dapp->h) / 2); break; case 'E': default: - dapp->y = DOCKBORDER + size; - dapp->x = DOCKBORDER; - n = dapp->h / config.dockspace + (dapp->h % config.dockspace ? 1 : 0); - n *= config.dockspace; - dapp->x += max(0, (config.dockwidth - dapp->w) / 2); - dapp->y += max(0, (n - dapp->h) / 2); + dapp->x = DOCKBORDER + max(0, (config.dockwidth - dapp->w) / 2); + dapp->y = DOCKBORDER + size + max(0, (dapp->slotsize - dapp->h) / 2); break; } - size += n; + size += dapp->slotsize; } if (size == 0) { XUnmapWindow(dpy, dock.win); @@ -118,6 +121,10 @@ dockupdate(void) } if (config.dockgravity[0] == 'N' || config.dockgravity[0] == 'S') { switch (config.dockgravity[1]) { + case 'F': + dock.x = 0; + dock.w = TAILQ_FIRST(&wm.monq)->mw; + break; case 'W': dock.w = min(size, TAILQ_FIRST(&wm.monq)->mw); dock.x = 0; @@ -133,6 +140,10 @@ dockupdate(void) } } else if (config.dockgravity[0] != '\0') { switch (config.dockgravity[1]) { + case 'F': + dock.h = TAILQ_FIRST(&wm.monq)->mh; + dock.y = 0; + break; case 'N': dock.h = min(size, TAILQ_FIRST(&wm.monq)->mh); dock.y = 0; @@ -149,8 +160,133 @@ dockupdate(void) } TAILQ_FOREACH(p, &dock.dappq, entry) { dapp = (struct Dockapp *)p; - XMoveWindow(dpy, dapp->obj.win, dapp->x, dapp->y); + XMoveResizeWindow(dpy, dapp->obj.win, dapp->x, dapp->y, dapp->w, dapp->h); + winnotify(dapp->obj.win, dock.x + dapp->x, dock.y + dapp->y, dapp->w, dapp->h); + } +} + +/* update dock position; create it, if necessary */ +void +dockupdatefull(void) +{ + struct Object *p; + struct Dockapp *dapp; + int part, nextend, size; + int i, n; + + if (TAILQ_FIRST(&dock.dappq) == NULL) { + XUnmapWindow(dpy, dock.win); + dock.mapped = 0; + return; + } + dock.mapped = 1; + switch (config.dockgravity[0]) { + case 'N': + dock.x = 0; + dock.y = 0; + dock.w = TAILQ_FIRST(&wm.monq)->mw; + dock.h = config.dockwidth; + part = dock.w; + break; + case 'S': + dock.x = 0; + dock.y = TAILQ_FIRST(&wm.monq)->mh - config.dockwidth; + dock.w = TAILQ_FIRST(&wm.monq)->mw; + dock.h = config.dockwidth; + part = dock.w; + break; + case 'W': + dock.x = 0; + dock.y = 0; + dock.w = config.dockwidth; + dock.h = TAILQ_FIRST(&wm.monq)->mh; + part = dock.h; + break; + case 'E': + default: + dock.x = TAILQ_FIRST(&wm.monq)->mw - config.dockwidth; + dock.y = 0; + dock.w = config.dockwidth; + dock.h = TAILQ_FIRST(&wm.monq)->mh; + part = dock.h; + break; + } + nextend = 0; + size = 0; + TAILQ_FOREACH(p, &dock.dappq, entry) { + dapp = (struct Dockapp *)p; + if (dapp->extend) { + nextend++; + } else { + size += dapp->slotsize; + } + } + part = max(part - size, 1); + if (nextend > 0) + part /= nextend; + i = 0; + size = 0; + TAILQ_FOREACH(p, &dock.dappq, entry) { + dapp = (struct Dockapp *)p; + switch (config.dockgravity[0]) { + case 'N': + if (dapp->extend) { + dapp->w = max(1, (i + 1) * part - i * part); + n = dapp->w; + } else { + n = dapp->slotsize; + } + dapp->x = size + max(0, (n - dapp->w) / 2); + dapp->y = DOCKBORDER + max(0, (config.dockwidth - dapp->h) / 2); + break; + case 'S': + if (dapp->extend) { + dapp->w = max(1, (i + 1) * part - i * part); + n = dapp->w; + } else { + n = dapp->slotsize; + } + dapp->x = size + max(0, (n - dapp->w) / 2); + dapp->y = DOCKBORDER + max(0, (config.dockwidth - dapp->h) / 2); + break; + case 'W': + if (dapp->extend) { + dapp->h = max(1, (i + 1) * part - i * part); + n = dapp->h; + } else { + n = dapp->slotsize; + } + dapp->x = DOCKBORDER + max(0, (config.dockwidth - dapp->w) / 2); + dapp->y = size + max(0, (n - dapp->h) / 2); + break; + case 'E': + default: + if (dapp->extend) { + dapp->h = max(1, (i + 1) * part - i * part); + n = dapp->h; + } else { + n = dapp->slotsize; + } + dapp->x = DOCKBORDER + max(0, (config.dockwidth - dapp->w) / 2); + dapp->y = size + max(0, (n - dapp->h) / 2); + break; + } + XMoveResizeWindow(dpy, dapp->obj.win, dapp->x, dapp->y, dapp->w, dapp->h); winnotify(dapp->obj.win, dock.x + dapp->x, dock.y + dapp->y, dapp->w, dapp->h); + size += n; + } +} + +/* update dock position; create it, if necessary */ +void +dockupdate(void) +{ + Window wins[2]; + + if (config.dockgravity[0] != '\0' && (config.dockgravity[1] == 'F' || config.dockgravity[1] == 'f')) { + dockupdatefull(); + } else { + dockupdateresizeable(); } dockdecorate(); wins[0] = wm.layerwins[LAYER_DOCK]; diff --git a/xdraw.c b/xdraw.c @@ -2,8 +2,6 @@ #include "shod.h" -#define DOCK_BORDER_THICKNESS 1 - static GC gc; static struct Theme { XftFont *font; @@ -483,15 +481,37 @@ drawdock(Pixmap pix, int w, int h) if (pix == None || w <= 0 || h <= 0) return; - recs = ecalloc(DOCK_BORDER_THICKNESS * 3, sizeof(*recs)); + recs = ecalloc(DOCKBORDER * 3, sizeof(*recs)); val.foreground = theme.dock[COLOR_DEF]; XChangeGC(dpy, gc, GCForeground, &val); XFillRectangle(dpy, pix, gc, 0, 0, w, h); + val.foreground = theme.dock[COLOR_ALT]; + XChangeGC(dpy, gc, GCForeground, &val); + + if (config.dockgravity[0] != '\0' && (config.dockgravity[1] == 'F' || config.dockgravity[1] == 'f')) { + switch (config.dockgravity[0]) { + case 'N': + XFillRectangle(dpy, pix, gc, 0, h - DOCKBORDER, w, 1); + break; + case 'S': + XFillRectangle(dpy, pix, gc, 0, 0, w, 1); + break; + case 'W': + XFillRectangle(dpy, pix, gc, w - DOCKBORDER, 0, 1, h); + break; + default: + case 'E': + XFillRectangle(dpy, pix, gc, 0, 0, 1, h); + break; + } + return; + } + switch (config.dockgravity[0]) { case 'N': - for(i = 0; i < DOCK_BORDER_THICKNESS; i++) { + for(i = 0; i < DOCKBORDER; i++) { recs[i * 3 + 0] = (XRectangle){ .x = i, .y = 0, @@ -513,7 +533,7 @@ drawdock(Pixmap pix, int w, int h) } break; case 'W': - for(i = 0; i < DOCK_BORDER_THICKNESS; i++) { + for(i = 0; i < DOCKBORDER; i++) { recs[i * 3 + 0] = (XRectangle){ .x = 0, .y = i, @@ -534,54 +554,53 @@ drawdock(Pixmap pix, int w, int h) }; } break; - case 'E': - for(i = 0; i < DOCK_BORDER_THICKNESS; i++) { + case 'S': + for(i = 0; i < DOCKBORDER; i++) { recs[i * 3 + 0] = (XRectangle){ - .x = 0, - .y = i, - .width = w, - .height = 1 - }; - recs[i * 3 + 1] = (XRectangle){ .x = i, .y = 0, .width = 1, .height = h }; - recs[i * 3 + 2] = (XRectangle){ + recs[i * 3 + 1] = (XRectangle){ .x = 0, - .y = h - 1 - i, + .y = i, .width = w, .height = 1 }; - } - break; - case 'S': - for(i = 0; i < DOCK_BORDER_THICKNESS; i++) { - recs[i * 3 + 0] = (XRectangle){ - .x = i, + recs[i * 3 + 2] = (XRectangle){ + .x = w - 1 - i, .y = 0, .width = 1, .height = h }; - recs[i * 3 + 1] = (XRectangle){ + } + break; + default: + case 'E': + for(i = 0; i < DOCKBORDER; i++) { + recs[i * 3 + 0] = (XRectangle){ .x = 0, .y = i, .width = w, .height = 1 }; - recs[i * 3 + 2] = (XRectangle){ - .x = w - 1 - i, + recs[i * 3 + 1] = (XRectangle){ + .x = i, .y = 0, .width = 1, .height = h }; + recs[i * 3 + 2] = (XRectangle){ + .x = 0, + .y = h - 1 - i, + .width = w, + .height = 1 + }; } break; } - val.foreground = theme.dock[COLOR_ALT]; - XChangeGC(dpy, gc, GCForeground, &val); - XFillRectangles(dpy, pix, gc, recs, DOCK_BORDER_THICKNESS * 3); + XFillRectangles(dpy, pix, gc, recs, DOCKBORDER * 3); free(recs); } diff --git a/xevents.c b/xevents.c @@ -339,6 +339,7 @@ getwintype(Window win, Window *leader, struct Tab **tab, int *state) /* rules for identifying windows */ enum { CLASS = 0, INSTANCE = 1, ROLE = 2 }; char *rule[] = { "_", "_", "_" }; + char *endp; struct MwmHints *mwmhints; XClassHint classh; @@ -427,8 +428,12 @@ getwintype(Window win, Window *leader, struct Tab **tab, int *state) /* check for dockapp position */ (void)snprintf(buf, NAMEMAXLEN, "shod.%s.%s.%s.dockpos", rule[CLASS], rule[INSTANCE], rule[ROLE]); if (XrmGetResource(xdb, buf, "*", &ds, &xval) == True) { - if ((n = strtol(xval.addr, NULL, 10)) >= 0 && n < INT_MAX) { - *state = n; + if ((n = strtol(xval.addr, &endp, 10)) >= 0 && n < INT_MAX) { + if (*endp == '*') { + *state = -n; + } else { + *state = n; + } } } }