Add IPC event for window title changes
Patch status: superseded
Patch by Marco Hunsicker
To apply this patch, use:
curl http://cr.i3wm.org/patch/384/raw.patch | git am
b/include/i3/ipc.h
17 |
@@ -100,3 +100,6 @@ typedef struct i3_ipc_header {
|
18 |
|
19 |
/** Bar config update will be triggered to update the bar config */
|
20 |
#define I3_IPC_EVENT_BARCONFIG_UPDATE (I3_IPC_EVENT_MASK | 4)
|
21 |
+
|
22 |
+/* The window title event will be triggered upon window title changes */
|
23 |
+#define I3_IPC_EVENT_WINDOW_TITLE (I3_IPC_EVENT_MASK | 5)
|
b/include/ipc.h
28 |
@@ -87,3 +87,9 @@ void dump_node(yajl_gen gen, Con *con, bool inplace_restart);
|
29 |
* respectively.
|
30 |
*/
|
31 |
void ipc_send_workspace_focus_event(Con *current, Con *old);
|
32 |
+
|
33 |
+/*
|
34 |
+ * For the window "window_title" event we send, along the usual "change" field,
|
35 |
+ * also the changed title, in "title".
|
36 |
+ */
|
37 |
+void ipc_send_window_title_event(Con *current);
|
b/src/con.c
42 |
@@ -213,6 +213,8 @@ void con_focus(Con *con) {
|
43 |
assert(con != NULL);
|
44 |
DLOG("con_focus = %p\n", con);
|
45 |
|
46 |
+ bool already_focused = (con == focused);
|
47 |
+
|
48 |
/* 1: set focused-pointer to the new con */
|
49 |
/* 2: exchange the position of the container in focus stack of the parent all the way up */
|
50 |
TAILQ_REMOVE(&(con->parent->focus_head), con, focused);
|
51 |
@@ -221,15 +223,22 @@ void con_focus(Con *con) {
|
52 |
con_focus(con->parent);
|
53 |
|
54 |
focused = con;
|
55 |
- /* We can't blindly reset non-leaf containers since they might have
|
56 |
- * other urgent children. Therefore we only reset leafs and propagate
|
57 |
- * the changes upwards via con_update_parents_urgency() which does proper
|
58 |
- * checks before resetting the urgency.
|
59 |
- */
|
60 |
- if (con->urgent && con_is_leaf(con)) {
|
61 |
- con->urgent = false;
|
62 |
- con_update_parents_urgency(con);
|
63 |
- workspace_update_urgent_flag(con_get_workspace(con));
|
64 |
+
|
65 |
+ if (con_is_leaf(con))
|
66 |
+ {
|
67 |
+ if (!already_focused)
|
68 |
+ ipc_send_window_title_event(con);
|
69 |
+
|
70 |
+ /* We can't blindly reset non-leaf containers since they might have
|
71 |
+ * other urgent children. Therefore we only reset leafs and propagate
|
72 |
+ * the changes upwards via con_update_parents_urgency() which does proper
|
73 |
+ * checks before resetting the urgency.
|
74 |
+ */
|
75 |
+ if (con->urgent) {
|
76 |
+ con->urgent = false;
|
77 |
+ con_update_parents_urgency(con);
|
78 |
+ workspace_update_urgent_flag(con_get_workspace(con));
|
79 |
+ }
|
80 |
}
|
81 |
}
|
82 |
|
b/src/handlers.c
87 |
@@ -540,6 +540,8 @@ static bool handle_windowname_change(void *data, xcb_connection_t *conn, uint8_t
|
88 |
|
89 |
window_update_name(con->window, prop, false);
|
90 |
|
91 |
+ ipc_send_window_title_event(con);
|
92 |
+
|
93 |
x_push_changes(croot);
|
94 |
|
95 |
return true;
|
96 |
@@ -558,6 +560,8 @@ static bool handle_windowname_change_legacy(void *data, xcb_connection_t *conn,
|
97 |
|
98 |
window_update_name_legacy(con->window, prop, false);
|
99 |
|
100 |
+ ipc_send_window_title_event(con);
|
101 |
+
|
102 |
x_push_changes(croot);
|
103 |
|
104 |
return true;
|
b/src/ipc.c
109 |
@@ -21,6 +21,7 @@
|
110 |
#include <yajl/yajl_parse.h>
|
111 |
|
112 |
char *current_socketpath = NULL;
|
113 |
+char *current_windowtitle = NULL;
|
114 |
|
115 |
TAILQ_HEAD(ipc_client_head, ipc_client) all_clients = TAILQ_HEAD_INITIALIZER(all_clients);
|
116 |
|
117 |
@@ -1056,3 +1057,43 @@ void ipc_send_workspace_focus_event(Con *current, Con *old) {
|
118 |
y(free);
|
119 |
setlocale(LC_NUMERIC, "");
|
120 |
}
|
121 |
+
|
122 |
+const char* get_window_title(Con *con) {
|
123 |
+ return (con != NULL && con->window != NULL && con->window->name != NULL) ? i3string_as_utf8(con->window->name) : "";
|
124 |
+}
|
125 |
+
|
126 |
+void ipc_send_window_title_event(Con *con) {
|
127 |
+ const char* title = get_window_title(con);
|
128 |
+
|
129 |
+ if (con != focused || (current_windowtitle != NULL && strcmp(current_windowtitle, title) == 0)) {
|
130 |
+ return;
|
131 |
+ }
|
132 |
+
|
133 |
+ FREE(current_windowtitle);
|
134 |
+
|
135 |
+ current_windowtitle = strdup(title);
|
136 |
+
|
137 |
+ setlocale(LC_NUMERIC, "C");
|
138 |
+ yajl_gen gen = ygenalloc();
|
139 |
+
|
140 |
+ y(map_open);
|
141 |
+
|
142 |
+ ystr("change");
|
143 |
+ ystr("window_title");
|
144 |
+
|
145 |
+ ystr("title");
|
146 |
+ ystr(title);
|
147 |
+
|
148 |
+ ystr("current");
|
149 |
+ dump_node(gen, con, false);
|
150 |
+
|
151 |
+ y(map_close);
|
152 |
+
|
153 |
+ const unsigned char *payload;
|
154 |
+ ylength length;
|
155 |
+ y(get_buf, &payload, &length);
|
156 |
+
|
157 |
+ ipc_send_event("window_title", I3_IPC_EVENT_WINDOW_TITLE, (const char *)payload);
|
158 |
+ y(free);
|
159 |
+ setlocale(LC_NUMERIC, "");
|
160 |
+}
|