2 #define I3__FILE__ "x.c"
73 static
con_state *state_for_frame(xcb_window_t window) {
76 if (state->
id == window)
80 ELOG(
"No state found\n");
97 xcb_visualid_t visual = XCB_COPY_FROM_PARENT;
98 xcb_colormap_t win_colormap = XCB_NONE;
99 if (depth !=
root_depth && depth != XCB_COPY_FROM_PARENT) {
103 win_colormap = xcb_generate_id(
conn);
104 xcb_create_colormap_checked(
conn, XCB_COLORMAP_ALLOC_NONE, win_colormap,
root, visual);
110 mask |= XCB_CW_BACK_PIXEL;
113 mask |= XCB_CW_BORDER_PIXEL;
117 mask |= XCB_CW_OVERRIDE_REDIRECT;
121 mask |= XCB_CW_EVENT_MASK;
124 mask |= XCB_CW_COLORMAP;
125 values[4] = win_colormap;
128 mask = XCB_CW_OVERRIDE_REDIRECT;
132 mask |= XCB_CW_EVENT_MASK;
135 mask |= XCB_CW_COLORMAP;
139 Rect dims = { -15, -15, 10, 10 };
142 if (win_colormap != XCB_NONE)
143 xcb_free_colormap(
conn, win_colormap);
151 DLOG(
"adding new state for window id 0x%08x\n", state->
id);
163 if ((state = state_for_frame(con->
frame)) == NULL) {
164 ELOG(
"window state not found\n");
168 DLOG(
"resetting state %p to initial\n", state);
182 if ((state = state_for_frame(con->
frame)) == NULL) {
183 ELOG(
"window state for con not found\n");
196 struct con_state *state_src, *state_dest;
198 if ((state_src = state_for_frame(src->
frame)) == NULL) {
199 ELOG(
"window state for src not found\n");
203 if ((state_dest = state_for_frame(dest->
frame)) == NULL) {
204 ELOG(
"window state for dest not found\n");
208 state_dest->
con = state_src->
con;
209 state_src->
con = NULL;
211 Rect zero = { 0, 0, 0, 0 };
214 DLOG(
"COPYING RECT\n");
228 state = state_for_frame(con->
frame);
243 xcb_get_property_cookie_t cookie;
252 for (uint32_t i = 0; i < protocols.atoms_len; i++)
253 if (protocols.atoms[i] == atom)
269 LOG(
"Killing specific window 0x%08x\n", window);
270 xcb_destroy_window(
conn, window);
272 LOG(
"Killing the X11 client which owns window 0x%08x\n", window);
273 xcb_kill_client(
conn, window);
282 xcb_client_message_event_t *ev = event;
284 ev->response_type = XCB_CLIENT_MESSAGE;
286 ev->type = A_WM_PROTOCOLS;
288 ev->data.data32[0] = A_WM_DELETE_WINDOW;
289 ev->data.data32[1] = XCB_CURRENT_TIME;
291 LOG(
"Sending WM_DELETE to the client\n");
292 xcb_send_event(
conn,
false, window, XCB_EVENT_MASK_NO_EVENT, (
char*)ev);
314 parent->
layout != L_STACKED &&
315 parent->
layout != L_TABBED) ||
316 parent->
type == CT_OUTPUT ||
317 parent->
type == CT_DOCKAREA ||
318 con->
type == CT_FLOATING_CON)
328 if (leaf && con->
pixmap == XCB_NONE)
339 else if (con ==
TAILQ_FIRST(&(parent->focus_head)))
379 if (con->
window != NULL) {
380 xcb_rectangle_t background[] = {
391 for (
int i = 0; i < 4; i++)
392 DLOG(
"rect is (%d, %d) with %d x %d\n",
401 xcb_poly_fill_rectangle(
conn, con->
pixmap, con->
pm_gc,
sizeof(background) /
sizeof(xcb_rectangle_t), background);
405 if (p->border_style !=
BS_NONE && p->con_is_leaf) {
413 DLOG(
"border_rect spans (%d, %d) with %d x %d\n", br.
x, br.
y, br.
width, br.
height);
421 xcb_change_gc(
conn,
con->
pm_gc, XCB_GC_FOREGROUND, (uint32_t[]){ p->color->background });
423 xcb_rectangle_t leftline = { 0, 0, br.
x, r->height };
427 xcb_rectangle_t rightline = { r->width + br.
width + br.
x, 0, r->width, r->height };
431 xcb_rectangle_t bottomline = { 0, r->height + br.
height + br.
y, r->width, r->height };
447 xcb_change_gc(
conn,
con->
pm_gc, XCB_GC_FOREGROUND, (uint32_t[]){ p->color->indicator });
448 if (p->parent_orientation ==
HORIZ)
450 { r->width + br.
width + br.
x, br.
y, r->width, r->height + br.
height } });
452 xcb_poly_fill_rectangle(
conn, con->pixmap, con->pm_gc, 1, (xcb_rectangle_t[]){
453 { br.
x, r->height + br.
height + br.
y, r->width - (2 * br.
x), r->height } });
464 xcb_change_gc(
conn, parent->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]){ p->color->background });
465 xcb_rectangle_t drect = { con->deco_rect.x, con->deco_rect.y, con->deco_rect.width, con->deco_rect.height };
466 xcb_poly_fill_rectangle(
conn, parent->pixmap, parent->pm_gc, 1, &drect);
469 xcb_change_gc(
conn, parent->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]){ p->color->border });
470 Rect *dr = &(con->deco_rect);
473 if (parent->layout == L_TABBED) {
474 if (
TAILQ_PREV(con, nodes_head, nodes) != NULL)
479 xcb_segment_t segments[] = {
481 dr->x + dr->width - 1, dr->y },
483 { dr->x + deco_diff_l, dr->y + dr->height - 1,
484 dr->x - deco_diff_r + dr->width - 1, dr->y + dr->height - 1 }
486 xcb_poly_segment(
conn, parent->pixmap, parent->pm_gc, 2, segments);
492 struct Window *win = con->window;
503 parent->pixmap, parent->pm_gc,
504 con->deco_rect.x + 2, con->deco_rect.y + text_offset_y,
505 con->deco_rect.width - 2);
511 if (win->
name == NULL)
514 int indent_level = 0,
516 Con *il_parent = parent;
517 if (il_parent->
layout != L_STACKED) {
520 if (il_parent->
layout == L_STACKED)
522 if (il_parent->
type == CT_WORKSPACE || il_parent->
type == CT_DOCKAREA || il_parent->
type == CT_OUTPUT)
524 il_parent = il_parent->
parent;
529 int indent_px = (indent_level * 5) * indent_mult;
532 parent->pixmap, parent->pm_gc,
533 con->deco_rect.x + 2 + indent_px, con->deco_rect.y + text_offset_y,
534 con->deco_rect.width - 2 - indent_px);
543 if (parent->layout == L_TABBED &&
TAILQ_NEXT(con, nodes) != NULL) {
544 xcb_change_gc(
conn, parent->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]){ p->color->border });
546 xcb_change_gc(
conn, parent->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]){ p->color->background });
548 xcb_poly_line(
conn, XCB_COORD_MODE_ORIGIN, parent->pixmap, parent->pm_gc, 4,
550 { dr->x + dr->width - 1, dr->y },
551 { dr->x + dr->width - 1, dr->y + dr->height },
552 { dr->x + dr->width - 2, dr->y },
553 { dr->x + dr->width - 2, dr->y + dr->height }
556 xcb_change_gc(
conn, parent->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]){ p->color->border });
557 xcb_poly_segment(
conn, parent->pixmap, parent->pm_gc, 2, segments);
560 xcb_copy_area(
conn, con->pixmap, con->frame, con->pm_gc, 0, 0, 0, 0, con->rect.width, con->rect.height);
579 TAILQ_FOREACH(current, &(con->floating_head), floating_windows)
586 if ((con->
type != CT_ROOT && con->
type != CT_OUTPUT) &&
603 state = state_for_frame(con->
frame);
605 if (state->
name != NULL) {
606 DLOG(
"pushing name %s for con %p\n", state->
name, con);
608 xcb_change_property(
conn, XCB_PROP_MODE_REPLACE, con->
frame,
613 if (con->
window == NULL) {
616 uint32_t max_y = 0, max_height = 0;
619 if (dr->
y >= max_y && dr->
height >= max_height) {
624 rect.
height = max_y + max_height;
632 DLOG(
"Reparenting child window\n");
637 uint32_t values[] = { XCB_NONE };
638 xcb_change_window_attributes(
conn, state->
old_frame, XCB_CW_EVENT_MASK, values);
639 xcb_change_window_attributes(
conn, con->
window->
id, XCB_CW_EVENT_MASK, values);
644 xcb_change_window_attributes(
conn, state->
old_frame, XCB_CW_EVENT_MASK, values);
646 xcb_change_window_attributes(
conn, con->
window->
id, XCB_CW_EVENT_MASK, values);
652 DLOG(
"ignore_unmap for reparenting of con %p (win 0x%08x) is now %d\n",
656 bool fake_notify =
false;
658 if (memcmp(&(state->
rect), &rect,
sizeof(
Rect)) != 0 &&
689 uint32_t values[] = { 0 };
690 xcb_create_gc(
conn, con->
pm_gc, con->
pixmap, XCB_GC_GRAPHICS_EXPOSURES, values);
705 DLOG(
"setting rect (%d, %d, %d, %d)\n", rect.
x, rect.
y, rect.
width, rect.
height);
712 if (con->
pixmap != XCB_NONE)
716 memcpy(&(state->
rect), &rect,
sizeof(
Rect));
721 if (con->
window != NULL &&
723 DLOG(
"setting window rect (%d, %d, %d, %d)\n",
736 xcb_void_cookie_t cookie;
738 if (con->
window != NULL) {
742 xcb_change_property(
conn, XCB_PROP_MODE_REPLACE, con->
window->
id,
743 A_WM_STATE, A_WM_STATE, 32, 2, data);
753 xcb_change_window_attributes(
conn, con->
window->
id, XCB_CW_EVENT_MASK, values);
754 DLOG(
"mapping child window (serial %d)\n", cookie.sequence);
758 cookie = xcb_map_window(
conn, con->
frame);
761 xcb_change_window_attributes(
conn, con->
frame, XCB_CW_EVENT_MASK, values);
764 if (con->
pixmap != XCB_NONE)
768 DLOG(
"mapping container %08x (serial %d)\n", con->
frame, cookie.sequence);
775 DLOG(
"Sending fake configure notify\n");
800 state = state_for_frame(con->
frame);
806 xcb_void_cookie_t cookie;
807 if (con->
window != NULL) {
810 xcb_change_property(
conn, XCB_PROP_MODE_REPLACE, con->
window->
id,
811 A_WM_STATE, A_WM_STATE, 32, 2, data);
814 cookie = xcb_unmap_window(
conn, con->
frame);
815 DLOG(
"unmapping container %p / %s (serial %d)\n", con, con->
name, cookie.sequence);
819 if (con->
window != NULL) {
830 TAILQ_FOREACH(current, &(con->floating_head), floating_windows)
847 xcb_query_pointer_cookie_t pointercookie;
851 pointercookie = xcb_query_pointer(
conn,
root);
854 DLOG(
"-- PUSHING WINDOW STACK --\n");
856 uint32_t values[1] = { XCB_NONE };
859 xcb_change_window_attributes(
conn, state->
id, XCB_CW_EVENT_MASK, values);
862 bool order_changed =
false;
863 bool stacking_changed =
false;
882 memcpy(walk++, &(state->
con->
window->
id),
sizeof(xcb_window_t));
887 if (prev != old_prev)
888 order_changed =
true;
890 stacking_changed =
true;
893 mask |= XCB_CONFIG_WINDOW_SIBLING;
894 mask |= XCB_CONFIG_WINDOW_STACK_MODE;
895 uint32_t values[] = {state->
id, XCB_STACK_MODE_ABOVE};
897 xcb_configure_window(
conn, prev->
id, mask, values);
904 if (stacking_changed)
907 DLOG(
"PUSHING CHANGES\n");
911 xcb_query_pointer_reply_t *pointerreply = xcb_query_pointer_reply(
conn, pointercookie, NULL);
913 ELOG(
"Could not query pointer position, not warping pointer\n");
915 int mid_x = warp_to->
x + (warp_to->
width / 2);
916 int mid_y = warp_to->
y + (warp_to->
height / 2);
920 if (current != target)
921 xcb_warp_pointer(
conn, XCB_NONE,
root, 0, 0, 0, 0, mid_x, mid_y);
930 xcb_change_window_attributes(
conn, state->
id, XCB_CW_EVENT_MASK, values);
946 bool set_focus =
true;
949 DLOG(
"Updating focus by sending WM_TAKE_FOCUS to window 0x%08x (focused: %p / %s)\n",
953 DLOG(
"set_focus = %d\n", set_focus);
965 xcb_set_input_focus(
conn, XCB_INPUT_FOCUS_POINTER_ROOT, to_focus, XCB_CURRENT_TIME);
979 DLOG(
"Still no window focused, better set focus to the root window\n");
980 xcb_set_input_focus(
conn, XCB_INPUT_FOCUS_POINTER_ROOT,
root, XCB_CURRENT_TIME);
985 DLOG(
"ENDING CHANGES\n");
998 xcb_change_window_attributes(
conn, state->
id, XCB_CW_EVENT_MASK, values);
1023 state = state_for_frame(con->
frame);
1039 if ((state = state_for_frame(con->
frame)) == NULL) {
1040 ELOG(
"window state not found\n");
1053 pid_t pid = getpid();
1054 xcb_change_property(
conn, XCB_PROP_MODE_REPLACE,
root, A_I3_SOCKET_PATH, A_UTF8_STRING, 8,
1058 xcb_change_property(
conn, XCB_PROP_MODE_REPLACE,
root, A_I3_CONFIG_PATH, A_UTF8_STRING, 8,
1060 xcb_change_property(
conn, XCB_PROP_MODE_REPLACE,
root, A_I3_SHMLOG_PATH, A_UTF8_STRING, 8,
1086 xcb_change_window_attributes(
conn, state->
id, XCB_CW_EVENT_MASK, values);