diff options
Diffstat (limited to 'sway/tree')
-rw-r--r-- | sway/tree/arrange.c | 3 | ||||
-rw-r--r-- | sway/tree/container.c | 38 | ||||
-rw-r--r-- | sway/tree/output.c | 30 | ||||
-rw-r--r-- | sway/tree/root.c | 21 | ||||
-rw-r--r-- | sway/tree/view.c | 29 | ||||
-rw-r--r-- | sway/tree/workspace.c | 81 |
6 files changed, 115 insertions, 87 deletions
diff --git a/sway/tree/arrange.c b/sway/tree/arrange.c index d50be25d..373460a2 100644 --- a/sway/tree/arrange.c +++ b/sway/tree/arrange.c @@ -186,6 +186,7 @@ void arrange_workspace(struct sway_workspace *workspace) { area->width, area->height, area->x, area->y); workspace_remove_gaps(workspace); + bool first_arrange = workspace->width == 0 && workspace->height == 0; double prev_x = workspace->x; double prev_y = workspace->y; workspace->width = area->width; @@ -196,7 +197,7 @@ void arrange_workspace(struct sway_workspace *workspace) { // Adjust any floating containers double diff_x = workspace->x - prev_x; double diff_y = workspace->y - prev_y; - if (diff_x != 0 || diff_y != 0) { + if (!first_arrange && (diff_x != 0 || diff_y != 0)) { for (int i = 0; i < workspace->floating->length; ++i) { struct sway_container *floater = workspace->floating->items[i]; container_floating_translate(floater, diff_x, diff_y); diff --git a/sway/tree/container.c b/sway/tree/container.c index 47687744..788300cc 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -67,12 +67,10 @@ void container_destroy(struct sway_container *con) { list_free(con->outputs); if (con->view) { - struct sway_view *view = con->view; - view->container = NULL; - free(view->title_format); - view->title_format = NULL; - - if (view->destroying) { + if (con->view->container == con) { + con->view->container = NULL; + } + if (con->view->destroying) { view_destroy(con->view); } } @@ -215,8 +213,7 @@ static struct sway_container *container_at_tabbed(struct sway_node *parent, child_index = children->length - 1; } struct sway_container *child = children->items[child_index]; - struct sway_node *node = seat_get_focus_inactive(seat, &child->node); - return node->sway_container; + return child; } // Surfaces @@ -243,8 +240,7 @@ static struct sway_container *container_at_stacked(struct sway_node *parent, int child_index = (ly - box.y) / title_height; if (child_index < children->length) { struct sway_container *child = children->items[child_index]; - struct sway_node *node = seat_get_focus_inactive(seat, &child->node); - return node->sway_container; + return child; } // Surfaces @@ -465,11 +461,17 @@ static void update_title_texture(struct sway_container *con, cairo_surface_t *surface = cairo_image_surface_create( CAIRO_FORMAT_ARGB32, width, height); cairo_t *cairo = cairo_create(surface); + cairo_set_antialias(cairo, CAIRO_ANTIALIAS_BEST); + cairo_font_options_t *fo = cairo_font_options_create(); + cairo_font_options_set_hint_style(fo, CAIRO_HINT_STYLE_FULL); + cairo_font_options_set_antialias(fo, CAIRO_ANTIALIAS_SUBPIXEL); + cairo_font_options_set_subpixel_order(fo, to_cairo_subpixel_order(output->wlr_output->subpixel)); + cairo_set_font_options(cairo, fo); + cairo_font_options_destroy(fo); cairo_set_source_rgba(cairo, class->background[0], class->background[1], class->background[2], class->background[3]); cairo_paint(cairo); PangoContext *pango = pango_cairo_create_context(cairo); - cairo_set_antialias(cairo, CAIRO_ANTIALIAS_BEST); cairo_set_source_rgba(cairo, class->text[0], class->text[1], class->text[2], class->text[3]); cairo_move_to(cairo, 0, 0); @@ -591,7 +593,7 @@ void container_update_representation(struct sway_container *con) { } } -size_t container_titlebar_height() { +size_t container_titlebar_height(void) { return config->font_height + TITLEBAR_V_PADDING * 2; } @@ -821,9 +823,16 @@ void container_floating_move_to_center(struct sway_container *con) { return; } struct sway_workspace *ws = con->workspace; + bool full = con->is_fullscreen; + if (full) { + container_set_fullscreen(con, false); + } double new_lx = ws->x + (ws->width - con->width) / 2; double new_ly = ws->y + (ws->height - con->height) / 2; container_floating_translate(con, new_lx - con->x, new_ly - con->y); + if (full) { + container_set_fullscreen(con, true); + } } static bool find_urgent_iterator(struct sway_container *con, void *data) { @@ -981,7 +990,8 @@ void container_discover_outputs(struct sway_container *con) { } } struct sway_output *new_output = container_get_effective_output(con); - double old_scale = old_output ? old_output->wlr_output->scale : -1; + double old_scale = old_output && old_output->enabled ? + old_output->wlr_output->scale : -1; double new_scale = new_output ? new_output->wlr_output->scale : -1; if (old_scale != new_scale) { container_update_title_textures(con); @@ -1019,7 +1029,7 @@ void container_add_gaps(struct sway_container *c) { struct sway_workspace *ws = c->workspace; - c->current_gaps = ws->has_gaps ? ws->gaps_inner : config->gaps_inner; + c->current_gaps = ws->gaps_inner; c->x += c->current_gaps; c->y += c->current_gaps; c->width -= 2 * c->current_gaps; diff --git a/sway/tree/output.c b/sway/tree/output.c index 1976ad51..c3176325 100644 --- a/sway/tree/output.c +++ b/sway/tree/output.c @@ -109,12 +109,24 @@ void output_enable(struct sway_output *output, struct output_config *oc) { wl_signal_emit(&root->events.new_node, &output->node); - load_swaybars(); - arrange_layers(output); arrange_root(); } +static void evacuate_sticky(struct sway_workspace *old_ws, + struct sway_output *new_output) { + struct sway_workspace *new_ws = output_get_active_workspace(new_output); + while (old_ws->floating->length) { + struct sway_container *sticky = old_ws->floating->items[0]; + container_detach(sticky); + workspace_add_floating(new_ws, sticky); + container_handle_fullscreen_reparent(sticky); + container_floating_move_to_center(sticky); + ipc_event_window(sticky, "move"); + } + workspace_detect_urgent(new_ws); +} + static void output_evacuate(struct sway_output *output) { if (!output->workspaces->length) { return; @@ -132,17 +144,21 @@ static void output_evacuate(struct sway_output *output) { workspace_detach(workspace); - if (workspace_is_empty(workspace)) { - workspace_begin_destroy(workspace); - continue; - } - struct sway_output *new_output = workspace_output_get_highest_available(workspace, output); if (!new_output) { new_output = fallback_output; } + if (workspace_is_empty(workspace)) { + // If floating is not empty, there are sticky containers to move + if (workspace->floating->length) { + evacuate_sticky(workspace, new_output); + } + workspace_begin_destroy(workspace); + continue; + } + if (new_output) { workspace_output_add_priority(workspace, new_output); output_add_workspace(new_output, workspace); diff --git a/sway/tree/root.c b/sway/tree/root.c index ecc04ddb..6748e9c9 100644 --- a/sway/tree/root.c +++ b/sway/tree/root.c @@ -265,14 +265,20 @@ void root_for_each_container(void (*f)(struct sway_container *con, void *data), // Scratchpad for (int i = 0; i < root->scratchpad->length; ++i) { struct sway_container *container = root->scratchpad->items[i]; - // If the container has a parent then it's visible on a workspace + // If the container has a workspace then it's visible on a workspace // and will have been iterated in the previous for loop. So we only // iterate the hidden scratchpad containers here. - if (!container->parent) { + if (!container->workspace) { f(container, data); container_for_each_child(container, f, data); } } + + // Saved workspaces + for (int i = 0; i < root->saved_workspaces->length; ++i) { + struct sway_workspace *ws = root->saved_workspaces->items[i]; + workspace_for_each_container(ws, f, data); + } } struct sway_output *root_find_output( @@ -311,7 +317,7 @@ struct sway_container *root_find_container( // Scratchpad for (int i = 0; i < root->scratchpad->length; ++i) { struct sway_container *container = root->scratchpad->items[i]; - if (!container->parent) { + if (!container->workspace) { if (test(container, data)) { return container; } @@ -320,6 +326,15 @@ struct sway_container *root_find_container( } } } + + // Saved workspaces + for (int i = 0; i < root->saved_workspaces->length; ++i) { + struct sway_workspace *ws = root->saved_workspaces->items[i]; + if ((result = workspace_find_container(ws, test, data))) { + return result; + } + } + return NULL; } diff --git a/sway/tree/view.c b/sway/tree/view.c index 4398f518..a024f325 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -391,8 +391,6 @@ static bool view_has_executed_criteria(struct sway_view *view, } void view_execute_criteria(struct sway_view *view) { - struct sway_seat *seat = input_manager_current_seat(input_manager); - struct sway_node *prior_focus = seat_get_focus(seat); list_t *criterias = criteria_for_view(view, CT_COMMAND); for (int i = 0; i < criterias->length; i++) { struct criteria *criteria = criterias->items[i]; @@ -403,16 +401,12 @@ void view_execute_criteria(struct sway_view *view) { } wlr_log(WLR_DEBUG, "for_window '%s' matches view %p, cmd: '%s'", criteria->raw, view, criteria->cmdlist); - seat_set_focus_container(seat, view->container); list_add(view->executed_criteria, criteria); - struct cmd_results *res = execute_command(criteria->cmdlist, NULL); - if (res->status != CMD_SUCCESS) { - wlr_log(WLR_ERROR, "Command '%s' failed: %s", res->input, res->error); - } + struct cmd_results *res = execute_command( + criteria->cmdlist, NULL, view->container); free_cmd_results(res); } list_free(criterias); - seat_set_focus(seat, prior_focus); } static struct sway_workspace *select_workspace(struct sway_view *view) { @@ -785,14 +779,9 @@ static size_t parse_title_format(struct sway_view *view, char *buffer) { } static char *escape_title(char *buffer) { - int length = escape_markup_text(buffer, NULL, 0); + size_t length = escape_markup_text(buffer, NULL); char *escaped_title = calloc(length + 1, sizeof(char)); - int result = escape_markup_text(buffer, escaped_title, length); - if (result != length) { - wlr_log(WLR_ERROR, "Could not escape title: %s", buffer); - free(escaped_title); - return buffer; - } + escape_markup_text(buffer, escaped_title); free(buffer); return escaped_title; } @@ -1000,12 +989,16 @@ bool view_is_visible(struct sway_view *view) { floater = floater->parent; } bool is_sticky = container_is_floating(floater) && floater->is_sticky; + if (!is_sticky && !workspace_is_visible(workspace)) { + return false; + } // Check view isn't in a tabbed or stacked container on an inactive tab struct sway_seat *seat = input_manager_current_seat(input_manager); struct sway_container *con = view->container; while (con) { enum sway_container_layout layout = container_parent_layout(con); - if (layout == L_TABBED || layout == L_STACKED) { + if ((layout == L_TABBED || layout == L_STACKED) + && !container_is_floating(con)) { struct sway_node *parent = con->parent ? &con->parent->node : &con->workspace->node; if (seat_get_active_tiling_child(seat, parent) != &con->node) { @@ -1019,10 +1012,6 @@ bool view_is_visible(struct sway_view *view) { !container_is_fullscreen_or_child(view->container)) { return false; } - // Check the workspace is visible - if (!is_sticky) { - return workspace_is_visible(workspace); - } return true; } diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 18746430..9dd5c815 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -20,17 +20,23 @@ #include "log.h" #include "util.h" +struct workspace_config *workspace_find_config(const char *ws_name) { + for (int i = 0; i < config->workspace_configs->length; ++i) { + struct workspace_config *wsc = config->workspace_configs->items[i]; + if (strcmp(wsc->workspace, ws_name) == 0) { + return wsc; + } + } + return NULL; +} + struct sway_output *workspace_get_initial_output(const char *name) { - // Search for workspace<->output pair - for (int i = 0; i < config->workspace_outputs->length; ++i) { - struct workspace_output *wso = config->workspace_outputs->items[i]; - if (strcasecmp(wso->workspace, name) == 0) { - // Find output to use if it exists - struct sway_output *output = output_by_name(wso->output); - if (output) { - return output; - } - break; + // Check workspace configs for a workspace<->output pair + struct workspace_config *wsc = workspace_find_config(name); + if (wsc && wsc->output) { + struct sway_output *output = output_by_name(wsc->output); + if (output) { + return output; } } // Otherwise put it on the focused output @@ -54,10 +60,6 @@ struct sway_workspace *workspace_create(struct sway_output *output, return NULL; } node_init(&ws->node, N_WORKSPACE, ws); - ws->x = output->lx; - ws->y = output->ly; - ws->width = output->width; - ws->height = output->height; ws->name = name ? strdup(name) : NULL; ws->prev_split_layout = L_NONE; ws->layout = output_get_default_layout(output); @@ -66,6 +68,20 @@ struct sway_workspace *workspace_create(struct sway_output *output, ws->output_priority = create_list(); workspace_output_add_priority(ws, output); + ws->gaps_outer = config->gaps_outer; + ws->gaps_inner = config->gaps_inner; + if (name) { + struct workspace_config *wsc = workspace_find_config(name); + if (wsc) { + if (wsc->gaps_outer != -1) { + ws->gaps_outer = wsc->gaps_outer; + } + if (wsc->gaps_inner != -1) { + ws->gaps_inner = wsc->gaps_inner; + } + } + } + output_add_workspace(output, ws); output_sort_workspaces(output); @@ -125,17 +141,8 @@ void next_name_map(struct sway_container *ws, void *data) { static bool workspace_valid_on_output(const char *output_name, const char *ws_name) { - int i; - for (i = 0; i < config->workspace_outputs->length; ++i) { - struct workspace_output *wso = config->workspace_outputs->items[i]; - if (strcasecmp(wso->workspace, ws_name) == 0) { - if (strcasecmp(wso->output, output_name) != 0) { - return false; - } - } - } - - return true; + struct workspace_config *wsc = workspace_find_config(ws_name); + return !wsc || !wsc->output || strcmp(wsc->output, output_name) == 0; } static void workspace_name_from_binding(const struct sway_binding * binding, @@ -235,13 +242,13 @@ char *workspace_next_name(const char *output_name) { workspace_name_from_binding(mode->keycode_bindings->items[i], output_name, &order, &target); } - for (int i = 0; i < config->workspace_outputs->length; ++i) { + for (int i = 0; i < config->workspace_configs->length; ++i) { // Unlike with bindings, this does not guarantee order - const struct workspace_output *wso = config->workspace_outputs->items[i]; - if (strcmp(wso->output, output_name) == 0 - && workspace_by_name(wso->workspace) == NULL) { + const struct workspace_config *wsc = config->workspace_configs->items[i]; + if (wsc->output && strcmp(wsc->output, output_name) == 0 + && workspace_by_name(wsc->workspace) == NULL) { free(target); - target = strdup(wso->workspace); + target = strdup(wsc->workspace); break; } } @@ -389,13 +396,11 @@ bool workspace_switch(struct sway_workspace *workspace, struct sway_output *next_output = workspace->output; struct sway_workspace *next_output_prev_ws = output_get_active_workspace(next_output); - bool has_sticky = false; if (workspace != next_output_prev_ws) { for (int i = 0; i < next_output_prev_ws->floating->length; ++i) { struct sway_container *floater = next_output_prev_ws->floating->items[i]; if (floater->is_sticky) { - has_sticky = true; container_detach(floater); workspace_add_floating(workspace, floater); if (&floater->node == focus) { @@ -414,14 +419,6 @@ bool workspace_switch(struct sway_workspace *workspace, if (next == NULL) { next = &workspace->node; } - if (has_sticky) { - // If there's a sticky container, we might be setting focus to the same - // container that's already focused, so seat_set_focus is effectively a - // no op. We therefore need to send the IPC event and clean up the old - // workspace here. - ipc_event_workspace(active_ws, workspace, "focus"); - workspace_consider_destroy(active_ws); - } seat_set_focus(seat, next); arrange_workspace(workspace); cursor_send_pointer_motion(seat->cursor, 0, true); @@ -649,13 +646,13 @@ void workspace_add_gaps(struct sway_workspace *ws) { return; } - ws->current_gaps = ws->has_gaps ? ws->gaps_outer : config->gaps_outer; + ws->current_gaps = ws->gaps_outer; if (ws->layout == L_TABBED || ws->layout == L_STACKED) { // We have to add inner gaps for this, because children of tabbed and // stacked containers don't apply their own gaps - they assume the // tabbed/stacked container is using gaps. - ws->current_gaps += ws->has_gaps ? ws->gaps_inner : config->gaps_inner; + ws->current_gaps += ws->gaps_inner; } ws->x += ws->current_gaps; |