shod

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

commit e79be7617b0bb040138bb79184d3b7e0142a2db0
parent 5a48a8a830b1f2086901ecf8056f6525525b5d90
Author: Lucas de Sena <lucas@seninha.org>
Date:   Mon, 16 Jan 2023 21:24:09 -0300

add shodc cycle

Diffstat:
Mshod.1 | 58+++++++++++++++++++++++++++++++++-------------------------
Mshod.c | 7++-----
Mshodc.c | 33+++++++++++++++++++++++++++++++++
Mxevents.c | 41+++++++++++++----------------------------
Mxutil.c | 1+
Mxutil.h | 1+
6 files changed, 83 insertions(+), 58 deletions(-)

diff --git a/shod.1 b/shod.1 @@ -7,7 +7,7 @@ .Nd mouse-focused window manager .Sh SYNOPSIS .Nm shod -.Op Fl cdhst +.Op Fl cdhs .Op Fl m Ar keysym .Op Ar file .Pp @@ -15,6 +15,11 @@ .Cm close .Op Ar win_id .Nm shodc +.Cm cycle +.Op Fl s +.Op Fl a Ar altkey +.Op Fl t Ar tabkey +.Nm shodc .Cm desk .Nm shodc .Cm focus @@ -119,9 +124,6 @@ or on most systems). .It Fl s Use sloppy focus rather than click-to-focus. -.It Fl t -Disable container cycling (aka -.Dq "alt-tab" No ). .El .Pp .Nm shodc @@ -140,6 +142,33 @@ The .Cm close operation closes a window whose ID is provided as argument. If no argument is provided, close the active window. +.Ss Cycle containers +The +.Cm cycle +operation cycles through the open containers on the current desktop. +This cycling is generally called +.Qq "Alt-Tab" +and is initiated by pressing a key (usually +.Qq "Tab" ) +while a modifier key (usually +.Qq "Alt_L" ) +is pressed. +If the +.Qq "Shift" +modifier is also pressed, the cycling is performed in the opposite direction. +.Pp The options are as follows. +.Bl -tag -width Ds +.It Fl a Ar altkey +Use the key +.Ar altkey +as Alt. +.It Fl s +Initiate the cycling in the opposite direction. +.It Fl t Ar tabkey +Use the key +.Ar tabkey +as Tab. +.El .Ss List desktops The .Cm desks @@ -491,27 +520,6 @@ or undoes this state. Each title bar has a right button. Clicking on the right title-bar button with the first mouse button closes the focused client or its top dialog. -.Pp -Containers can be cycled using the key provided by the -.Fl m -option -.No ( Cm Alt_L -by default) followed by the -.Cm Tab -key. -The -.Cm Tab -key can be further modified by -.Cm Shift -to cycle in the oposite direction. -This mechanism is usually called -.Dq "alt-tab" -because of the key combination that usually triggers it. -This mechanism can be turned off by invoking -.Nm shod -with the -.Fl t -command-line option. .Ss Dialog Windows that are transient for another managed windows (called its leader) are mapped in the center of the leader. diff --git a/shod.c b/shod.c @@ -35,7 +35,7 @@ struct Dock dock; static void usage(void) { - (void)fprintf(stderr, "usage: shod [-cdhst] [-m modifier] [file]\n"); + (void)fprintf(stderr, "usage: shod [-cdhs] [-m modifier] [file]\n"); exit(1); } @@ -119,7 +119,7 @@ getoptions(int argc, char *argv[]) { int c; - while ((c = getopt(argc, argv, "cdhm:st")) != -1) { + while ((c = getopt(argc, argv, "cdhm:s")) != -1) { switch (c) { case 'c': config.honorconfig = 1; @@ -137,9 +137,6 @@ getoptions(int argc, char *argv[]) case 's': config.sloppyfocus = 1; break; - case 't': - config.disablealttab = 1; - break; default: usage(); break; diff --git a/shodc.c b/shodc.c @@ -589,6 +589,37 @@ state(int argc, char *argv[]) clientmsg(win, atoms[_NET_WM_STATE], action, state1, state2, DIRECT_ACTION, 0); } +/* cycle containers */ +static void +cycle(int argc, char *argv[]) +{ + KeyCode alt, tab; + KeySym ksym; + int c, shift; + + alt = XKeysymToKeycode(dpy, XK_Alt_L); + tab = XKeysymToKeycode(dpy, XK_Tab); + shift = 0; + while ((c = getopt(argc, argv, "a:st:")) != -1) { + switch (c) { + case 'a': + if ((ksym = XStringToKeysym(optarg)) == NoSymbol) + errx(1, "%s: unknown key", optarg); + alt = XKeysymToKeycode(dpy, ksym); + break; + case 's': + shift = 1; + break; + case 't': + if ((ksym = XStringToKeysym(optarg)) == NoSymbol) + errx(1, "%s: unknown key", optarg); + tab = XKeysymToKeycode(dpy, ksym); + break; + } + } + clientmsg(None, atoms[_SHOD_CYCLE], alt, tab, shift, 0, 0); +} + /* shodc: remote controller for shod */ int main(int argc, char *argv[]) @@ -615,6 +646,8 @@ main(int argc, char *argv[]) sendto(argc - 1, argv + 1); else if (strcmp(argv[1], "state") == 0) state(argc - 1, argv + 1); + else if (strcmp(argv[1], "cycle") == 0) + cycle(argc - 1, argv + 1); else usage(); diff --git a/xevents.c b/xevents.c @@ -699,52 +699,48 @@ manage(Window win, XRectangle rect, int ignoreunmap) /* perform container switching (aka alt-tab) */ static void -alttab(XEvent *e) +alttab(KeyCode alt, KeyCode tab, int shift) { struct Container *c, *prevfocused; XEvent ev; - int raised; prevfocused = wm.focused; if ((c = TAILQ_FIRST(&wm.focusq)) == NULL) return; - ev = *e; - raised = 0; if (XGrabKeyboard(dpy, root, True, GrabModeAsync, GrabModeAsync, CurrentTime) != GrabSuccess) goto done; if (XGrabPointer(dpy, root, False, 0, GrabModeAsync, GrabModeAsync, None, None, CurrentTime) != GrabSuccess) goto done; - do { + containerbacktoplace(c, 0); + c = containerraisetemp(c, shift); + while (!XMaskEvent(dpy, ALTTABMASK, &ev)) { switch (ev.type) { case Expose: if (ev.xexpose.count == 0) copypixmap(ev.xexpose.window); break; case KeyPress: - if (ev.xkey.keycode == config.tabkeycode && isvalidstate(ev.xkey.state)) { - containerbacktoplace(c, raised); + if (ev.xkey.keycode == tab && isvalidstate(ev.xkey.state)) { + containerbacktoplace(c, 1); c = containerraisetemp(c, isshiftstate(ev.xkey.state)); - raised = 1; } else if (!isvalidstate(ev.xkey.state)) { goto done; } break; case KeyRelease: - if (ev.xkey.keycode == config.altkeycode || !isvalidstate(ev.xkey.state)) + if (ev.xkey.keycode == config.altkeycode || ev.xkey.keycode == alt || !isvalidstate(ev.xkey.state)) goto done; break; } - } while (!XMaskEvent(dpy, ALTTABMASK, &ev)); + } done: XUngrabKeyboard(dpy, CurrentTime); XUngrabPointer(dpy, CurrentTime); if (c == NULL) return; - if (raised) { - containerbacktoplace(c, raised); - wm.focused = prevfocused; - tabfocus(c->selcol->selrow->seltab, 0); - } + containerbacktoplace(c, 1); + wm.focused = prevfocused; + tabfocus(c->selcol->selrow->seltab, 0); } /* detach tab from window with mouse */ @@ -1395,6 +1391,8 @@ xeventclientmessage(XEvent *e) } if (ev->message_type == atoms[_NET_CURRENT_DESKTOP]) { deskfocus(wm.selmon, ev->data.l[0]); + } else if (ev->message_type == atoms[_SHOD_CYCLE]) { + alttab(ev->data.l[0], ev->data.l[1], ev->data.l[2]); } else if (ev->message_type == atoms[_NET_SHOWING_DESKTOP]) { if (ev->data.l[0]) { deskshow(1); @@ -1663,9 +1661,6 @@ xeventkeypress(XEvent *e) XKeyPressedEvent *ev; ev = &e->xkey; - if (!config.disablealttab && ev->keycode == config.tabkeycode) { - alttab(e); - } if (ev->window == wm.wmcheckwin) { e->xkey.window = root; XSendEvent(dpy, root, False, KeyPressMask, e); @@ -1832,20 +1827,10 @@ setmod(void) warnx("could not get keycode from keysym"); return; } - if ((config.tabkeycode = XKeysymToKeycode(dpy, config.tabkeysym)) == 0) { - warnx("could not get keycode from keysym"); - return; - } if ((config.modifier = XkbKeysymToModifiers(dpy, config.altkeysym)) == 0) { warnx("could not get modifier from keysym"); return; } - if (config.disablealttab) - return; - XUngrabKey(dpy, config.tabkeycode, config.modifier, root); - XUngrabKey(dpy, config.tabkeycode, config.modifier | config.shift, root); - XGrabKey(dpy, config.tabkeycode, config.modifier, root, False, GrabModeAsync, GrabModeAsync); - XGrabKey(dpy, config.tabkeycode, config.modifier | config.shift, root, False, GrabModeAsync, GrabModeAsync); } void (*xevents[LASTEvent])(XEvent *) = { diff --git a/xutil.c b/xutil.c @@ -55,6 +55,7 @@ static char *atomnames[ATOM_LAST] = { [_NET_FRAME_EXTENTS] = "_NET_FRAME_EXTENTS", [_NET_WM_FULL_PLACEMENT] = "_NET_WM_FULL_PLACEMENT", [_MOTIF_WM_HINTS] = "_MOTIF_WM_HINTS", + [_SHOD_CYCLE] = "_SHOD_CYCLE", [_SHOD_GROUP_TAB] = "_SHOD_GROUP_TAB", [_SHOD_GROUP_CONTAINER] = "_SHOD_GROUP_CONTAINER", [_SHOD_CONTAINER_LIST] = "_SHOD_CONTAINER_LIST", diff --git a/xutil.h b/xutil.h @@ -66,6 +66,7 @@ enum { _MOTIF_WM_HINTS, /* shod atoms */ + _SHOD_CYCLE, _SHOD_GROUP_TAB, _SHOD_GROUP_CONTAINER, _SHOD_CONTAINER_LIST,