From dc4e535b253dcb38605443508d17cda2d8323d01 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Tue, 15 Nov 2022 10:31:15 +0100 Subject: [PATCH 1/3] tagpreview: make sure that tagwin is created following configure notify requests ref. #308 --- dwm.c | 6 +-- patch/bar_tagpreview.c | 119 +++++++++++++++++++++++------------------ patch/bar_tagpreview.h | 4 +- 3 files changed, 73 insertions(+), 56 deletions(-) diff --git a/dwm.c b/dwm.c index 2661987..60b25ea 100644 --- a/dwm.c +++ b/dwm.c @@ -1483,6 +1483,9 @@ configurenotify(XEvent *e) #endif // !FAKEFULLSCREEN_PATCH for (bar = m->bar; bar; bar = bar->next) XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh); + #if BAR_TAGPREVIEW_PATCH + createpreview(m); + #endif // BAR_TAGPREVIEW_PATCH } focus(NULL); arrange(NULL); @@ -3770,9 +3773,6 @@ setup(void) updatebars(); updatestatus(); - #if BAR_TAGPREVIEW_PATCH - updatepreview(); - #endif // BAR_TAGPREVIEW_PATCH /* supporting window for NetWMCheck */ wmcheckwin = XCreateSimpleWindow(dpy, root, 0, 0, 1, 1, 0, 0, 0); diff --git a/patch/bar_tagpreview.c b/patch/bar_tagpreview.c index c92d05f..27731b0 100644 --- a/patch/bar_tagpreview.c +++ b/patch/bar_tagpreview.c @@ -1,16 +1,43 @@ #include void -showtagpreview(int tag, int x, int y) +createpreview(Monitor *m) { - if (selmon->tagmap[tag]) { - XSetWindowBackgroundPixmap(dpy, selmon->tagwin, selmon->tagmap[tag]); - XCopyArea(dpy, selmon->tagmap[tag], selmon->tagwin, drw->gc, 0, 0, selmon->mw / scalepreview, selmon->mh / scalepreview, 0, 0); - XMoveWindow(dpy, selmon->tagwin, x, y); - XSync(dpy, False); - XMapWindow(dpy, selmon->tagwin); - } else - XUnmapWindow(dpy, selmon->tagwin); + if (m->tagwin) { + XMoveResizeWindow( + dpy, m->tagwin, + m->mx, + m->bar->by + bh, + m->mw / scalepreview, + m->mh / scalepreview + ); + return; + } + + XSetWindowAttributes wa = { + .override_redirect = True, + #if BAR_ALPHA_PATCH + .background_pixel = 0, + .border_pixel = 0, + .colormap = cmap, + #else + .background_pixmap = ParentRelative, + #endif // BAR_ALPHA_PATCH + .event_mask = ButtonPressMask|ExposureMask + }; + + m->tagwin = XCreateWindow(dpy, root, m->wx, m->bar->by + bh, m->mw / scalepreview, m->mh / scalepreview, 0, + #if BAR_ALPHA_PATCH + depth, CopyFromParent, visual, + CWOverrideRedirect|CWBackPixel|CWBorderPixel|CWColormap|CWEventMask, &wa + #else + DefaultDepth(dpy, screen), CopyFromParent, DefaultVisual(dpy, screen), + CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa + #endif // BAR_ALPHA_PATCH + ); + XDefineCursor(dpy, m->tagwin, cursor[CurNormal]->cursor); + XMapRaised(dpy, m->tagwin); + XUnmapWindow(dpy, m->tagwin); } void @@ -20,6 +47,24 @@ hidetagpreview(Monitor *m) XUnmapWindow(dpy, m->tagwin); } +void +showtagpreview(int tag, int x, int y) +{ + Monitor *m = selmon; + + if (!m->tagwin) + return; + + if (m->tagmap[tag]) { + XSetWindowBackgroundPixmap(dpy, m->tagwin, m->tagmap[tag]); + XCopyArea(dpy, m->tagmap[tag], m->tagwin, drw->gc, 0, 0, m->mw / scalepreview, m->mh / scalepreview, 0, 0); + XMoveWindow(dpy, m->tagwin, x, y); + XSync(dpy, False); + XMapWindow(dpy, m->tagwin); + } else + XUnmapWindow(dpy, m->tagwin); +} + void tagpreviewswitchtag(void) { @@ -27,14 +72,18 @@ tagpreviewswitchtag(void) unsigned int occ = 0; Client *c; Imlib_Image image; + Monitor *m = selmon; - for (c = selmon->clients; c; c = c->next) + if (!m->tagwin) + createpreview(m); + + for (c = m->clients; c; c = c->next) occ |= c->tags; for (i = 0; i < NUMTAGS; i++) { - if (selmon->tagset[selmon->seltags] & 1 << i) { - if (selmon->tagmap[i] != 0) { - XFreePixmap(dpy, selmon->tagmap[i]); - selmon->tagmap[i] = 0; + if (m->tagset[m->seltags] & 1 << i) { + if (m->tagmap[i] != 0) { + XFreePixmap(dpy, m->tagmap[i]); + m->tagmap[i] = 0; } if (occ & 1 << i) { image = imlib_create_image(sw, sh); @@ -48,48 +97,16 @@ tagpreviewswitchtag(void) imlib_context_set_visual(DefaultVisual(dpy, screen)); #endif // BAR_ALPHA_PATCH imlib_context_set_drawable(root); - imlib_copy_drawable_to_image(0, selmon->mx, selmon->my, selmon->mw ,selmon->mh, 0, 0, 1); + imlib_copy_drawable_to_image(0, m->mx, m->my, m->mw ,m->mh, 0, 0, 1); #if BAR_ALPHA_PATCH - selmon->tagmap[i] = XCreatePixmap(dpy, selmon->tagwin, selmon->mw / scalepreview, selmon->mh / scalepreview, depth); + m->tagmap[i] = XCreatePixmap(dpy, m->tagwin, m->mw / scalepreview, m->mh / scalepreview, depth); #else - selmon->tagmap[i] = XCreatePixmap(dpy, selmon->tagwin, selmon->mw / scalepreview, selmon->mh / scalepreview, DefaultDepth(dpy, screen)); + m->tagmap[i] = XCreatePixmap(dpy, m->tagwin, m->mw / scalepreview, m->mh / scalepreview, DefaultDepth(dpy, screen)); #endif // BAR_ALPHA_PATCH - imlib_context_set_drawable(selmon->tagmap[i]); - imlib_render_image_part_on_drawable_at_size(0, 0, selmon->mw, selmon->mh, 0, 0, selmon->mw / scalepreview, selmon->mh / scalepreview); + imlib_context_set_drawable(m->tagmap[i]); + imlib_render_image_part_on_drawable_at_size(0, 0, m->mw, m->mh, 0, 0, m->mw / scalepreview, m->mh / scalepreview); imlib_free_image(); } } } } - -void -updatepreview(void) -{ - Monitor *m; - - XSetWindowAttributes wa = { - .override_redirect = True, - #if BAR_ALPHA_PATCH - .background_pixel = 0, - .border_pixel = 0, - .colormap = cmap, - #else - .background_pixmap = ParentRelative, - #endif // BAR_ALPHA_PATCH - .event_mask = ButtonPressMask|ExposureMask - }; - for (m = mons; m; m = m->next) { - m->tagwin = XCreateWindow(dpy, root, m->wx, m->bar->by + bh, m->mw / 4, m->mh / 4, 0, - #if BAR_ALPHA_PATCH - depth, CopyFromParent, visual, - CWOverrideRedirect|CWBackPixel|CWBorderPixel|CWColormap|CWEventMask, &wa - #else - DefaultDepth(dpy, screen), CopyFromParent, DefaultVisual(dpy, screen), - CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa - #endif // BAR_ALPHA_PATCH - ); - XDefineCursor(dpy, m->tagwin, cursor[CurNormal]->cursor); - XMapRaised(dpy, m->tagwin); - XUnmapWindow(dpy, m->tagwin); - } -} diff --git a/patch/bar_tagpreview.h b/patch/bar_tagpreview.h index 8129187..44be36d 100644 --- a/patch/bar_tagpreview.h +++ b/patch/bar_tagpreview.h @@ -1,4 +1,4 @@ -static void showtagpreview(int tag, int x, int y); +static void createpreview(Monitor *m); static void hidetagpreview(Monitor *m); +static void showtagpreview(int tag, int x, int y); static void tagpreviewswitchtag(void); -static void updatepreview(void); From 4c32f6f52d024c5bea66f00ee88ffd05c7676345 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Thu, 8 Dec 2022 10:44:07 +0100 Subject: [PATCH 2/3] Bump to 89f9905. grabkeys: Avoid missing events when a keysym maps to multiple keycodes It's not uncommon for one keysym to map to multiple keycodes. For example, the "play" button on my keyboard sends keycode 172, but my bluetooth headphones send keycode 208, both of which map back to XF86AudioPlay: % xmodmap -pke | grep XF86AudioPlay keycode 172 = XF86AudioPlay XF86AudioPause XF86AudioPlay XF86AudioPause keycode 208 = XF86AudioPlay NoSymbol XF86AudioPlay keycode 215 = XF86AudioPlay NoSymbol XF86AudioPlay This is a problem because the current code only grabs a single one of these keycodes, which means that events for any other keycode also mapping to the bound keysym will not be handled by dwm. In my case, this means that binding XF86AudioPlay does the right thing and correctly handles my keyboard's keys, but does nothing on my headphones. I'm not the only person affected by this, there are other reports[0]. In order to fix this, we look at the mappings between keycodes and keysyms at grabkeys() time and pick out all matching keycodes rather than just the first one. The keypress() side of this doesn't need any changes because the keycode gets converted back to a canonical keysym before any action is taken. 0: https://github.com/cdown/dwm/issues/11 Ref. https://git.suckless.org/dwm/commit/89f9905714c1c1b2e8b09986dfbeca15b68d8af8.html --- README.md | 2 +- dwm.c | 38 ++++++++++++++++++++++++++------------ 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 444c9dd..24b0d6a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -This dwm 6.4 (ba56fe9, 2022-10-28) side project has a different take on dwm patching. It uses preprocessor directives to decide whether or not to include a patch during build time. Essentially this means that this build, for better or worse, contains both the patched _and_ the original code. The aim being that you can select which patches to include and the build will contain that code and nothing more. Due to the complexity of some of the patches dwm-flexipatch has diverged from mainstream dwm by making some core patches non-optional for maintenance reasons. For the classic dwm-flexipatch build refer to branch [dwm-flexipatch-1.0](https://github.com/bakkeby/dwm-flexipatch/tree/dwm-flexipatch-1.0). +This dwm 6.4 (89f9905, 2022-12-07) side project has a different take on dwm patching. It uses preprocessor directives to decide whether or not to include a patch during build time. Essentially this means that this build, for better or worse, contains both the patched _and_ the original code. The aim being that you can select which patches to include and the build will contain that code and nothing more. Due to the complexity of some of the patches dwm-flexipatch has diverged from mainstream dwm by making some core patches non-optional for maintenance reasons. For the classic dwm-flexipatch build refer to branch [dwm-flexipatch-1.0](https://github.com/bakkeby/dwm-flexipatch/tree/dwm-flexipatch-1.0). For example to include the `alpha` patch then you would only need to flip this setting from 0 to 1 in [patches.h](https://github.com/bakkeby/dwm-flexipatch/blob/master/patches.def.h): ```c diff --git a/dwm.c b/dwm.c index 60b25ea..7dbf150 100644 --- a/dwm.c +++ b/dwm.c @@ -2281,24 +2281,38 @@ grabkeys(void) { updatenumlockmask(); { - unsigned int i, j; + unsigned int i, j, k; unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; - KeyCode code; + int start, end, skip; + KeySym *syms; XUngrabKey(dpy, AnyKey, AnyModifier, root); - for (i = 0; i < LENGTH(keys); i++) - if ((code = XKeysymToKeycode(dpy, keys[i].keysym))) - for (j = 0; j < LENGTH(modifiers); j++) - XGrabKey(dpy, code, keys[i].mod | modifiers[j], root, - True, GrabModeAsync, GrabModeAsync); + XDisplayKeycodes(dpy, &start, &end); + syms = XGetKeyboardMapping(dpy, start, end - start + 1, &skip); + if (!syms) + return; + for (k = start; k <= end; k++) + for (i = 0; i < LENGTH(keys); i++) + /* skip modifier codes, we do that ourselves */ + if (keys[i].keysym == syms[(k - start) * skip]) + for (j = 0; j < LENGTH(modifiers); j++) + XGrabKey(dpy, k, + keys[i].mod | modifiers[j], + root, True, + GrabModeAsync, GrabModeAsync); #if ON_EMPTY_KEYS_PATCH if (!selmon->sel) - for (i = 0; i < LENGTH(on_empty_keys); i++) - if ((code = XKeysymToKeycode(dpy, on_empty_keys[i].keysym))) - for (j = 0; j < LENGTH(modifiers); j++) - XGrabKey(dpy, code, on_empty_keys[i].mod | modifiers[j], root, - True, GrabModeAsync, GrabModeAsync); + for (k = start; k <= end; k++) + for (i = 0; i < LENGTH(on_empty_keys); i++) + /* skip modifier codes, we do that ourselves */ + if (on_empty_keys[i].keysym == syms[(k - start) * skip]) + for (j = 0; j < LENGTH(modifiers); j++) + XGrabKey(dpy, k, + on_empty_keys[i].mod | modifiers[j], + root, True, + GrabModeAsync, GrabModeAsync); #endif // ON_EMPTY_KEYS_PATCH + XFree(syms); } } From 668e18fddf11ea3071c92fa348b316366ffaf66a Mon Sep 17 00:00:00 2001 From: bakkeby Date: Wed, 14 Dec 2022 17:56:50 +0100 Subject: [PATCH 3/3] seamless restart: Fix positioning of hidden scratchpad windows following restart ref. #315 --- patch/seamless_restart.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/patch/seamless_restart.c b/patch/seamless_restart.c index 7241eea..2be269e 100644 --- a/patch/seamless_restart.c +++ b/patch/seamless_restart.c @@ -466,6 +466,13 @@ restorewindowfloatposition(Client *c, Monitor *m) c->sfw = w; c->sfh = h; + if (c->isfloating) { + c->x = c->sfx; + c->y = c->sfy; + c->w = c->sfw; + c->h = c->sfh; + } + return 1; } #endif // SAVEFLOATS_PATCH