Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package cage for openSUSE:Factory checked in 
at 2023-08-02 16:49:01
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/cage (Old)
 and      /work/SRC/openSUSE:Factory/.cage.new.22712 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "cage"

Wed Aug  2 16:49:01 2023 rev:2 rq:1101959 version:0.1.5+0.83ffc57

Changes:
--------
--- /work/SRC/openSUSE:Factory/cage/cage.changes        2022-12-02 
13:13:09.301857734 +0100
+++ /work/SRC/openSUSE:Factory/.cage.new.22712/cage.changes     2023-08-02 
16:50:36.845561003 +0200
@@ -1,0 +2,12 @@
+Mon Jul 31 05:46:16 UTC 2023 - Michael Vetter <[email protected]>
+
+- Update to 0.1.5:
+  * Implement the following protocols: wlr-output-management-unstable-v1,
+    virtual-keyboard-unstable-v1, wlr-virtual-pointer-unstable-v1,
+    single-pixel-buffer-v1, presentation-time, viewporter.
+  * Use wlroots' scene-graph API, which should improve performance.
+  * Fall back to lower resolutions when the preferred output
+    mode cannot be used.
+- Drop cage-wlroots-016-compat.patch
+
+-------------------------------------------------------------------

Old:
----
  cage-0.1.4+39.a81ab70.obscpio
  cage-0.1.4+39.a81ab70.tar.gz
  cage-wlroots-016-compat.patch

New:
----
  cage-0.1.5+0.83ffc57.obscpio

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ cage.spec ++++++
--- /var/tmp/diff_new_pack.jdTBjW/_old  2023-08-02 16:50:37.533565159 +0200
+++ /var/tmp/diff_new_pack.jdTBjW/_new  2023-08-02 16:50:37.537565184 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package cage
 #
-# Copyright (c) 2021 SUSE LLC
+# Copyright (c) 2023 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -17,14 +17,13 @@
 
 
 Name:           cage
-Version:        0.1.4+39.a81ab70
+Version:        0.1.5+0.83ffc57
 Release:        0
 Summary:        Wayland Kiosk
 License:        MIT
 Group:          System/GUI/Other
 URL:            https://www.hjdskes.nl/projects/cage/
 Source:         %{name}-%{version}.tar.gz
-Patch0:         
https://patch-diff.githubusercontent.com/raw/Hjdskes/cage/pull/244.patch#/cage-wlroots-016-compat.patch
 BuildRequires:  meson >= 0.43.0
 BuildRequires:  pkgconfig
 BuildRequires:  scdoc
@@ -39,7 +38,6 @@
 
 %prep
 %setup -q -n %{name}-%{version}
-%patch0 -p1
 
 %build
 %meson

++++++ _service ++++++
--- /var/tmp/diff_new_pack.jdTBjW/_old  2023-08-02 16:50:37.577565426 +0200
+++ /var/tmp/diff_new_pack.jdTBjW/_new  2023-08-02 16:50:37.581565449 +0200
@@ -3,7 +3,7 @@
   <service name="obs_scm" mode="disabled">
     <param name="url">https://github.com/Hjdskes/cage.git</param>
     <param name="scm">git</param>
-    <param name="revision">a81ab70</param>
+    <param name="revision">v0.1.5</param>
     <param name="versionformat">@PARENT_TAG@+@TAG_OFFSET@.%h</param>
     <param name="match-tag">*</param>
     <param name="versionrewrite-pattern">v(\d+\.\d+\.\d+)</param>

++++++ cage-0.1.4+39.a81ab70.obscpio -> cage-0.1.5+0.83ffc57.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cage-0.1.4+39.a81ab70/.github/workflows/main.yml 
new/cage-0.1.5+0.83ffc57/.github/workflows/main.yml
--- old/cage-0.1.4+39.a81ab70/.github/workflows/main.yml        2022-08-19 
11:59:41.000000000 +0200
+++ new/cage-0.1.5+0.83ffc57/.github/workflows/main.yml 2023-07-28 
16:46:37.000000000 +0200
@@ -22,7 +22,7 @@
 
       - 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'"
