static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct wlc_modifiers *modifiers, uint32_t button, enum wlc_button_state state) { swayc_t *focused = get_focused_container(&root_container); if (state == WLC_BUTTON_STATE_PRESSED) { sway_log(L_DEBUG, "Mouse button %u pressed", button); if (button == 272) { m1_held = true; } if (button == 273) { m2_held = true; } swayc_t *pointer = container_under_pointer(); set_focused_container(pointer); return (pointer && pointer != focused); } else { sway_log(L_DEBUG, "Mouse button %u released", button); if (button == 272) { m1_held = false; } if (button == 273) { m2_held = false; } } return false; }
void pointer_position_set(struct wlc_point *new_origin, bool force_focus) { struct wlc_point origin; wlc_pointer_get_position(&origin); pointer_state.delta.x = new_origin->x - origin.x; pointer_state.delta.y = new_origin->y - origin.y; wlc_pointer_set_position(new_origin); // Update view under pointer swayc_t *prev_view = pointer_state.view; pointer_state.view = container_under_pointer(); // If pointer is in a mode, update it if (pointer_state.mode) { pointer_mode_update(); // Otherwise change focus if config is set } else if (force_focus || (prev_view != pointer_state.view && config->focus_follows_mouse)) { if (pointer_state.view && pointer_state.view->type == C_VIEW) { set_focused_container(pointer_state.view); } } }
static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct wlc_origin *origin) { // Update pointer origin pointer_state.delta.x = origin->x - pointer_state.origin.x; pointer_state.delta.y = origin->y - pointer_state.origin.y; pointer_state.origin.x = origin->x; pointer_state.origin.y = origin->y; // Update view under pointer swayc_t *prev_view = pointer_state.view; pointer_state.view = container_under_pointer(); // If pointer is in a mode, update it if (pointer_state.mode) { pointer_mode_update(); } // Otherwise change focus if config is set an else if (prev_view != pointer_state.view && config->focus_follows_mouse) { if (pointer_state.view && pointer_state.view->type == C_VIEW) { set_focused_container(pointer_state.view); } } return EVENT_PASSTHROUGH; }
static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct wlc_origin *origin) { static struct wlc_origin prev_pos; static wlc_handle prev_handle = 0; mouse_origin = *origin; bool changed_floating = false; int i = 0; // Do checks to determine if proper keys are being held swayc_t *view = active_workspace->focused; if (m1_held && view) { if (view->is_floating) { while (keys_pressed[i++]) { if (keys_pressed[i] == config->floating_mod) { int dx = mouse_origin.x - prev_pos.x; int dy = mouse_origin.y - prev_pos.y; sway_log(L_DEBUG, "Moving from px: %d to cx: %d and from py: %d to cy: %d", prev_pos.x, mouse_origin.x, prev_pos.y, mouse_origin.y); sway_log(L_DEBUG, "Moving: dx: %d, dy: %d", dx, dy); view->x += dx; view->y += dy; changed_floating = true; break; } } } } else if (m2_held && view) { if (view->is_floating) { while (keys_pressed[i++]) { if (keys_pressed[i] == config->floating_mod) { int dx = mouse_origin.x - prev_pos.x; int dy = mouse_origin.y - prev_pos.y; sway_log(L_DEBUG, "Moving from px: %d to cx: %d and from py: %d to cy: %d", prev_pos.x, mouse_origin.x, prev_pos.y, mouse_origin.y); sway_log(L_INFO, "Moving: dx: %d, dy: %d", dx, dy); // Move and resize the view based on the dx/dy and mouse position int midway_x = view->x + view->width/2; int midway_y = view->y + view->height/2; if (dx < 0) { changed_floating = true; if (mouse_origin.x > midway_x) { sway_log(L_INFO, "Downsizing view to the left"); view->width += dx; } else { sway_log(L_INFO, "Upsizing view to the left"); view->x += dx; view->width -= dx; } } else if (dx > 0){ changed_floating = true; if (mouse_origin.x > midway_x) { sway_log(L_INFO, "Upsizing to the right"); view->width += dx; } else { sway_log(L_INFO, "Downsizing to the right"); view->x += dx; view->width -= dx; } } if (dy < 0) { changed_floating = true; if (mouse_origin.y > midway_y) { sway_log(L_INFO, "Downsizing view to the top"); view->height += dy; } else { sway_log(L_INFO, "Upsizing the view to the top"); view->y += dy; view->height -= dy; } } else if (dy > 0) { changed_floating = true; if (mouse_origin.y > midway_y) { sway_log(L_INFO, "Upsizing to the bottom"); view->height += dy; } else { sway_log(L_INFO, "Downsizing to the bottom"); view->y += dy; view->height -= dy; } } break; } } } } if (config->focus_follows_mouse && prev_handle != handle) { set_focused_container(container_under_pointer()); } prev_handle = handle; prev_pos = mouse_origin; if (changed_floating) { arrange_windows(view, -1, -1); return true; } return false; }
static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct wlc_origin *origin) { static struct wlc_origin prev_pos; static wlc_handle prev_handle = 0; mouse_origin = *origin; bool changed_floating = false; bool changed_tiling = false; int min_sane_w = 100; int min_sane_h = 60; if (!active_workspace) { return false; } // Do checks to determine if proper keys are being held swayc_t *view = container_under_pointer(); uint32_t edge = 0; if (pointer_state.floating.drag && view) { if (view->is_floating) { int dx = mouse_origin.x - prev_pos.x; int dy = mouse_origin.y - prev_pos.y; view->x += dx; view->y += dy; changed_floating = true; } } else if (pointer_state.floating.resize && view) { if (view->is_floating) { int dx = mouse_origin.x - prev_pos.x; int dy = mouse_origin.y - prev_pos.y; // Move and resize the view based on the dx/dy and mouse position int midway_x = view->x + view->width/2; int midway_y = view->y + view->height/2; if (dx < 0) { if (!pointer_state.lock.right) { if (view->width > min_sane_w) { changed_floating = true; view->width += dx; edge += WLC_RESIZE_EDGE_RIGHT; } } else if (mouse_origin.x < midway_x && !pointer_state.lock.left) { changed_floating = true; view->x += dx; view->width -= dx; edge += WLC_RESIZE_EDGE_LEFT; } } else if (dx > 0) { if (mouse_origin.x > midway_x && !pointer_state.lock.right) { changed_floating = true; view->width += dx; edge += WLC_RESIZE_EDGE_RIGHT; } else if (!pointer_state.lock.left) { if (view->width > min_sane_w) { changed_floating = true; view->x += dx; view->width -= dx; edge += WLC_RESIZE_EDGE_LEFT; } } } if (dy < 0) { if (!pointer_state.lock.bottom) { if (view->height > min_sane_h) { changed_floating = true; view->height += dy; edge += WLC_RESIZE_EDGE_BOTTOM; } } else if (mouse_origin.y < midway_y && !pointer_state.lock.top) { changed_floating = true; view->y += dy; view->height -= dy; edge += WLC_RESIZE_EDGE_TOP; } } else if (dy > 0) { if (mouse_origin.y > midway_y && !pointer_state.lock.bottom) { changed_floating = true; view->height += dy; edge += WLC_RESIZE_EDGE_BOTTOM; } else if (!pointer_state.lock.top) { if (view->height > min_sane_h) { changed_floating = true; view->y += dy; view->height -= dy; edge += WLC_RESIZE_EDGE_TOP; } } } } } else if (pointer_state.tiling.resize && view) { bool valid = true; double dx = mouse_origin.x - prev_pos.x; double dy = mouse_origin.y - prev_pos.y; if ((dx < 0 || mouse_origin.x < pointer_state.tiling.lock_pos.x) && pointer_state.lock.temp_left) { changed_tiling = true; valid = false; } else if (dx > 0 && pointer_state.lock.temp_left) { pointer_state.lock.temp_left = false; } if ((dx > 0 || mouse_origin.x > pointer_state.tiling.lock_pos.x) && pointer_state.lock.temp_right) { changed_tiling = true; valid = false; } else if (dx < 0 && pointer_state.lock.temp_right) { pointer_state.lock.temp_right = false; } if ((dy < 0 || mouse_origin.y < pointer_state.tiling.lock_pos.y) && pointer_state.lock.temp_up) { changed_tiling = true; valid = false; } else if (dy > 0 && pointer_state.lock.temp_up) { pointer_state.lock.temp_up = false; } if ((dy > 0 || mouse_origin.y > pointer_state.tiling.lock_pos.y) && pointer_state.lock.temp_down) { changed_tiling = true; valid = false; } else if (dy < 0 && pointer_state.lock.temp_down) { pointer_state.lock.temp_down = false; } if (!view->is_floating && valid) { // Handle layout resizes -- Find the biggest parent container then apply resizes to that // and its bordering siblings swayc_t *parent = view; if (!pointer_state.lock.bottom) { while (parent->type != C_WORKSPACE) { // TODO: Absolute value is a bad hack here to compensate for rounding. Find a better // way of doing this. if (fabs(parent->parent->y + parent->parent->height - (view->y + view->height)) <= 1) { parent = parent->parent; } else { break; } } if (parent->parent->children->length > 1 && parent->parent->layout == L_VERT) { swayc_t *sibling = get_swayc_in_direction(parent, MOVE_DOWN); if (sibling) { if ((parent->height > min_sane_h || dy > 0) && (sibling->height > min_sane_h || dy < 0)) { recursive_resize(parent, dy, WLC_RESIZE_EDGE_BOTTOM); recursive_resize(sibling, -1 * dy, WLC_RESIZE_EDGE_TOP); changed_tiling = true; } else { pointer_state.tiling.lock_pos.y = mouse_origin.y; if (parent->height < min_sane_h) { pointer_state.lock.temp_up = true; } else if (sibling->height < min_sane_h) { pointer_state.lock.temp_down = true; } } } } } else if (!pointer_state.lock.top) { while (parent->type != C_WORKSPACE) { if (fabs(parent->parent->y - view->y) <= 1) { parent = parent->parent; } else { break; } } if (parent->parent->children->length > 1 && parent->parent->layout == L_VERT) { swayc_t *sibling = get_swayc_in_direction(parent, MOVE_UP); if (sibling) { if ((parent->height > min_sane_h || dy < 0) && (sibling->height > min_sane_h || dy > 0)) { recursive_resize(parent, -1 * dy, WLC_RESIZE_EDGE_TOP); recursive_resize(sibling, dy, WLC_RESIZE_EDGE_BOTTOM); changed_tiling = true; } else { pointer_state.tiling.lock_pos.y = mouse_origin.y; if (parent->height < min_sane_h) { pointer_state.lock.temp_down = true; } else if (sibling->height < min_sane_h) { pointer_state.lock.temp_up = true; } } } } } parent = view; if (!pointer_state.lock.right) { while (parent->type != C_WORKSPACE) { if (fabs(parent->parent->x + parent->parent->width - (view->x + view->width)) <= 1) { parent = parent->parent; } else { sway_log(L_DEBUG, "view: %f vs parent: %f", view->x + view->width, parent->parent->x + parent->parent->width); break; } } if (parent->parent->children->length > 1 && parent->parent->layout == L_HORIZ) { swayc_t *sibling = get_swayc_in_direction(parent, MOVE_RIGHT); if (sibling) { if ((parent->width > min_sane_w || dx > 0) && (sibling->width > min_sane_w || dx < 0)) { recursive_resize(parent, dx, WLC_RESIZE_EDGE_RIGHT); recursive_resize(sibling, -1 * dx, WLC_RESIZE_EDGE_LEFT); changed_tiling = true; } else { pointer_state.tiling.lock_pos.x = mouse_origin.x; if (parent->width < min_sane_w) { pointer_state.lock.temp_left = true; } else if (sibling->width < min_sane_w) { pointer_state.lock.temp_right = true; } } } } } else if (!pointer_state.lock.left) { while (parent->type != C_WORKSPACE) { if (fabs(parent->parent->x - view->x) <= 1 && parent->parent) { parent = parent->parent; } else { break; } } if (parent->parent->children->length > 1 && parent->parent->layout == L_HORIZ) { swayc_t *sibling = get_swayc_in_direction(parent, MOVE_LEFT); if (sibling) { if ((parent->width > min_sane_w || dx < 0) && (sibling->width > min_sane_w || dx > 0)) { recursive_resize(parent, -1 * dx, WLC_RESIZE_EDGE_LEFT); recursive_resize(sibling, dx, WLC_RESIZE_EDGE_RIGHT); changed_tiling = true; } else { pointer_state.tiling.lock_pos.x = mouse_origin.x; if (parent->width < min_sane_w) { pointer_state.lock.temp_right = true; } else if (sibling->width < min_sane_w) { pointer_state.lock.temp_left = true; } } } } } arrange_windows(active_workspace, -1, -1); } } if (config->focus_follows_mouse && prev_handle != handle) { // Dont change focus if fullscreen swayc_t *focused = get_focused_view(view); if (!(focused->type == C_VIEW && wlc_view_get_state(focused->handle) & WLC_BIT_FULLSCREEN) && !(pointer_state.l_held || pointer_state.r_held)) { set_focused_container(container_under_pointer()); } } prev_handle = handle; prev_pos = mouse_origin; if (changed_floating) { struct wlc_geometry geometry = { .origin = { .x = view->x, .y = view->y }, .size = { .w = view->width, .h = view->height } }; wlc_view_set_geometry(view->handle, edge, &geometry); return true; }
struct cmd_results *cmd_floating(int argc, char **argv) { struct cmd_results *error = NULL; if (config->reading) return cmd_results_new(CMD_FAILURE, "floating", "Can't be used in config file."); if ((error = checkarg(argc, "floating", EXPECTED_EQUAL_TO, 1))) { return error; } swayc_t *view = current_container; bool wants_floating; if (strcasecmp(argv[0], "enable") == 0) { wants_floating = true; } else if (strcasecmp(argv[0], "disable") == 0) { wants_floating = false; } else if (strcasecmp(argv[0], "toggle") == 0) { wants_floating = !view->is_floating; } else { return cmd_results_new(CMD_FAILURE, "floating", "Expected 'floating <enable|disable|toggle>"); } // Prevent running floating commands on things like workspaces if (view->type != C_VIEW) { return cmd_results_new(CMD_SUCCESS, NULL, NULL); } // Change from nonfloating to floating if (!view->is_floating && wants_floating) { // Remove view from its current location destroy_container(remove_child(view)); // and move it into workspace floating add_floating(swayc_active_workspace(), view); view->x = (swayc_active_workspace()->width - view->width)/2; view->y = (swayc_active_workspace()->height - view->height)/2; if (view->desired_width != -1) { view->width = view->desired_width; } if (view->desired_height != -1) { view->height = view->desired_height; } arrange_windows(swayc_active_workspace(), -1, -1); } else if (view->is_floating && !wants_floating) { // Delete the view from the floating list and unset its is_floating flag remove_child(view); view->is_floating = false; // Get the properly focused container, and add in the view there swayc_t *focused = container_under_pointer(); // If focused is null, it's because the currently focused container is a workspace if (focused == NULL || focused->is_floating) { focused = swayc_active_workspace(); } set_focused_container(focused); sway_log(L_DEBUG, "Non-floating focused container is %p", focused); // Case of focused workspace, just create as child of it if (focused->type == C_WORKSPACE) { add_child(focused, view); } // Regular case, create as sibling of current container else { add_sibling(focused, view); } // Refocus on the view once its been put back into the layout view->width = view->height = 0; arrange_windows(swayc_active_workspace(), -1, -1); remove_view_from_scratchpad(view); ipc_event_window(view, "floating"); } set_focused_container(view); return cmd_results_new(CMD_SUCCESS, NULL, NULL); }
static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct wlc_modifiers *modifiers, uint32_t button, enum wlc_button_state state, const struct wlc_origin *origin) { // Update view pointer is on pointer_state.view = container_under_pointer(); // Update pointer origin pointer_state.origin.x = origin->x; pointer_state.origin.y = origin->y; // Update pointer_state switch (button) { case M_LEFT_CLICK: if (state == WLC_BUTTON_STATE_PRESSED) { pointer_state.left.held = true; pointer_state.left.x = origin->x; pointer_state.left.y = origin->y; pointer_state.left.view = pointer_state.view; } else { pointer_state.left.held = false; } break; case M_RIGHT_CLICK: if (state == WLC_BUTTON_STATE_PRESSED) { pointer_state.right.held = true; pointer_state.right.x = origin->x; pointer_state.right.y = origin->y; pointer_state.right.view = pointer_state.view; } else { pointer_state.right.held = false; } break; case M_SCROLL_CLICK: if (state == WLC_BUTTON_STATE_PRESSED) { pointer_state.scroll.held = true; pointer_state.scroll.x = origin->x; pointer_state.scroll.y = origin->y; pointer_state.scroll.view = pointer_state.view; } else { pointer_state.scroll.held = false; } break; //TODO scrolling behavior case M_SCROLL_UP: case M_SCROLL_DOWN: break; } // get focused window and check if to change focus on mouse click swayc_t *focused = get_focused_container(&root_container); // dont change focus or mode if fullscreen if (swayc_is_fullscreen(focused)) { return EVENT_PASSTHROUGH; } // set pointer mode only if floating mod has been set if (config->floating_mod) { pointer_mode_set(button, !(modifiers->mods ^ config->floating_mod)); } // Check whether to change focus swayc_t *pointer = pointer_state.view; if (pointer) { if (focused != pointer) { set_focused_container(pointer_state.view); } // Send to front if floating if (pointer->is_floating) { int i; for (i = 0; i < pointer->parent->floating->length; i++) { if (pointer->parent->floating->items[i] == pointer) { list_del(pointer->parent->floating, i); list_add(pointer->parent->floating, pointer); break; } } wlc_view_bring_to_front(pointer->handle); } } // Return if mode has been set if (pointer_state.mode) { return EVENT_HANDLED; } // Always send mouse release if (state == WLC_BUTTON_STATE_RELEASED) { return EVENT_PASSTHROUGH; } // Finally send click return EVENT_PASSTHROUGH; }