From e458d29c98b1a0240c9f67a1afc3fa901be8fdda Mon Sep 17 00:00:00 2001 From: speedie Date: Sun, 22 Jan 2023 13:54:06 +0100 Subject: [PATCH] fix: tag preview multi-monitor crash --- Makefile | 2 +- host.mk | 2 +- speedwm.c | 124 ++++++++++++++++++++++++++++++++++++------------------ 3 files changed, 85 insertions(+), 43 deletions(-) diff --git a/Makefile b/Makefile index c04b75a..425495e 100644 --- a/Makefile +++ b/Makefile @@ -29,7 +29,7 @@ options: @echo .c.o: - ${CC} -c ${CFLAGS} $< + ${CC} -c ${CFLAGS} -g $< ${OBJ}: options.mk diff --git a/host.mk b/host.mk index e7ffc8e..bbc7f89 100644 --- a/host.mk +++ b/host.mk @@ -16,7 +16,7 @@ PAGEDIR = "/home/anon/Projects/speediegq/projects" FREETYPELIBS = -lfontconfig -lXft FREETYPEINC = /usr/include/freetype2 EXCFLAGS = -Wno-unused-variable -Wno-unused-function -Wno-unused-result -Wno-array-bounds -CFLAGS = -std=c99 -pedantic -Wall -Wno-deprecated-declarations -Ofast -march=native ${INCS} ${CPPFLAGS} ${EXCFLAGS} +CFLAGS = -std=c99 -pedantic -Wall -Wno-deprecated-declarations -O2 -march=native ${INCS} ${CPPFLAGS} ${EXCFLAGS} LDFLAGS = ${LIBS} -g # OpenBSD support diff --git a/speedwm.c b/speedwm.c index 78e52dd..17f1b7a 100644 --- a/speedwm.c +++ b/speedwm.c @@ -313,10 +313,10 @@ struct Monitor { #endif #if USETAGPREVIEW int previewshow; - int scalepreview; Window tagwin; Pixmap *tagmap; #endif + int scalepreview; float mfact; /* mfact value */ float cfact; /* cfact value */ int ltaxis[4]; @@ -777,6 +777,7 @@ static void zoom(const Arg *arg); #if USETAGPREVIEW static void showtagpreview(unsigned int i); static void takepreview(void); +static void updatepreviews(Monitor *m); #endif /* We will keep this one, in order to keep keybinds.h clean. */ @@ -1077,9 +1078,9 @@ applyrules(Client *c) if (r->floath >= 0) c->h = r->floath; } - for (m = mons; m && m->num != r->monitor; m = m->next); - if (m) - c->mon = m; + for (m = mons; m && m->num != r->monitor; m = m->next) + if (m) + c->mon = m; } } if (ch.res_class) @@ -1494,7 +1495,6 @@ cleanup(void) #endif } -/* clean up on the selected monitor only */ void cleanupmon(Monitor *mon) { @@ -1510,11 +1510,11 @@ cleanupmon(Monitor *mon) size_t i; for (i = 0; i < LENGTH(ftags); i++) - if (mon->tagmap[i]) - XFreePixmap(dpy, mon->tagmap[i]); - free(mon->tagmap); - XUnmapWindow(dpy, mon->tagwin); - XDestroyWindow(dpy, mon->tagwin); + if (m->tagmap[i]) + XFreePixmap(dpy, m->tagmap[i]); + free(m->tagmap); + XUnmapWindow(dpy, m->tagwin); + XDestroyWindow(dpy, m->tagwin); #endif free(mon); } @@ -1637,6 +1637,10 @@ configurenotify(XEvent *e) for (bar = m->bar; bar; bar = bar->next) XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh); + + #if USETAGPREVIEW + updatepreviews(m); + #endif } focus(NULL); arrange(NULL); @@ -2961,6 +2965,7 @@ showwin(Client *c) void showhide(Client *c) { + return; if (!c) return; if (ISVISIBLE(c)) { @@ -5107,6 +5112,7 @@ setup(void) tw = DisplayWidth(dpy, screen); sh = DisplayHeight(dpy, screen); root = RootWindow(dpy, screen); + xinitvisual(); drw = drw_create(dpy, screen, root, tw, sh, visual, depth, cmap); if (!drw_font_create(drw, font)) @@ -5208,9 +5214,11 @@ setup(void) setcurrentdesktop(); setdesktopnames(); setviewport(); + XDeleteProperty(dpy, root, netatom[NetClientList]); XDeleteProperty(dpy, root, netatom[NetClientInfo]); XDeleteProperty(dpy, root, netatom[NetClientListStacking]); + /* select events */ wa.cursor = cursor[CurNormal]->cursor; wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask @@ -5713,15 +5721,9 @@ updatebars(void) .colormap = cmap, .event_mask = ButtonPressMask|ExposureMask|PointerMotionMask }; + XClassHint ch = {"speedwm", "speedwm"}; for (m = mons; m; m = m->next) { - #if USETAGPREVIEW - m->tagwin = XCreateWindow(dpy, root, m->wx + x_pad, bar->by + bh + y_pad + selmon->gapsizeov / 2, m->mw / selmon->scalepreview, m->mh / selmon->scalepreview, 0, - depth, CopyFromParent, visual, CWOverrideRedirect|CWBackPixel|CWBorderPixel|CWColormap|CWEventMask, &wa); - XDefineCursor(dpy, m->tagwin, cursor[CurNormal]->cursor); - XUnmapWindow(dpy, m->tagwin); - #endif - for (bar = m->bar; bar; bar = bar->next) { if (!bar->win) { bar->win = XCreateWindow(dpy, root, bar->bx, bar->by, bar->bw, bar->bh, 0, depth, @@ -6169,7 +6171,7 @@ view(const Arg *arg) focus(NULL); arrange(NULL); - updatecurrentdesktop(); +// updatecurrentdesktop(); } pid_t @@ -6578,6 +6580,7 @@ inplacerotate(const Arg *arg) if (arg->i == 2) insertclient(selmon->clients, stail, 0); if (arg->i == -2) insertclient(stail, selmon->clients, 1); + /* stack xor master rotate */ if (arg->i == -1 && selidx >= selmon->mastercount) insertclient(stail, shead, 1); if (arg->i == 1 && selidx >= selmon->mastercount) insertclient(shead, stail, 0); @@ -6599,17 +6602,19 @@ inplacerotate(const Arg *arg) void showtagpreview(unsigned int i) { - if (!selmon->previewshow || !selmon->tagmap[i]) { - XUnmapWindow(dpy, selmon->tagwin); - return; - } + if (!selmon->tagwin) + return; - XSetWindowBackgroundPixmap(dpy, selmon->tagwin, selmon->tagmap[i]); - XCopyArea(dpy, selmon->tagmap[i], selmon->tagwin, drw->gc, 0, 0, - selmon->mw / selmon->scalepreview, selmon->mh / selmon->scalepreview, - 0, 0); - XSync(dpy, False); - XMapRaised(dpy, selmon->tagwin); + if (selmon->tagmap[i] && selmon->previewshow) { + XSetWindowBackgroundPixmap(dpy, selmon->tagwin, selmon->tagmap[i]); + XCopyArea(dpy, selmon->tagmap[i], selmon->tagwin, drw->gc, 0, 0, + selmon->mw / selmon->scalepreview, selmon->mh / selmon->scalepreview, + 0, 0); + XSync(dpy, False); + XMapRaised(dpy, selmon->tagwin); + } else { + XUnmapWindow(dpy, selmon->tagwin); + } } void @@ -6618,25 +6623,35 @@ takepreview(void) Client *c; Imlib_Image image; unsigned int occ = 0, i; + Monitor *m = selmon; - for (c = selmon->clients; c; c = c->next) - if (!selmon->hideemptytags) + if (!m->tagwin) { + updatepreviews(m); + + /* failsafe, should prevent crashing if updatepreviews(m) doesn't create tagwin */ + if (!m->tagwin) { + return; + } + } + + for (c = m->clients; c; c = c->next) + if (!m->hideemptytags) occ |= c->tags; else occ |= c->tags == 255 ? 0 : c->tags; for (i = 0; i < LENGTH(ftags); i++) { /* searching for tags that are occupied && selected */ - if (!(occ & 1 << i) || !(selmon->tagset[selmon->seltags] & 1 << i)) + if (!(occ & 1 << i) || !(m->tagset[m->seltags] & 1 << i)) continue; - if (selmon->tagmap[i]) { /* tagmap exist, clean it */ - XFreePixmap(dpy, selmon->tagmap[i]); - selmon->tagmap[i] = 0; + if (m->tagmap[i]) { /* tagmap exist, clean it */ + XFreePixmap(dpy, m->tagmap[i]); + m->tagmap[i] = 0; } - selmon->previewshow = 0; - XUnmapWindow(dpy, selmon->tagwin); + m->previewshow = 0; + XUnmapWindow(dpy, m->tagwin); XSync(dpy, False); if (!(image = imlib_create_image(tw, sh))) { @@ -6651,16 +6666,43 @@ takepreview(void) imlib_context_set_drawable(root); if (!barpreview) - imlib_copy_drawable_to_image(0, selmon->wx, selmon->wy, selmon->ww ,selmon->wh, 0, 0, 1); + imlib_copy_drawable_to_image(0, m->wx, m->wy, m->ww, m->wh, 0, 0, 1); else - 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); - selmon->tagmap[i] = XCreatePixmap(dpy, selmon->tagwin, selmon->mw / selmon->scalepreview, selmon->mh / selmon->scalepreview, depth); - 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 / selmon->scalepreview, selmon->mh / selmon->scalepreview); + m->tagmap[i] = XCreatePixmap(dpy, m->tagwin, m->mw / m->scalepreview, m->mh / m->scalepreview, depth); + 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 / m->scalepreview, m->mh / m->scalepreview); imlib_free_image(); } } + +void +updatepreviews(Monitor *m) +{ + int x_pad = sp; + int y_pad = vp; + + if (m->tagwin) { + XMoveResizeWindow(dpy, m->tagwin, m->mx, m->bar->by + bh, m->mw / m->scalepreview, m->mh / m->scalepreview); + return; + } + + XSetWindowAttributes wa = { + .override_redirect = True, + .background_pixel = 0, + .border_pixel = 0, + .colormap = cmap, + .event_mask = ButtonPressMask|ExposureMask|PointerMotionMask + }; + + m->tagwin = XCreateWindow(dpy, root, m->wx + x_pad, m->bar->by + bh + y_pad + m->gapsizeov / 2, m->mw / m->scalepreview, m->mh / m->scalepreview, 0, + depth, CopyFromParent, visual, CWOverrideRedirect|CWBackPixel|CWBorderPixel|CWColormap|CWEventMask, &wa); + + XDefineCursor(dpy, m->tagwin, cursor[CurNormal]->cursor); + XMapRaised(dpy, m->tagwin); + XUnmapWindow(dpy, m->tagwin); +} #endif void