@@ -31,7 +31,7 @@
           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 }})
@@ -48,9 +48,9 @@
       - 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
@@ -67,9 +67,9 @@
       - 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
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cage-0.1.4+39.a81ab70/README.md 
new/cage-0.1.5+0.83ffc57/README.md
--- old/cage-0.1.4+39.a81ab70/README.md 2022-08-19 11:59:41.000000000 +0200
+++ new/cage-0.1.5+0.83ffc57/README.md  2023-07-28 16:46:37.000000000 +0200
@@ -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
 
 <img src="https://www.hjdskes.nl/img/projects/cage/cage.svg"; alt="Cage's logo" 
width="150px" align="right">
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cage-0.1.4+39.a81ab70/cage.1.scd 
new/cage-0.1.5+0.83ffc57/cage.1.scd
--- old/cage-0.1.4+39.a81ab70/cage.1.scd        2022-08-19 11:59:41.000000000 
+0200
+++ new/cage-0.1.5+0.83ffc57/cage.1.scd 2023-07-28 16:46:37.000000000 +0200
@@ -27,10 +27,6 @@
        *last* Cage uses only the last connected monitor.
        *extend* Cage extends the display across all connected monitors.
 
-*-r*
-       Rotate the output 90 degrees clockwise. This can be specified up to 
three
-       times, each resulting in an additional 90 degrees clockwise rotation.
-
 *-s*
        Allow VT switching
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cage-0.1.4+39.a81ab70/cage.c 
new/cage-0.1.5+0.83ffc57/cage.c
--- old/cage-0.1.4+39.a81ab70/cage.c    2022-08-19 11:59:41.000000000 +0200
+++ new/cage-0.1.5+0.83ffc57/cage.c     2023-07-28 16:46:37.000000000 +0200
@@ -28,11 +28,16 @@
 #include <wlr/types/wlr_idle.h>
 #include <wlr/types/wlr_idle_inhibit_v1.h>
 #include <wlr/types/wlr_output_layout.h>
+#include <wlr/types/wlr_output_management_v1.h>
 #include <wlr/types/wlr_presentation_time.h>
 #include <wlr/types/wlr_scene.h>
 #include <wlr/types/wlr_screencopy_v1.h>
 #include <wlr/types/wlr_server_decoration.h>
+#include <wlr/types/wlr_single_pixel_buffer_v1.h>
+#include <wlr/types/wlr_subcompositor.h>
 #include <wlr/types/wlr_viewporter.h>
+#include <wlr/types/wlr_virtual_keyboard_v1.h>
+#include <wlr/types/wlr_virtual_pointer_v1.h>
 #if CAGE_HAS_XWAYLAND
 #include <wlr/types/wlr_xcursor_manager.h>
 #endif
@@ -108,6 +113,8 @@
                /* Close read, we only need write in the primary client 
process. */
                close(fd[0]);
                execvp(argv[0], argv);
