From 7ead2e85a7816a65e87bb7fded7414f571d56619 Mon Sep 17 00:00:00 2001 From: somdoron Date: Mon, 23 Jul 2018 19:29:32 +0300 Subject: fix crash on new output while swaylock is running --- sway/desktop/render.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sway/desktop/render.c') diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 4c85e516..7da54594 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -838,7 +838,7 @@ void output_render(struct sway_output *output, struct timespec *when, struct sway_view *fullscreen_view = workspace->current.ws_fullscreen; struct sway_seat *seat = input_manager_current_seat(input_manager); - if (output_has_opaque_lockscreen(output, seat)) { + if (output_has_opaque_lockscreen(output, seat) && seat->focused_layer) { struct wlr_layer_surface *wlr_layer_surface = seat->focused_layer; struct sway_layer_surface *sway_layer_surface = layer_from_wlr_layer_surface(seat->focused_layer); -- cgit v1.2.3 From 24ad1c3983192b47345566fd876e26b45160d68e Mon Sep 17 00:00:00 2001 From: Pascal Pascher Date: Tue, 24 Jul 2018 22:16:06 +0200 Subject: Added meson option "enable_xwayland" (default: true) to enable/disable xwayland support --- include/sway/criteria.h | 2 ++ include/sway/server.h | 9 ++++++--- include/sway/tree/layout.h | 3 ++- include/sway/tree/view.h | 15 ++++++++++++--- include/sway/xwayland.h | 2 ++ meson.build | 6 ++++++ meson_options.txt | 1 + sway/commands/swap.c | 6 ++++++ sway/criteria.c | 12 ++++++++++++ sway/desktop/output.c | 15 +++++++++------ sway/desktop/render.c | 10 ++++++---- sway/desktop/xwayland.c | 2 ++ sway/input/cursor.c | 3 ++- sway/input/seat.c | 2 ++ sway/server.c | 4 ++++ sway/tree/container.c | 2 ++ sway/tree/layout.c | 2 ++ sway/tree/view.c | 16 ++++++++++++++-- 18 files changed, 92 insertions(+), 20 deletions(-) (limited to 'sway/desktop/render.c') diff --git a/include/sway/criteria.h b/include/sway/criteria.h index 6a8337c5..5b5c0f58 100644 --- a/include/sway/criteria.h +++ b/include/sway/criteria.h @@ -25,7 +25,9 @@ struct criteria { pcre *instance; pcre *con_mark; uint32_t con_id; // internal ID + #ifdef HAVE_XWAYLAND uint32_t id; // X11 window ID + #endif pcre *window_role; uint32_t window_type; bool floating; diff --git a/include/sway/server.h b/include/sway/server.h index 70bde6d4..fb22125f 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -12,7 +12,9 @@ #include // TODO WLR: make Xwayland optional #include "list.h" +#ifdef HAVE_XWAYLAND #include "sway/xwayland.h" +#endif struct sway_server { struct wl_display *wl_display; @@ -39,11 +41,11 @@ struct sway_server { struct wlr_xdg_shell *xdg_shell; struct wl_listener xdg_shell_surface; - + #ifdef HAVE_XWAYLAND struct sway_xwayland xwayland; struct wl_listener xwayland_surface; struct wl_listener xwayland_ready; - + #endif bool debug_txn_timings; list_t *transactions; @@ -65,6 +67,7 @@ void handle_idle_inhibitor_v1(struct wl_listener *listener, void *data); void handle_layer_shell_surface(struct wl_listener *listener, void *data); void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data); void handle_xdg_shell_surface(struct wl_listener *listener, void *data); +#ifdef HAVE_XWAYLAND void handle_xwayland_surface(struct wl_listener *listener, void *data); - +#endif #endif diff --git a/include/sway/tree/layout.h b/include/sway/tree/layout.h index 7d7da2d7..da74e205 100644 --- a/include/sway/tree/layout.h +++ b/include/sway/tree/layout.h @@ -27,8 +27,9 @@ struct sway_root { struct wlr_output_layout *output_layout; struct wl_listener output_layout_change; - + #ifdef HAVE_XWAYLAND struct wl_list xwayland_unmanaged; // sway_xwayland_unmanaged::link + #endif struct wl_list drag_icons; // sway_drag_icon::link struct wlr_texture *debug_tree; diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 3bdfe252..af12cf88 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -3,7 +3,9 @@ #include #include #include +#ifdef HAVE_XWAYLAND #include +#endif #include "sway/input/input-manager.h" #include "sway/input/seat.h" @@ -12,7 +14,9 @@ struct sway_container; enum sway_view_type { SWAY_VIEW_XDG_SHELL_V6, SWAY_VIEW_XDG_SHELL, + #ifdef HAVE_XWAYLAND SWAY_VIEW_XWAYLAND, + #endif }; enum sway_view_prop { @@ -22,7 +26,9 @@ enum sway_view_prop { VIEW_PROP_INSTANCE, VIEW_PROP_WINDOW_TYPE, VIEW_PROP_WINDOW_ROLE, + #ifdef HAVE_XWAYLAND VIEW_PROP_X11_WINDOW_ID, + #endif }; struct sway_view_impl { @@ -90,7 +96,9 @@ struct sway_view { union { struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6; struct wlr_xdg_surface *wlr_xdg_surface; + #ifdef HAVE_XWAYLAND struct wlr_xwayland_surface *wlr_xwayland_surface; + #endif struct wlr_wl_shell_surface *wlr_wl_shell_surface; }; @@ -133,7 +141,7 @@ struct sway_xdg_shell_view { struct wl_listener unmap; struct wl_listener destroy; }; - +#ifdef HAVE_XWAYLAND struct sway_xwayland_view { struct sway_view view; @@ -165,7 +173,7 @@ struct sway_xwayland_unmanaged { struct wl_listener unmap; struct wl_listener destroy; }; - +#endif struct sway_view_child; struct sway_view_child_impl { @@ -281,9 +289,10 @@ struct sway_view *view_from_wlr_xdg_surface( struct wlr_xdg_surface *xdg_surface); struct sway_view *view_from_wlr_xdg_surface_v6( struct wlr_xdg_surface_v6 *xdg_surface_v6); +#ifdef HAVE_XWAYLAND struct sway_view *view_from_wlr_xwayland_surface( struct wlr_xwayland_surface *xsurface); - +#endif struct sway_view *view_from_wlr_surface(struct wlr_surface *surface); /** diff --git a/include/sway/xwayland.h b/include/sway/xwayland.h index 78d1053b..e6572ae9 100644 --- a/include/sway/xwayland.h +++ b/include/sway/xwayland.h @@ -1,3 +1,4 @@ +#ifdef HAVE_XWAYLAND #ifndef SWAY_XWAYLAND_H #define SWAY_XWAYLAND_H @@ -23,3 +24,4 @@ struct sway_xwayland { void handle_xwayland_ready(struct wl_listener *listener, void *data); #endif +#endif diff --git a/meson.build b/meson.build index 1d40581a..a2def755 100644 --- a/meson.build +++ b/meson.build @@ -48,6 +48,12 @@ git = find_program('git', required: false) conf_data = configuration_data() +if get_option('enable-xwayland') + conf_data.set('HAVE_XWAYLAND', true) +else + conf_data.set('HAVE_XWAYLAND', false) +endif + if gdk_pixbuf.found() conf_data.set('HAVE_GDK_PIXBUF', true) endif diff --git a/meson_options.txt b/meson_options.txt index 541ccf13..1897cba6 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -1,3 +1,4 @@ option('sway_version', type : 'string', description: 'The version string reported in `sway --version`.') option('default_wallpaper', type: 'boolean', value: true, description: 'Install the default wallpaper.') option('zsh_completions', type: 'boolean', value: true, description: 'Install zsh shell completions.') +option('enable-xwayland', type: 'boolean', value: false, description: 'Enable support X11 applications') diff --git a/sway/commands/swap.c b/sway/commands/swap.c index 2fc88308..3563cdd9 100644 --- a/sway/commands/swap.c +++ b/sway/commands/swap.c @@ -14,10 +14,14 @@ static bool test_con_id(struct sway_container *container, void *con_id) { } static bool test_id(struct sway_container *container, void *id) { + #ifdef HAVE_XWAYLAND xcb_window_t *wid = id; return (container->type == C_VIEW && container->sway_view->type == SWAY_VIEW_XWAYLAND && container->sway_view->wlr_xwayland_surface->window_id == *wid); + #else + return false; + #endif } static bool test_mark(struct sway_container *container, void *mark) { @@ -43,8 +47,10 @@ struct cmd_results *cmd_swap(int argc, char **argv) { char *value = join_args(argv + 3, argc - 3); if (strcasecmp(argv[2], "id") == 0) { + #ifdef HAVE_XWAYLAND xcb_window_t id = strtol(value, NULL, 0); other = container_find(&root_container, test_id, (void *)&id); + #endif } else if (strcasecmp(argv[2], "con_id") == 0) { size_t con_id = atoi(value); other = container_find(&root_container, test_con_id, (void *)con_id); diff --git a/sway/criteria.c b/sway/criteria.c index c2e9c07e..b2c6edf9 100644 --- a/sway/criteria.c +++ b/sway/criteria.c @@ -19,7 +19,9 @@ bool criteria_is_empty(struct criteria *criteria) { && !criteria->instance && !criteria->con_mark && !criteria->con_id + #ifdef HAVE_XWAYLAND && !criteria->id + #endif && !criteria->window_role && !criteria->window_type && !criteria->floating @@ -127,12 +129,14 @@ static bool criteria_matches_view(struct criteria *criteria, } } + #ifdef HAVE_XWAYLAND if (criteria->id) { // X11 window ID uint32_t x11_window_id = view_get_x11_window_id(view); if (!x11_window_id || x11_window_id != criteria->id) { return false; } } + #endif if (criteria->window_role) { // TODO @@ -265,7 +269,9 @@ enum criteria_token { T_CON_ID, T_CON_MARK, T_FLOATING, + #ifdef HAVE_XWAYLAND T_ID, + #endif T_INSTANCE, T_SHELL, T_TILING, @@ -287,8 +293,10 @@ static enum criteria_token token_from_name(char *name) { return T_CON_ID; } else if (strcmp(name, "con_mark") == 0) { return T_CON_MARK; + #ifdef HAVE_XWAYLAND } else if (strcmp(name, "id") == 0) { return T_ID; + #endif } else if (strcmp(name, "instance") == 0) { return T_INSTANCE; } else if (strcmp(name, "shell") == 0) { @@ -355,7 +363,9 @@ static char *get_focused_prop(enum criteria_token token) { case T_CON_ID: // These do not support __focused__ case T_CON_MARK: case T_FLOATING: + #ifdef HAVE_XWAYLAND case T_ID: + #endif case T_TILING: case T_URGENT: case T_WINDOW_TYPE: @@ -426,12 +436,14 @@ static bool parse_token(struct criteria *criteria, char *name, char *value) { case T_WINDOW_TYPE: // TODO: This is a string but will be stored as an enum or integer break; + #ifdef HAVE_XWAYLAND case T_ID: criteria->id = strtoul(effective_value, &endptr, 10); if (*endptr != 0) { error = strdup("The value for 'id' should be numeric"); } break; + #endif case T_FLOATING: criteria->floating = true; break; diff --git a/sway/desktop/output.c b/sway/desktop/output.c index a206ac6b..7cca23bd 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -128,7 +128,7 @@ void output_layer_for_each_surface(struct wl_list *layer_surfaces, user_data); } } - +#ifdef HAVE_XWAYLAND void output_unmanaged_for_each_surface(struct wl_list *unmanaged, struct sway_output *output, struct root_geometry *geo, wlr_surface_iterator_func_t iterator, void *user_data) { @@ -143,7 +143,7 @@ void output_unmanaged_for_each_surface(struct wl_list *unmanaged, iterator, user_data); } } - +#endif void output_drag_icons_for_each_surface(struct wl_list *drag_icons, struct sway_output *output, struct root_geometry *geo, wlr_surface_iterator_func_t iterator, void *user_data) { @@ -244,13 +244,13 @@ static void send_frame_done_layer(struct send_frame_done_data *data, output_layer_for_each_surface(layer_surfaces, &data->root_geo, send_frame_done_iterator, data); } - +#ifdef HAVE_XWAYLAND static void send_frame_done_unmanaged(struct send_frame_done_data *data, struct wl_list *unmanaged) { output_unmanaged_for_each_surface(unmanaged, data->output, &data->root_geo, send_frame_done_iterator, data); } - +#endif static void send_frame_done_drag_icons(struct send_frame_done_data *data, struct wl_list *drag_icons) { output_drag_icons_for_each_surface(drag_icons, data->output, &data->root_geo, @@ -291,11 +291,12 @@ static void send_frame_done(struct sway_output *output, struct timespec *when) { if (workspace->current.ws_fullscreen) { send_frame_done_container_iterator( workspace->current.ws_fullscreen->swayc, &data); - + #ifdef HAVE_XWAYLAND if (workspace->current.ws_fullscreen->type == SWAY_VIEW_XWAYLAND) { send_frame_done_unmanaged(&data, &root_container.sway_root->xwayland_unmanaged); } + #endif } else { send_frame_done_layer(&data, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]); @@ -304,9 +305,11 @@ static void send_frame_done(struct sway_output *output, struct timespec *when) { send_frame_done_container(&data, workspace); send_frame_done_container(&data, workspace->sway_workspace->floating); - + + #ifdef HAVE_XWAYLAND send_frame_done_unmanaged(&data, &root_container.sway_root->xwayland_unmanaged); + #endif send_frame_done_layer(&data, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); } diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 7da54594..46bfec6b 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -132,7 +132,7 @@ static void render_layer(struct sway_output *output, output_layer_for_each_surface(layer_surfaces, &data.root_geo, render_surface_iterator, &data); } - +#ifdef HAVE_XWAYLAND static void render_unmanaged(struct sway_output *output, pixman_region32_t *damage, struct wl_list *unmanaged) { struct render_data data = { @@ -143,7 +143,7 @@ static void render_unmanaged(struct sway_output *output, output_unmanaged_for_each_surface(unmanaged, output, &data.root_geo, render_surface_iterator, &data); } - +#endif static void render_drag_icons(struct sway_output *output, pixman_region32_t *damage, struct wl_list *drag_icons) { struct render_data data = { @@ -866,11 +866,12 @@ void output_render(struct sway_output *output, struct timespec *when, } else { render_view_surfaces(fullscreen_view, output, damage, 1.0f); } - + #ifdef HAVE_XWAYLAND if (fullscreen_view->type == SWAY_VIEW_XWAYLAND) { render_unmanaged(output, damage, &root_container.sway_root->xwayland_unmanaged); } + #endif } else { float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f}; @@ -888,9 +889,10 @@ void output_render(struct sway_output *output, struct timespec *when, render_container(output, damage, workspace, workspace->current.focused); render_floating(output, damage); - + #ifdef HAVE_XWAYLAND render_unmanaged(output, damage, &root_container.sway_root->xwayland_unmanaged); + #endif render_layer(output, damage, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); } diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 65d4fcd4..d940d47b 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -1,4 +1,5 @@ #define _POSIX_C_SOURCE 199309L +#ifdef HAVE_XWAYLAND #include #include #include @@ -591,3 +592,4 @@ void handle_xwayland_ready(struct wl_listener *listener, void *data) { xcb_disconnect(xcb_conn); } +#endif diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 27597640..c873a20e 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -54,6 +54,7 @@ static struct sway_container *container_at_coords( struct sway_seat *seat, double lx, double ly, struct wlr_surface **surface, double *sx, double *sy) { // check for unmanaged views first + #ifdef HAVE_XWAYLAND struct wl_list *unmanaged = &root_container.sway_root->xwayland_unmanaged; struct sway_xwayland_unmanaged *unmanaged_surface; wl_list_for_each_reverse(unmanaged_surface, unmanaged, link) { @@ -69,7 +70,7 @@ static struct sway_container *container_at_coords( return NULL; } } - + #endif // find the output the cursor is on struct wlr_output_layout *output_layout = root_container.sway_root->output_layout; diff --git a/sway/input/seat.c b/sway/input/seat.c index fc9e54b6..66d11eea 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -103,11 +103,13 @@ static void seat_send_focus(struct sway_container *con, if (con->type == C_VIEW && seat_is_input_allowed(seat, con->sway_view->surface)) { + #ifdef HAVE_XWAYLAND if (con->sway_view->type == SWAY_VIEW_XWAYLAND) { struct wlr_xwayland *xwayland = seat->input->server->xwayland.wlr_xwayland; wlr_xwayland_set_seat(xwayland, seat->wlr_seat); } + #endif struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat->wlr_seat); if (keyboard) { wlr_seat_keyboard_notify_enter(seat->wlr_seat, diff --git a/sway/server.c b/sway/server.c index 89dfbf8c..90f25dbc 100644 --- a/sway/server.c +++ b/sway/server.c @@ -25,7 +25,9 @@ #include "sway/input/input-manager.h" #include "sway/server.h" #include "sway/tree/layout.h" +#ifdef HAVE_XWAYLAND #include "sway/xwayland.h" +#endif bool server_privileged_prepare(struct sway_server *server) { wlr_log(WLR_DEBUG, "Preparing Wayland server initialization"); @@ -81,6 +83,7 @@ bool server_init(struct sway_server *server) { server->xdg_shell_surface.notify = handle_xdg_shell_surface; // TODO make xwayland optional + #ifdef HAVE_XWAYLAND server->xwayland.wlr_xwayland = wlr_xwayland_create(server->wl_display, server->compositor, true); wl_signal_add(&server->xwayland.wlr_xwayland->events.new_surface, @@ -101,6 +104,7 @@ bool server_init(struct sway_server *server) { image->width * 4, image->width, image->height, image->hotspot_x, image->hotspot_y); } + #endif // TODO: Integration with sway borders struct wlr_server_decoration_manager *deco_manager = diff --git a/sway/tree/container.c b/sway/tree/container.c index 4f743c40..0a655db5 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -527,10 +527,12 @@ static struct sway_container *container_at_view(struct sway_container *swayc, double _sx, _sy; struct wlr_surface *_surface = NULL; switch (sview->type) { + #ifdef HAVE_XWAYLAND case SWAY_VIEW_XWAYLAND: _surface = wlr_surface_surface_at(sview->surface, view_sx, view_sy, &_sx, &_sy); break; + #endif case SWAY_VIEW_XDG_SHELL_V6: _surface = wlr_xdg_surface_v6_surface_at( sview->wlr_xdg_surface_v6, diff --git a/sway/tree/layout.c b/sway/tree/layout.c index a2be0ef3..91350c3f 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -39,7 +39,9 @@ void layout_init(void) { root_container.sway_root = calloc(1, sizeof(*root_container.sway_root)); root_container.sway_root->output_layout = wlr_output_layout_create(); wl_list_init(&root_container.sway_root->outputs); + #ifdef HAVE_XWAYLAND wl_list_init(&root_container.sway_root->xwayland_unmanaged); + #endif wl_list_init(&root_container.sway_root->drag_icons); wl_signal_init(&root_container.sway_root->events.new_container); root_container.sway_root->scratchpad = create_list(); diff --git a/sway/tree/view.c b/sway/tree/view.c index a55c8a29..e99b938e 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -3,7 +3,9 @@ #include #include #include +#ifdef HAVE_XWAYLAND #include +#endif #include "list.h" #include "log.h" #include "sway/criteria.h" @@ -108,14 +110,14 @@ const char *view_get_instance(struct sway_view *view) { } return NULL; } - +#ifdef HAVE_XWAYLAND uint32_t view_get_x11_window_id(struct sway_view *view) { if (view->impl->get_int_prop) { return view->impl->get_int_prop(view, VIEW_PROP_X11_WINDOW_ID); } return 0; } - +#endif const char *view_get_window_role(struct sway_view *view) { if (view->impl->get_string_prop) { return view->impl->get_string_prop(view, VIEW_PROP_WINDOW_ROLE); @@ -136,8 +138,10 @@ const char *view_get_shell(struct sway_view *view) { return "xdg_shell_v6"; case SWAY_VIEW_XDG_SHELL: return "xdg_shell"; + #ifdef HAVE_XWAYLAND case SWAY_VIEW_XWAYLAND: return "xwayland"; + #endif } return "unknown"; } @@ -563,6 +567,7 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { } pid_t pid; + #ifdef HAVE_XWAYLAND if (view->type == SWAY_VIEW_XWAYLAND) { struct wlr_xwayland_surface *surf = wlr_xwayland_surface_from_wlr_surface(wlr_surface); @@ -572,6 +577,11 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { wl_resource_get_client(wlr_surface->resource); wl_client_get_credentials(client, &pid, NULL, NULL); } + #else + struct wl_client *client = + wl_resource_get_client(wlr_surface->resource); + wl_client_get_credentials(client, &pid, NULL, NULL); + #endif struct sway_seat *seat = input_manager_current_seat(input_manager); struct sway_container *target_sibling = @@ -825,11 +835,13 @@ struct sway_view *view_from_wlr_surface(struct wlr_surface *wlr_surface) { wlr_xdg_surface_v6_from_wlr_surface(wlr_surface); return view_from_wlr_xdg_surface_v6(xdg_surface_v6); } + #ifdef HAVE_XWAYLAND if (wlr_surface_is_xwayland_surface(wlr_surface)) { struct wlr_xwayland_surface *xsurface = wlr_xwayland_surface_from_wlr_surface(wlr_surface); return view_from_wlr_xwayland_surface(xsurface); } + #endif if (wlr_surface_is_subsurface(wlr_surface)) { struct wlr_subsurface *subsurface = wlr_subsurface_from_wlr_surface(wlr_surface); -- cgit v1.2.3 From 2bf893248a94c7f70a9557aad4a8228731041eeb Mon Sep 17 00:00:00 2001 From: Pascal Pascher Date: Tue, 24 Jul 2018 23:37:41 +0200 Subject: style fixes, exclude sway/desctop/xwayland.c when enable_xwayland: false --- include/sway/criteria.h | 4 ++-- include/sway/server.h | 4 ++-- include/sway/tree/layout.h | 4 ++-- include/sway/tree/view.h | 12 ++++++------ meson.build | 4 ++-- meson_options.txt | 2 +- sway/commands/swap.c | 12 ++++++------ sway/desktop/output.c | 10 +++++----- sway/desktop/render.c | 8 ++++---- sway/desktop/xwayland.c | 2 -- sway/input/cursor.c | 4 ++-- sway/input/seat.c | 4 ++-- sway/meson.build | 5 ++++- sway/server.c | 4 ++-- sway/tree/container.c | 4 ++-- sway/tree/layout.c | 4 ++-- sway/tree/view.c | 14 +++++++------- 17 files changed, 51 insertions(+), 50 deletions(-) (limited to 'sway/desktop/render.c') diff --git a/include/sway/criteria.h b/include/sway/criteria.h index 5b5c0f58..23efe9d4 100644 --- a/include/sway/criteria.h +++ b/include/sway/criteria.h @@ -25,9 +25,9 @@ struct criteria { pcre *instance; pcre *con_mark; uint32_t con_id; // internal ID - #ifdef HAVE_XWAYLAND +#ifdef HAVE_XWAYLAND uint32_t id; // X11 window ID - #endif +#endif pcre *window_role; uint32_t window_type; bool floating; diff --git a/include/sway/server.h b/include/sway/server.h index fb22125f..b6a6bde3 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -41,11 +41,11 @@ struct sway_server { struct wlr_xdg_shell *xdg_shell; struct wl_listener xdg_shell_surface; - #ifdef HAVE_XWAYLAND +#ifdef HAVE_XWAYLAND struct sway_xwayland xwayland; struct wl_listener xwayland_surface; struct wl_listener xwayland_ready; - #endif +#endif bool debug_txn_timings; list_t *transactions; diff --git a/include/sway/tree/layout.h b/include/sway/tree/layout.h index da74e205..580acd16 100644 --- a/include/sway/tree/layout.h +++ b/include/sway/tree/layout.h @@ -27,9 +27,9 @@ struct sway_root { struct wlr_output_layout *output_layout; struct wl_listener output_layout_change; - #ifdef HAVE_XWAYLAND +#ifdef HAVE_XWAYLAND struct wl_list xwayland_unmanaged; // sway_xwayland_unmanaged::link - #endif +#endif struct wl_list drag_icons; // sway_drag_icon::link struct wlr_texture *debug_tree; diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index af12cf88..d4416dd3 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -14,9 +14,9 @@ struct sway_container; enum sway_view_type { SWAY_VIEW_XDG_SHELL_V6, SWAY_VIEW_XDG_SHELL, - #ifdef HAVE_XWAYLAND +#ifdef HAVE_XWAYLAND SWAY_VIEW_XWAYLAND, - #endif +#endif }; enum sway_view_prop { @@ -26,9 +26,9 @@ enum sway_view_prop { VIEW_PROP_INSTANCE, VIEW_PROP_WINDOW_TYPE, VIEW_PROP_WINDOW_ROLE, - #ifdef HAVE_XWAYLAND +#ifdef HAVE_XWAYLAND VIEW_PROP_X11_WINDOW_ID, - #endif +#endif }; struct sway_view_impl { @@ -96,9 +96,9 @@ struct sway_view { union { struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6; struct wlr_xdg_surface *wlr_xdg_surface; - #ifdef HAVE_XWAYLAND +#ifdef HAVE_XWAYLAND struct wlr_xwayland_surface *wlr_xwayland_surface; - #endif +#endif struct wlr_wl_shell_surface *wlr_wl_shell_surface; }; diff --git a/meson.build b/meson.build index a2def755..06299618 100644 --- a/meson.build +++ b/meson.build @@ -49,9 +49,9 @@ git = find_program('git', required: false) conf_data = configuration_data() if get_option('enable-xwayland') - conf_data.set('HAVE_XWAYLAND', true) + conf_data.set('HAVE_XWAYLAND', true) else - conf_data.set('HAVE_XWAYLAND', false) + conf_data.set('HAVE_XWAYLAND', false) endif if gdk_pixbuf.found() diff --git a/meson_options.txt b/meson_options.txt index 1897cba6..6c7f241d 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -1,4 +1,4 @@ option('sway_version', type : 'string', description: 'The version string reported in `sway --version`.') option('default_wallpaper', type: 'boolean', value: true, description: 'Install the default wallpaper.') option('zsh_completions', type: 'boolean', value: true, description: 'Install zsh shell completions.') -option('enable-xwayland', type: 'boolean', value: false, description: 'Enable support X11 applications') +option('enable-xwayland', type: 'boolean', value: true, description: 'Enable support for X11 applications') diff --git a/sway/commands/swap.c b/sway/commands/swap.c index 3563cdd9..325adc38 100644 --- a/sway/commands/swap.c +++ b/sway/commands/swap.c @@ -14,14 +14,14 @@ static bool test_con_id(struct sway_container *container, void *con_id) { } static bool test_id(struct sway_container *container, void *id) { - #ifdef HAVE_XWAYLAND +#ifdef HAVE_XWAYLAND xcb_window_t *wid = id; return (container->type == C_VIEW && container->sway_view->type == SWAY_VIEW_XWAYLAND && container->sway_view->wlr_xwayland_surface->window_id == *wid); - #else - return false; - #endif +#else + return false; +#endif } static bool test_mark(struct sway_container *container, void *mark) { @@ -47,10 +47,10 @@ struct cmd_results *cmd_swap(int argc, char **argv) { char *value = join_args(argv + 3, argc - 3); if (strcasecmp(argv[2], "id") == 0) { - #ifdef HAVE_XWAYLAND +#ifdef HAVE_XWAYLAND xcb_window_t id = strtol(value, NULL, 0); other = container_find(&root_container, test_id, (void *)&id); - #endif +#endif } else if (strcasecmp(argv[2], "con_id") == 0) { size_t con_id = atoi(value); other = container_find(&root_container, test_con_id, (void *)con_id); diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 7cca23bd..05daad7b 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -291,12 +291,12 @@ static void send_frame_done(struct sway_output *output, struct timespec *when) { if (workspace->current.ws_fullscreen) { send_frame_done_container_iterator( workspace->current.ws_fullscreen->swayc, &data); - #ifdef HAVE_XWAYLAND +#ifdef HAVE_XWAYLAND if (workspace->current.ws_fullscreen->type == SWAY_VIEW_XWAYLAND) { send_frame_done_unmanaged(&data, &root_container.sway_root->xwayland_unmanaged); } - #endif +#endif } else { send_frame_done_layer(&data, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]); @@ -305,11 +305,11 @@ static void send_frame_done(struct sway_output *output, struct timespec *when) { send_frame_done_container(&data, workspace); send_frame_done_container(&data, workspace->sway_workspace->floating); - - #ifdef HAVE_XWAYLAND + +#ifdef HAVE_XWAYLAND send_frame_done_unmanaged(&data, &root_container.sway_root->xwayland_unmanaged); - #endif +#endif send_frame_done_layer(&data, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); } diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 46bfec6b..2e6b6649 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -866,12 +866,12 @@ void output_render(struct sway_output *output, struct timespec *when, } else { render_view_surfaces(fullscreen_view, output, damage, 1.0f); } - #ifdef HAVE_XWAYLAND +#ifdef HAVE_XWAYLAND if (fullscreen_view->type == SWAY_VIEW_XWAYLAND) { render_unmanaged(output, damage, &root_container.sway_root->xwayland_unmanaged); } - #endif +#endif } else { float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f}; @@ -889,10 +889,10 @@ void output_render(struct sway_output *output, struct timespec *when, render_container(output, damage, workspace, workspace->current.focused); render_floating(output, damage); - #ifdef HAVE_XWAYLAND +#ifdef HAVE_XWAYLAND render_unmanaged(output, damage, &root_container.sway_root->xwayland_unmanaged); - #endif +#endif render_layer(output, damage, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); } diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index d940d47b..65d4fcd4 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -1,5 +1,4 @@ #define _POSIX_C_SOURCE 199309L -#ifdef HAVE_XWAYLAND #include #include #include @@ -592,4 +591,3 @@ void handle_xwayland_ready(struct wl_listener *listener, void *data) { xcb_disconnect(xcb_conn); } -#endif diff --git a/sway/input/cursor.c b/sway/input/cursor.c index c873a20e..33eebf97 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -54,7 +54,7 @@ static struct sway_container *container_at_coords( struct sway_seat *seat, double lx, double ly, struct wlr_surface **surface, double *sx, double *sy) { // check for unmanaged views first - #ifdef HAVE_XWAYLAND +#ifdef HAVE_XWAYLAND struct wl_list *unmanaged = &root_container.sway_root->xwayland_unmanaged; struct sway_xwayland_unmanaged *unmanaged_surface; wl_list_for_each_reverse(unmanaged_surface, unmanaged, link) { @@ -70,7 +70,7 @@ static struct sway_container *container_at_coords( return NULL; } } - #endif +#endif // find the output the cursor is on struct wlr_output_layout *output_layout = root_container.sway_root->output_layout; diff --git a/sway/input/seat.c b/sway/input/seat.c index 66d11eea..6b4e5f2e 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -103,13 +103,13 @@ static void seat_send_focus(struct sway_container *con, if (con->type == C_VIEW && seat_is_input_allowed(seat, con->sway_view->surface)) { - #ifdef HAVE_XWAYLAND +#ifdef HAVE_XWAYLAND if (con->sway_view->type == SWAY_VIEW_XWAYLAND) { struct wlr_xwayland *xwayland = seat->input->server->xwayland.wlr_xwayland; wlr_xwayland_set_seat(xwayland, seat->wlr_seat); } - #endif +#endif struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat->wlr_seat); if (keyboard) { wlr_seat_keyboard_notify_enter(seat->wlr_seat, diff --git a/sway/meson.build b/sway/meson.build index 30c848e2..649a3ac2 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -18,7 +18,6 @@ sway_sources = files( 'desktop/transaction.c', 'desktop/xdg_shell_v6.c', 'desktop/xdg_shell.c', - 'desktop/xwayland.c', 'input/input-manager.c', 'input/seat.c', @@ -152,6 +151,10 @@ sway_sources = files( 'tree/output.c', ) +if get_option('enable-xwayland') + sway_sources += 'desktop/xwayland.c' +endif + sway_deps = [ cairo, gdk_pixbuf, diff --git a/sway/server.c b/sway/server.c index 90f25dbc..1521597f 100644 --- a/sway/server.c +++ b/sway/server.c @@ -83,7 +83,7 @@ bool server_init(struct sway_server *server) { server->xdg_shell_surface.notify = handle_xdg_shell_surface; // TODO make xwayland optional - #ifdef HAVE_XWAYLAND +#ifdef HAVE_XWAYLAND server->xwayland.wlr_xwayland = wlr_xwayland_create(server->wl_display, server->compositor, true); wl_signal_add(&server->xwayland.wlr_xwayland->events.new_surface, @@ -104,7 +104,7 @@ bool server_init(struct sway_server *server) { image->width * 4, image->width, image->height, image->hotspot_x, image->hotspot_y); } - #endif +#endif // TODO: Integration with sway borders struct wlr_server_decoration_manager *deco_manager = diff --git a/sway/tree/container.c b/sway/tree/container.c index 0a655db5..b56b4e87 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -527,12 +527,12 @@ static struct sway_container *container_at_view(struct sway_container *swayc, double _sx, _sy; struct wlr_surface *_surface = NULL; switch (sview->type) { - #ifdef HAVE_XWAYLAND +#ifdef HAVE_XWAYLAND case SWAY_VIEW_XWAYLAND: _surface = wlr_surface_surface_at(sview->surface, view_sx, view_sy, &_sx, &_sy); break; - #endif +#endif case SWAY_VIEW_XDG_SHELL_V6: _surface = wlr_xdg_surface_v6_surface_at( sview->wlr_xdg_surface_v6, diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 91350c3f..3d361ea5 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -39,9 +39,9 @@ void layout_init(void) { root_container.sway_root = calloc(1, sizeof(*root_container.sway_root)); root_container.sway_root->output_layout = wlr_output_layout_create(); wl_list_init(&root_container.sway_root->outputs); - #ifdef HAVE_XWAYLAND +#ifdef HAVE_XWAYLAND wl_list_init(&root_container.sway_root->xwayland_unmanaged); - #endif +#endif wl_list_init(&root_container.sway_root->drag_icons); wl_signal_init(&root_container.sway_root->events.new_container); root_container.sway_root->scratchpad = create_list(); diff --git a/sway/tree/view.c b/sway/tree/view.c index e99b938e..2eff80a8 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -138,10 +138,10 @@ const char *view_get_shell(struct sway_view *view) { return "xdg_shell_v6"; case SWAY_VIEW_XDG_SHELL: return "xdg_shell"; - #ifdef HAVE_XWAYLAND +#ifdef HAVE_XWAYLAND case SWAY_VIEW_XWAYLAND: return "xwayland"; - #endif +#endif } return "unknown"; } @@ -567,7 +567,7 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { } pid_t pid; - #ifdef HAVE_XWAYLAND +#ifdef HAVE_XWAYLAND if (view->type == SWAY_VIEW_XWAYLAND) { struct wlr_xwayland_surface *surf = wlr_xwayland_surface_from_wlr_surface(wlr_surface); @@ -577,11 +577,11 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { wl_resource_get_client(wlr_surface->resource); wl_client_get_credentials(client, &pid, NULL, NULL); } - #else +#else struct wl_client *client = wl_resource_get_client(wlr_surface->resource); wl_client_get_credentials(client, &pid, NULL, NULL); - #endif +#endif struct sway_seat *seat = input_manager_current_seat(input_manager); struct sway_container *target_sibling = @@ -835,13 +835,13 @@ struct sway_view *view_from_wlr_surface(struct wlr_surface *wlr_surface) { wlr_xdg_surface_v6_from_wlr_surface(wlr_surface); return view_from_wlr_xdg_surface_v6(xdg_surface_v6); } - #ifdef HAVE_XWAYLAND +#ifdef HAVE_XWAYLAND if (wlr_surface_is_xwayland_surface(wlr_surface)) { struct wlr_xwayland_surface *xsurface = wlr_xwayland_surface_from_wlr_surface(wlr_surface); return view_from_wlr_xwayland_surface(xsurface); } - #endif +#endif if (wlr_surface_is_subsurface(wlr_surface)) { struct wlr_subsurface *subsurface = wlr_subsurface_from_wlr_surface(wlr_surface); -- cgit v1.2.3 From 0e79b2114c0bd374c6b4a37fc2ee0e672b8fbb38 Mon Sep 17 00:00:00 2001 From: emersion Date: Wed, 25 Jul 2018 08:50:06 +0100 Subject: Improve rendering with a fullscreen opaque overlay surface The rendering code doesn't use the exclusive input surface at all anymore to decide to skip rendering of shell surfaces. This fixes a weird situation in which a client requests exclusive input but isn't an overlay layer surface. The renderer also renders all overlay surfaces in this situation, not just one. This simplifies the code and fixes rendering when there are more than one overlay surfaces (e.g. for a virtual keyboard to type the lockscreen password). --- include/sway/output.h | 3 +-- sway/desktop/output.c | 26 ++++++++------------------ sway/desktop/render.c | 23 ++++++++--------------- 3 files changed, 17 insertions(+), 35 deletions(-) (limited to 'sway/desktop/render.c') diff --git a/include/sway/output.h b/include/sway/output.h index b6cda83c..c225e541 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -65,8 +65,7 @@ struct sway_container *output_by_name(const char *name); void output_enable(struct sway_output *output); -bool output_has_opaque_lockscreen(struct sway_output *output, - struct sway_seat *seat); +bool output_has_opaque_overlay_layer_surface(struct sway_output *output); struct sway_container *output_get_active_workspace(struct sway_output *output); diff --git a/sway/desktop/output.c b/sway/desktop/output.c index a206ac6b..cbd6ef86 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -181,21 +181,14 @@ struct sway_container *output_get_active_workspace(struct sway_output *output) { return workspace; } -bool output_has_opaque_lockscreen(struct sway_output *output, - struct sway_seat *seat) { - if (!seat->exclusive_client) { - return false; - } - +bool output_has_opaque_overlay_layer_surface(struct sway_output *output) { struct wlr_layer_surface *wlr_layer_surface; wl_list_for_each(wlr_layer_surface, &server.layer_shell->surfaces, link) { - if (wlr_layer_surface->output != output->wlr_output) { + if (wlr_layer_surface->output != output->wlr_output || + wlr_layer_surface->layer != ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY) { continue; } struct wlr_surface *wlr_surface = wlr_layer_surface->surface; - if (wlr_surface->resource->client != seat->exclusive_client) { - continue; - } struct sway_layer_surface *sway_layer_surface = layer_from_wlr_layer_surface(wlr_layer_surface); pixman_box32_t output_box = { @@ -221,16 +214,11 @@ struct send_frame_done_data { struct root_geometry root_geo; struct sway_output *output; struct timespec *when; - struct wl_client *exclusive_client; }; static void send_frame_done_iterator(struct wlr_surface *surface, int sx, int sy, void *_data) { struct send_frame_done_data *data = _data; - if (data->exclusive_client && - data->exclusive_client != surface->resource->client) { - return; - } bool intersects = output_get_surface_box(&data->root_geo, data->output, surface, sx, sy, NULL); @@ -279,14 +267,15 @@ static void send_frame_done_container(struct send_frame_done_data *data, } static void send_frame_done(struct sway_output *output, struct timespec *when) { - struct sway_seat *seat = input_manager_current_seat(input_manager); struct send_frame_done_data data = { .output = output, .when = when, - .exclusive_client = output_has_opaque_lockscreen(output, seat) ? - seat->exclusive_client : NULL, }; + if (output_has_opaque_overlay_layer_surface(output)) { + goto send_frame_overlay; + } + struct sway_container *workspace = output_get_active_workspace(output); if (workspace->current.ws_fullscreen) { send_frame_done_container_iterator( @@ -311,6 +300,7 @@ static void send_frame_done(struct sway_output *output, struct timespec *when) { &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); } +send_frame_overlay: send_frame_done_layer(&data, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); send_frame_done_drag_icons(&data, &root_container.sway_root->drag_icons); diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 7da54594..d6c3fa8c 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -836,21 +836,12 @@ void output_render(struct sway_output *output, struct timespec *when, struct sway_container *workspace = output_get_active_workspace(output); struct sway_view *fullscreen_view = workspace->current.ws_fullscreen; - struct sway_seat *seat = input_manager_current_seat(input_manager); - - if (output_has_opaque_lockscreen(output, seat) && seat->focused_layer) { - struct wlr_layer_surface *wlr_layer_surface = seat->focused_layer; - struct sway_layer_surface *sway_layer_surface = - layer_from_wlr_layer_surface(seat->focused_layer); - struct render_data data = { - .output = output, - .damage = damage, - .alpha = 1.0f, - }; - output_surface_for_each_surface(wlr_layer_surface->surface, - sway_layer_surface->geo.x, sway_layer_surface->geo.y, - &data.root_geo, render_surface_iterator, &data); - } else if (fullscreen_view) { + + if (output_has_opaque_overlay_layer_surface(output)) { + goto render_overlay; + } + + if (fullscreen_view) { float clear_color[] = {0.0f, 0.0f, 0.0f, 1.0f}; int nrects; @@ -894,6 +885,8 @@ void output_render(struct sway_output *output, struct timespec *when, render_layer(output, damage, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); } + +render_overlay: render_layer(output, damage, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); render_drag_icons(output, damage, &root_container.sway_root->drag_icons); -- cgit v1.2.3 From f95cb9a7c17251c43b1d1058092e0a15d1fe8dd9 Mon Sep 17 00:00:00 2001 From: Pascal Pascher Date: Wed, 25 Jul 2018 13:32:20 +0200 Subject: reverted includes of "sway/config.h" and replaced with "config.h" from meson build --- include/sway/criteria.h | 1 + include/sway/tree/layout.h | 1 + include/sway/tree/view.h | 1 + sway/commands/swap.c | 2 +- sway/desktop/output.c | 1 + sway/desktop/render.c | 1 + sway/input/cursor.c | 2 +- sway/input/seat.c | 2 +- sway/server.c | 1 + sway/tree/layout.c | 2 +- sway/tree/view.c | 2 +- 11 files changed, 11 insertions(+), 5 deletions(-) (limited to 'sway/desktop/render.c') diff --git a/include/sway/criteria.h b/include/sway/criteria.h index 23efe9d4..b4ff7d49 100644 --- a/include/sway/criteria.h +++ b/include/sway/criteria.h @@ -2,6 +2,7 @@ #define _SWAY_CRITERIA_H #include +#include "config.h" #include "list.h" #include "tree/view.h" diff --git a/include/sway/tree/layout.h b/include/sway/tree/layout.h index 580acd16..a4c31bf6 100644 --- a/include/sway/tree/layout.h +++ b/include/sway/tree/layout.h @@ -3,6 +3,7 @@ #include #include #include "sway/tree/container.h" +#include "config.h" enum movement_direction { MOVE_LEFT, diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index d4416dd3..1972447b 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -3,6 +3,7 @@ #include #include #include +#include "config.h" #ifdef HAVE_XWAYLAND #include #endif diff --git a/sway/commands/swap.c b/sway/commands/swap.c index 8b8e9d79..4e3a9cce 100644 --- a/sway/commands/swap.c +++ b/sway/commands/swap.c @@ -1,6 +1,6 @@ #include #include -#include "sway/config.h" +#include "config.h" #include "sway/commands.h" #include "sway/tree/arrange.h" #include "sway/tree/layout.h" diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 05daad7b..1512408e 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -14,6 +14,7 @@ #include #include #include "log.h" +#include "config.h" #include "sway/config.h" #include "sway/input/input-manager.h" #include "sway/input/seat.h" diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 2e6b6649..3e7bd94b 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -14,6 +14,7 @@ #include #include #include "log.h" +#include "config.h" #include "sway/config.h" #include "sway/debug.h" #include "sway/input/input-manager.h" diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 3de36e1c..2468a341 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -11,7 +11,7 @@ #include #include "list.h" #include "log.h" -#include "sway/config.h" +#include "config.h" #include "sway/desktop.h" #include "sway/desktop/transaction.h" #include "sway/input/cursor.h" diff --git a/sway/input/seat.c b/sway/input/seat.c index 2d62b101..cc0b16cf 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -12,7 +12,7 @@ #include #include #include "log.h" -#include "sway/config.h" +#include "config.h" #include "sway/debug.h" #include "sway/desktop.h" #include "sway/input/cursor.h" diff --git a/sway/server.c b/sway/server.c index 1521597f..10ca9614 100644 --- a/sway/server.c +++ b/sway/server.c @@ -25,6 +25,7 @@ #include "sway/input/input-manager.h" #include "sway/server.h" #include "sway/tree/layout.h" +#include "config.h" #ifdef HAVE_XWAYLAND #include "sway/xwayland.h" #endif diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 91f6accd..2b3263f8 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -6,7 +6,7 @@ #include #include #include -#include "sway/config.h" +#include "config.h" #include "sway/debug.h" #include "sway/tree/arrange.h" #include "sway/tree/container.h" diff --git a/sway/tree/view.c b/sway/tree/view.c index 7cc15ae3..f672417e 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -3,12 +3,12 @@ #include #include #include -#include "sway/config.h" #ifdef HAVE_XWAYLAND #include #endif #include "list.h" #include "log.h" +#include "config.h" #include "sway/criteria.h" #include "sway/commands.h" #include "sway/ipc-server.h" -- cgit v1.2.3 From 27a20a488465468511de9b2307941ac1bc4db8bf Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Wed, 25 Jul 2018 20:56:23 +1000 Subject: Allow containers to be fullscreen --- include/sway/tree/container.h | 23 +++++++++++- include/sway/tree/view.h | 6 --- include/sway/tree/workspace.h | 2 +- sway/commands/fullscreen.c | 18 ++++++--- sway/commands/move.c | 2 +- sway/desktop/output.c | 14 ++++--- sway/desktop/render.c | 23 +++++++----- sway/desktop/transaction.c | 2 +- sway/desktop/xdg_shell.c | 4 +- sway/desktop/xdg_shell_v6.c | 4 +- sway/desktop/xwayland.c | 4 +- sway/input/cursor.c | 14 ++----- sway/input/seat.c | 3 +- sway/scratchpad.c | 2 +- sway/tree/arrange.c | 18 ++++++++- sway/tree/container.c | 87 +++++++++++++++++++++++++++++++++++++++++++ sway/tree/layout.c | 83 ++++++++++++++++++++++++----------------- sway/tree/view.c | 73 ++---------------------------------- 18 files changed, 226 insertions(+), 156 deletions(-) (limited to 'sway/desktop/render.c') diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 2a4be18c..c584cd92 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -60,6 +60,8 @@ struct sway_container_state { double swayc_x, swayc_y; double swayc_width, swayc_height; + bool is_fullscreen; + bool has_gaps; double current_gaps; double gaps_inner; @@ -74,7 +76,6 @@ struct sway_container_state { // View properties double view_x, view_y; double view_width, view_height; - bool is_fullscreen; enum sway_container_border border; int border_thickness; @@ -84,7 +85,7 @@ struct sway_container_state { bool border_right; // Workspace properties - struct sway_view *ws_fullscreen; + struct sway_container *ws_fullscreen; struct sway_container *ws_floating; }; @@ -124,6 +125,8 @@ struct sway_container { double saved_x, saved_y; double saved_width, saved_height; + bool is_fullscreen; + // The gaps currently applied to the container. double current_gaps; @@ -335,4 +338,20 @@ bool container_has_urgent_child(struct sway_container *container); */ void container_end_mouse_operation(struct sway_container *container); +void container_set_fullscreen(struct sway_container *container, bool enable); + +/** + * Return true if the container is fullscreen, or a child of a fullscreen split + * container. + */ +bool container_is_fullscreen_or_child(struct sway_container *container); + +/** + * Wrap the children of parent in a new container. The new container will be the + * only child of parent. + * + * The new container is returned. + */ +struct sway_container *container_wrap_children(struct sway_container *parent); + #endif diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 1972447b..7086314f 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -69,8 +69,6 @@ struct sway_view { // Used when changing a view from tiled to floating. int natural_width, natural_height; - bool is_fullscreen; - char *title_format; enum sway_container_border border; int border_thickness; @@ -251,10 +249,6 @@ void view_set_activated(struct sway_view *view, bool activated); void view_set_tiled(struct sway_view *view, bool tiled); -void view_set_fullscreen_raw(struct sway_view *view, bool fullscreen); - -void view_set_fullscreen(struct sway_view *view, bool fullscreen); - void view_close(struct sway_view *view); void view_damage_from(struct sway_view *view); diff --git a/include/sway/tree/workspace.h b/include/sway/tree/workspace.h index ff66da6b..5ae0ae3a 100644 --- a/include/sway/tree/workspace.h +++ b/include/sway/tree/workspace.h @@ -7,7 +7,7 @@ struct sway_view; struct sway_workspace { struct sway_container *swayc; - struct sway_view *fullscreen; + struct sway_container *fullscreen; struct sway_container *floating; list_t *output_priority; bool urgent; diff --git a/sway/commands/fullscreen.c b/sway/commands/fullscreen.c index b423fd23..5ad06e40 100644 --- a/sway/commands/fullscreen.c +++ b/sway/commands/fullscreen.c @@ -14,18 +14,24 @@ struct cmd_results *cmd_fullscreen(int argc, char **argv) { } struct sway_container *container = config->handler_context.current_container; - if (container->type != C_VIEW) { + if (container->type == C_WORKSPACE && container->children->length == 0) { return cmd_results_new(CMD_INVALID, "fullscreen", - "Only views can fullscreen"); + "Can't fullscreen an empty workspace"); } - struct sway_view *view = container->sway_view; - bool wants_fullscreen = !view->is_fullscreen; + if (container->type == C_WORKSPACE) { + // Wrap the workspace's children in a container so we can fullscreen it + struct sway_container *workspace = container; + container = container_wrap_children(container); + workspace->layout = L_HORIZ; + seat_set_focus(config->handler_context.seat, container); + } + bool enable = !container->is_fullscreen; if (argc) { - wants_fullscreen = parse_boolean(argv[0], view->is_fullscreen); + enable = parse_boolean(argv[0], container->is_fullscreen); } - view_set_fullscreen(view, wants_fullscreen); + container_set_fullscreen(container, enable); struct sway_container *workspace = container_parent(container, C_WORKSPACE); arrange_windows(workspace->parent); diff --git a/sway/commands/move.c b/sway/commands/move.c index 1940043d..aede3d6c 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c @@ -196,7 +196,7 @@ static struct cmd_results *move_in_direction(struct sway_container *container, "Cannot move workspaces in a direction"); } if (container_is_floating(container)) { - if (container->type == C_VIEW && container->sway_view->is_fullscreen) { + if (container->is_fullscreen) { return cmd_results_new(CMD_FAILURE, "move", "Cannot move fullscreen floating container"); } diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 1764b4e3..cecd300a 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -279,13 +279,15 @@ static void send_frame_done(struct sway_output *output, struct timespec *when) { struct sway_container *workspace = output_get_active_workspace(output); if (workspace->current.ws_fullscreen) { - send_frame_done_container_iterator( - workspace->current.ws_fullscreen->swayc, &data); -#ifdef HAVE_XWAYLAND - if (workspace->current.ws_fullscreen->type == SWAY_VIEW_XWAYLAND) { - send_frame_done_unmanaged(&data, - &root_container.sway_root->xwayland_unmanaged); + if (workspace->current.ws_fullscreen->type == C_VIEW) { + send_frame_done_container_iterator( + workspace->current.ws_fullscreen, &data); + } else { + send_frame_done_container(&data, workspace->current.ws_fullscreen); } +#ifdef HAVE_XWAYLAND + send_frame_done_unmanaged(&data, + &root_container.sway_root->xwayland_unmanaged); #endif } else { send_frame_done_layer(&data, diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 15c5b94c..3e7b1a62 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -836,13 +836,13 @@ void output_render(struct sway_output *output, struct timespec *when, } struct sway_container *workspace = output_get_active_workspace(output); - struct sway_view *fullscreen_view = workspace->current.ws_fullscreen; + struct sway_container *fullscreen_con = workspace->current.ws_fullscreen; if (output_has_opaque_overlay_layer_surface(output)) { goto render_overlay; } - if (fullscreen_view) { + if (fullscreen_con) { float clear_color[] = {0.0f, 0.0f, 0.0f, 1.0f}; int nrects; @@ -853,16 +853,21 @@ void output_render(struct sway_output *output, struct timespec *when, } // TODO: handle views smaller than the output - if (fullscreen_view->swayc->instructions->length) { - render_saved_view(fullscreen_view, output, damage, 1.0f); + if (fullscreen_con->type == C_VIEW) { + if (fullscreen_con->instructions->length) { + render_saved_view(fullscreen_con->sway_view, + output, damage, 1.0f); } else { - render_view_surfaces(fullscreen_view, output, damage, 1.0f); + render_view_surfaces(fullscreen_con->sway_view, + output, damage, 1.0f); + } + } else { + render_container(output, damage, fullscreen_con, + fullscreen_con->current.focused); } #ifdef HAVE_XWAYLAND - if (fullscreen_view->type == SWAY_VIEW_XWAYLAND) { - render_unmanaged(output, damage, - &root_container.sway_root->xwayland_unmanaged); - } + render_unmanaged(output, damage, + &root_container.sway_root->xwayland_unmanaged); #endif } else { float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f}; diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c index 2a89880a..ee7a0704 100644 --- a/sway/desktop/transaction.c +++ b/sway/desktop/transaction.c @@ -110,6 +110,7 @@ static void copy_pending_state(struct sway_container *container, state->swayc_y = container->y; state->swayc_width = container->width; state->swayc_height = container->height; + state->is_fullscreen = container->is_fullscreen; state->has_gaps = container->has_gaps; state->current_gaps = container->current_gaps; state->gaps_inner = container->gaps_inner; @@ -122,7 +123,6 @@ static void copy_pending_state(struct sway_container *container, state->view_y = view->y; state->view_width = view->width; state->view_height = view->height; - state->is_fullscreen = view->is_fullscreen; state->border = view->border; state->border_thickness = view->border_thickness; state->border_top = view->border_top; diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index f3e4fef8..e6e1527e 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -267,7 +267,7 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data) return; } - view_set_fullscreen(view, e->fullscreen); + container_set_fullscreen(view->swayc, e->fullscreen); struct sway_container *output = container_parent(view->swayc, C_OUTPUT); arrange_windows(output); @@ -338,7 +338,7 @@ static void handle_map(struct wl_listener *listener, void *data) { view_map(view, view->wlr_xdg_surface->surface); if (xdg_surface->toplevel->client_pending.fullscreen) { - view_set_fullscreen(view, true); + container_set_fullscreen(view->swayc, true); struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); arrange_windows(ws); } else { diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 46fd4769..5feee3e4 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -262,7 +262,7 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data) return; } - view_set_fullscreen(view, e->fullscreen); + container_set_fullscreen(view->swayc, e->fullscreen); struct sway_container *output = container_parent(view->swayc, C_OUTPUT); arrange_windows(output); @@ -333,7 +333,7 @@ static void handle_map(struct wl_listener *listener, void *data) { view_map(view, view->wlr_xdg_surface_v6->surface); if (xdg_surface->toplevel->client_pending.fullscreen) { - view_set_fullscreen(view, true); + container_set_fullscreen(view->swayc, true); struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); arrange_windows(ws); } else { diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 65d4fcd4..390ca580 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -357,7 +357,7 @@ static void handle_map(struct wl_listener *listener, void *data) { view_map(view, xsurface->surface); if (xsurface->fullscreen) { - view_set_fullscreen(view, true); + container_set_fullscreen(view->swayc, true); struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); arrange_windows(ws); } else { @@ -395,7 +395,7 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data) if (!xsurface->mapped) { return; } - view_set_fullscreen(view, xsurface->fullscreen); + container_set_fullscreen(view->swayc, xsurface->fullscreen); struct sway_container *output = container_parent(view->swayc, C_OUTPUT); arrange_windows(output); diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 02bd2239..cc0dbe99 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -99,14 +99,8 @@ static struct sway_container *container_at_coords( return ws; } if (ws->sway_workspace->fullscreen) { - struct wlr_surface *wlr_surface = ws->sway_workspace->fullscreen->surface; - if (wlr_surface_point_accepts_input(wlr_surface, ox, oy)) { - *sx = ox; - *sy = oy; - *surface = wlr_surface; - return ws->sway_workspace->fullscreen->swayc; - } - return NULL; + return container_at(ws->sway_workspace->fullscreen, lx, ly, + surface, sx, sy); } if ((*surface = layer_surface_at(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], @@ -438,8 +432,8 @@ static void dispatch_cursor_button_floating(struct sway_cursor *cursor, struct sway_container *cont) { struct sway_seat *seat = cursor->seat; - // Deny moving or resizing a fullscreen view - if (cont->type == C_VIEW && cont->sway_view->is_fullscreen) { + // Deny moving or resizing a fullscreen container + if (container_is_fullscreen_or_child(cont)) { seat_pointer_notify_button(seat, time_msec, button, state); return; } diff --git a/sway/input/seat.c b/sway/input/seat.c index 8698d69e..e7b6e0c5 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -632,8 +632,7 @@ void seat_set_focus_warp(struct sway_seat *seat, if (last_workspace && last_workspace == new_workspace && last_workspace->sway_workspace->fullscreen - && container && container->type == C_VIEW - && !container->sway_view->is_fullscreen) { + && container && !container_is_fullscreen_or_child(container)) { return; } diff --git a/sway/scratchpad.c b/sway/scratchpad.c index 1e836e7d..64636c77 100644 --- a/sway/scratchpad.c +++ b/sway/scratchpad.c @@ -54,7 +54,7 @@ static void scratchpad_show(struct sway_container *con) { // If the current con or any of its parents are in fullscreen mode, we // first need to disable it before showing the scratchpad con. if (ws->sway_workspace->fullscreen) { - view_set_fullscreen(ws->sway_workspace->fullscreen, false); + container_set_fullscreen(ws->sway_workspace->fullscreen, false); } // Show the container diff --git a/sway/tree/arrange.c b/sway/tree/arrange.c index 533cf71c..5452b13c 100644 --- a/sway/tree/arrange.c +++ b/sway/tree/arrange.c @@ -220,8 +220,22 @@ static void arrange_workspace(struct sway_container *workspace) { container_set_dirty(workspace); wlr_log(WLR_DEBUG, "Arranging workspace '%s' at %f, %f", workspace->name, workspace->x, workspace->y); - arrange_floating(workspace->sway_workspace->floating); - arrange_children_of(workspace); + if (workspace->sway_workspace->fullscreen) { + struct sway_container *fs = workspace->sway_workspace->fullscreen; + fs->x = workspace->parent->x; + fs->y = workspace->parent->y; + fs->width = workspace->parent->width; + fs->height = workspace->parent->height; + if (fs->type == C_VIEW) { + view_autoconfigure(fs->sway_view); + } else { + arrange_children_of(fs); + } + container_set_dirty(fs); + } else { + arrange_floating(workspace->sway_workspace->floating); + arrange_children_of(workspace); + } } static void arrange_output(struct sway_container *output) { diff --git a/sway/tree/container.c b/sway/tree/container.c index 237e1a35..6ebf2653 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -1130,3 +1130,90 @@ void container_end_mouse_operation(struct sway_container *container) { } } } + +static void set_fullscreen_iterator(struct sway_container *con, void *data) { + if (con->type != C_VIEW) { + return; + } + if (con->sway_view->impl->set_fullscreen) { + bool *enable = data; + con->sway_view->impl->set_fullscreen(con->sway_view, *enable); + } +} + +void container_set_fullscreen(struct sway_container *container, bool enable) { + if (container->is_fullscreen == enable) { + return; + } + + struct sway_container *workspace = container_parent(container, C_WORKSPACE); + if (enable && workspace->sway_workspace->fullscreen) { + container_set_fullscreen(workspace->sway_workspace->fullscreen, false); + } + + container_for_each_descendant_dfs(container, + set_fullscreen_iterator, &enable); + + container->is_fullscreen = enable; + + if (enable) { + workspace->sway_workspace->fullscreen = container; + container->saved_x = container->x; + container->saved_y = container->y; + container->saved_width = container->width; + container->saved_height = container->height; + + struct sway_seat *seat; + struct sway_container *focus, *focus_ws; + wl_list_for_each(seat, &input_manager->seats, link) { + focus = seat_get_focus(seat); + if (focus) { + focus_ws = focus; + if (focus_ws->type != C_WORKSPACE) { + focus_ws = container_parent(focus_ws, C_WORKSPACE); + } + if (focus_ws == workspace) { + seat_set_focus(seat, container); + } + } + } + } else { + workspace->sway_workspace->fullscreen = NULL; + if (container_is_floating(container)) { + container->x = container->saved_x; + container->y = container->saved_y; + container->width = container->saved_width; + container->height = container->saved_height; + } else { + container->width = container->saved_width; + container->height = container->saved_height; + } + } + + container_end_mouse_operation(container); + + ipc_event_window(container, "fullscreen_mode"); +} + +bool container_is_fullscreen_or_child(struct sway_container *container) { + do { + if (container->is_fullscreen) { + return true; + } + container = container->parent; + } while (container && container->type != C_WORKSPACE); + + return false; +} + +struct sway_container *container_wrap_children(struct sway_container *parent) { + struct sway_container *middle = container_create(C_CONTAINER); + middle->layout = parent->layout; + while (parent->children->length) { + struct sway_container *child = parent->children->items[0]; + container_remove_child(child); + container_add_child(middle, child); + } + container_add_child(parent, middle); + return middle; +} diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 2b3263f8..ab5acc16 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -66,10 +66,9 @@ static int index_child(const struct sway_container *child) { static void container_handle_fullscreen_reparent(struct sway_container *con, struct sway_container *old_parent) { - if (con->type != C_VIEW || !con->sway_view->is_fullscreen) { + if (!con->is_fullscreen) { return; } - struct sway_view *view = con->sway_view; struct sway_container *old_workspace = old_parent; if (old_workspace && old_workspace->type != C_WORKSPACE) { old_workspace = container_parent(old_workspace, C_WORKSPACE); @@ -85,19 +84,27 @@ static void container_handle_fullscreen_reparent(struct sway_container *con, // Mark the new workspace as fullscreen if (new_workspace->sway_workspace->fullscreen) { - view_set_fullscreen(new_workspace->sway_workspace->fullscreen, false); + container_set_fullscreen( + new_workspace->sway_workspace->fullscreen, false); } - new_workspace->sway_workspace->fullscreen = view; - // Resize view to new output dimensions + new_workspace->sway_workspace->fullscreen = con; + + // Resize container to new output dimensions struct sway_container *output = new_workspace->parent; - view->x = output->x; - view->y = output->y; - view->width = output->width; - view->height = output->height; con->x = output->x; con->y = output->y; con->width = output->width; con->height = output->height; + + if (con->type == C_VIEW) { + struct sway_view *view = con->sway_view; + view->x = output->x; + view->y = output->y; + view->width = output->width; + view->height = output->height; + } else { + arrange_windows(new_workspace); + } } void container_insert_child(struct sway_container *parent, @@ -146,7 +153,7 @@ void container_add_child(struct sway_container *parent, } struct sway_container *container_remove_child(struct sway_container *child) { - if (child->type == C_VIEW && child->sway_view->is_fullscreen) { + if (child->is_fullscreen) { struct sway_container *workspace = container_parent(child, C_WORKSPACE); workspace->sway_workspace->fullscreen = NULL; } @@ -229,10 +236,10 @@ void container_move_to(struct sway_container *container, if (focus_ws->type != C_WORKSPACE) { focus_ws = container_parent(focus_ws, C_WORKSPACE); } - seat_set_focus(seat, - new_workspace->sway_workspace->fullscreen->swayc); - if (focus_ws != new_workspace) { - seat_set_focus(seat, focus); + if (focus_ws == new_workspace) { + struct sway_container *new_focus = seat_get_focus_inactive(seat, + new_workspace->sway_workspace->fullscreen); + seat_set_focus(seat, new_focus); } } } @@ -375,10 +382,16 @@ void container_move(struct sway_container *container, struct sway_container *sibling = NULL; struct sway_container *current = container; struct sway_container *parent = current->parent; + struct sway_container *top = &root_container; // If moving a fullscreen view, only consider outputs - if (container->type == C_VIEW && container->sway_view->is_fullscreen) { + if (container->is_fullscreen) { current = container_parent(container, C_OUTPUT); + } else if (container_is_fullscreen_or_child(container)) { + // If we've fullscreened a split container, only allow the child to move + // around within the fullscreen parent. + struct sway_container *ws = container_parent(container, C_WORKSPACE); + top = ws->sway_workspace->fullscreen; } struct sway_container *new_parent = container_flatten(parent); @@ -388,7 +401,7 @@ void container_move(struct sway_container *container, } while (!sibling) { - if (current->type == C_ROOT) { + if (current == top) { return; } @@ -452,8 +465,9 @@ void container_move(struct sway_container *container, if ((index == parent->children->length - 1 && offs > 0) || (index == 0 && offs < 0)) { if (current->parent == container->parent) { - if (parent->layout == L_TABBED - || parent->layout == L_STACKED) { + if (!parent->is_fullscreen && + (parent->layout == L_TABBED || + parent->layout == L_STACKED)) { move_out_of_tabs_stacks(container, current, move_dir, offs); return; @@ -474,8 +488,8 @@ void container_move(struct sway_container *container, sibling = parent->children->items[index + offs]; wlr_log(WLR_DEBUG, "Selecting sibling id:%zd", sibling->id); } - } else if (parent->layout == L_TABBED - || parent->layout == L_STACKED) { + } else if (!parent->is_fullscreen && (parent->layout == L_TABBED || + parent->layout == L_STACKED)) { move_out_of_tabs_stacks(container, current, move_dir, offs); return; } else { @@ -707,16 +721,16 @@ struct sway_container *container_get_in_direction( return NULL; } - if (container->type == C_VIEW && container->sway_view->is_fullscreen) { - if (dir == MOVE_PARENT || dir == MOVE_CHILD) { + if (dir == MOVE_CHILD) { + return seat_get_focus_inactive(seat, container); + } + if (container->is_fullscreen) { + if (dir == MOVE_PARENT) { return NULL; } container = container_parent(container, C_OUTPUT); parent = container->parent; } else { - if (dir == MOVE_CHILD) { - return seat_get_focus_inactive(seat, container); - } if (dir == MOVE_PARENT) { if (parent->type == C_OUTPUT) { return NULL; @@ -767,7 +781,8 @@ struct sway_container *container_get_in_direction( } sway_assert(next_workspace, "Next container has no workspace"); if (next_workspace->sway_workspace->fullscreen) { - return next_workspace->sway_workspace->fullscreen->swayc; + return seat_get_focus_inactive(seat, + next_workspace->sway_workspace->fullscreen); } if (next->children && next->children->length) { // TODO consider floating children as well @@ -1014,13 +1029,13 @@ void container_swap(struct sway_container *con1, struct sway_container *con2) { wlr_log(WLR_DEBUG, "Swapping containers %zu and %zu", con1->id, con2->id); - int fs1 = con1->type == C_VIEW && con1->sway_view->is_fullscreen; - int fs2 = con2->type == C_VIEW && con2->sway_view->is_fullscreen; + int fs1 = con1->is_fullscreen; + int fs2 = con2->is_fullscreen; if (fs1) { - view_set_fullscreen(con1->sway_view, false); + container_set_fullscreen(con1, false); } if (fs2) { - view_set_fullscreen(con2->sway_view, false); + container_set_fullscreen(con2, false); } struct sway_seat *seat = input_manager_get_default_seat(input_manager); @@ -1053,10 +1068,10 @@ void container_swap(struct sway_container *con1, struct sway_container *con2) { prev_workspace_name = stored_prev_name; } - if (fs1 && con2->type == C_VIEW) { - view_set_fullscreen(con2->sway_view, true); + if (fs1) { + container_set_fullscreen(con2, true); } - if (fs2 && con1->type == C_VIEW) { - view_set_fullscreen(con1->sway_view, true); + if (fs2) { + container_set_fullscreen(con1, true); } } diff --git a/sway/tree/view.c b/sway/tree/view.c index beeb8144..82c3ad4a 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -225,7 +225,7 @@ void view_autoconfigure(struct sway_view *view) { struct sway_container *output = container_parent(view->swayc, C_OUTPUT); - if (view->is_fullscreen) { + if (view->swayc->is_fullscreen) { view->x = output->x; view->y = output->y; view->width = output->width; @@ -233,10 +233,6 @@ void view_autoconfigure(struct sway_view *view) { return; } - if (container_is_floating(view->swayc)) { - return; - } - struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); int other_views = 0; @@ -349,68 +345,6 @@ void view_set_tiled(struct sway_view *view, bool tiled) { } } -void view_set_fullscreen(struct sway_view *view, bool fullscreen) { - if (view->is_fullscreen == fullscreen) { - return; - } - - struct sway_container *workspace = - container_parent(view->swayc, C_WORKSPACE); - - if (view->impl->set_fullscreen) { - view->impl->set_fullscreen(view, fullscreen); - } - - view->is_fullscreen = fullscreen; - - if (fullscreen) { - if (workspace->sway_workspace->fullscreen) { - view_set_fullscreen(workspace->sway_workspace->fullscreen, false); - } - workspace->sway_workspace->fullscreen = view; - view->saved_x = view->x; - view->saved_y = view->y; - view->saved_width = view->width; - view->saved_height = view->height; - view->swayc->saved_x = view->swayc->x; - view->swayc->saved_y = view->swayc->y; - view->swayc->saved_width = view->swayc->width; - view->swayc->saved_height = view->swayc->height; - - struct sway_seat *seat; - struct sway_container *focus, *focus_ws; - wl_list_for_each(seat, &input_manager->seats, link) { - focus = seat_get_focus(seat); - if (focus) { - focus_ws = focus; - if (focus && focus_ws->type != C_WORKSPACE) { - focus_ws = container_parent(focus_ws, C_WORKSPACE); - } - seat_set_focus(seat, view->swayc); - if (focus_ws != workspace) { - seat_set_focus(seat, focus); - } - } - } - } else { - workspace->sway_workspace->fullscreen = NULL; - if (container_is_floating(view->swayc)) { - view->x = view->saved_x; - view->y = view->saved_y; - view->width = view->saved_width; - view->height = view->saved_height; - container_set_geometry_from_floating_view(view->swayc); - } else { - view->swayc->width = view->swayc->saved_width; - view->swayc->height = view->swayc->saved_height; - } - } - - container_end_mouse_operation(view->swayc); - - ipc_event_window(view->swayc, "fullscreen_mode"); -} - void view_close(struct sway_view *view) { if (view->impl->close) { view->impl->close(view); @@ -680,7 +614,7 @@ void view_unmap(struct sway_view *view) { struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); struct sway_container *parent; - if (view->is_fullscreen) { + if (view->swayc->is_fullscreen) { ws->sway_workspace->fullscreen = NULL; parent = container_destroy(view->swayc); @@ -1133,7 +1067,8 @@ bool view_is_visible(struct sway_view *view) { container = container->parent; } // Check view isn't hidden by another fullscreen view - if (workspace->sway_workspace->fullscreen && !view->is_fullscreen) { + if (workspace->sway_workspace->fullscreen && + !container_is_fullscreen_or_child(view->swayc)) { return false; } // Check the workspace is visible -- cgit v1.2.3 From 868dcde14ef2116fcbd5c2c66badf2bcc514bba3 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Thu, 26 Jul 2018 08:28:05 +1000 Subject: Fix indent --- sway/desktop/render.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sway/desktop/render.c') diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 3e7b1a62..d2f1c9f2 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -857,7 +857,7 @@ void output_render(struct sway_output *output, struct timespec *when, if (fullscreen_con->instructions->length) { render_saved_view(fullscreen_con->sway_view, output, damage, 1.0f); - } else { + } else { render_view_surfaces(fullscreen_con->sway_view, output, damage, 1.0f); } -- cgit v1.2.3 From 08cfba2192f5770d975c5fe70789a81aaee4dc7e Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Thu, 26 Jul 2018 18:36:46 +1000 Subject: Allow containers to float Things worth noting: * When a fullscreen view unmaps, the check to unset fullscreen on the workspace has been moved out of view_unmap and into container_destroy, because containers can be fullscreen too * The calls to `container_reap_empty_recursive(workspace)` have been removed from `container_set_floating`. That function reaps upwards so it wouldn't do anything. I'm probably the one who originally added it... * My fix (b14bd1b0b1536039e4f46fe94515c7c44e7afc61) for the tabbed child crash has a side effect where when you close a floating container, focus is not given to the tiled container again. I've removed my fix and removed the call to `send_cursor_motion` from `seat_set_focus_warp`. We should consider calling it from somewhere earlier in the call stack. --- include/sway/tree/container.h | 11 ++++++ include/sway/tree/view.h | 5 --- sway/commands/floating.c | 13 +++++-- sway/commands/move.c | 10 ++++-- sway/desktop/render.c | 2 +- sway/input/cursor.c | 5 ++- sway/input/seat.c | 5 --- sway/scratchpad.c | 7 ++-- sway/tree/container.c | 82 ++++++++++++++++++++++++++++++++++++++++--- sway/tree/layout.c | 19 ++++++---- sway/tree/view.c | 53 +--------------------------- 11 files changed, 126 insertions(+), 86 deletions(-) (limited to 'sway/desktop/render.c') diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index c584cd92..d91b3bf1 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -297,6 +297,11 @@ void container_notify_subtree_changed(struct sway_container *container); */ size_t container_titlebar_height(void); +/** + * Resize and center the container in its workspace. + */ +void container_init_floating(struct sway_container *container); + void container_set_floating(struct sway_container *container, bool enable); void container_set_geometry_from_floating_view(struct sway_container *con); @@ -340,6 +345,12 @@ void container_end_mouse_operation(struct sway_container *container); void container_set_fullscreen(struct sway_container *container, bool enable); +/** + * Return true if the container is floating, or a child of a floating split + * container. + */ +bool container_is_floating_or_child(struct sway_container *container); + /** * Return true if the container is fullscreen, or a child of a fullscreen split * container. diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 7086314f..0152ed55 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -234,11 +234,6 @@ void view_get_constraints(struct sway_view *view, double *min_width, uint32_t view_configure(struct sway_view *view, double lx, double ly, int width, int height); -/** - * Center the view in its workspace and build the swayc decorations around it. - */ -void view_init_floating(struct sway_view *view); - /** * Configure the view's position and size based on the swayc's position and * size, taking borders into consideration. diff --git a/sway/commands/floating.c b/sway/commands/floating.c index 6ab56c3b..b67e736f 100644 --- a/sway/commands/floating.c +++ b/sway/commands/floating.c @@ -17,9 +17,16 @@ struct cmd_results *cmd_floating(int argc, char **argv) { } struct sway_container *container = config->handler_context.current_container; - if (container->type != C_VIEW) { - // TODO: This doesn't strictly speaking have to be true - return cmd_results_new(CMD_INVALID, "float", "Only views can float"); + if (container->type == C_WORKSPACE && container->children->length == 0) { + return cmd_results_new(CMD_INVALID, "floating", + "Can't float an empty workspace"); + } + if (container->type == C_WORKSPACE) { + // Wrap the workspace's children in a container so we can float it + struct sway_container *workspace = container; + container = container_wrap_children(container); + workspace->layout = L_HORIZ; + seat_set_focus(config->handler_context.seat, container); } bool wants_floating; diff --git a/sway/commands/move.c b/sway/commands/move.c index aede3d6c..b127c89f 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c @@ -298,9 +298,15 @@ static struct cmd_results *move_to_position(struct sway_container *container, } static struct cmd_results *move_to_scratchpad(struct sway_container *con) { - if (con->type != C_CONTAINER && con->type != C_VIEW) { + if (con->type == C_WORKSPACE && con->children->length == 0) { return cmd_results_new(CMD_INVALID, "move", - "Only views and containers can be moved to the scratchpad"); + "Can't move an empty workspace to the scratchpad"); + } + if (con->type == C_WORKSPACE) { + // Wrap the workspace's children in a container + struct sway_container *workspace = con; + con = container_wrap_children(con); + workspace->layout = L_HORIZ; } if (con->scratchpad) { return cmd_results_new(CMD_INVALID, "move", diff --git a/sway/desktop/render.c b/sway/desktop/render.c index d2f1c9f2..c9fdfd95 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -779,7 +779,7 @@ static void render_floating_container(struct sway_output *soutput, } render_view(soutput, damage, con, colors); } else { - render_container(soutput, damage, con, false); + render_container(soutput, damage, con, con->current.focused); } } diff --git a/sway/input/cursor.c b/sway/input/cursor.c index cc0dbe99..d1347198 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -598,7 +598,10 @@ void dispatch_cursor_button(struct sway_cursor *cursor, seat_set_focus_layer(cursor->seat, layer); } seat_pointer_notify_button(cursor->seat, time_msec, button, state); - } else if (cont && container_is_floating(cont)) { + } else if (cont && container_is_floating_or_child(cont)) { + while (cont->parent->layout != L_FLOATING) { + cont = cont->parent; + } dispatch_cursor_button_floating(cursor, time_msec, button, state, surface, sx, sy, cont); } else if (surface && cont && cont->type != C_VIEW) { diff --git a/sway/input/seat.c b/sway/input/seat.c index e7b6e0c5..877a93c6 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -184,7 +184,6 @@ static void handle_seat_container_destroy(struct wl_listener *listener, bool set_focus = focus != NULL && (focus == con || container_has_child(con, focus)) && - con->parent && con->parent->children->length > 1 && con->type != C_WORKSPACE; seat_container_destroy(seat_con); @@ -754,10 +753,6 @@ void seat_set_focus_warp(struct sway_seat *seat, } } - if (last_focus != NULL) { - cursor_send_pointer_motion(seat->cursor, 0, true); - } - seat->has_focus = (container != NULL); update_debug_tree(); diff --git a/sway/scratchpad.c b/sway/scratchpad.c index 64636c77..181d9b3b 100644 --- a/sway/scratchpad.c +++ b/sway/scratchpad.c @@ -72,11 +72,7 @@ static void scratchpad_show(struct sway_container *con) { if (!wlr_box_contains_point(&workspace_box, center_lx, center_ly)) { // Maybe resize it if (con->width > ws->width || con->height > ws->height) { - // TODO: Do this properly once we can float C_CONTAINERs - if (con->type == C_VIEW) { - view_init_floating(con->sway_view); - arrange_windows(con); - } + container_init_floating(con); } // Center it @@ -85,6 +81,7 @@ static void scratchpad_show(struct sway_container *con) { container_floating_move_to(con, new_lx, new_ly); } + arrange_windows(ws); seat_set_focus(seat, con); container_set_dirty(con->parent); diff --git a/sway/tree/container.c b/sway/tree/container.c index 6ebf2653..566432b1 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -407,6 +407,10 @@ struct sway_container *container_flatten(struct sway_container *container) { * This function just wraps container_destroy_noreaping(), then does reaping. */ struct sway_container *container_destroy(struct sway_container *con) { + if (con->is_fullscreen) { + struct sway_container *ws = container_parent(con, C_WORKSPACE); + ws->sway_workspace->fullscreen = NULL; + } struct sway_container *parent = container_destroy_noreaping(con); if (!parent) { @@ -945,23 +949,81 @@ size_t container_titlebar_height() { return config->font_height + TITLEBAR_V_PADDING * 2; } +void container_init_floating(struct sway_container *con) { + if (!sway_assert(con->type == C_VIEW || con->type == C_CONTAINER, + "Expected a view or container")) { + return; + } + struct sway_container *ws = container_parent(con, C_WORKSPACE); + int min_width, min_height; + int max_width, max_height; + + if (config->floating_minimum_width == -1) { // no minimum + min_width = 0; + } else if (config->floating_minimum_width == 0) { // automatic + min_width = 75; + } else { + min_width = config->floating_minimum_width; + } + + if (config->floating_minimum_height == -1) { // no minimum + min_height = 0; + } else if (config->floating_minimum_height == 0) { // automatic + min_height = 50; + } else { + min_height = config->floating_minimum_height; + } + + if (config->floating_maximum_width == -1) { // no maximum + max_width = INT_MAX; + } else if (config->floating_maximum_width == 0) { // automatic + max_width = ws->width * 0.6666; + } else { + max_width = config->floating_maximum_width; + } + + if (config->floating_maximum_height == -1) { // no maximum + max_height = INT_MAX; + } else if (config->floating_maximum_height == 0) { // automatic + max_height = ws->height * 0.6666; + } else { + max_height = config->floating_maximum_height; + } + + if (con->type == C_CONTAINER) { + con->width = max_width; + con->height = max_height; + con->x = ws->x + (ws->width - con->width) / 2; + con->y = ws->y + (ws->height - con->height) / 2; + } else { + struct sway_view *view = con->sway_view; + view->width = fmax(min_width, fmin(view->natural_width, max_width)); + view->height = fmax(min_height, fmin(view->natural_height, max_height)); + view->x = ws->x + (ws->width - view->width) / 2; + view->y = ws->y + (ws->height - view->height) / 2; + + // If the view's border is B_NONE then these properties are ignored. + view->border_top = view->border_bottom = true; + view->border_left = view->border_right = true; + + container_set_geometry_from_floating_view(view->swayc); + } +} + void container_set_floating(struct sway_container *container, bool enable) { if (container_is_floating(container) == enable) { return; } struct sway_container *workspace = container_parent(container, C_WORKSPACE); - struct sway_seat *seat = input_manager_current_seat(input_manager); if (enable) { container_remove_child(container); container_add_child(workspace->sway_workspace->floating, container); + container_init_floating(container); if (container->type == C_VIEW) { - view_init_floating(container->sway_view); view_set_tiled(container->sway_view, false); } - seat_set_focus(seat, seat_get_focus_inactive(seat, container)); - container_reap_empty_recursive(workspace); } else { // Returning to tiled if (container->scratchpad) { @@ -975,7 +1037,6 @@ void container_set_floating(struct sway_container *container, bool enable) { view_set_tiled(container->sway_view, true); } container->is_sticky = false; - container_reap_empty_recursive(workspace->sway_workspace->floating); } container_end_mouse_operation(container); @@ -1195,6 +1256,17 @@ void container_set_fullscreen(struct sway_container *container, bool enable) { ipc_event_window(container, "fullscreen_mode"); } +bool container_is_floating_or_child(struct sway_container *container) { + do { + if (container->parent && container->parent->layout == L_FLOATING) { + return true; + } + container = container->parent; + } while (container && container->type != C_WORKSPACE); + + return false; +} + bool container_is_fullscreen_or_child(struct sway_container *container) { do { if (container->is_fullscreen) { diff --git a/sway/tree/layout.c b/sway/tree/layout.c index ab5acc16..a0764a54 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -387,9 +387,11 @@ void container_move(struct sway_container *container, // If moving a fullscreen view, only consider outputs if (container->is_fullscreen) { current = container_parent(container, C_OUTPUT); - } else if (container_is_fullscreen_or_child(container)) { + } else if (container_is_fullscreen_or_child(container) || + container_is_floating_or_child(container)) { // If we've fullscreened a split container, only allow the child to move // around within the fullscreen parent. + // Same with floating a split container. struct sway_container *ws = container_parent(container, C_WORKSPACE); top = ws->sway_workspace->fullscreen; } @@ -465,6 +467,9 @@ void container_move(struct sway_container *container, if ((index == parent->children->length - 1 && offs > 0) || (index == 0 && offs < 0)) { if (current->parent == container->parent) { + if (parent->parent->layout == L_FLOATING) { + return; + } if (!parent->is_fullscreen && (parent->layout == L_TABBED || parent->layout == L_STACKED)) { @@ -488,10 +493,14 @@ void container_move(struct sway_container *container, sibling = parent->children->items[index + offs]; wlr_log(WLR_DEBUG, "Selecting sibling id:%zd", sibling->id); } - } else if (!parent->is_fullscreen && (parent->layout == L_TABBED || + } else if (!parent->is_fullscreen && + parent->parent->layout != L_FLOATING && + (parent->layout == L_TABBED || parent->layout == L_STACKED)) { move_out_of_tabs_stacks(container, current, move_dir, offs); return; + } else if (parent->parent->layout == L_FLOATING) { + return; } else { wlr_log(WLR_DEBUG, "Moving up to find a parallel container"); current = current->parent; @@ -717,10 +726,6 @@ struct sway_container *container_get_in_direction( enum movement_direction dir) { struct sway_container *parent = container->parent; - if (container_is_floating(container)) { - return NULL; - } - if (dir == MOVE_CHILD) { return seat_get_focus_inactive(seat, container); } @@ -732,7 +737,7 @@ struct sway_container *container_get_in_direction( parent = container->parent; } else { if (dir == MOVE_PARENT) { - if (parent->type == C_OUTPUT) { + if (parent->type == C_OUTPUT || container_is_floating(container)) { return NULL; } else { return parent; diff --git a/sway/tree/view.c b/sway/tree/view.c index e641544e..253f3001 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -168,55 +168,6 @@ uint32_t view_configure(struct sway_view *view, double lx, double ly, int width, return 0; } -void view_init_floating(struct sway_view *view) { - struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); - int min_width, min_height; - int max_width, max_height; - - if (config->floating_minimum_width == -1) { // no minimum - min_width = 0; - } else if (config->floating_minimum_width == 0) { // automatic - min_width = 75; - } else { - min_width = config->floating_minimum_width; - } - - if (config->floating_minimum_height == -1) { // no minimum - min_height = 0; - } else if (config->floating_minimum_height == 0) { // automatic - min_height = 50; - } else { - min_height = config->floating_minimum_height; - } - - if (config->floating_maximum_width == -1) { // no maximum - max_width = INT_MAX; - } else if (config->floating_maximum_width == 0) { // automatic - max_width = ws->width * 0.6666; - } else { - max_width = config->floating_maximum_width; - } - - if (config->floating_maximum_height == -1) { // no maximum - max_height = INT_MAX; - } else if (config->floating_maximum_height == 0) { // automatic - max_height = ws->height * 0.6666; - } else { - max_height = config->floating_maximum_height; - } - - view->width = fmax(min_width, fmin(view->natural_width, max_width)); - view->height = fmax(min_height, fmin(view->natural_height, max_height)); - view->x = ws->x + (ws->width - view->width) / 2; - view->y = ws->y + (ws->height - view->height) / 2; - - // If the view's border is B_NONE then these properties are ignored. - view->border_top = view->border_bottom = true; - view->border_left = view->border_right = true; - - container_set_geometry_from_floating_view(view->swayc); -} - void view_autoconfigure(struct sway_view *view) { if (!sway_assert(view->swayc, "Called view_autoconfigure() on a view without a swayc")) { @@ -626,10 +577,8 @@ void view_unmap(struct sway_view *view) { struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); struct sway_container *parent; - if (view->swayc->is_fullscreen) { - ws->sway_workspace->fullscreen = NULL; + if (container_is_fullscreen_or_child(view->swayc)) { parent = container_destroy(view->swayc); - arrange_windows(ws->parent); } else { parent = container_destroy(view->swayc); -- cgit v1.2.3 From d2172bd331937ab406175a6b4c5a76db6f406fbe Mon Sep 17 00:00:00 2001 From: emersion Date: Fri, 27 Jul 2018 18:17:47 +0100 Subject: wip: redesign output_unmanaged_for_each_surface iterator --- include/sway/output.h | 17 +++++++++--- sway/desktop/output.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++----- sway/desktop/render.c | 31 ++++++++++++++++++++-- 3 files changed, 110 insertions(+), 11 deletions(-) (limited to 'sway/desktop/render.c') diff --git a/include/sway/output.h b/include/sway/output.h index c225e541..99b0bcc6 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -5,6 +5,7 @@ #include #include #include +#include "config.h" #include "sway/tree/view.h" struct sway_server; @@ -48,6 +49,10 @@ struct root_geometry { float rotation; }; +typedef void (*sway_surface_iterator_func_t)(struct sway_output *output, + struct wlr_surface *surface, struct wlr_box *box, float rotation, + void *user_data); + void output_damage_whole(struct sway_output *output); void output_damage_surface(struct sway_output *output, double ox, double oy, @@ -80,6 +85,10 @@ void output_surface_for_each_surface(struct wlr_surface *surface, double ox, double oy, struct root_geometry *geo, wlr_surface_iterator_func_t iterator, void *user_data); +void output_surface_for_each_surface2(struct sway_output *output, + struct wlr_surface *surface, double ox, double oy, float rotation, + sway_surface_iterator_func_t iterator, void *user_data); + void output_view_for_each_surface(struct sway_view *view, struct sway_output *output, struct root_geometry *geo, wlr_surface_iterator_func_t iterator, void *user_data); @@ -88,9 +97,11 @@ void output_layer_for_each_surface(struct wl_list *layer_surfaces, struct root_geometry *geo, wlr_surface_iterator_func_t iterator, void *user_data); -void output_unmanaged_for_each_surface(struct wl_list *unmanaged, - struct sway_output *output, struct root_geometry *geo, - wlr_surface_iterator_func_t iterator, void *user_data); +#ifdef HAVE_XWAYLAND +void output_unmanaged_for_each_surface(struct sway_output *output, + struct wl_list *unmanaged, sway_surface_iterator_func_t iterator, + void *user_data); +#endif void output_drag_icons_for_each_surface(struct wl_list *drag_icons, struct sway_output *output, struct root_geometry *geo, diff --git a/sway/desktop/output.c b/sway/desktop/output.c index cecd300a..9c2a1a07 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -105,6 +105,56 @@ void output_surface_for_each_surface(struct wlr_surface *surface, wlr_surface_for_each_surface(surface, iterator, user_data); } +struct surface_iterator_data { + sway_surface_iterator_func_t user_iterator; + void *user_data; + + struct sway_output *output; + double ox, oy; + int width, height; + float rotation; +}; + +void output_surface_for_each_surface2_iterator(struct wlr_surface *surface, + int sx, int sy, void *_data) { + struct surface_iterator_data *data = _data; + + struct root_geometry geo = { + .x = data->ox, + .y = data->oy, + .width = data->width, + .height = data->height, + .rotation = data->rotation, + }; + struct wlr_box box; + bool intersects = output_get_surface_box(&geo, data->output, + surface, sx, sy, &box); + if (!intersects) { + return; + } + + data->user_iterator(data->output, surface, &box, data->rotation, + data->user_data); +} + +void output_surface_for_each_surface2(struct sway_output *output, + struct wlr_surface *surface, double ox, double oy, float rotation, + sway_surface_iterator_func_t iterator, void *user_data) { + struct surface_iterator_data data = { + .user_iterator = iterator, + .user_data = user_data, + .output = output, + .ox = ox, + .oy = oy, + .width = surface->current.width, + .height = surface->current.height, + .rotation = rotation, + }; + + wlr_surface_for_each_surface(surface, + output_surface_for_each_surface2_iterator, &data); +} + void output_view_for_each_surface(struct sway_view *view, struct sway_output *output, struct root_geometry *geo, wlr_surface_iterator_func_t iterator, void *user_data) { @@ -129,10 +179,11 @@ void output_layer_for_each_surface(struct wl_list *layer_surfaces, user_data); } } + #ifdef HAVE_XWAYLAND -void output_unmanaged_for_each_surface(struct wl_list *unmanaged, - struct sway_output *output, struct root_geometry *geo, - wlr_surface_iterator_func_t iterator, void *user_data) { +void output_unmanaged_for_each_surface(struct sway_output *output, + struct wl_list *unmanaged, sway_surface_iterator_func_t iterator, + void *user_data) { struct sway_xwayland_unmanaged *unmanaged_surface; wl_list_for_each(unmanaged_surface, unmanaged, link) { struct wlr_xwayland_surface *xsurface = @@ -140,11 +191,12 @@ void output_unmanaged_for_each_surface(struct wl_list *unmanaged, double ox = unmanaged_surface->lx - output->swayc->current.swayc_x; double oy = unmanaged_surface->ly - output->swayc->current.swayc_y; - output_surface_for_each_surface(xsurface->surface, ox, oy, geo, + output_surface_for_each_surface2(output, xsurface->surface, ox, oy, 0, iterator, user_data); } } #endif + void output_drag_icons_for_each_surface(struct wl_list *drag_icons, struct sway_output *output, struct root_geometry *geo, wlr_surface_iterator_func_t iterator, void *user_data) { @@ -228,18 +280,27 @@ static void send_frame_done_iterator(struct wlr_surface *surface, } } +static void send_frame_done_iterator2(struct sway_output *output, + struct wlr_surface *surface, struct wlr_box *box, float rotation, + void *_data) { + struct send_frame_done_data *data = _data; + wlr_surface_send_frame_done(surface, data->when); +} + static void send_frame_done_layer(struct send_frame_done_data *data, struct wl_list *layer_surfaces) { output_layer_for_each_surface(layer_surfaces, &data->root_geo, send_frame_done_iterator, data); } + #ifdef HAVE_XWAYLAND static void send_frame_done_unmanaged(struct send_frame_done_data *data, struct wl_list *unmanaged) { - output_unmanaged_for_each_surface(unmanaged, data->output, &data->root_geo, - send_frame_done_iterator, data); + output_unmanaged_for_each_surface(data->output, unmanaged, + send_frame_done_iterator2, data); } #endif + static void send_frame_done_drag_icons(struct send_frame_done_data *data, struct wl_list *drag_icons) { output_drag_icons_for_each_surface(drag_icons, data->output, &data->root_geo, diff --git a/sway/desktop/render.c b/sway/desktop/render.c index c9fdfd95..8eea19e0 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -123,6 +123,31 @@ static void render_surface_iterator(struct wlr_surface *surface, int sx, int sy, render_texture(wlr_output, output_damage, texture, &box, matrix, alpha); } +static void render_surface_iterator2(struct sway_output *output, + struct wlr_surface *surface, struct wlr_box *_box, float rotation, + void *_data) { + struct render_data *data = _data; + struct wlr_output *wlr_output = output->wlr_output; + pixman_region32_t *output_damage = data->damage; + float alpha = data->alpha; + + struct wlr_texture *texture = wlr_surface_get_texture(surface); + if (!texture) { + return; + } + + struct wlr_box box = *_box; + scale_box(&box, wlr_output->scale); + + float matrix[9]; + enum wl_output_transform transform = + wlr_output_transform_invert(surface->current.transform); + wlr_matrix_project_box(matrix, &box, transform, rotation, + wlr_output->transform_matrix); + + render_texture(wlr_output, output_damage, texture, &box, matrix, alpha); +} + static void render_layer(struct sway_output *output, pixman_region32_t *damage, struct wl_list *layer_surfaces) { struct render_data data = { @@ -133,6 +158,7 @@ static void render_layer(struct sway_output *output, output_layer_for_each_surface(layer_surfaces, &data.root_geo, render_surface_iterator, &data); } + #ifdef HAVE_XWAYLAND static void render_unmanaged(struct sway_output *output, pixman_region32_t *damage, struct wl_list *unmanaged) { @@ -141,10 +167,11 @@ static void render_unmanaged(struct sway_output *output, .damage = damage, .alpha = 1.0f, }; - output_unmanaged_for_each_surface(unmanaged, output, &data.root_geo, - render_surface_iterator, &data); + output_unmanaged_for_each_surface(output, unmanaged, + render_surface_iterator2, &data); } #endif + static void render_drag_icons(struct sway_output *output, pixman_region32_t *damage, struct wl_list *drag_icons) { struct render_data data = { -- cgit v1.2.3 From dbf6dd0daec9e712a002c3e01accbd0fee769fac Mon Sep 17 00:00:00 2001 From: emersion Date: Fri, 27 Jul 2018 18:44:36 +0100 Subject: wip: redesign output_drag_icons_for_each_surface iterator --- include/sway/output.h | 6 +++--- sway/desktop/output.c | 15 ++++++++------- sway/desktop/render.c | 4 ++-- 3 files changed, 13 insertions(+), 12 deletions(-) (limited to 'sway/desktop/render.c') diff --git a/include/sway/output.h b/include/sway/output.h index 99b0bcc6..10a14207 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -103,8 +103,8 @@ void output_unmanaged_for_each_surface(struct sway_output *output, void *user_data); #endif -void output_drag_icons_for_each_surface(struct wl_list *drag_icons, - struct sway_output *output, struct root_geometry *geo, - wlr_surface_iterator_func_t iterator, void *user_data); +void output_drag_icons_for_each_surface(struct sway_output *output, + struct wl_list *drag_icons, sway_surface_iterator_func_t iterator, + void *user_data); #endif diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 9c2a1a07..e83a9a3d 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -197,17 +197,18 @@ void output_unmanaged_for_each_surface(struct sway_output *output, } #endif -void output_drag_icons_for_each_surface(struct wl_list *drag_icons, - struct sway_output *output, struct root_geometry *geo, - wlr_surface_iterator_func_t iterator, void *user_data) { +void output_drag_icons_for_each_surface(struct sway_output *output, + struct wl_list *drag_icons, sway_surface_iterator_func_t iterator, + void *user_data) { struct sway_drag_icon *drag_icon; wl_list_for_each(drag_icon, drag_icons, link) { double ox = drag_icon->x - output->swayc->x; double oy = drag_icon->y - output->swayc->y; if (drag_icon->wlr_drag_icon->mapped) { - output_surface_for_each_surface(drag_icon->wlr_drag_icon->surface, - ox, oy, geo, iterator, user_data); + output_surface_for_each_surface2(output, + drag_icon->wlr_drag_icon->surface, ox, oy, 0, + iterator, user_data); } } } @@ -303,8 +304,8 @@ static void send_frame_done_unmanaged(struct send_frame_done_data *data, static void send_frame_done_drag_icons(struct send_frame_done_data *data, struct wl_list *drag_icons) { - output_drag_icons_for_each_surface(drag_icons, data->output, &data->root_geo, - send_frame_done_iterator, data); + output_drag_icons_for_each_surface(data->output, drag_icons, + send_frame_done_iterator2, data); } static void send_frame_done_container_iterator(struct sway_container *con, diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 8eea19e0..1270b7cf 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -179,8 +179,8 @@ static void render_drag_icons(struct sway_output *output, .damage = damage, .alpha = 1.0f, }; - output_drag_icons_for_each_surface(drag_icons, output, &data.root_geo, - render_surface_iterator, &data); + output_drag_icons_for_each_surface(output, drag_icons, + render_surface_iterator2, &data); } static void render_rect(struct wlr_output *wlr_output, -- cgit v1.2.3 From a0dd9776172796f65b0fce0a8e5cfb66bdb2e2e5 Mon Sep 17 00:00:00 2001 From: emersion Date: Fri, 27 Jul 2018 18:53:15 +0100 Subject: wip: redesign output_layer_for_each_surface iterator --- include/sway/output.h | 4 ++-- sway/desktop/output.c | 32 ++++++++++++++++---------------- sway/desktop/render.c | 4 ++-- 3 files changed, 20 insertions(+), 20 deletions(-) (limited to 'sway/desktop/render.c') diff --git a/include/sway/output.h b/include/sway/output.h index 10a14207..c1763b26 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -93,8 +93,8 @@ void output_view_for_each_surface(struct sway_view *view, struct sway_output *output, struct root_geometry *geo, wlr_surface_iterator_func_t iterator, void *user_data); -void output_layer_for_each_surface(struct wl_list *layer_surfaces, - struct root_geometry *geo, wlr_surface_iterator_func_t iterator, +void output_layer_for_each_surface(struct sway_output *output, + struct wl_list *layer_surfaces, sway_surface_iterator_func_t iterator, void *user_data); #ifdef HAVE_XWAYLAND diff --git a/sway/desktop/output.c b/sway/desktop/output.c index e83a9a3d..5e309250 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -167,15 +167,15 @@ void output_view_for_each_surface(struct sway_view *view, view_for_each_surface(view, iterator, user_data); } -void output_layer_for_each_surface(struct wl_list *layer_surfaces, - struct root_geometry *geo, wlr_surface_iterator_func_t iterator, +void output_layer_for_each_surface(struct sway_output *output, + struct wl_list *layer_surfaces, sway_surface_iterator_func_t iterator, void *user_data) { struct sway_layer_surface *layer_surface; wl_list_for_each(layer_surface, layer_surfaces, link) { struct wlr_layer_surface *wlr_layer_surface = layer_surface->layer_surface; - output_surface_for_each_surface(wlr_layer_surface->surface, - layer_surface->geo.x, layer_surface->geo.y, geo, iterator, + output_surface_for_each_surface2(output, wlr_layer_surface->surface, + layer_surface->geo.x, layer_surface->geo.y, 0, iterator, user_data); } } @@ -288,10 +288,10 @@ static void send_frame_done_iterator2(struct sway_output *output, wlr_surface_send_frame_done(surface, data->when); } -static void send_frame_done_layer(struct send_frame_done_data *data, - struct wl_list *layer_surfaces) { - output_layer_for_each_surface(layer_surfaces, &data->root_geo, - send_frame_done_iterator, data); +static void send_frame_done_layer(struct sway_output *output, + struct wl_list *layer_surfaces, struct send_frame_done_data *data) { + output_layer_for_each_surface(output, layer_surfaces, + send_frame_done_iterator2, data); } #ifdef HAVE_XWAYLAND @@ -352,10 +352,10 @@ static void send_frame_done(struct sway_output *output, struct timespec *when) { &root_container.sway_root->xwayland_unmanaged); #endif } else { - send_frame_done_layer(&data, - &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]); - send_frame_done_layer(&data, - &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]); + send_frame_done_layer(output, + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &data); + send_frame_done_layer(output, + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], &data); send_frame_done_container(&data, workspace); send_frame_done_container(&data, workspace->sway_workspace->floating); @@ -364,13 +364,13 @@ static void send_frame_done(struct sway_output *output, struct timespec *when) { send_frame_done_unmanaged(&data, &root_container.sway_root->xwayland_unmanaged); #endif - send_frame_done_layer(&data, - &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); + send_frame_done_layer(output, + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &data); } send_frame_overlay: - send_frame_done_layer(&data, - &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); + send_frame_done_layer(output, + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], &data); send_frame_done_drag_icons(&data, &root_container.sway_root->drag_icons); } diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 1270b7cf..35dc3edc 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -155,8 +155,8 @@ static void render_layer(struct sway_output *output, .damage = damage, .alpha = 1.0f, }; - output_layer_for_each_surface(layer_surfaces, &data.root_geo, - render_surface_iterator, &data); + output_layer_for_each_surface(output, layer_surfaces, + render_surface_iterator2, &data); } #ifdef HAVE_XWAYLAND -- cgit v1.2.3 From e9d674cfd294f13a32893dd584826ed7481e05e3 Mon Sep 17 00:00:00 2001 From: emersion Date: Fri, 27 Jul 2018 18:59:14 +0100 Subject: wip: redesign output_view_for_each_surface iterator --- include/sway/output.h | 6 ++--- sway/desktop/output.c | 75 ++++++++++++++++++++++++++++++++++++++++++--------- sway/desktop/render.c | 3 +-- 3 files changed, 66 insertions(+), 18 deletions(-) (limited to 'sway/desktop/render.c') diff --git a/include/sway/output.h b/include/sway/output.h index c1763b26..7a458a84 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -89,9 +89,9 @@ void output_surface_for_each_surface2(struct sway_output *output, struct wlr_surface *surface, double ox, double oy, float rotation, sway_surface_iterator_func_t iterator, void *user_data); -void output_view_for_each_surface(struct sway_view *view, - struct sway_output *output, struct root_geometry *geo, - wlr_surface_iterator_func_t iterator, void *user_data); +void output_view_for_each_surface(struct sway_output *output, + struct sway_view *view, sway_surface_iterator_func_t iterator, + void *user_data); void output_layer_for_each_surface(struct sway_output *output, struct wl_list *layer_surfaces, sway_surface_iterator_func_t iterator, diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 5e309250..31033ee3 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -155,16 +155,22 @@ void output_surface_for_each_surface2(struct sway_output *output, output_surface_for_each_surface2_iterator, &data); } -void output_view_for_each_surface(struct sway_view *view, - struct sway_output *output, struct root_geometry *geo, - wlr_surface_iterator_func_t iterator, void *user_data) { - geo->x = view->swayc->current.view_x - output->swayc->current.swayc_x; - geo->y = view->swayc->current.view_y - output->swayc->current.swayc_y; - geo->width = view->swayc->current.view_width; - geo->height = view->swayc->current.view_height; - geo->rotation = 0; // TODO +void output_view_for_each_surface(struct sway_output *output, + struct sway_view *view, sway_surface_iterator_func_t iterator, + void *user_data) { + struct surface_iterator_data data = { + .user_iterator = iterator, + .user_data = user_data, + .output = output, + .ox = view->swayc->current.view_x - output->swayc->current.swayc_x, + .oy = view->swayc->current.view_y - output->swayc->current.swayc_y, + .width = view->swayc->current.view_width, + .height = view->swayc->current.view_height, + .rotation = 0, // TODO + }; - view_for_each_surface(view, iterator, user_data); + view_for_each_surface(view, + output_surface_for_each_surface2_iterator, &data); } void output_layer_for_each_surface(struct sway_output *output, @@ -319,8 +325,8 @@ static void send_frame_done_container_iterator(struct sway_container *con, return; } - output_view_for_each_surface(con->sway_view, data->output, &data->root_geo, - send_frame_done_iterator, data); + output_view_for_each_surface(data->output, con->sway_view, + send_frame_done_iterator2, data); } static void send_frame_done_container(struct send_frame_done_data *data, @@ -463,6 +469,50 @@ static void damage_surface_iterator(struct wlr_surface *surface, int sx, int sy, wlr_output_schedule_frame(output->wlr_output); } +static void damage_surface_iterator2(struct sway_output *output, + struct wlr_surface *surface, struct wlr_box *_box, float rotation, + void *_data) { + struct damage_data *data = _data; + bool whole = data->whole; + + struct wlr_box box = *_box; + scale_box(&box, output->wlr_output->scale); + + int center_x = box.x + box.width/2; + int center_y = box.y + box.height/2; + + if (pixman_region32_not_empty(&surface->buffer_damage)) { + enum wl_output_transform transform = + wlr_output_transform_invert(surface->current.transform); + + pixman_region32_t damage; + pixman_region32_init(&damage); + pixman_region32_copy(&damage, &surface->buffer_damage); + wlr_region_transform(&damage, &damage, transform, + surface->current.buffer_width, surface->current.buffer_height); + wlr_region_scale(&damage, &damage, + output->wlr_output->scale / (float)surface->current.scale); + if (ceil(output->wlr_output->scale) > surface->current.scale) { + // When scaling up a surface, it'll become blurry so we need to + // expand the damage region + wlr_region_expand(&damage, &damage, + ceil(output->wlr_output->scale) - surface->current.scale); + } + pixman_region32_translate(&damage, box.x, box.y); + wlr_region_rotated_bounds(&damage, &damage, rotation, + center_x, center_y); + wlr_output_damage_add(output->damage, &damage); + pixman_region32_fini(&damage); + } + + if (whole) { + wlr_box_rotated_bounds(&box, rotation, &box); + wlr_output_damage_add_box(output->damage, &box); + } + + wlr_output_schedule_frame(output->wlr_output); +} + void output_damage_surface(struct sway_output *output, double ox, double oy, struct wlr_surface *surface, bool whole) { struct damage_data data = { @@ -489,8 +539,7 @@ static void output_damage_view(struct sway_output *output, .whole = whole, }; - output_view_for_each_surface(view, output, &data.root_geo, - damage_surface_iterator, &data); + output_view_for_each_surface(output, view, damage_surface_iterator2, &data); } void output_damage_from_view(struct sway_output *output, diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 35dc3edc..18d076df 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -231,8 +231,7 @@ static void render_view_surfaces(struct sway_view *view, .view = view, .alpha = alpha, }; - output_view_for_each_surface(view, output, &data.root_geo, - render_surface_iterator, &data); + output_view_for_each_surface(output, view, render_surface_iterator2, &data); } static void render_saved_view(struct sway_view *view, -- cgit v1.2.3 From 8d5cc8625ce04c657eab6bd5f242a02e97ddd647 Mon Sep 17 00:00:00 2001 From: emersion Date: Fri, 27 Jul 2018 19:16:36 +0100 Subject: Completely switch over to new iterators --- include/sway/output.h | 18 ---- sway/desktop/output.c | 243 +++++++++++++++----------------------------------- sway/desktop/render.c | 49 ++-------- 3 files changed, 79 insertions(+), 231 deletions(-) (limited to 'sway/desktop/render.c') diff --git a/include/sway/output.h b/include/sway/output.h index 7a458a84..70f631a0 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -39,16 +39,6 @@ struct sway_output { } events; }; -/** - * Contains a surface's root geometry information. For instance, when rendering - * a popup, this will contain the parent view's position and size. - */ -struct root_geometry { - double x, y; - int width, height; - float rotation; -}; - typedef void (*sway_surface_iterator_func_t)(struct sway_output *output, struct wlr_surface *surface, struct wlr_box *box, float rotation, void *user_data); @@ -77,14 +67,6 @@ struct sway_container *output_get_active_workspace(struct sway_output *output); void output_render(struct sway_output *output, struct timespec *when, pixman_region32_t *damage); -bool output_get_surface_box(struct root_geometry *geo, - struct sway_output *output, struct wlr_surface *surface, int sx, int sy, - struct wlr_box *surface_box); - -void output_surface_for_each_surface(struct wlr_surface *surface, - double ox, double oy, struct root_geometry *geo, - wlr_surface_iterator_func_t iterator, void *user_data); - void output_surface_for_each_surface2(struct sway_output *output, struct wlr_surface *surface, double ox, double oy, float rotation, sway_surface_iterator_func_t iterator, void *user_data); diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 31033ee3..e1d85b10 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -57,9 +57,21 @@ static void rotate_child_position(double *sx, double *sy, double sw, double sh, *sy = ry + ph/2 - sh/2; } -bool output_get_surface_box(struct root_geometry *geo, - struct sway_output *output, struct wlr_surface *surface, int sx, int sy, +struct surface_iterator_data { + sway_surface_iterator_func_t user_iterator; + void *user_data; + + struct sway_output *output; + double ox, oy; + int width, height; + float rotation; +}; + +static bool get_surface_box(struct surface_iterator_data *data, + struct wlr_surface *surface, int sx, int sy, struct wlr_box *surface_box) { + struct sway_output *output = data->output; + if (!wlr_surface_has_buffer(surface)) { return false; } @@ -68,12 +80,12 @@ bool output_get_surface_box(struct root_geometry *geo, int sh = surface->current.height; double _sx = sx, _sy = sy; - rotate_child_position(&_sx, &_sy, sw, sh, geo->width, geo->height, - geo->rotation); + rotate_child_position(&_sx, &_sy, sw, sh, data->width, data->height, + data->rotation); struct wlr_box box = { - .x = geo->x + _sx, - .y = geo->y + _sy, + .x = data->ox + _sx, + .y = data->oy + _sy, .width = sw, .height = sh, }; @@ -82,7 +94,7 @@ bool output_get_surface_box(struct root_geometry *geo, } struct wlr_box rotated_box; - wlr_box_rotated_bounds(&box, geo->rotation, &rotated_box); + wlr_box_rotated_bounds(&box, data->rotation, &rotated_box); struct wlr_box output_box = { .width = output->swayc->current.swayc_width, @@ -93,42 +105,12 @@ bool output_get_surface_box(struct root_geometry *geo, return wlr_box_intersection(&output_box, &rotated_box, &intersection); } -void output_surface_for_each_surface(struct wlr_surface *surface, - double ox, double oy, struct root_geometry *geo, - wlr_surface_iterator_func_t iterator, void *user_data) { - geo->x = ox; - geo->y = oy; - geo->width = surface->current.width; - geo->height = surface->current.height; - geo->rotation = 0; - - wlr_surface_for_each_surface(surface, iterator, user_data); -} - -struct surface_iterator_data { - sway_surface_iterator_func_t user_iterator; - void *user_data; - - struct sway_output *output; - double ox, oy; - int width, height; - float rotation; -}; - -void output_surface_for_each_surface2_iterator(struct wlr_surface *surface, +void output_surface_for_each_surface_iterator(struct wlr_surface *surface, int sx, int sy, void *_data) { struct surface_iterator_data *data = _data; - struct root_geometry geo = { - .x = data->ox, - .y = data->oy, - .width = data->width, - .height = data->height, - .rotation = data->rotation, - }; struct wlr_box box; - bool intersects = output_get_surface_box(&geo, data->output, - surface, sx, sy, &box); + bool intersects = get_surface_box(data, surface, sx, sy, &box); if (!intersects) { return; } @@ -137,7 +119,7 @@ void output_surface_for_each_surface2_iterator(struct wlr_surface *surface, data->user_data); } -void output_surface_for_each_surface2(struct sway_output *output, +void output_surface_for_each_surface(struct sway_output *output, struct wlr_surface *surface, double ox, double oy, float rotation, sway_surface_iterator_func_t iterator, void *user_data) { struct surface_iterator_data data = { @@ -152,7 +134,7 @@ void output_surface_for_each_surface2(struct sway_output *output, }; wlr_surface_for_each_surface(surface, - output_surface_for_each_surface2_iterator, &data); + output_surface_for_each_surface_iterator, &data); } void output_view_for_each_surface(struct sway_output *output, @@ -170,7 +152,7 @@ void output_view_for_each_surface(struct sway_output *output, }; view_for_each_surface(view, - output_surface_for_each_surface2_iterator, &data); + output_surface_for_each_surface_iterator, &data); } void output_layer_for_each_surface(struct sway_output *output, @@ -180,7 +162,7 @@ void output_layer_for_each_surface(struct sway_output *output, wl_list_for_each(layer_surface, layer_surfaces, link) { struct wlr_layer_surface *wlr_layer_surface = layer_surface->layer_surface; - output_surface_for_each_surface2(output, wlr_layer_surface->surface, + output_surface_for_each_surface(output, wlr_layer_surface->surface, layer_surface->geo.x, layer_surface->geo.y, 0, iterator, user_data); } @@ -197,7 +179,7 @@ void output_unmanaged_for_each_surface(struct sway_output *output, double ox = unmanaged_surface->lx - output->swayc->current.swayc_x; double oy = unmanaged_surface->ly - output->swayc->current.swayc_y; - output_surface_for_each_surface2(output, xsurface->surface, ox, oy, 0, + output_surface_for_each_surface(output, xsurface->surface, ox, oy, 0, iterator, user_data); } } @@ -212,7 +194,7 @@ void output_drag_icons_for_each_surface(struct sway_output *output, double oy = drag_icon->y - output->swayc->y; if (drag_icon->wlr_drag_icon->mapped) { - output_surface_for_each_surface2(output, + output_surface_for_each_surface(output, drag_icon->wlr_drag_icon->surface, ox, oy, 0, iterator, user_data); } @@ -270,50 +252,38 @@ bool output_has_opaque_overlay_layer_surface(struct sway_output *output) { return false; } -struct send_frame_done_data { - struct root_geometry root_geo; - struct sway_output *output; - struct timespec *when; -}; - -static void send_frame_done_iterator(struct wlr_surface *surface, - int sx, int sy, void *_data) { - struct send_frame_done_data *data = _data; - - bool intersects = output_get_surface_box(&data->root_geo, data->output, surface, - sx, sy, NULL); - if (intersects) { - wlr_surface_send_frame_done(surface, data->when); - } -} - -static void send_frame_done_iterator2(struct sway_output *output, +static void send_frame_done_iterator(struct sway_output *output, struct wlr_surface *surface, struct wlr_box *box, float rotation, void *_data) { - struct send_frame_done_data *data = _data; - wlr_surface_send_frame_done(surface, data->when); + struct timespec *when = _data; + wlr_surface_send_frame_done(surface, when); } static void send_frame_done_layer(struct sway_output *output, - struct wl_list *layer_surfaces, struct send_frame_done_data *data) { + struct wl_list *layer_surfaces, struct timespec *when) { output_layer_for_each_surface(output, layer_surfaces, - send_frame_done_iterator2, data); + send_frame_done_iterator, when); } #ifdef HAVE_XWAYLAND -static void send_frame_done_unmanaged(struct send_frame_done_data *data, - struct wl_list *unmanaged) { - output_unmanaged_for_each_surface(data->output, unmanaged, - send_frame_done_iterator2, data); +static void send_frame_done_unmanaged(struct sway_output *output, + struct wl_list *unmanaged, struct timespec *when) { + output_unmanaged_for_each_surface(output, unmanaged, + send_frame_done_iterator, when); } #endif -static void send_frame_done_drag_icons(struct send_frame_done_data *data, - struct wl_list *drag_icons) { - output_drag_icons_for_each_surface(data->output, drag_icons, - send_frame_done_iterator2, data); +static void send_frame_done_drag_icons(struct sway_output *output, + struct wl_list *drag_icons, struct timespec *when) { + output_drag_icons_for_each_surface(output, drag_icons, + send_frame_done_iterator, when); } +struct send_frame_done_data { + struct sway_output *output; + struct timespec *when; +}; + static void send_frame_done_container_iterator(struct sway_container *con, void *_data) { struct send_frame_done_data *data = _data; @@ -326,21 +296,20 @@ static void send_frame_done_container_iterator(struct sway_container *con, } output_view_for_each_surface(data->output, con->sway_view, - send_frame_done_iterator2, data); -} - -static void send_frame_done_container(struct send_frame_done_data *data, - struct sway_container *con) { - container_descendants(con, C_VIEW, - send_frame_done_container_iterator, data); + send_frame_done_iterator, data->when); } -static void send_frame_done(struct sway_output *output, struct timespec *when) { +static void send_frame_done_container(struct sway_output *output, + struct sway_container *con, struct timespec *when) { struct send_frame_done_data data = { .output = output, .when = when, }; + container_descendants(con, C_VIEW, + send_frame_done_container_iterator, &data); +} +static void send_frame_done(struct sway_output *output, struct timespec *when) { if (output_has_opaque_overlay_layer_surface(output)) { goto send_frame_overlay; } @@ -349,35 +318,38 @@ static void send_frame_done(struct sway_output *output, struct timespec *when) { if (workspace->current.ws_fullscreen) { if (workspace->current.ws_fullscreen->type == C_VIEW) { send_frame_done_container_iterator( - workspace->current.ws_fullscreen, &data); + workspace->current.ws_fullscreen, when); } else { - send_frame_done_container(&data, workspace->current.ws_fullscreen); + send_frame_done_container(output, workspace->current.ws_fullscreen, + when); } #ifdef HAVE_XWAYLAND - send_frame_done_unmanaged(&data, - &root_container.sway_root->xwayland_unmanaged); + send_frame_done_unmanaged(output, + &root_container.sway_root->xwayland_unmanaged, when); #endif } else { send_frame_done_layer(output, - &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &data); + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], when); send_frame_done_layer(output, - &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], &data); + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], when); - send_frame_done_container(&data, workspace); - send_frame_done_container(&data, workspace->sway_workspace->floating); + send_frame_done_container(output, workspace, when); + send_frame_done_container(output, workspace->sway_workspace->floating, + when); #ifdef HAVE_XWAYLAND - send_frame_done_unmanaged(&data, - &root_container.sway_root->xwayland_unmanaged); + send_frame_done_unmanaged(output, + &root_container.sway_root->xwayland_unmanaged, when); #endif send_frame_done_layer(output, - &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &data); + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], when); } send_frame_overlay: send_frame_done_layer(output, - &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], &data); - send_frame_done_drag_icons(&data, &root_container.sway_root->drag_icons); + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], when); + send_frame_done_drag_icons(output, &root_container.sway_root->drag_icons, + when); } static void damage_handle_frame(struct wl_listener *listener, void *data) { @@ -412,68 +384,11 @@ void output_damage_whole(struct sway_output *output) { wlr_output_damage_add_whole(output->damage); } -struct damage_data { - struct root_geometry root_geo; - struct sway_output *output; - bool whole; -}; - -static void damage_surface_iterator(struct wlr_surface *surface, int sx, int sy, - void *_data) { - struct damage_data *data = _data; - struct sway_output *output = data->output; - float rotation = data->root_geo.rotation; - bool whole = data->whole; - - struct wlr_box box; - bool intersects = output_get_surface_box(&data->root_geo, data->output, surface, - sx, sy, &box); - if (!intersects) { - return; - } - - scale_box(&box, output->wlr_output->scale); - - int center_x = box.x + box.width/2; - int center_y = box.y + box.height/2; - - if (pixman_region32_not_empty(&surface->buffer_damage)) { - enum wl_output_transform transform = - wlr_output_transform_invert(surface->current.transform); - - pixman_region32_t damage; - pixman_region32_init(&damage); - pixman_region32_copy(&damage, &surface->buffer_damage); - wlr_region_transform(&damage, &damage, transform, - surface->current.buffer_width, surface->current.buffer_height); - wlr_region_scale(&damage, &damage, - output->wlr_output->scale / (float)surface->current.scale); - if (ceil(output->wlr_output->scale) > surface->current.scale) { - // When scaling up a surface, it'll become blurry so we need to - // expand the damage region - wlr_region_expand(&damage, &damage, - ceil(output->wlr_output->scale) - surface->current.scale); - } - pixman_region32_translate(&damage, box.x, box.y); - wlr_region_rotated_bounds(&damage, &damage, rotation, - center_x, center_y); - wlr_output_damage_add(output->damage, &damage); - pixman_region32_fini(&damage); - } - - if (whole) { - wlr_box_rotated_bounds(&box, rotation, &box); - wlr_output_damage_add_box(output->damage, &box); - } - - wlr_output_schedule_frame(output->wlr_output); -} - -static void damage_surface_iterator2(struct sway_output *output, +static void damage_surface_iterator(struct sway_output *output, struct wlr_surface *surface, struct wlr_box *_box, float rotation, void *_data) { - struct damage_data *data = _data; - bool whole = data->whole; + bool *data = _data; + bool whole = *data; struct wlr_box box = *_box; scale_box(&box, output->wlr_output->scale); @@ -515,13 +430,8 @@ static void damage_surface_iterator2(struct sway_output *output, void output_damage_surface(struct sway_output *output, double ox, double oy, struct wlr_surface *surface, bool whole) { - struct damage_data data = { - .output = output, - .whole = whole, - }; - - output_surface_for_each_surface(surface, ox, oy, &data.root_geo, - damage_surface_iterator, &data); + output_surface_for_each_surface(output, surface, ox, oy, 0, + damage_surface_iterator, &whole); } static void output_damage_view(struct sway_output *output, @@ -534,12 +444,7 @@ static void output_damage_view(struct sway_output *output, return; } - struct damage_data data = { - .output = output, - .whole = whole, - }; - - output_view_for_each_surface(output, view, damage_surface_iterator2, &data); + output_view_for_each_surface(output, view, damage_surface_iterator, &whole); } void output_damage_from_view(struct sway_output *output, diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 18d076df..f25055b8 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -29,10 +29,7 @@ #include "sway/tree/workspace.h" struct render_data { - struct root_geometry root_geo; - struct sway_output *output; pixman_region32_t *damage; - struct sway_view *view; float alpha; }; @@ -92,38 +89,7 @@ damage_finish: pixman_region32_fini(&damage); } -static void render_surface_iterator(struct wlr_surface *surface, int sx, int sy, - void *_data) { - struct render_data *data = _data; - struct wlr_output *wlr_output = data->output->wlr_output; - float rotation = data->root_geo.rotation; - pixman_region32_t *output_damage = data->damage; - float alpha = data->alpha; - - struct wlr_texture *texture = wlr_surface_get_texture(surface); - if (!texture) { - return; - } - - struct wlr_box box; - bool intersects = output_get_surface_box(&data->root_geo, data->output, - surface, sx, sy, &box); - if (!intersects) { - return; - } - - scale_box(&box, wlr_output->scale); - - float matrix[9]; - enum wl_output_transform transform = - wlr_output_transform_invert(surface->current.transform); - wlr_matrix_project_box(matrix, &box, transform, rotation, - wlr_output->transform_matrix); - - render_texture(wlr_output, output_damage, texture, &box, matrix, alpha); -} - -static void render_surface_iterator2(struct sway_output *output, +static void render_surface_iterator(struct sway_output *output, struct wlr_surface *surface, struct wlr_box *_box, float rotation, void *_data) { struct render_data *data = _data; @@ -151,36 +117,33 @@ static void render_surface_iterator2(struct sway_output *output, static void render_layer(struct sway_output *output, pixman_region32_t *damage, struct wl_list *layer_surfaces) { struct render_data data = { - .output = output, .damage = damage, .alpha = 1.0f, }; output_layer_for_each_surface(output, layer_surfaces, - render_surface_iterator2, &data); + render_surface_iterator, &data); } #ifdef HAVE_XWAYLAND static void render_unmanaged(struct sway_output *output, pixman_region32_t *damage, struct wl_list *unmanaged) { struct render_data data = { - .output = output, .damage = damage, .alpha = 1.0f, }; output_unmanaged_for_each_surface(output, unmanaged, - render_surface_iterator2, &data); + render_surface_iterator, &data); } #endif static void render_drag_icons(struct sway_output *output, pixman_region32_t *damage, struct wl_list *drag_icons) { struct render_data data = { - .output = output, .damage = damage, .alpha = 1.0f, }; output_drag_icons_for_each_surface(output, drag_icons, - render_surface_iterator2, &data); + render_surface_iterator, &data); } static void render_rect(struct wlr_output *wlr_output, @@ -226,12 +189,10 @@ static void premultiply_alpha(float color[4], float opacity) { static void render_view_surfaces(struct sway_view *view, struct sway_output *output, pixman_region32_t *damage, float alpha) { struct render_data data = { - .output = output, .damage = damage, - .view = view, .alpha = alpha, }; - output_view_for_each_surface(output, view, render_surface_iterator2, &data); + output_view_for_each_surface(output, view, render_surface_iterator, &data); } static void render_saved_view(struct sway_view *view, -- cgit v1.2.3 From de86d65627e96cffe77f4abf11c4a0b982326ff9 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Tue, 31 Jul 2018 18:41:30 +1000 Subject: Fix popups Fixes the render and container_at order for popups. Fixes #2210 For rendering: * render_view_surfaces has been renamed to render_view_toplevels * render_view_toplevels now uses output_surface_for_each_surface (which is now public), as that function uses wlr_surface_for_each_surface which doesn't descend into popups * Views now have a for_each_popup iterator, which is used by the renderer to render the focused view's popups * When rendering a popup, toplevels (xdg subsurfaces) of that popup are also rendered For sending frame done, the logic has been updated to match the rendering logic: * send_frame_done_container no longer descends into popups * for_each_popup is used to send frame done to the focused view's popups and their child toplevels For container_at: * floating_container_at is now static, which means it had to be moved higher in the file. * container_at now considers popups for the focused view before checking containers. * tiling_container_at has been introduced, so that it doesn't call container_at recursively (it would check popups recursively if it did) --- include/sway/output.h | 8 +++ include/sway/tree/container.h | 11 +--- include/sway/tree/view.h | 11 ++++ sway/desktop/output.c | 52 +++++++++++++++- sway/desktop/render.c | 37 ++++++++++-- sway/desktop/xdg_shell.c | 9 +++ sway/desktop/xdg_shell_v6.c | 10 ++++ sway/input/cursor.c | 3 - sway/tree/container.c | 134 ++++++++++++++++++++++++++++++------------ sway/tree/view.c | 10 ++++ 10 files changed, 228 insertions(+), 57 deletions(-) (limited to 'sway/desktop/render.c') diff --git a/include/sway/output.h b/include/sway/output.h index 6283db68..80dcd37b 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -67,10 +67,18 @@ struct sway_container *output_get_active_workspace(struct sway_output *output); void output_render(struct sway_output *output, struct timespec *when, pixman_region32_t *damage); +void output_surface_for_each_surface(struct sway_output *output, + struct wlr_surface *surface, double ox, double oy, + sway_surface_iterator_func_t iterator, void *user_data); + void output_view_for_each_surface(struct sway_output *output, struct sway_view *view, sway_surface_iterator_func_t iterator, void *user_data); +void output_view_for_each_popup(struct sway_output *output, + struct sway_view *view, sway_surface_iterator_func_t iterator, + void *user_data); + void output_layer_for_each_surface(struct sway_output *output, struct wl_list *layer_surfaces, sway_surface_iterator_func_t iterator, void *user_data); diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index d4a42a71..12ff8a5a 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -230,17 +230,10 @@ struct sway_container *container_parent(struct sway_container *container, * surface-local coordinates of the given layout coordinates if the container * is a view and the view contains a surface at those coordinates. */ -struct sway_container *container_at(struct sway_container *container, - double ox, double oy, struct wlr_surface **surface, +struct sway_container *container_at(struct sway_container *workspace, + double lx, double ly, struct wlr_surface **surface, double *sx, double *sy); -/** - * Same as container_at, but only checks floating views and expects coordinates - * to be layout coordinates, as that's what floating views use. - */ -struct sway_container *floating_container_at(double lx, double ly, - struct wlr_surface **surface, double *sx, double *sy); - /** * Apply the function for each descendant of the container breadth first. */ diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 0152ed55..9f6d36fe 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -47,6 +47,8 @@ struct sway_view_impl { bool (*has_client_side_decorations)(struct sway_view *view); void (*for_each_surface)(struct sway_view *view, wlr_surface_iterator_func_t iterator, void *user_data); + void (*for_each_popup)(struct sway_view *view, + wlr_surface_iterator_func_t iterator, void *user_data); void (*close)(struct sway_view *view); void (*destroy)(struct sway_view *view); }; @@ -248,9 +250,18 @@ void view_close(struct sway_view *view); void view_damage_from(struct sway_view *view); +/** + * Iterate all surfaces of a view (toplevels + popups). + */ void view_for_each_surface(struct sway_view *view, wlr_surface_iterator_func_t iterator, void *user_data); +/** + * Iterate all popups recursively. + */ +void view_for_each_popup(struct sway_view *view, + wlr_surface_iterator_func_t iterator, void *user_data); + // view implementation void view_init(struct sway_view *view, enum sway_view_type type, diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 31b53213..4c9d978c 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -119,7 +119,7 @@ static void output_for_each_surface_iterator(struct wlr_surface *surface, data->user_data); } -static void output_surface_for_each_surface(struct sway_output *output, +void output_surface_for_each_surface(struct sway_output *output, struct wlr_surface *surface, double ox, double oy, sway_surface_iterator_func_t iterator, void *user_data) { struct surface_iterator_data data = { @@ -155,6 +155,23 @@ void output_view_for_each_surface(struct sway_output *output, output_for_each_surface_iterator, &data); } +void output_view_for_each_popup(struct sway_output *output, + struct sway_view *view, sway_surface_iterator_func_t iterator, + void *user_data) { + struct surface_iterator_data data = { + .user_iterator = iterator, + .user_data = user_data, + .output = output, + .ox = view->swayc->current.view_x - output->swayc->current.swayc_x, + .oy = view->swayc->current.view_y - output->swayc->current.swayc_y, + .width = view->swayc->current.view_width, + .height = view->swayc->current.view_height, + .rotation = 0, // TODO + }; + + view_for_each_popup(view, output_for_each_surface_iterator, &data); +} + void output_layer_for_each_surface(struct sway_output *output, struct wl_list *layer_surfaces, sway_surface_iterator_func_t iterator, void *user_data) { @@ -295,8 +312,9 @@ static void send_frame_done_container_iterator(struct sway_container *con, return; } - output_view_for_each_surface(data->output, con->sway_view, - send_frame_done_iterator, data->when); + // Toplevels only + output_surface_for_each_surface(data->output, con->sway_view->surface, + con->x, con->y, send_frame_done_iterator, data->when); } static void send_frame_done_container(struct sway_output *output, @@ -309,6 +327,27 @@ static void send_frame_done_container(struct sway_output *output, send_frame_done_container_iterator, &data); } +static void send_frame_done_popup_iterator(struct sway_output *output, + struct wlr_surface *surface, struct wlr_box *box, float rotation, + void *data) { + // Send frame done to this popup's surface + send_frame_done_iterator(output, surface, box, rotation, data); + + // Send frame done to this popup's child toplevels + output_surface_for_each_surface(output, surface, box->x, box->y, + send_frame_done_iterator, data); +} + +static void send_frame_done_popups(struct sway_output *output, + struct sway_view *view, struct timespec *when) { + struct send_frame_done_data data = { + .output = output, + .when = when, + }; + output_view_for_each_popup(output, view, + send_frame_done_popup_iterator, &data); +} + static void send_frame_done(struct sway_output *output, struct timespec *when) { if (output_has_opaque_overlay_layer_surface(output)) { goto send_frame_overlay; @@ -346,6 +385,13 @@ static void send_frame_done(struct sway_output *output, struct timespec *when) { &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], when); } + struct sway_seat *seat = input_manager_current_seat(input_manager); + struct sway_container *focus = seat_get_focus(seat); + if (focus && focus->type == C_VIEW) { + send_frame_done_popups(output, focus->sway_view, when); + } + + send_frame_overlay: send_frame_done_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], when); diff --git a/sway/desktop/render.c b/sway/desktop/render.c index f25055b8..ea4361f2 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -186,13 +186,36 @@ static void premultiply_alpha(float color[4], float opacity) { color[2] *= color[3]; } -static void render_view_surfaces(struct sway_view *view, +static void render_view_toplevels(struct sway_view *view, struct sway_output *output, pixman_region32_t *damage, float alpha) { struct render_data data = { .damage = damage, .alpha = alpha, }; - output_view_for_each_surface(output, view, render_surface_iterator, &data); + // Render all toplevels without descending into popups + output_surface_for_each_surface(output, view->surface, + view->swayc->current.view_x, view->swayc->current.view_y, + render_surface_iterator, &data); +} + +static void render_popup_iterator(struct sway_output *output, + struct wlr_surface *surface, struct wlr_box *box, float rotation, + void *data) { + // Render this popup's surface + render_surface_iterator(output, surface, box, rotation, data); + + // Render this popup's child toplevels + output_surface_for_each_surface(output, surface, box->x, box->y, + render_surface_iterator, data); +} + +static void render_view_popups(struct sway_view *view, + struct sway_output *output, pixman_region32_t *damage, float alpha) { + struct render_data data = { + .damage = damage, + .alpha = alpha, + }; + output_view_for_each_popup(output, view, render_popup_iterator, &data); } static void render_saved_view(struct sway_view *view, @@ -241,7 +264,7 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage, if (view->swayc->instructions->length) { render_saved_view(view, output, damage, view->swayc->alpha); } else { - render_view_surfaces(view, output, damage, view->swayc->alpha); + render_view_toplevels(view, output, damage, view->swayc->alpha); } if (view->using_csd) { @@ -845,7 +868,7 @@ void output_render(struct sway_output *output, struct timespec *when, render_saved_view(fullscreen_con->sway_view, output, damage, 1.0f); } else { - render_view_surfaces(fullscreen_con->sway_view, + render_view_toplevels(fullscreen_con->sway_view, output, damage, 1.0f); } } else { @@ -881,6 +904,12 @@ void output_render(struct sway_output *output, struct timespec *when, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); } + struct sway_seat *seat = input_manager_current_seat(input_manager); + struct sway_container *focus = seat_get_focus(seat); + if (focus && focus->type == C_VIEW) { + render_view_popups(focus->sway_view, output, damage, focus->alpha); + } + render_overlay: render_layer(output, damage, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index e6e1527e..9f94bd74 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -179,6 +179,14 @@ static void for_each_surface(struct sway_view *view, user_data); } +static void for_each_popup(struct sway_view *view, + wlr_surface_iterator_func_t iterator, void *user_data) { + if (xdg_shell_view_from_view(view) == NULL) { + return; + } + wlr_xdg_surface_for_each_popup(view->wlr_xdg_surface, iterator, user_data); +} + static void _close(struct sway_view *view) { if (xdg_shell_view_from_view(view) == NULL) { return; @@ -207,6 +215,7 @@ static const struct sway_view_impl view_impl = { .set_fullscreen = set_fullscreen, .wants_floating = wants_floating, .for_each_surface = for_each_surface, + .for_each_popup = for_each_popup, .close = _close, .destroy = destroy, }; diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 5feee3e4..4502c386 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -175,6 +175,15 @@ static void for_each_surface(struct sway_view *view, user_data); } +static void for_each_popup(struct sway_view *view, + wlr_surface_iterator_func_t iterator, void *user_data) { + if (xdg_shell_v6_view_from_view(view) == NULL) { + return; + } + wlr_xdg_surface_v6_for_each_popup(view->wlr_xdg_surface_v6, iterator, + user_data); +} + static void _close(struct sway_view *view) { if (xdg_shell_v6_view_from_view(view) == NULL) { return; @@ -203,6 +212,7 @@ static const struct sway_view_impl view_impl = { .set_fullscreen = set_fullscreen, .wants_floating = wants_floating, .for_each_surface = for_each_surface, + .for_each_popup = for_each_popup, .close = _close, .destroy = destroy, }; diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 96ac7b33..ad4b1718 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -109,9 +109,6 @@ static struct sway_container *container_at_coords( } struct sway_container *c; - if ((c = floating_container_at(lx, ly, surface, sx, sy))) { - return c; - } if ((c = container_at(ws, lx, ly, surface, sx, sy))) { return c; } diff --git a/sway/tree/container.c b/sway/tree/container.c index 4e85021d..b5fefd17 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -561,10 +561,15 @@ static struct sway_container *container_at_view(struct sway_container *swayc, *sx = _sx; *sy = _sy; *surface = _surface; + return swayc; } - return swayc; + return NULL; } +static struct sway_container *tiling_container_at( + struct sway_container *con, double lx, double ly, + struct wlr_surface **surface, double *sx, double *sy); + /** * container_at for a container with layout L_TABBED. */ @@ -591,7 +596,7 @@ static struct sway_container *container_at_tabbed(struct sway_container *parent, // Surfaces struct sway_container *current = seat_get_active_child(seat, parent); - return container_at(current, lx, ly, surface, sx, sy); + return tiling_container_at(current, lx, ly, surface, sx, sy); } /** @@ -616,7 +621,7 @@ static struct sway_container *container_at_stacked( // Surfaces struct sway_container *current = seat_get_active_child(seat, parent); - return container_at(current, lx, ly, surface, sx, sy); + return tiling_container_at(current, lx, ly, surface, sx, sy); } /** @@ -634,45 +639,13 @@ static struct sway_container *container_at_linear(struct sway_container *parent, .height = child->height, }; if (wlr_box_contains_point(&box, lx, ly)) { - return container_at(child, lx, ly, surface, sx, sy); + return tiling_container_at(child, lx, ly, surface, sx, sy); } } return NULL; } -struct sway_container *container_at(struct sway_container *parent, - double lx, double ly, - struct wlr_surface **surface, double *sx, double *sy) { - if (!sway_assert(parent->type >= C_WORKSPACE, - "Expected workspace or deeper")) { - return NULL; - } - if (parent->type == C_VIEW) { - return container_at_view(parent, lx, ly, surface, sx, sy); - } - if (!parent->children->length) { - return NULL; - } - - switch (parent->layout) { - case L_HORIZ: - case L_VERT: - return container_at_linear(parent, lx, ly, surface, sx, sy); - case L_TABBED: - return container_at_tabbed(parent, lx, ly, surface, sx, sy); - case L_STACKED: - return container_at_stacked(parent, lx, ly, surface, sx, sy); - case L_FLOATING: - sway_assert(false, "Didn't expect to see floating here"); - return NULL; - case L_NONE: - return NULL; - } - - return NULL; -} - -struct sway_container *floating_container_at(double lx, double ly, +static struct sway_container *floating_container_at(double lx, double ly, struct wlr_surface **surface, double *sx, double *sy) { for (int i = 0; i < root_container.children->length; ++i) { struct sway_container *output = root_container.children->items[i]; @@ -694,7 +667,8 @@ struct sway_container *floating_container_at(double lx, double ly, .height = floater->height, }; if (wlr_box_contains_point(&box, lx, ly)) { - return container_at(floater, lx, ly, surface, sx, sy); + return tiling_container_at(floater, lx, ly, + surface, sx, sy); } } } @@ -702,6 +676,90 @@ struct sway_container *floating_container_at(double lx, double ly, return NULL; } +static struct sway_container *tiling_container_at( + struct sway_container *con, double lx, double ly, + struct wlr_surface **surface, double *sx, double *sy) { + if (con->type == C_VIEW) { + return container_at_view(con, lx, ly, surface, sx, sy); + } + if (!con->children->length) { + return NULL; + } + + switch (con->layout) { + case L_HORIZ: + case L_VERT: + return container_at_linear(con, lx, ly, surface, sx, sy); + case L_TABBED: + return container_at_tabbed(con, lx, ly, surface, sx, sy); + case L_STACKED: + return container_at_stacked(con, lx, ly, surface, sx, sy); + case L_FLOATING: + sway_assert(false, "Didn't expect to see floating here"); + return NULL; + case L_NONE: + return NULL; + } + return NULL; +} + +static bool surface_is_popup(struct wlr_surface *surface) { + if (wlr_surface_is_xdg_surface(surface)) { + struct wlr_xdg_surface *xdg_surface = + wlr_xdg_surface_from_wlr_surface(surface); + while (xdg_surface) { + if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP) { + return true; + } + xdg_surface = xdg_surface->toplevel->parent; + } + return false; + } + + if (wlr_surface_is_xdg_surface_v6(surface)) { + struct wlr_xdg_surface_v6 *xdg_surface_v6 = + wlr_xdg_surface_v6_from_wlr_surface(surface); + while (xdg_surface_v6) { + if (xdg_surface_v6->role == WLR_XDG_SURFACE_V6_ROLE_POPUP) { + return true; + } + xdg_surface_v6 = xdg_surface_v6->toplevel->parent; + } + return false; + } + + return false; +} + +struct sway_container *container_at(struct sway_container *workspace, + double lx, double ly, + struct wlr_surface **surface, double *sx, double *sy) { + if (!sway_assert(workspace->type == C_WORKSPACE, "Expected a workspace")) { + return NULL; + } + struct sway_container *c; + // Focused view's popups + struct sway_seat *seat = input_manager_current_seat(input_manager); + struct sway_container *focus = + seat_get_focus_inactive(seat, &root_container); + if (focus && focus->type == C_VIEW) { + container_at_view(focus, lx, ly, surface, sx, sy); + if (*surface && surface_is_popup(*surface)) { + return focus; + } + *surface = NULL; + } + // Floating + if ((c = floating_container_at(lx, ly, surface, sx, sy))) { + return c; + } + // Tiling + if ((c = tiling_container_at(workspace, lx, ly, surface, sx, sy))) { + return c; + } + return NULL; +} + void container_for_each_descendant_dfs(struct sway_container *container, void (*f)(struct sway_container *container, void *data), void *data) { diff --git a/sway/tree/view.c b/sway/tree/view.c index 8f54cc11..c1207821 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -332,6 +332,16 @@ void view_for_each_surface(struct sway_view *view, } } +void view_for_each_popup(struct sway_view *view, + wlr_surface_iterator_func_t iterator, void *user_data) { + if (!view->surface) { + return; + } + if (view->impl->for_each_popup) { + view->impl->for_each_popup(view, iterator, user_data); + } +} + static void view_subsurface_create(struct sway_view *view, struct wlr_subsurface *subsurface); -- cgit v1.2.3 From d10ccc1eb144e4de2477398f6b11753f6b7df70b Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Wed, 1 Aug 2018 16:23:11 +1000 Subject: Correctly track saved surfaces during multiple transactions Fixes #2364. Suppose a view is 600px wide, and we tell it to resize to 601px during a resize operation. We create a transaction, save the 600px buffer and send the configure. This buffer is saved into the associated instruction, and is rendered while we wait for the view to commit a 601px buffer. Before the view commits the 601px buffer, suppose we tell it to resize to 602px. The new transaction will also save the buffer, but it's still the 600px buffer because we haven't received a new one yet. Then suppose the view commits its original 601px buffer. This completes the first transaction, so we apply the 601px width to the container. There's still the second (now only) transaction remaining, so we render the saved buffer from that. But this is still the 600px buffer, and we believe it's 601px. Whoops. The problem here is we can't stack buffers like this. So this commit removes the saved buffer from the instructions, places it in the view instead, and re-saves the latest buffer every time the view completes a transaction and still has further pending transactions. As saved buffers are now specific to views rather than instructions, the functions for saving and removing the saved buffer have been moved to view.c. The calls to save and restore the buffer have been relocated to more appropriate functions too, favouring transaction_commit and transaction_apply rather than transaction_add_container and transaction_destroy. --- include/sway/desktop/transaction.h | 13 ---------- include/sway/tree/view.h | 7 ++++++ sway/desktop/render.c | 16 ++++++------ sway/desktop/transaction.c | 51 +++++++++----------------------------- sway/tree/view.c | 20 +++++++++++++++ 5 files changed, 46 insertions(+), 61 deletions(-) (limited to 'sway/desktop/render.c') diff --git a/include/sway/desktop/transaction.h b/include/sway/desktop/transaction.h index cee4afed..56361d94 100644 --- a/include/sway/desktop/transaction.h +++ b/include/sway/desktop/transaction.h @@ -42,17 +42,4 @@ void transaction_notify_view_ready(struct sway_view *view, uint32_t serial); void transaction_notify_view_ready_by_size(struct sway_view *view, int width, int height); -/** - * Get the saved texture that should be rendered for a view. - * - * The addresses pointed at by the width and height pointers will be populated - * with the surface's dimensions, which may be different to the texture's - * dimensions if output scaling is used. - * - * This function should only be called if it is known that the view has - * instructions. - */ -struct wlr_texture *transaction_get_saved_texture(struct sway_view *view, - int *width, int *height); - #endif diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 0152ed55..0f9b0bb2 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -82,6 +82,9 @@ struct sway_view { bool allow_request_urgent; struct wl_event_source *urgent_timer; + struct wlr_buffer *saved_buffer; + int saved_buffer_width, saved_buffer_height; + bool destroying; list_t *executed_criteria; // struct criteria * @@ -323,4 +326,8 @@ void view_set_urgent(struct sway_view *view, bool enable); bool view_is_urgent(struct sway_view *view); +void view_remove_saved_buffer(struct sway_view *view); + +void view_save_buffer(struct sway_view *view); + #endif diff --git a/sway/desktop/render.c b/sway/desktop/render.c index f25055b8..f0e47c95 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -199,17 +199,14 @@ static void render_saved_view(struct sway_view *view, struct sway_output *output, pixman_region32_t *damage, float alpha) { struct wlr_output *wlr_output = output->wlr_output; - int width, height; - struct wlr_texture *texture = - transaction_get_saved_texture(view, &width, &height); - if (!texture) { + if (!view->saved_buffer || !view->saved_buffer->texture) { return; } struct wlr_box box = { .x = view->swayc->current.view_x - output->swayc->current.swayc_x, .y = view->swayc->current.view_y - output->swayc->current.swayc_y, - .width = width, - .height = height, + .width = view->saved_buffer_width, + .height = view->saved_buffer_height, }; struct wlr_box output_box = { @@ -229,7 +226,8 @@ static void render_saved_view(struct sway_view *view, wlr_matrix_project_box(matrix, &box, WL_OUTPUT_TRANSFORM_NORMAL, 0, wlr_output->transform_matrix); - render_texture(wlr_output, damage, texture, &box, matrix, alpha); + render_texture(wlr_output, damage, view->saved_buffer->texture, + &box, matrix, alpha); } /** @@ -238,7 +236,7 @@ static void render_saved_view(struct sway_view *view, static void render_view(struct sway_output *output, pixman_region32_t *damage, struct sway_container *con, struct border_colors *colors) { struct sway_view *view = con->sway_view; - if (view->swayc->instructions->length) { + if (view->saved_buffer) { render_saved_view(view, output, damage, view->swayc->alpha); } else { render_view_surfaces(view, output, damage, view->swayc->alpha); @@ -841,7 +839,7 @@ void output_render(struct sway_output *output, struct timespec *when, // TODO: handle views smaller than the output if (fullscreen_con->type == C_VIEW) { - if (fullscreen_con->instructions->length) { + if (fullscreen_con->sway_view->saved_buffer) { render_saved_view(fullscreen_con->sway_view, output, damage, 1.0f); } else { diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c index 7975366e..94070363 100644 --- a/sway/desktop/transaction.c +++ b/sway/desktop/transaction.c @@ -41,8 +41,6 @@ struct sway_transaction_instruction { struct sway_transaction *transaction; struct sway_container *container; struct sway_container_state state; - struct wlr_buffer *saved_buffer; - int saved_buffer_width, saved_buffer_height; uint32_t serial; bool ready; }; @@ -57,27 +55,6 @@ static struct sway_transaction *transaction_create() { return transaction; } -static void remove_saved_view_buffer( - struct sway_transaction_instruction *instruction) { - if (instruction->saved_buffer) { - wlr_buffer_unref(instruction->saved_buffer); - instruction->saved_buffer = NULL; - } -} - -static void save_view_buffer(struct sway_view *view, - struct sway_transaction_instruction *instruction) { - if (!sway_assert(instruction->saved_buffer == NULL, - "Didn't expect instruction to have a saved buffer already")) { - remove_saved_view_buffer(instruction); - } - if (view->surface && wlr_surface_has_buffer(view->surface)) { - instruction->saved_buffer = wlr_buffer_ref(view->surface->buffer); - instruction->saved_buffer_width = view->surface->current.width; - instruction->saved_buffer_height = view->surface->current.height; - } -} - static void transaction_destroy(struct sway_transaction *transaction) { // Free instructions for (int i = 0; i < transaction->instructions->length; ++i) { @@ -93,7 +70,6 @@ static void transaction_destroy(struct sway_transaction *transaction) { if (con->destroying && !con->instructions->length) { container_free(con); } - remove_saved_view_buffer(instruction); free(instruction); } list_free(transaction->instructions); @@ -158,9 +134,6 @@ static void transaction_add_container(struct sway_transaction *transaction, copy_pending_state(container, &instruction->state); - if (container->type == C_VIEW) { - save_view_buffer(container->sway_view, instruction); - } list_add(transaction->instructions, instruction); } @@ -220,6 +193,15 @@ static void transaction_apply(struct sway_transaction *transaction) { memcpy(&container->current, &instruction->state, sizeof(struct sway_container_state)); + + if (container->type == C_VIEW) { + if (container->sway_view->saved_buffer) { + view_remove_saved_buffer(container->sway_view); + } + if (container->instructions->length > 1) { + view_save_buffer(container->sway_view); + } + } } } @@ -294,6 +276,9 @@ static void transaction_commit(struct sway_transaction *transaction) { // mapping and its default geometry doesn't intersect an output. struct timespec when; wlr_surface_send_frame_done(con->sway_view->surface, &when); + if (!con->sway_view->saved_buffer) { + view_save_buffer(con->sway_view); + } } list_add(con->instructions, instruction); } @@ -400,18 +385,6 @@ void transaction_notify_view_ready_by_size(struct sway_view *view, } } -struct wlr_texture *transaction_get_saved_texture(struct sway_view *view, - int *width, int *height) { - struct sway_transaction_instruction *instruction = - view->swayc->instructions->items[0]; - if (!instruction->saved_buffer) { - return NULL; - } - *width = instruction->saved_buffer_width; - *height = instruction->saved_buffer_height; - return instruction->saved_buffer->texture; -} - void transaction_commit_dirty(void) { if (!server.dirty_containers->length) { return; diff --git a/sway/tree/view.c b/sway/tree/view.c index 8f54cc11..0dbd3812 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include "config.h" #ifdef HAVE_XWAYLAND @@ -1070,3 +1071,22 @@ void view_set_urgent(struct sway_view *view, bool enable) { bool view_is_urgent(struct sway_view *view) { return view->urgent.tv_sec || view->urgent.tv_nsec; } + +void view_remove_saved_buffer(struct sway_view *view) { + if (!sway_assert(view->saved_buffer, "Expected a saved buffer")) { + return; + } + wlr_buffer_unref(view->saved_buffer); + view->saved_buffer = NULL; +} + +void view_save_buffer(struct sway_view *view) { + if (!sway_assert(!view->saved_buffer, "Didn't expect saved buffer")) { + view_remove_saved_buffer(view); + } + if (view->surface && wlr_surface_has_buffer(view->surface)) { + view->saved_buffer = wlr_buffer_ref(view->surface->buffer); + view->saved_buffer_width = view->surface->current.width; + view->saved_buffer_height = view->surface->current.height; + } +} -- cgit v1.2.3 From 9aa258d33a9baa42895214da7e82f4568fcb8f76 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 2 Aug 2018 09:05:46 -0400 Subject: Revert "Fix popups" This reverts commit de86d65627e96cffe77f4abf11c4a0b982326ff9. --- include/sway/output.h | 8 --- include/sway/tree/container.h | 11 +++- include/sway/tree/view.h | 11 ---- sway/desktop/output.c | 19 +----- sway/desktop/render.c | 37 ++---------- sway/desktop/xdg_shell.c | 9 --- sway/desktop/xdg_shell_v6.c | 10 ---- sway/input/cursor.c | 3 + sway/tree/container.c | 134 ++++++++++++------------------------------ sway/tree/view.c | 10 ---- 10 files changed, 55 insertions(+), 197 deletions(-) (limited to 'sway/desktop/render.c') diff --git a/include/sway/output.h b/include/sway/output.h index 80dcd37b..6283db68 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -67,18 +67,10 @@ struct sway_container *output_get_active_workspace(struct sway_output *output); void output_render(struct sway_output *output, struct timespec *when, pixman_region32_t *damage); -void output_surface_for_each_surface(struct sway_output *output, - struct wlr_surface *surface, double ox, double oy, - sway_surface_iterator_func_t iterator, void *user_data); - void output_view_for_each_surface(struct sway_output *output, struct sway_view *view, sway_surface_iterator_func_t iterator, void *user_data); -void output_view_for_each_popup(struct sway_output *output, - struct sway_view *view, sway_surface_iterator_func_t iterator, - void *user_data); - void output_layer_for_each_surface(struct sway_output *output, struct wl_list *layer_surfaces, sway_surface_iterator_func_t iterator, void *user_data); diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 12ff8a5a..d4a42a71 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -230,10 +230,17 @@ struct sway_container *container_parent(struct sway_container *container, * surface-local coordinates of the given layout coordinates if the container * is a view and the view contains a surface at those coordinates. */ -struct sway_container *container_at(struct sway_container *workspace, - double lx, double ly, struct wlr_surface **surface, +struct sway_container *container_at(struct sway_container *container, + double ox, double oy, struct wlr_surface **surface, double *sx, double *sy); +/** + * Same as container_at, but only checks floating views and expects coordinates + * to be layout coordinates, as that's what floating views use. + */ +struct sway_container *floating_container_at(double lx, double ly, + struct wlr_surface **surface, double *sx, double *sy); + /** * Apply the function for each descendant of the container breadth first. */ diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 37fd02bc..6d8c3e6c 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -47,8 +47,6 @@ struct sway_view_impl { bool (*has_client_side_decorations)(struct sway_view *view); void (*for_each_surface)(struct sway_view *view, wlr_surface_iterator_func_t iterator, void *user_data); - void (*for_each_popup)(struct sway_view *view, - wlr_surface_iterator_func_t iterator, void *user_data); void (*close)(struct sway_view *view); void (*close_popups)(struct sway_view *view); void (*destroy)(struct sway_view *view); @@ -256,18 +254,9 @@ void view_close_popups(struct sway_view *view); void view_damage_from(struct sway_view *view); -/** - * Iterate all surfaces of a view (toplevels + popups). - */ void view_for_each_surface(struct sway_view *view, wlr_surface_iterator_func_t iterator, void *user_data); -/** - * Iterate all popups recursively. - */ -void view_for_each_popup(struct sway_view *view, - wlr_surface_iterator_func_t iterator, void *user_data); - // view implementation void view_init(struct sway_view *view, enum sway_view_type type, diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 66747a3f..31b53213 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -119,7 +119,7 @@ static void output_for_each_surface_iterator(struct wlr_surface *surface, data->user_data); } -void output_surface_for_each_surface(struct sway_output *output, +static void output_surface_for_each_surface(struct sway_output *output, struct wlr_surface *surface, double ox, double oy, sway_surface_iterator_func_t iterator, void *user_data) { struct surface_iterator_data data = { @@ -155,23 +155,6 @@ void output_view_for_each_surface(struct sway_output *output, output_for_each_surface_iterator, &data); } -void output_view_for_each_popup(struct sway_output *output, - struct sway_view *view, sway_surface_iterator_func_t iterator, - void *user_data) { - struct surface_iterator_data data = { - .user_iterator = iterator, - .user_data = user_data, - .output = output, - .ox = view->swayc->current.view_x - output->swayc->current.swayc_x, - .oy = view->swayc->current.view_y - output->swayc->current.swayc_y, - .width = view->swayc->current.view_width, - .height = view->swayc->current.view_height, - .rotation = 0, // TODO - }; - - view_for_each_popup(view, output_for_each_surface_iterator, &data); -} - void output_layer_for_each_surface(struct sway_output *output, struct wl_list *layer_surfaces, sway_surface_iterator_func_t iterator, void *user_data) { diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 1f374740..f0e47c95 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -186,36 +186,13 @@ static void premultiply_alpha(float color[4], float opacity) { color[2] *= color[3]; } -static void render_view_toplevels(struct sway_view *view, +static void render_view_surfaces(struct sway_view *view, struct sway_output *output, pixman_region32_t *damage, float alpha) { struct render_data data = { .damage = damage, .alpha = alpha, }; - // Render all toplevels without descending into popups - output_surface_for_each_surface(output, view->surface, - view->swayc->current.view_x, view->swayc->current.view_y, - render_surface_iterator, &data); -} - -static void render_popup_iterator(struct sway_output *output, - struct wlr_surface *surface, struct wlr_box *box, float rotation, - void *data) { - // Render this popup's surface - render_surface_iterator(output, surface, box, rotation, data); - - // Render this popup's child toplevels - output_surface_for_each_surface(output, surface, box->x, box->y, - render_surface_iterator, data); -} - -static void render_view_popups(struct sway_view *view, - struct sway_output *output, pixman_region32_t *damage, float alpha) { - struct render_data data = { - .damage = damage, - .alpha = alpha, - }; - output_view_for_each_popup(output, view, render_popup_iterator, &data); + output_view_for_each_surface(output, view, render_surface_iterator, &data); } static void render_saved_view(struct sway_view *view, @@ -262,7 +239,7 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage, if (view->saved_buffer) { render_saved_view(view, output, damage, view->swayc->alpha); } else { - render_view_toplevels(view, output, damage, view->swayc->alpha); + render_view_surfaces(view, output, damage, view->swayc->alpha); } if (view->using_csd) { @@ -866,7 +843,7 @@ void output_render(struct sway_output *output, struct timespec *when, render_saved_view(fullscreen_con->sway_view, output, damage, 1.0f); } else { - render_view_toplevels(fullscreen_con->sway_view, + render_view_surfaces(fullscreen_con->sway_view, output, damage, 1.0f); } } else { @@ -902,12 +879,6 @@ void output_render(struct sway_output *output, struct timespec *when, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); } - struct sway_seat *seat = input_manager_current_seat(input_manager); - struct sway_container *focus = seat_get_focus(seat); - if (focus && focus->type == C_VIEW) { - render_view_popups(focus->sway_view, output, damage, focus->alpha); - } - render_overlay: render_layer(output, damage, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index b364663d..9d6b27e5 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -179,14 +179,6 @@ static void for_each_surface(struct sway_view *view, user_data); } -static void for_each_popup(struct sway_view *view, - wlr_surface_iterator_func_t iterator, void *user_data) { - if (xdg_shell_view_from_view(view) == NULL) { - return; - } - wlr_xdg_surface_for_each_popup(view->wlr_xdg_surface, iterator, user_data); -} - static void _close(struct sway_view *view) { if (xdg_shell_view_from_view(view) == NULL) { return; @@ -227,7 +219,6 @@ static const struct sway_view_impl view_impl = { .set_fullscreen = set_fullscreen, .wants_floating = wants_floating, .for_each_surface = for_each_surface, - .for_each_popup = for_each_popup, .close = _close, .close_popups = close_popups, .destroy = destroy, diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index ffea03ad..6e4aae62 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -175,15 +175,6 @@ static void for_each_surface(struct sway_view *view, user_data); } -static void for_each_popup(struct sway_view *view, - wlr_surface_iterator_func_t iterator, void *user_data) { - if (xdg_shell_v6_view_from_view(view) == NULL) { - return; - } - wlr_xdg_surface_v6_for_each_popup(view->wlr_xdg_surface_v6, iterator, - user_data); -} - static void _close(struct sway_view *view) { if (xdg_shell_v6_view_from_view(view) == NULL) { return; @@ -224,7 +215,6 @@ static const struct sway_view_impl view_impl = { .set_fullscreen = set_fullscreen, .wants_floating = wants_floating, .for_each_surface = for_each_surface, - .for_each_popup = for_each_popup, .close = _close, .close_popups = close_popups, .destroy = destroy, diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 79f6ec46..d6fdc1da 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -109,6 +109,9 @@ static struct sway_container *container_at_coords( } struct sway_container *c; + if ((c = floating_container_at(lx, ly, surface, sx, sy))) { + return c; + } if ((c = container_at(ws, lx, ly, surface, sx, sy))) { return c; } diff --git a/sway/tree/container.c b/sway/tree/container.c index b980c5e9..b6ff4d30 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -569,15 +569,10 @@ static struct sway_container *container_at_view(struct sway_container *swayc, *sx = _sx; *sy = _sy; *surface = _surface; - return swayc; } - return NULL; + return swayc; } -static struct sway_container *tiling_container_at( - struct sway_container *con, double lx, double ly, - struct wlr_surface **surface, double *sx, double *sy); - /** * container_at for a container with layout L_TABBED. */ @@ -604,7 +599,7 @@ static struct sway_container *container_at_tabbed(struct sway_container *parent, // Surfaces struct sway_container *current = seat_get_active_child(seat, parent); - return tiling_container_at(current, lx, ly, surface, sx, sy); + return container_at(current, lx, ly, surface, sx, sy); } /** @@ -629,7 +624,7 @@ static struct sway_container *container_at_stacked( // Surfaces struct sway_container *current = seat_get_active_child(seat, parent); - return tiling_container_at(current, lx, ly, surface, sx, sy); + return container_at(current, lx, ly, surface, sx, sy); } /** @@ -647,13 +642,45 @@ static struct sway_container *container_at_linear(struct sway_container *parent, .height = child->height, }; if (wlr_box_contains_point(&box, lx, ly)) { - return tiling_container_at(child, lx, ly, surface, sx, sy); + return container_at(child, lx, ly, surface, sx, sy); } } return NULL; } -static struct sway_container *floating_container_at(double lx, double ly, +struct sway_container *container_at(struct sway_container *parent, + double lx, double ly, + struct wlr_surface **surface, double *sx, double *sy) { + if (!sway_assert(parent->type >= C_WORKSPACE, + "Expected workspace or deeper")) { + return NULL; + } + if (parent->type == C_VIEW) { + return container_at_view(parent, lx, ly, surface, sx, sy); + } + if (!parent->children->length) { + return NULL; + } + + switch (parent->layout) { + case L_HORIZ: + case L_VERT: + return container_at_linear(parent, lx, ly, surface, sx, sy); + case L_TABBED: + return container_at_tabbed(parent, lx, ly, surface, sx, sy); + case L_STACKED: + return container_at_stacked(parent, lx, ly, surface, sx, sy); + case L_FLOATING: + sway_assert(false, "Didn't expect to see floating here"); + return NULL; + case L_NONE: + return NULL; + } + + return NULL; +} + +struct sway_container *floating_container_at(double lx, double ly, struct wlr_surface **surface, double *sx, double *sy) { for (int i = 0; i < root_container.children->length; ++i) { struct sway_container *output = root_container.children->items[i]; @@ -675,8 +702,7 @@ static struct sway_container *floating_container_at(double lx, double ly, .height = floater->height, }; if (wlr_box_contains_point(&box, lx, ly)) { - return tiling_container_at(floater, lx, ly, - surface, sx, sy); + return container_at(floater, lx, ly, surface, sx, sy); } } } @@ -684,90 +710,6 @@ static struct sway_container *floating_container_at(double lx, double ly, return NULL; } -static struct sway_container *tiling_container_at( - struct sway_container *con, double lx, double ly, - struct wlr_surface **surface, double *sx, double *sy) { - if (con->type == C_VIEW) { - return container_at_view(con, lx, ly, surface, sx, sy); - } - if (!con->children->length) { - return NULL; - } - - switch (con->layout) { - case L_HORIZ: - case L_VERT: - return container_at_linear(con, lx, ly, surface, sx, sy); - case L_TABBED: - return container_at_tabbed(con, lx, ly, surface, sx, sy); - case L_STACKED: - return container_at_stacked(con, lx, ly, surface, sx, sy); - case L_FLOATING: - sway_assert(false, "Didn't expect to see floating here"); - return NULL; - case L_NONE: - return NULL; - } - return NULL; -} - -static bool surface_is_popup(struct wlr_surface *surface) { - if (wlr_surface_is_xdg_surface(surface)) { - struct wlr_xdg_surface *xdg_surface = - wlr_xdg_surface_from_wlr_surface(surface); - while (xdg_surface) { - if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP) { - return true; - } - xdg_surface = xdg_surface->toplevel->parent; - } - return false; - } - - if (wlr_surface_is_xdg_surface_v6(surface)) { - struct wlr_xdg_surface_v6 *xdg_surface_v6 = - wlr_xdg_surface_v6_from_wlr_surface(surface); - while (xdg_surface_v6) { - if (xdg_surface_v6->role == WLR_XDG_SURFACE_V6_ROLE_POPUP) { - return true; - } - xdg_surface_v6 = xdg_surface_v6->toplevel->parent; - } - return false; - } - - return false; -} - -struct sway_container *container_at(struct sway_container *workspace, - double lx, double ly, - struct wlr_surface **surface, double *sx, double *sy) { - if (!sway_assert(workspace->type == C_WORKSPACE, "Expected a workspace")) { - return NULL; - } - struct sway_container *c; - // Focused view's popups - struct sway_seat *seat = input_manager_current_seat(input_manager); - struct sway_container *focus = - seat_get_focus_inactive(seat, &root_container); - if (focus && focus->type == C_VIEW) { - container_at_view(focus, lx, ly, surface, sx, sy); - if (*surface && surface_is_popup(*surface)) { - return focus; - } - *surface = NULL; - } - // Floating - if ((c = floating_container_at(lx, ly, surface, sx, sy))) { - return c; - } - // Tiling - if ((c = tiling_container_at(workspace, lx, ly, surface, sx, sy))) { - return c; - } - return NULL; -} - void container_for_each_descendant_dfs(struct sway_container *container, void (*f)(struct sway_container *container, void *data), void *data) { diff --git a/sway/tree/view.c b/sway/tree/view.c index 97318daa..27a6a8bd 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -339,16 +339,6 @@ void view_for_each_surface(struct sway_view *view, } } -void view_for_each_popup(struct sway_view *view, - wlr_surface_iterator_func_t iterator, void *user_data) { - if (!view->surface) { - return; - } - if (view->impl->for_each_popup) { - view->impl->for_each_popup(view, iterator, user_data); - } -} - static void view_subsurface_create(struct sway_view *view, struct wlr_subsurface *subsurface); -- cgit v1.2.3 From 8392eae40f17e550338b8b7058d8e9c1a6ad4f78 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Thu, 2 Aug 2018 23:30:26 +1000 Subject: Revert "Revert "Fix popups"" This reverts commit 9aa258d33a9baa42895214da7e82f4568fcb8f76. Reverting the revert, so that popups can be fixed. --- include/sway/output.h | 8 +++ include/sway/tree/container.h | 11 +--- include/sway/tree/view.h | 11 ++++ sway/desktop/output.c | 19 +++++- sway/desktop/render.c | 37 ++++++++++-- sway/desktop/xdg_shell.c | 9 +++ sway/desktop/xdg_shell_v6.c | 10 ++++ sway/input/cursor.c | 3 - sway/tree/container.c | 134 ++++++++++++++++++++++++++++++------------ sway/tree/view.c | 10 ++++ 10 files changed, 197 insertions(+), 55 deletions(-) (limited to 'sway/desktop/render.c') diff --git a/include/sway/output.h b/include/sway/output.h index 6283db68..80dcd37b 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -67,10 +67,18 @@ struct sway_container *output_get_active_workspace(struct sway_output *output); void output_render(struct sway_output *output, struct timespec *when, pixman_region32_t *damage); +void output_surface_for_each_surface(struct sway_output *output, + struct wlr_surface *surface, double ox, double oy, + sway_surface_iterator_func_t iterator, void *user_data); + void output_view_for_each_surface(struct sway_output *output, struct sway_view *view, sway_surface_iterator_func_t iterator, void *user_data); +void output_view_for_each_popup(struct sway_output *output, + struct sway_view *view, sway_surface_iterator_func_t iterator, + void *user_data); + void output_layer_for_each_surface(struct sway_output *output, struct wl_list *layer_surfaces, sway_surface_iterator_func_t iterator, void *user_data); diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index d4a42a71..12ff8a5a 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -230,17 +230,10 @@ struct sway_container *container_parent(struct sway_container *container, * surface-local coordinates of the given layout coordinates if the container * is a view and the view contains a surface at those coordinates. */ -struct sway_container *container_at(struct sway_container *container, - double ox, double oy, struct wlr_surface **surface, +struct sway_container *container_at(struct sway_container *workspace, + double lx, double ly, struct wlr_surface **surface, double *sx, double *sy); -/** - * Same as container_at, but only checks floating views and expects coordinates - * to be layout coordinates, as that's what floating views use. - */ -struct sway_container *floating_container_at(double lx, double ly, - struct wlr_surface **surface, double *sx, double *sy); - /** * Apply the function for each descendant of the container breadth first. */ diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 6d8c3e6c..37fd02bc 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -47,6 +47,8 @@ struct sway_view_impl { bool (*has_client_side_decorations)(struct sway_view *view); void (*for_each_surface)(struct sway_view *view, wlr_surface_iterator_func_t iterator, void *user_data); + void (*for_each_popup)(struct sway_view *view, + wlr_surface_iterator_func_t iterator, void *user_data); void (*close)(struct sway_view *view); void (*close_popups)(struct sway_view *view); void (*destroy)(struct sway_view *view); @@ -254,9 +256,18 @@ void view_close_popups(struct sway_view *view); void view_damage_from(struct sway_view *view); +/** + * Iterate all surfaces of a view (toplevels + popups). + */ void view_for_each_surface(struct sway_view *view, wlr_surface_iterator_func_t iterator, void *user_data); +/** + * Iterate all popups recursively. + */ +void view_for_each_popup(struct sway_view *view, + wlr_surface_iterator_func_t iterator, void *user_data); + // view implementation void view_init(struct sway_view *view, enum sway_view_type type, diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 31b53213..66747a3f 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -119,7 +119,7 @@ static void output_for_each_surface_iterator(struct wlr_surface *surface, data->user_data); } -static void output_surface_for_each_surface(struct sway_output *output, +void output_surface_for_each_surface(struct sway_output *output, struct wlr_surface *surface, double ox, double oy, sway_surface_iterator_func_t iterator, void *user_data) { struct surface_iterator_data data = { @@ -155,6 +155,23 @@ void output_view_for_each_surface(struct sway_output *output, output_for_each_surface_iterator, &data); } +void output_view_for_each_popup(struct sway_output *output, + struct sway_view *view, sway_surface_iterator_func_t iterator, + void *user_data) { + struct surface_iterator_data data = { + .user_iterator = iterator, + .user_data = user_data, + .output = output, + .ox = view->swayc->current.view_x - output->swayc->current.swayc_x, + .oy = view->swayc->current.view_y - output->swayc->current.swayc_y, + .width = view->swayc->current.view_width, + .height = view->swayc->current.view_height, + .rotation = 0, // TODO + }; + + view_for_each_popup(view, output_for_each_surface_iterator, &data); +} + void output_layer_for_each_surface(struct sway_output *output, struct wl_list *layer_surfaces, sway_surface_iterator_func_t iterator, void *user_data) { diff --git a/sway/desktop/render.c b/sway/desktop/render.c index f0e47c95..1f374740 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -186,13 +186,36 @@ static void premultiply_alpha(float color[4], float opacity) { color[2] *= color[3]; } -static void render_view_surfaces(struct sway_view *view, +static void render_view_toplevels(struct sway_view *view, struct sway_output *output, pixman_region32_t *damage, float alpha) { struct render_data data = { .damage = damage, .alpha = alpha, }; - output_view_for_each_surface(output, view, render_surface_iterator, &data); + // Render all toplevels without descending into popups + output_surface_for_each_surface(output, view->surface, + view->swayc->current.view_x, view->swayc->current.view_y, + render_surface_iterator, &data); +} + +static void render_popup_iterator(struct sway_output *output, + struct wlr_surface *surface, struct wlr_box *box, float rotation, + void *data) { + // Render this popup's surface + render_surface_iterator(output, surface, box, rotation, data); + + // Render this popup's child toplevels + output_surface_for_each_surface(output, surface, box->x, box->y, + render_surface_iterator, data); +} + +static void render_view_popups(struct sway_view *view, + struct sway_output *output, pixman_region32_t *damage, float alpha) { + struct render_data data = { + .damage = damage, + .alpha = alpha, + }; + output_view_for_each_popup(output, view, render_popup_iterator, &data); } static void render_saved_view(struct sway_view *view, @@ -239,7 +262,7 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage, if (view->saved_buffer) { render_saved_view(view, output, damage, view->swayc->alpha); } else { - render_view_surfaces(view, output, damage, view->swayc->alpha); + render_view_toplevels(view, output, damage, view->swayc->alpha); } if (view->using_csd) { @@ -843,7 +866,7 @@ void output_render(struct sway_output *output, struct timespec *when, render_saved_view(fullscreen_con->sway_view, output, damage, 1.0f); } else { - render_view_surfaces(fullscreen_con->sway_view, + render_view_toplevels(fullscreen_con->sway_view, output, damage, 1.0f); } } else { @@ -879,6 +902,12 @@ void output_render(struct sway_output *output, struct timespec *when, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); } + struct sway_seat *seat = input_manager_current_seat(input_manager); + struct sway_container *focus = seat_get_focus(seat); + if (focus && focus->type == C_VIEW) { + render_view_popups(focus->sway_view, output, damage, focus->alpha); + } + render_overlay: render_layer(output, damage, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index 9d6b27e5..b364663d 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -179,6 +179,14 @@ static void for_each_surface(struct sway_view *view, user_data); } +static void for_each_popup(struct sway_view *view, + wlr_surface_iterator_func_t iterator, void *user_data) { + if (xdg_shell_view_from_view(view) == NULL) { + return; + } + wlr_xdg_surface_for_each_popup(view->wlr_xdg_surface, iterator, user_data); +} + static void _close(struct sway_view *view) { if (xdg_shell_view_from_view(view) == NULL) { return; @@ -219,6 +227,7 @@ static const struct sway_view_impl view_impl = { .set_fullscreen = set_fullscreen, .wants_floating = wants_floating, .for_each_surface = for_each_surface, + .for_each_popup = for_each_popup, .close = _close, .close_popups = close_popups, .destroy = destroy, diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 6e4aae62..ffea03ad 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -175,6 +175,15 @@ static void for_each_surface(struct sway_view *view, user_data); } +static void for_each_popup(struct sway_view *view, + wlr_surface_iterator_func_t iterator, void *user_data) { + if (xdg_shell_v6_view_from_view(view) == NULL) { + return; + } + wlr_xdg_surface_v6_for_each_popup(view->wlr_xdg_surface_v6, iterator, + user_data); +} + static void _close(struct sway_view *view) { if (xdg_shell_v6_view_from_view(view) == NULL) { return; @@ -215,6 +224,7 @@ static const struct sway_view_impl view_impl = { .set_fullscreen = set_fullscreen, .wants_floating = wants_floating, .for_each_surface = for_each_surface, + .for_each_popup = for_each_popup, .close = _close, .close_popups = close_popups, .destroy = destroy, diff --git a/sway/input/cursor.c b/sway/input/cursor.c index d6fdc1da..79f6ec46 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -109,9 +109,6 @@ static struct sway_container *container_at_coords( } struct sway_container *c; - if ((c = floating_container_at(lx, ly, surface, sx, sy))) { - return c; - } if ((c = container_at(ws, lx, ly, surface, sx, sy))) { return c; } diff --git a/sway/tree/container.c b/sway/tree/container.c index b6ff4d30..b980c5e9 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -569,10 +569,15 @@ static struct sway_container *container_at_view(struct sway_container *swayc, *sx = _sx; *sy = _sy; *surface = _surface; + return swayc; } - return swayc; + return NULL; } +static struct sway_container *tiling_container_at( + struct sway_container *con, double lx, double ly, + struct wlr_surface **surface, double *sx, double *sy); + /** * container_at for a container with layout L_TABBED. */ @@ -599,7 +604,7 @@ static struct sway_container *container_at_tabbed(struct sway_container *parent, // Surfaces struct sway_container *current = seat_get_active_child(seat, parent); - return container_at(current, lx, ly, surface, sx, sy); + return tiling_container_at(current, lx, ly, surface, sx, sy); } /** @@ -624,7 +629,7 @@ static struct sway_container *container_at_stacked( // Surfaces struct sway_container *current = seat_get_active_child(seat, parent); - return container_at(current, lx, ly, surface, sx, sy); + return tiling_container_at(current, lx, ly, surface, sx, sy); } /** @@ -642,45 +647,13 @@ static struct sway_container *container_at_linear(struct sway_container *parent, .height = child->height, }; if (wlr_box_contains_point(&box, lx, ly)) { - return container_at(child, lx, ly, surface, sx, sy); + return tiling_container_at(child, lx, ly, surface, sx, sy); } } return NULL; } -struct sway_container *container_at(struct sway_container *parent, - double lx, double ly, - struct wlr_surface **surface, double *sx, double *sy) { - if (!sway_assert(parent->type >= C_WORKSPACE, - "Expected workspace or deeper")) { - return NULL; - } - if (parent->type == C_VIEW) { - return container_at_view(parent, lx, ly, surface, sx, sy); - } - if (!parent->children->length) { - return NULL; - } - - switch (parent->layout) { - case L_HORIZ: - case L_VERT: - return container_at_linear(parent, lx, ly, surface, sx, sy); - case L_TABBED: - return container_at_tabbed(parent, lx, ly, surface, sx, sy); - case L_STACKED: - return container_at_stacked(parent, lx, ly, surface, sx, sy); - case L_FLOATING: - sway_assert(false, "Didn't expect to see floating here"); - return NULL; - case L_NONE: - return NULL; - } - - return NULL; -} - -struct sway_container *floating_container_at(double lx, double ly, +static struct sway_container *floating_container_at(double lx, double ly, struct wlr_surface **surface, double *sx, double *sy) { for (int i = 0; i < root_container.children->length; ++i) { struct sway_container *output = root_container.children->items[i]; @@ -702,7 +675,8 @@ struct sway_container *floating_container_at(double lx, double ly, .height = floater->height, }; if (wlr_box_contains_point(&box, lx, ly)) { - return container_at(floater, lx, ly, surface, sx, sy); + return tiling_container_at(floater, lx, ly, + surface, sx, sy); } } } @@ -710,6 +684,90 @@ struct sway_container *floating_container_at(double lx, double ly, return NULL; } +static struct sway_container *tiling_container_at( + struct sway_container *con, double lx, double ly, + struct wlr_surface **surface, double *sx, double *sy) { + if (con->type == C_VIEW) { + return container_at_view(con, lx, ly, surface, sx, sy); + } + if (!con->children->length) { + return NULL; + } + + switch (con->layout) { + case L_HORIZ: + case L_VERT: + return container_at_linear(con, lx, ly, surface, sx, sy); + case L_TABBED: + return container_at_tabbed(con, lx, ly, surface, sx, sy); + case L_STACKED: + return container_at_stacked(con, lx, ly, surface, sx, sy); + case L_FLOATING: + sway_assert(false, "Didn't expect to see floating here"); + return NULL; + case L_NONE: + return NULL; + } + return NULL; +} + +static bool surface_is_popup(struct wlr_surface *surface) { + if (wlr_surface_is_xdg_surface(surface)) { + struct wlr_xdg_surface *xdg_surface = + wlr_xdg_surface_from_wlr_surface(surface); + while (xdg_surface) { + if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP) { + return true; + } + xdg_surface = xdg_surface->toplevel->parent; + } + return false; + } + + if (wlr_surface_is_xdg_surface_v6(surface)) { + struct wlr_xdg_surface_v6 *xdg_surface_v6 = + wlr_xdg_surface_v6_from_wlr_surface(surface); + while (xdg_surface_v6) { + if (xdg_surface_v6->role == WLR_XDG_SURFACE_V6_ROLE_POPUP) { + return true; + } + xdg_surface_v6 = xdg_surface_v6->toplevel->parent; + } + return false; + } + + return false; +} + +struct sway_container *container_at(struct sway_container *workspace, + double lx, double ly, + struct wlr_surface **surface, double *sx, double *sy) { + if (!sway_assert(workspace->type == C_WORKSPACE, "Expected a workspace")) { + return NULL; + } + struct sway_container *c; + // Focused view's popups + struct sway_seat *seat = input_manager_current_seat(input_manager); + struct sway_container *focus = + seat_get_focus_inactive(seat, &root_container); + if (focus && focus->type == C_VIEW) { + container_at_view(focus, lx, ly, surface, sx, sy); + if (*surface && surface_is_popup(*surface)) { + return focus; + } + *surface = NULL; + } + // Floating + if ((c = floating_container_at(lx, ly, surface, sx, sy))) { + return c; + } + // Tiling + if ((c = tiling_container_at(workspace, lx, ly, surface, sx, sy))) { + return c; + } + return NULL; +} + void container_for_each_descendant_dfs(struct sway_container *container, void (*f)(struct sway_container *container, void *data), void *data) { diff --git a/sway/tree/view.c b/sway/tree/view.c index 27a6a8bd..97318daa 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -339,6 +339,16 @@ void view_for_each_surface(struct sway_view *view, } } +void view_for_each_popup(struct sway_view *view, + wlr_surface_iterator_func_t iterator, void *user_data) { + if (!view->surface) { + return; + } + if (view->impl->for_each_popup) { + view->impl->for_each_popup(view, iterator, user_data); + } +} + static void view_subsurface_create(struct sway_view *view, struct wlr_subsurface *subsurface); -- cgit v1.2.3 From 787f08da7ff9ecb325def2e3a44dc5043d7e2753 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Thu, 2 Aug 2018 23:34:26 +1000 Subject: Convert toplevel coordinates to output-local --- sway/desktop/render.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sway/desktop/render.c') diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 1f374740..cdac9c72 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -194,7 +194,8 @@ static void render_view_toplevels(struct sway_view *view, }; // Render all toplevels without descending into popups output_surface_for_each_surface(output, view->surface, - view->swayc->current.view_x, view->swayc->current.view_y, + view->swayc->current.view_x - output->wlr_output->lx, + view->swayc->current.view_y - output->wlr_output->ly, render_surface_iterator, &data); } -- cgit v1.2.3