2 #define I3__FILE__ "handlers.c"
18 #include <xcb/randr.h>
19 #include <X11/XKBlib.h>
20 #define SN_API_NOT_YET_FROZEN 1
21 #include <libsn/sn-monitor.h>
45 event->added = time(NULL);
56 time_t now = time(NULL);
58 if ((now - event->
added) > 5) {
100 ELOG(
"ERROR: No such screen\n");
104 if (output->
con == NULL) {
105 ELOG(
"ERROR: The screen is not recognized by i3 (no container associated)\n");
131 DLOG(
"enter_notify for %08x, mode = %d, detail %d, serial %d\n",
132 event->event, event->mode, event->detail, event->sequence);
133 DLOG(
"coordinates %d, %d\n", event->event_x, event->event_y);
134 if (event->mode != XCB_NOTIFY_MODE_NORMAL) {
135 DLOG(
"This was not a normal notify, ignoring\n");
141 DLOG(
"Event ignored\n");
145 bool enter_child =
false;
154 DLOG(
"Getting screen at %d x %d\n", event->root_x, event->root_y);
160 DLOG(
"Ignoring, this is a dock client\n");
170 LOG(
"using child %p / %s instead!\n", child, child->
name);
177 if (client->workspace != c_ws && client->workspace->output == c_ws->output) {
181 DLOG(
"enter_notify for a client on a different workspace but the same screen, ignoring\n");
218 if (event->child != 0)
223 DLOG(
"MotionNotify for an unknown container, checking if it crosses screen boundaries.\n");
258 if (event->request != XCB_MAPPING_KEYBOARD &&
259 event->request != XCB_MAPPING_MODIFIER)
262 DLOG(
"Received mapping_notify for keyboard or modifier mapping, re-grabbing keys\n");
263 xcb_refresh_keyboard_mapping(
keysyms, event);
279 xcb_get_window_attributes_cookie_t cookie;
281 cookie = xcb_get_window_attributes_unchecked(
conn, event->window);
283 DLOG(
"window = 0x%08x, serial is %d.\n", event->window, event->sequence);
301 DLOG(
"window 0x%08x wants to be at %dx%d with %dx%d\n",
302 event->window, event->x, event->y, event->width, event->height);
307 DLOG(
"Configure request for unmanaged window, can do that.\n");
312 #define COPY_MASK_MEMBER(mask_member, event_member) \
314 if (event->value_mask & mask_member) { \
315 mask |= mask_member; \
316 values[c++] = event->event_member; \
328 xcb_configure_window(
conn, event->window, mask, values);
334 DLOG(
"Configure request!\n");
354 bsr.
y += deco_height;
355 bsr.
height -= deco_height;
360 DLOG(
"This is a scratchpad container, ignoring ConfigureRequest\n");
366 if (event->value_mask & XCB_CONFIG_WINDOW_X) {
367 newrect.
x =
event->x + (-1) * bsr.
x;
368 DLOG(
"proposed x = %d, new x is %d\n", event->x, newrect.
x);
370 if (event->value_mask & XCB_CONFIG_WINDOW_Y) {
371 newrect.
y =
event->y + (-1) * bsr.
y;
372 DLOG(
"proposed y = %d, new y is %d\n", event->y, newrect.
y);
374 if (event->value_mask & XCB_CONFIG_WINDOW_WIDTH) {
375 newrect.
width =
event->width + (-1) * bsr.
width;
377 DLOG(
"proposed width = %d, new width is %d (x11 border %d)\n",
380 if (event->value_mask & XCB_CONFIG_WINDOW_HEIGHT) {
383 DLOG(
"proposed height = %d, new height is %d (x11 border %d)\n",
387 DLOG(
"Container is a floating leaf node, will do that.\n");
394 DLOG(
"Dock window, only height reconfiguration allowed\n");
395 if (event->value_mask & XCB_CONFIG_WINDOW_HEIGHT) {
396 DLOG(
"Height given, changing\n");
414 int handle_configure_event(
void *prophs, xcb_connection_t *
conn, xcb_configure_notify_event_t *event) {
415 DLOG(
"configure_event, sequence %d\n", event->sequence);
430 DLOG(
"RandR screen change\n");
434 xcb_get_geometry_cookie_t cookie = xcb_get_geometry(
conn,
root);
435 xcb_get_geometry_reply_t *reply = xcb_get_geometry_reply(
conn, cookie, NULL);
437 ELOG(
"Could not get geometry of the root window, exiting\n");
440 DLOG(
"root geometry reply: (%d, %d) %d x %d\n", reply->x, reply->y, reply->width, reply->height);
449 ipc_send_event(
"output", I3_IPC_EVENT_OUTPUT,
"{\"change\":\"unspecified\"}");
460 DLOG(
"UnmapNotify for 0x%08x (received from 0x%08x), serial %d\n", event->window, event->event, event->sequence);
461 xcb_get_input_focus_cookie_t cookie;
468 LOG(
"Not a managed window, ignoring UnmapNotify event\n");
475 cookie = xcb_get_input_focus(
conn);
476 DLOG(
"ignore_unmap = %d for frame of container %p\n", con->
ignore_unmap, con);
481 cookie = xcb_get_input_focus(
conn);
513 free(xcb_get_input_focus_reply(
conn, cookie, NULL));
526 DLOG(
"destroy notify for 0x%08x, 0x%08x\n", event->event, event->window);
528 xcb_unmap_notify_event_t unmap;
529 unmap.sequence =
event->sequence;
530 unmap.event =
event->event;
531 unmap.window =
event->window;
537 if ((old_name == NULL) && (window->
name == NULL))
541 if ((old_name == NULL) ^ (window->
name == NULL))
552 xcb_window_t window, xcb_atom_t atom, xcb_get_property_reply_t *prop) {
577 xcb_window_t window, xcb_atom_t atom, xcb_get_property_reply_t *prop) {
601 xcb_window_t window, xcb_atom_t atom, xcb_get_property_reply_t *prop) {
616 static int handle_windowclass_change(
void *data, xcb_connection_t *
conn, uint8_t
state,
617 xcb_window_t window, xcb_atom_t atom, xcb_get_property_reply_t *prop) {
635 DLOG(
"window = %08x\n", event->window);
638 LOG(
"expose event for unknown window, ignoring\n");
647 event->x, event->y, event->x, event->y,
648 event->width, event->height);
654 #define _NET_WM_MOVERESIZE_SIZE_TOPLEFT 0
655 #define _NET_WM_MOVERESIZE_SIZE_TOP 1
656 #define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT 2
657 #define _NET_WM_MOVERESIZE_SIZE_RIGHT 3
658 #define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4
659 #define _NET_WM_MOVERESIZE_SIZE_BOTTOM 5
660 #define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT 6
661 #define _NET_WM_MOVERESIZE_SIZE_LEFT 7
662 #define _NET_WM_MOVERESIZE_MOVE 8
663 #define _NET_WM_MOVERESIZE_SIZE_KEYBOARD 9
664 #define _NET_WM_MOVERESIZE_MOVE_KEYBOARD 10
665 #define _NET_WM_MOVERESIZE_CANCEL 11
674 if (sn_xcb_display_process_event(
sndisplay, (xcb_generic_event_t *)event))
677 LOG(
"ClientMessage for window 0x%08x\n", event->window);
678 if (event->type == A__NET_WM_STATE) {
679 if (event->format != 32 ||
680 (event->data.data32[1] != A__NET_WM_STATE_FULLSCREEN &&
681 event->data.data32[1] != A__NET_WM_STATE_DEMANDS_ATTENTION)) {
682 DLOG(
"Unknown atom in clientmessage of type %d\n", event->data.data32[1]);
688 DLOG(
"Could not get window for client message\n");
692 if (event->data.data32[1] == A__NET_WM_STATE_FULLSCREEN) {
700 DLOG(
"toggling fullscreen\n");
703 }
else if (event->data.data32[1] == A__NET_WM_STATE_DEMANDS_ATTENTION) {
714 }
else if (event->type == A__NET_ACTIVE_WINDOW) {
715 if (event->format != 32)
718 DLOG(
"_NET_ACTIVE_WINDOW: Window 0x%08x should be activated\n", event->window);
722 DLOG(
"Could not get window for client message\n");
729 DLOG(
"Window is not being managed, ignoring _NET_ACTIVE_WINDOW\n");
734 DLOG(
"Workspace is internal, ignoring _NET_ACTIVE_WINDOW\n");
739 if (event->data.data32[0] == 2) {
742 DLOG(
"This request came from a pager. Focusing con = %p\n", con);
749 DLOG(
"Request to focus con on a visible workspace. Focusing con = %p\n", con);
753 DLOG(
"Request to focus con on a hidden workspace. Setting urgent con = %p\n", con);
759 }
else if (event->type == A_I3_SYNC) {
760 xcb_window_t window =
event->data.data32[0];
761 uint32_t rnd =
event->data.data32[1];
762 DLOG(
"[i3 sync protocol] Sending random value %d back to X11 window 0x%08x\n", rnd, window);
765 xcb_client_message_event_t *ev = reply;
767 ev->response_type = XCB_CLIENT_MESSAGE;
769 ev->type = A_I3_SYNC;
771 ev->data.data32[0] = window;
772 ev->data.data32[1] = rnd;
774 xcb_send_event(conn,
false, window, XCB_EVENT_MASK_NO_EVENT, (
char *)ev);
777 }
else if (event->type == A__NET_REQUEST_FRAME_EXTENTS) {
790 DLOG(
"_NET_REQUEST_FRAME_EXTENTS for window 0x%08x\n", event->window);
801 XCB_PROP_MODE_REPLACE,
803 A__NET_FRAME_EXTENTS,
807 }
else if (event->type == A__NET_CURRENT_DESKTOP) {
815 DLOG(
"Request to change current desktop to index %d\n", event->data.data32[0]);
823 if (idx == event->data.data32[0]) {
825 if (event->data.data32[1])
828 DLOG(
"Handling request to focus workspace %s\n", ws->
name);
839 }
else if (event->type == A__NET_CLOSE_WINDOW) {
847 DLOG(
"Handling _NET_CLOSE_WINDOW request (con = %p)\n", con);
849 if (event->data.data32[0])
855 DLOG(
"Couldn't find con for _NET_CLOSE_WINDOW request. (window = %d)\n", event->window);
857 }
else if (event->type == A__NET_WM_MOVERESIZE) {
864 DLOG(
"Couldn't find con for _NET_WM_MOVERESIZE request, or con not floating (window = %d)\n", event->window);
867 DLOG(
"Handling _NET_WM_MOVERESIZE request (con = %p)\n", con);
868 uint32_t direction =
event->data.data32[2];
869 uint32_t x_root =
event->data.data32[0];
870 uint32_t y_root =
event->data.data32[1];
872 xcb_button_press_event_t fake = {
875 .event_x = x_root - (con->
rect.
x),
876 .event_y = y_root - (con->
rect.
y)};
882 DLOG(
"_NET_WM_MOVERESIZE direction %d not implemented\n", direction);
885 DLOG(
"unhandled clientmessage\n");
891 int handle_window_type(
void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window,
892 xcb_atom_t atom, xcb_get_property_reply_t *property) {
895 ELOG(
"_NET_WM_WINDOW_TYPE changed, this is not yet implemented.\n");
908 xcb_atom_t name, xcb_get_property_reply_t *reply) {
911 DLOG(
"Received WM_NORMAL_HINTS for unknown client\n");
915 xcb_size_hints_t size_hints;
927 DLOG(
"Minimum size: %d (width) x %d (height)\n", size_hints.min_width, size_hints.min_height);
930 bool changed =
false;
932 if (size_hints.width_inc > 0 && size_hints.width_inc < 0xFFFF)
937 if (size_hints.height_inc > 0 && size_hints.height_inc < 0xFFFF)
944 DLOG(
"resize increments changed\n");
947 int base_width = 0, base_height = 0;
953 base_width = size_hints.base_width;
954 base_height = size_hints.base_height;
957 base_width = size_hints.min_width;
958 base_height = size_hints.min_height;
965 DLOG(
"client's base_height changed to %d\n", base_height);
966 DLOG(
"client's base_width changed to %d\n", base_width);
972 (size_hints.min_aspect_num <= 0) ||
973 (size_hints.min_aspect_den <= 0)) {
974 goto render_and_return;
981 double min_aspect = (double)size_hints.min_aspect_num / size_hints.min_aspect_den;
982 double max_aspect = (
double)size_hints.max_aspect_num / size_hints.min_aspect_den;
984 DLOG(
"Aspect ratio set: minimum %f, maximum %f\n", min_aspect, max_aspect);
985 DLOG(
"width = %f, height = %f\n", width, height);
988 if (max_aspect <= 0 || min_aspect <= 0 || height == 0 || (width / height) <= 0)
989 goto render_and_return;
992 double aspect_ratio = 0.0;
993 if ((width / height) < min_aspect) {
994 aspect_ratio = min_aspect;
995 }
else if ((width / height) > max_aspect) {
996 aspect_ratio = max_aspect;
998 goto render_and_return;
1000 if (fabs(con->
aspect_ratio - aspect_ratio) > DBL_EPSILON) {
1016 static bool handle_hints(
void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window,
1017 xcb_atom_t name, xcb_get_property_reply_t *reply) {
1020 DLOG(
"Received WM_HINTS for unknown client\n");
1042 xcb_atom_t name, xcb_get_property_reply_t *prop) {
1046 DLOG(
"No such window\n");
1051 prop = xcb_get_property_reply(conn, xcb_get_property_unchecked(conn,
1069 xcb_atom_t name, xcb_get_property_reply_t *prop) {
1075 prop = xcb_get_property_reply(conn, xcb_get_property_unchecked(conn,
1094 DLOG(
"focus change in, for window 0x%08x\n", event->event);
1098 DLOG(
"That is con %p / %s\n", con, con->
name);
1100 if (event->mode == XCB_NOTIFY_MODE_GRAB ||
1101 event->mode == XCB_NOTIFY_MODE_UNGRAB) {
1102 DLOG(
"FocusIn event for grab/ungrab, ignoring\n");
1106 if (event->detail == XCB_NOTIFY_DETAIL_POINTER) {
1107 DLOG(
"notify detail is pointer, ignoring this event\n");
1112 DLOG(
"focus matches the currently focused window, not doing anything\n");
1118 DLOG(
"This is a dock client, not focusing.\n");
1122 DLOG(
"focus is different, updating decorations\n");
1143 xcb_atom_t name, xcb_get_property_reply_t *prop) {
1149 prop = xcb_get_property_reply(conn, xcb_get_property_unchecked(conn,
1164 typedef bool (*
cb_property_handler_t)(
void *data, xcb_connection_t *c, uint8_t
state, xcb_window_t window, xcb_atom_t atom, xcb_get_property_reply_t *property);
1181 #define NUM_HANDLERS (sizeof(property_handlers) / sizeof(struct property_handler_t))
1191 property_handlers[0].
atom = A__NET_WM_NAME;
1195 property_handlers[4].
atom = A_WM_CLIENT_LEADER;
1197 property_handlers[6].
atom = A_WM_WINDOW_ROLE;
1203 xcb_get_property_reply_t *propr = NULL;
1206 if (property_handlers[c].atom != atom)
1209 handler = &property_handlers[c];
1213 if (handler == NULL) {
1218 if (state != XCB_PROPERTY_DELETE) {
1219 xcb_get_property_cookie_t cookie = xcb_get_property(conn, 0, window, atom, XCB_GET_PROPERTY_TYPE_ANY, 0, handler->
long_len);
1220 propr = xcb_get_property_reply(conn, cookie, 0);
1224 if (!handler->
cb(NULL, conn, state, window, atom, propr))
1236 type ==
randr_base + XCB_RANDR_SCREEN_CHANGE_NOTIFY) {
1242 DLOG(
"xkb event, need to handle it.\n");
1244 xcb_xkb_state_notify_event_t *state = (xcb_xkb_state_notify_event_t *)event;
1245 if (state->xkbType == XCB_XKB_NEW_KEYBOARD_NOTIFY) {
1246 DLOG(
"xkb new keyboard notify, sequence %d, time %d\n", state->sequence, state->time);
1247 xcb_key_symbols_free(
keysyms);
1248 keysyms = xcb_key_symbols_alloc(conn);
1252 }
else if (state->xkbType == XCB_XKB_MAP_NOTIFY) {
1254 DLOG(
"Ignoring map notify event for sequence %d.\n", state->sequence);
1256 DLOG(
"xkb map notify, sequence %d, time %d\n", state->sequence, state->time);
1258 xcb_key_symbols_free(
keysyms);
1259 keysyms = xcb_key_symbols_alloc(conn);
1264 }
else if (state->xkbType == XCB_XKB_STATE_NOTIFY) {
1265 DLOG(
"xkb state group = %d\n", state->group);
1274 if (state->group == XCB_XKB_GROUP_1) {
1275 DLOG(
"Mode_switch disabled\n");
1279 DLOG(
"Mode_switch enabled\n");
1289 case XCB_KEY_RELEASE:
1293 case XCB_BUTTON_PRESS:
1294 case XCB_BUTTON_RELEASE:
1298 case XCB_MAP_REQUEST:
1302 case XCB_UNMAP_NOTIFY:
1306 case XCB_DESTROY_NOTIFY:
1314 case XCB_MOTION_NOTIFY:
1319 case XCB_ENTER_NOTIFY:
1326 case XCB_CLIENT_MESSAGE:
1331 case XCB_CONFIGURE_REQUEST:
1336 case XCB_MAPPING_NOTIFY:
1344 case XCB_PROPERTY_NOTIFY: {
1345 xcb_property_notify_event_t *e = (xcb_property_notify_event_t *)event;
#define STARTS_WITH(string, needle)
const char * i3string_as_utf8(i3String *str)
Returns the UTF-8 encoded version of the i3String.
void floating_resize_window(Con *con, const bool proportional, const xcb_button_press_event_t *event)
Called when the user clicked on a floating window while holding the floating_modifier and the right m...
char * sstrdup(const char *str)
Safe-wrapper around strdup which exits if malloc returns NULL (meaning that there is no more memory a...
#define XCB_ATOM_WM_HINTS
void handle_key_press(xcb_key_press_event_t *event)
There was a key press.
static bool handle_class_change(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window, xcb_atom_t name, xcb_get_property_reply_t *prop)
#define SLIST_FOREACH(var, head, field)
bool con_is_floating(Con *con)
Returns true if the node is floating.
void tree_render(void)
Renders the tree, that is rendering all outputs using render_con() and pushing the changes to X11 usi...
uint8_t ignore_unmap
This counter contains the number of UnmapNotify events for this container (or, more precisely...
void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cookie, bool needs_to_be_mapped)
Do some sanity checks and then reparent the window.
Con * con_get_workspace(Con *con)
Gets the workspace container this node is on.
bool disable_focus_follows_mouse
By default, focus follows mouse.
static bool window_name_changed(i3Window *window, char *old_name)
#define xcb_icccm_get_wm_hints
Stores a rectangle, for example the size of a window, the child window etc.
bool workspace_is_visible(Con *ws)
Returns true if the workspace is currently visible.
static struct property_handler_t property_handlers[]
static void handle_map_request(xcb_map_request_event_t *event)
#define SLIST_NEXT(elm, field)
int handle_button_press(xcb_button_press_event_t *event)
The button press X callback.
static void handle_expose_event(xcb_expose_event_t *event)
void translate_keysyms(void)
Translates keysymbols to keycodes for all bindings which use keysyms.
void floating_drag_window(Con *con, const xcb_button_press_event_t *event)
Called when the user clicked on the titlebar of a floating window.
void workspace_show(Con *workspace)
Switches to the given workspace.
Con * con_descend_focused(Con *con)
Returns the focused con inside this client, descending the tree as far as possible.
void window_update_transient_for(i3Window *win, xcb_get_property_reply_t *prop)
Updates the TRANSIENT_FOR (logical parent window).
#define _NET_WM_STATE_ADD
static void handle_mapping_notify(xcb_mapping_notify_event_t *event)
#define SLIST_INSERT_HEAD(head, elm, field)
#define TAILQ_FIRST(head)
static void handle_client_message(xcb_client_message_event_t *event)
void window_update_leader(i3Window *win, xcb_get_property_reply_t *prop)
Updates the CLIENT_LEADER (logical parent window).
xcb_timestamp_t last_timestamp
The last timestamp we got from X11 (timestamps are included in some events and are used for some thin...
#define XCB_ICCCM_SIZE_HINT_BASE_SIZE
#define COPY_MASK_MEMBER(mask_member, event_member)
static bool handle_windowname_change(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window, xcb_atom_t atom, xcb_get_property_reply_t *prop)
An Output is a physical output on your graphics driver.
layout_t
Container layouts.
void floating_reposition(Con *con, Rect newrect)
Repositions the CT_FLOATING_CON to have the coordinates specified by newrect, but only if the coordin...
static bool handle_clientleader_change(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window, xcb_atom_t name, xcb_get_property_reply_t *prop)
void grab_all_keys(xcb_connection_t *conn, bool bind_mode_switch)
Grab the bound keys (tell X to send us keypress events for those keycodes)
border_style_t border_style
bool con_is_internal(Con *con)
Returns true if the container is internal, such as __i3_scratch.
A 'Window' is a type which contains an xcb_window_t and all the related information (hints like _NET_...
#define xcb_icccm_get_wm_size_hints_from_reply
#define XCB_ATOM_WM_NORMAL_HINTS
bool rect_contains(Rect rect, uint32_t x, uint32_t y)
void ipc_send_event(const char *event, uint32_t message_type, const char *payload)
Sends the specified event to all IPC clients which are currently connected and subscribed to this kin...
Con * con_by_window_id(xcb_window_t window)
Returns the container with the given client window ID or NULL if no such container exists...
static bool handle_windowname_change_legacy(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window, xcb_atom_t atom, xcb_get_property_reply_t *prop)
static bool handle_normal_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window, xcb_atom_t name, xcb_get_property_reply_t *reply)
#define xcb_icccm_get_wm_normal_hints_reply
void randr_query_outputs(void)
Initializes the specified output, assigning the specified workspace to it.
void window_update_name_legacy(i3Window *win, xcb_get_property_reply_t *prop, bool before_mgmt)
Updates the name by using WM_NAME (encoded in COMPOUND_TEXT).
Con * con_get_fullscreen_con(Con *con, fullscreen_mode_t fullscreen_mode)
Returns the first fullscreen node below this node.
bool tree_close(Con *con, kill_window_t kill_window, bool dont_kill_parent, bool force_set_focus)
Closes the given container including all children.
Rect con_border_style_rect(Con *con)
Returns a "relative" Rect which contains the amount of pixels that need to be added to the original R...
bool con_is_leaf(Con *con)
Returns true when this node is a leaf node (has no children)
#define XCB_ICCCM_SIZE_HINT_P_MIN_SIZE
static SLIST_HEAD(ignore_head, Ignore_Event)
Con * con
Pointer to the Con which represents this output.
struct Rect geometry
the geometry this window requested when getting mapped
void x_push_changes(Con *con)
Pushes all changes (state of each node, see x_push_node() and the window stack) to X11...
bool event_is_ignored(const int sequence, const int response_type)
Checks if the given sequence is ignored and returns true if so.
fullscreen_mode_t fullscreen_mode
int height
The height of the font, built from font_ascent + font_descent.
void con_focus(Con *con)
Sets input focus to the given container.
Con * con_by_frame_id(xcb_window_t frame)
Returns the container with the given frame ID or NULL if no such container exists.
void add_ignore_event(const int sequence, const int response_type)
Adds the given sequence to the list of events which are ignored.
#define xcb_icccm_get_wm_normal_hints_unchecked
static bool handle_transient_for(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window, xcb_atom_t name, xcb_get_property_reply_t *prop)
static bool handle_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window, xcb_atom_t name, xcb_get_property_reply_t *reply)
void ungrab_all_keys(xcb_connection_t *conn)
Ungrabs all keys, to be called before re-grabbing the keys because of a mapping_notify event or a con...
static void handle_focus_in(xcb_focus_in_event_t *event)
#define _NET_WM_MOVERESIZE_SIZE_TOPLEFT
static void handle_motion_notify(xcb_motion_notify_event_t *event)
unsigned int xcb_numlock_mask
void window_update_class(i3Window *win, xcb_get_property_reply_t *prop, bool before_mgmt)
Updates the WM_CLASS (consisting of the class and instance) for the given window. ...
static void check_crossing_screen_boundary(uint32_t x, uint32_t y)
static void handle_screen_change(xcb_generic_event_t *e)
static void handle_configure_request(xcb_configure_request_event_t *event)
A 'Con' represents everything from the X11 root window down to a single X11 window.
void * scalloc(size_t size)
Safe-wrapper around calloc which exits if malloc returns NULL (meaning that there is no more memory a...
void window_update_hints(i3Window *win, xcb_get_property_reply_t *prop, bool *urgency_hint)
Updates the WM_HINTS (we only care about the input focus handling part).
uint32_t aio_get_mod_mask_for(uint32_t keysym, xcb_key_symbols_t *symbols)
All-in-one function which returns the modifier mask (XCB_MOD_MASK_*) for the given keysymbol...
void scratchpad_fix_resolution(void)
When starting i3 initially (and after each change to the connected outputs), this function fixes the ...
#define XCB_ICCCM_SIZE_HINT_P_ASPECT
void window_update_name(i3Window *win, xcb_get_property_reply_t *prop, bool before_mgmt)
Updates the name by using _NET_WM_NAME (encoded in UTF-8) for the given window.
static void property_notify(uint8_t state, xcb_window_t window, xcb_atom_t atom)
#define SLIST_REMOVE(head, elm, type, field)
Output * get_output_containing(unsigned int x, unsigned int y)
Returns the active (!) output which contains the coordinates x, y or NULL if there is no output which...
void fake_absolute_configure_notify(Con *con)
Generates a configure_notify_event with absolute coordinates (relative to the X root window...
static void handle_enter_notify(xcb_enter_notify_event_t *event)
static bool handle_windowrole_change(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window, xcb_atom_t atom, xcb_get_property_reply_t *prop)
void startup_monitor_event(SnMonitorEvent *event, void *userdata)
Called by libstartup-notification when something happens.
#define _NET_WM_STATE_TOGGLE
Con * output_get_content(Con *output)
Returns the output container below the given output container.
i3String * name
The name of the window.
static void handle_destroy_notify_event(xcb_destroy_notify_event_t *event)
void * smalloc(size_t size)
Safe-wrapper around malloc which exits if malloc returns NULL (meaning that there is no more memory a...
bool(* cb_property_handler_t)(void *data, xcb_connection_t *c, uint8_t state, xcb_window_t window, xcb_atom_t atom, xcb_get_property_reply_t *property)
xcb_key_symbols_t * keysyms
#define TAILQ_FOREACH(var, head, field)
void window_update_role(i3Window *win, xcb_get_property_reply_t *prop, bool before_mgmt)
Updates the WM_WINDOW_ROLE.
#define _NET_WM_STATE_REMOVE
static void handle_unmap_notify_event(xcb_unmap_notify_event_t *event)
void property_handlers_init(void)
Sets the appropriate atoms for the property handlers after the atoms were received from X11...
#define _NET_WM_MOVERESIZE_SIZE_LEFT
void ipc_send_window_event(const char *property, Con *con)
For the window events we send, along the usual "change" field, also the window container, in "container".
#define XCB_ICCCM_SIZE_HINT_P_RESIZE_INC
#define XCB_ATOM_WM_CLASS
void con_set_urgency(Con *con, bool urgent)
Set urgency flag to the container, all the parent containers and the workspace.
void con_toggle_fullscreen(Con *con, int fullscreen_mode)
Toggles fullscreen mode for the given container.
#define SLIST_FIRST(head)
#define _NET_WM_MOVERESIZE_MOVE
xcb_window_t focused_id
Stores the X11 window ID of the currently focused window.
#define XCB_ATOM_CARDINAL
void handle_event(int type, xcb_generic_event_t *event)
Takes an xcb_generic_event_t and calls the appropriate handler, based on the event type...
#define XCB_ATOM_WM_TRANSIENT_FOR