if (binding->input_code != event->detail)
continue;
- i3_send_msg(I3_IPC_MESSAGE_TYPE_COMMAND, binding->command);
+ i3_send_msg(I3_IPC_MESSAGE_TYPE_RUN_COMMAND, binding->command);
return;
}
buffer[outpos] = utf8_name[inpos];
}
buffer[outpos] = '"';
- i3_send_msg(I3_IPC_MESSAGE_TYPE_COMMAND, buffer);
+ i3_send_msg(I3_IPC_MESSAGE_TYPE_RUN_COMMAND, buffer);
free(buffer);
}
*
*/
static void handle_client_message(xcb_client_message_event_t *event) {
- if (event->type == atoms[_NET_SYSTEM_TRAY_OPCODE] &&
- event->format == 32) {
+ if (event->type == atoms[I3_SYNC]) {
+ xcb_window_t window = event->data.data32[0];
+ uint32_t rnd = event->data.data32[1];
+ DLOG("[i3 sync protocol] Forwarding random value %d, X11 window 0x%08x to i3\n", rnd, window);
+
+ void *reply = scalloc(32, 1);
+ xcb_client_message_event_t *ev = reply;
+
+ ev->response_type = XCB_CLIENT_MESSAGE;
+ ev->window = window;
+ ev->type = atoms[I3_SYNC];
+ ev->format = 32;
+ ev->data.data32[0] = window;
+ ev->data.data32[1] = rnd;
+
+ xcb_send_event(conn, false, xcb_root, XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (char *)ev);
+ xcb_flush(conn);
+ free(reply);
+ } else if (event->type == atoms[_NET_SYSTEM_TRAY_OPCODE] &&
+ event->format == 32) {
DLOG("_NET_SYSTEM_TRAY_OPCODE received\n");
/* event->data.data32[0] is the timestamp */
uint32_t op = event->data.data32[1];
* client to finish the protocol. After this event is received, there is no
* further interaction with the tray client.
*
- * See: http://standards.freedesktop.org/xembed-spec/xembed-spec-latest.html
+ * See: https://standards.freedesktop.org/xembed-spec/xembed-spec-latest.html
*
*/
static void handle_destroy_notify(xcb_destroy_notify_event_t *event) {
ev_prepare_init(xcb_prep, &xcb_prep_cb);
ev_check_init(xcb_chk, &xcb_chk_cb);
+ /* Within an event loop iteration, run the xcb_chk watcher last: other
+ * watchers might call xcb_flush(), which, unexpectedly, can also read
+ * events into the queue (see _xcb_conn_wait). Hence, we need to drain xcb’s
+ * queue last, otherwise we risk dead-locking. */
+ ev_set_priority(xcb_chk, EV_MINPRI);
+
ev_io_start(main_loop, xcb_io);
ev_prepare_start(main_loop, xcb_prep);
ev_check_start(main_loop, xcb_chk);