17#define SN_API_NOT_YET_FROZEN 1
18#include <libsn/sn-monitor.h>
43 event->added = time(NULL);
54 time_t now = time(NULL);
56 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");
132 DLOG(
"enter_notify for %08x, mode = %d, detail %d, serial %d\n",
133 event->event, event->mode, event->detail, event->sequence);
134 DLOG(
"coordinates %d, %d\n", event->event_x, event->event_y);
135 if (event->mode != XCB_NOTIFY_MODE_NORMAL) {
136 DLOG(
"This was not a normal notify, ignoring\n");
142 DLOG(
"Event ignored\n");
146 bool enter_child =
false;
156 if (con == NULL || con->
parent->
type == CT_DOCKAREA) {
157 DLOG(
"Getting screen at %d x %d\n", event->root_x, event->root_y);
168 LOG(
"using child %p / %s instead!\n", child, child->
name);
208 if (event->child != XCB_NONE) {
214 DLOG(
"MotionNotify for an unknown container, checking if it crosses screen boundaries.\n");
228 if (con->
window != NULL) {
264 if (event->request != XCB_MAPPING_KEYBOARD &&
265 event->request != XCB_MAPPING_MODIFIER) {
269 DLOG(
"Received mapping_notify for keyboard or modifier mapping, re-grabbing keys\n");
270 xcb_refresh_keyboard_mapping(
keysyms, event);
284 xcb_get_window_attributes_cookie_t cookie;
286 cookie = xcb_get_window_attributes_unchecked(
conn, event->window);
288 DLOG(
"window = 0x%08x, serial is %d.\n", event->window, event->sequence);
305 DLOG(
"window 0x%08x wants to be at %dx%d with %dx%d\n",
306 event->window, event->x, event->y, event->width, event->height);
311 DLOG(
"Configure request for unmanaged window, can do that.\n");
316#define COPY_MASK_MEMBER(mask_member, event_member) \
318 if (event->value_mask & mask_member) { \
319 mask |= mask_member; \
320 values[c++] = event->event_member; \
332 xcb_configure_window(
conn, event->window, mask, values);
338 DLOG(
"Configure request!\n");
341 if (workspace && (strcmp(workspace->
name,
"__i3_scratch") == 0)) {
342 DLOG(
"This is a scratchpad container, ignoring ConfigureRequest\n");
354 if (event->value_mask & XCB_CONFIG_WINDOW_X) {
355 newrect.
x =
event->x + (-1) * bsr.
x;
356 DLOG(
"proposed x = %d, new x is %d\n", event->x, newrect.
x);
358 if (event->value_mask & XCB_CONFIG_WINDOW_Y) {
359 newrect.
y =
event->y + (-1) * bsr.
y;
360 DLOG(
"proposed y = %d, new y is %d\n", event->y, newrect.
y);
362 if (event->value_mask & XCB_CONFIG_WINDOW_WIDTH) {
363 newrect.
width =
event->width + (-1) * bsr.
width;
365 DLOG(
"proposed width = %d, new width is %d (x11 border %d)\n",
368 if (event->value_mask & XCB_CONFIG_WINDOW_HEIGHT) {
371 DLOG(
"proposed height = %d, new height is %d (x11 border %d)\n",
375 DLOG(
"Container is a floating leaf node, will do that.\n");
382 DLOG(
"Reconfiguring dock window (con = %p).\n", con);
383 if (event->value_mask & XCB_CONFIG_WINDOW_HEIGHT) {
384 DLOG(
"Dock client wants to change height to %d, we can do that.\n", event->height);
390 if (event->value_mask & XCB_CONFIG_WINDOW_X || event->value_mask & XCB_CONFIG_WINDOW_Y) {
391 int16_t x =
event->value_mask & XCB_CONFIG_WINDOW_X ?
event->x : (int16_t)con->
geometry.
x;
392 int16_t
y =
event->value_mask & XCB_CONFIG_WINDOW_Y ?
event->y : (int16_t)con->
geometry.
y;
396 if (target != NULL && current_output != target->
con) {
400 DLOG(
"Dock client will be moved to container %p.\n", nc);
406 DLOG(
"Dock client will not be moved, we only support moving it to another output.\n");
412 if (event->value_mask & XCB_CONFIG_WINDOW_STACK_MODE) {
413 DLOG(
"window 0x%08x wants to be stacked %d\n", event->window, event->stack_mode);
417 if (event->stack_mode != XCB_STACK_MODE_ABOVE) {
418 DLOG(
"stack_mode != XCB_STACK_MODE_ABOVE, ignoring ConfigureRequest\n");
423 DLOG(
"fullscreen or not a leaf, ignoring ConfigureRequest\n");
427 if (workspace == NULL) {
428 DLOG(
"Window is not being managed, ignoring ConfigureRequest\n");
433 DLOG(
"Focusing con = %p\n", con);
438 DLOG(
"Marking con = %p urgent\n", con);
443 DLOG(
"Ignoring request for con = %p.\n", con);
457 DLOG(
"RandR screen change\n");
461 xcb_get_geometry_cookie_t cookie = xcb_get_geometry(
conn,
root);
462 xcb_get_geometry_reply_t *reply = xcb_get_geometry_reply(
conn, cookie, NULL);
464 ELOG(
"Could not get geometry of the root window, exiting\n");
467 DLOG(
"root geometry reply: (%d, %d) %d x %d\n", reply->x, reply->y, reply->width, reply->height);
476 ipc_send_event(
"output", I3_IPC_EVENT_OUTPUT,
"{\"change\":\"unspecified\"}");
485 DLOG(
"UnmapNotify for 0x%08x (received from 0x%08x), serial %d\n", event->window, event->event, event->sequence);
486 xcb_get_input_focus_cookie_t cookie;
493 LOG(
"Not a managed window, ignoring UnmapNotify event\n");
501 cookie = xcb_get_input_focus(
conn);
502 DLOG(
"ignore_unmap = %d for frame of container %p\n", con->
ignore_unmap, con);
507 cookie = xcb_get_input_focus(
conn);
517 xcb_delete_property(
conn, event->window, A__NET_WM_DESKTOP);
518 xcb_delete_property(
conn, event->window, A__NET_WM_STATE);
544 free(xcb_get_input_focus_reply(
conn, cookie, NULL));
557 DLOG(
"destroy notify for 0x%08x, 0x%08x\n", event->event, event->window);
559 xcb_unmap_notify_event_t unmap;
560 unmap.sequence =
event->sequence;
561 unmap.event =
event->event;
562 unmap.window =
event->window;
568 if ((old_name == NULL) && (window->
name == NULL)) {
573 if ((old_name == NULL) ^ (window->
name == NULL)) {
644 DLOG(
"window = %08x\n", event->window);
647 LOG(
"expose event for unknown window, ignoring\n");
658#define _NET_WM_MOVERESIZE_SIZE_TOPLEFT 0
659#define _NET_WM_MOVERESIZE_SIZE_TOP 1
660#define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT 2
661#define _NET_WM_MOVERESIZE_SIZE_RIGHT 3
662#define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4
663#define _NET_WM_MOVERESIZE_SIZE_BOTTOM 5
664#define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT 6
665#define _NET_WM_MOVERESIZE_SIZE_LEFT 7
666#define _NET_WM_MOVERESIZE_MOVE 8
667#define _NET_WM_MOVERESIZE_SIZE_KEYBOARD 9
668#define _NET_WM_MOVERESIZE_MOVE_KEYBOARD 10
669#define _NET_WM_MOVERESIZE_CANCEL 11
671#define _NET_MOVERESIZE_WINDOW_X (1 << 8)
672#define _NET_MOVERESIZE_WINDOW_Y (1 << 9)
673#define _NET_MOVERESIZE_WINDOW_WIDTH (1 << 10)
674#define _NET_MOVERESIZE_WINDOW_HEIGHT (1 << 11)
683 if (atom == A__NET_WM_STATE_FULLSCREEN) {
684 DLOG(
"Received a client message to %s _NET_WM_STATE_FULLSCREEN.\n", debug_change);
690 DLOG(
"toggling fullscreen\n");
693 }
else if (atom == A__NET_WM_STATE_DEMANDS_ATTENTION) {
694 DLOG(
"Received a client message to %s _NET_WM_STATE_DEMANDS_ATTENTION.\n", debug_change);
707 }
else if (atom == A__NET_WM_STATE_STICKY) {
708 DLOG(
"Received a client message to %s _NET_WM_STATE_STICKY.\n", debug_change);
718 DLOG(
"New sticky status for con = %p is %i.\n", con, con->
sticky);
723 DLOG(
"Unknown atom in ClientMessage to %s type %u\n", debug_change, atom);
737 if (sn_xcb_display_process_event(
sndisplay, (xcb_generic_event_t *)event)) {
741 LOG(
"ClientMessage for window 0x%08x\n", event->window);
742 if (event->type == A__NET_WM_STATE) {
743 if (event->format != 32) {
744 DLOG(
"Unknown format %d in ClientMessage\n", event->format);
750 DLOG(
"Could not get window for client message\n");
754 for (
size_t i = 0; i <
sizeof(
event->data.data32) /
sizeof(
event->data.data32[0]) - 1; i++) {
757 }
else if (event->type == A__NET_ACTIVE_WINDOW) {
758 if (event->format != 32) {
762 DLOG(
"_NET_ACTIVE_WINDOW: Window 0x%08x should be activated\n", event->window);
766 DLOG(
"Could not get window for client message\n");
772 DLOG(
"Window is not being managed, ignoring _NET_ACTIVE_WINDOW\n");
777 DLOG(
"Workspace is internal but not scratchpad, ignoring _NET_ACTIVE_WINDOW\n");
782 if (event->data.data32[0] == 2) {
785 DLOG(
"This request came from a pager. Focusing con = %p\n", con);
798 DLOG(
"Ignoring request to make con = %p active because it's on an internal workspace.\n", con);
803 DLOG(
"Focusing con = %p\n", con);
806 DLOG(
"Marking con = %p urgent\n", con);
810 DLOG(
"Ignoring request for con = %p.\n", con);
815 }
else if (event->type == A_I3_SYNC) {
816 xcb_window_t window =
event->data.data32[0];
817 uint32_t rnd =
event->data.data32[1];
819 }
else if (event->type == A__NET_REQUEST_FRAME_EXTENTS) {
832 DLOG(
"_NET_REQUEST_FRAME_EXTENTS for window 0x%08x\n", event->window);
843 XCB_PROP_MODE_REPLACE,
845 A__NET_FRAME_EXTENTS,
846 XCB_ATOM_CARDINAL, 32, 4,
849 }
else if (event->type == A_WM_CHANGE_STATE) {
851 if (event->data.data32[0] == XCB_ICCCM_WM_STATE_ICONIC) {
854 DLOG(
"Client has requested iconic state, rejecting. (window = %08x)\n", event->window);
855 long data[] = {XCB_ICCCM_WM_STATE_NORMAL, XCB_NONE};
856 xcb_change_property(
conn, XCB_PROP_MODE_REPLACE, event->window,
857 A_WM_STATE, A_WM_STATE, 32, 2, data);
859 DLOG(
"Not handling WM_CHANGE_STATE request. (window = %08x, state = %d)\n", event->window, event->data.data32[0]);
861 }
else if (event->type == A__NET_CURRENT_DESKTOP) {
867 DLOG(
"Request to change current desktop to index %d\n", event->data.data32[0]);
870 ELOG(
"Could not determine workspace for this index, ignoring request.\n");
874 DLOG(
"Handling request to focus workspace %s\n", ws->
name);
877 }
else if (event->type == A__NET_WM_DESKTOP) {
878 uint32_t index =
event->data.data32[0];
879 DLOG(
"Request to move window %d to EWMH desktop index %d\n", event->window, index);
883 DLOG(
"Couldn't find con for window %d, ignoring the request.\n", event->window);
890 DLOG(
"The window was requested to be visible on all workspaces, making it sticky and floating.\n");
902 ELOG(
"Could not determine workspace for this index, ignoring request.\n");
911 }
else if (event->type == A__NET_CLOSE_WINDOW) {
919 DLOG(
"Handling _NET_CLOSE_WINDOW request (con = %p)\n", con);
921 if (event->data.data32[0]) {
928 DLOG(
"Couldn't find con for _NET_CLOSE_WINDOW request. (window = %08x)\n", event->window);
930 }
else if (event->type == A__NET_WM_MOVERESIZE) {
937 DLOG(
"Couldn't find con for _NET_WM_MOVERESIZE request, or con not floating (window = %08x)\n", event->window);
940 DLOG(
"Handling _NET_WM_MOVERESIZE request (con = %p)\n", con);
941 uint32_t direction =
event->data.data32[2];
942 uint32_t x_root =
event->data.data32[0];
943 uint32_t y_root =
event->data.data32[1];
945 xcb_button_press_event_t fake = {
948 .event_x = x_root - (con->
rect.
x),
949 .event_y = y_root - (con->
rect.
y)};
958 DLOG(
"_NET_WM_MOVERESIZE direction %d not implemented\n", direction);
961 }
else if (event->type == A__NET_MOVERESIZE_WINDOW) {
962 DLOG(
"Received _NET_MOVE_RESIZE_WINDOW. Handling by faking a configure request.\n");
964 void *_generated_event =
scalloc(32, 1);
965 xcb_configure_request_event_t *generated_event = _generated_event;
967 generated_event->window =
event->window;
968 generated_event->response_type = XCB_CONFIGURE_REQUEST;
970 generated_event->value_mask = 0;
972 generated_event->value_mask |= XCB_CONFIG_WINDOW_X;
973 generated_event->x =
event->data.data32[1];
976 generated_event->value_mask |= XCB_CONFIG_WINDOW_Y;
977 generated_event->y =
event->data.data32[2];
980 generated_event->value_mask |= XCB_CONFIG_WINDOW_WIDTH;
981 generated_event->width =
event->data.data32[3];
984 generated_event->value_mask |= XCB_CONFIG_WINDOW_HEIGHT;
985 generated_event->height =
event->data.data32[4];
989 FREE(generated_event);
991 DLOG(
"Skipping client message for unhandled type %d\n", event->type);
1064 DLOG(
"focus change in, for window 0x%08x\n", event->event);
1066 if (event->event ==
root) {
1067 DLOG(
"Received focus in for root window, refocusing the focused window.\n");
1077 DLOG(
"That is con %p / %s\n", con, con->
name);
1079 if (event->mode == XCB_NOTIFY_MODE_GRAB ||
1080 event->mode == XCB_NOTIFY_MODE_UNGRAB) {
1081 DLOG(
"FocusIn event for grab/ungrab, ignoring\n");
1085 if (event->detail == XCB_NOTIFY_DETAIL_POINTER) {
1086 DLOG(
"notify detail is pointer, ignoring this event\n");
1093 DLOG(
"focus matches the currently focused window, not doing anything\n");
1099 DLOG(
"This is a dock client, not focusing.\n");
1103 DLOG(
"focus is different / refocusing floating window: updating decorations\n");
1118 const char *window_name, *mode, *detail;
1121 window_name = con->
name;
1122 if (window_name == NULL) {
1123 window_name =
"<unnamed con>";
1125 }
else if (event->event ==
root) {
1126 window_name =
"<the root window>";
1128 window_name =
"<unknown window>";
1131 switch (event->mode) {
1132 case XCB_NOTIFY_MODE_NORMAL:
1135 case XCB_NOTIFY_MODE_GRAB:
1138 case XCB_NOTIFY_MODE_UNGRAB:
1141 case XCB_NOTIFY_MODE_WHILE_GRABBED:
1142 mode =
"WhileGrabbed";
1149 switch (event->detail) {
1150 case XCB_NOTIFY_DETAIL_ANCESTOR:
1151 detail =
"Ancestor";
1153 case XCB_NOTIFY_DETAIL_VIRTUAL:
1156 case XCB_NOTIFY_DETAIL_INFERIOR:
1157 detail =
"Inferior";
1159 case XCB_NOTIFY_DETAIL_NONLINEAR:
1160 detail =
"Nonlinear";
1162 case XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL:
1163 detail =
"NonlinearVirtual";
1165 case XCB_NOTIFY_DETAIL_POINTER:
1168 case XCB_NOTIFY_DETAIL_POINTER_ROOT:
1169 detail =
"PointerRoot";
1171 case XCB_NOTIFY_DETAIL_NONE:
1179 DLOG(
"focus change out: window 0x%08x (con %p, %s) lost focus with detail=%s, mode=%s\n", event->event, con, window_name, detail, mode);
1188 if (event->event !=
root) {
1189 DLOG(
"ConfigureNotify for non-root window 0x%08x, ignoring\n", event->event);
1192 DLOG(
"ConfigureNotify for root window 0x%08x\n", event->event);
1199 ipc_send_event(
"output", I3_IPC_EVENT_OUTPUT,
"{\"change\":\"unspecified\"}");
1207 if (event->selection !=
wm_sn) {
1208 DLOG(
"SelectionClear for unknown selection %d, ignoring\n", event->selection);
1211 LOG(
"Lost WM_Sn selection, exiting.\n");
1245 if (has_mwm_hints && motif_border_style != con->
border_style) {
1246 DLOG(
"Update border style of con %p to %d\n", con, motif_border_style);
1269 if (output != NULL) {
1270 DLOG(
"Starting search at output %s\n", output->
name);
1276 DLOG(
"Top dock client\n");
1279 DLOG(
"Bottom dock client\n");
1282 DLOG(
"Ignoring invalid reserved edges (_NET_WM_STRUT_PARTIAL), using position as fallback:\n");
1284 DLOG(
"geom->y = %d < rect.height / 2 = %d, it is a top dock client\n",
1288 DLOG(
"geom->y = %d >= rect.height / 2 = %d, it is a bottom dock client\n",
1296 assert(dockarea != NULL);
1319 DLOG(
"floating change for con %p\n", con);
1359#define NUM_HANDLERS (sizeof(property_handlers) / sizeof(struct property_handler_t))
1387 xcb_get_property_reply_t *propr = NULL;
1388 xcb_generic_error_t *err = NULL;
1400 if (handler == NULL) {
1406 DLOG(
"Received property for atom %d for unknown client\n",
atom);
1410 if (
state != XCB_PROPERTY_DELETE) {
1411 xcb_get_property_cookie_t cookie = xcb_get_property(
conn, 0, window,
atom, XCB_GET_PROPERTY_TYPE_ANY, 0, handler->
long_len);
1412 propr = xcb_get_property_reply(
conn, cookie, &err);
1414 DLOG(
"got error %d when getting property of atom %d\n", err->error_code,
atom);
1421 if (!handler->
cb(con, propr)) {
1432 if (type != XCB_MOTION_NOTIFY) {
1437 type ==
randr_base + XCB_RANDR_SCREEN_CHANGE_NOTIFY) {
1443 DLOG(
"xkb event, need to handle it.\n");
1445 xcb_xkb_state_notify_event_t *
state = (xcb_xkb_state_notify_event_t *)event;
1446 if (
state->xkbType == XCB_XKB_NEW_KEYBOARD_NOTIFY) {
1447 DLOG(
"xkb new keyboard notify, sequence %d, time %d\n",
state->sequence,
state->time);
1448 xcb_key_symbols_free(
keysyms);
1450 if (((xcb_xkb_new_keyboard_notify_event_t *)event)->changed & XCB_XKB_NKN_DETAIL_KEYCODES) {
1456 }
else if (
state->xkbType == XCB_XKB_MAP_NOTIFY) {
1458 DLOG(
"Ignoring map notify event for sequence %d.\n",
state->sequence);
1460 DLOG(
"xkb map notify, sequence %d, time %d\n",
state->sequence,
state->time);
1462 xcb_key_symbols_free(
keysyms);
1469 }
else if (
state->xkbType == XCB_XKB_STATE_NOTIFY) {
1470 DLOG(
"xkb state group = %d\n",
state->group);
1483 xcb_shape_notify_event_t *shape = (xcb_shape_notify_event_t *)event;
1485 DLOG(
"shape_notify_event for window 0x%08x, shape_kind = %d, shaped = %d\n",
1486 shape->affected_window, shape->shape_kind, shape->shaped);
1490 LOG(
"Not a managed window 0x%08x, ignoring shape_notify_event\n",
1491 shape->affected_window);
1495 if (shape->shape_kind == XCB_SHAPE_SK_BOUNDING ||
1496 shape->shape_kind == XCB_SHAPE_SK_INPUT) {
1497 x_set_shape(con, shape->shape_kind, shape->shaped);
1505 case XCB_KEY_RELEASE:
1509 case XCB_BUTTON_PRESS:
1510 case XCB_BUTTON_RELEASE:
1514 case XCB_MAP_REQUEST:
1518 case XCB_UNMAP_NOTIFY:
1522 case XCB_DESTROY_NOTIFY:
1527 if (((xcb_expose_event_t *)event)->count == 0) {
1533 case XCB_MOTION_NOTIFY:
1538 case XCB_ENTER_NOTIFY:
1545 case XCB_CLIENT_MESSAGE:
1550 case XCB_CONFIGURE_REQUEST:
1555 case XCB_MAPPING_NOTIFY:
1567 case XCB_PROPERTY_NOTIFY: {
1568 xcb_property_notify_event_t *e = (xcb_property_notify_event_t *)event;
1574 case XCB_CONFIGURE_NOTIFY:
1578 case XCB_SELECTION_CLEAR:
bool load_keymap(void)
Loads the XKB keymap from the X11 server and feeds it to xkbcommon.
void grab_all_keys(xcb_connection_t *conn)
Grab the bound keys (tell X to send us keypress events for those keycodes)
void translate_keysyms(void)
Translates keysymbols to keycodes for all bindings which use keysyms.
void handle_button_press(xcb_button_press_event_t *event)
The button press X callback.
void con_move_to_workspace(Con *con, Con *workspace, bool fix_coordinates, bool dont_warp, bool ignore_focus)
Moves the given container to the currently focused container on the given workspace.
void con_set_urgency(Con *con, bool urgent)
Set urgency flag to the container, all the parent containers and the workspace.
bool con_is_floating(Con *con)
Returns true if the node is floating.
Con * con_for_window(Con *con, i3Window *window, Match **store_match)
Returns the first container below 'con' which wants to swallow this window TODO: priority.
Con * con_get_workspace(Con *con)
Gets the workspace container this node is on.
void con_set_border_style(Con *con, border_style_t border_style, int border_width)
Sets the given border style on con, correctly keeping the position/size of a floating window.
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.
void con_activate_unblock(Con *con)
Activates the container like in con_activate but removes fullscreen restrictions and properly warps t...
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...
Con * con_get_fullscreen_covering_ws(Con *ws)
Returns the fullscreen node that covers the given workspace if it exists.
Con * con_inside_floating(Con *con)
Checks if the given container is either floating or inside some floating container.
bool con_is_internal(Con *con)
Returns true if the container is internal, such as __i3_scratch.
void con_detach(Con *con)
Detaches the given container from its current parent.
void con_toggle_fullscreen(Con *con, int fullscreen_mode)
Toggles fullscreen mode for the given container.
void con_attach(Con *con, Con *parent, bool ignore_focus)
Attaches the given container to the given parent.
Con * con_by_frame_id(xcb_window_t frame)
Returns the container with the given frame ID or NULL if no such container exists.
bool con_is_leaf(Con *con)
Returns true when this node is a leaf node (has no children)
void con_focus(Con *con)
Sets input focus to the given container.
Con * con_get_output(Con *con)
Gets the output container (first container with CT_OUTPUT in hierarchy) this node is on.
Con * con_descend_focused(Con *con)
Returns the focused con inside this client, descending the tree as far as possible.
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...
Con * ewmh_get_workspace_by_index(uint32_t idx)
Returns the workspace container as enumerated by the EWMH desktop model.
void ewmh_update_wm_desktop(void)
Updates _NET_WM_DESKTOP for all windows.
void ewmh_update_sticky(xcb_window_t window, bool sticky)
Set or remove _NET_WM_STATE_STICKY on the window.
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...
void floating_check_size(Con *floating_con, bool prefer_height)
Called when a floating window is created or resized.
void floating_drag_window(Con *con, const xcb_button_press_event_t *event, bool use_threshold)
Called when the user clicked on the titlebar of a floating window.
bool floating_enable(Con *con, bool automatic)
Enables floating mode for the given container by detaching it from its parent, creating a new contain...
bool floating_reposition(Con *con, Rect newrect)
Repositions the CT_FLOATING_CON to have the coordinates specified by newrect, but only if the coordin...
static void handle_focus_in(xcb_focus_in_event_t *event)
static void handle_selection_clear(xcb_selection_clear_event_t *event)
static bool handle_windowname_change(Con *con, xcb_get_property_reply_t *prop)
static void handle_enter_notify(xcb_enter_notify_event_t *event)
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.
static void handle_map_request(xcb_map_request_event_t *event)
static bool handle_hints(Con *con, xcb_get_property_reply_t *reply)
#define _NET_WM_MOVERESIZE_SIZE_TOPLEFT
static void handle_screen_change(xcb_generic_event_t *e)
bool(* cb_property_handler_t)(Con *con, xcb_get_property_reply_t *property)
static void handle_configure_notify(xcb_configure_notify_event_t *event)
#define _NET_WM_MOVERESIZE_SIZE_LEFT
static bool handle_motif_hints_change(Con *con, xcb_get_property_reply_t *prop)
static void handle_destroy_notify_event(xcb_destroy_notify_event_t *event)
static bool handle_class_change(Con *con, xcb_get_property_reply_t *prop)
static void check_crossing_screen_boundary(uint32_t x, uint32_t y)
static bool handle_clientleader_change(Con *con, xcb_get_property_reply_t *prop)
static bool handle_windowicon_change(Con *con, xcb_get_property_reply_t *prop)
static void handle_client_message(xcb_client_message_event_t *event)
static void property_notify(uint8_t state, xcb_window_t window, xcb_atom_t atom)
bool event_is_ignored(const int sequence, const int response_type)
Checks if the given sequence is ignored and returns true if so.
#define _NET_MOVERESIZE_WINDOW_HEIGHT
static struct property_handler_t property_handlers[]
static bool handle_strut_partial_change(Con *con, xcb_get_property_reply_t *prop)
void property_handlers_init(void)
Sets the appropriate atoms for the property handlers after the atoms were received from X11.
#define _NET_MOVERESIZE_WINDOW_Y
#define COPY_MASK_MEMBER(mask_member, event_member)
static bool window_name_changed(i3Window *window, char *old_name)
static bool handle_windowname_change_legacy(Con *con, xcb_get_property_reply_t *prop)
static bool handle_normal_hints(Con *con, xcb_get_property_reply_t *reply)
static void handle_unmap_notify_event(xcb_unmap_notify_event_t *event)
static bool handle_i3_floating(Con *con, xcb_get_property_reply_t *prop)
static void handle_configure_request(xcb_configure_request_event_t *event)
static bool handle_window_type(Con *con, xcb_get_property_reply_t *reply)
#define _NET_MOVERESIZE_WINDOW_WIDTH
#define _NET_WM_MOVERESIZE_MOVE
static void handle_mapping_notify(xcb_mapping_notify_event_t *event)
static void handle_expose_event(xcb_expose_event_t *event)
static void handle_motion_notify(xcb_motion_notify_event_t *event)
static bool handle_machine_change(Con *con, xcb_get_property_reply_t *prop)
#define _NET_MOVERESIZE_WINDOW_X
static bool handle_transient_for(Con *con, xcb_get_property_reply_t *prop)
static void handle_net_wm_state_change(Con *con, uint32_t change, uint32_t atom)
static bool handle_windowrole_change(Con *con, xcb_get_property_reply_t *prop)
static void handle_focus_out(xcb_focus_in_event_t *event)
void handle_key_press(xcb_key_press_event_t *event)
There was a key press.
Con * remanage_window(Con *con)
Remanages a window: performs a swallow check and runs assignments.
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.
void output_push_sticky_windows(Con *old_focus)
Iterates over all outputs and pushes sticky windows to the currently visible workspace on that output...
char * output_primary_name(Output *output)
Retrieves the primary name of an output.
Con * output_get_content(Con *output)
Returns the output container below the given output container.
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 randr_query_outputs(void)
(Re-)queries the outputs via RandR and stores them in the list of outputs.
int render_deco_height(void)
Returns the height for the decorations.
void scratchpad_fix_resolution(void)
When starting i3 initially (and after each change to the connected outputs), this function fixes the ...
bool scratchpad_show(Con *con)
Either shows the top-most scratchpad window (con == NULL) or shows the specified con (if it is scratc...
void startup_monitor_event(SnMonitorEvent *event, void *userdata)
Called by libstartup-notification when something happens.
void sync_respond(xcb_window_t window, uint32_t rnd)
bool tree_close_internal(Con *con, kill_window_t kill_window, bool dont_kill_parent)
Closes the given container including all children.
void tree_render(void)
Renders the tree, that is rendering all outputs using render_con() and pushing the changes to X11 usi...
bool rect_contains(Rect rect, uint32_t x, uint32_t y)
void window_update_icon(i3Window *win, xcb_get_property_reply_t *prop)
Updates the _NET_WM_ICON.
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).
void window_update_strut_partial(i3Window *win, xcb_get_property_reply_t *prop)
Updates the _NET_WM_STRUT_PARTIAL (reserved pixels at the screen edges)
void window_update_role(i3Window *win, xcb_get_property_reply_t *prop)
Updates the WM_WINDOW_ROLE.
void window_update_name_legacy(i3Window *win, xcb_get_property_reply_t *prop)
Updates the name by using WM_NAME (encoded in COMPOUND_TEXT).
void window_update_transient_for(i3Window *win, xcb_get_property_reply_t *prop)
Updates the TRANSIENT_FOR (logical parent window).
void window_update_machine(i3Window *win, xcb_get_property_reply_t *prop)
Updates the WM_CLIENT_MACHINE.
void window_update_leader(i3Window *win, xcb_get_property_reply_t *prop)
Updates the CLIENT_LEADER (logical parent window).
bool window_update_normal_hints(i3Window *win, xcb_get_property_reply_t *reply, xcb_get_geometry_reply_t *geom)
Updates the WM_NORMAL_HINTS.
void window_update_name(i3Window *win, xcb_get_property_reply_t *prop)
Updates the name by using _NET_WM_NAME (encoded in UTF-8) for the given window.
void window_update_class(i3Window *win, xcb_get_property_reply_t *prop)
Updates the WM_CLASS (consisting of the class and instance) for the given window.
void window_update_type(i3Window *window, xcb_get_property_reply_t *reply)
Updates the _NET_WM_WINDOW_TYPE property.
bool window_update_motif_hints(i3Window *win, xcb_get_property_reply_t *prop, border_style_t *motif_border_style)
Updates the MOTIF_WM_HINTS.
void workspace_show(Con *workspace)
Switches to the given workspace.
bool workspace_is_visible(Con *ws)
Returns true if the workspace is currently visible.
Con * workspace_get(const char *num)
Returns a pointer to the workspace with the given number (starting at 0), creating the workspace if n...
xcb_window_t focused_id
Stores the X11 window ID of the currently focused window.
void x_push_changes(Con *con)
Pushes all changes (state of each node, see x_push_node() and the window stack) to X11.
void x_set_shape(Con *con, xcb_shape_sk_t kind, bool enable)
Enables or disables nonrectangular shape of the container frame.
unsigned int xcb_numlock_mask
void fake_absolute_configure_notify(Con *con)
Generates a configure_notify_event with absolute coordinates (relative to the X root window,...
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...
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,...
xcb_timestamp_t last_timestamp
The last timestamp we got from X11 (timestamps are included in some events and are used for some thin...
xcb_connection_t * conn
XCB connection and root screen.
xcb_key_symbols_t * keysyms
layout_t
Container layouts.
void add_ignore_event(const int sequence, const int response_type)
Adds the given sequence to the list of events which are ignored.
void draw_util_copy_surface(surface_t *src, surface_t *dest, double src_x, double src_y, double dest_x, double dest_y, double width, double height)
Copies a surface onto another surface.
char * sstrdup(const char *str)
Safe-wrapper around strdup which exits if malloc returns NULL (meaning that there is no more memory a...
const char * i3string_as_utf8(i3String *str)
Returns the UTF-8 encoded version of the i3String.
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 * scalloc(size_t num, size_t size)
Safe-wrapper around calloc which exits if malloc returns NULL (meaning that there is no more memory a...
void * smalloc(size_t size)
Safe-wrapper around malloc which exits if malloc returns NULL (meaning that there is no more memory a...
#define SLIST_FOREACH(var, head, field)
#define SLIST_INSERT_HEAD(head, elm, field)
#define SLIST_NEXT(elm, field)
#define TAILQ_FIRST(head)
#define SLIST_HEAD(name, type)
#define SLIST_FIRST(head)
#define SLIST_REMOVE(head, elm, type, field)
#define TAILQ_FOREACH_REVERSE(var, head, headname, field)
#define NET_WM_DESKTOP_ALL
#define _NET_WM_STATE_TOGGLE
#define _NET_WM_STATE_REMOVE
#define _NET_WM_STATE_ADD
bool disable_focus_follows_mouse
By default, focus follows mouse.
enum Config::@4 focus_on_window_activation
Behavior when a window sends a NET_ACTIVE_WINDOW message.
Stores a rectangle, for example the size of a window, the child window etc.
An Output is a physical output on your graphics driver.
Con * con
Pointer to the Con which represents this output.
A 'Window' is a type which contains an xcb_window_t and all the related information (hints like _NET_...
i3String * name
The name of the window.
enum Window::@11 dock
Whether the window says it is a dock window.
struct reservedpx reserved
Pixels the window reserves.
A "match" is a data structure which acts like a mask or expression to match certain windows or not.
A 'Con' represents everything from the X11 root window down to a single X11 window.
uint8_t ignore_unmap
This counter contains the number of UnmapNotify events for this container (or, more precisely,...
border_style_t border_style
struct Rect geometry
the geometry this window requested when getting mapped
enum Con::@19 floating
floating? (= not in tiling layout) This cannot be simply a bool because we want to keep track of whet...
fullscreen_mode_t fullscreen_mode