+               /* execvp() returns only on failure */
+               wlr_log_errno(WLR_ERROR, "Failed to spawn client");
                _exit(1);
        } else if (pid == -1) {
                wlr_log_errno(WLR_ERROR, "Unable to fork");
@@ -149,7 +156,12 @@
 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");
@@ -192,7 +204,6 @@
                " -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"
-               " -r\t Rotate the output 90 degrees clockwise, specify up to 
three times\n"
                " -s\t Allow VT switching\n"
                " -v\t Show the version number and exit\n"
                "\n"
@@ -204,7 +215,7 @@
 parse_args(struct cg_server *server, int argc, char *argv[])
 {
        int c;
-       while ((c = getopt(argc, argv, "dhm:rsv")) != -1) {
+       while ((c = getopt(argc, argv, "dhm:sv")) != -1) {
                switch (c) {
                case 'd':
                        server->xdg_decoration = true;
@@ -219,12 +230,6 @@
                                server->output_mode = 
CAGE_MULTI_OUTPUT_MODE_EXTEND;
                        }
                        break;
-               case 'r':
-                       server->output_transform++;
-                       if (server->output_transform > WL_OUTPUT_TRANSFORM_270) 
{
-                               server->output_transform = 
WL_OUTPUT_TRANSFORM_NORMAL;
-                       }
-                       break;
                case 's':
                        server->allow_vt_switch = true;
                        break;
@@ -254,13 +259,17 @@
        struct wl_event_source *sigterm_source = NULL;
        struct wl_event_source *sigchld_source = 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;
        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;
@@ -334,6 +343,8 @@
                ret = 1;
                goto end;
        }
+       server.output_layout_change.notify = handle_output_layout_change;
+       wl_signal_add(&server.output_layout->events.change, 
&server.output_layout_change);
 
        server.scene = wlr_scene_create();
        if (!server.scene) {
@@ -351,6 +362,13 @@
                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");
@@ -388,7 +406,7 @@
        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;
@@ -445,6 +463,13 @@
                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");
@@ -452,6 +477,17 @@
                goto end;
        }
 
+       server.output_manager_v1 = 
wlr_output_manager_v1_create(server.wl_display);
+       if (!server.output_manager_v1) {
+               wlr_log(WLR_ERROR, "Unable to create the output manager");
+               ret = 1;
+               goto end;
+       }
+       server.output_manager_apply.notify = handle_output_manager_apply;
+       wl_signal_add(&server.output_manager_v1->events.apply, 
&server.output_manager_apply);
+       server.output_manager_test.notify = handle_output_manager_test;
+       wl_signal_add(&server.output_manager_v1->events.test, 
&server.output_manager_test);
+
        gamma_control_manager = 
wlr_gamma_control_manager_v1_create(server.wl_display);
        if (!gamma_control_manager) {
                wlr_log(WLR_ERROR, "Unable to create the gamma control 
manager");
@@ -459,6 +495,22 @@
                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) {
@@ -522,8 +574,9 @@
        }
 
        /* 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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cage-0.1.4+39.a81ab70/meson.build 
new/cage-0.1.5+0.83ffc57/meson.build
--- old/cage-0.1.4+39.a81ab70/meson.build       2022-08-19 11:59:41.000000000 
+0200
+++ new/cage-0.1.5+0.83ffc57/meson.build        2023-07-28 16:46:37.000000000 
+0200
@@ -1,5 +1,5 @@
 project('cage', 'c',
-  version: '0.1.4',
+  version: '0.1.5',
   license: 'MIT',
   meson_version: '>=0.58.1',
   default_options: [
@@ -35,7 +35,7 @@
   )
 endif
 
-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')
 xkbcommon      = dependency('xkbcommon')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cage-0.1.4+39.a81ab70/meson_options.txt 
new/cage-0.1.5+0.83ffc57/meson_options.txt
--- old/cage-0.1.4+39.a81ab70/meson_options.txt 2022-08-19 11:59:41.000000000 
+0200
+++ new/cage-0.1.5+0.83ffc57/meson_options.txt  2023-07-28 16:46:37.000000000 
+0200
@@ -1,2 +1,2 @@
 option('man-pages', type: 'feature', value: 'auto', description: 'Generate and 
install man pages')
-option('xwayland', type: 'boolean', value: 'false', description: 'Enable 
support for X11 applications')
+option('xwayland', type: 'boolean', value: false, description: 'Enable support 
for X11 applications')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cage-0.1.4+39.a81ab70/output.c 
new/cage-0.1.5+0.83ffc57/output.c
--- old/cage-0.1.4+39.a81ab70/output.c  2022-08-19 11:59:41.000000000 +0200
+++ new/cage-0.1.5+0.83ffc57/output.c   2023-07-28 16:46:37.000000000 +0200
@@ -22,13 +22,14 @@
 #include <wlr/backend/x11.h>
 #endif
 #include <wlr/render/wlr_renderer.h>
+#include <wlr/types/wlr_compositor.h>
 #include <wlr/types/wlr_data_device.h>
 #include <wlr/types/wlr_matrix.h>
 #include <wlr/types/wlr_output.h>
 #include <wlr/types/wlr_output_damage.h>
 #include <wlr/types/wlr_output_layout.h>
+#include <wlr/types/wlr_output_management_v1.h>
 #include <wlr/types/wlr_scene.h>
-#include <wlr/types/wlr_surface.h>
 #include <wlr/types/wlr_xdg_shell.h>
 #include <wlr/util/log.h>
 #include <wlr/util/region.h>
@@ -41,6 +42,32 @@
 #include "xwayland.h"
 #endif
 
+#define OUTPUT_CONFIG_UPDATED                                                  
                                        \
+       (WLR_OUTPUT_STATE_ENABLED | WLR_OUTPUT_STATE_SCALE | 
WLR_OUTPUT_STATE_TRANSFORM |                              \
+        WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED)
+
+static void
+update_output_manager_config(struct cg_server *server)
+{
+       struct wlr_output_configuration_v1 *config = 
wlr_output_configuration_v1_create();
+
+       struct cg_output *output;
+       wl_list_for_each (output, &server->outputs, link) {
+               struct wlr_output *wlr_output = output->wlr_output;
+               struct wlr_output_configuration_head_v1 *config_head =
+                       wlr_output_configuration_head_v1_create(config, 
wlr_output);
+               struct wlr_box output_box;
+
+               wlr_output_layout_get_box(server->output_layout, wlr_output, 
&output_box);
+               if (!wlr_box_empty(&output_box)) {
+                       config_head->state.x = output_box.x;
+                       config_head->state.y = output_box.y;
+               }
+       }
+
+       wlr_output_manager_v1_set_configuration(server->output_manager_v1, 
config);
+}
+
 static void
 output_enable(struct cg_output *output)
 {
@@ -57,6 +84,8 @@
 
        output->scene_output = 
wlr_scene_get_scene_output(output->server->scene, wlr_output);
        assert(output->scene_output != NULL);
+
+       update_output_manager_config(output->server);
 }
 
 static void
@@ -77,6 +106,44 @@
        wlr_output_commit(wlr_output);
 }
 
+static bool
+output_apply_config(struct cg_output *output, struct 
wlr_output_configuration_head_v1 *head, bool test_only)
+{
+       wlr_output_enable(output->wlr_output, head->state.enabled);
+
+       if (head->state.enabled) {
+               /* Do not mess with these parameters for output to be disabled 
*/
+               wlr_output_set_scale(output->wlr_output, head->state.scale);
+               wlr_output_set_transform(output->wlr_output, 
head->state.transform);
+
+               if (head->state.mode) {
+                       wlr_output_set_mode(output->wlr_output, 
head->state.mode);
+               } else {
+                       wlr_output_set_custom_mode(output->wlr_output, 
head->state.custom_mode.width,
+                                                  
head->state.custom_mode.height, head->state.custom_mode.refresh);
+               }
+       }
+
+       if (test_only) {
+               bool ret = wlr_output_test(output->wlr_output);
+               wlr_output_rollback(output->wlr_output);
+               return ret;
+       }
+
+       /* Apply output configuration */
+       if (!wlr_output_commit(output->wlr_output)) {
+               return false;
+       }
+
+       if (head->state.enabled) {
+               wlr_output_layout_add(output->server->output_layout, 
head->state.output, head->state.x, head->state.y);
+       } else {
+               wlr_output_layout_remove(output->server->output_layout, 
output->wlr_output);
+       }
+
+       return true;
+}
+
 static void
 handle_output_frame(struct wl_listener *listener, void *data)
 {
@@ -99,15 +166,21 @@
        struct cg_output *output = wl_container_of(listener, output, commit);
        struct wlr_output_event_commit *event = data;
 
-       if (!output->wlr_output->enabled) {
-               return;
+       /* Notes:
+        * - output layout change will also be called if needed to position the 
views
+        * - always update output manager configuration even if the output is 
now disabled */
+
+       if (event->committed & WLR_OUTPUT_STATE_ENABLED) {
+               if (output->wlr_output->enabled) {
+                       output->scene_output = 
wlr_scene_get_scene_output(output->server->scene, output->wlr_output);
+                       assert(output->scene_output != NULL);
+               } else {
+                       output->scene_output = NULL;
+               }
        }
 
-       if (event->committed & WLR_OUTPUT_STATE_TRANSFORM) {
-               struct cg_view *view;
-               wl_list_for_each (view, &output->server->views, link) {
-                       view_position(view);
-               }
+       if (event->committed & OUTPUT_CONFIG_UPDATED) {
+               update_output_manager_config(output->server);
        }
 }
 
@@ -120,10 +193,17 @@
                return;
        }
 
-       struct cg_view *view;
-       wl_list_for_each (view, &output->server->views, link) {
-               view_position(view);
-       }
+       view_position_all(output->server);
+       update_output_manager_config(output->server);
+}
+
+void
+handle_output_layout_change(struct wl_listener *listener, void *data)
+{
+       struct cg_server *server = wl_container_of(listener, server, 
output_layout_change);
+
+       view_position_all(server);
+       update_output_manager_config(server);
 }
 
 static void
@@ -145,16 +225,10 @@
 
        if (wl_list_empty(&server->outputs)) {
                wl_display_terminate(server->wl_display);
-       } else if (server->output_mode == CAGE_MULTI_OUTPUT_MODE_LAST) {
+       } else if (server->output_mode == CAGE_MULTI_OUTPUT_MODE_LAST && 
!wl_list_empty(&server->outputs)) {
                struct cg_output *prev = wl_container_of(server->outputs.next, 
prev, link);
-               if (prev) {
-                       output_enable(prev);
-
-                       struct cg_view *view;
-                       wl_list_for_each (view, &server->views, link) {
-                               view_position(view);
-                       }
-               }
+               output_enable(prev);
+               view_position_all(server);
        }
 }
 
@@ -217,13 +291,9 @@
                }
        }
 
