void configure_request(xcb_generic_event_t *evt) { xcb_configure_request_event_t *e = (xcb_configure_request_event_t *) evt; PRINTF("configure request %X\n", e->window); coordinates_t loc; bool is_managed = locate_window(e->window, &loc); client_t *c = (is_managed ? loc.node->client : NULL); int w = 0, h = 0; if (is_managed && !is_floating(c)) { if (e->value_mask & XCB_CONFIG_WINDOW_X) c->floating_rectangle.x = e->x; if (e->value_mask & XCB_CONFIG_WINDOW_Y) c->floating_rectangle.y = e->y; if (e->value_mask & XCB_CONFIG_WINDOW_WIDTH) w = e->width; if (e->value_mask & XCB_CONFIG_WINDOW_HEIGHT) h = e->height; if (w != 0) { restrain_floating_width(c, &w); c->floating_rectangle.width = w; } if (h != 0) { restrain_floating_height(c, &h); c->floating_rectangle.height = h; } xcb_configure_notify_event_t evt; xcb_rectangle_t rect; xcb_window_t win = c->window; unsigned int bw = c->border_width; if (c->fullscreen) rect = loc.monitor->rectangle; else rect = c->tiled_rectangle; evt.response_type = XCB_CONFIGURE_NOTIFY; evt.event = win; evt.window = win; evt.above_sibling = XCB_NONE; evt.x = rect.x; evt.y = rect.y; evt.width = rect.width; evt.height = rect.height; evt.border_width = bw; evt.override_redirect = false; xcb_send_event(dpy, false, win, XCB_EVENT_MASK_STRUCTURE_NOTIFY, (const char *) &evt); if (c->pseudo_tiled) arrange(loc.monitor, loc.desktop); } else { uint16_t mask = 0; uint32_t values[7]; unsigned short i = 0; if (e->value_mask & XCB_CONFIG_WINDOW_X) { mask |= XCB_CONFIG_WINDOW_X; values[i++] = e->x; if (is_managed) c->floating_rectangle.x = e->x; } if (e->value_mask & XCB_CONFIG_WINDOW_Y) { mask |= XCB_CONFIG_WINDOW_Y; values[i++] = e->y; if (is_managed) c->floating_rectangle.y = e->y; } if (e->value_mask & XCB_CONFIG_WINDOW_WIDTH) { mask |= XCB_CONFIG_WINDOW_WIDTH; w = e->width; if (is_managed) { restrain_floating_width(c, &w); c->floating_rectangle.width = w; } values[i++] = w; } if (e->value_mask & XCB_CONFIG_WINDOW_HEIGHT) { mask |= XCB_CONFIG_WINDOW_HEIGHT; h = e->height; if (is_managed) { restrain_floating_height(c, &h); c->floating_rectangle.height = h; } values[i++] = h; } if (!is_managed && e->value_mask & XCB_CONFIG_WINDOW_BORDER_WIDTH) { mask |= XCB_CONFIG_WINDOW_BORDER_WIDTH; values[i++] = e->border_width; } if (e->value_mask & XCB_CONFIG_WINDOW_SIBLING) { mask |= XCB_CONFIG_WINDOW_SIBLING; values[i++] = e->sibling; } if (e->value_mask & XCB_CONFIG_WINDOW_STACK_MODE) { mask |= XCB_CONFIG_WINDOW_STACK_MODE; values[i++] = e->stack_mode; } xcb_configure_window(dpy, e->window, mask, values); } if (is_managed) translate_client(monitor_from_client(c), loc.monitor, c); }
void manage_window(xcb_window_t win, rule_consequence_t *csq, int fd) { monitor_t *m = mon; desktop_t *d = mon->desk; node_t *f = mon->desk->focus; parse_rule_consequence(fd, csq); if (!csq->manage) { free(csq->layer); free(csq->state); window_show(win); return; } if (csq->node_desc[0] != '\0') { coordinates_t ref = {m, d, f}; coordinates_t trg = {NULL, NULL, NULL}; if (node_from_desc(csq->node_desc, &ref, &trg)) { m = trg.monitor; d = trg.desktop; f = trg.node; } } else if (csq->desktop_desc[0] != '\0') { coordinates_t ref = {m, d, NULL}; coordinates_t trg = {NULL, NULL, NULL}; if (desktop_from_desc(csq->desktop_desc, &ref, &trg)) { m = trg.monitor; d = trg.desktop; f = trg.desktop->focus; } } else if (csq->monitor_desc[0] != '\0') { coordinates_t ref = {m, NULL, NULL}; coordinates_t trg = {NULL, NULL, NULL}; if (monitor_from_desc(csq->monitor_desc, &ref, &trg)) { m = trg.monitor; d = trg.monitor->desk; f = trg.monitor->desk->focus; } } if (csq->sticky) { m = mon; d = mon->desk; f = mon->desk->focus; } if (csq->split_dir[0] != '\0' && f != NULL) { direction_t dir; if (parse_direction(csq->split_dir, &dir)) { presel_dir(m, d, f, dir); } } if (csq->split_ratio != 0 && f != NULL) { presel_ratio(m, d, f, csq->split_ratio); } node_t *n = make_node(win); client_t *c = make_client(); c->border_width = csq->border ? d->border_width : 0; n->client = c; initialize_client(n); update_floating_rectangle(n); if (c->floating_rectangle.x == 0 && c->floating_rectangle.y == 0) { csq->center = true; } c->min_width = csq->min_width; c->max_width = csq->max_width; c->min_height = csq->min_height; c->max_height = csq->max_height; monitor_t *mm = monitor_from_client(c); embrace_client(mm, c); adapt_geometry(&mm->rectangle, &m->rectangle, n); if (csq->center) { window_center(m, c); } snprintf(c->class_name, sizeof(c->class_name), "%s", csq->class_name); snprintf(c->instance_name, sizeof(c->instance_name), "%s", csq->instance_name); f = insert_node(m, d, n, f); clients_count++; put_status(SBSC_MASK_NODE_MANAGE, "node_manage %s %s 0x%X 0x%X\n", m->name, d->name, win, f!=NULL?f->id:0); if (f != NULL && f->client != NULL && csq->state != NULL && *(csq->state) == STATE_FLOATING) { c->last_layer = c->layer = f->client->layer; } if (csq->layer != NULL) { c->last_layer = c->layer = *(csq->layer); } if (csq->state != NULL) { set_state(m, d, n, *(csq->state)); c->last_state = c->state; } set_locked(m, d, n, csq->locked); set_sticky(m, d, n, csq->sticky); set_private(m, d, n, csq->private); arrange(m, d); bool give_focus = (csq->focus && (d == mon->desk || csq->follow)); if (give_focus) { focus_node(m, d, n); } else if (csq->focus) { activate_node(m, d, n); } else { stack(d, n, false); } uint32_t values[] = {CLIENT_EVENT_MASK | (focus_follows_pointer ? XCB_EVENT_MASK_ENTER_WINDOW : 0)}; xcb_change_window_attributes(dpy, win, XCB_CW_EVENT_MASK, values); if (d == m->desk) { window_show(n->id); } else { window_hide(n->id); } /* the same function is already called in `focus_node` but has no effects on unmapped windows */ if (give_focus) { xcb_set_input_focus(dpy, XCB_INPUT_FOCUS_POINTER_ROOT, win, XCB_CURRENT_TIME); } ewmh_set_wm_desktop(n, d); ewmh_update_client_list(false); free(csq->layer); free(csq->state); }
bool move_client(coordinates_t *loc, int dx, int dy) { node_t *n = loc->node; if (n == NULL || n->client == NULL) { return false; } monitor_t *pm = NULL; if (IS_TILED(n->client)) { if (!grabbing) { return false; } xcb_window_t pwin = XCB_NONE; query_pointer(&pwin, NULL); if (pwin == n->id) { return false; } coordinates_t dst; bool is_managed = (pwin != XCB_NONE && locate_window(pwin, &dst)); if (is_managed && dst.monitor == loc->monitor && IS_TILED(dst.node->client)) { swap_nodes(loc->monitor, loc->desktop, n, loc->monitor, loc->desktop, dst.node); return true; } else { if (is_managed && dst.monitor == loc->monitor) { return false; } else { xcb_point_t pt = {0, 0}; query_pointer(NULL, &pt); pm = monitor_from_point(pt); } } } else { client_t *c = n->client; xcb_rectangle_t rect = c->floating_rectangle; int16_t x = rect.x + dx; int16_t y = rect.y + dy; if (focus_follows_pointer) { listen_enter_notify(loc->desktop->root, false); } window_move(n->id, x, y); if (focus_follows_pointer) { listen_enter_notify(loc->desktop->root, true); } c->floating_rectangle.x = x; c->floating_rectangle.y = y; if (!grabbing) { put_status(SBSC_MASK_NODE_GEOMETRY, "node_geometry 0x%08X 0x%08X 0x%08X %ux%u+%i+%i\n", loc->monitor->id, loc->desktop->id, loc->node->id, rect.width, rect.height, x, y); } pm = monitor_from_client(c); } if (pm == NULL || pm == loc->monitor) { return true; } bool focused = (n == mon->desk->focus); transfer_node(loc->monitor, loc->desktop, n, pm, pm->desk, pm->desk->focus); loc->monitor = pm; loc->desktop = pm->desk; if (focused) { focus_node(pm, pm->desk, n); } return true; }
void manage_window(xcb_window_t win, rule_consequence_t *csq, int fd) { monitor_t *m = mon; desktop_t *d = mon->desk; node_t *f = mon->desk->focus; parse_rule_consequence(fd, csq); if (!csq->manage) { free(csq->layer); free(csq->state); window_show(win); return; } if (csq->node_desc[0] != '\0') { coordinates_t ref = {m, d, f}; coordinates_t trg = {NULL, NULL, NULL}; if (node_from_desc(csq->node_desc, &ref, &trg) == SELECTOR_OK) { m = trg.monitor; d = trg.desktop; f = trg.node; } } else if (csq->desktop_desc[0] != '\0') { coordinates_t ref = {m, d, NULL}; coordinates_t trg = {NULL, NULL, NULL}; if (desktop_from_desc(csq->desktop_desc, &ref, &trg) == SELECTOR_OK) { m = trg.monitor; d = trg.desktop; f = trg.desktop->focus; } } else if (csq->monitor_desc[0] != '\0') { coordinates_t ref = {m, NULL, NULL}; coordinates_t trg = {NULL, NULL, NULL}; if (monitor_from_desc(csq->monitor_desc, &ref, &trg) == SELECTOR_OK) { m = trg.monitor; d = trg.monitor->desk; f = trg.monitor->desk->focus; } } if (csq->sticky) { m = mon; d = mon->desk; f = mon->desk->focus; } if (csq->split_dir[0] != '\0' && f != NULL) { direction_t dir; if (parse_direction(csq->split_dir, &dir)) { presel_dir(m, d, f, dir); } } if (csq->split_ratio != 0 && f != NULL) { presel_ratio(m, d, f, csq->split_ratio); } node_t *n = make_node(win); client_t *c = make_client(); c->border_width = csq->border ? d->border_width : 0; n->client = c; initialize_client(n); initialize_floating_rectangle(n); if (c->floating_rectangle.x == 0 && c->floating_rectangle.y == 0) { csq->center = true; } monitor_t *mm = monitor_from_client(c); embrace_client(mm, c); adapt_geometry(&mm->rectangle, &m->rectangle, n); if (csq->center) { window_center(m, c); } snprintf(c->class_name, sizeof(c->class_name), "%s", csq->class_name); snprintf(c->instance_name, sizeof(c->instance_name), "%s", csq->instance_name); f = insert_node(m, d, n, f); clients_count++; put_status(SBSC_MASK_NODE_MANAGE, "node_manage 0x%08X 0x%08X 0x%08X 0x%08X\n", m->id, d->id, win, f!=NULL?f->id:0); if (f != NULL && f->client != NULL && csq->state != NULL && *(csq->state) == STATE_FLOATING) { c->layer = f->client->layer; } if (csq->layer != NULL) { c->layer = *(csq->layer); } if (csq->state != NULL) { set_state(m, d, n, *(csq->state)); } set_hidden(m, d, n, csq->hidden); set_sticky(m, d, n, csq->sticky); set_private(m, d, n, csq->private); set_locked(m, d, n, csq->locked); arrange(m, d); uint32_t values[] = {CLIENT_EVENT_MASK | (focus_follows_pointer ? XCB_EVENT_MASK_ENTER_WINDOW : 0)}; xcb_change_window_attributes(dpy, win, XCB_CW_EVENT_MASK, values); if (d == m->desk) { show_node(d, n); } else { hide_node(d, n); } if (!csq->hidden && csq->focus) { if (d == mon->desk || csq->follow) { focus_node(m, d, n); } else { activate_node(m, d, n); } } else { stack(d, n, false); } ewmh_set_wm_desktop(n, d); ewmh_update_client_list(false); free(csq->layer); free(csq->state); }
void configure_request(xcb_generic_event_t *evt) { xcb_configure_request_event_t *e = (xcb_configure_request_event_t *) evt; coordinates_t loc; bool is_managed = locate_window(e->window, &loc); client_t *c = (is_managed ? loc.node->client : NULL); int w = 0, h = 0; if (is_managed && !IS_FLOATING(c)) { if (e->value_mask & XCB_CONFIG_WINDOW_X) { c->floating_rectangle.x = e->x; } if (e->value_mask & XCB_CONFIG_WINDOW_Y) { c->floating_rectangle.y = e->y; } if (e->value_mask & XCB_CONFIG_WINDOW_WIDTH) { w = e->width; } if (e->value_mask & XCB_CONFIG_WINDOW_HEIGHT) { h = e->height; } if (w != 0) { restrain_floating_width(c, &w); c->floating_rectangle.width = w; } if (h != 0) { restrain_floating_height(c, &h); c->floating_rectangle.height = h; } xcb_configure_notify_event_t evt; unsigned int bw = c->border_width; xcb_rectangle_t rect = get_rectangle(loc.desktop, loc.node); evt.response_type = XCB_CONFIGURE_NOTIFY; evt.event = e->window; evt.window = e->window; evt.above_sibling = XCB_NONE; evt.x = rect.x; evt.y = rect.y; evt.width = rect.width; evt.height = rect.height; evt.border_width = bw; evt.override_redirect = false; xcb_send_event(dpy, false, e->window, XCB_EVENT_MASK_STRUCTURE_NOTIFY, (const char *) &evt); if (c->state == STATE_PSEUDO_TILED) { arrange(loc.monitor, loc.desktop); } } else { uint16_t mask = 0; uint32_t values[7]; unsigned short i = 0; if (e->value_mask & XCB_CONFIG_WINDOW_X) { mask |= XCB_CONFIG_WINDOW_X; values[i++] = e->x; if (is_managed) { c->floating_rectangle.x = e->x; } } if (e->value_mask & XCB_CONFIG_WINDOW_Y) { mask |= XCB_CONFIG_WINDOW_Y; values[i++] = e->y; if (is_managed) { c->floating_rectangle.y = e->y; } } if (e->value_mask & XCB_CONFIG_WINDOW_WIDTH) { mask |= XCB_CONFIG_WINDOW_WIDTH; w = e->width; if (is_managed) { restrain_floating_width(c, &w); c->floating_rectangle.width = w; } values[i++] = w; } if (e->value_mask & XCB_CONFIG_WINDOW_HEIGHT) { mask |= XCB_CONFIG_WINDOW_HEIGHT; h = e->height; if (is_managed) { restrain_floating_height(c, &h); c->floating_rectangle.height = h; } values[i++] = h; } if (!is_managed && e->value_mask & XCB_CONFIG_WINDOW_BORDER_WIDTH) { mask |= XCB_CONFIG_WINDOW_BORDER_WIDTH; values[i++] = e->border_width; } if (!is_managed && e->value_mask & XCB_CONFIG_WINDOW_SIBLING) { mask |= XCB_CONFIG_WINDOW_SIBLING; values[i++] = e->sibling; } if (!is_managed && e->value_mask & XCB_CONFIG_WINDOW_STACK_MODE) { mask |= XCB_CONFIG_WINDOW_STACK_MODE; values[i++] = e->stack_mode; } xcb_configure_window(dpy, e->window, mask, values); if (is_managed && mask & XCB_CONFIG_WINDOW_X_Y_WIDTH_HEIGHT) { xcb_rectangle_t r = c->floating_rectangle; put_status(SBSC_MASK_NODE_GEOMETRY, "node_geometry 0x%X 0x%X 0x%X %ux%u+%i+%i\n", loc.monitor->id, loc.desktop->id, e->window, r.width, r.height, r.x, r.y); } } if (is_managed) { monitor_t *m = monitor_from_client(c); adapt_geometry(&m->rectangle, &loc.monitor->rectangle, loc.node); } }