mirror of
https://github.com/labwc/labwc.git
synced 2025-11-02 09:01:47 -05:00
132 lines
4.1 KiB
C
132 lines
4.1 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
#include "labwc.h"
|
|
|
|
static void
|
|
unmanaged_handle_request_configure(struct wl_listener *listener, void *data)
|
|
{
|
|
struct xwayland_unmanaged *unmanaged =
|
|
wl_container_of(listener, unmanaged, request_configure);
|
|
struct wlr_xwayland_surface *xsurface = unmanaged->xwayland_surface;
|
|
struct wlr_xwayland_surface_configure_event *ev = data;
|
|
wlr_xwayland_surface_configure(xsurface, ev->x, ev->y, ev->width,
|
|
ev->height);
|
|
}
|
|
|
|
static void
|
|
unmanaged_handle_commit(struct wl_listener *listener, void *data)
|
|
{
|
|
struct xwayland_unmanaged *unmanaged =
|
|
wl_container_of(listener, unmanaged, commit);
|
|
struct wlr_xwayland_surface *xsurface = unmanaged->xwayland_surface;
|
|
unmanaged->lx = xsurface->x;
|
|
unmanaged->ly = xsurface->y;
|
|
damage_all_outputs(unmanaged->server);
|
|
}
|
|
|
|
static struct view *
|
|
parent_view(struct server *server, struct wlr_xwayland_surface *surface)
|
|
{
|
|
struct wlr_xwayland_surface *s = surface;
|
|
while (s->parent) {
|
|
s = s->parent;
|
|
}
|
|
struct view *view;
|
|
wl_list_for_each(view, &server->views, link) {
|
|
if (view->xwayland_surface == s) {
|
|
return view;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static void
|
|
unmanaged_handle_map(struct wl_listener *listener, void *data)
|
|
{
|
|
struct xwayland_unmanaged *unmanaged =
|
|
wl_container_of(listener, unmanaged, map);
|
|
struct wlr_xwayland_surface *xsurface = unmanaged->xwayland_surface;
|
|
|
|
wl_list_insert(unmanaged->server->unmanaged_surfaces.prev,
|
|
&unmanaged->link);
|
|
|
|
wl_signal_add(&xsurface->surface->events.commit, &unmanaged->commit);
|
|
unmanaged->commit.notify = unmanaged_handle_commit;
|
|
|
|
unmanaged->lx = xsurface->x;
|
|
unmanaged->ly = xsurface->y;
|
|
damage_all_outputs(unmanaged->server);
|
|
if (wlr_xwayland_or_surface_wants_focus(xsurface)) {
|
|
seat_focus_surface(&unmanaged->server->seat, xsurface->surface);
|
|
}
|
|
|
|
int lx = unmanaged->lx;
|
|
int ly = unmanaged->ly;
|
|
struct wlr_scene_node *parent, *node;
|
|
struct view *view = parent_view(unmanaged->server, xsurface);
|
|
if (!view || !view->scene_node) {
|
|
parent = &unmanaged->server->unmanaged_tree->node;
|
|
} else {
|
|
lx -= view->x;
|
|
ly -= view->y;
|
|
parent = &view->scene_tree->node;
|
|
}
|
|
/* node will be destroyed automatically once surface is destroyed */
|
|
node = &wlr_scene_surface_create(parent, xsurface->surface)->node;
|
|
wlr_scene_node_set_position(node, lx, ly);
|
|
}
|
|
|
|
static void
|
|
unmanaged_handle_unmap(struct wl_listener *listener, void *data)
|
|
{
|
|
struct xwayland_unmanaged *unmanaged =
|
|
wl_container_of(listener, unmanaged, unmap);
|
|
struct wlr_xwayland_surface *xsurface = unmanaged->xwayland_surface;
|
|
damage_all_outputs(unmanaged->server);
|
|
wl_list_remove(&unmanaged->link);
|
|
wl_list_remove(&unmanaged->commit.link);
|
|
|
|
struct seat *seat = &unmanaged->server->seat;
|
|
if (seat->seat->keyboard_state.focused_surface == xsurface->surface) {
|
|
struct xwayland_unmanaged *u;
|
|
struct wl_list *list = &unmanaged->server->unmanaged_surfaces;
|
|
wl_list_for_each (u, list, link) {
|
|
struct wlr_xwayland_surface *prev = u->xwayland_surface;
|
|
if (!wlr_xwayland_or_surface_wants_focus(prev)) {
|
|
continue;
|
|
}
|
|
seat_focus_surface(seat, prev->surface);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
unmanaged_handle_destroy(struct wl_listener *listener, void *data)
|
|
{
|
|
struct xwayland_unmanaged *unmanaged =
|
|
wl_container_of(listener, unmanaged, destroy);
|
|
wl_list_remove(&unmanaged->map.link);
|
|
wl_list_remove(&unmanaged->unmap.link);
|
|
wl_list_remove(&unmanaged->destroy.link);
|
|
free(unmanaged);
|
|
}
|
|
|
|
void
|
|
xwayland_unmanaged_create(struct server *server,
|
|
struct wlr_xwayland_surface *xsurface)
|
|
{
|
|
struct xwayland_unmanaged *unmanaged;
|
|
unmanaged = calloc(1, sizeof(struct xwayland_unmanaged));
|
|
unmanaged->server = server;
|
|
unmanaged->xwayland_surface = xsurface;
|
|
wl_signal_add(&xsurface->events.request_configure,
|
|
&unmanaged->request_configure);
|
|
unmanaged->request_configure.notify =
|
|
unmanaged_handle_request_configure;
|
|
wl_signal_add(&xsurface->events.map, &unmanaged->map);
|
|
unmanaged->map.notify = unmanaged_handle_map;
|
|
wl_signal_add(&xsurface->events.unmap, &unmanaged->unmap);
|
|
unmanaged->unmap.notify = unmanaged_handle_unmap;
|
|
wl_signal_add(&xsurface->events.destroy, &unmanaged->destroy);
|
|
unmanaged->destroy.notify = unmanaged_handle_destroy;
|
|
}
|