diff --git a/include/labwc.h b/include/labwc.h index d038963f..7297af7f 100644 --- a/include/labwc.h +++ b/include/labwc.h @@ -348,6 +348,7 @@ void xdg_toplevel_decoration(struct wl_listener *listener, void *data); void xdg_activation_handle_request(struct wl_listener *listener, void *data); +void xdg_toplevel_view_convert_to_unmanaged(struct view *view); void xdg_surface_new(struct wl_listener *listener, void *data); void foreign_toplevel_handle_create(struct view *view); diff --git a/include/node.h b/include/node.h index 3e0601a5..3d6ef7d5 100644 --- a/include/node.h +++ b/include/node.h @@ -13,6 +13,7 @@ enum node_descriptor_type { LAB_NODE_DESC_NODE = 0, LAB_NODE_DESC_VIEW, LAB_NODE_DESC_XDG_POPUP, + LAB_NODE_DESC_XDG_UNMANAGED, LAB_NODE_DESC_LAYER_SURFACE, LAB_NODE_DESC_LAYER_POPUP, LAB_NODE_DESC_MENUITEM, @@ -37,6 +38,7 @@ struct node_descriptor { * @data: struct to point to as follows: * - LAB_NODE_DESC_VIEW struct view * - LAB_NODE_DESC_XDG_POPUP struct view + * - LAB_NODE_DESC_XDG_UNMANAGED struct xdg_unmanaged * - LAB_NODE_DESC_LAYER_SURFACE struct lab_layer_surface * - LAB_NODE_DESC_LAYER_POPUP struct lab_layer_popup * - LAB_NODE_DESC_MENUITEM struct menuitem diff --git a/include/view.h b/include/view.h index abc8b6ce..c93e8fe9 100644 --- a/include/view.h +++ b/include/view.h @@ -167,6 +167,7 @@ void view_adjust_size(struct view *view, int *w, int *h); void view_evacuate_region(struct view *view); void view_on_output_destroy(struct view *view); void view_destroy(struct view *view); +void view_apply_rules(struct view *view); /* xdg.c */ struct wlr_xdg_surface *xdg_surface_from_view(struct view *view); diff --git a/include/xdg-unmanaged.h b/include/xdg-unmanaged.h new file mode 100644 index 00000000..243865b6 --- /dev/null +++ b/include/xdg-unmanaged.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef __LABWC_XDG_UNMANAGED +#define __LABWC_XDG_UNMANAGED + +struct server; +struct wlr_xdg_surface; + +void xdg_unmanaged_create(struct server *server, struct wlr_xdg_surface *wlr_xdg_surface); + +#endif /* __LABWC_XDG_UNMANAGED */ diff --git a/src/desktop.c b/src/desktop.c index 5c7151fc..522c8b62 100644 --- a/src/desktop.c +++ b/src/desktop.c @@ -348,6 +348,10 @@ get_cursor_context(struct server *server) ret.surface = lab_wlr_surface_from_node(ret.node); } return ret; + case LAB_NODE_DESC_XDG_UNMANAGED: + ret.type = LAB_SSD_CLIENT; + ret.surface = lab_wlr_surface_from_node(ret.node); + return ret; case LAB_NODE_DESC_SSD_BUTTON: { /* * Always return the top scene node for SSD diff --git a/src/meson.build b/src/meson.build index da040d12..1891fa3c 100644 --- a/src/meson.build +++ b/src/meson.build @@ -26,6 +26,7 @@ labwc_sources = files( 'xdg.c', 'xdg-deco.c', 'xdg-popup.c', + 'xdg-unmanaged.c', ) if have_xwayland diff --git a/src/view.c b/src/view.c index 9bd38757..c6542cb9 100644 --- a/src/view.c +++ b/src/view.c @@ -978,6 +978,26 @@ view_get_string_prop(struct view *view, const char *prop) return ""; } +void +view_apply_rules(struct view *view) +{ + if (!view->mapped) { + return; + } + + /* TODO: read rc.xml element */ + const char *title = view_get_string_prop(view, "title"); + if (title && !strcmp(title, "lxqt-panel")) { + xdg_toplevel_view_convert_to_unmanaged(view); + return; + } + const char *app_id = view_get_string_prop(view, "app_id"); + if (app_id && !strcmp(app_id, "lxqt-panel")) { + xdg_toplevel_view_convert_to_unmanaged(view); + return; + } +} + void view_update_title(struct view *view) { diff --git a/src/xdg-unmanaged.c b/src/xdg-unmanaged.c new file mode 100644 index 00000000..f530d207 --- /dev/null +++ b/src/xdg-unmanaged.c @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-2.0-only +#include +#include "common/mem.h" +#include "labwc.h" +#include "node.h" +#include "view.h" +#include "view-impl-common.h" +#include "workspaces.h" +#include "xdg-unmanaged.h" + +struct xdg_unmanaged { + struct server *server; + struct wlr_xdg_surface *wlr_xdg_surface; + struct wlr_scene_tree *tree; + struct wlr_scene_node *node; + + struct wl_listener destroy; +}; + +static void +unmanaged_handle_destroy(struct wl_listener *listener, void *data) +{ + struct xdg_unmanaged *unmanaged = wl_container_of(listener, unmanaged, destroy); + wl_list_remove(&unmanaged->destroy.link); + free(unmanaged); +} + +void +xdg_unmanaged_create(struct server *server, struct wlr_xdg_surface *wlr_xdg_surface) +{ + struct xdg_unmanaged *unmanaged = znew(*unmanaged); + unmanaged->server = server; + unmanaged->wlr_xdg_surface = wlr_xdg_surface; + + unmanaged->destroy.notify = unmanaged_handle_destroy; + wl_signal_add(&wlr_xdg_surface->events.destroy, &unmanaged->destroy); + + unmanaged->tree = server->view_tree_always_on_top; + unmanaged->node = &wlr_scene_surface_create(unmanaged->tree, + wlr_xdg_surface->surface)->buffer->node; + node_descriptor_create(unmanaged->node, LAB_NODE_DESC_XDG_UNMANAGED, unmanaged); + wlr_scene_node_set_position(unmanaged->node, 0, 0); + cursor_update_focus(unmanaged->server); +} diff --git a/src/xdg.c b/src/xdg.c index 11785d15..e7c87ddd 100644 --- a/src/xdg.c +++ b/src/xdg.c @@ -6,6 +6,7 @@ #include "view.h" #include "view-impl-common.h" #include "workspaces.h" +#include "xdg-unmanaged.h" static struct xdg_toplevel_view * xdg_toplevel_view_from_view(struct view *view) @@ -134,6 +135,17 @@ handle_destroy(struct wl_listener *listener, void *data) view_destroy(view); } +void +xdg_toplevel_view_convert_to_unmanaged(struct view *view) +{ + struct wlr_xdg_surface *xdg_surface = xdg_surface_from_view(view); + struct server *server = view->server; + + handle_unmap(&view->unmap, xdg_surface); + handle_destroy(&view->destroy, xdg_surface); + xdg_unmanaged_create(server, xdg_surface); +} + static void handle_request_move(struct wl_listener *listener, void *data) { @@ -375,6 +387,7 @@ xdg_toplevel_view_map(struct view *view) wl_signal_add(&xdg_surface->surface->events.commit, &view->commit); view_impl_map(view); + view_apply_rules(view); } static void