commit 46b63a8
wf
·
2026-04-10 18:42:26 +0000 UTC
parent b438599
Add focus_prev/next, lower/raise, silence compiler warnings
7 files changed,
+181,
-2
M
client.c
+4,
-0
1@@ -26,6 +26,10 @@ static const struct command commands[] = {
2 { "fullscreen", cmd_fullscreen, 0, false },
3 { "hide", cmd_hide, 0, false },
4 { "show", cmd_show, 0, false },
5+ { "lower", cmd_lower, 0, false },
6+ { "raise", cmd_raise, 0, false },
7+ { "focus_prev", cmd_focus_prev, 0, false },
8+ { "focus_next", cmd_focus_next, 0, false },
9 { "close", cmd_close, 0, false },
10 { "workspace", cmd_workspace, 1, false },
11 { "move_workspace", cmd_move_workspace, 1, false },
+26,
-0
1@@ -75,6 +75,32 @@ $ howlc hide
2 .br
3 $ howlc show
4 .TP
5+\fBfocus_prev\fR, \fBfocus_next\fR
6+Focus the previous/next window\.
7+.IP
8+Example:
9+.IP
10+# Focus the previous window
11+.br
12+$ howlc focus_prev
13+.IP
14+# And the next
15+.br
16+$ howlc focus_next
17+.TP
18+\fBlower\fR, \fBraise\fR
19+Lower/raise the window's stack order\.
20+.IP
21+Example:
22+.IP
23+# Lower the current window
24+.br
25+$ howlc lower
26+.IP
27+# And then raise it
28+.br
29+$ howlc raise
30+.TP
31 \fBclose\fR
32 Closes the window\.
33 .IP
+22,
-0
1@@ -73,6 +73,28 @@ howlc(1) -- client to control the howl compositor
2 \# And now show (map) it<br>
3 $ howlc show
4
5+ * `focus_prev`, `focus_next`:
6+ Focus the previous/next window.
7+
8+ Example:
9+
10+ \# Focus the previous window<br>
11+ $ howlc focus_prev
12+
13+ \# And the next<br>
14+ $ howlc focus_next
15+
16+ * `lower`, `raise`:
17+ Lower/raise the window's stack order.
18+
19+ Example:
20+
21+ \# Lower the current window<br>
22+ $ howlc lower
23+
24+ \# And then raise it<br>
25+ $ howlc raise
26+
27 * `close`:
28 Closes the window.
29
M
howl.c
+91,
-1
1@@ -31,6 +31,10 @@ extern void ipc_center(char **);
2 extern void ipc_fullscreen(char **);
3 extern void ipc_hide(char **);
4 extern void ipc_show(char **);
5+extern void ipc_lower(char **);
6+extern void ipc_raise(char **);
7+extern void ipc_focus_prev(char **);
8+extern void ipc_focus_next(char **);
9 extern void ipc_close(char **);
10 extern void ipc_workspace(char **);
11 extern void ipc_move_workspace(char **);
12@@ -70,6 +74,10 @@ static const cmd_handler_t cmd_handler [cmd_last] = {
13 [cmd_fullscreen] = ipc_fullscreen,
14 [cmd_hide] = ipc_hide,
15 [cmd_show] = ipc_show,
16+ [cmd_lower] = ipc_lower,
17+ [cmd_raise] = ipc_raise,
18+ [cmd_focus_prev] = ipc_focus_prev,
19+ [cmd_focus_next] = ipc_focus_next,
20 [cmd_close] = ipc_close,
21 [cmd_workspace] = ipc_workspace,
22 [cmd_move_workspace] = ipc_move_workspace,
23@@ -139,7 +147,7 @@ ipc_handler(int fd, uint32_t mask, void *data) {
24 if (argc == 0) return 0;
25
26 int cmd = atoi(argv[0]);
27- void *fn = cmd_handler[cmd];
28+ void (*fn)(char **) = cmd_handler[cmd];
29 /* TODO: this is hard to debug */
30 if (!fn) _wrn("no such command #%d", cmd);
31
32@@ -305,6 +313,12 @@ sync_windows(void) {
33 }
34 }
35
36+
37+/*
38+ * TODO: These 4 functions should probably be grouped together & moved.
39+ * Maybe this is a good enough reason for a rehaul?
40+ */
41+
42 void
43 ws_go_to(uint8_t ws) {
44 struct client *c;
45@@ -340,6 +354,82 @@ ws_move_to(uint8_t ws) {
46 focus(next);
47 }
48
49+void
50+focus_prev(void) {
51+ if (wl_list_empty(&wm.clients))
52+ return;
53+
54+ _inf("focus_prev");
55+
56+ struct client *c = NULL;
57+ if (!wm.cur || !is_ws_client(wm.cur, wm.scr)) {
58+ c = first_client(wm.scr);
59+ if (!c) c = first_client(NULL);
60+ focus(c);
61+ return;
62+ }
63+
64+ struct wl_list *start = wm.cur->link.prev;
65+ struct wl_list *it = start;
66+
67+ do {
68+ if (it == &wm.clients)
69+ it = wm.clients.prev;
70+ if (it == &wm.clients)
71+ break;
72+
73+ c = wl_container_of(it, c, link);
74+ if (is_ws_client(c, wm.scr)) {
75+ focus(c);
76+ return;
77+ }
78+ it = it->prev;
79+ } while (it != start);
80+
81+ c = first_client(wm.scr);
82+ if (!c) c = first_client(NULL);
83+ focus(c);
84+ _inf("DONE focus_prev");
85+}
86+
87+void
88+focus_next(void) {
89+ if (wl_list_empty(&wm.clients))
90+ return;
91+
92+ _inf("focus_next");
93+
94+ struct client *c = NULL;
95+ if (!wm.cur || !is_ws_client(wm.cur, wm.scr)) {
96+ c = first_client(wm.scr);
97+ if (!c) c = first_client(NULL);
98+ focus(c);
99+ return;
100+ }
101+
102+ struct wl_list *start = wm.cur->link.next;
103+ struct wl_list *it = start;
104+
105+ do {
106+ if (it == &wm.clients)
107+ it = wm.clients.next;
108+ if (it == &wm.clients)
109+ break;
110+
111+ c = wl_container_of(it, c, link);
112+ if (is_ws_client(c, wm.scr)) {
113+ focus(c);
114+ return;
115+ }
116+ it = it->next;
117+ } while (it != start);
118+
119+ c = first_client(wm.scr);
120+ if (!c) c = first_client(NULL);
121+ focus(c);
122+ _inf("DONE focus_next");
123+}
124+
125 static void
126 new_screen(struct swc_screen *scr) {
127 struct screen *s;
+4,
-0
1@@ -11,6 +11,10 @@ enum cmd {
2 cmd_fullscreen,
3 cmd_hide,
4 cmd_show,
5+ cmd_lower,
6+ cmd_raise,
7+ cmd_focus_prev,
8+ cmd_focus_next,
9 cmd_close,
10 cmd_workspace,
11 cmd_move_workspace,
M
ipc.c
+33,
-0
1@@ -62,6 +62,8 @@ fn_bind(char *s) {
2 extern void bind_handler(void *, uint32_t, uint32_t, uint32_t);
3 extern void ws_go_to(int8_t);
4 extern void ws_move_to(int8_t);
5+extern void focus_prev(void);
6+extern void focus_next(void);
7 extern void cleanup(void);
8
9 /*********/
10@@ -200,6 +202,37 @@ ipc_show(char **arg) {
11 swc_window_show(wm.cur->win);
12 }
13
14+/* I really doubt anyone even has 99 clients opened at the same time */
15+void
16+ipc_lower(char **arg) {
17+ UNUSED(arg);
18+ if (!wm.cur) return;
19+
20+ swc_window_stack(wm.cur->win, 99);
21+}
22+
23+void
24+ipc_raise(char **arg) {
25+ UNUSED(arg);
26+ if (!wm.cur) return;
27+
28+ swc_window_stack(wm.cur->win, -99);
29+}
30+
31+void
32+ipc_focus_prev(char **arg) {
33+ UNUSED(arg);
34+
35+ focus_prev();
36+}
37+
38+void
39+ipc_focus_next(char **arg) {
40+ UNUSED(arg);
41+
42+ focus_next();
43+}
44+
45 void
46 ipc_close(char **arg) {
47 UNUSED(arg);
M
log.c
+1,
-1
1@@ -4,7 +4,7 @@
2
3 #include "howl.h"
4
5-extern void cleanup();
6+extern void cleanup(void);
7
8 void
9 _inf(const char *msg, ...) {