git.strcat.st

/strcat/wm.git/ - summarytreelogarchivereleases

subject
replace prog title placeholder and switched to focus on hover
commit
f51770177a6b16e38c76d1da8dc6e7d1bbe36ef2
date
2026-05-30T23:56:11Z
message
diff
 wm.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 79 insertions(+), 11 deletions(-)

diff --git a/wm.c b/wm.c
index d9453e0..87647cd 100644
--- a/wm.c
+++ b/wm.c
@@ -27,8 +27,10 @@ static int window_workspace[max_windows], window_count, current_workspace;
 static Atom net_wm_desktop_atom;
 #ifdef BAR
 static Atom wm_bar_margin_x_atom, wm_bar_margin_y_atom, wm_bar_bottom_atom;
+static Atom net_wm_name_atom, utf8_string_atom;
 #endif
 static int is_root_child(Display *display, Window root_window, Window window);
+static void select_window_events(Display *display, Window window);
 
 static int
 find_window_index(Window window)
@@ -94,12 +96,47 @@ place_window_at_pointer(Display *display, Window root_window, Window window)
 
 #ifdef BAR
 static void
-refresh_bar(void)
+set_bar_title_from_window(Display *display, Window window)
+{
+	Atom actual_type;
+	int actual_format;
+	unsigned long nitems, bytes_after;
+	unsigned char *prop_data;
+	char *window_name;
+
+	prop_data = NULL;
+	if (window != None && window != PointerRoot &&
+	    XGetWindowProperty(display, window, net_wm_name_atom, 0, 2048, False,
+	        utf8_string_atom, &actual_type, &actual_format, &nitems, &bytes_after,
+	        &prop_data) == Success &&
+	    prop_data != NULL && actual_type == utf8_string_atom &&
+	    actual_format == 8 && nitems > 0) {
+	    bar_set_title((char *)prop_data);
+	    XFree(prop_data);
+	    return;
+	}
+	if (prop_data != NULL)
+	    XFree(prop_data);
+	window_name = NULL;
+	if (window != None && window != PointerRoot &&
+	    XFetchName(display, window, &window_name) && window_name != NULL) {
+	    bar_set_title(window_name);
+	    XFree(window_name);
+	    return;
+	}
+	bar_set_title("");
+}
+
+static void
+refresh_bar(Display *display)
 {
 	static int tags[num_workspaces] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+	Window focused_window;
+	int revert_to;
 
 	bar_set_tags(tags, num_workspaces, current_workspace);
-	bar_set_title("wm");
+	XGetInputFocus(display, &focused_window, &revert_to);
+	set_bar_title_from_window(display, focused_window);
 	bar_set_status("");
 	bar_draw();
 }
@@ -236,6 +273,12 @@ get_window_attrs(Display *display, Window window, XWindowAttributes *window_attr
 	    window_attrs->override_redirect = True;
 }
 
