From 042ea266a5ddbd5c20584f285f8fad402272ed8d Mon Sep 17 00:00:00 2001 From: Johan Malm Date: Thu, 5 Aug 2021 12:18:10 +0100 Subject: [PATCH] Add simple foreign toplevel implementation --- include/labwc.h | 12 ++++++++++++ src/foreign.c | 11 +++++++++++ src/meson.build | 1 + src/server.c | 3 +++ src/view.c | 12 +++++++++++- src/xdg.c | 25 +++++++++++++++++++++++++ src/xwayland.c | 29 ++++++++++++++++++++++++++++- 7 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 src/foreign.c diff --git a/include/labwc.h b/include/labwc.h index f95fb201..61933bcf 100644 --- a/include/labwc.h +++ b/include/labwc.h @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -118,6 +119,8 @@ struct server { struct wl_listener output_manager_apply; struct wlr_output_configuration_v1 *pending_output_config; + struct wlr_foreign_toplevel_manager_v1 *foreign_toplevel_manager; + /* Set when in cycle (alt-tab) mode */ struct view *cycle_view; @@ -152,6 +155,7 @@ struct view_impl { wlr_surface_iterator_func_t iterator, void *data); void (*for_each_surface)(struct view *view, wlr_surface_iterator_func_t iterator, void *data); + const char *(*get_string_prop)(struct view *view, const char *prop); void (*map)(struct view *view); void (*move)(struct view *view, double x, double y); void (*unmap)(struct view *view); @@ -219,6 +223,8 @@ struct view { struct wlr_box box; /* remember geo so we know when to update */ } ssd; + struct wlr_foreign_toplevel_handle_v1 *toplevel_handle; + struct wl_listener map; struct wl_listener unmap; struct wl_listener destroy; @@ -227,6 +233,7 @@ struct view { struct wl_listener request_resize; struct wl_listener request_configure; struct wl_listener request_maximize; + struct wl_listener set_title; struct wl_listener new_popup; /* xdg-shell only */ struct wl_listener new_subsurface; /* xdg-shell only */ }; @@ -290,6 +297,8 @@ void view_move_resize(struct view *view, struct wlr_box geo); void view_move(struct view *view, double x, double y); void view_minimize(struct view *view); void view_unminimize(struct view *view); +/* view_wlr_output - return the output that a view is mostly on */ +struct wlr_output *view_wlr_output(struct view *view); void view_center(struct view *view); void view_maximize(struct view *view, bool maximize); void view_toggle_maximize(struct view *view); @@ -298,6 +307,9 @@ void view_for_each_surface(struct view *view, void view_for_each_popup_surface(struct view *view, wlr_surface_iterator_func_t iterator, void *data); void view_move_to_edge(struct view *view, const char *direction); +void view_update_title(struct view *view); + +void foreign_toplevel_handle_create(struct view *view); void desktop_set_focus_view_only(struct seat *seat, struct view *view); void desktop_focus_view(struct seat *seat, struct view *view); diff --git a/src/foreign.c b/src/foreign.c new file mode 100644 index 00000000..e6d5dec2 --- /dev/null +++ b/src/foreign.c @@ -0,0 +1,11 @@ +#include "labwc.h" + +void +foreign_toplevel_handle_create(struct view *view) +{ + view->toplevel_handle = wlr_foreign_toplevel_handle_v1_create( + view->server->foreign_toplevel_manager); + view_update_title(view); + wlr_foreign_toplevel_handle_v1_output_enter(view->toplevel_handle, + view_wlr_output(view)); +} diff --git a/src/meson.build b/src/meson.build index df65dcc8..6d014505 100644 --- a/src/meson.build +++ b/src/meson.build @@ -3,6 +3,7 @@ labwc_sources = files( 'cursor.c', 'damage.c', 'desktop.c', + 'foreign.c', 'interactive.c', 'keyboard.c', 'layers.c', diff --git a/src/server.c b/src/server.c index 66f1aec8..e091426b 100644 --- a/src/server.c +++ b/src/server.c @@ -196,6 +196,9 @@ server_init(struct server *server) wlr_gamma_control_manager_v1_create(server->wl_display); wlr_primary_selection_v1_device_manager_create(server->wl_display); + server->foreign_toplevel_manager = + wlr_foreign_toplevel_manager_v1_create(server->wl_display); + layers_init(server); #if HAVE_XWAYLAND diff --git a/src/view.c b/src/view.c index 42d720f7..0b29ad72 100644 --- a/src/view.c +++ b/src/view.c @@ -36,7 +36,7 @@ view_unminimize(struct view *view) } /* view_wlr_output - return the output that a view is mostly on */ -static struct wlr_output * +struct wlr_output * view_wlr_output(struct view *view) { return wlr_output_layout_output_at(view->server->output_layout, @@ -163,3 +163,13 @@ view_move_to_edge(struct view *view, const char *direction) } view_move(view, x, y); } + +void +view_update_title(struct view *view) +{ + const char *title = view->impl->get_string_prop(view, "title"); + if (!view->toplevel_handle || !title) { + return; + } + wlr_foreign_toplevel_handle_v1_set_title(view->toplevel_handle, title); +} diff --git a/src/xdg.c b/src/xdg.c index 1f9d0105..827bc3fc 100644 --- a/src/xdg.c +++ b/src/xdg.c @@ -91,6 +91,9 @@ static void handle_destroy(struct wl_listener *listener, void *data) { struct view *view = wl_container_of(listener, view, destroy); + if (view->toplevel_handle) { + wlr_foreign_toplevel_handle_v1_destroy(view->toplevel_handle); + } wl_list_remove(&view->link); ssd_destroy(view); free(view); @@ -136,6 +139,14 @@ handle_request_maximize(struct wl_listener *listener, void *data) } +static void +handle_set_title(struct wl_listener *listener, void *data) +{ + struct view *view = wl_container_of(listener, view, set_title); + assert(view); + view_update_title(view); +} + static void xdg_toplevel_view_configure(struct view *view, struct wlr_box geo) { @@ -248,6 +259,15 @@ position_xdg_toplevel_view(struct view *view) view->y += view->margin.top - view->padding.top; } +static const char * +xdg_toplevel_view_get_string_prop(struct view *view, const char *prop) +{ + if (!strcmp(prop, "title")) { + return view->xdg_surface->toplevel->title; + } + return "none"; +} + static void xdg_toplevel_view_map(struct view *view) { @@ -260,6 +280,8 @@ xdg_toplevel_view_map(struct view *view) */ view_maximize(view, false); + foreign_toplevel_handle_create(view); + view->ssd.enabled = has_ssd(view); if (view->ssd.enabled) { view->margin = ssd_thickness(view); @@ -308,6 +330,7 @@ static const struct view_impl xdg_toplevel_view_impl = { .close = xdg_toplevel_view_close, .for_each_popup_surface = xdg_toplevel_view_for_each_popup_surface, .for_each_surface = xdg_toplevel_view_for_each_surface, + .get_string_prop = xdg_toplevel_view_get_string_prop, .map = xdg_toplevel_view_map, .move = xdg_toplevel_view_move, .unmap = xdg_toplevel_view_unmap, @@ -349,6 +372,8 @@ xdg_surface_new(struct wl_listener *listener, void *data) wl_signal_add(&toplevel->events.request_resize, &view->request_resize); view->request_maximize.notify = handle_request_maximize; wl_signal_add(&toplevel->events.request_maximize, &view->request_maximize); + view->set_title.notify = handle_set_title; + wl_signal_add(&toplevel->events.set_title, &view->set_title); wl_list_insert(&server->views, &view->link); } diff --git a/src/xwayland.c b/src/xwayland.c index 5c8f0820..c7dfcd10 100644 --- a/src/xwayland.c +++ b/src/xwayland.c @@ -44,6 +44,9 @@ static void handle_destroy(struct wl_listener *listener, void *data) { struct view *view = wl_container_of(listener, view, destroy); + if (view->toplevel_handle) { + wlr_foreign_toplevel_handle_v1_destroy(view->toplevel_handle); + } wl_list_remove(&view->link); wl_list_remove(&view->map.link); wl_list_remove(&view->unmap.link); @@ -64,7 +67,8 @@ handle_request_configure(struct wl_listener *listener, void *data) damage_all_outputs(view->server); } -static void handle_request_maximize(struct wl_listener *listener, void *data) +static void +handle_request_maximize(struct wl_listener *listener, void *data) { struct view *view = wl_container_of(listener, view, request_maximize); @@ -72,6 +76,14 @@ static void handle_request_maximize(struct wl_listener *listener, void *data) view_toggle_maximize(view); } +static void +handle_set_title(struct wl_listener *listener, void *data) +{ + struct view *view = wl_container_of(listener, view, set_title); + assert(view); + view_update_title(view); +} + static void configure(struct view *view, struct wlr_box geo) { @@ -116,6 +128,15 @@ for_each_surface(struct view *view, wlr_surface_iterator_func_t iterator, wlr_surface_for_each_surface(view->surface, iterator, data); } +static const char * +get_string_prop(struct view *view, const char *prop) +{ + if (!strcmp(prop, "title")) { + return view->xwayland_surface->title; + } + return "none"; +} + static bool want_deco(struct view *view) { @@ -157,6 +178,9 @@ map(struct view *view) if (!view->been_mapped) { view_maximize(view, false); + + foreign_toplevel_handle_create(view); + struct wlr_box box = output_usable_area_from_cursor_coords(view->server); view->x = box.x; view->y = box.y; @@ -194,6 +218,7 @@ static const struct view_impl xwl_view_impl = { .configure = configure, .close = _close, .for_each_surface = for_each_surface, + .get_string_prop = get_string_prop, .map = map, .move = move, .unmap = unmap, @@ -235,6 +260,8 @@ xwayland_surface_new(struct wl_listener *listener, void *data) &view->request_configure); view->request_maximize.notify = handle_request_maximize; wl_signal_add(&xsurface->events.request_maximize, &view->request_maximize); + view->set_title.notify = handle_set_title; + wl_signal_add(&xsurface->events.set_title, &view->set_title); wl_list_insert(&view->server->views, &view->link); } -- 2.52.0