-       wlr_output_set_transform(wlr_output, output->server->output_transform);
-
-       if (server->output_mode == CAGE_MULTI_OUTPUT_MODE_LAST) {
+       if (server->output_mode == CAGE_MULTI_OUTPUT_MODE_LAST && 
wl_list_length(&server->outputs) > 1) {
                struct cg_output *next = wl_container_of(output->link.next, 
next, link);
-               if (next) {
-                       output_disable(next);
-               }
+               output_disable(next);
        }
 
        if (!wlr_xcursor_manager_load(server->seat->xcursor_manager, 
wlr_output->scale)) {
@@ -232,11 +302,7 @@
        }
 
        output_enable(output);
-
-       struct cg_view *view;
-       wl_list_for_each (view, &output->server->views, link) {
-               view_position(view);
-       }
+       view_position_all(output->server);
 }
 
 void
@@ -257,3 +323,49 @@
 #endif
        }
 }
+
+static bool
+output_config_apply(struct cg_server *server, struct 
wlr_output_configuration_v1 *config, bool test_only)
+{
+       struct wlr_output_configuration_head_v1 *head;
+
+       wl_list_for_each (head, &config->heads, link) {
+               struct cg_output *output = head->state.output->data;
+
+               if (!output_apply_config(output, head, test_only)) {
+                       return false;
+               }
+       }
+
+       return true;
+}
+
+void
+handle_output_manager_apply(struct wl_listener *listener, void *data)
+{
+       struct cg_server *server = wl_container_of(listener, server, 
output_manager_apply);
+       struct wlr_output_configuration_v1 *config = data;
+
+       if (output_config_apply(server, config, false)) {
+               wlr_output_configuration_v1_send_succeeded(config);
+       } else {
+               wlr_output_configuration_v1_send_failed(config);
+       }
+
+       wlr_output_configuration_v1_destroy(config);
+}
+
+void
+handle_output_manager_test(struct wl_listener *listener, void *data)
+{
+       struct cg_server *server = wl_container_of(listener, server, 
output_manager_test);
+       struct wlr_output_configuration_v1 *config = data;
+
+       if (output_config_apply(server, config, true)) {
+               wlr_output_configuration_v1_send_succeeded(config);
+       } else {
+               wlr_output_configuration_v1_send_failed(config);
+       }
+
+       wlr_output_configuration_v1_destroy(config);
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cage-0.1.4+39.a81ab70/output.h 
new/cage-0.1.5+0.83ffc57/output.h
--- old/cage-0.1.4+39.a81ab70/output.h  2022-08-19 11:59:41.000000000 +0200
+++ new/cage-0.1.5+0.83ffc57/output.h   2023-07-28 16:46:37.000000000 +0200
@@ -21,6 +21,9 @@
        struct wl_list link; // cg_server::outputs
 };
 
