From 68a0b669ef2733b19dffa7c5a5ba682a6cc420ab Mon Sep 17 00:00:00 2001 From: DanyLE Date: Sat, 13 Apr 2024 00:25:39 +0200 Subject: [PATCH] improve: better support foreign protocol --- diyac.h | 2 ++ foreign.c | 21 ++++++++++++++++--- view.c | 31 ++++++++++++++++++++++++++++ view.h | 2 ++ xdg.c | 61 ++++++++++++++++++++++++++++++++++++------------------- 5 files changed, 93 insertions(+), 24 deletions(-) diff --git a/diyac.h b/diyac.h index 8db5f7e..17b601c 100644 --- a/diyac.h +++ b/diyac.h @@ -205,6 +205,8 @@ struct diyac_view struct wl_listener set_app_id; // only useful when using SSD struct wl_listener new_popup; + struct wl_listener set_title; + struct foreign_toplevel toplevel; }; diff --git a/foreign.c b/foreign.c index f03e8d9..a49bc5e 100644 --- a/foreign.c +++ b/foreign.c @@ -9,7 +9,6 @@ static void handle_request_minimize(struct wl_listener *listener, void *data) // view_minimize(view, event->minimized); diyac_view_set_mimimize(view, event->minimized); wlr_log(WLR_INFO, "foreign: request minimize"); - } static void handle_request_maximize(struct wl_listener *listener, void *data) @@ -37,7 +36,7 @@ static void handle_request_activate(struct wl_listener *listener, void *data) // struct wlr_foreign_toplevel_handle_v1_activated_event *event = data; /* In a multi-seat world we would select seat based on event->seat here. */ // desktop_focus_view(view, /*raise*/ true); - diyac_focus_view(view,true); + diyac_focus_view(view, true); wlr_log(WLR_INFO, "foreign: request activate"); } @@ -45,7 +44,7 @@ static void handle_request_close(struct wl_listener *listener, void *data) { struct diyac_view *view = wl_container_of(listener, view, toplevel.close); - //view_close(view); + wlr_xdg_toplevel_send_close(view->xdg_toplevel); } static void @@ -94,4 +93,20 @@ void diyac_init_foreign_toplevel(struct diyac_view *view) toplevel->destroy.notify = handle_destroy; wl_signal_add(&toplevel->handle->events.destroy, &toplevel->destroy); + + wlr_foreign_toplevel_handle_v1_output_enter( + view->toplevel.handle, view->output->wlr_output); + //wlr_foreign_toplevel_handle_v1_output_enter + struct wlr_xdg_toplevel *xdg_toplevel = view->xdg_toplevel; + if (!xdg_toplevel->parent) + { + return; + } + struct wlr_xdg_surface *surface = xdg_toplevel->parent->base; + struct diyac_view *parent = surface->data; + if (!parent->toplevel.handle) + { + return; + } + wlr_foreign_toplevel_handle_v1_set_parent(view->toplevel.handle, parent->toplevel.handle); } \ No newline at end of file diff --git a/view.c b/view.c index 9aa812d..fd0b578 100644 --- a/view.c +++ b/view.c @@ -349,4 +349,35 @@ void diyac_view_set_mimimize(struct diyac_view * view, bool activated) // view->requested.minimized = activated; //TODO implement minimize wlr_xdg_surface_schedule_configure(view->xdg_toplevel->base); +} + +void diyac_view_update_title(struct diyac_view * view) +{ + struct wlr_xdg_toplevel *xdg_toplevel = view->xdg_toplevel; + if (!xdg_toplevel) + { + return; + } + const char *title = xdg_toplevel->title; + wlr_log(WLR_INFO, "diyac_view_update_title: %s", title ? title : ""); + if (!view->toplevel.handle || !title) + { + return; + } + wlr_foreign_toplevel_handle_v1_set_title(view->toplevel.handle, title); +} +void diyac_view_update_app_id(struct diyac_view * view) +{ + struct wlr_xdg_toplevel *xdg_toplevel = view->xdg_toplevel; + if (!xdg_toplevel) + { + return; + } + const char *appid = xdg_toplevel->app_id; + wlr_log(WLR_INFO, "diyac_view_update_app_id: %s", appid ? appid : ""); + if (!view->toplevel.handle || !appid) + { + return; + } + wlr_foreign_toplevel_handle_v1_set_app_id(view->toplevel.handle, appid); } \ No newline at end of file diff --git a/view.h b/view.h index f620846..b5ae8a8 100644 --- a/view.h +++ b/view.h @@ -18,4 +18,6 @@ struct wlr_box diyac_view_get_geometry(struct diyac_view *view); void diyac_view_set_maximize(struct diyac_view * view, bool activated); void diyac_view_set_fullscreen(struct diyac_view * view, bool activated); void diyac_view_set_mimimize(struct diyac_view * view, bool activated); +void diyac_view_update_title(struct diyac_view * view); +void diyac_view_update_app_id(struct diyac_view * view); #endif \ No newline at end of file diff --git a/xdg.c b/xdg.c index e45eff3..d8d40a4 100644 --- a/xdg.c +++ b/xdg.c @@ -56,10 +56,10 @@ static void begin_interactive(struct diyac_view *toplevel, static void xdg_toplevel_map(struct wl_listener *listener, void *data) { - + /* Called when the surface is mapped, or ready to display on-screen. */ struct diyac_view *toplevel = wl_container_of(listener, toplevel, map); - if(toplevel->mapped) + if (toplevel->mapped) { return; } @@ -67,13 +67,14 @@ static void xdg_toplevel_map(struct wl_listener *listener, void *data) wlr_xdg_toplevel_set_wm_capabilities(toplevel->xdg_toplevel, WLR_XDG_TOPLEVEL_WM_CAPABILITIES_MAXIMIZE | WLR_XDG_TOPLEVEL_WM_CAPABILITIES_MINIMIZE); - //WLR_XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN + //WLR_XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN */ wlr_xdg_surface_get_geometry(toplevel->xdg_toplevel->base, &toplevel->original); wlr_scene_node_set_enabled(&toplevel->scene_tree->node, true); toplevel->mapped = true; - diyac_init_foreign_toplevel(toplevel); wl_list_insert(&toplevel->server->views, &toplevel->link); + diyac_view_update_app_id(toplevel); + diyac_view_update_title(toplevel); toplevel->original.x = (toplevel->output->usable_area.width - toplevel->original.width) / 2; toplevel->original.y = (toplevel->output->usable_area.height - toplevel->original.height) / 2; if (toplevel->original.width > toplevel->output->usable_area.width) @@ -98,15 +99,15 @@ static void xdg_toplevel_unmap(struct wl_listener *listener, void *data) { diyac_reset_cursor_mode(toplevel->server); } - if(toplevel->state.fullscreen) + if (toplevel->state.fullscreen) { /** * When a client exit during fullscreen mode, the top layer shall * be restored as it is currently disabled - */ + */ wlr_scene_node_set_enabled(&toplevel->output->scenes.top->node, true); } - if(toplevel->server->active_view == toplevel) + if (toplevel->server->active_view == toplevel) { toplevel->server->active_view = NULL; } @@ -114,11 +115,11 @@ static void xdg_toplevel_unmap(struct wl_listener *listener, void *data) if (root && root->mapped) { diyac_focus_view(root, true); - //wlr_log(WLR_INFO, "focus root"); + // wlr_log(WLR_INFO, "focus root"); } else { - //wlr_log(WLR_INFO, "focus topmost"); + // wlr_log(WLR_INFO, "focus topmost"); diyac_focus_topmost_view(toplevel->server, true); } @@ -169,7 +170,7 @@ static void xdg_toplevel_request_fullscreen(struct wl_listener *listener, void * { struct diyac_view *toplevel = wl_container_of(listener, toplevel, request_fullscreen); - diyac_view_set_fullscreen(toplevel,toplevel->xdg_toplevel->requested.fullscreen); + diyac_view_set_fullscreen(toplevel, toplevel->xdg_toplevel->requested.fullscreen); } static void xdg_toplevel_request_minimize(struct wl_listener *listener, void *data) @@ -183,7 +184,10 @@ static void xdg_toplevel_destroy(struct wl_listener *listener, void *data) { /* Called when the xdg_toplevel is destroyed. */ struct diyac_view *toplevel = wl_container_of(listener, toplevel, destroy); - + if (toplevel->toplevel.handle) + { + wlr_foreign_toplevel_handle_v1_destroy(toplevel->toplevel.handle); + } wl_list_remove(&toplevel->map.link); wl_list_remove(&toplevel->unmap.link); wl_list_remove(&toplevel->destroy.link); @@ -191,6 +195,11 @@ static void xdg_toplevel_destroy(struct wl_listener *listener, void *data) wl_list_remove(&toplevel->request_resize.link); wl_list_remove(&toplevel->request_maximize.link); wl_list_remove(&toplevel->request_fullscreen.link); + + wl_list_remove(&toplevel->set_app_id.link); + wl_list_remove(&toplevel->new_popup.link); + wl_list_remove(&toplevel->set_title.link); + free(toplevel); } @@ -215,13 +224,12 @@ static void popup_unconstrain(struct diyac_popup *popup) struct wlr_output_layout *output_layout = server->output_layout; struct wlr_output *wlr_output = view->output->wlr_output; struct wlr_box usable = { - .x = 0, - .y = 0, - .width = view->output->wlr_output->width, - .height = view->output->wlr_output->height - }; + .x = 0, + .y = 0, + .width = view->output->wlr_output->width, + .height = view->output->wlr_output->height}; struct diyac_view *root = diyac_get_root_view(view); - if(!root || ! root->state.fullscreen) + if (!root || !root->state.fullscreen) { usable = view->output->usable_area; } @@ -316,9 +324,14 @@ static void xdg_popup_create(struct diyac_view *view, struct wlr_xdg_popup *wlr_ static void xdg_set_appid_notify(struct wl_listener *listener, void *data) { - struct diyac_view *xdg_toplevel_view = - wl_container_of(listener, xdg_toplevel_view, set_app_id); - wlr_log(WLR_INFO, "set application id"); + struct diyac_view *view = wl_container_of(listener, view, set_app_id); + diyac_view_update_app_id(view); +} + +static void xdg_set_title_notify(struct wl_listener *listener, void *data) +{ + struct diyac_view *view = wl_container_of(listener, view, set_title); + diyac_view_update_title(view); } static void xdg_new_popup_notify(struct wl_listener *listener, void *data) @@ -358,7 +371,7 @@ void diyac_new_xdg_surface(struct wl_listener *listener, void *data) wlr_log(WLR_INFO, "diyac_new_xdg_surface: Creating new application windows"); wlr_xdg_surface_ping(xdg_surface); /* Allocate a diyac_view for this surface */ - struct diyac_view *toplevel = calloc(1, sizeof(*toplevel)); + struct diyac_view *toplevel = calloc(1, sizeof(*toplevel)); memset(&toplevel->state, 0, sizeof(toplevel->state)); memset(&toplevel->requested, 0, sizeof(toplevel->requested)); toplevel->server = server; @@ -379,6 +392,8 @@ void diyac_new_xdg_surface(struct wl_listener *listener, void *data) wlr_scene_node_set_enabled(&toplevel->scene_tree->node, false); diyac_node_descriptor_create(&toplevel->scene_tree->node, DIYAC_NODE_VIEW, toplevel); + diyac_init_foreign_toplevel(toplevel); + /* Listen to the various events it can emit */ toplevel->map.notify = xdg_toplevel_map; wl_signal_add(&xdg_surface->surface->events.map, &toplevel->map); @@ -403,6 +418,10 @@ void diyac_new_xdg_surface(struct wl_listener *listener, void *data) &toplevel->request_fullscreen); toplevel->new_popup.notify = xdg_new_popup_notify; wl_signal_add(&xdg_surface->events.new_popup, &toplevel->new_popup); + toplevel->set_app_id.notify = xdg_set_appid_notify; wl_signal_add(&xdg_toplevel->events.set_app_id, &toplevel->set_app_id); + + toplevel->set_title.notify = xdg_set_title_notify; + wl_signal_add(&xdg_toplevel->events.set_title, &toplevel->set_title); } \ No newline at end of file