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); // reset container geometry container->width = container->height = 0; // Send to new destination if (container->is_floating) { add_floating(swayc_active_workspace_for(destination), container); } else if (destination->type == C_WORKSPACE) { add_child(destination, container); } else { 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 reset_initial_sibling(void) { initial.horiz.ptr->width = initial.horiz.w; initial.horiz.parent.ptr->width = initial.horiz.parent.w; initial.vert.ptr->height = initial.vert.h; initial.vert.parent.ptr->height = initial.vert.parent.h; arrange_windows(initial.horiz.ptr->parent, -1, -1); arrange_windows(initial.vert.ptr->parent, -1, -1); pointer_state.mode = 0; }
static void handle_view_destroyed(wlc_handle handle) { sway_log(L_DEBUG, "Destroying window %lu", handle); swayc_t *view = get_swayc_for_handle(handle, &root_container); switch (wlc_view_get_type(handle)) { // regular view created regularly case 0: case WLC_BIT_MODAL: if (view) { swayc_t *parent = destroy_view(view); arrange_windows(parent, -1, -1); } break; // takes keyboard focus case WLC_BIT_OVERRIDE_REDIRECT: locked_view_focus = false; break; // Takes container focus case WLC_BIT_OVERRIDE_REDIRECT|WLC_BIT_UNMANAGED: locked_container_focus = false; case WLC_BIT_POPUP: break; } set_focused_container(get_focused_view(&root_container)); }
static void handle_view_destroyed(wlc_handle handle) { sway_log(L_DEBUG, "Destroying window %lu", handle); swayc_t *view = get_swayc_for_handle(handle, &root_container); switch (wlc_view_get_type(handle)) { // regular view created regularly case 0: case WLC_BIT_MODAL: case WLC_BIT_POPUP: if (view) { swayc_t *parent = destroy_view(view); arrange_windows(parent, -1, -1); } break; // DMENU has this flag, and takes view_focus, but other things with this // flag dont case WLC_BIT_OVERRIDE_REDIRECT: // locked_view_focus = false; break; case WLC_BIT_OVERRIDE_REDIRECT|WLC_BIT_UNMANAGED: locked_container_focus = false; break; } set_focused_container(get_focused_view(&root_container)); }
bool read_config(FILE *file, bool is_active) { struct sway_config *temp_config = malloc(sizeof(struct sway_config)); config_defaults(temp_config); if (is_active) { sway_log(L_DEBUG, "Performing configuration file reload"); temp_config->reloading = true; temp_config->active = true; } bool success = true; int temp_depth = 0; // Temporary: skip all config sections with depth while (!feof(file)) { int _; char *line = read_line(file); line = strip_whitespace(line, &_); line = strip_comments(line); if (!line[0]) { goto _continue; } if (temp_depth && line[0] == '}') { temp_depth--; goto _continue; } // Any command which would require wlc to be initialized // should be queued for later execution list_t *args = split_string(line, " "); if (!is_active && ( strcmp("exec", args->items[0]) == 0 || strcmp("exec_always", args->items[0]) == 0 )) { sway_log(L_DEBUG, "Deferring command %s", line); char *cmd = malloc(strlen(line) + 1); strcpy(cmd, line); list_add(temp_config->cmd_queue, cmd); } else if (!temp_depth && !handle_command(temp_config, line)) { sway_log(L_DEBUG, "Config load failed for line %s", line); success = false; temp_config->failed = true; } list_free(args); _continue: if (line && line[strlen(line) - 1] == '{') { temp_depth++; } free(line); } if (is_active) { temp_config->reloading = false; container_map(&root_container, reset_gaps, NULL); arrange_windows(&root_container, -1, -1); } config = temp_config; return success; }
static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit state, bool toggle) { swayc_t *c = NULL; switch(state) { case WLC_BIT_FULLSCREEN: // i3 just lets it become fullscreen wlc_view_set_state(view, state, toggle); c = get_swayc_for_handle(view, &root_container); sway_log(L_DEBUG, "setting view %ld %s, fullscreen %d",view,c->name,toggle); if (c) { arrange_windows(c->parent, -1, -1); // Set it as focused window for that workspace if its going fullscreen if (toggle) { swayc_t *ws = c; while (ws->type != C_WORKSPACE) { ws = ws->parent; } // Set ws focus to c set_focused_container_for(ws, c); } } break; case WLC_BIT_MAXIMIZED: case WLC_BIT_RESIZING: case WLC_BIT_MOVING: case WLC_BIT_ACTIVATED: break; } return; }
static swayc_t *fetch_view_from_scratchpad() { if (sp_index >= scratchpad->length) { sp_index = 0; } swayc_t *view = scratchpad->items[sp_index++]; if (wlc_view_get_output(view->handle) != swayc_active_output()->handle) { wlc_view_set_output(view->handle, swayc_active_output()->handle); } if (!view->is_floating) { view->width = swayc_active_workspace()->width/2; view->height = swayc_active_workspace()->height/2; view->x = (swayc_active_workspace()->width - view->width)/2; view->y = (swayc_active_workspace()->height - view->height)/2; } if (swayc_active_workspace()->width < view->x + 20 || view->x + view->width < 20) { view->x = (swayc_active_workspace()->width - view->width)/2; } if (swayc_active_workspace()->height < view->y + 20 || view->y + view->height < 20) { view->y = (swayc_active_workspace()->height - view->height)/2; } add_floating(swayc_active_workspace(), view); wlc_view_set_mask(view->handle, VISIBLE); view->visible = true; arrange_windows(swayc_active_workspace(), -1, -1); set_focused_container(view); return view; }
static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit state, bool toggle) { swayc_t *c = swayc_by_handle(view); switch (state) { case WLC_BIT_FULLSCREEN: // i3 just lets it become fullscreen wlc_view_set_state(view, state, toggle); if (c) { sway_log(L_DEBUG, "setting view %ld %s, fullscreen %d", view, c->name, toggle); arrange_windows(c->parent, -1, -1); // Set it as focused window for that workspace if its going fullscreen if (toggle) { swayc_t *ws = swayc_parent_by_type(c, C_WORKSPACE); // Set ws focus to c set_focused_container_for(ws, c); } } break; case WLC_BIT_MAXIMIZED: case WLC_BIT_RESIZING: case WLC_BIT_MOVING: break; case WLC_BIT_ACTIVATED: sway_log(L_DEBUG, "View %p requested to be activated", c); break; } return; }
static void handle_output_resolution_change(wlc_handle output, const struct wlc_size *from, const struct wlc_size *to) { sway_log(L_DEBUG, "Output %u resolution changed to %d x %d", (unsigned int)output, to->w, to->h); swayc_t *c = get_swayc_for_handle(output, &root_container); if (!c) return; c->width = to->w; c->height = to->h; arrange_windows(&root_container, -1, -1); }
static void reset_initial_view(void) { initial.ptr->x = initial.x; initial.ptr->y = initial.y; initial.ptr->width = initial.w; initial.ptr->height = initial.h; arrange_windows(initial.ptr, -1, -1); pointer_state.mode = 0; }
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); } }
void panel_surface_destructor(struct wl_resource *resource) { sway_log(L_DEBUG, "Panel surface killed"); int i; for (i = 0; i < desktop_shell.panels->length; ++i) { struct panel_config *config = desktop_shell.panels->items[i]; if (config->wl_surface_res == resource) { list_del(desktop_shell.panels, i); arrange_windows(&root_container, -1, -1); break; } } }
void lock_surface_destructor(struct wl_resource *resource) { sway_log(L_DEBUG, "Lock surface killed"); int i; for (i = 0; i < desktop_shell.lock_surfaces->length; ++i) { struct wl_resource *surface = desktop_shell.lock_surfaces->items[i]; if (surface == resource) { list_del(desktop_shell.lock_surfaces, i); arrange_windows(&root_container, -1, -1); desktop_shell.is_locked = false; break; } } }
static bool handle_view_created(wlc_handle handle) { swayc_t *focused = get_focused_container(&root_container); uint32_t type = wlc_view_get_type(handle); // If override_redirect/unmanaged/popup/modal/splach if (type) { sway_log(L_DEBUG,"Unmanaged window of type %x left alone", type); wlc_view_set_state(handle, WLC_BIT_ACTIVATED, true); if (type & WLC_BIT_UNMANAGED) { return true; } // For things like Dmenu if (type & WLC_BIT_OVERRIDE_REDIRECT) { override_redirect = true; wlc_view_focus(handle); } // Float popups if (type & WLC_BIT_POPUP) { swayc_t *view = new_floating_view(handle); wlc_view_set_state(handle, WLC_BIT_MAXIMIZED, false); focus_view(view); arrange_windows(active_workspace, -1, -1); } } else { swayc_t *view = new_view(focused, handle); //Set maximize flag for windows. //TODO: floating windows have this unset wlc_view_set_state(handle, WLC_BIT_MAXIMIZED, true); unfocus_all(&root_container); focus_view(view); arrange_windows(view->parent, -1, -1); } if (wlc_view_get_state(focused->handle) & WLC_BIT_FULLSCREEN) { unfocus_all(&root_container); focus_view(focused); arrange_windows(focused, -1, -1); } return true; }
static void set_panel(struct wl_client *client, struct wl_resource *resource, struct wl_resource *_output, struct wl_resource *surface) { wlc_handle output = wlc_handle_from_wl_output_resource(_output); if (!output) { return; } sway_log(L_DEBUG, "Setting surface %p as panel for output %d (wl_resource: %p)", surface, (int)output, resource); struct panel_config *config = find_or_create_panel_config(resource); config->output = output; config->surface = wlc_resource_from_wl_surface_resource(surface); config->wl_surface_res = surface; wl_resource_set_destructor(surface, panel_surface_destructor); desktop_shell.panel_size = *wlc_surface_get_size(config->surface); arrange_windows(&root_container, -1, -1); }
struct cmd_results *cmd_reload(int argc, char **argv) { struct cmd_results *error = NULL; if (config->reading) return cmd_results_new(CMD_FAILURE, "reload", "Can't be used in config file."); if ((error = checkarg(argc, "reload", EXPECTED_EQUAL_TO, 0))) { return error; } if (!load_main_config(config->current_config, true)) { return cmd_results_new(CMD_FAILURE, "reload", "Error(s) reloading config."); } load_swaybars(); arrange_windows(&root_container, -1, -1); return cmd_results_new(CMD_SUCCESS, NULL, NULL); }
static void handle_output_resolution_change(wlc_handle output, const struct wlc_size *from, const struct wlc_size *to) { sway_log(L_DEBUG, "Output %u resolution changed to %d x %d", (unsigned int)output, to->w, to->h); swayc_t *c = swayc_by_handle(output); if (!c) return; c->width = to->w; c->height = to->h; if (config->default_layout == L_NONE && config->default_orientation == L_NONE) { if (c->width >= c->height) { ((swayc_t*)c->children->items[0])->layout = L_HORIZ; } else { ((swayc_t*)c->children->items[0])->layout = L_VERT; } } arrange_windows(&root_container, -1, -1); }
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); }
static void handle_view_geometry_request(wlc_handle handle, const struct wlc_geometry* geometry) { // If the view is floating, then apply the geometry. // Otherwise save the desired width/height for the view. // This will not do anything for the time being as WLC improperly sends geometry requests swayc_t *view = get_swayc_for_handle(handle, &root_container); if (view) { view->desired_width = geometry->size.w; view->desired_height = geometry->size.h; if (view->is_floating) { view->width = view->desired_width; view->height = view->desired_height; view->x = geometry->origin.x; view->y = geometry->origin.y; arrange_windows(view->parent, -1, -1); } } }
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 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 void handle_view_destroyed(wlc_handle handle) { sway_log(L_DEBUG, "Destroying window %u", (unsigned int)handle); // Properly handle unmanaged views uint32_t type = wlc_view_get_type(handle); if (type) { wlc_view_set_state(handle, WLC_BIT_ACTIVATED, true); sway_log(L_DEBUG,"Unmanaged window of type %x was destroyed", type); if (type & WLC_BIT_UNMANAGED) { // We need to call focus_view() on focus_pointer because unmanaged windows // do not alter the focus structure of the container tree. This makes focus_pointer() // think that it doesn't need to do anything, so we manually focus the result. focus_view(focus_pointer()); return; } if (type & WLC_BIT_OVERRIDE_REDIRECT) { override_redirect = false; focus_view(focus_pointer()); return; } // WLC_BIT_POPUP doesn't need to be dealt with since it's // treated as a floating view. } swayc_t *view = get_swayc_for_handle(handle, &root_container); swayc_t *parent; swayc_t *focused = get_focused_container(&root_container); if (view) { parent = destroy_view(view); arrange_windows(parent, -1, -1); } if (!focused || focused == view) { focus_pointer(); } }
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); }
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 resize_tiled(int amount, bool use_width) { swayc_t *parent = get_focused_view(swayc_active_workspace()); swayc_t *focused = parent; swayc_t *sibling; if (!parent) { return true; } // Find the closest parent container which has siblings of the proper layout. // Then apply the resize to all of them. int i; if (use_width) { int lnumber = 0; int rnumber = 0; while (parent->parent) { if (parent->parent->layout == L_HORIZ && parent->parent->children) { for (i = 0; i < parent->parent->children->length; i++) { sibling = parent->parent->children->items[i]; if (sibling->x != focused->x) { if (sibling->x < parent->x) { lnumber++; } else if (sibling->x > parent->x) { rnumber++; } } } if (rnumber || lnumber) { break; } } parent = parent->parent; } if (parent == &root_container) { return true; } sway_log(L_DEBUG, "Found the proper parent: %p. It has %d l conts, and %d r conts", parent->parent, lnumber, rnumber); //TODO: Ensure rounding is done in such a way that there are NO pixel leaks bool valid = true; for (i = 0; i < parent->parent->children->length; i++) { sibling = parent->parent->children->items[i]; if (sibling->x != focused->x) { if (sibling->x < parent->x) { double pixels = -1 * amount; pixels /= lnumber; if (rnumber) { if ((sibling->width + pixels/2) < min_sane_w) { valid = false; break; } } else { if ((sibling->width + pixels) < min_sane_w) { valid = false; break; } } } else if (sibling->x > parent->x) { double pixels = -1 * amount; pixels /= rnumber; if (lnumber) { if ((sibling->width + pixels/2) < min_sane_w) { valid = false; break; } } else { if ((sibling->width + pixels) < min_sane_w) { valid = false; break; } } } } else { double pixels = amount; if (parent->width + pixels < min_sane_w) { valid = false; break; } } } if (valid) { for (i = 0; i < parent->parent->children->length; i++) { sibling = parent->parent->children->items[i]; if (sibling->x != focused->x) { if (sibling->x < parent->x) { double pixels = -1 * amount; pixels /= lnumber; if (rnumber) { recursive_resize(sibling, pixels/2, WLC_RESIZE_EDGE_RIGHT); } else { recursive_resize(sibling, pixels, WLC_RESIZE_EDGE_RIGHT); } } else if (sibling->x > parent->x) { double pixels = -1 * amount; pixels /= rnumber; if (lnumber) { recursive_resize(sibling, pixels/2, WLC_RESIZE_EDGE_LEFT); } else { recursive_resize(sibling, pixels, WLC_RESIZE_EDGE_LEFT); } } } else { if (rnumber != 0 && lnumber != 0) { double pixels = amount; pixels /= 2; recursive_resize(parent, pixels, WLC_RESIZE_EDGE_LEFT); recursive_resize(parent, pixels, WLC_RESIZE_EDGE_RIGHT); } else if (rnumber) { recursive_resize(parent, amount, WLC_RESIZE_EDGE_RIGHT); } else if (lnumber) { recursive_resize(parent, amount, WLC_RESIZE_EDGE_LEFT); } } } // Recursive resize does not handle positions, let arrange_windows // take care of that. arrange_windows(swayc_active_workspace(), -1, -1); } return true; } else { int tnumber = 0; int bnumber = 0; while (parent->parent) { if (parent->parent->layout == L_VERT) { for (i = 0; i < parent->parent->children->length; i++) { sibling = parent->parent->children->items[i]; if (sibling->y != focused->y) { if (sibling->y < parent->y) { bnumber++; } else if (sibling->y > parent->y) { tnumber++; } } } if (bnumber || tnumber) { break; } } parent = parent->parent; } if (parent->parent == NULL || parent->parent->children == NULL) { return true; } sway_log(L_DEBUG, "Found the proper parent: %p. It has %d b conts, and %d t conts", parent->parent, bnumber, tnumber); //TODO: Ensure rounding is done in such a way that there are NO pixel leaks bool valid = true; for (i = 0; i < parent->parent->children->length; i++) { sibling = parent->parent->children->items[i]; if (sibling->y != focused->y) { if (sibling->y < parent->y) { double pixels = -1 * amount; pixels /= bnumber; if (tnumber) { if ((sibling->height + pixels/2) < min_sane_h) { valid = false; break; } } else { if ((sibling->height + pixels) < min_sane_h) { valid = false; break; } } } else if (sibling->y > parent->y) { double pixels = -1 * amount; pixels /= tnumber; if (bnumber) { if ((sibling->height + pixels/2) < min_sane_h) { valid = false; break; } } else { if ((sibling->height + pixels) < min_sane_h) { valid = false; break; } } } } else { double pixels = amount; if (parent->height + pixels < min_sane_h) { valid = false; break; } } } if (valid) { for (i = 0; i < parent->parent->children->length; i++) { sibling = parent->parent->children->items[i]; if (sibling->y != focused->y) { if (sibling->y < parent->y) { double pixels = -1 * amount; pixels /= bnumber; if (tnumber) { recursive_resize(sibling, pixels/2, WLC_RESIZE_EDGE_BOTTOM); } else { recursive_resize(sibling, pixels, WLC_RESIZE_EDGE_BOTTOM); } } else if (sibling->x > parent->x) { double pixels = -1 * amount; pixels /= tnumber; if (bnumber) { recursive_resize(sibling, pixels/2, WLC_RESIZE_EDGE_TOP); } else { recursive_resize(sibling, pixels, WLC_RESIZE_EDGE_TOP); } } } else { if (bnumber != 0 && tnumber != 0) { double pixels = amount/2; recursive_resize(parent, pixels, WLC_RESIZE_EDGE_TOP); recursive_resize(parent, pixels, WLC_RESIZE_EDGE_BOTTOM); } else if (tnumber) { recursive_resize(parent, amount, WLC_RESIZE_EDGE_TOP); } else if (bnumber) { recursive_resize(parent, amount, WLC_RESIZE_EDGE_BOTTOM); } } } arrange_windows(swayc_active_workspace(), -1, -1); } return true; } 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; } }
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; }
void move_container(swayc_t *container, enum movement_direction dir) { enum swayc_layouts layout; if (container->is_floating || (container->type != C_VIEW && container->type != C_CONTAINER)) { return; } if (dir == MOVE_UP || dir == MOVE_DOWN) { layout = L_VERT; } else if (dir == MOVE_LEFT || dir == MOVE_RIGHT) { layout = L_HORIZ; } else { return; } swayc_t *parent = container->parent; swayc_t *child = container; bool ascended = false; while (true) { sway_log(L_DEBUG, "container:%p, parent:%p, child %p,", container,parent,child); if (parent->layout == layout || (parent->layout == L_TABBED && layout == L_HORIZ) || (parent->layout == L_STACKED && layout == L_VERT)) { int diff; // If it has ascended (parent has moved up), no container is removed // so insert it at index, or index+1. // if it has not, the moved container is removed, so it needs to be // inserted at index-1, or index+1 if (ascended) { diff = dir == MOVE_LEFT || dir == MOVE_UP ? 0 : 1; } else { diff = dir == MOVE_LEFT || dir == MOVE_UP ? -1 : 1; } int desired = index_child(child) + diff; // when it has ascended, legal insertion position is 0:len // when it has not, legal insertion position is 0:len-1 if (desired >= 0 && desired - ascended < parent->children->length) { if (!ascended) { child = parent->children->items[desired]; // Move container into sibling container if (child->type == C_CONTAINER) { parent = child; // Insert it in first/last if matching layout, otherwise // inesrt it next to focused container if (parent->layout == layout || (parent->layout == L_TABBED && layout == L_HORIZ) || (parent->layout == L_STACKED && layout == L_VERT)) { desired = (diff < 0) * parent->children->length; } else { desired = index_child(child->focused); } //reset geometry container->width = container->height = 0; } } swayc_t *old_parent = remove_child(container); insert_child(parent, container, desired); destroy_container(old_parent); sway_log(L_DEBUG,"Moving to %p %d",parent, desired); break; } } // Change parent layout if we need to if (parent->children->length == 1 && parent->layout != layout) { parent->layout = layout; continue; } if (parent->type == C_WORKSPACE) { // We simply cannot move any further. if (parent->layout == layout) { break; } // Create container around workspace to insert child into parent = new_container(parent, layout); } ascended = true; child = parent; parent = child->parent; } arrange_windows(parent->parent, -1, -1); set_focused_container_for(parent->parent, container); }
bool read_config(FILE *file, bool is_active) { struct sway_config *old_config = config; config = calloc(1, sizeof(struct sway_config)); config_defaults(config); config->reading = true; if (is_active) { sway_log(L_DEBUG, "Performing configuration file reload"); config->reloading = true; config->active = true; } bool success = true; enum cmd_status block = CMD_BLOCK_END; int line_number = 0; char *line; while (!feof(file)) { line = read_line(file); line_number++; line = strip_whitespace(line); if (line[0] == '#') { continue; } struct cmd_results *res = config_command(line, block); switch(res->status) { case CMD_FAILURE: case CMD_INVALID: sway_log(L_ERROR, "Error on line %i '%s': %s", line_number, line, res->error); success = false; break; case CMD_DEFER: sway_log(L_DEBUG, "Defferring command `%s'", line); list_add(config->cmd_queue, strdup(line)); break; case CMD_BLOCK_MODE: if (block == CMD_BLOCK_END) { block = CMD_BLOCK_MODE; } else { sway_log(L_ERROR, "Invalid block '%s'", line); } break; case CMD_BLOCK_END: switch(block) { case CMD_BLOCK_MODE: sway_log(L_DEBUG, "End of mode block"); config->current_mode = config->modes->items[0]; break; case CMD_BLOCK_END: sway_log(L_ERROR, "Unmatched }"); break; default:; } default:; } free(line); free(res); } if (is_active) { config->reloading = false; arrange_windows(&root_container, -1, -1); } if (old_config) { free_config(old_config); } config->reading = false; return success; }