void property_notify(xcb_generic_event_t *evt) { xcb_property_notify_event_t *e = (xcb_property_notify_event_t *) evt; /* PRINTF("property notify %X\n", e->window); */ if (e->atom != XCB_ATOM_WM_HINTS && e->atom != XCB_ATOM_WM_NORMAL_HINTS) return; coordinates_t loc; if (!locate_window(e->window, &loc)) return; if (e->atom == XCB_ATOM_WM_HINTS) { xcb_icccm_wm_hints_t hints; if (xcb_icccm_get_wm_hints_reply(dpy, xcb_icccm_get_wm_hints(dpy, e->window), &hints, NULL) == 1 && (hints.flags & XCB_ICCCM_WM_HINT_X_URGENCY)) set_urgency(loc.monitor, loc.desktop, loc.node, xcb_icccm_wm_hints_get_urgency(&hints)); } else if (e->atom == XCB_ATOM_WM_NORMAL_HINTS) { client_t *c = loc.node->client; xcb_size_hints_t size_hints; if (xcb_icccm_get_wm_normal_hints_reply(dpy, xcb_icccm_get_wm_normal_hints(dpy, e->window), &size_hints, NULL) == 1 && (size_hints.flags & (XCB_ICCCM_SIZE_HINT_P_MIN_SIZE | XCB_ICCCM_SIZE_HINT_P_MAX_SIZE))) { c->min_width = size_hints.min_width; c->max_width = size_hints.max_width; c->min_height = size_hints.min_height; c->max_height = size_hints.max_height; int w = c->floating_rectangle.width; int h = c->floating_rectangle.height; restrain_floating_size(c, &w, &h); c->floating_rectangle.width = w; c->floating_rectangle.height = h; arrange(loc.monitor, loc.desktop); } } }
void track_pointer(int root_x, int root_y) { if (frozen_pointer->action == ACTION_NONE) return; int delta_x, delta_y, x = 0, y = 0, w = 1, h = 1; pointer_action_t pac = frozen_pointer->action; monitor_t *m = frozen_pointer->monitor; desktop_t *d = frozen_pointer->desktop; node_t *n = frozen_pointer->node; client_t *c = frozen_pointer->client; xcb_window_t win = frozen_pointer->window; xcb_rectangle_t rect = frozen_pointer->rectangle; node_t *vertical_fence = frozen_pointer->vertical_fence; node_t *horizontal_fence = frozen_pointer->horizontal_fence; delta_x = root_x - frozen_pointer->position.x; delta_y = root_y - frozen_pointer->position.y; switch (pac) { case ACTION_MOVE: if (frozen_pointer->is_tiled) { xcb_window_t pwin = XCB_NONE; query_pointer(&pwin, NULL); if (pwin == win) return; coordinates_t loc; bool is_managed = (pwin == XCB_NONE ? false : locate_window(pwin, &loc)); if (is_managed && !IS_FLOATING(loc.node->client) && loc.monitor == m) { swap_nodes(m, d, n, m, d, loc.node); arrange(m, d); } else { if (is_managed && loc.monitor == m) { return; } else if (!is_managed) { xcb_point_t pt = (xcb_point_t) {root_x, root_y}; monitor_t *pmon = monitor_from_point(pt); if (pmon == NULL || pmon == m) { return; } else { loc.monitor = pmon; loc.desktop = pmon->desk; } } bool focused = (n == mon->desk->focus); transfer_node(m, d, n, loc.monitor, loc.desktop, loc.desktop->focus); if (focused) focus_node(loc.monitor, loc.desktop, n); frozen_pointer->monitor = loc.monitor; frozen_pointer->desktop = loc.desktop; } } else { x = rect.x + delta_x; y = rect.y + delta_y; window_move(win, x, y); c->floating_rectangle.x = x; c->floating_rectangle.y = y; xcb_point_t pt = (xcb_point_t) {root_x, root_y}; monitor_t *pmon = monitor_from_point(pt); if (pmon == NULL || pmon == m) return; bool focused = (n == mon->desk->focus); transfer_node(m, d, n, pmon, pmon->desk, pmon->desk->focus); if (focused) focus_node(pmon, pmon->desk, n); frozen_pointer->monitor = pmon; frozen_pointer->desktop = pmon->desk; } break; case ACTION_RESIZE_SIDE: case ACTION_RESIZE_CORNER: if (frozen_pointer->is_tiled) { if (vertical_fence != NULL) { double sr = frozen_pointer->vertical_ratio + (double) delta_x / vertical_fence->rectangle.width; sr = MAX(0, sr); sr = MIN(1, sr); vertical_fence->split_ratio = sr; } if (horizontal_fence != NULL) { double sr = frozen_pointer->horizontal_ratio + (double) delta_y / horizontal_fence->rectangle.height; sr = MAX(0, sr); sr = MIN(1, sr); horizontal_fence->split_ratio = sr; } arrange(m, d); } else { if (pac == ACTION_RESIZE_SIDE) { switch (frozen_pointer->side) { case SIDE_TOP: x = rect.x; y = rect.y + delta_y; w = rect.width; h = rect.height - delta_y; break; case SIDE_RIGHT: x = rect.x; y = rect.y; w = rect.width + delta_x; h = rect.height; break; case SIDE_BOTTOM: x = rect.x; y = rect.y; w = rect.width; h = rect.height + delta_y; break; case SIDE_LEFT: x = rect.x + delta_x; y = rect.y; w = rect.width - delta_x; h = rect.height; break; } } else if (pac == ACTION_RESIZE_CORNER) { switch (frozen_pointer->corner) { case CORNER_TOP_LEFT: x = rect.x + delta_x; y = rect.y + delta_y; w = rect.width - delta_x; h = rect.height - delta_y; break; case CORNER_TOP_RIGHT: x = rect.x; y = rect.y + delta_y; w = rect.width + delta_x; h = rect.height - delta_y; break; case CORNER_BOTTOM_LEFT: x = rect.x + delta_x; y = rect.y; w = rect.width - delta_x; h = rect.height + delta_y; break; case CORNER_BOTTOM_RIGHT: x = rect.x; y = rect.y; w = rect.width + delta_x; h = rect.height + delta_y; break; } } int oldw = w, oldh = h; restrain_floating_size(c, &w, &h); if (c->state == STATE_FLOATING) { if (oldw == w) { c->floating_rectangle.x = x; c->floating_rectangle.width = w; } if (oldh == h) { c->floating_rectangle.y = y; c->floating_rectangle.height = h; } window_move_resize(win, c->floating_rectangle.x, c->floating_rectangle.y, c->floating_rectangle.width, c->floating_rectangle.height); } else { c->floating_rectangle.width = w; c->floating_rectangle.height = h; arrange(m, d); } } break; case ACTION_FOCUS: case ACTION_NONE: break; } }