+static void
+select_window_events(Display *display, Window window)
+{
+	XSelectInput(display, window, EnterWindowMask | PropertyChangeMask);
+}
+
 static int
 is_managed_window(Display *display, Window root_window, Window window)
 {
@@ -259,6 +302,7 @@ track_windows(Display *display, Window root_window)
 
 	        if (!is_managed_window(display, root_window, children[i]))
 	            continue;
+	        select_window_events(display, children[i]);
 	        window_index = get_window_index(children[i]);
 	        desktop = get_window_desktop(display, children[i]);
 	        if (window_index >= 0 && desktop >= 0)
@@ -335,6 +379,8 @@ main(int argc, char **argv)
 	wm_bar_margin_x_atom = XInternAtom(display, "_WM_BAR_MARGIN_X", False);
 	wm_bar_margin_y_atom = XInternAtom(display, "_WM_BAR_MARGIN_Y", False);
 	wm_bar_bottom_atom = XInternAtom(display, "_WM_BAR_BOTTOM", False);
+	net_wm_name_atom = XInternAtom(display, "_NET_WM_NAME", False);
+	utf8_string_atom = XInternAtom(display, "UTF8_STRING", False);
 #endif
 	XSelectInput(display, root_window, SubstructureNotifyMask | StructureNotifyMask);
 	track_windows(display, root_window);
@@ -348,7 +394,7 @@ main(int argc, char **argv)
 	bar_set_margins(read_root_int_property(display, root_window, wm_bar_margin_x_atom, 0),
 	    read_root_int_property(display, root_window, wm_bar_margin_y_atom, 0));
 	bar_set_bottom(read_root_int_property(display, root_window, wm_bar_bottom_atom, 0) ? 1 : 0);
-	refresh_bar();
+	refresh_bar(display);
 #endif
 
 	grab_button_variants(display, 1, 0, root_window, GrabModeSync);
@@ -371,17 +417,17 @@ main(int argc, char **argv)
 	        if (command == cmd_bar_position) {
 	            bar_set_bottom(value ? 1 : 0);
 	            write_root_int_property(display, root_window, wm_bar_bottom_atom, value ? 1 : 0);
-	            refresh_bar();
+	            refresh_bar(display);
 	            continue;
 	        } else if (command == cmd_bar_margin_x) {
 	            bar_set_margins(value, -1);
 	            write_root_int_property(display, root_window, wm_bar_margin_x_atom, value);
-	            refresh_bar();
+	            refresh_bar(display);
 	            continue;
 	        } else if (command == cmd_bar_margin_y) {
 	            bar_set_margins(-1, value);
 	            write_root_int_property(display, root_window, wm_bar_margin_y_atom, value);
-	            refresh_bar();
+	            refresh_bar(display);
 	            continue;
 	        }
 #endif
@@ -405,7 +451,7 @@ main(int argc, char **argv)
 	                ewmh_set_current_desktop(display, root_window, current_workspace);
 	                ewmh_sync(display, root_window, windows, window_workspace, window_count);
 #ifdef BAR
-	                refresh_bar();
+	                refresh_bar(display);
 #endif
 	            } else if (command == cmd_move) {
 	                XGetInputFocus(display, &focused_window, &j);
@@ -419,7 +465,7 @@ main(int argc, char **argv)
 	                        XUnmapWindow(display, focused_window);
 	                    ewmh_sync(display, root_window, windows, window_workspace, window_count);
 #ifdef BAR
-	                    refresh_bar();
+	                    refresh_bar(display);
 #endif
 	                }
 	            }
@@ -428,7 +474,7 @@ main(int argc, char **argv)
 	        remove_window(event.xdestroywindow.window);
 	        ewmh_sync(display, root_window, windows, window_workspace, window_count);
 #ifdef BAR
-	        refresh_bar();
+	        refresh_bar(display);
 #endif
 	    } else if (event.type == MapNotify) {
 	        Window mapped_window;
@@ -438,10 +484,11 @@ main(int argc, char **argv)
 	            continue;
 	        if (find_window_index(mapped_window) < 0) {
 	            place_window_at_pointer(display, root_window, mapped_window);
+	            select_window_events(display, mapped_window);
 	            get_window_index(mapped_window);
 	            ewmh_sync(display, root_window, windows, window_workspace, window_count);
 #ifdef BAR
-	            refresh_bar();
+	            refresh_bar(display);
 #endif
 	        }
 	    } else if (event.type == ButtonPress && event.xbutton.subwindow != None) {
@@ -458,7 +505,7 @@ main(int argc, char **argv)
 	            window_workspace[j] = current_workspace;
 	        ewmh_sync(display, root_window, windows, window_workspace, window_count);
 #ifdef BAR
-	        refresh_bar();
+	        refresh_bar(display);
 #endif
 	        if (!(event.xbutton.state & mod_key) && event.xbutton.button == 1) {
 	            XAllowEvents(display, ReplayPointer, event.xbutton.time);
@@ -480,6 +527,27 @@ main(int argc, char **argv)
 	        is_dragging = 1;
 	    } else if (event.type == ButtonPress && event.xbutton.subwindow == None) {
 	        XAllowEvents(display, AsyncPointer, event.xbutton.time);
+	    } else if (event.type == EnterNotify && event.xcrossing.window != None) {
+	        Window hover_window;
+
+	        hover_window = event.xcrossing.window;
+	        if (event.xcrossing.mode != NotifyNormal ||
+	            event.xcrossing.detail == NotifyInferior)
+	            continue;
+	        if (!is_managed_window(display, root_window, hover_window))
+	            continue;
+	        XSetInputFocus(display, hover_window, RevertToPointerRoot, CurrentTime);
+	        ewmh_set_active_window(display, root_window, hover_window);
+#ifdef BAR
+	        refresh_bar(display);
+#endif
+	    } else if (event.type == PropertyNotify) {
+#ifdef BAR
+	        if (event.xproperty.state == PropertyNewValue &&
+	            (event.xproperty.atom == net_wm_name_atom ||
+	            event.xproperty.atom == XA_WM_NAME))
+	            refresh_bar(display);
+#endif
 	    } else if (event.type == MotionNotify && is_dragging) {
 	        int x_diff, y_diff;