diff --git a/cage-vi/.SRCINFO b/cage-vi/.SRCINFO
index 1ae3fb5..7f2e870 100644
--- a/cage-vi/.SRCINFO
+++ b/cage-vi/.SRCINFO
@@ -1,6 +1,6 @@
pkgbase = cage-vi
pkgdesc = A Wayland kiosk, with virtual input patch applied
- pkgver = 0.1.4+39+ga81ab70
+ pkgver = 0.1.4+54+gbd5b20e
pkgrel = 1
url = https://www.hjdskes.nl/projects/cage/
arch = x86_64
@@ -18,10 +18,8 @@ pkgbase = cage-vi
provides = cage
conflicts = cage
source = https://github.com/Hjdskes/cage/releases/download/v0.1.4/cage-0.1.4.tar.gz
- source = a81ab70.patch
- source = virtual_input.patch
+ source = bd5b20e.patch
sha256sums = dfe27fb0c7d43db72d6c82f01e2736580a0791a23ba69d7b56285d08af98ad90
- sha256sums = 8580568cc9b68b33de206a841e2110be14de730356c504b66fe366912d0abf76
- sha256sums = 352a3f33c2690a401c90c4de668d38e4cdff53db6c2fc9577a7c607d8a9ec369
+ sha256sums = b3608b082c8859433158377ec875ee17ca72f10d61d8827eb5b1c2e01771c0ce
pkgname = cage-vi
diff --git a/cage-vi/PKGBUILD b/cage-vi/PKGBUILD
index f1f4453..ad82ad2 100644
--- a/cage-vi/PKGBUILD
+++ b/cage-vi/PKGBUILD
@@ -1,6 +1,6 @@
pkgname=cage-vi
_pkgname=${pkgname%%-*}
-pkgver=0.1.4+39+ga81ab70
+pkgver=0.1.4+54+gbd5b20e
_pkgver=${pkgver%%+*}
pkgrel=1
pkgdesc='A Wayland kiosk, with virtual input patch applied'
@@ -17,19 +17,20 @@ provides=("${_pkgname}")
conflicts=("${_pkgname}")
source=(
"https://github.com/Hjdskes/${_pkgname}/releases/download/v${_pkgver}/${_pkgname}-${_pkgver}.tar.gz"
- 'a81ab70.patch'
- 'virtual_input.patch'
-)
-sha256sums=(
- 'dfe27fb0c7d43db72d6c82f01e2736580a0791a23ba69d7b56285d08af98ad90'
- '8580568cc9b68b33de206a841e2110be14de730356c504b66fe366912d0abf76'
- '352a3f33c2690a401c90c4de668d38e4cdff53db6c2fc9577a7c607d8a9ec369'
+ 'bd5b20e.patch'
)
+sha256sums=('dfe27fb0c7d43db72d6c82f01e2736580a0791a23ba69d7b56285d08af98ad90'
+ 'b3608b082c8859433158377ec875ee17ca72f10d61d8827eb5b1c2e01771c0ce')
+
+#pkgver() {
+# cd "${srcdir}/${_pkgname}-${_pkgver}"
+# git describe --long --tags | sed 's/^v//;s/-/+/g'
+#}
+
prepare() {
cd "${srcdir}/${_pkgname}-${_pkgver}"
- patch -Np1 -i '../a81ab70.patch'
- patch -Np1 -i '../virtual_input.patch'
+ patch -Np1 -i '../bd5b20e.patch'
meson --buildtype=release -Dxwayland=true --prefix /usr "$srcdir/build"
}
diff --git a/cage-vi/a81ab70.patch b/cage-vi/bd5b20e.patch
similarity index 68%
rename from cage-vi/a81ab70.patch
rename to cage-vi/bd5b20e.patch
index 6939578..d59ba45 100644
--- a/cage-vi/a81ab70.patch
+++ b/cage-vi/bd5b20e.patch
@@ -143,7 +143,7 @@ index 0000000..60dd059
\ No newline at end of file
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
new file mode 100644
-index 0000000..5e95347
+index 0000000..a98291a
--- /dev/null
+++ b/.github/workflows/main.yml
@@ -0,0 +1,76 @@
@@ -171,7 +171,7 @@ index 0000000..5e95347
+
+ - name: Install dependencies (Alpine)
+ if: "matrix.OS == 'alpine:edge'"
-+ run: apk add build-base xcb-util-wm-dev libseat-dev clang git eudev-dev mesa-dev libdrm-dev libinput-dev libxkbcommon-dev pixman-dev wayland-dev meson wayland-protocols xwayland scdoc-doc
++ run: apk add build-base xcb-util-wm-dev libseat-dev clang git eudev-dev mesa-dev libdrm-dev libinput-dev libxkbcommon-dev pixman-dev wayland-dev meson wayland-protocols xwayland scdoc-doc hwdata
+
+ - name: Install dependencies (Arch)
+ if: "matrix.OS == 'archlinux:base-devel'"
@@ -180,7 +180,7 @@ index 0000000..5e95347
+ pacman -Syu --noconfirm xcb-util-wm seatd git clang meson libinput libdrm mesa libxkbcommon wayland wayland-protocols xorg-server-xwayland scdoc
+
+ - name: Fetch wlroots as a subproject
-+ run: git clone https://gitlab.freedesktop.org/wlroots/wlroots.git subprojects/wlroots -b 0.15.0
++ run: git clone https://gitlab.freedesktop.org/wlroots/wlroots.git subprojects/wlroots -b 0.16.0
+
+ # TODO: use --fatal-meson-warnings when on wlroots 0.15.0
+ - name: Compile Cage (XWayland=${{ matrix.xwayland }})
@@ -197,9 +197,9 @@ index 0000000..5e95347
+ - name: Install dependencies
+ run: |
+ pacman-key --init
-+ pacman -Syu --noconfirm xcb-util-wm seatd git clang meson libinput libdrm mesa libxkbcommon wayland wayland-protocols xorg-server-xwayland scdoc
++ pacman -Syu --noconfirm xcb-util-wm seatd git clang meson libinput libdrm mesa libxkbcommon wayland wayland-protocols xorg-server-xwayland scdoc hwdata
+ - name: Fetch wlroots as a subproject
-+ run: git clone https://gitlab.freedesktop.org/wlroots/wlroots.git subprojects/wlroots -b 0.15.0
++ run: git clone https://gitlab.freedesktop.org/wlroots/wlroots.git subprojects/wlroots -b 0.16.0
+ - name: Check for formatting changes
+ run: |
+ meson build-clang-format -Dxwayland=true
@@ -216,15 +216,25 @@ index 0000000..5e95347
+ - name: Install dependencies
+ run: |
+ pacman-key --init
-+ pacman -Syu --noconfirm xcb-util-wm seatd git clang meson libinput libdrm mesa libxkbcommon wayland wayland-protocols xorg-server-xwayland scdoc
++ pacman -Syu --noconfirm xcb-util-wm seatd git clang meson libinput libdrm mesa libxkbcommon wayland wayland-protocols xorg-server-xwayland scdoc hwdata
+ - name: Fetch wlroots as a subproject
-+ run: git clone https://gitlab.freedesktop.org/wlroots/wlroots.git subprojects/wlroots -b 0.15.0
++ run: git clone https://gitlab.freedesktop.org/wlroots/wlroots.git subprojects/wlroots -b 0.16.0
+ - name: Run scan-build
+ run: |
+ meson build-scan-build -Dxwayland=true
+ ninja -C build-scan-build scan-build
+diff --git a/README.md b/README.md
+index e1b6f56..752387e 100644
+--- a/README.md
++++ b/README.md
+@@ -1,4 +1,4 @@
+-# Cage: a Wayland kiosk [![builds.sr.ht status](https://builds.sr.ht/~hjdskes.svg)](https://builds.sr.ht/~hjdskes?)
++# Cage: a Wayland kiosk
+
+
+
diff --git a/cage.c b/cage.c
-index 5392535..95f0cc7 100644
+index 5392535..c5eda4d 100644
--- a/cage.c
+++ b/cage.c
@@ -19,6 +19,7 @@
@@ -235,7 +245,7 @@ index 5392535..95f0cc7 100644
#include
#include
#include
-@@ -27,8 +28,11 @@
+@@ -27,8 +28,15 @@
#include
#include
#include
@@ -243,11 +253,28 @@ index 5392535..95f0cc7 100644
+#include
#include
#include
++#include
++#include
+#include
++#include
++#include
#if CAGE_HAS_XWAYLAND
#include
#endif
-@@ -185,9 +189,6 @@ usage(FILE *file, const char *cage)
+@@ -145,7 +153,12 @@ cleanup_primary_client(pid_t pid)
+ static bool
+ drop_permissions(void)
+ {
++ if (getuid() == 0 || getgid() == 0) {
++ wlr_log(WLR_INFO, "Running as root user, this is dangerous");
++ return true;
++ }
+ if (getuid() != geteuid() || getgid() != getegid()) {
++ wlr_log(WLR_INFO, "setuid/setgid bit detected, dropping permissions");
+ // Set the gid and uid in the correct order.
+ if (setgid(getgid()) != 0 || setuid(getuid()) != 0) {
+ wlr_log(WLR_ERROR, "Unable to drop root, refusing to start");
+@@ -185,9 +198,6 @@ usage(FILE *file, const char *cage)
"Usage: %s [OPTIONS] [--] APPLICATION\n"
"\n"
" -d\t Don't draw client side decorations, when possible\n"
@@ -257,7 +284,7 @@ index 5392535..95f0cc7 100644
" -h\t Display this help message\n"
" -m extend Extend the display across all connected outputs (default)\n"
" -m last Use only the last connected output\n"
-@@ -203,20 +204,11 @@ static bool
+@@ -203,20 +213,11 @@ static bool
parse_args(struct cg_server *server, int argc, char *argv[])
{
int c;
@@ -278,24 +305,29 @@ index 5392535..95f0cc7 100644
case 'h':
usage(stdout, argv[0]);
return false;
-@@ -261,7 +253,6 @@ main(int argc, char *argv[])
+@@ -261,15 +262,20 @@ main(int argc, char *argv[])
struct wl_event_source *sigint_source = NULL;
struct wl_event_source *sigterm_source = NULL;
struct wl_event_source *sigchld_source = NULL;
- struct wlr_renderer *renderer = NULL;
struct wlr_compositor *compositor = NULL;
++ struct wlr_subcompositor *subcompositor = NULL;
struct wlr_data_device_manager *data_device_manager = NULL;
struct wlr_server_decoration_manager *server_decoration_manager = NULL;
-@@ -270,6 +261,8 @@ main(int argc, char *argv[])
+ struct wlr_xdg_decoration_manager_v1 *xdg_decoration_manager = NULL;
+ struct wlr_export_dmabuf_manager_v1 *export_dmabuf_manager = NULL;
struct wlr_screencopy_manager_v1 *screencopy_manager = NULL;
++ struct wlr_single_pixel_buffer_manager_v1 *single_pixel_buffer = NULL;
struct wlr_xdg_output_manager_v1 *output_manager = NULL;
struct wlr_gamma_control_manager_v1 *gamma_control_manager = NULL;
++ struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard = NULL;
++ struct wlr_virtual_pointer_manager_v1 *virtual_pointer = NULL;
+ struct wlr_viewporter *viewporter = NULL;
+ struct wlr_presentation *presentation = NULL;
struct wlr_xdg_shell *xdg_shell = NULL;
#if CAGE_HAS_XWAYLAND
struct wlr_xwayland *xwayland = NULL;
-@@ -316,8 +309,21 @@ main(int argc, char *argv[])
+@@ -316,8 +322,21 @@ main(int argc, char *argv[])
goto end;
}
@@ -319,7 +351,7 @@ index 5392535..95f0cc7 100644
wl_list_init(&server.views);
wl_list_init(&server.outputs);
-@@ -329,7 +335,16 @@ main(int argc, char *argv[])
+@@ -329,13 +348,29 @@ main(int argc, char *argv[])
goto end;
}
@@ -337,7 +369,29 @@ index 5392535..95f0cc7 100644
if (!compositor) {
wlr_log(WLR_ERROR, "Unable to create the wlroots compositor");
ret = 1;
-@@ -401,6 +416,21 @@ main(int argc, char *argv[])
+ goto end;
+ }
+
++ subcompositor = wlr_subcompositor_create(server.wl_display);
++ if (!subcompositor) {
++ wlr_log(WLR_ERROR, "Unable to create the wlroots subcompositor");
++ ret = 1;
++ goto end;
++ }
++
+ data_device_manager = wlr_data_device_manager_create(server.wl_display);
+ if (!data_device_manager) {
+ wlr_log(WLR_ERROR, "Unable to create the data device manager");
+@@ -373,7 +408,7 @@ main(int argc, char *argv[])
+ wl_signal_add(&server.idle_inhibit_v1->events.new_inhibitor, &server.new_idle_inhibitor_v1);
+ wl_list_init(&server.inhibitors);
+
+- xdg_shell = wlr_xdg_shell_create(server.wl_display);
++ xdg_shell = wlr_xdg_shell_create(server.wl_display, 4);
+ if (!xdg_shell) {
+ wlr_log(WLR_ERROR, "Unable to create the XDG shell interface");
+ ret = 1;
+@@ -401,6 +436,21 @@ main(int argc, char *argv[])
server_decoration_manager, server.xdg_decoration ? WLR_SERVER_DECORATION_MANAGER_MODE_SERVER
: WLR_SERVER_DECORATION_MANAGER_MODE_CLIENT);
@@ -359,8 +413,57 @@ index 5392535..95f0cc7 100644
export_dmabuf_manager = wlr_export_dmabuf_manager_v1_create(server.wl_display);
if (!export_dmabuf_manager) {
wlr_log(WLR_ERROR, "Unable to create the export DMABUF manager");
+@@ -415,6 +465,13 @@ main(int argc, char *argv[])
+ goto end;
+ }
+
++ single_pixel_buffer = wlr_single_pixel_buffer_manager_v1_create(server.wl_display);
++ if (!single_pixel_buffer) {
++ wlr_log(WLR_ERROR, "Unable to create the single pixel buffer manager");
++ ret = 1;
++ goto end;
++ }
++
+ output_manager = wlr_xdg_output_manager_v1_create(server.wl_display, server.output_layout);
+ if (!output_manager) {
+ wlr_log(WLR_ERROR, "Unable to create the output manager");
+@@ -429,6 +486,22 @@ main(int argc, char *argv[])
+ goto end;
+ }
+
++ virtual_keyboard = wlr_virtual_keyboard_manager_v1_create(server.wl_display);
++ if (!virtual_keyboard) {
++ wlr_log(WLR_ERROR, "Unable to create the virtual keyboard manager");
++ ret = 1;
++ goto end;
++ }
++ wl_signal_add(&virtual_keyboard->events.new_virtual_keyboard, &server.new_virtual_keyboard);
++
++ virtual_pointer = wlr_virtual_pointer_manager_v1_create(server.wl_display);
++ if (!virtual_pointer) {
++ wlr_log(WLR_ERROR, "Unable to create the virtual pointer manager");
++ ret = 1;
++ goto end;
++ }
++ wl_signal_add(&virtual_pointer->events.new_virtual_pointer, &server.new_virtual_pointer);
++
+ #if CAGE_HAS_XWAYLAND
+ xwayland = wlr_xwayland_create(server.wl_display, compositor, true);
+ if (!xwayland) {
+@@ -492,8 +565,9 @@ main(int argc, char *argv[])
+ }
+
+ /* Place the cursor in the center of the output layout. */
+- struct wlr_box *layout_box = wlr_output_layout_get_box(server.output_layout, NULL);
+- wlr_cursor_warp(server.seat->cursor, NULL, layout_box->width / 2, layout_box->height / 2);
++ struct wlr_box layout_box;
++ wlr_output_layout_get_box(server.output_layout, NULL, &layout_box);
++ wlr_cursor_warp(server.seat->cursor, NULL, layout_box.width / 2, layout_box.height / 2);
+
+ wl_display_run(server.wl_display);
+
diff --git a/meson.build b/meson.build
-index 3a84794..5a8b28c 100644
+index 3a84794..fbd7e16 100644
--- a/meson.build
+++ b/meson.build
@@ -1,16 +1,17 @@
@@ -388,7 +491,7 @@ index 3a84794..5a8b28c 100644
endif
-wlroots = dependency('wlroots', version: '>= 0.14.0')
-+wlroots = dependency('wlroots', version: '>= 0.15.0', fallback: ['wlroots', 'wlroots'])
++wlroots = dependency('wlroots', version: '>= 0.16.0', fallback: ['wlroots', 'wlroots'])
wayland_protos = dependency('wayland-protocols', version: '>=1.14')
wayland_server = dependency('wayland-server')
-pixman = dependency('pixman-1')
@@ -474,7 +577,7 @@ index 3a84794..5a8b28c 100644
],
install: true,
diff --git a/output.c b/output.c
-index d8da3b9..c33bbe1 100644
+index d8da3b9..6eca0db 100644
--- a/output.c
+++ b/output.c
@@ -1,7 +1,7 @@
@@ -494,12 +597,18 @@ index d8da3b9..c33bbe1 100644
#include
#include
#include
-@@ -26,216 +27,20 @@
+@@ -21,221 +22,25 @@
+ #include
+ #endif
+ #include
++#include
+ #include
+ #include
#include
#include
#include
+-#include
+#include
- #include
#include
#include
#include
@@ -1187,53 +1296,44 @@ index 085b00b..0000000
-
-#endif
diff --git a/seat.c b/seat.c
-index 08f25a3..4dce511 100644
+index 08f25a3..5d80e33 100644
--- a/seat.c
+++ b/seat.c
-@@ -8,6 +8,7 @@
+@@ -6,10 +6,14 @@
+ * See the LICENSE file accompanying this file.
+ */
++#define _POSIX_C_SOURCE 200809L
++
#include "config.h"
+#include
#include
#include
++#include
#include
-@@ -18,6 +19,7 @@
+ #include
+ #include
+@@ -18,9 +22,11 @@
#include
#include
#include
+#include
#include
- #include
+-#include
#include
-@@ -41,42 +43,31 @@ static void drag_icon_update_position(struct cg_drag_icon *drag_icon);
++#include
++#include
+ #include
+ #include
+ #if CAGE_HAS_XWAYLAND
+@@ -41,42 +47,42 @@ static void drag_icon_update_position(struct cg_drag_icon *drag_icon);
* menus or tooltips. This function tests if any of those are underneath the
* coordinates lx and ly (in output Layout Coordinates). If so, it sets the
* surface pointer to that wlr_surface and the sx and sy coordinates to the
- * coordinates relative to that surface's top-left corner. */
-static bool
-view_at(struct cg_view *view, double lx, double ly, struct wlr_surface **surface, double *sx, double *sy)
--{
-- double view_sx = lx - view->lx;
-- double view_sy = ly - view->ly;
--
-- double _sx, _sy;
-- struct wlr_surface *_surface = view_wlr_surface_at(view, view_sx, view_sy, &_sx, &_sy);
-- if (_surface != NULL) {
-- *sx = _sx;
-- *sy = _sy;
-- *surface = _surface;
-- return true;
-- }
--
-- return false;
--}
--
--/* This iterates over all of our surfaces and attempts to find one
-- * under the cursor. This relies on server->views being ordered from
-- * top-to-bottom. If desktop_view_at returns a view, there is also a
-- * surface. There cannot be a surface without a view, either. It's
-- * both or nothing. */
+ * coordinates relative to that surface's top-left corner.
+ *
+ * This function iterates over all of our surfaces and attempts to find one
@@ -1241,34 +1341,297 @@ index 08f25a3..4dce511 100644
+ * surface. There cannot be a surface without a view, either. It's both or
+ * nothing.
+ */
- static struct cg_view *
- desktop_view_at(struct cg_server *server, double lx, double ly, struct wlr_surface **surface, double *sx, double *sy)
++static struct cg_view *
++desktop_view_at(struct cg_server *server, double lx, double ly, struct wlr_surface **surface, double *sx, double *sy)
{
-- struct cg_view *view;
-+ struct wlr_scene_node *node = wlr_scene_node_at(&server->scene->node, lx, ly, sx, sy);
-+ if (node == NULL || node->type != WLR_SCENE_NODE_SURFACE) {
+- double view_sx = lx - view->lx;
+- double view_sy = ly - view->ly;
++ struct wlr_scene_node *node = wlr_scene_node_at(&server->scene->tree.node, lx, ly, sx, sy);
++ if (node == NULL || node->type != WLR_SCENE_NODE_BUFFER) {
+ return NULL;
+ }
+- double _sx, _sy;
+- struct wlr_surface *_surface = view_wlr_surface_at(view, view_sx, view_sy, &_sx, &_sy);
+- if (_surface != NULL) {
+- *sx = _sx;
+- *sy = _sy;
+- *surface = _surface;
+- return true;
++ struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node);
++ struct wlr_scene_surface *scene_surface = wlr_scene_surface_from_buffer(scene_buffer);
++ if (!scene_surface) {
++ return NULL;
+ }
+
+- return false;
+-}
++ *surface = scene_surface->surface;
+
+-/* This iterates over all of our surfaces and attempts to find one
+- * under the cursor. This relies on server->views being ordered from
+- * top-to-bottom. If desktop_view_at returns a view, there is also a
+- * surface. There cannot be a surface without a view, either. It's
+- * both or nothing. */
+-static struct cg_view *
+-desktop_view_at(struct cg_server *server, double lx, double ly, struct wlr_surface **surface, double *sx, double *sy)
+-{
+- struct cg_view *view;
+-
- wl_list_for_each (view, &server->views, link) {
- if (view_at(view, lx, ly, surface, sx, sy)) {
- return view;
-- }
-+ *surface = wlr_scene_surface_from_node(node)->surface;
-+
+ /* Walk up the tree until we find a node with a data pointer. When done,
+ * we've found the node representing the view. */
-+ while (node != NULL && node->data == NULL) {
-+ node = node->parent;
++ while (!node->data) {
++ if (!node->parent) {
++ node = NULL;
++ break;
+ }
++
++ node = &node->parent->node;
}
-+ assert(node != NULL);
- return NULL;
++ assert(node != NULL);
+ return node->data;
}
static void
-@@ -351,17 +342,11 @@ handle_new_keyboard(struct cg_seat *seat, struct wlr_input_device *device)
+@@ -127,16 +133,16 @@ update_capabilities(struct cg_seat *seat)
+ }
+
+ static void
+-map_input_device_to_output(struct cg_seat *seat, struct wlr_input_device *device)
++map_input_device_to_output(struct cg_seat *seat, struct wlr_input_device *device, const char *output_name)
+ {
+- if (!device->output_name) {
++ if (!output_name) {
+ wlr_log(WLR_INFO, "Input device %s cannot be mapped to an output device\n", device->name);
+ return;
+ }
+
+ struct cg_output *output;
+ wl_list_for_each (output, &seat->server->outputs, link) {
+- if (strcmp(device->output_name, output->wlr_output->name) == 0) {
++ if (strcmp(output_name, output->wlr_output->name) == 0) {
+ wlr_log(WLR_INFO, "Mapping input device %s to output device %s\n", device->name,
+ output->wlr_output->name);
+ wlr_cursor_map_input_to_output(seat->cursor, device, output->wlr_output);
+@@ -154,7 +160,7 @@ handle_touch_destroy(struct wl_listener *listener, void *data)
+ struct cg_seat *seat = touch->seat;
+
+ wl_list_remove(&touch->link);
+- wlr_cursor_detach_input_device(seat->cursor, touch->device);
++ wlr_cursor_detach_input_device(seat->cursor, &touch->touch->base);
+ wl_list_remove(&touch->destroy.link);
+ free(touch);
+
+@@ -162,7 +168,7 @@ handle_touch_destroy(struct wl_listener *listener, void *data)
+ }
+
+ static void
+-handle_new_touch(struct cg_seat *seat, struct wlr_input_device *device)
++handle_new_touch(struct cg_seat *seat, struct wlr_touch *wlr_touch)
+ {
+ struct cg_touch *touch = calloc(1, sizeof(struct cg_touch));
+ if (!touch) {
+@@ -171,14 +177,14 @@ handle_new_touch(struct cg_seat *seat, struct wlr_input_device *device)
+ }
+
+ touch->seat = seat;
+- touch->device = device;
+- wlr_cursor_attach_input_device(seat->cursor, device);
++ touch->touch = wlr_touch;
++ wlr_cursor_attach_input_device(seat->cursor, &wlr_touch->base);
+
+ wl_list_insert(&seat->touch, &touch->link);
+ touch->destroy.notify = handle_touch_destroy;
+- wl_signal_add(&touch->device->events.destroy, &touch->destroy);
++ wl_signal_add(&wlr_touch->base.events.destroy, &touch->destroy);
+
+- map_input_device_to_output(seat, device);
++ map_input_device_to_output(seat, &wlr_touch->base, wlr_touch->output_name);
+ }
+
+ static void
+@@ -188,7 +194,7 @@ handle_pointer_destroy(struct wl_listener *listener, void *data)
+ struct cg_seat *seat = pointer->seat;
+
+ wl_list_remove(&pointer->link);
+- wlr_cursor_detach_input_device(seat->cursor, pointer->device);
++ wlr_cursor_detach_input_device(seat->cursor, &pointer->pointer->base);
+ wl_list_remove(&pointer->destroy.link);
+ free(pointer);
+
+@@ -196,7 +202,7 @@ handle_pointer_destroy(struct wl_listener *listener, void *data)
+ }
+
+ static void
+-handle_new_pointer(struct cg_seat *seat, struct wlr_input_device *device)
++handle_new_pointer(struct cg_seat *seat, struct wlr_pointer *wlr_pointer)
+ {
+ struct cg_pointer *pointer = calloc(1, sizeof(struct cg_pointer));
+ if (!pointer) {
+@@ -205,21 +211,42 @@ handle_new_pointer(struct cg_seat *seat, struct wlr_input_device *device)
+ }
+
+ pointer->seat = seat;
+- pointer->device = device;
+- wlr_cursor_attach_input_device(seat->cursor, device);
++ pointer->pointer = wlr_pointer;
++ wlr_cursor_attach_input_device(seat->cursor, &wlr_pointer->base);
+
+ wl_list_insert(&seat->pointers, &pointer->link);
+ pointer->destroy.notify = handle_pointer_destroy;
+- wl_signal_add(&device->events.destroy, &pointer->destroy);
++ wl_signal_add(&wlr_pointer->base.events.destroy, &pointer->destroy);
++
++ map_input_device_to_output(seat, &wlr_pointer->base, wlr_pointer->output_name);
++}
+
+- map_input_device_to_output(seat, device);
++static void
++handle_virtual_pointer(struct wl_listener *listener, void *data)
++{
++ struct cg_server *server = wl_container_of(listener, server, new_virtual_pointer);
++ struct cg_seat *seat = server->seat;
++ struct wlr_virtual_pointer_v1_new_pointer_event *event = data;
++ struct wlr_virtual_pointer_v1 *pointer = event->new_pointer;
++ struct wlr_pointer *wlr_pointer = &pointer->pointer;
++
++ /* We'll want to map the device back to an output later, this is a bit
++ * sub-optimal (we could just keep the suggested_output), but just copy
++ * its name so we do like other devices
++ */
++ if (event->suggested_output != NULL) {
++ wlr_pointer->output_name = strdup(event->suggested_output->name);
++ }
++ /* TODO: event->suggested_seat should be checked if we handle multiple seats */
++ handle_new_pointer(seat, wlr_pointer);
++ update_capabilities(seat);
+ }
+
+ static void
+-handle_modifier_event(struct wlr_input_device *device, struct cg_seat *seat)
++handle_modifier_event(struct wlr_keyboard *keyboard, struct cg_seat *seat)
+ {
+- wlr_seat_set_keyboard(seat->seat, device);
+- wlr_seat_keyboard_notify_modifiers(seat->seat, &device->keyboard->modifiers);
++ wlr_seat_set_keyboard(seat->seat, keyboard);
++ wlr_seat_keyboard_notify_modifiers(seat->seat, &keyboard->modifiers);
+
+ wlr_idle_notify_activity(seat->server->idle, seat->seat);
+ }
+@@ -249,18 +276,18 @@ handle_keybinding(struct cg_server *server, xkb_keysym_t sym)
+ }
+
+ static void
+-handle_key_event(struct wlr_input_device *device, struct cg_seat *seat, void *data)
++handle_key_event(struct wlr_keyboard *keyboard, struct cg_seat *seat, void *data)
+ {
+- struct wlr_event_keyboard_key *event = data;
++ struct wlr_keyboard_key_event *event = data;
+
+ /* Translate from libinput keycode to an xkbcommon keycode. */
+ xkb_keycode_t keycode = event->keycode + 8;
+
+ const xkb_keysym_t *syms;
+- int nsyms = xkb_state_key_get_syms(device->keyboard->xkb_state, keycode, &syms);
++ int nsyms = xkb_state_key_get_syms(keyboard->xkb_state, keycode, &syms);
+
+ bool handled = false;
+- uint32_t modifiers = wlr_keyboard_get_modifiers(device->keyboard);
++ uint32_t modifiers = wlr_keyboard_get_modifiers(keyboard);
+ if ((modifiers & WLR_MODIFIER_ALT) && event->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
+ /* If Alt is held down and this button was pressed, we
+ * attempt to process it as a compositor
+@@ -272,7 +299,7 @@ handle_key_event(struct wlr_input_device *device, struct cg_seat *seat, void *da
+
+ if (!handled) {
+ /* Otherwise, we pass it along to the client. */
+- wlr_seat_set_keyboard(seat->seat, device);
++ wlr_seat_set_keyboard(seat->seat, keyboard);
+ wlr_seat_keyboard_notify_key(seat->seat, event->time_msec, event->keycode, event->state);
+ }
+
+@@ -283,27 +310,32 @@ static void
+ handle_keyboard_group_key(struct wl_listener *listener, void *data)
+ {
+ struct cg_keyboard_group *cg_group = wl_container_of(listener, cg_group, key);
+- handle_key_event(cg_group->wlr_group->input_device, cg_group->seat, data);
++ handle_key_event(&cg_group->wlr_group->keyboard, cg_group->seat, data);
+ }
+
+ static void
+ handle_keyboard_group_modifiers(struct wl_listener *listener, void *data)
+ {
+ struct cg_keyboard_group *group = wl_container_of(listener, group, modifiers);
+- handle_modifier_event(group->wlr_group->input_device, group->seat);
++ handle_modifier_event(&group->wlr_group->keyboard, group->seat);
+ }
+
+ static void
+-cg_keyboard_group_add(struct wlr_input_device *device, struct cg_seat *seat)
++cg_keyboard_group_add(struct wlr_keyboard *keyboard, struct cg_seat *seat, bool virtual)
+ {
+- struct wlr_keyboard *wlr_keyboard = device->keyboard;
+-
+- struct cg_keyboard_group *group;
+- wl_list_for_each (group, &seat->keyboard_groups, link) {
+- struct wlr_keyboard_group *wlr_group = group->wlr_group;
+- if (wlr_keyboard_group_add_keyboard(wlr_group, wlr_keyboard)) {
+- wlr_log(WLR_DEBUG, "Added new keyboard to existing group");
+- return;
++ /* We apparently should not group virtual keyboards,
++ * so create a new group with it
++ */
++ if (!virtual) {
++ struct cg_keyboard_group *group;
++ wl_list_for_each (group, &seat->keyboard_groups, link) {
++ if (group->is_virtual)
++ continue;
++ struct wlr_keyboard_group *wlr_group = group->wlr_group;
++ if (wlr_keyboard_group_add_keyboard(wlr_group, keyboard)) {
++ wlr_log(WLR_DEBUG, "Added new keyboard to existing group");
++ return;
++ }
+ }
+ }
+
+@@ -315,6 +347,7 @@ cg_keyboard_group_add(struct wlr_input_device *device, struct cg_seat *seat)
+ return;
+ }
+ cg_group->seat = seat;
++ cg_group->is_virtual = virtual;
+ cg_group->wlr_group = wlr_keyboard_group_create();
+ if (cg_group->wlr_group == NULL) {
+ wlr_log(WLR_ERROR, "Failed to create wlr keyboard group.");
+@@ -322,14 +355,14 @@ cg_keyboard_group_add(struct wlr_input_device *device, struct cg_seat *seat)
+ }
+
+ cg_group->wlr_group->data = cg_group;
+- wlr_keyboard_set_keymap(&cg_group->wlr_group->keyboard, device->keyboard->keymap);
++ wlr_keyboard_set_keymap(&cg_group->wlr_group->keyboard, keyboard->keymap);
+
+- wlr_keyboard_set_repeat_info(&cg_group->wlr_group->keyboard, wlr_keyboard->repeat_info.rate,
+- wlr_keyboard->repeat_info.delay);
++ wlr_keyboard_set_repeat_info(&cg_group->wlr_group->keyboard, keyboard->repeat_info.rate,
++ keyboard->repeat_info.delay);
+
+ wlr_log(WLR_DEBUG, "Created keyboard group");
+
+- wlr_keyboard_group_add_keyboard(cg_group->wlr_group, wlr_keyboard);
++ wlr_keyboard_group_add_keyboard(cg_group->wlr_group, keyboard);
+ wl_list_insert(&seat->keyboard_groups, &cg_group->link);
+
+ wl_signal_add(&cg_group->wlr_group->keyboard.events.key, &cg_group->key);
+@@ -347,36 +380,45 @@ cleanup:
+ }
+
+ static void
+-handle_new_keyboard(struct cg_seat *seat, struct wlr_input_device *device)
++handle_new_keyboard(struct cg_seat *seat, struct wlr_keyboard *keyboard, bool virtual)
{
struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
if (!context) {
@@ -1288,7 +1651,136 @@ index 08f25a3..4dce511 100644
if (!keymap) {
wlr_log(WLR_ERROR, "Unable to configure keyboard: keymap does not exist");
xkb_context_unref(context);
-@@ -569,10 +554,7 @@ process_cursor_motion(struct cg_seat *seat, uint32_t time)
+ return;
+ }
+
+- wlr_keyboard_set_keymap(device->keyboard, keymap);
++ wlr_keyboard_set_keymap(keyboard, keymap);
+
+ xkb_keymap_unref(keymap);
+ xkb_context_unref(context);
+- wlr_keyboard_set_repeat_info(device->keyboard, 25, 600);
++ wlr_keyboard_set_repeat_info(keyboard, 25, 600);
++
++ cg_keyboard_group_add(keyboard, seat, virtual);
++
++ wlr_seat_set_keyboard(seat->seat, keyboard);
++}
+
+- cg_keyboard_group_add(device, seat);
++static void
++handle_virtual_keyboard(struct wl_listener *listener, void *data)
++{
++ struct cg_server *server = wl_container_of(listener, server, new_virtual_keyboard);
++ struct cg_seat *seat = server->seat;
++ struct wlr_virtual_keyboard_v1 *keyboard = data;
++ struct wlr_keyboard *wlr_keyboard = &keyboard->keyboard;
++
++ /* TODO: If multiple seats are supported, check keyboard->seat
++ * to select the appropriate one */
+
+- wlr_seat_set_keyboard(seat->seat, device);
++ handle_new_keyboard(seat, wlr_keyboard, true);
++ update_capabilities(seat);
+ }
+
+ static void
+@@ -387,13 +429,13 @@ handle_new_input(struct wl_listener *listener, void *data)
+
+ switch (device->type) {
+ case WLR_INPUT_DEVICE_KEYBOARD:
+- handle_new_keyboard(seat, device);
++ handle_new_keyboard(seat, wlr_keyboard_from_input_device(device), false);
+ break;
+ case WLR_INPUT_DEVICE_POINTER:
+- handle_new_pointer(seat, device);
++ handle_new_pointer(seat, wlr_pointer_from_input_device(device));
+ break;
+ case WLR_INPUT_DEVICE_TOUCH:
+- handle_new_touch(seat, device);
++ handle_new_touch(seat, wlr_touch_from_input_device(device));
+ break;
+ case WLR_INPUT_DEVICE_SWITCH:
+ wlr_log(WLR_DEBUG, "Switch input is not implemented");
+@@ -448,10 +490,10 @@ static void
+ handle_touch_down(struct wl_listener *listener, void *data)
+ {
+ struct cg_seat *seat = wl_container_of(listener, seat, touch_down);
+- struct wlr_event_touch_down *event = data;
++ struct wlr_touch_down_event *event = data;
+
+ double lx, ly;
+- wlr_cursor_absolute_to_layout_coords(seat->cursor, event->device, event->x, event->y, &lx, &ly);
++ wlr_cursor_absolute_to_layout_coords(seat->cursor, &event->touch->base, event->x, event->y, &lx, &ly);
+
+ double sx, sy;
+ struct wlr_surface *surface;
+@@ -466,7 +508,7 @@ handle_touch_down(struct wl_listener *listener, void *data)
+ seat->touch_id = event->touch_id;
+ seat->touch_lx = lx;
+ seat->touch_ly = ly;
+- press_cursor_button(seat, event->device, event->time_msec, BTN_LEFT, WLR_BUTTON_PRESSED, lx, ly);
++ press_cursor_button(seat, &event->touch->base, event->time_msec, BTN_LEFT, WLR_BUTTON_PRESSED, lx, ly);
+ }
+
+ wlr_idle_notify_activity(seat->server->idle, seat->seat);
+@@ -476,14 +518,14 @@ static void
+ handle_touch_up(struct wl_listener *listener, void *data)
+ {
+ struct cg_seat *seat = wl_container_of(listener, seat, touch_up);
+- struct wlr_event_touch_up *event = data;
++ struct wlr_touch_up_event *event = data;
+
+ if (!wlr_seat_touch_get_point(seat->seat, event->touch_id)) {
+ return;
+ }
+
+ if (wlr_seat_touch_num_points(seat->seat) == 1) {
+- press_cursor_button(seat, event->device, event->time_msec, BTN_LEFT, WLR_BUTTON_RELEASED,
++ press_cursor_button(seat, &event->touch->base, event->time_msec, BTN_LEFT, WLR_BUTTON_RELEASED,
+ seat->touch_lx, seat->touch_ly);
+ }
+
+@@ -495,14 +537,14 @@ static void
+ handle_touch_motion(struct wl_listener *listener, void *data)
+ {
+ struct cg_seat *seat = wl_container_of(listener, seat, touch_motion);
+- struct wlr_event_touch_motion *event = data;
++ struct wlr_touch_motion_event *event = data;
+
+ if (!wlr_seat_touch_get_point(seat->seat, event->touch_id)) {
+ return;
+ }
+
+ double lx, ly;
+- wlr_cursor_absolute_to_layout_coords(seat->cursor, event->device, event->x, event->y, &lx, &ly);
++ wlr_cursor_absolute_to_layout_coords(seat->cursor, &event->touch->base, event->x, event->y, &lx, &ly);
+
+ double sx, sy;
+ struct wlr_surface *surface;
+@@ -536,7 +578,7 @@ static void
+ handle_cursor_axis(struct wl_listener *listener, void *data)
+ {
+ struct cg_seat *seat = wl_container_of(listener, seat, cursor_axis);
+- struct wlr_event_pointer_axis *event = data;
++ struct wlr_pointer_axis_event *event = data;
+
+ wlr_seat_pointer_notify_axis(seat->seat, event->time_msec, event->orientation, event->delta,
+ event->delta_discrete, event->source);
+@@ -547,10 +589,10 @@ static void
+ handle_cursor_button(struct wl_listener *listener, void *data)
+ {
+ struct cg_seat *seat = wl_container_of(listener, seat, cursor_button);
+- struct wlr_event_pointer_button *event = data;
++ struct wlr_pointer_button_event *event = data;
+
+ wlr_seat_pointer_notify_button(seat->seat, event->time_msec, event->button, event->state);
+- press_cursor_button(seat, event->device, event->time_msec, event->button, event->state, seat->cursor->x,
++ press_cursor_button(seat, &event->pointer->base, event->time_msec, event->button, event->state, seat->cursor->x,
+ seat->cursor->y);
+ wlr_idle_notify_activity(seat->server->idle, seat->seat);
+ }
+@@ -569,10 +611,7 @@ process_cursor_motion(struct cg_seat *seat, uint32_t time)
} else {
wlr_seat_pointer_notify_enter(wlr_seat, surface, sx, sy);
@@ -1300,7 +1792,28 @@ index 08f25a3..4dce511 100644
}
struct cg_drag_icon *drag_icon;
-@@ -605,15 +587,6 @@ handle_cursor_motion(struct wl_listener *listener, void *data)
+@@ -587,9 +626,9 @@ static void
+ handle_cursor_motion_absolute(struct wl_listener *listener, void *data)
+ {
+ struct cg_seat *seat = wl_container_of(listener, seat, cursor_motion_absolute);
+- struct wlr_event_pointer_motion_absolute *event = data;
++ struct wlr_pointer_motion_absolute_event *event = data;
+
+- wlr_cursor_warp_absolute(seat->cursor, event->device, event->x, event->y);
++ wlr_cursor_warp_absolute(seat->cursor, &event->pointer->base, event->x, event->y);
+ process_cursor_motion(seat, event->time_msec);
+ wlr_idle_notify_activity(seat->server->idle, seat->seat);
+ }
+@@ -598,22 +637,13 @@ static void
+ handle_cursor_motion(struct wl_listener *listener, void *data)
+ {
+ struct cg_seat *seat = wl_container_of(listener, seat, cursor_motion);
+- struct wlr_event_pointer_motion *event = data;
++ struct wlr_pointer_motion_event *event = data;
+
+- wlr_cursor_move(seat->cursor, event->device, event->delta_x, event->delta_y);
++ wlr_cursor_move(seat->cursor, &event->pointer->base, event->delta_x, event->delta_y);
+ process_cursor_motion(seat, event->time_msec);
wlr_idle_notify_activity(seat->server->idle, seat->seat);
}
@@ -1316,7 +1829,7 @@ index 08f25a3..4dce511 100644
static void
drag_icon_update_position(struct cg_drag_icon *drag_icon)
{
-@@ -621,8 +594,6 @@ drag_icon_update_position(struct cg_drag_icon *drag_icon)
+@@ -621,8 +651,6 @@ drag_icon_update_position(struct cg_drag_icon *drag_icon)
struct cg_seat *seat = drag_icon->seat;
struct wlr_touch_point *point;
@@ -1325,36 +1838,46 @@ index 08f25a3..4dce511 100644
switch (wlr_icon->drag->grab_type) {
case WLR_DRAG_GRAB_KEYBOARD:
return;
-@@ -640,7 +611,7 @@ drag_icon_update_position(struct cg_drag_icon *drag_icon)
+@@ -640,7 +668,7 @@ drag_icon_update_position(struct cg_drag_icon *drag_icon)
break;
}
- drag_icon_damage(drag_icon);
-+ wlr_scene_node_set_position(drag_icon->scene_node, drag_icon->lx, drag_icon->ly);
++ wlr_scene_node_set_position(&drag_icon->scene_tree->node, drag_icon->lx, drag_icon->ly);
}
static void
-@@ -650,6 +621,7 @@ handle_drag_icon_destroy(struct wl_listener *listener, void *data)
+@@ -650,6 +678,7 @@ handle_drag_icon_destroy(struct wl_listener *listener, void *data)
wl_list_remove(&drag_icon->link);
wl_list_remove(&drag_icon->destroy.link);
-+ wlr_scene_node_destroy(drag_icon->scene_node);
++ wlr_scene_node_destroy(&drag_icon->scene_tree->node);
free(drag_icon);
}
-@@ -692,6 +664,11 @@ handle_start_drag(struct wl_listener *listener, void *data)
+@@ -692,6 +721,11 @@ handle_start_drag(struct wl_listener *listener, void *data)
}
drag_icon->seat = seat;
drag_icon->wlr_drag_icon = wlr_drag_icon;
-+ drag_icon->scene_node = wlr_scene_subsurface_tree_create(&seat->server->scene->node, wlr_drag_icon->surface);
-+ if (!drag_icon->scene_node) {
++ drag_icon->scene_tree = wlr_scene_subsurface_tree_create(&seat->server->scene->tree, wlr_drag_icon->surface);
++ if (!drag_icon->scene_tree) {
+ free(drag_icon);
+ return;
+ }
drag_icon->destroy.notify = handle_drag_icon_destroy;
wl_signal_add(&wlr_drag_icon->events.destroy, &drag_icon->destroy);
-@@ -840,7 +817,10 @@ struct cg_view *
+@@ -812,6 +846,9 @@ seat_create(struct cg_server *server, struct wlr_backend *backend)
+ seat->new_input.notify = handle_new_input;
+ wl_signal_add(&backend->events.new_input, &seat->new_input);
+
++ server->new_virtual_keyboard.notify = handle_virtual_keyboard;
++ server->new_virtual_pointer.notify = handle_virtual_pointer;
++
+ wl_list_init(&seat->drag_icons);
+ seat->request_start_drag.notify = handle_request_start_drag;
+ wl_signal_add(&seat->seat->events.request_start_drag, &seat->request_start_drag);
+@@ -840,7 +877,10 @@ struct cg_view *
seat_get_focus(struct cg_seat *seat)
{
struct wlr_surface *prev_surface = seat->seat->keyboard_state.focused_surface;
@@ -1367,22 +1890,57 @@ index 08f25a3..4dce511 100644
void
diff --git a/seat.h b/seat.h
-index 188543d..5fb2db3 100644
+index 188543d..52cbee4 100644
--- a/seat.h
+++ b/seat.h
-@@ -77,6 +77,7 @@ struct cg_drag_icon {
+@@ -55,12 +55,13 @@ struct cg_keyboard_group {
+ struct wl_listener key;
+ struct wl_listener modifiers;
+ struct wl_list link; // cg_seat::keyboard_groups
++ bool is_virtual;
+ };
+
+ struct cg_pointer {
+ struct wl_list link; // seat::pointers
+ struct cg_seat *seat;
+- struct wlr_input_device *device;
++ struct wlr_pointer *pointer;
+
+ struct wl_listener destroy;
+ };
+@@ -68,7 +69,7 @@ struct cg_pointer {
+ struct cg_touch {
+ struct wl_list link; // seat::touch
+ struct cg_seat *seat;
+- struct wlr_input_device *device;
++ struct wlr_touch *touch;
+
+ struct wl_listener destroy;
+ };
+@@ -77,6 +78,7 @@ struct cg_drag_icon {
struct wl_list link; // seat::drag_icons
struct cg_seat *seat;
struct wlr_drag_icon *wlr_drag_icon;
-+ struct wlr_scene_node *scene_node;
++ struct wlr_scene_tree *scene_tree;
/* The drag icon has a position in layout coordinates. */
double lx, ly;
diff --git a/server.h b/server.h
-index 817637b..bb7f3c1 100644
+index 817637b..082a435 100644
--- a/server.h
+++ b/server.h
-@@ -25,6 +25,8 @@ struct cg_server {
+@@ -12,10 +12,6 @@
+ #include
+ #endif
+
+-#include "output.h"
+-#include "seat.h"
+-#include "view.h"
+-
+ enum cg_multi_output_mode {
+ CAGE_MULTI_OUTPUT_MODE_EXTEND,
+ CAGE_MULTI_OUTPUT_MODE_LAST,
+@@ -25,6 +21,8 @@ struct cg_server {
struct wl_display *wl_display;
struct wl_list views;
struct wlr_backend *backend;
@@ -1391,7 +1949,7 @@ index 817637b..bb7f3c1 100644
struct cg_seat *seat;
struct wlr_idle *idle;
-@@ -34,6 +36,7 @@ struct cg_server {
+@@ -34,6 +32,7 @@ struct cg_server {
enum cg_multi_output_mode output_mode;
struct wlr_output_layout *output_layout;
@@ -1399,7 +1957,17 @@ index 817637b..bb7f3c1 100644
/* Includes disabled outputs; depending on the output_mode
* some outputs may be disabled. */
struct wl_list outputs; // cg_output::link
-@@ -48,9 +51,6 @@ struct cg_server {
+@@ -41,6 +40,9 @@ struct cg_server {
+
+ struct wl_listener xdg_toplevel_decoration;
+ struct wl_listener new_xdg_shell_surface;
++
++ struct wl_listener new_virtual_keyboard;
++ struct wl_listener new_virtual_pointer;
+ #if CAGE_HAS_XWAYLAND
+ struct wl_listener new_xwayland_surface;
+ #endif
+@@ -48,9 +50,6 @@ struct cg_server {
bool xdg_decoration;
bool allow_vt_switch;
enum wl_output_transform output_transform;
@@ -1469,10 +2037,10 @@ index db6bc7d..0000000
-
-#endif
diff --git a/view.c b/view.c
-index 3f3b0ed..6551142 100644
+index 3f3b0ed..b4a3eca 100644
--- a/view.c
+++ b/view.c
-@@ -1,19 +1,20 @@
+@@ -1,20 +1,20 @@
/*
* Cage: A Wayland kiosk.
*
@@ -1491,11 +2059,12 @@ index 3f3b0ed..6551142 100644
#include
-#include
#include
+-#include
+#include
- #include
#include "output.h"
-@@ -24,96 +25,6 @@
+ #include "seat.h"
+@@ -24,96 +24,6 @@
#include "xwayland.h"
#endif
@@ -1592,7 +2161,7 @@ index 3f3b0ed..6551142 100644
char *
view_get_title(struct cg_view *view)
{
-@@ -136,24 +47,6 @@ view_is_transient_for(struct cg_view *child, struct cg_view *parent)
+@@ -136,24 +46,6 @@ view_is_transient_for(struct cg_view *child, struct cg_view *parent)
return child->impl->is_transient_for(child, parent);
}
@@ -1617,29 +2186,40 @@ index 3f3b0ed..6551142 100644
void
view_activate(struct cg_view *view, bool activate)
{
-@@ -174,6 +67,9 @@ view_maximize(struct cg_view *view, struct wlr_box *layout_box)
+@@ -174,6 +66,9 @@ view_maximize(struct cg_view *view, struct wlr_box *layout_box)
{
view->lx = layout_box->x;
view->ly = layout_box->y;
+
-+ wlr_scene_node_set_position(view->scene_node, view->lx, view->ly);
++ wlr_scene_node_set_position(&view->scene_tree->node, view->lx, view->ly);
+
view->impl->maximize(view, layout_box->width, layout_box->height);
}
-@@ -185,6 +81,8 @@ view_center(struct cg_view *view, struct wlr_box *layout_box)
+@@ -185,33 +80,21 @@ view_center(struct cg_view *view, struct wlr_box *layout_box)
view->lx = (layout_box->width - width) / 2;
view->ly = (layout_box->height - height) / 2;
+
-+ wlr_scene_node_set_position(view->scene_node, view->lx, view->ly);
++ wlr_scene_node_set_position(&view->scene_tree->node, view->lx, view->ly);
}
void
-@@ -199,51 +97,29 @@ view_position(struct cg_view *view)
- }
- }
+ view_position(struct cg_view *view)
+ {
+- struct wlr_box *layout_box = wlr_output_layout_get_box(view->server->output_layout, NULL);
++ struct wlr_box layout_box;
++ wlr_output_layout_get_box(view->server->output_layout, NULL, &layout_box);
+- if (view_is_primary(view) || view_extends_output_layout(view, layout_box)) {
+- view_maximize(view, layout_box);
++ if (view_is_primary(view) || view_extends_output_layout(view, &layout_box)) {
++ view_maximize(view, &layout_box);
+ } else {
+- view_center(view, layout_box);
+- }
+-}
+-
-void
-view_for_each_surface(struct cg_view *view, wlr_surface_iterator_func_t iterator, void *data)
-{
@@ -1651,12 +2231,13 @@ index 3f3b0ed..6551142 100644
-{
- if (!view->impl->for_each_popup_surface) {
- return;
-- }
++ view_center(view, &layout_box);
+ }
- view->impl->for_each_popup_surface(view, iterator, data);
--}
--
+ }
+
void
- view_unmap(struct cg_view *view)
+@@ -219,31 +102,24 @@ view_unmap(struct cg_view *view)
{
wl_list_remove(&view->link);
@@ -1666,7 +2247,7 @@ index 3f3b0ed..6551142 100644
- wl_list_for_each_safe (child, tmp, &view->children, link) {
- child->destroy(child);
- }
-+ wlr_scene_node_destroy(view->scene_node);
++ wlr_scene_node_destroy(&view->scene_tree->node);
+ view->wlr_surface->data = NULL;
view->wlr_surface = NULL;
@@ -1683,12 +2264,12 @@ index 3f3b0ed..6551142 100644
- }
- wl_list_for_each (subsurface, &view->wlr_surface->subsurfaces_above, parent_link) {
- subsurface_create(view, subsurface);
-+ view->scene_node = wlr_scene_subsurface_tree_create(&view->server->scene->node, surface);
-+ if (!view->scene_node) {
++ view->scene_tree = wlr_scene_subsurface_tree_create(&view->server->scene->tree, surface);
++ if (!view->scene_tree) {
+ wl_resource_post_no_memory(surface->resource);
+ return;
}
-+ view->scene_node->data = view;
++ view->scene_tree->node.data = view;
- view->new_subsurface.notify = handle_new_subsurface;
- wl_signal_add(&view->wlr_surface->events.new_subsurface, &view->new_subsurface);
@@ -1726,7 +2307,7 @@ index 3f3b0ed..6551142 100644
+ return surface->data;
}
diff --git a/view.h b/view.h
-index cd16e42..677a949 100644
+index cd16e42..5ae13dd 100644
--- a/view.h
+++ b/view.h
@@ -5,9 +5,9 @@
@@ -1734,7 +2315,8 @@ index cd16e42..677a949 100644
#include
#include
-#include
- #include
+-#include
++#include
#include
+#include
#if CAGE_HAS_XWAYLAND
@@ -1746,7 +2328,7 @@ index cd16e42..677a949 100644
struct wl_list link; // server::views
- struct wl_list children; // cg_view_child::link
struct wlr_surface *wlr_surface;
-+ struct wlr_scene_node *scene_node;
++ struct wlr_scene_tree *scene_tree;
/* The view has a position in layout coordinates. */
int lx, ly;
@@ -1808,7 +2390,7 @@ index cd16e42..677a949 100644
#endif
diff --git a/xdg_shell.c b/xdg_shell.c
-index 2e42347..ede71f4 100644
+index 2e42347..c577dc5 100644
--- a/xdg_shell.c
+++ b/xdg_shell.c
@@ -6,10 +6,11 @@
@@ -1824,7 +2406,7 @@ index 2e42347..ede71f4 100644
#include
#include
-@@ -41,60 +42,32 @@ xdg_decoration_handle_request_mode(struct wl_listener *listener, void *data)
+@@ -41,105 +42,47 @@ xdg_decoration_handle_request_mode(struct wl_listener *listener, void *data)
wlr_xdg_toplevel_decoration_v1_set_mode(xdg_decoration->wlr_decoration, mode);
}
@@ -1846,16 +2428,16 @@ index 2e42347..ede71f4 100644
-
-static void
-handle_xdg_popup_map(struct wl_listener *listener, void *data)
-+static struct cg_view *
-+popup_get_view(struct wlr_xdg_popup *popup)
- {
+-{
- struct cg_xdg_popup *popup = wl_container_of(listener, popup, map);
- view_damage_whole(popup->view_child.view);
-}
-
-static void
-handle_xdg_popup_unmap(struct wl_listener *listener, void *data)
--{
++static struct cg_view *
++popup_get_view(struct wlr_xdg_popup *popup)
+ {
- struct cg_xdg_popup *popup = wl_container_of(listener, popup, unmap);
- view_damage_whole(popup->view_child.view);
-}
@@ -1900,12 +2482,24 @@ index 2e42347..ede71f4 100644
- struct cg_view *view = popup->view_child.view;
struct cg_server *server = view->server;
- struct wlr_box *popup_box = &popup->wlr_popup->geometry;
-+ struct wlr_box *popup_box = &popup->geometry;
++ struct wlr_box *popup_box = &popup->current.geometry;
struct wlr_output_layout *output_layout = server->output_layout;
struct wlr_output *wlr_output =
-@@ -108,38 +81,7 @@ popup_unconstrain(struct cg_xdg_popup *popup)
- .height = output_box->height,
+ wlr_output_layout_output_at(output_layout, view->lx + popup_box->x, view->ly + popup_box->y);
+- struct wlr_box *output_box = wlr_output_layout_get_box(output_layout, wlr_output);
++ struct wlr_box output_box;
++ wlr_output_layout_get_box(output_layout, wlr_output, &output_box);
+
+ struct wlr_box output_toplevel_box = {
+- .x = output_box->x - view->lx,
+- .y = output_box->y - view->ly,
+- .width = output_box->width,
+- .height = output_box->height,
++ .x = output_box.x - view->lx,
++ .y = output_box.y - view->ly,
++ .width = output_box.width,
++ .height = output_box.height,
};
- wlr_xdg_popup_unconstrain_from_box(popup->wlr_popup, &output_toplevel_box);
@@ -1944,23 +2538,76 @@ index 2e42347..ede71f4 100644
}
static struct cg_xdg_shell_view *
-@@ -170,9 +112,12 @@ static bool
+@@ -152,7 +95,7 @@ static char *
+ get_title(struct cg_view *view)
+ {
+ struct cg_xdg_shell_view *xdg_shell_view = xdg_shell_view_from_view(view);
+- return xdg_shell_view->xdg_surface->toplevel->title;
++ return xdg_shell_view->xdg_toplevel->title;
+ }
+
+ static void
+@@ -161,7 +104,7 @@ get_geometry(struct cg_view *view, int *width_out, int *height_out)
+ struct cg_xdg_shell_view *xdg_shell_view = xdg_shell_view_from_view(view);
+ struct wlr_box geom;
+
+- wlr_xdg_surface_get_geometry(xdg_shell_view->xdg_surface, &geom);
++ wlr_xdg_surface_get_geometry(xdg_shell_view->xdg_toplevel->base, &geom);
+ *width_out = geom.width;
+ *height_out = geom.height;
+ }
+@@ -170,9 +113,9 @@ static bool
is_primary(struct cg_view *view)
{
struct cg_xdg_shell_view *xdg_shell_view = xdg_shell_view_from_view(view);
- struct wlr_xdg_surface *parent = xdg_shell_view->xdg_surface->toplevel->parent;
- /* FIXME: role is 0? */
- return parent == NULL; /*&& role == WLR_XDG_SURFACE_ROLE_TOPLEVEL */
-+ struct wlr_xdg_surface *xdg_surface = xdg_shell_view->xdg_surface;
++ struct wlr_xdg_toplevel *parent = xdg_shell_view->xdg_toplevel->parent;
+
-+ struct wlr_xdg_surface *parent = xdg_surface->toplevel->parent;
-+ enum wlr_xdg_surface_role role = xdg_surface->role;
-+
-+ return parent == NULL && role == WLR_XDG_SURFACE_ROLE_TOPLEVEL;
++ return parent == NULL;
}
static bool
-@@ -216,41 +161,20 @@ destroy(struct cg_view *view)
+@@ -182,14 +125,13 @@ is_transient_for(struct cg_view *child, struct cg_view *parent)
+ return false;
+ }
+ struct cg_xdg_shell_view *_child = xdg_shell_view_from_view(child);
+- struct wlr_xdg_surface *xdg_surface = _child->xdg_surface;
++ struct wlr_xdg_toplevel *xdg_toplevel = _child->xdg_toplevel;
+ struct cg_xdg_shell_view *_parent = xdg_shell_view_from_view(parent);
+- struct wlr_xdg_surface *parent_xdg_surface = _parent->xdg_surface;
+- while (xdg_surface) {
+- if (xdg_surface->toplevel->parent == parent_xdg_surface) {
++ while (xdg_toplevel) {
++ if (xdg_toplevel->parent == _parent->xdg_toplevel) {
+ return true;
+ }
+- xdg_surface = xdg_surface->toplevel->parent;
++ xdg_toplevel = xdg_toplevel->parent;
+ }
+ return false;
+ }
+@@ -198,15 +140,15 @@ static void
+ activate(struct cg_view *view, bool activate)
+ {
+ struct cg_xdg_shell_view *xdg_shell_view = xdg_shell_view_from_view(view);
+- wlr_xdg_toplevel_set_activated(xdg_shell_view->xdg_surface, activate);
++ wlr_xdg_toplevel_set_activated(xdg_shell_view->xdg_toplevel, activate);
+ }
+
+ static void
+ maximize(struct cg_view *view, int output_width, int output_height)
+ {
+ struct cg_xdg_shell_view *xdg_shell_view = xdg_shell_view_from_view(view);
+- wlr_xdg_toplevel_set_size(xdg_shell_view->xdg_surface, output_width, output_height);
+- wlr_xdg_toplevel_set_maximized(xdg_shell_view->xdg_surface, true);
++ wlr_xdg_toplevel_set_size(xdg_shell_view->xdg_toplevel, output_width, output_height);
++ wlr_xdg_toplevel_set_maximized(xdg_shell_view->xdg_toplevel, true);
+ }
+
+ static void
+@@ -216,41 +158,21 @@ destroy(struct cg_view *view)
free(xdg_shell_view);
}
@@ -1989,7 +2636,7 @@ index 2e42347..ede71f4 100644
handle_xdg_shell_surface_request_fullscreen(struct wl_listener *listener, void *data)
{
struct cg_xdg_shell_view *xdg_shell_view = wl_container_of(listener, xdg_shell_view, request_fullscreen);
- struct wlr_xdg_toplevel_set_fullscreen_event *event = data;
+- struct wlr_xdg_toplevel_set_fullscreen_event *event = data;
- wlr_xdg_toplevel_set_fullscreen(xdg_shell_view->xdg_surface, event->fullscreen);
-}
@@ -2003,14 +2650,16 @@ index 2e42347..ede71f4 100644
+ * Certain clients do not like figuring out their own window geometry if they
+ * display in fullscreen mode, so we set it here.
+ */
-+ struct wlr_box *layout_box = wlr_output_layout_get_box(xdg_shell_view->view.server->output_layout, NULL);
-+ wlr_xdg_toplevel_set_size(xdg_shell_view->xdg_surface, layout_box->width, layout_box->height);
++ struct wlr_box layout_box;
++ wlr_output_layout_get_box(xdg_shell_view->view.server->output_layout, NULL, &layout_box);
++ wlr_xdg_toplevel_set_size(xdg_shell_view->xdg_toplevel, layout_box.width, layout_box.height);
+
-+ wlr_xdg_toplevel_set_fullscreen(xdg_shell_view->xdg_surface, event->fullscreen);
++ wlr_xdg_toplevel_set_fullscreen(xdg_shell_view->xdg_toplevel,
++ xdg_shell_view->xdg_toplevel->requested.fullscreen);
}
static void
-@@ -259,10 +183,6 @@ handle_xdg_shell_surface_unmap(struct wl_listener *listener, void *data)
+@@ -259,10 +181,6 @@ handle_xdg_shell_surface_unmap(struct wl_listener *listener, void *data)
struct cg_xdg_shell_view *xdg_shell_view = wl_container_of(listener, xdg_shell_view, unmap);
struct cg_view *view = &xdg_shell_view->view;
@@ -2021,28 +2670,31 @@ index 2e42347..ede71f4 100644
view_unmap(view);
}
-@@ -272,12 +192,7 @@ handle_xdg_shell_surface_map(struct wl_listener *listener, void *data)
+@@ -272,12 +190,7 @@ handle_xdg_shell_surface_map(struct wl_listener *listener, void *data)
struct cg_xdg_shell_view *xdg_shell_view = wl_container_of(listener, xdg_shell_view, map);
struct cg_view *view = &xdg_shell_view->view;
- xdg_shell_view->commit.notify = handle_xdg_shell_surface_commit;
- wl_signal_add(&xdg_shell_view->xdg_surface->surface->events.commit, &xdg_shell_view->commit);
-
- view_map(view, xdg_shell_view->xdg_surface->surface);
+- view_map(view, xdg_shell_view->xdg_surface->surface);
-
- view_damage_whole(view);
++ view_map(view, xdg_shell_view->xdg_toplevel->base->surface);
}
static void
-@@ -290,7 +205,6 @@ handle_xdg_shell_surface_destroy(struct wl_listener *listener, void *data)
+@@ -290,8 +203,7 @@ handle_xdg_shell_surface_destroy(struct wl_listener *listener, void *data)
wl_list_remove(&xdg_shell_view->unmap.link);
wl_list_remove(&xdg_shell_view->destroy.link);
wl_list_remove(&xdg_shell_view->request_fullscreen.link);
- wl_list_remove(&xdg_shell_view->new_popup.link);
- xdg_shell_view->xdg_surface = NULL;
+- xdg_shell_view->xdg_surface = NULL;
++ xdg_shell_view->xdg_toplevel = NULL;
view_destroy(view);
-@@ -304,9 +218,6 @@ static const struct cg_view_impl xdg_shell_view_impl = {
+ }
+@@ -304,9 +216,6 @@ static const struct cg_view_impl xdg_shell_view_impl = {
.activate = activate,
.maximize = maximize,
.destroy = destroy,
@@ -2052,7 +2704,7 @@ index 2e42347..ede71f4 100644
};
void
-@@ -315,29 +226,64 @@ handle_xdg_shell_surface_new(struct wl_listener *listener, void *data)
+@@ -315,29 +224,64 @@ handle_xdg_shell_surface_new(struct wl_listener *listener, void *data)
struct cg_server *server = wl_container_of(listener, server, new_xdg_shell_surface);
struct wlr_xdg_surface *xdg_surface = data;
@@ -2073,7 +2725,7 @@ index 2e42347..ede71f4 100644
- return;
- }
+ view_init(&xdg_shell_view->view, server, CAGE_XDG_SHELL_VIEW, &xdg_shell_view_impl);
-+ xdg_shell_view->xdg_surface = xdg_surface;
++ xdg_shell_view->xdg_toplevel = xdg_surface->toplevel;
+
+ xdg_shell_view->map.notify = handle_xdg_shell_surface_map;
+ wl_signal_add(&xdg_surface->events.map, &xdg_shell_view->map);
@@ -2093,19 +2745,19 @@ index 2e42347..ede71f4 100644
+ return;
+ }
+
-+ struct wlr_scene_node *parent_scene_node = NULL;
++ struct wlr_scene_tree *parent_scene_tree = NULL;
+ struct wlr_xdg_surface *parent = wlr_xdg_surface_from_wlr_surface(popup->parent);
+ switch (parent->role) {
+ case WLR_XDG_SURFACE_ROLE_TOPLEVEL:;
-+ parent_scene_node = view->scene_node;
++ parent_scene_tree = view->scene_tree;
+ break;
+ case WLR_XDG_SURFACE_ROLE_POPUP:
-+ parent_scene_node = parent->data;
++ parent_scene_tree = parent->data;
+ break;
+ case WLR_XDG_SURFACE_ROLE_NONE:
+ break;
+ }
-+ if (parent_scene_node == NULL) {
++ if (parent_scene_tree == NULL) {
+ return;
+ }
@@ -2122,15 +2774,15 @@ index 2e42347..ede71f4 100644
- wl_signal_add(&xdg_surface->toplevel->events.request_fullscreen, &xdg_shell_view->request_fullscreen);
- xdg_shell_view->new_popup.notify = handle_new_xdg_popup;
- wl_signal_add(&xdg_surface->events.new_popup, &xdg_shell_view->new_popup);
-+ struct wlr_scene_node *popup_scene_node = wlr_scene_xdg_surface_create(parent_scene_node, xdg_surface);
-+ if (popup_scene_node == NULL) {
++ struct wlr_scene_tree *popup_scene_tree = wlr_scene_xdg_surface_create(parent_scene_tree, xdg_surface);
++ if (popup_scene_tree == NULL) {
+ wlr_log(WLR_ERROR, "Failed to allocate scene-graph node for XDG popup");
+ return;
+ }
+
+ popup_unconstrain(view, popup);
+
-+ xdg_surface->data = popup_scene_node;
++ xdg_surface->data = popup_scene_tree;
+ break;
+ case WLR_XDG_SURFACE_ROLE_NONE:
+ assert(false); // unreachable
@@ -2139,10 +2791,16 @@ index 2e42347..ede71f4 100644
void
diff --git a/xdg_shell.h b/xdg_shell.h
-index 45d87db..9a101c6 100644
+index 45d87db..2fd506a 100644
--- a/xdg_shell.h
+++ b/xdg_shell.h
-@@ -14,19 +14,7 @@ struct cg_xdg_shell_view {
+@@ -9,24 +9,12 @@
+
+ struct cg_xdg_shell_view {
+ struct cg_view view;
+- struct wlr_xdg_surface *xdg_surface;
++ struct wlr_xdg_toplevel *xdg_toplevel;
+
struct wl_listener destroy;
struct wl_listener unmap;
struct wl_listener map;
diff --git a/cage-vi/virtual_input.patch b/cage-vi/virtual_input.patch
deleted file mode 100644
index a34b567..0000000
--- a/cage-vi/virtual_input.patch
+++ /dev/null
@@ -1,218 +0,0 @@
-From 99956cd5301ad1c19e3a3d07e022c942ca8b312d Mon Sep 17 00:00:00 2001
-From: Dominique Martinet
-Date: Tue, 18 May 2021 08:52:06 +0900
-Subject: [PATCH 1/2] seat: add wlr_virtual_keyboard_manager_v1
-
----
- seat.c | 43 ++++++++++++++++++++++++++++++++++++-------
- seat.h | 4 ++++
- 2 files changed, 40 insertions(+), 7 deletions(-)
-
-diff --git a/seat.c b/seat.c
-index 08f25a3..d8556f6 100644
---- a/seat.c
-+++ b/seat.c
-@@ -21,6 +21,7 @@
- #include
- #include
- #include
-+#include
- #include
- #include
- #if CAGE_HAS_XWAYLAND
-@@ -294,10 +295,16 @@ handle_keyboard_group_modifiers(struct wl_listener *listener, void *data)
- }
-
- static void
--cg_keyboard_group_add(struct wlr_input_device *device, struct cg_seat *seat)
-+cg_keyboard_group_add(struct wlr_input_device *device, struct cg_seat *seat, bool virtual)
- {
- struct wlr_keyboard *wlr_keyboard = device->keyboard;
-
-+ if (virtual)
-+ /* We apparently should not group virtual keyboards,
-+ * so create a new group with it
-+ */
-+ goto create_new;
-+
- struct cg_keyboard_group *group;
- wl_list_for_each (group, &seat->keyboard_groups, link) {
- struct wlr_keyboard_group *wlr_group = group->wlr_group;
-@@ -309,7 +316,9 @@ cg_keyboard_group_add(struct wlr_input_device *device, struct cg_seat *seat)
-
- /* This is reached if and only if the keyboard could not be inserted into
- * any group */
-- struct cg_keyboard_group *cg_group = calloc(1, sizeof(struct cg_keyboard_group));
-+ struct cg_keyboard_group *cg_group;
-+create_new:
-+ cg_group = calloc(1, sizeof(struct cg_keyboard_group));
- if (cg_group == NULL) {
- wlr_log(WLR_ERROR, "Failed to allocate keyboard group.");
- return;
-@@ -322,7 +331,7 @@ cg_keyboard_group_add(struct wlr_input_device *device, struct cg_seat *seat)
- }
-
- cg_group->wlr_group->data = cg_group;
-- wlr_keyboard_set_keymap(&cg_group->wlr_group->keyboard, device->keyboard->keymap);
-+ wlr_keyboard_set_keymap(&cg_group->wlr_group->keyboard, wlr_keyboard->keymap);
-
- wlr_keyboard_set_repeat_info(&cg_group->wlr_group->keyboard, wlr_keyboard->repeat_info.rate,
- wlr_keyboard->repeat_info.delay);
-@@ -330,7 +339,10 @@ cg_keyboard_group_add(struct wlr_input_device *device, struct cg_seat *seat)
- wlr_log(WLR_DEBUG, "Created keyboard group");
-
- wlr_keyboard_group_add_keyboard(cg_group->wlr_group, wlr_keyboard);
-- wl_list_insert(&seat->keyboard_groups, &cg_group->link);
-+ if (!virtual)
-+ wl_list_insert(&seat->keyboard_groups, &cg_group->link);
-+ else
-+ wl_list_init(&cg_group->link);
-
- wl_signal_add(&cg_group->wlr_group->keyboard.events.key, &cg_group->key);
- cg_group->key.notify = handle_keyboard_group_key;
-@@ -347,7 +359,7 @@ cg_keyboard_group_add(struct wlr_input_device *device, struct cg_seat *seat)
- }
-
- static void
--handle_new_keyboard(struct cg_seat *seat, struct wlr_input_device *device)
-+handle_new_keyboard(struct cg_seat *seat, struct wlr_input_device *device, bool virtual)
- {
- struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
- if (!context) {
-@@ -374,11 +386,24 @@ handle_new_keyboard(struct cg_seat *seat, struct wlr_input_device *device)
- xkb_context_unref(context);
- wlr_keyboard_set_repeat_info(device->keyboard, 25, 600);
-
-- cg_keyboard_group_add(device, seat);
-+ cg_keyboard_group_add(device, seat, virtual);
-
- wlr_seat_set_keyboard(seat->seat, device);
- }
-
-+static void
-+handle_virtual_keyboard(struct wl_listener *listener, void *data)
-+{
-+ struct cg_seat *seat = wl_container_of(listener, seat, new_virtual_keyboard);
-+ struct wlr_virtual_keyboard_v1 *keyboard = data;
-+ struct wlr_input_device *device = &keyboard->input_device;
-+
-+ /* If multiple seats are supported, check keyboard->seat
-+ * to select the appropriate one */
-+
-+ handle_new_keyboard(seat, device, true);
-+}
-+
- static void
- handle_new_input(struct wl_listener *listener, void *data)
- {
-@@ -387,7 +412,7 @@ handle_new_input(struct wl_listener *listener, void *data)
-
- switch (device->type) {
- case WLR_INPUT_DEVICE_KEYBOARD:
-- handle_new_keyboard(seat, device);
-+ handle_new_keyboard(seat, device, false);
- break;
- case WLR_INPUT_DEVICE_POINTER:
- handle_new_pointer(seat, device);
-@@ -818,6 +843,10 @@ seat_create(struct cg_server *server, struct wlr_backend *backend)
- seat->start_drag.notify = handle_start_drag;
- wl_signal_add(&seat->seat->events.start_drag, &seat->start_drag);
-
-+ seat->virtual_keyboard = wlr_virtual_keyboard_manager_v1_create(server->wl_display);
-+ wl_signal_add(&seat->virtual_keyboard->events.new_virtual_keyboard, &seat->new_virtual_keyboard);
-+ seat->new_virtual_keyboard.notify = handle_virtual_keyboard;
-+
- return seat;
- }
-
-diff --git a/seat.h b/seat.h
-index 188543d..428801a 100644
---- a/seat.h
-+++ b/seat.h
-@@ -25,6 +25,10 @@ struct cg_seat {
- struct wl_list touch;
- struct wl_listener new_input;
-
-+ // These belong to higher level if multiple seats are allowed
-+ struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard;
-+ struct wl_listener new_virtual_keyboard;
-+
- struct wlr_cursor *cursor;
- struct wlr_xcursor_manager *xcursor_manager;
- struct wl_listener cursor_motion;
-
-From 9d2e1c2131c27fd656f37580689fce92a663dad0 Mon Sep 17 00:00:00 2001
-From: Dominique Martinet
-Date: Tue, 18 May 2021 08:52:22 +0900
-Subject: [PATCH 2/2] seat: add wlr_virtual_pointer_manager_v1
-
-together with the previous patch, wayvnc can now be used with cage:
- $ cage something
- # figure out which wayland socket cage used
- $ WAYLAND_DISPLAY=wayland-0 wayvnc
-
-Note this does not appear to work with headless backend, e.g. starting cage with
-WLR_BACKENDS=headless WLR_LIBINPUT_NO_DEVICES=1 cage something
-does start and wayvnc connects/displays output, but there are tons of errors
-and input does not work
----
- seat.c | 17 +++++++++++++++++
- seat.h | 2 ++
- 2 files changed, 19 insertions(+)
-
-diff --git a/seat.c b/seat.c
-index d8556f6..9bf6672 100644
---- a/seat.c
-+++ b/seat.c
-@@ -22,6 +22,7 @@
- #include
- #include
- #include
-+#include
- #include
- #include
- #if CAGE_HAS_XWAYLAND
-@@ -216,6 +217,18 @@ handle_new_pointer(struct cg_seat *seat, struct wlr_input_device *device)
- map_input_device_to_output(seat, device);
- }
-
-+static void
-+handle_virtual_pointer(struct wl_listener *listener, void *data)
-+{
-+ struct cg_seat *seat = wl_container_of(listener, seat, new_virtual_pointer);
-+ struct wlr_virtual_pointer_v1_new_pointer_event *event = data;
-+ struct wlr_virtual_pointer_v1 *pointer = event->new_pointer;
-+ struct wlr_input_device *device = &pointer->input_device;
-+
-+ /* event->suggested_seat should be checked if we handle multiple seats */
-+ handle_new_pointer(seat, device);
-+}
-+
- static void
- handle_modifier_event(struct wlr_input_device *device, struct cg_seat *seat)
- {
-@@ -847,6 +860,10 @@ seat_create(struct cg_server *server, struct wlr_backend *backend)
- wl_signal_add(&seat->virtual_keyboard->events.new_virtual_keyboard, &seat->new_virtual_keyboard);
- seat->new_virtual_keyboard.notify = handle_virtual_keyboard;
-
-+ seat->virtual_pointer = wlr_virtual_pointer_manager_v1_create(server->wl_display);
-+ wl_signal_add(&seat->virtual_pointer->events.new_virtual_pointer, &seat->new_virtual_pointer);
-+ seat->new_virtual_pointer.notify = handle_virtual_pointer;
-+
- return seat;
- }
-
-diff --git a/seat.h b/seat.h
-index 428801a..0f6de59 100644
---- a/seat.h
-+++ b/seat.h
-@@ -27,7 +27,9 @@ struct cg_seat {
-
- // These belong to higher level if multiple seats are allowed
- struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard;
-+ struct wlr_virtual_pointer_manager_v1 *virtual_pointer;
- struct wl_listener new_virtual_keyboard;
-+ struct wl_listener new_virtual_pointer;
-
- struct wlr_cursor *cursor;
- struct wlr_xcursor_manager *xcursor_manager;