+void handle_output_manager_apply(struct wl_listener *listener, void *data);
+void handle_output_manager_test(struct wl_listener *listener, void *data);
+void handle_output_layout_change(struct wl_listener *listener, void *data);
 void handle_new_output(struct wl_listener *listener, void *data);
 void output_set_window_title(struct cg_output *output, const char *title);
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cage-0.1.4+39.a81ab70/seat.c 
new/cage-0.1.5+0.83ffc57/seat.c
--- old/cage-0.1.4+39.a81ab70/seat.c    2022-08-19 11:59:41.000000000 +0200
+++ new/cage-0.1.5+0.83ffc57/seat.c     2023-07-28 16:46:37.000000000 +0200
@@ -6,11 +6,14 @@
  * See the LICENSE file accompanying this file.
  */
 
+#define _POSIX_C_SOURCE 200809L
+
 #include "config.h"
 
 #include <assert.h>
 #include <linux/input-event-codes.h>
 #include <stdlib.h>
+#include <string.h>
 #include <wayland-server-core.h>
 #include <wlr/backend.h>
 #include <wlr/backend/multi.h>
@@ -21,8 +24,9 @@
 #include <wlr/types/wlr_primary_selection.h>
 #include <wlr/types/wlr_scene.h>
 #include <wlr/types/wlr_seat.h>
