diff options
author | Drew DeVault <sir@cmpwn.com> | 2018-06-01 15:41:49 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-06-01 15:41:49 -0700 |
commit | 96446fdbf748acfdbd4c60fbc0d12e45a27199fe (patch) | |
tree | 6d46cc61a1e7c74efe36565796ccbf8b47e7e4a7 /sway/desktop | |
parent | fd885d5779ef9aa408fa856a66fa7343ce01fa19 (diff) | |
parent | 70c2c504452eccbe5a74bc014e99b5b03db14124 (diff) | |
download | sway-96446fdbf748acfdbd4c60fbc0d12e45a27199fe.tar.xz |
Merge pull request #2027 from RyanDwyer/implement-floating
Implement floating
Diffstat (limited to 'sway/desktop')
-rw-r--r-- | sway/desktop/output.c | 112 | ||||
-rw-r--r-- | sway/desktop/xdg_shell.c | 35 | ||||
-rw-r--r-- | sway/desktop/xdg_shell_v6.c | 35 | ||||
-rw-r--r-- | sway/desktop/xwayland.c | 52 |
4 files changed, 169 insertions, 65 deletions
diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 0deb86ca..4047fa3f 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -65,6 +65,13 @@ struct root_geometry { float rotation; }; +struct render_data { + struct root_geometry root_geo; + struct sway_output *output; + pixman_region32_t *damage; + float alpha; +}; + static bool get_surface_box(struct root_geometry *geo, struct sway_output *output, struct wlr_surface *surface, int sx, int sy, struct wlr_box *surface_box) { @@ -116,8 +123,9 @@ static void surface_for_each_surface(struct wlr_surface *surface, static void output_view_for_each_surface(struct sway_view *view, struct root_geometry *geo, wlr_surface_iterator_func_t iterator, void *user_data) { - geo->x = view->x; - geo->y = view->y; + struct render_data *data = user_data; + geo->x = view->x - data->output->swayc->x; + geo->y = view->y - data->output->swayc->y; geo->width = view->surface->current->width; geo->height = view->surface->current->height; geo->rotation = 0; // TODO @@ -160,13 +168,6 @@ static void scale_box(struct wlr_box *box, float scale) { box->height *= scale; } -struct render_data { - struct root_geometry root_geo; - struct sway_output *output; - pixman_region32_t *damage; - float alpha; -}; - static void scissor_output(struct wlr_output *wlr_output, pixman_box32_t *rect) { struct wlr_renderer *renderer = wlr_backend_get_renderer(wlr_output->backend); @@ -275,7 +276,10 @@ static void render_rect(struct wlr_output *wlr_output, struct wlr_renderer *renderer = wlr_backend_get_renderer(wlr_output->backend); - struct wlr_box box = *_box; + struct wlr_box box; + memcpy(&box, _box, sizeof(struct wlr_box)); + box.x -= wlr_output->lx * wlr_output->scale; + box.y -= wlr_output->ly * wlr_output->scale; pixman_region32_t damage; pixman_region32_init(&damage); @@ -449,9 +453,10 @@ static void render_titlebar(struct sway_output *output, struct wlr_box texture_box; wlr_texture_get_size(marks_texture, &texture_box.width, &texture_box.height); - texture_box.x = - (x + width - TITLEBAR_H_PADDING) * output_scale - texture_box.width; - texture_box.y = (y + TITLEBAR_V_PADDING) * output_scale; + texture_box.x = (x - output->swayc->x + width - TITLEBAR_H_PADDING) + * output_scale - texture_box.width; + texture_box.y = (y - output->swayc->y + TITLEBAR_V_PADDING) + * output_scale; float matrix[9]; wlr_matrix_project_box(matrix, &texture_box, @@ -472,8 +477,10 @@ static void render_titlebar(struct sway_output *output, struct wlr_box texture_box; wlr_texture_get_size(title_texture, &texture_box.width, &texture_box.height); - texture_box.x = (x + TITLEBAR_H_PADDING) * output_scale; - texture_box.y = (y + TITLEBAR_V_PADDING) * output_scale; + texture_box.x = (x - output->swayc->x + TITLEBAR_H_PADDING) + * output_scale; + texture_box.y = (y - output->swayc->y + TITLEBAR_V_PADDING) + * output_scale; float matrix[9]; wlr_matrix_project_box(matrix, &texture_box, @@ -755,8 +762,58 @@ static void render_container(struct sway_output *output, render_container_tabbed(output, damage, con, parent_focused); break; case L_FLOATING: - // TODO - break; + sway_assert(false, "Didn't expect to see floating here"); + } +} + +static void render_floating_container(struct sway_output *soutput, + pixman_region32_t *damage, struct sway_container *con) { + if (con->type == C_VIEW) { + struct sway_view *view = con->sway_view; + struct sway_seat *seat = input_manager_current_seat(input_manager); + struct sway_container *focus = seat_get_focus(seat); + struct border_colors *colors; + struct wlr_texture *title_texture; + struct wlr_texture *marks_texture; + + if (focus == con) { + colors = &config->border_colors.focused; + title_texture = con->title_focused; + marks_texture = view->marks_focused; + } else { + colors = &config->border_colors.unfocused; + title_texture = con->title_unfocused; + marks_texture = view->marks_unfocused; + } + + if (con->sway_view->border == B_NORMAL) { + render_titlebar(soutput, damage, con, con->x, con->y, con->width, + colors, title_texture, marks_texture); + } else { + render_top_border(soutput, damage, con, colors); + } + render_view(soutput, damage, con, colors); + } else { + render_container(soutput, damage, con, false); + } +} + +static void render_floating(struct sway_output *soutput, + pixman_region32_t *damage) { + for (int i = 0; i < root_container.children->length; ++i) { + struct sway_container *output = root_container.children->items[i]; + for (int j = 0; j < output->children->length; ++j) { + struct sway_container *workspace = output->children->items[j]; + struct sway_workspace *ws = workspace->sway_workspace; + if (!workspace_is_visible(workspace)) { + continue; + } + for (int k = 0; k < ws->floating->children->length; ++k) { + struct sway_container *floater = + ws->floating->children->items[k]; + render_floating_container(soutput, damage, floater); + } + } } } @@ -794,8 +851,6 @@ static void render_output(struct sway_output *output, struct timespec *when, goto renderer_end; } - //wlr_renderer_clear(renderer, (float[]){1, 1, 0, 1}); - struct sway_container *workspace = output_get_active_workspace(output); if (workspace->sway_workspace->fullscreen) { @@ -834,6 +889,7 @@ static void render_output(struct sway_output *output, struct timespec *when, struct sway_seat *seat = input_manager_current_seat(input_manager); struct sway_container *focus = seat_get_focus(seat); render_container(output, damage, workspace, focus == workspace); + render_floating(output, damage); render_unmanaged(output, damage, &root_container.sway_root->xwayland_unmanaged); @@ -915,6 +971,7 @@ static void send_frame_done(struct sway_output *output, struct timespec *when) { struct sway_container *workspace = output_get_active_workspace(output); send_frame_done_container(&data, workspace); + send_frame_done_container(&data, workspace->sway_workspace->floating); send_frame_done_unmanaged(&data, &root_container.sway_root->xwayland_unmanaged); @@ -1052,21 +1109,14 @@ static void output_damage_whole_container_iterator(struct sway_container *con, void output_damage_whole_container(struct sway_output *output, struct sway_container *con) { - float scale = output->wlr_output->scale; struct wlr_box box = { - .x = con->x * scale, - .y = con->y * scale, - .width = con->width * scale, - .height = con->height * scale, + .x = con->x - output->wlr_output->lx, + .y = con->y - output->wlr_output->ly, + .width = con->width, + .height = con->height, }; + scale_box(&box, output->wlr_output->scale); wlr_output_damage_add_box(output->damage, &box); - - if (con->type == C_VIEW) { - output_damage_whole_container_iterator(con, output); - } else { - container_descendants(con, C_VIEW, - output_damage_whole_container_iterator, output); - } } static void damage_handle_destroy(struct wl_listener *listener, void *data) { diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index b2b95fa0..d2b8822c 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -87,7 +87,7 @@ static const char *get_string_prop(struct sway_view *view, enum sway_view_prop p } } -static void configure(struct sway_view *view, double ox, double oy, int width, +static void configure(struct sway_view *view, double lx, double ly, int width, int height) { struct sway_xdg_shell_view *xdg_shell_view = xdg_shell_view_from_view(view); @@ -98,6 +98,7 @@ static void configure(struct sway_view *view, double ox, double oy, int width, xdg_shell_view->pending_width = width; xdg_shell_view->pending_height = height; wlr_xdg_toplevel_set_size(view->wlr_xdg_surface, width, height); + view_update_position(view, lx, ly); } static void set_activated(struct sway_view *view, bool activated) { @@ -118,6 +119,14 @@ static void set_fullscreen(struct sway_view *view, bool fullscreen) { wlr_xdg_toplevel_set_fullscreen(surface, fullscreen); } +static bool wants_floating(struct sway_view *view) { + struct wlr_xdg_toplevel_state *state = + &view->wlr_xdg_surface->toplevel->current; + return state->min_width != 0 && state->min_height != 0 + && state->min_width == state->max_width + && state->min_height == state->max_height; +} + static void for_each_surface(struct sway_view *view, wlr_surface_iterator_func_t iterator, void *user_data) { if (xdg_shell_view_from_view(view) == NULL) { @@ -155,6 +164,7 @@ static const struct sway_view_impl view_impl = { .configure = configure, .set_activated = set_activated, .set_fullscreen = set_fullscreen, + .wants_floating = wants_floating, .for_each_surface = for_each_surface, .close = _close, .destroy = destroy, @@ -164,11 +174,18 @@ static void handle_commit(struct wl_listener *listener, void *data) { struct sway_xdg_shell_view *xdg_shell_view = wl_container_of(listener, xdg_shell_view, commit); struct sway_view *view = &xdg_shell_view->view; - // NOTE: We intentionally discard the view's desired width here - // TODO: Store this for restoration when moving to floating plane - // TODO: Let floating views do whatever - view_update_size(view, xdg_shell_view->pending_width, - xdg_shell_view->pending_height); + if (view->swayc && container_is_floating(view->swayc)) { + int width = view->wlr_xdg_surface->geometry.width; + int height = view->wlr_xdg_surface->geometry.height; + if (!width && !height) { + width = view->wlr_xdg_surface->surface->current->width; + height = view->wlr_xdg_surface->surface->current->height; + } + view_update_size(view, width, height); + } else { + view_update_size(view, xdg_shell_view->pending_width, + xdg_shell_view->pending_height); + } view_update_title(view, false); view_damage_from(view); } @@ -196,6 +213,12 @@ static void handle_map(struct wl_listener *listener, void *data) { struct sway_view *view = &xdg_shell_view->view; struct wlr_xdg_surface *xdg_surface = view->wlr_xdg_surface; + view->natural_width = view->wlr_xdg_surface->geometry.width; + view->natural_height = view->wlr_xdg_surface->geometry.height; + if (!view->natural_width && !view->natural_height) { + view->natural_width = view->wlr_xdg_surface->surface->current->width; + view->natural_height = view->wlr_xdg_surface->surface->current->height; + } view_map(view, view->wlr_xdg_surface->surface); xdg_shell_view->commit.notify = handle_commit; diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index d098c797..6ffe334a 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -86,7 +86,7 @@ static const char *get_string_prop(struct sway_view *view, enum sway_view_prop p } } -static void configure(struct sway_view *view, double ox, double oy, int width, +static void configure(struct sway_view *view, double lx, double ly, int width, int height) { struct sway_xdg_shell_v6_view *xdg_shell_v6_view = xdg_shell_v6_view_from_view(view); @@ -97,6 +97,7 @@ static void configure(struct sway_view *view, double ox, double oy, int width, xdg_shell_v6_view->pending_width = width; xdg_shell_v6_view->pending_height = height; wlr_xdg_toplevel_v6_set_size(view->wlr_xdg_surface_v6, width, height); + view_update_position(view, lx, ly); } static void set_activated(struct sway_view *view, bool activated) { @@ -117,6 +118,14 @@ static void set_fullscreen(struct sway_view *view, bool fullscreen) { wlr_xdg_toplevel_v6_set_fullscreen(surface, fullscreen); } +static bool wants_floating(struct sway_view *view) { + struct wlr_xdg_toplevel_v6_state *state = + &view->wlr_xdg_surface_v6->toplevel->current; + return state->min_width != 0 && state->min_height != 0 + && state->min_width == state->max_width + && state->min_height == state->max_height; +} + static void for_each_surface(struct sway_view *view, wlr_surface_iterator_func_t iterator, void *user_data) { if (xdg_shell_v6_view_from_view(view) == NULL) { @@ -154,6 +163,7 @@ static const struct sway_view_impl view_impl = { .configure = configure, .set_activated = set_activated, .set_fullscreen = set_fullscreen, + .wants_floating = wants_floating, .for_each_surface = for_each_surface, .close = _close, .destroy = destroy, @@ -163,11 +173,18 @@ static void handle_commit(struct wl_listener *listener, void *data) { struct sway_xdg_shell_v6_view *xdg_shell_v6_view = wl_container_of(listener, xdg_shell_v6_view, commit); struct sway_view *view = &xdg_shell_v6_view->view; - // NOTE: We intentionally discard the view's desired width here - // TODO: Store this for restoration when moving to floating plane - // TODO: Let floating views do whatever - view_update_size(view, xdg_shell_v6_view->pending_width, - xdg_shell_v6_view->pending_height); + if (view->swayc && container_is_floating(view->swayc)) { + int width = view->wlr_xdg_surface_v6->geometry.width; + int height = view->wlr_xdg_surface_v6->geometry.height; + if (!width && !height) { + width = view->wlr_xdg_surface_v6->surface->current->width; + height = view->wlr_xdg_surface_v6->surface->current->height; + } + view_update_size(view, width, height); + } else { + view_update_size(view, xdg_shell_v6_view->pending_width, + xdg_shell_v6_view->pending_height); + } view_update_title(view, false); view_damage_from(view); } @@ -195,6 +212,12 @@ static void handle_map(struct wl_listener *listener, void *data) { struct sway_view *view = &xdg_shell_v6_view->view; struct wlr_xdg_surface_v6 *xdg_surface = view->wlr_xdg_surface_v6; + view->natural_width = view->wlr_xdg_surface_v6->geometry.width; + view->natural_height = view->wlr_xdg_surface_v6->geometry.height; + if (!view->natural_width && !view->natural_height) { + view->natural_width = view->wlr_xdg_surface_v6->surface->current->width; + view->natural_height = view->wlr_xdg_surface_v6->surface->current->height; + } view_map(view, view->wlr_xdg_surface_v6->surface); xdg_shell_v6_view->commit.notify = handle_commit; diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 6a99a66a..75bfb7b2 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -152,7 +152,7 @@ static uint32_t get_int_prop(struct sway_view *view, enum sway_view_prop prop) { } } -static void configure(struct sway_view *view, double ox, double oy, int width, +static void configure(struct sway_view *view, double lx, double ly, int width, int height) { struct sway_xwayland_view *xwayland_view = xwayland_view_from_view(view); if (xwayland_view == NULL) { @@ -160,25 +160,11 @@ static void configure(struct sway_view *view, double ox, double oy, int width, } struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; - struct sway_container *output = container_parent(view->swayc, C_OUTPUT); - if (!sway_assert(output, "view must be within tree to set position")) { - return; - } - struct sway_container *root = container_parent(output, C_ROOT); - if (!sway_assert(root, "output must be within tree to set position")) { - return; - } - struct wlr_output_layout *layout = root->sway_root->output_layout; - struct wlr_output_layout_output *loutput = - wlr_output_layout_get(layout, output->sway_output->wlr_output); - if (!sway_assert(loutput, "output must be within layout to set position")) { - return; - } - + xwayland_view->pending_lx = lx; + xwayland_view->pending_ly = ly; xwayland_view->pending_width = width; xwayland_view->pending_height = height; - wlr_xwayland_surface_configure(xsurface, ox + loutput->x, oy + loutput->y, - width, height); + wlr_xwayland_surface_configure(xsurface, lx, ly, width, height); } static void set_activated(struct sway_view *view, bool activated) { @@ -197,6 +183,19 @@ static void set_fullscreen(struct sway_view *view, bool fullscreen) { wlr_xwayland_surface_set_fullscreen(surface, fullscreen); } +static bool wants_floating(struct sway_view *view) { + // TODO: + // We want to return true if the window type contains any of these: + // NET_WM_WINDOW_TYPE_DIALOG + // NET_WM_WINDOW_TYPE_UTILITY + // NET_WM_WINDOW_TYPE_TOOLBAR + // NET_WM_WINDOW_TYPE_SPLASH + // + // We also want to return true if the NET_WM_STATE is MODAL. + // wlroots doesn't appear to provide all this information at the moment. + return false; +} + static void _close(struct sway_view *view) { if (xwayland_view_from_view(view) == NULL) { return; @@ -226,6 +225,7 @@ static const struct sway_view_impl view_impl = { .configure = configure, .set_activated = set_activated, .set_fullscreen = set_fullscreen, + .wants_floating = wants_floating, .close = _close, .destroy = destroy, }; @@ -234,10 +234,15 @@ static void handle_commit(struct wl_listener *listener, void *data) { struct sway_xwayland_view *xwayland_view = wl_container_of(listener, xwayland_view, commit); struct sway_view *view = &xwayland_view->view; - // NOTE: We intentionally discard the view's desired width here - // TODO: Let floating views do whatever - view_update_size(view, xwayland_view->pending_width, - xwayland_view->pending_height); + struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; + if (view->swayc && container_is_floating(view->swayc)) { + view_update_size(view, xsurface->width, xsurface->height); + } else { + view_update_size(view, xwayland_view->pending_width, + xwayland_view->pending_height); + } + view_update_position(view, + xwayland_view->pending_lx, xwayland_view->pending_ly); view_damage_from(view); } @@ -254,6 +259,9 @@ static void handle_map(struct wl_listener *listener, void *data) { struct wlr_xwayland_surface *xsurface = data; struct sway_view *view = &xwayland_view->view; + view->natural_width = xsurface->width; + view->natural_height = xsurface->height; + // Wire up the commit listener here, because xwayland map/unmap can change // the underlying wlr_surface wl_signal_add(&xsurface->surface->events.commit, &xwayland_view->commit); |