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 |
+}
|