-#include <wlr/types/wlr_surface.h>
 #include <wlr/types/wlr_touch.h>
+#include <wlr/types/wlr_virtual_keyboard_v1.h>
+#include <wlr/types/wlr_virtual_pointer_v1.h>
 #include <wlr/types/wlr_xcursor_manager.h>
 #include <wlr/util/log.h>
 #if CAGE_HAS_XWAYLAND
@@ -53,20 +57,31 @@
 static struct cg_view *
 desktop_view_at(struct cg_server *server, double lx, double ly, struct 
wlr_surface **surface, double *sx, double *sy)
 {
-       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) {
+       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;
+       }
+
+       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;
        }
 
-       *surface = wlr_scene_surface_from_node(node)->surface;
+       *surface = scene_surface->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);
 
+       assert(node != NULL);
        return node->data;
 }
 
@@ -118,16 +133,16 @@
 }
 
 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);
@@ -145,7 +160,7 @@
        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);
 
@@ -153,7 +168,7 @@
 }
 
 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) {
@@ -162,14 +177,14 @@
        }
 
        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
@@ -179,7 +194,7 @@
        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);
 
@@ -187,7 +202,7 @@
 }
 
 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) {
@@ -196,21 +211,42 @@
        }
 
        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);
+}
+
+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;
 
-       map_input_device_to_output(seat, device);
+       /* 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);
 }
@@ -240,18 +276,18 @@
 }
 
 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
@@ -263,7 +299,7 @@
 
        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);
        }
 
@@ -274,27 +310,32 @@
 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;
+                       }
                }
        }
 
@@ -306,6 +347,7 @@
                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.");
@@ -313,14 +355,14 @@
        }
 
        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);
@@ -338,7 +380,7 @@
 }
 
 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) {
@@ -353,15 +395,30 @@
                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(device, seat);
+       cg_keyboard_group_add(keyboard, seat, virtual);
 
-       wlr_seat_set_keyboard(seat->seat, device);
+       wlr_seat_set_keyboard(seat->seat, keyboard);
+}
+
+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 */
+
+       handle_new_keyboard(seat, wlr_keyboard, true);
+       update_capabilities(seat);
 }
 
 static void
