diff --git a/include/sway/server.h b/include/sway/server.h index adb62cda..7dbce0b7 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -116,6 +117,7 @@ struct sway_server { struct wl_listener output_power_manager_set_mode; struct wlr_input_method_manager_v2 *input_method; struct wlr_text_input_manager_v3 *text_input; + struct wlr_ext_foreign_toplevel_list_v1 *foreign_toplevel_list; struct wlr_foreign_toplevel_manager_v1 *foreign_toplevel_manager; struct wlr_content_type_manager_v1 *content_type_manager_v1; struct wlr_data_control_manager_v1 *data_control_manager_v1; diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 3e5a9bfe..5f6c2ead 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -84,6 +84,9 @@ struct sway_view { // transaction state. Updated on every commit. struct wlr_box geometry; + struct wlr_ext_foreign_toplevel_handle_v1 *ext_foreign_toplevel; + struct wl_listener ext_foreign_destroy; + struct wlr_foreign_toplevel_handle_v1 *foreign_toplevel; struct wl_listener foreign_activate_request; struct wl_listener foreign_fullscreen_request; @@ -284,6 +287,8 @@ struct sway_view *view_from_wlr_xwayland_surface( #endif struct sway_view *view_from_wlr_surface(struct wlr_surface *surface); +void view_update_app_id(struct sway_view *view); + /** * Re-read the view's title property and update any relevant title bars. * The force argument makes it recreate the title bars even if the title hasn't diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index 7cdd97c8..d3f69a15 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -337,6 +337,7 @@ static void handle_set_app_id(struct wl_listener *listener, void *data) { struct sway_xdg_shell_view *xdg_shell_view = wl_container_of(listener, xdg_shell_view, set_app_id); struct sway_view *view = &xdg_shell_view->view; + view_update_app_id(view); view_execute_criteria(view); } diff --git a/sway/server.c b/sway/server.c index cc20e89d..8b8ccce9 100644 --- a/sway/server.c +++ b/sway/server.c @@ -60,6 +60,7 @@ #define SWAY_XDG_SHELL_VERSION 2 #define SWAY_LAYER_SHELL_VERSION 4 +#define SWAY_FOREIGN_TOPLEVEL_LIST_VERSION 1 bool allow_unsupported_gpu = false; @@ -93,6 +94,7 @@ static bool is_privileged(const struct wl_global *global) { global == server.output_manager_v1->global || global == server.output_power_manager_v1->global || global == server.input_method->global || + global == server.foreign_toplevel_list->global || global == server.foreign_toplevel_manager->global || global == server.data_control_manager_v1->global || global == server.screencopy_manager_v1->global || @@ -289,6 +291,8 @@ bool server_init(struct sway_server *server) { &server->output_power_manager_set_mode); server->input_method = wlr_input_method_manager_v2_create(server->wl_display); server->text_input = wlr_text_input_manager_v3_create(server->wl_display); + server->foreign_toplevel_list = + wlr_ext_foreign_toplevel_list_v1_create(server->wl_display, SWAY_FOREIGN_TOPLEVEL_LIST_VERSION); server->foreign_toplevel_manager = wlr_foreign_toplevel_manager_v1_create(server->wl_display); diff --git a/sway/tree/view.c b/sway/tree/view.c index d6984178..aa87a0bb 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -582,6 +582,14 @@ static struct sway_workspace *select_workspace(struct sway_view *view) { return NULL; } +static void update_ext_foreign_toplevel(struct sway_view *view) { + struct wlr_ext_foreign_toplevel_handle_v1_state toplevel_state = { + .app_id = view_get_app_id(view), + .title = view_get_title(view), + }; + wlr_ext_foreign_toplevel_handle_v1_update_state(view->ext_foreign_toplevel, &toplevel_state); +} + static bool should_focus(struct sway_view *view) { struct sway_seat *seat = input_manager_current_seat(); struct sway_container *prev_con = seat_get_focused_container(seat); @@ -751,6 +759,15 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface, } } + struct wlr_ext_foreign_toplevel_handle_v1_state foreign_toplevel_state = { + .app_id = view_get_app_id(view), + .title = view_get_title(view), + }; + view->ext_foreign_toplevel = + wlr_ext_foreign_toplevel_handle_v1_create(server.foreign_toplevel_list, &foreign_toplevel_state); + wl_signal_add(&view->ext_foreign_toplevel->events.destroy, + &view->ext_foreign_destroy); + view->foreign_toplevel = wlr_foreign_toplevel_handle_v1_create(server.foreign_toplevel_manager); view->foreign_activate_request.notify = handle_foreign_activate_request; @@ -828,6 +845,10 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface, input_manager_set_focus(&view->container->node); } + if (view->ext_foreign_toplevel) { + update_ext_foreign_toplevel(view); + } + const char *app_id; const char *class; if ((app_id = view_get_app_id(view)) != NULL) { @@ -847,6 +868,11 @@ void view_unmap(struct sway_view *view) { view->urgent_timer = NULL; } + if (view->ext_foreign_toplevel) { + wlr_ext_foreign_toplevel_handle_v1_destroy(view->ext_foreign_toplevel); + view->ext_foreign_toplevel = NULL; + } + if (view->foreign_toplevel) { wlr_foreign_toplevel_handle_v1_destroy(view->foreign_toplevel); view->foreign_toplevel = NULL; @@ -1014,6 +1040,18 @@ static size_t parse_title_format(struct sway_view *view, char *buffer) { return len; } +void view_update_app_id(struct sway_view *view) { + const char *app_id = view_get_app_id(view); + + if (view->foreign_toplevel && app_id) { + wlr_foreign_toplevel_handle_v1_set_app_id(view->foreign_toplevel, app_id); + } + + if (view->ext_foreign_toplevel) { + update_ext_foreign_toplevel(view); + } +} + void view_update_title(struct sway_view *view, bool force) { const char *title = view_get_title(view); @@ -1060,6 +1098,10 @@ void view_update_title(struct sway_view *view, bool force) { if (view->foreign_toplevel && title) { wlr_foreign_toplevel_handle_v1_set_title(view->foreign_toplevel, title); } + + if (view->ext_foreign_toplevel) { + update_ext_foreign_toplevel(view); + } } bool view_is_visible(struct sway_view *view) {