void move_fence(node_t *n, direction_t dir, fence_move_t mov) { node_t *fence = find_fence(n, dir); if (fence == NULL) return; if ((mov == MOVE_PUSH && (dir == DIR_RIGHT || dir == DIR_DOWN)) || (mov == MOVE_PULL && (dir == DIR_LEFT || dir == DIR_UP))) change_split_ratio(fence, CHANGE_INCREASE); else change_split_ratio(fence, CHANGE_DECREASE); }
node_t *find_neighbor(node_t *n, direction_t dir) { node_t *fence = find_fence(n, dir); if (fence == NULL) return NULL; if (dir == DIR_UP || dir == DIR_LEFT) return second_extrema(fence->first_child); else if (dir == DIR_DOWN || dir == DIR_RIGHT) return first_extrema(fence->second_child); return NULL; }
void grab_pointer(pointer_action_t pac) { PRINTF("grab pointer %u\n", pac); xcb_window_t win = XCB_NONE; xcb_point_t pos; query_pointer(&win, &pos); coordinates_t loc; if (locate_window(win, &loc)) { client_t *c = NULL; frozen_pointer->position = pos; frozen_pointer->action = pac; c = loc.node->client; frozen_pointer->monitor = loc.monitor; frozen_pointer->desktop = loc.desktop; frozen_pointer->node = loc.node; frozen_pointer->client = c; frozen_pointer->window = c->window; frozen_pointer->horizontal_fence = NULL; frozen_pointer->vertical_fence = NULL; switch (pac) { case ACTION_FOCUS: if (loc.node != mon->desk->focus) { bool backup = pointer_follows_monitor; pointer_follows_monitor = false; focus_node(loc.monitor, loc.desktop, loc.node); pointer_follows_monitor = backup; } else if (focus_follows_pointer) { stack(loc.node, STACK_ABOVE); } frozen_pointer->action = ACTION_NONE; break; case ACTION_MOVE: case ACTION_RESIZE_SIDE: case ACTION_RESIZE_CORNER: if (is_tiled(c)) { frozen_pointer->rectangle = c->tiled_rectangle; frozen_pointer->is_tiled = true; } else if (is_floating(c)) { frozen_pointer->rectangle = c->floating_rectangle; frozen_pointer->is_tiled = false; } else { frozen_pointer->action = ACTION_NONE; return; } if (pac == ACTION_RESIZE_SIDE) { float W = frozen_pointer->rectangle.width; float H = frozen_pointer->rectangle.height; float ratio = W / H; float x = pos.x - frozen_pointer->rectangle.x; float y = pos.y - frozen_pointer->rectangle.y; float diag_a = ratio * y; float diag_b = W - diag_a; if (x < diag_a) { if (x < diag_b) frozen_pointer->side = SIDE_LEFT; else frozen_pointer->side = SIDE_BOTTOM; } else { if (x < diag_b) frozen_pointer->side = SIDE_TOP; else frozen_pointer->side = SIDE_RIGHT; } } else if (pac == ACTION_RESIZE_CORNER) { int16_t mid_x = frozen_pointer->rectangle.x + (frozen_pointer->rectangle.width / 2); int16_t mid_y = frozen_pointer->rectangle.y + (frozen_pointer->rectangle.height / 2); if (pos.x > mid_x) { if (pos.y > mid_y) frozen_pointer->corner = CORNER_BOTTOM_RIGHT; else frozen_pointer->corner = CORNER_TOP_RIGHT; } else { if (pos.y > mid_y) frozen_pointer->corner = CORNER_BOTTOM_LEFT; else frozen_pointer->corner = CORNER_TOP_LEFT; } } if (frozen_pointer->is_tiled) { if (pac == ACTION_RESIZE_SIDE) { switch (frozen_pointer->side) { case SIDE_TOP: frozen_pointer->horizontal_fence = find_fence(loc.node, DIR_UP); break; case SIDE_RIGHT: frozen_pointer->vertical_fence = find_fence(loc.node, DIR_RIGHT); break; case SIDE_BOTTOM: frozen_pointer->horizontal_fence = find_fence(loc.node, DIR_DOWN); break; case SIDE_LEFT: frozen_pointer->vertical_fence = find_fence(loc.node, DIR_LEFT); break; } } else if (pac == ACTION_RESIZE_CORNER) { switch (frozen_pointer->corner) { case CORNER_TOP_LEFT: frozen_pointer->horizontal_fence = find_fence(loc.node, DIR_UP); frozen_pointer->vertical_fence = find_fence(loc.node, DIR_LEFT); break; case CORNER_TOP_RIGHT: frozen_pointer->horizontal_fence = find_fence(loc.node, DIR_UP); frozen_pointer->vertical_fence = find_fence(loc.node, DIR_RIGHT); break; case CORNER_BOTTOM_RIGHT: frozen_pointer->horizontal_fence = find_fence(loc.node, DIR_DOWN); frozen_pointer->vertical_fence = find_fence(loc.node, DIR_RIGHT); break; case CORNER_BOTTOM_LEFT: frozen_pointer->horizontal_fence = find_fence(loc.node, DIR_DOWN); frozen_pointer->vertical_fence = find_fence(loc.node, DIR_LEFT); break; } } if (frozen_pointer->horizontal_fence != NULL) frozen_pointer->horizontal_ratio = frozen_pointer->horizontal_fence->split_ratio; if (frozen_pointer->vertical_fence != NULL) frozen_pointer->vertical_ratio = frozen_pointer->vertical_fence->split_ratio; } break; case ACTION_NONE: break; } } else { if (pac == ACTION_FOCUS) { monitor_t *m = monitor_from_point(pos); if (m != NULL && m != mon) focus_node(m, m->desk, m->desk->focus); } frozen_pointer->action = ACTION_NONE; } }
void grab_pointer(pointer_action_t pac) { xcb_window_t win = XCB_NONE; xcb_point_t pos; query_pointer(&win, &pos); coordinates_t loc; if (locate_window(win, &loc)) { client_t *c = loc.node->client; frozen_pointer->position = pos; frozen_pointer->action = pac; frozen_pointer->monitor = loc.monitor; frozen_pointer->desktop = loc.desktop; frozen_pointer->node = loc.node; frozen_pointer->client = c; frozen_pointer->window = loc.node->id; frozen_pointer->horizontal_fence = NULL; frozen_pointer->vertical_fence = NULL; switch (pac) { case ACTION_FOCUS: if (loc.node != mon->desk->focus) { bool backup = pointer_follows_monitor; pointer_follows_monitor = false; focus_node(loc.monitor, loc.desktop, loc.node); pointer_follows_monitor = backup; } else if (focus_follows_pointer) { stack(loc.desktop, loc.node, true); } frozen_pointer->action = ACTION_NONE; break; case ACTION_MOVE: case ACTION_RESIZE_SIDE: case ACTION_RESIZE_CORNER: if (IS_FLOATING(c)) { frozen_pointer->rectangle = c->floating_rectangle; frozen_pointer->is_tiled = false; } else if (IS_TILED(c)) { frozen_pointer->rectangle = c->tiled_rectangle; frozen_pointer->is_tiled = (pac == ACTION_MOVE || c->state != STATE_PSEUDO_TILED); } else { frozen_pointer->action = ACTION_NONE; return; } if (pac == ACTION_RESIZE_SIDE) { float W = frozen_pointer->rectangle.width; float H = frozen_pointer->rectangle.height; float ratio = W / H; float x = pos.x - frozen_pointer->rectangle.x; float y = pos.y - frozen_pointer->rectangle.y; float diag_a = ratio * y; float diag_b = W - diag_a; if (x < diag_a) { if (x < diag_b) { frozen_pointer->side = SIDE_LEFT; } else { frozen_pointer->side = SIDE_BOTTOM; } } else { if (x < diag_b) { frozen_pointer->side = SIDE_TOP; } else { frozen_pointer->side = SIDE_RIGHT; } } } else if (pac == ACTION_RESIZE_CORNER) { int16_t mid_x = frozen_pointer->rectangle.x + (frozen_pointer->rectangle.width / 2); int16_t mid_y = frozen_pointer->rectangle.y + (frozen_pointer->rectangle.height / 2); if (pos.x > mid_x) { if (pos.y > mid_y) { frozen_pointer->corner = CORNER_BOTTOM_RIGHT; } else { frozen_pointer->corner = CORNER_TOP_RIGHT; } } else { if (pos.y > mid_y) { frozen_pointer->corner = CORNER_BOTTOM_LEFT; } else { frozen_pointer->corner = CORNER_TOP_LEFT; } } } if (frozen_pointer->is_tiled) { if (pac == ACTION_RESIZE_SIDE) { switch (frozen_pointer->side) { case SIDE_TOP: frozen_pointer->horizontal_fence = find_fence(loc.node, DIR_NORTH); break; case SIDE_RIGHT: frozen_pointer->vertical_fence = find_fence(loc.node, DIR_EAST); break; case SIDE_BOTTOM: frozen_pointer->horizontal_fence = find_fence(loc.node, DIR_SOUTH); break; case SIDE_LEFT: frozen_pointer->vertical_fence = find_fence(loc.node, DIR_WEST); break; } } else if (pac == ACTION_RESIZE_CORNER) { switch (frozen_pointer->corner) { case CORNER_TOP_LEFT: frozen_pointer->horizontal_fence = find_fence(loc.node, DIR_NORTH); frozen_pointer->vertical_fence = find_fence(loc.node, DIR_WEST); break; case CORNER_TOP_RIGHT: frozen_pointer->horizontal_fence = find_fence(loc.node, DIR_NORTH); frozen_pointer->vertical_fence = find_fence(loc.node, DIR_EAST); break; case CORNER_BOTTOM_RIGHT: frozen_pointer->horizontal_fence = find_fence(loc.node, DIR_SOUTH); frozen_pointer->vertical_fence = find_fence(loc.node, DIR_EAST); break; case CORNER_BOTTOM_LEFT: frozen_pointer->horizontal_fence = find_fence(loc.node, DIR_SOUTH); frozen_pointer->vertical_fence = find_fence(loc.node, DIR_WEST); break; } } if (frozen_pointer->horizontal_fence != NULL) { frozen_pointer->horizontal_ratio = frozen_pointer->horizontal_fence->split_ratio; } if (frozen_pointer->vertical_fence != NULL) { frozen_pointer->vertical_ratio = frozen_pointer->vertical_fence->split_ratio; } } break; case ACTION_NONE: break; } } else { if (pac == ACTION_FOCUS) { monitor_t *m = monitor_from_point(pos); if (m != NULL && m != mon && (win == XCB_NONE || win == m->root)) { focus_node(m, m->desk, m->desk->focus); } } frozen_pointer->action = ACTION_NONE; } }
bool resize_client(coordinates_t *loc, resize_handle_t rh, int dx, int dy) { node_t *n = loc->node; if (n == NULL || n->client == NULL || n->client->state == STATE_FULLSCREEN) { return false; } node_t *horizontal_fence = NULL, *vertical_fence = NULL; xcb_rectangle_t rect = get_rectangle(NULL, n); uint16_t width = rect.width, height = rect.height; int16_t x = rect.x, y = rect.y; if (n->client->state == STATE_TILED) { if (rh & HANDLE_LEFT) { vertical_fence = find_fence(n, DIR_WEST); } else if (rh & HANDLE_RIGHT) { vertical_fence = find_fence(n, DIR_EAST); } if (rh & HANDLE_TOP) { horizontal_fence = find_fence(n, DIR_NORTH); } else if (rh & HANDLE_BOTTOM) { horizontal_fence = find_fence(n, DIR_SOUTH); } if (vertical_fence == NULL && horizontal_fence == NULL) { return false; } if (vertical_fence != NULL) { double sr = vertical_fence->split_ratio + (double) dx / vertical_fence->rectangle.width; sr = MAX(0, sr); sr = MIN(1, sr); vertical_fence->split_ratio = sr; } if (horizontal_fence != NULL) { double sr = horizontal_fence->split_ratio + (double) dy / horizontal_fence->rectangle.height; sr = MAX(0, sr); sr = MIN(1, sr); horizontal_fence->split_ratio = sr; } arrange(loc->monitor, loc->desktop); } else { int w = width + dx * (rh & HANDLE_LEFT ? -1 : (rh & HANDLE_RIGHT ? 1 : 0)); int h = height + dy * (rh & HANDLE_TOP ? -1 : (rh & HANDLE_BOTTOM ? 1 : 0)); width = MAX(1, w); height = MAX(1, h); apply_size_hints(n->client, &width, &height); if (rh & HANDLE_LEFT) { x += rect.width - width; } if (rh & HANDLE_TOP) { y += rect.height - height; } n->client->floating_rectangle = (xcb_rectangle_t) {x, y, width, height}; if (n->client->state == STATE_FLOATING) { if (focus_follows_pointer) { listen_enter_notify(loc->desktop->root, false); } window_move_resize(n->id, x, y, width, height); if (focus_follows_pointer) { listen_enter_notify(loc->desktop->root, true); } 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, width, height, x, y); } } else { arrange(loc->monitor, loc->desktop); } } return true; }