@@ -372,13 +429,13 @@
 
        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");
@@ -433,10 +490,10 @@
 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;
@@ -451,7 +508,7 @@
                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);
@@ -461,14 +518,14 @@
 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);
        }
 
@@ -480,14 +537,14 @@
 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;
@@ -521,7 +578,7 @@
 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);
@@ -532,10 +589,10 @@
 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,9 +626,9 @@
 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);
 }
@@ -580,9 +637,9 @@
 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);
 }
@@ -611,7 +668,7 @@
                break;
        }
 
-       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
@@ -621,7 +678,7 @@
 
        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);
 }
 
@@ -664,8 +721,8 @@
        }
        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;
        }
@@ -789,6 +846,9 @@
        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);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cage-0.1.4+39.a81ab70/seat.h 
new/cage-0.1.5+0.83ffc57/seat.h
--- old/cage-0.1.4+39.a81ab70/seat.h    2022-08-19 11:59:41.000000000 +0200
+++ new/cage-0.1.5+0.83ffc57/seat.h     2023-07-28 16:46:37.000000000 +0200
@@ -55,12 +55,13 @@
        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_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,7 +78,7 @@
        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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cage-0.1.4+39.a81ab70/server.h 
new/cage-0.1.5+0.83ffc57/server.h
--- old/cage-0.1.4+39.a81ab70/server.h  2022-08-19 11:59:41.000000000 +0200
+++ new/cage-0.1.5+0.83ffc57/server.h   2023-07-28 16:46:37.000000000 +0200
@@ -12,10 +12,6 @@
 #include <wlr/xwayland.h>
 #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,
@@ -41,16 +37,22 @@
         * some outputs may be disabled. */
        struct wl_list outputs; // cg_output::link
        struct wl_listener new_output;
+       struct wl_listener output_layout_change;
 
        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
+       struct wlr_output_manager_v1 *output_manager_v1;
+       struct wl_listener output_manager_apply;
+       struct wl_listener output_manager_test;
 
        bool xdg_decoration;
        bool allow_vt_switch;
-       enum wl_output_transform output_transform;
 };
 
 #endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cage-0.1.4+39.a81ab70/view.c 
new/cage-0.1.5+0.83ffc57/view.c
--- old/cage-0.1.4+39.a81ab70/view.c    2022-08-19 11:59:41.000000000 +0200
+++ new/cage-0.1.5+0.83ffc57/view.c     2023-07-28 16:46:37.000000000 +0200
@@ -15,7 +15,6 @@
 #include <wayland-server-core.h>
 #include <wlr/types/wlr_output.h>
 #include <wlr/types/wlr_scene.h>
-#include <wlr/types/wlr_surface.h>
 
 #include "output.h"
 #include "seat.h"
@@ -68,7 +67,7 @@
        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);
 }
@@ -82,18 +81,28 @@
        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
 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);
+               view_center(view, &layout_box);
+       }
+}
+
+void
+view_position_all(struct cg_server *server)
+{
+       struct cg_view *view;
+       wl_list_for_each (view, &server->views, link) {
+               view_position(view);
        }
 }
 
