diff options
Diffstat (limited to 'sway/tree')
-rw-r--r-- | sway/tree/arrange.c | 25 | ||||
-rw-r--r-- | sway/tree/container.c | 47 | ||||
-rw-r--r-- | sway/tree/node.c | 8 | ||||
-rw-r--r-- | sway/tree/output.c | 43 | ||||
-rw-r--r-- | sway/tree/root.c | 181 | ||||
-rw-r--r-- | sway/tree/view.c | 44 | ||||
-rw-r--r-- | sway/tree/workspace.c | 8 |
7 files changed, 119 insertions, 237 deletions
diff --git a/sway/tree/arrange.c b/sway/tree/arrange.c index 4aa82c35..9c1a11e5 100644 --- a/sway/tree/arrange.c +++ b/sway/tree/arrange.c @@ -311,12 +311,13 @@ void arrange_output(struct sway_output *output) { if (config->reloading) { return; } - const struct wlr_box *output_box = wlr_output_layout_get_box( - root->output_layout, output->wlr_output); - output->lx = output_box->x; - output->ly = output_box->y; - output->width = output_box->width; - output->height = output_box->height; + struct wlr_box output_box; + wlr_output_layout_get_box(root->output_layout, + output->wlr_output, &output_box); + output->lx = output_box.x; + output->ly = output_box.y; + output->width = output_box.width; + output->height = output_box.height; for (int i = 0; i < output->workspaces->length; ++i) { struct sway_workspace *workspace = output->workspaces->items[i]; @@ -328,12 +329,12 @@ void arrange_root(void) { if (config->reloading) { return; } - const struct wlr_box *layout_box = - wlr_output_layout_get_box(root->output_layout, NULL); - root->x = layout_box->x; - root->y = layout_box->y; - root->width = layout_box->width; - root->height = layout_box->height; + struct wlr_box layout_box; + wlr_output_layout_get_box(root->output_layout, NULL, &layout_box); + root->x = layout_box.x; + root->y = layout_box.y; + root->width = layout_box.width; + root->height = layout_box.height; if (root->fullscreen_global) { struct sway_container *fs = root->fullscreen_global; diff --git a/sway/tree/container.c b/sway/tree/container.c index 73bb865c..29a1e226 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -9,6 +9,7 @@ #include <wayland-server-core.h> #include <wlr/types/wlr_linux_dmabuf_v1.h> #include <wlr/types/wlr_output_layout.h> +#include <wlr/types/wlr_subcompositor.h> #include <wlr/render/drm_format_set.h> #include "linux-dmabuf-unstable-v1-protocol.h" #include "cairo_util.h" @@ -51,7 +52,7 @@ struct sway_container *container_create(struct sway_view *view) { c->outputs = create_list(); wl_signal_init(&c->events.destroy); - wl_signal_emit(&root->events.new_node, &c->node); + wl_signal_emit_mutable(&root->events.new_node, &c->node); return c; } @@ -106,7 +107,7 @@ void container_begin_destroy(struct sway_container *con) { container_fullscreen_disable(con); } - wl_signal_emit(&con->node.events.destroy, &con->node); + wl_signal_emit_mutable(&con->node.events.destroy, &con->node); container_end_mouse_operation(con); @@ -196,7 +197,7 @@ static struct sway_container *surface_at_view(struct sway_container *con, double #endif case SWAY_VIEW_XDG_SHELL: _surface = wlr_xdg_surface_surface_at( - view->wlr_xdg_surface, + view->wlr_xdg_toplevel->base, view_sx, view_sy, &_sx, &_sy); break; } @@ -522,7 +523,7 @@ static void render_titlebar_text_texture(struct sway_output *output, to_cairo_subpixel_order(output->wlr_output->subpixel)); } cairo_set_font_options(c, fo); - get_text_size(c, config->font, &width, NULL, &baseline, scale, + get_text_size(c, config->font_description, &width, NULL, &baseline, scale, config->pango_markup, "%s", text); cairo_surface_destroy(dummy_surface); cairo_destroy(c); @@ -556,7 +557,7 @@ static void render_titlebar_text_texture(struct sway_output *output, class->text[2], class->text[3]); cairo_move_to(cairo, 0, config->font_baseline * scale - baseline); - render_text(cairo, config->font, scale, pango_markup, "%s", text); + render_text(cairo, config->font_description, scale, pango_markup, "%s", text); cairo_surface_flush(surface); unsigned char *data = cairo_image_surface_get_data(surface); @@ -697,12 +698,13 @@ void floating_calculate_constraints(int *min_width, int *max_width, *min_height = config->floating_minimum_height; } - struct wlr_box *box = wlr_output_layout_get_box(root->output_layout, NULL); + struct wlr_box box; + wlr_output_layout_get_box(root->output_layout, NULL, &box); if (config->floating_maximum_width == -1) { // no maximum *max_width = INT_MAX; } else if (config->floating_maximum_width == 0) { // automatic - *max_width = box->width; + *max_width = box.width; } else { *max_width = config->floating_maximum_width; } @@ -710,7 +712,7 @@ void floating_calculate_constraints(int *min_width, int *max_width, if (config->floating_maximum_height == -1) { // no maximum *max_height = INT_MAX; } else if (config->floating_maximum_height == 0) { // automatic - *max_height = box->height; + *max_height = box.height; } else { *max_height = config->floating_maximum_height; } @@ -742,9 +744,9 @@ void container_floating_resize_and_center(struct sway_container *con) { return; } - struct wlr_box *ob = wlr_output_layout_get_box(root->output_layout, - ws->output->wlr_output); - if (!ob) { + struct wlr_box ob; + wlr_output_layout_get_box(root->output_layout, ws->output->wlr_output, &ob); + if (wlr_box_empty(&ob)) { // On NOOP output. Will be called again when moved to an output con->pending.x = 0; con->pending.y = 0; @@ -756,8 +758,8 @@ void container_floating_resize_and_center(struct sway_container *con) { floating_natural_resize(con); if (!con->view) { if (con->pending.width > ws->width || con->pending.height > ws->height) { - con->pending.x = ob->x + (ob->width - con->pending.width) / 2; - con->pending.y = ob->y + (ob->height - con->pending.height) / 2; + con->pending.x = ob.x + (ob.width - con->pending.width) / 2; + con->pending.y = ob.y + (ob.height - con->pending.height) / 2; } else { con->pending.x = ws->x + (ws->width - con->pending.width) / 2; con->pending.y = ws->y + (ws->height - con->pending.height) / 2; @@ -765,8 +767,8 @@ void container_floating_resize_and_center(struct sway_container *con) { } else { if (con->pending.content_width > ws->width || con->pending.content_height > ws->height) { - con->pending.content_x = ob->x + (ob->width - con->pending.content_width) / 2; - con->pending.content_y = ob->y + (ob->height - con->pending.content_height) / 2; + con->pending.content_x = ob.x + (ob.width - con->pending.content_width) / 2; + con->pending.content_y = ob.y + (ob.height - con->pending.content_height) / 2; } else { con->pending.content_x = ws->x + (ws->width - con->pending.content_width) / 2; con->pending.content_y = ws->y + (ws->height - con->pending.content_height) / 2; @@ -788,11 +790,11 @@ void container_floating_set_default_size(struct sway_container *con) { int min_width, max_width, min_height, max_height; floating_calculate_constraints(&min_width, &max_width, &min_height, &max_height); - struct wlr_box *box = calloc(1, sizeof(struct wlr_box)); - workspace_get_box(con->pending.workspace, box); + struct wlr_box box; + workspace_get_box(con->pending.workspace, &box); - double width = fmax(min_width, fmin(box->width * 0.5, max_width)); - double height = fmax(min_height, fmin(box->height * 0.75, max_height)); + double width = fmax(min_width, fmin(box.width * 0.5, max_width)); + double height = fmax(min_height, fmin(box.height * 0.75, max_height)); if (!con->view) { con->pending.width = width; con->pending.height = height; @@ -801,8 +803,6 @@ void container_floating_set_default_size(struct sway_container *con) { con->pending.content_height = height; container_set_geometry_from_content(con); } - - free(box); } @@ -1413,6 +1413,9 @@ list_t *container_get_siblings(struct sway_container *container) { if (container_is_scratchpad_hidden(container)) { return NULL; } + if (!container->pending.workspace) { + return NULL; + } if (list_find(container->pending.workspace->tiling, container) != -1) { return container->pending.workspace->tiling; } @@ -1707,7 +1710,7 @@ static void update_marks_texture(struct sway_container *con, for (int i = 0; i < con->marks->length; ++i) { char *mark = con->marks->items[i]; if (mark[0] != '_') { - sprintf(part, "[%s]", mark); + snprintf(part, len + 1, "[%s]", mark); strcat(buffer, part); } } diff --git a/sway/tree/node.c b/sway/tree/node.c index bc7e2aa5..12361c75 100644 --- a/sway/tree/node.c +++ b/sway/tree/node.c @@ -18,13 +18,13 @@ void node_init(struct sway_node *node, enum sway_node_type type, void *thing) { const char *node_type_to_str(enum sway_node_type type) { switch (type) { case N_ROOT: - return "N_ROOT"; + return "root"; case N_OUTPUT: - return "N_OUTPUT"; + return "output"; case N_WORKSPACE: - return "N_WORKSPACE"; + return "workspace"; case N_CONTAINER: - return "N_CONTAINER"; + return "container"; } return ""; } diff --git a/sway/tree/output.c b/sway/tree/output.c index ad8d2482..eccab2f7 100644 --- a/sway/tree/output.c +++ b/sway/tree/output.c @@ -3,12 +3,12 @@ #include <ctype.h> #include <string.h> #include <strings.h> -#include <wlr/types/wlr_output_damage.h> #include "sway/ipc-server.h" #include "sway/layers.h" #include "sway/output.h" #include "sway/tree/arrange.h" #include "sway/tree/workspace.h" +#include "sway/server.h" #include "log.h" #include "util.h" @@ -146,7 +146,7 @@ void output_enable(struct sway_output *output) { input_manager_configure_xcursor(); - wl_signal_emit(&root->events.new_node, &output->node); + wl_signal_emit_mutable(&root->events.new_node, &output->node); arrange_layers(output); arrange_root(); @@ -262,7 +262,7 @@ void output_disable(struct sway_output *output) { } sway_log(SWAY_DEBUG, "Disabling output '%s'", output->wlr_output->name); - wl_signal_emit(&output->events.disable, output); + wl_signal_emit_mutable(&output->events.disable, output); output_evacuate(output); @@ -286,7 +286,7 @@ void output_begin_destroy(struct sway_output *output) { return; } sway_log(SWAY_DEBUG, "Destroying output '%s'", output->wlr_output->name); - wl_signal_emit(&output->node.events.destroy, &output->node); + wl_signal_emit_mutable(&output->node.events.destroy, &output->node); output->node.destroying = true; node_set_dirty(&output->node); @@ -301,10 +301,10 @@ struct sway_output *output_get_in_direction(struct sway_output *reference, if (!sway_assert(direction, "got invalid direction: %d", direction)) { return NULL; } - struct wlr_box *output_box = - wlr_output_layout_get_box(root->output_layout, reference->wlr_output); - int lx = output_box->x + output_box->width / 2; - int ly = output_box->y + output_box->height / 2; + struct wlr_box output_box; + wlr_output_layout_get_box(root->output_layout, reference->wlr_output, &output_box); + int lx = output_box.x + output_box.width / 2; + int ly = output_box.y + output_box.height / 2; struct wlr_output *wlr_adjacent = wlr_output_layout_adjacent_output( root->output_layout, direction, reference->wlr_output, lx, ly); if (!wlr_adjacent) { @@ -390,6 +390,33 @@ void output_get_box(struct sway_output *output, struct wlr_box *box) { box->height = output->height; } +static void handle_destroy_non_desktop(struct wl_listener *listener, void *data) { + struct sway_output_non_desktop *output = + wl_container_of(listener, output, destroy); + + sway_log(SWAY_DEBUG, "Destroying non-desktop output '%s'", output->wlr_output->name); + + int index = list_find(root->non_desktop_outputs, output); + list_del(root->non_desktop_outputs, index); + + wl_list_remove(&output->destroy.link); + + free(output); +} + +struct sway_output_non_desktop *output_non_desktop_create( + struct wlr_output *wlr_output) { + struct sway_output_non_desktop *output = + calloc(1, sizeof(struct sway_output_non_desktop)); + + output->wlr_output = wlr_output; + + wl_signal_add(&wlr_output->events.destroy, &output->destroy); + output->destroy.notify = handle_destroy_non_desktop; + + return output; +} + enum sway_container_layout output_get_default_layout( struct sway_output *output) { if (config->default_orientation != L_NONE) { diff --git a/sway/tree/root.c b/sway/tree/root.c index 73f3993c..8934721f 100644 --- a/sway/tree/root.c +++ b/sway/tree/root.c @@ -38,6 +38,7 @@ struct sway_root *root_create(void) { wl_list_init(&root->drag_icons); wl_signal_init(&root->events.new_node); root->outputs = create_list(); + root->non_desktop_outputs = create_list(); root->scratchpad = create_list(); root->output_layout_change.notify = output_layout_handle_change; @@ -183,172 +184,6 @@ void root_scratchpad_hide(struct sway_container *con) { ipc_event_window(con, "move"); } -struct pid_workspace { - pid_t pid; - char *workspace; - struct timespec time_added; - - struct sway_output *output; - struct wl_listener output_destroy; - - struct wl_list link; -}; - -static struct wl_list pid_workspaces; - -/** - * Get the pid of a parent process given the pid of a child process. - * - * Returns the parent pid or NULL if the parent pid cannot be determined. - */ -static pid_t get_parent_pid(pid_t child) { - pid_t parent = -1; - char file_name[100]; - char *buffer = NULL; - const char *sep = " "; - FILE *stat = NULL; - size_t buf_size = 0; - - sprintf(file_name, "/proc/%d/stat", child); - - if ((stat = fopen(file_name, "r"))) { - if (getline(&buffer, &buf_size, stat) != -1) { - strtok(buffer, sep); // pid - strtok(NULL, sep); // executable name - strtok(NULL, sep); // state - char *token = strtok(NULL, sep); // parent pid - parent = strtol(token, NULL, 10); - } - free(buffer); - fclose(stat); - } - - if (parent) { - return (parent == child) ? -1 : parent; - } - - return -1; -} - -static void pid_workspace_destroy(struct pid_workspace *pw) { - wl_list_remove(&pw->output_destroy.link); - wl_list_remove(&pw->link); - free(pw->workspace); - free(pw); -} - -struct sway_workspace *root_workspace_for_pid(pid_t pid) { - if (!pid_workspaces.prev && !pid_workspaces.next) { - wl_list_init(&pid_workspaces); - return NULL; - } - - struct sway_workspace *ws = NULL; - struct pid_workspace *pw = NULL; - - sway_log(SWAY_DEBUG, "Looking up workspace for pid %d", pid); - - do { - struct pid_workspace *_pw = NULL; - wl_list_for_each(_pw, &pid_workspaces, link) { - if (pid == _pw->pid) { - pw = _pw; - sway_log(SWAY_DEBUG, - "found pid_workspace for pid %d, workspace %s", - pid, pw->workspace); - goto found; - } - } - pid = get_parent_pid(pid); - } while (pid > 1); -found: - - if (pw && pw->workspace) { - ws = workspace_by_name(pw->workspace); - - if (!ws) { - sway_log(SWAY_DEBUG, - "Creating workspace %s for pid %d because it disappeared", - pw->workspace, pid); - - struct sway_output *output = pw->output; - if (pw->output && !pw->output->enabled) { - sway_log(SWAY_DEBUG, - "Workspace output %s is disabled, trying another one", - pw->output->wlr_output->name); - output = NULL; - } - - ws = workspace_create(output, pw->workspace); - } - - pid_workspace_destroy(pw); - } - - return ws; -} - -static void pw_handle_output_destroy(struct wl_listener *listener, void *data) { - struct pid_workspace *pw = wl_container_of(listener, pw, output_destroy); - pw->output = NULL; - wl_list_remove(&pw->output_destroy.link); - wl_list_init(&pw->output_destroy.link); -} - -void root_record_workspace_pid(pid_t pid) { - sway_log(SWAY_DEBUG, "Recording workspace for process %d", pid); - if (!pid_workspaces.prev && !pid_workspaces.next) { - wl_list_init(&pid_workspaces); - } - - struct sway_seat *seat = input_manager_current_seat(); - struct sway_workspace *ws = seat_get_focused_workspace(seat); - if (!ws) { - sway_log(SWAY_DEBUG, "Bailing out, no workspace"); - return; - } - struct sway_output *output = ws->output; - if (!output) { - sway_log(SWAY_DEBUG, "Bailing out, no output"); - return; - } - - struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - - // Remove expired entries - static const int timeout = 60; - struct pid_workspace *old, *_old; - wl_list_for_each_safe(old, _old, &pid_workspaces, link) { - if (now.tv_sec - old->time_added.tv_sec >= timeout) { - pid_workspace_destroy(old); - } - } - - struct pid_workspace *pw = calloc(1, sizeof(struct pid_workspace)); - pw->workspace = strdup(ws->name); - pw->output = output; - pw->pid = pid; - memcpy(&pw->time_added, &now, sizeof(struct timespec)); - pw->output_destroy.notify = pw_handle_output_destroy; - wl_signal_add(&output->wlr_output->events.destroy, &pw->output_destroy); - wl_list_insert(&pid_workspaces, &pw->link); -} - -void root_remove_workspace_pid(pid_t pid) { - if (!pid_workspaces.prev || !pid_workspaces.next) { - return; - } - - struct pid_workspace *pw, *tmp; - wl_list_for_each_safe(pw, tmp, &pid_workspaces, link) { - if (pid == pw->pid) { - pid_workspace_destroy(pw); - return; - } - } -} - void root_for_each_workspace(void (*f)(struct sway_workspace *ws, void *data), void *data) { for (int i = 0; i < root->outputs->length; ++i) { @@ -443,17 +278,3 @@ void root_get_box(struct sway_root *root, struct wlr_box *box) { box->width = root->width; box->height = root->height; } - -void root_rename_pid_workspaces(const char *old_name, const char *new_name) { - if (!pid_workspaces.prev && !pid_workspaces.next) { - wl_list_init(&pid_workspaces); - } - - struct pid_workspace *pw = NULL; - wl_list_for_each(pw, &pid_workspaces, link) { - if (strcmp(pw->workspace, old_name) == 0) { - free(pw->workspace); - pw->workspace = strdup(new_name); - } - } -} diff --git a/sway/tree/view.c b/sway/tree/view.c index 8b7061ba..9d7b68d1 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -6,6 +6,7 @@ #include <wlr/types/wlr_buffer.h> #include <wlr/types/wlr_output_layout.h> #include <wlr/types/wlr_server_decoration.h> +#include <wlr/types/wlr_subcompositor.h> #include <wlr/types/wlr_xdg_decoration_v1.h> #include "config.h" #if HAVE_XWAYLAND @@ -18,6 +19,7 @@ #include "sway/desktop.h" #include "sway/desktop/transaction.h" #include "sway/desktop/idle_inhibit_v1.h" +#include "sway/desktop/launcher.h" #include "sway/input/cursor.h" #include "sway/ipc-server.h" #include "sway/output.h" @@ -62,6 +64,8 @@ void view_destroy(struct sway_view *view) { } list_free(view->executed_criteria); + view_assign_ctx(view, NULL); + free(view->title_format); if (view->impl->destroy) { @@ -532,6 +536,20 @@ static void view_populate_pid(struct sway_view *view) { view->pid = pid; } +void view_assign_ctx(struct sway_view *view, struct launcher_ctx *ctx) { + if (view->ctx) { + // This ctx has been replaced + launcher_ctx_destroy(view->ctx); + view->ctx = NULL; + } + if (ctx == NULL) { + return; + } + launcher_ctx_consume(ctx); + + view->ctx = ctx; +} + static struct sway_workspace *select_workspace(struct sway_view *view) { struct sway_seat *seat = input_manager_current_seat(); @@ -567,13 +585,14 @@ static struct sway_workspace *select_workspace(struct sway_view *view) { } list_free(criterias); if (ws) { - root_remove_workspace_pid(view->pid); + view_assign_ctx(view, NULL); return ws; } // Check if there's a PID mapping - ws = root_workspace_for_pid(view->pid); + ws = view->ctx ? launcher_ctx_get_workspace(view->ctx) : NULL; if (ws) { + view_assign_ctx(view, NULL); return ws; } @@ -739,6 +758,13 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface, view_populate_pid(view); view->container = container_create(view); + if (view->ctx == NULL) { + struct launcher_ctx *ctx = launcher_ctx_find_pid(view->pid); + if (ctx != NULL) { + view_assign_ctx(view, ctx); + } + } + // If there is a request to be opened fullscreen on a specific output, try // to honor that request. Otherwise, fallback to assigns, pid mappings, // focused workspace, etc @@ -873,7 +899,7 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface, } void view_unmap(struct sway_view *view) { - wl_signal_emit(&view->events.unmap, view); + wl_signal_emit_mutable(&view->events.unmap, view); wl_list_remove(&view->surface_new_subsurface.link); @@ -1308,21 +1334,23 @@ void view_update_title(struct sway_view *view, bool force) { free(view->container->title); free(view->container->formatted_title); - if (title) { - size_t len = parse_title_format(view, NULL); + + size_t len = parse_title_format(view, NULL); + + if (len) { char *buffer = calloc(len + 1, sizeof(char)); if (!sway_assert(buffer, "Unable to allocate title string")) { return; } - parse_title_format(view, buffer); - view->container->title = strdup(title); + parse_title_format(view, buffer); view->container->formatted_title = buffer; } else { - view->container->title = NULL; view->container->formatted_title = NULL; } + view->container->title = title ? strdup(title) : NULL; + // Update title after the global font height is updated container_update_title_textures(view->container); diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index c84320bd..ee940466 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -56,6 +56,8 @@ struct sway_output *workspace_get_initial_output(const char *name) { struct sway_workspace *workspace_create(struct sway_output *output, const char *name) { + sway_assert(name, "NULL name given to workspace_create"); + if (output == NULL) { output = workspace_get_initial_output(name); } @@ -69,7 +71,7 @@ struct sway_workspace *workspace_create(struct sway_output *output, return NULL; } node_init(&ws->node, N_WORKSPACE, ws); - ws->name = name ? strdup(name) : NULL; + ws->name = strdup(name); ws->prev_split_layout = L_NONE; ws->layout = output_get_default_layout(output); ws->floating = create_list(); @@ -114,7 +116,7 @@ struct sway_workspace *workspace_create(struct sway_output *output, output_sort_workspaces(output); ipc_event_workspace(NULL, ws, "init"); - wl_signal_emit(&root->events.new_node, &ws->node); + wl_signal_emit_mutable(&root->events.new_node, &ws->node); return ws; } @@ -142,7 +144,7 @@ void workspace_destroy(struct sway_workspace *workspace) { void workspace_begin_destroy(struct sway_workspace *workspace) { sway_log(SWAY_DEBUG, "Destroying workspace '%s'", workspace->name); ipc_event_workspace(NULL, workspace, "empty"); // intentional - wl_signal_emit(&workspace->node.events.destroy, &workspace->node); + wl_signal_emit_mutable(&workspace->node.events.destroy, &workspace->node); if (workspace->output) { workspace_detach(workspace); |