From 073235ada42e04d0eed0e70a2edd432cdef2a5eb Mon Sep 17 00:00:00 2001 From: David Maciejak Date: Sat, 21 Feb 2026 14:54:48 -0500 Subject: [PATCH] wmaker: set proper group window class when hint is empty This patch is setting a proper class hint internally when the app is not setting any. That issue can be reproduced with terminator 2.1.3, where the window itself is setting a proper WM_CLASS $ xprop|grep WM_CLASS WM_CLASS(STRING) = "terminator", "Terminator But the window id # of group leader: 0x1000001 is setting only the instance name not the class name. $ xprop -id 0x1000001|grep CLASS WM_CLASS(STRING) = "terminator", "" The issue is that wmaker is using those 2 string values for the dock apps and to identify linked launched apps. Those strings are concatenated and used in WMWindowAttributes. Without the patch, that entry below is created: terminator. = { Icon = terminator..xpm; }; If wmaker is warm restarted, a new entry appears in WMWindowAttributes: terminator. = { Icon = terminator..xpm; }; terminator = { Icon = terminator..xpm; }; and the opened window is not linked anymore to the dock app as the WM_CLASS is different. So you can launch the app as many times as you want from the dock, the dock icon will always have the 3 dots on the bottom left corner showing no window apps are linked to it. In case if the group window is not defining a CLASS but the client window has one, the patch is setting the group window CLASS to the value of the client window CLASS, or as a fallback, as seen in PropGetWMClass function, setting it to "default". With the patch, in WMWindowAttributes, we have now: terminator.Terminator = { Icon = terminator.Terminator.xpm; }; and a warm restart is not creating another entry. --- src/window.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/window.c b/src/window.c index e56bb638..978f7b88 100644 --- a/src/window.c +++ b/src/window.c @@ -848,6 +848,12 @@ WWindow *wManageWindow(WScreen *scr, Window window) /* // only enter here if PropGetWMClass() succeeds */ PropGetWMClass(wwin->main_window, &class, &instance); + if (!class || class[0] == '\0') { + if (wwin->wm_class && wwin->wm_class[0] != '\0') + class = strdup(wwin->wm_class); + else + class = strdup("default"); + } buffer = StrConcatDot(instance, class); index = WMFindInArray(scr->fakeGroupLeaders, matchIdentifier, (void *)buffer);