@@ -102,7 +111,7 @@
 {
        wl_list_remove(&view->link);
 
-       wlr_scene_node_destroy(view->scene_node);
+       wlr_scene_node_destroy(&view->scene_tree->node);
 
        view->wlr_surface->data = NULL;
        view->wlr_surface = NULL;
@@ -111,12 +120,12 @@
 void
 view_map(struct cg_view *view, struct wlr_surface *surface)
 {
-       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->wlr_surface = surface;
        surface->data = view;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cage-0.1.4+39.a81ab70/view.h 
new/cage-0.1.5+0.83ffc57/view.h
--- old/cage-0.1.4+39.a81ab70/view.h    2022-08-19 11:59:41.000000000 +0200
+++ new/cage-0.1.5+0.83ffc57/view.h     2023-07-28 16:46:37.000000000 +0200
@@ -5,7 +5,7 @@
 
 #include <stdbool.h>
 #include <wayland-server-core.h>
-#include <wlr/types/wlr_surface.h>
+#include <wlr/types/wlr_compositor.h>
 #include <wlr/types/wlr_xdg_shell.h>
 #include <wlr/util/box.h>
 #if CAGE_HAS_XWAYLAND
@@ -25,7 +25,7 @@
        struct cg_server *server;
        struct wl_list link; // server::views
        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;
@@ -49,6 +49,7 @@
 bool view_is_transient_for(struct cg_view *child, struct cg_view *parent);
 void view_activate(struct cg_view *view, bool activate);
 void view_position(struct cg_view *view);
+void view_position_all(struct cg_server *server);
 void view_unmap(struct cg_view *view);
 void view_map(struct cg_view *view, struct wlr_surface *surface);
 void view_destroy(struct cg_view *view);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cage-0.1.4+39.a81ab70/xdg_shell.c 
new/cage-0.1.5+0.83ffc57/xdg_shell.c
--- old/cage-0.1.4+39.a81ab70/xdg_shell.c       2022-08-19 11:59:41.000000000 
+0200
+++ new/cage-0.1.5+0.83ffc57/xdg_shell.c        2023-07-28 16:46:37.000000000 
+0200
@@ -67,18 +67,19 @@
 popup_unconstrain(struct cg_view *view, struct wlr_xdg_popup *popup)
 {
        struct cg_server *server = view->server;
-       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 =
                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, &output_toplevel_box);
@@ -94,7 +95,7 @@
 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
@@ -103,7 +104,7 @@
        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;
 }
@@ -112,12 +113,9 @@
 is_primary(struct cg_view *view)
 {
        struct cg_xdg_shell_view *xdg_shell_view = 
xdg_shell_view_from_view(view);
-       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
@@ -127,14 +125,13 @@
                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;
 }
@@ -143,15 +140,15 @@
 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
@@ -165,16 +162,17 @@
 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;
 
        /**
         * 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
@@ -192,7 +190,7 @@
        struct cg_xdg_shell_view *xdg_shell_view = wl_container_of(listener, 
xdg_shell_view, map);
        struct cg_view *view = &xdg_shell_view->view;
 
-       view_map(view, xdg_shell_view->xdg_surface->surface);
+       view_map(view, xdg_shell_view->xdg_toplevel->base->surface);
 }
 
 static void
@@ -205,7 +203,7 @@
        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);
-       xdg_shell_view->xdg_surface = NULL;
+       xdg_shell_view->xdg_toplevel = NULL;
 
        view_destroy(view);
 }
@@ -235,7 +233,7 @@
                }
 
                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);
@@ -255,31 +253,31 @@
                        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;
                }
 
-               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
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cage-0.1.4+39.a81ab70/xdg_shell.h 
new/cage-0.1.5+0.83ffc57/xdg_shell.h
--- old/cage-0.1.4+39.a81ab70/xdg_shell.h       2022-08-19 11:59:41.000000000 
+0200
+++ new/cage-0.1.5+0.83ffc57/xdg_shell.h        2023-07-28 16:46:37.000000000 
+0200
@@ -9,7 +9,7 @@
 
 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;

++++++ cage.obsinfo ++++++
--- /var/tmp/diff_new_pack.jdTBjW/_old  2023-08-02 16:50:37.713566247 +0200
+++ /var/tmp/diff_new_pack.jdTBjW/_new  2023-08-02 16:50:37.713566247 +0200
@@ -1,5 +1,5 @@
 name: cage
-version: 0.1.4+39.a81ab70
-mtime: 1660903181
-commit: a81ab701d73d0f43c9bb9747e5fdf3c5e226139c
+version: 0.1.5+0.83ffc57
+mtime: 1690555597
+commit: 83ffc574be860527814c595756a558c228a3475d
 

Reply via email to