void move_container_to(swayc_t* container, swayc_t* destination) { if (container == destination || swayc_is_parent_of(container, destination)) { return; } swayc_t *parent = remove_child(container); // Send to new destination if (container->is_floating) { swayc_t *ws = swayc_active_workspace_for(destination); add_floating(ws, container); // If the workspace only has one child after adding one, it // means that the workspace was just initialized. if (ws->children->length + ws->floating->length == 1) { ipc_event_workspace(NULL, ws, "init"); } } else if (destination->type == C_WORKSPACE) { // reset container geometry container->width = container->height = 0; add_child(destination, container); // If the workspace only has one child after adding one, it // means that the workspace was just initialized. if (destination->children->length + destination->floating->length == 1) { ipc_event_workspace(NULL, destination, "init"); } } else { // reset container geometry container->width = container->height = 0; add_sibling(destination, container); } // Destroy old container if we need to parent = destroy_container(parent); // Refocus swayc_t *op1 = swayc_parent_by_type(destination, C_OUTPUT); swayc_t *op2 = swayc_parent_by_type(parent, C_OUTPUT); set_focused_container(get_focused_view(op1)); arrange_windows(op1, -1, -1); update_visibility(op1); if (op1 != op2) { set_focused_container(get_focused_view(op2)); arrange_windows(op2, -1, -1); update_visibility(op2); } }
static void handle_output_focused(wlc_handle output, bool focus) { swayc_t *c = get_swayc_for_handle(output, &root_container); // if for some reason this output doesnt exist, create it. if (!c) { handle_output_created(output); } if (focus) { set_focused_container(c); } }
bool move_focus(enum movement_direction direction) { swayc_t *old_view = get_focused_container(&root_container); swayc_t *new_view = get_swayc_in_direction(old_view, direction); if (!new_view) { return false; } else if (direction == MOVE_PARENT) { return set_focused_container(new_view); } else if (config->mouse_warping) { swayc_t *old_op = old_view->type == C_OUTPUT ? old_view : swayc_parent_by_type(old_view, C_OUTPUT); swayc_t *focused = get_focused_view(new_view); if (set_focused_container(focused)) { if (old_op != swayc_active_output() && focused && focused->type == C_VIEW) { center_pointer_on(focused); } return true; } } else { return set_focused_container(get_focused_view(new_view)); } return false; }
void move_workspace_to(swayc_t* workspace, swayc_t* destination) { if (workspace == destination || swayc_is_parent_of(workspace, destination)) { return; } swayc_t *src_op = remove_child(workspace); // reset container geometry workspace->width = workspace->height = 0; add_child(destination, workspace); // Refocus destination (change to new workspace) set_focused_container(get_focused_view(workspace)); arrange_windows(destination, -1, -1); update_visibility(destination); // make sure source output has a workspace if (src_op->children->length == 0) { char *ws_name = workspace_next_name(src_op->name); swayc_t *ws = new_workspace(src_op, ws_name); ws->is_focused = true; free(ws_name); } set_focused_container(get_focused_view(src_op)); update_visibility(src_op); }
bool workspace_switch(swayc_t *workspace) { if (!workspace) { return false; } swayc_t *active_ws = swayc_active_workspace(); if (config->auto_back_and_forth && active_ws == workspace && prev_workspace_name) { swayc_t *new_ws = workspace_by_name(prev_workspace_name); workspace = new_ws ? new_ws : workspace_create(prev_workspace_name); } if (!prev_workspace_name || (strcmp(prev_workspace_name, active_ws->name) && active_ws != workspace)) { free(prev_workspace_name); prev_workspace_name = malloc(strlen(active_ws->name)+1); strcpy(prev_workspace_name, active_ws->name); } // move sticky containers if (swayc_parent_by_type(active_ws, C_OUTPUT) == swayc_parent_by_type(workspace, C_OUTPUT)) { // don't change list while traversing it, use intermediate list instead list_t *stickies = create_list(); for (int i = 0; i < active_ws->floating->length; i++) { swayc_t *cont = active_ws->floating->items[i]; if (cont->sticky) { list_add(stickies, cont); } } for (int i = 0; i < stickies->length; i++) { swayc_t *cont = stickies->items[i]; sway_log(L_DEBUG, "Moving sticky container %p to %p:%s", cont, workspace, workspace->name); swayc_t *parent = remove_child(cont); add_floating(workspace, cont); // Destroy old container if we need to destroy_container(parent); } list_free(stickies); } sway_log(L_DEBUG, "Switching to workspace %p:%s", workspace, workspace->name); if (!set_focused_container(get_focused_view(workspace))) { return false; } swayc_t *output = swayc_parent_by_type(workspace, C_OUTPUT); arrange_backgrounds(); arrange_windows(output, -1, -1); return true; }
void workspace_switch(swayc_t *workspace) { if (!workspace) { return; } if (strcmp(prev_workspace_name, swayc_active_workspace()->name) != 0 && swayc_active_workspace() != workspace) { prev_workspace_name = malloc(strlen(swayc_active_workspace()->name) + 1); strcpy(prev_workspace_name, swayc_active_workspace()->name); } else if (config->auto_back_and_forth && swayc_active_workspace() == workspace && strlen(prev_workspace_name) != 0) { workspace = workspace_by_name(prev_workspace_name) ? workspace_by_name(prev_workspace_name) : workspace_create(prev_workspace_name); prev_workspace_name = malloc(strlen(swayc_active_workspace()->name) + 1); strcpy(prev_workspace_name, swayc_active_workspace()->name); } sway_log(L_DEBUG, "Switching to workspace %p:%s", workspace, workspace->name); set_focused_container(get_focused_view(workspace)); arrange_windows(workspace, -1, -1); }
bool set_focused_container_for(swayc_t *a, swayc_t *c) { if (locked_container_focus || !c) { return false; } swayc_t *find = c; // Ensure that a is an ancestor of c while (find != a && (find = find->parent)) { if (find == &root_container) { return false; } } // Get workspace for c, get that workspaces current focused container. swayc_t *workspace = swayc_active_workspace_for(c); swayc_t *focused = get_focused_view(workspace); // if the workspace we are changing focus to has a fullscreen view return if (swayc_is_fullscreen(focused) && c != focused) { return false; } // Check if we changing a parent container that will see chnage bool effective = true; while (find != &root_container) { if (find->parent->focused != find) { effective = false; } find = find->parent; } if (effective) { // Go to set_focused_container return set_focused_container(c); } sway_log(L_DEBUG, "Setting focus for %p:%ld to %p:%ld", a, a->handle, c, c->handle); c->is_focused = true; swayc_t *p = c; while (p != a) { update_focus(p); p = p->parent; p->is_focused = false; } return true; }
static void set_lock_surface(struct wl_client *client, struct wl_resource *resource, struct wl_resource *_output, struct wl_resource *surface) { swayc_t *output = swayc_by_handle(wlc_handle_from_wl_output_resource(_output)); swayc_t *view = swayc_by_handle(wlc_handle_from_wl_surface_resource(surface)); sway_log(L_DEBUG, "Setting lock surface to %p", view); if (view && output) { swayc_t *workspace = output->focused; if (!swayc_is_child_of(view, workspace)) { move_container_to(view, workspace); } wlc_view_set_state(view->handle, WLC_BIT_FULLSCREEN, true); workspace->fullscreen = view; desktop_shell.is_locked = true; set_focused_container(view); arrange_windows(view, -1, -1); list_add(desktop_shell.lock_surfaces, surface); wl_resource_set_destructor(surface, lock_surface_destructor); } else { sway_log(L_ERROR, "Attempted to set lock surface to non-view"); } }
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); } } }
void workspace_switch(swayc_t *workspace) { if (!workspace) { return; } swayc_t *active_ws = swayc_active_workspace(); if (config->auto_back_and_forth && active_ws == workspace && prev_workspace_name) { swayc_t *new_ws = workspace_by_name(prev_workspace_name); workspace = new_ws ? new_ws : workspace_create(prev_workspace_name); } if (!prev_workspace_name || (strcmp(prev_workspace_name, active_ws->name) && active_ws != workspace)) { free(prev_workspace_name); prev_workspace_name = malloc(strlen(active_ws->name)+1); strcpy(prev_workspace_name, active_ws->name); } sway_log(L_DEBUG, "Switching to workspace %p:%s", workspace, workspace->name); set_focused_container(get_focused_view(workspace)); arrange_windows(workspace, -1, -1); }
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_view_created(wlc_handle handle) { swayc_t *focused = get_focused_container(&root_container); swayc_t *newview = NULL; switch (wlc_view_get_type(handle)) { // regular view created regularly case 0: newview = new_view(focused, handle); wlc_view_set_state(handle, WLC_BIT_MAXIMIZED, true); break; // takes keyboard focus case WLC_BIT_OVERRIDE_REDIRECT: sway_log(L_DEBUG, "view %ld with OVERRIDE_REDIRECT", handle); locked_view_focus = true; wlc_view_focus(handle); wlc_view_set_state(handle, WLC_BIT_ACTIVATED, true); wlc_view_bring_to_front(handle); break; // Takes container focus case WLC_BIT_OVERRIDE_REDIRECT|WLC_BIT_UNMANAGED: sway_log(L_DEBUG, "view %ld with OVERRIDE_REDIRECT|WLC_BIT_MANAGED", handle); wlc_view_bring_to_front(handle); locked_container_focus = true; break; // set modals as floating containers case WLC_BIT_MODAL: wlc_view_bring_to_front(handle); newview = new_floating_view(handle); case WLC_BIT_POPUP: break; } if (newview) { set_focused_container(newview); arrange_windows(newview->parent, -1, -1); } return true; }
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; }
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_view_created(wlc_handle handle) { // if view is child of another view, the use that as focused container wlc_handle parent = wlc_view_get_parent(handle); swayc_t *focused = NULL; swayc_t *newview = NULL; // Get parent container, to add view in if (parent) { focused = get_swayc_for_handle(parent, &root_container); } if (!focused || focused->type == C_OUTPUT) { focused = get_focused_container(&root_container); } sway_log(L_DEBUG, "handle:%ld type:%x state:%x parent:%ld " "mask:%d (x:%d y:%d w:%d h:%d) title:%s " "class:%s appid:%s", handle, wlc_view_get_type(handle), wlc_view_get_state(handle), parent, wlc_view_get_mask(handle), wlc_view_get_geometry(handle)->origin.x, wlc_view_get_geometry(handle)->origin.y,wlc_view_get_geometry(handle)->size.w, wlc_view_get_geometry(handle)->size.h, wlc_view_get_title(handle), wlc_view_get_class(handle), wlc_view_get_app_id(handle)); // TODO properly figure out how each window should be handled. switch (wlc_view_get_type(handle)) { // regular view created regularly case 0: newview = new_view(focused, handle); wlc_view_set_state(handle, WLC_BIT_MAXIMIZED, true); break; // Dmenu keeps viewfocus, but others with this flag dont, for now simulate // dmenu case WLC_BIT_OVERRIDE_REDIRECT: // locked_view_focus = true; wlc_view_focus(handle); wlc_view_set_state(handle, WLC_BIT_ACTIVATED, true); wlc_view_bring_to_front(handle); break; // Firefox popups have this flag set. case WLC_BIT_OVERRIDE_REDIRECT|WLC_BIT_UNMANAGED: wlc_view_bring_to_front(handle); locked_container_focus = true; break; // Modals, get focus, popups do not case WLC_BIT_MODAL: wlc_view_focus(handle); wlc_view_bring_to_front(handle); newview = new_floating_view(handle); case WLC_BIT_POPUP: wlc_view_bring_to_front(handle); break; } if (newview) { set_focused_container(newview); swayc_t *output = swayc_parent_by_type(newview, C_OUTPUT); arrange_windows(output, -1, -1); } return true; }
void pointer_mode_update(void) { if (initial.ptr->type != C_VIEW) { pointer_state.mode = 0; return; } struct wlc_point origin; wlc_pointer_get_position(&origin); int dx = origin.x; int dy = origin.y; switch (pointer_state.mode) { case M_FLOATING | M_DRAGGING: // Update position switch (config->dragging_key) { case M_LEFT_CLICK: dx -= pointer_state.left.x; dy -= pointer_state.left.y; break; case M_RIGHT_CLICK: dx -= pointer_state.right.x; dy -= pointer_state.right.y; break; } if (initial.x + dx != initial.ptr->x) { initial.ptr->x = initial.x + dx; } if (initial.y + dy != initial.ptr->y) { initial.ptr->y = initial.y + dy; } update_geometry(initial.ptr); break; case M_FLOATING | M_RESIZING: switch (config->resizing_key) { case M_LEFT_CLICK: dx -= pointer_state.left.x; dy -= pointer_state.left.y; initial.ptr = pointer_state.left.view; break; case M_RIGHT_CLICK: dx -= pointer_state.right.x; dy -= pointer_state.right.y; initial.ptr = pointer_state.right.view; break; } if (lock.left) { if (initial.w + dx > min_sane_w) { initial.ptr->width = initial.w + dx; } } else { // lock.right if (initial.w - dx > min_sane_w) { initial.ptr->width = initial.w - dx; initial.ptr->x = initial.x + dx; } } if (lock.top) { if (initial.h + dy > min_sane_h) { initial.ptr->height = initial.h + dy; } } else { // lock.bottom if (initial.h - dy > min_sane_h) { initial.ptr->height = initial.h - dy; initial.ptr->y = initial.y + dy; } } update_geometry(initial.ptr); break; case M_TILING | M_DRAGGING: // swap current view under pointer with dragged view if (pointer_state.view && pointer_state.view->type == C_VIEW && pointer_state.view != initial.ptr && !pointer_state.view->is_floating) { // Swap them around swap_container(pointer_state.view, initial.ptr); swap_geometry(pointer_state.view, initial.ptr); update_geometry(pointer_state.view); update_geometry(initial.ptr); // Set focus back to initial view set_focused_container(initial.ptr); } break; case M_TILING | M_RESIZING: switch (config->resizing_key) { case M_LEFT_CLICK: dx -= pointer_state.left.x; dy -= pointer_state.left.y; break; case M_RIGHT_CLICK: dx -= pointer_state.right.x; dy -= pointer_state.right.y; break; } // resize if we can if (initial.horiz.ptr) { if (lock.left) { // Check whether its fine to resize if (initial.w + dx > min_sane_w && initial.horiz.w - dx > min_sane_w) { initial.horiz.ptr->width = initial.horiz.w - dx; initial.horiz.parent.ptr->width = initial.horiz.parent.w + dx; } } else { // lock.right if (initial.w - dx > min_sane_w && initial.horiz.w + dx > min_sane_w) { initial.horiz.ptr->width = initial.horiz.w + dx; initial.horiz.parent.ptr->width = initial.horiz.parent.w - dx; } } arrange_windows(initial.horiz.ptr->parent, -1, -1); } if (initial.vert.ptr) { if (lock.top) { if (initial.h + dy > min_sane_h && initial.vert.h - dy > min_sane_h) { initial.vert.ptr->height = initial.vert.h - dy; initial.vert.parent.ptr->height = initial.vert.parent.h + dy; } } else { // lock.bottom if (initial.h - dy > min_sane_h && initial.vert.h + dy > min_sane_h) { initial.vert.ptr->height = initial.vert.h + dy; initial.vert.parent.ptr->height = initial.vert.parent.h - dy; } } arrange_windows(initial.vert.ptr->parent, -1, -1); } default: return; } }
bool move_focus(enum movement_direction direction) { if (locked_container_focus) { return false; } swayc_t *current = get_focused_container(&root_container); swayc_t *parent = current->parent; if (direction == MOVE_PARENT) { if (parent->type == C_OUTPUT) { sway_log(L_DEBUG, "Focus cannot move to parent"); return false; } else { sway_log(L_DEBUG, "Moving focus from %p:%ld to %p:%ld", current, current->handle, parent, parent->handle); set_focused_container(parent); return true; } } while (true) { sway_log(L_DEBUG, "Moving focus away from %p", current); // Test if we can even make a difference here bool can_move = false; int diff = 0; if (direction == MOVE_LEFT || direction == MOVE_RIGHT) { if (parent->layout == L_HORIZ || parent->type == C_ROOT) { can_move = true; diff = direction == MOVE_LEFT ? -1 : 1; } } else { if (parent->layout == L_VERT) { can_move = true; diff = direction == MOVE_UP ? -1 : 1; } } sway_log(L_DEBUG, "Can move? %s", can_move ? "yes" : "no"); if (can_move) { int i; for (i = 0; i < parent->children->length; ++i) { swayc_t *child = parent->children->items[i]; if (child == current) { break; } } int desired = i + diff; sway_log(L_DEBUG, "Moving from %d to %d", i, desired); if (desired < 0 || desired >= parent->children->length) { can_move = false; } else { swayc_t *newview = parent->children->items[desired]; set_focused_container(get_focused_view(newview)); return true; } } if (!can_move) { sway_log(L_DEBUG, "Can't move at current level, moving up tree"); current = parent; parent = parent->parent; if (!parent) { // Nothing we can do return false; } } } }