Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package waywall for openSUSE:Factory checked 
in at 2026-06-22 17:27:48
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/waywall (Old)
 and      /work/SRC/openSUSE:Factory/.waywall.new.1956 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "waywall"

Mon Jun 22 17:27:48 2026 rev:2 rq:1360722 version:0.2026.06.13

Changes:
--------
--- /work/SRC/openSUSE:Factory/waywall/waywall.changes  2026-04-29 
19:19:08.008251176 +0200
+++ /work/SRC/openSUSE:Factory/.waywall.new.1956/waywall.changes        
2026-06-22 17:28:51.868544163 +0200
@@ -1,0 +2,5 @@
+Fri Jun 19 12:59:19 UTC 2026 - jan gaza <[email protected]>
+
+- Update to version 0.2026.06.13
+
+-------------------------------------------------------------------

Old:
----
  waywall-0.2026.02.06.tar.gz

New:
----
  waywall-0.2026.06.13.tar.gz

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

Other differences:
------------------
++++++ waywall.spec ++++++
--- /var/tmp/diff_new_pack.rTlpmM/_old  2026-06-22 17:28:52.776575794 +0200
+++ /var/tmp/diff_new_pack.rTlpmM/_new  2026-06-22 17:28:52.776575794 +0200
@@ -17,7 +17,7 @@
 
 %global __provides_exclude_from ^%{_libdir}/waywall-glfw/.*$
 Name:           waywall
-Version:        0.2026.02.06
+Version:        0.2026.06.13
 Release:        0
 Summary:        Wayland compositor for Minecraft speedrunning
 License:        GPL-3.0-only AND Zlib

++++++ waywall-0.2026.02.06.tar.gz -> waywall-0.2026.06.13.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waywall-0.2026.02.06/Makefile 
new/waywall-0.2026.06.13/Makefile
--- old/waywall-0.2026.02.06/Makefile   2026-02-06 22:56:05.000000000 +0100
+++ new/waywall-0.2026.06.13/Makefile   2026-06-13 20:02:32.000000000 +0200
@@ -1,4 +1,4 @@
-.PHONY: all check clean configure_debug configure_release format lint
+.PHONY: all check clean configure_debug configure_release format install lint
 
 LUA=waywall/lua/api.lua \
        waywall/lua/helpers.lua \
@@ -23,6 +23,9 @@
        ninja -C build clang-format
        stylua $(LUA)
 
+install: build/build.ninja
+       ninja -C build install
+
 lint: build/build.ninja
        ninja -C build scan-build
        selene $(LUA)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waywall-0.2026.02.06/README.md 
new/waywall-0.2026.06.13/README.md
--- old/waywall-0.2026.02.06/README.md  2026-02-06 22:56:05.000000000 +0100
+++ new/waywall-0.2026.06.13/README.md  2026-06-13 20:02:32.000000000 +0200
@@ -11,62 +11,11 @@
 
 # Installation
 
-Waywall is available on Arch through the AUR and on systems with Nix through 
Nixpkgs.
+waywall is available through some package managers, and prebuilt binary 
packages
+are provided for various popular distributions on the 
[Releases](https://github.com/tesselslate/waywall/releases)
+page.
 
-  - [Arch Linux (AUR)](https://aur.archlinux.org/packages/waywall-working-git)
-  - [Nix 
(Nixpkgs)](https://search.nixos.org/packages?channel=unstable&query=waywall)
-
-Users on other distributions must [build waywall from 
source](#building-from-source),
-download a prebuilt package from the 
[Releases](https://github.com/tesselslate/waywall/releases)
-page, or [use the `build-packages.sh` script](#building-with-build-packagessh) 
to build their own.
-
-## Building with `build-packages.sh`
-
-> [!IMPORTANT]
-> This script only builds packages for **Arch Linux**, **Debian**, and
-> **Fedora**. If you use another distribution, you will have to
-> [build waywall from source](#building-from-source).
-
-This script automatically builds both the main waywall binary and the mandatory
-patched version of GLFW, which is located at 
`/usr/local/lib64/waywall-glfw/libglfw.so`.
-
-### Dependencies:
-- `podman`
-- `git`
-- `pacur fedora-42, arch and debian-trixie containers` (from 
https://github.com/pacur/pacur)
-- `docker`
-
-### Setup:
-
-- Clone waywall repository `git clone https://github.com/tesselslate/waywall`
-- Make the main script executable `chmod u+x build-packages.sh`
-- [Install pacur containers](#steps-for-installing-pacur-containers) for 
`archlinux`, `fedora-42`, and `debian-trixie`
-- Run `./build-packages.sh` inside the waywall directory and select which 
distributions to build for
-  - Within the script: 1 for Arch, 2 for Fedora, 3 for Debian, 4 for done
-  - Or, use the provided script flags for building (for example 
`./build-packages.sh --debian` or `./build-packages.sh --fedora --arch`)
-- Enjoy
-
-### Steps for installing pacur containers:
-
-```sh
-git clone https://github.com/pacur/pacur
-cd pacur/docker
-find . -maxdepth 1 -type d \( ! -name "archlinux" ! -name "debian-trixie" ! 
-name "fedora-42" \) -exec rm -rf {} +
-for dir in */ ; do podman build --rm -t "pacur/${dir::-1}" "$dir"; done
-```
-
-The containers should now be installed. If the build fails, try rebooting your 
machine.
-
-### Steps for installing the built waywall:
-
-The script will output where the build artifacts are located (for example 
`Build artifacts are located in: ~/waywall/waywall-build`).
-On some distributions, you can double-click the correct built package in your
-graphical file manager of choice. Otherwise, install it from the terminal with
-one of the following commands:
-
-- ArchLinux: `sudo pacman -U 
~/waywall/waywall-build/waywall-0.5-1-x86_64.pkg.tar.zst`
-- Fedora: `sudo dnf localinstall 
~/waywall/waywall-build/waywall-0.5-1.fc42.x86_64.rpm`
-- Debian: `sudo dpkg -i ~/waywall/waywall-build/waywall_0.5-1_amd64.deb`
+For more detailed installation instructions, refer to the 
[documentation](https://tesselslate.github.io/waywall/00_installation.html).
 
 ## Building from source
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waywall-0.2026.02.06/build-packages.sh 
new/waywall-0.2026.06.13/build-packages.sh
--- old/waywall-0.2026.02.06/build-packages.sh  2026-02-06 22:56:05.000000000 
+0100
+++ new/waywall-0.2026.06.13/build-packages.sh  2026-06-13 20:02:32.000000000 
+0200
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 
 set -e  # Exit on errors
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waywall-0.2026.02.06/doc/00_installation.md 
new/waywall-0.2026.06.13/doc/00_installation.md
--- old/waywall-0.2026.02.06/doc/00_installation.md     2026-02-06 
22:56:05.000000000 +0100
+++ new/waywall-0.2026.06.13/doc/00_installation.md     2026-06-13 
20:02:32.000000000 +0200
@@ -1,15 +1,51 @@
 # Installation
 
-waywall is available on Arch through the AUR and on systems with Nix through 
Nixpkgs.
+waywall is available through some distribution-specific package repositories
+(presently the Arch User Repository and Nixpkgs.). Additionally, prebuilt
+binary packages are provided on the [Releases] page.
 
-  - [Arch Linux (AUR)](https://aur.archlinux.org/packages/waywall-working-git)
-  - [Nix 
(Nixpkgs)](https://search.nixos.org/packages?channel=unstable&query=waywall)
+**The following sections contain the methods available for installing waywall
+on various distributions, listed roughly in order of preference.**
 
-Users on other distributions must download a prebuilt package from the
-[Releases](https://github.com/tesselslate/waywall/releases) page or build
-waywall from source.
+## Arch Linux
 
-## Installing with Nix
+waywall is available on Arch-based distributions through the the Arch User
+Repository via the [`waywall-working-git`] package.
+
+Prebuilt binary packages are additionally provided on the [Releases] page.
+
+Lastly, waywall can be manually [built from source].
+
+## Debian
+
+Prebuilt binary packages for Debian 13 are provided on the [Releases] page.
+
+> [!CAUTION]
+> waywall is unable to run on many Debian derivatives, including Linux Mint and
+> most versions of Ubuntu, as their package repositories are too outdated.
+
+<br/>
+
+Additionally, waywall can be manually [built from source].
+
+> [!NOTE]
+> If you want to compile from source on Debian 13, you will need to use Clang,
+> as the packaged version of GCC is not up-to-date enough.
+
+## Fedora
+
+Prebuilt binary packages for Fedora 42 are provided on the [Releases] page.
+
+Additionally, waywall can be manually [built from source].
+
+## OpenSUSE
+
+Prebuilt binary packages for openSUSE Tumbleweed are available in
+the [official package 
repositories](https://build.opensuse.org/package/show/openSUSE%3AFactory/waywall).
+
+waywall can be installed with `zypper install waywall`.
+
+## Nix
 
 waywall is available in Nixpkgs since 26.05.
 
@@ -49,14 +85,6 @@
 $ nix profile install nixpkgs#waywall
 ```
 
-## Building with the packaging script
-
-The package building script is able to create binary packages for Arch Linux,
-Debian 13, and Fedora 42.
-
-Refer to the instructions within the 
[README](https://github.com/tesselslate/waywall/#building-with-build-packagessh)
-for more information on how to use the packaging script.
-
 ## Building from source
 
 waywall is written in C and uses the Meson build system, so you will need to
@@ -98,3 +126,58 @@
 
 The compiled binary will be located at `build/waywall/waywall`. If you'd like,
 you can move it to somewhere on your `$PATH`.
+
+## Building with the packaging script
+
+The package building script is able to create binary packages for Arch Linux,
+Debian 13, and Fedora 42.
+
+> [!IMPORTANT]
+> This script only builds packages for **Arch Linux**, **Debian**, and
+> **Fedora**. If you use another distribution, you will have to
+> [build waywall from source](#building-from-source).
+
+This script automatically builds both the main waywall binary and the mandatory
+patched version of GLFW, which is located at 
`/usr/local/lib64/waywall-glfw/libglfw.so`.
+
+### Dependencies
+- `podman`
+- `git`
+- `pacur fedora-42, arch and debian-trixie containers` (from 
https://github.com/pacur/pacur)
+- `docker`
+
+### Container setup
+
+```sh
+git clone https://github.com/pacur/pacur
+cd pacur/docker
+find . -maxdepth 1 -type d \( ! -name "archlinux" ! -name "debian-trixie" ! 
-name "fedora-42" \) -exec rm -rf {} +
+for dir in */ ; do podman build --rm -t "pacur/${dir::-1}" "$dir"; done
+```
+
+The containers should now be installed. If the build fails, try rebooting your 
machine.
+
+### Setup
+
+- Clone waywall repository `git clone https://github.com/tesselslate/waywall`
+- Make the main script executable `chmod u+x build-packages.sh`
+- [Install pacur containers](#container-setup) for `archlinux`, `fedora-42`, 
and `debian-trixie`
+- Run `./build-packages.sh` inside the waywall directory and select which 
distributions to build for
+  - Within the script: 1 for Arch, 2 for Fedora, 3 for Debian, 4 for done
+  - Or, use the provided script flags for building (for example 
`./build-packages.sh --debian` or `./build-packages.sh --fedora --arch`)
+- Enjoy
+
+### Installation
+
+The script will output where the build artifacts are located (for example 
`Build artifacts are located in: ~/waywall/waywall-build`).
+On some distributions, you can double-click the correct built package in your
+graphical file manager of choice. Otherwise, install it from the terminal with
+one of the following commands:
+
+- ArchLinux: `sudo pacman -U 
~/waywall/waywall-build/waywall-0.5-1-x86_64.pkg.tar.zst`
+- Fedora: `sudo dnf localinstall 
~/waywall/waywall-build/waywall-0.5-1.fc42.x86_64.rpm`
+- Debian: `sudo dpkg -i ~/waywall/waywall-build/waywall_0.5-1_amd64.deb`
+
+[built from source]: #building-from-source
+[Releases]: https://github.com/tesselslate/waywall/releases
+[`waywall-working-git`]: https://aur.archlinux.org/packages/waywall-working-git
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waywall-0.2026.02.06/doc/00_known_issues.md 
new/waywall-0.2026.06.13/doc/00_known_issues.md
--- old/waywall-0.2026.02.06/doc/00_known_issues.md     2026-02-06 
22:56:05.000000000 +0100
+++ new/waywall-0.2026.06.13/doc/00_known_issues.md     2026-06-13 
20:02:32.000000000 +0200
@@ -32,4 +32,5 @@
 with the [`fullscreen_width` and `fullscreen_height` 
options](01_options_window.md#fullscreen-resolution).
 
 [Discord]: https://discord.gg/3tm4UpUQ8t
+[egl-wayland2]: https://github.com/NVIDIA/egl-wayland2/
 [issue tracker]: https://github.com/tesselslate/waywall/issues
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waywall-0.2026.02.06/doc/00_setup.md 
new/waywall-0.2026.06.13/doc/00_setup.md
--- old/waywall-0.2026.02.06/doc/00_setup.md    2026-02-06 22:56:05.000000000 
+0100
+++ new/waywall-0.2026.06.13/doc/00_setup.md    2026-06-13 20:02:32.000000000 
+0200
@@ -24,13 +24,17 @@
 > found at `/usr/local/lib64/waywall-glfw/libglfw.so`.
 
 > [!TIP]
-> If you are using Prism Launcher installed from Nixpkgs, you can skip and 
+> If you are using Prism Launcher installed from Nixpkgs, you can skip and
 > continue to the next step as it already includes the patch.
-> 
+>
 > If you have Nix but are using Prism Launcher from a *different* source, you 
 > can
 > install the `glfw3-minecraft` package with `nix profile` and use the path
 > `/home/USER/.nix-profile/lib/libglfw.so` in the upcoming steps.
 
+> [!NOTE]
+> Version 26.1 does not require this patch, instead requiring you to add the
+> following Java arguments: `-DMC_DEBUG_ENABLED -DMC_DEBUG_PREFER_WAYLAND`.
+
 You can compile the patched version of GLFW with the following commands:
 
 ```sh
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waywall-0.2026.02.06/doc/01_ninb.md 
new/waywall-0.2026.06.13/doc/01_ninb.md
--- old/waywall-0.2026.02.06/doc/01_ninb.md     2026-02-06 22:56:05.000000000 
+0100
+++ new/waywall-0.2026.06.13/doc/01_ninb.md     2026-06-13 20:02:32.000000000 
+0200
@@ -35,5 +35,14 @@
 > `-Dswing.defaultlaf=javax.swing.plaf.metal.MetalLookAndFeel` to your 
 > arguments
 > when launching Ninjabrain Bot.
 
+## Positioning floating windows
+
+You can automatically "anchor" Ninjabrain Bot to a specific position in the
+waywall window by using the [`theme.ninb_anchor`] option.
+
+Additionally, you can manually move all un-anchored floating windows by holding
+shift and dragging them with the left mouse button held down.
+
 [`waywall.show_floating`]: 02_waywall_show_floating.md
 [`helpers.toggle_floating`]: 02_helpers_toggle_floating.md
+[`theme.ninb_anchor`]: 01_options_theme.md#ninjabrain-bot
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waywall-0.2026.02.06/include/server/gl.h 
new/waywall-0.2026.06.13/include/server/gl.h
--- old/waywall-0.2026.02.06/include/server/gl.h        2026-02-06 
22:56:05.000000000 +0100
+++ new/waywall-0.2026.06.13/include/server/gl.h        2026-06-13 
20:02:32.000000000 +0200
@@ -41,6 +41,9 @@
         struct wp_viewport *viewport;
         struct wl_egl_window *window;
         EGLSurface egl;
+
+        struct wl_callback *frame_callback;
+        uint32_t swaps_since_frame_cb;
     } surface;
 
     struct {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waywall-0.2026.02.06/include/server/surface.h 
new/waywall-0.2026.06.13/include/server/surface.h
--- old/waywall-0.2026.02.06/include/server/surface.h   2026-02-06 
22:56:05.000000000 +0100
+++ new/waywall-0.2026.06.13/include/server/surface.h   2026-06-13 
20:02:32.000000000 +0200
@@ -20,6 +20,8 @@
         } present;
     } current, pending;
 
+    uint32_t swaps_since_frame_cb;
+
     const struct server_surface_role *role;
     struct wl_resource *role_resource;
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waywall-0.2026.02.06/include/server/xdg_shell.h 
new/waywall-0.2026.06.13/include/server/xdg_shell.h
--- old/waywall-0.2026.02.06/include/server/xdg_shell.h 2026-02-06 
22:56:05.000000000 +0100
+++ new/waywall-0.2026.06.13/include/server/xdg_shell.h 2026-06-13 
20:02:32.000000000 +0200
@@ -1,6 +1,6 @@
 #pragma once
 
-#include "util/serial.h"
+#include "util/list.h"
 #include <stdint.h>
 #include <wayland-server-core.h>
 #include <wayland-util.h>
@@ -27,7 +27,7 @@
     struct server_xdg_client *xdg_wm_base;
     struct server_surface *parent;
     struct server_xdg_toplevel *child;
-    struct serial_ring serials;
+    struct list_uint32 serials;
     bool initial_commit;
     bool initial_ack;
 };
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waywall-0.2026.02.06/include/util/list.h 
new/waywall-0.2026.06.13/include/util/list.h
--- old/waywall-0.2026.02.06/include/util/list.h        2026-02-06 
22:56:05.000000000 +0100
+++ new/waywall-0.2026.06.13/include/util/list.h        2026-06-13 
20:02:32.000000000 +0200
@@ -31,6 +31,16 @@
         list->len--;                                                           
                    \
     }                                                                          
                    \
                                                                                
                    \
+    [[maybe_unused]] static inline void name##_remove_range(struct name *list, 
ssize_t a,          \
+                                                            ssize_t b) {       
                    \
+        ww_assert(list->len > a);                                              
                    \
+        ww_assert(list->len >= b);                                             
                    \
+        ww_assert(b > a);                                                      
                    \
+                                                                               
                    \
+        memmove(list->data + a, list->data + b, (list->len - b) * 
sizeof(*list->data));            \
+        list->len -= (b - a);                                                  
                    \
+    }                                                                          
                    \
+                                                                               
                    \
     [[maybe_unused]] static inline struct name name##_create() {               
                    \
         struct name list = {};                                                 
                    \
         list.cap = 8;                                                          
                    \
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waywall-0.2026.02.06/include/util/sched.h 
new/waywall-0.2026.06.13/include/util/sched.h
--- old/waywall-0.2026.02.06/include/util/sched.h       1970-01-01 
01:00:00.000000000 +0100
+++ new/waywall-0.2026.06.13/include/util/sched.h       2026-06-13 
20:02:32.000000000 +0200
@@ -0,0 +1,3 @@
+#pragma once
+
+void util_sched_realtime();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waywall-0.2026.02.06/include/util/serial.h 
new/waywall-0.2026.06.13/include/util/serial.h
--- old/waywall-0.2026.02.06/include/util/serial.h      2026-02-06 
22:56:05.000000000 +0100
+++ new/waywall-0.2026.06.13/include/util/serial.h      1970-01-01 
01:00:00.000000000 +0100
@@ -1,39 +0,0 @@
-#pragma once
-
-#include "util/prelude.h"
-#include <stddef.h>
-#include <stdint.h>
-#include <wayland-server-core.h>
-
-struct serial_ring {
-    uint32_t data[64];
-    size_t tail, len;
-};
-
-static inline int
-serial_ring_consume(struct serial_ring *ring, uint32_t serial) {
-    for (size_t i = 0; i < ring->len; i++) {
-        uint32_t datum = ring->data[(ring->tail + i) % 
STATIC_ARRLEN(ring->data)];
-        if (datum == serial) {
-            ring->tail = (ring->tail + i + 1) % STATIC_ARRLEN(ring->data);
-            ring->len = ring->len - i - 1;
-            return 0;
-        }
-    }
-    return 1;
-}
-
-static inline int
-serial_ring_push(struct serial_ring *ring, uint32_t serial) {
-    if (ring->len == STATIC_ARRLEN(ring->data)) {
-        return 1;
-    }
-    ring->data[(ring->tail + ring->len) % STATIC_ARRLEN(ring->data)] = serial;
-    ring->len++;
-    return 0;
-}
-
-static inline uint32_t
-next_serial(struct wl_resource *resource) {
-    return 
wl_display_next_serial(wl_client_get_display(wl_resource_get_client(resource)));
-}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waywall-0.2026.02.06/meson.build 
new/waywall-0.2026.06.13/meson.build
--- old/waywall-0.2026.02.06/meson.build        2026-02-06 22:56:05.000000000 
+0100
+++ new/waywall-0.2026.06.13/meson.build        2026-06-13 20:02:32.000000000 
+0200
@@ -54,6 +54,7 @@
 
 waywall_deps = [
   cc.find_library('m'),
+  dependency('threads'),
 
   luajit,
   wayland_client,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waywall-0.2026.02.06/test/list.c 
new/waywall-0.2026.06.13/test/list.c
--- old/waywall-0.2026.02.06/test/list.c        1970-01-01 01:00:00.000000000 
+0100
+++ new/waywall-0.2026.06.13/test/list.c        2026-06-13 20:02:32.000000000 
+0200
@@ -0,0 +1,66 @@
+#include "util/list.h"
+#include "util/prelude.h"
+#include <stdio.h>
+
+int
+main() {
+    struct list_uint32 list = list_uint32_create();
+
+    for (uint32_t i = 0; i < 100; i++) {
+        list_uint32_append(&list, i);
+    }
+    ww_assert(list.len == 100);
+
+    for (uint32_t i = 0; i < list.len; i++) {
+        ww_assert(list.data[i] == i);
+    }
+
+    for (uint32_t i = 0; i < 100; i++) {
+        list_uint32_remove(&list, 0);
+        for (uint32_t j = 0; j < list.len; j++) {
+            ww_assert(list.data[j] == j + i + 1);
+        }
+    }
+    ww_assert(list.len == 0);
+
+    ww_assert(list.cap > 0);
+    for (uint32_t i = 0; i < list.cap; i++) {
+        list_uint32_append(&list, i);
+    }
+    ww_assert(list.len == list.cap);
+
+    for (int32_t i = list.len - 1; i >= 0; i--) {
+        list_uint32_remove(&list, i);
+        for (uint32_t j = 0; j < list.len; j++) {
+            ww_assert(list.data[j] == j);
+        }
+    }
+    ww_assert(list.len == 0);
+
+    list_uint32_append(&list, 0);
+    ww_assert(list.len == 1);
+    list_uint32_remove(&list, 0);
+    ww_assert(list.len == 0);
+
+    for (uint32_t i = 0; i < 100; i++) {
+        list_uint32_append(&list, i);
+    }
+    ww_assert(list.len == 100);
+
+    list_uint32_remove_range(&list, 0, 2);
+    ww_assert(list.len == 98);
+    list_uint32_remove_range(&list, 10, 11);
+    ww_assert(list.len == 97);
+    list_uint32_remove_range(&list, 95, 97);
+    ww_assert(list.len == 95);
+
+    for (uint32_t i = 0; i < list.len; i++) {
+        if (i < 10) {
+            ww_assert(list.data[i] == i + 2);
+        } else {
+            ww_assert(list.data[i] == i + 3);
+        }
+    }
+
+    list_uint32_destroy(&list);
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waywall-0.2026.02.06/test/meson.build 
new/waywall-0.2026.06.13/test/meson.build
--- old/waywall-0.2026.02.06/test/meson.build   2026-02-06 22:56:05.000000000 
+0100
+++ new/waywall-0.2026.06.13/test/meson.build   2026-06-13 20:02:32.000000000 
+0200
@@ -1,4 +1,5 @@
 waywall_tests = {
+  'list': ['util/prelude.c'],
   'str': ['util/prelude.c', 'util/str.c']
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waywall-0.2026.02.06/waywall/lua/api.lua 
new/waywall-0.2026.06.13/waywall/lua/api.lua
--- old/waywall-0.2026.02.06/waywall/lua/api.lua        2026-02-06 
22:56:05.000000000 +0100
+++ new/waywall-0.2026.06.13/waywall/lua/api.lua        2026-06-13 
20:02:32.000000000 +0200
@@ -36,11 +36,10 @@
     end
 end
 
-local events = {
-    ["load"] = event_handler("load"),
-    ["resolution"] = event_handler("resolution"),
-    ["state"] = event_handler("state"),
-}
+local events = {}
+events.load = event_handler("load")
+events.resolution = event_handler("resolution")
+events.state = event_handler("state")
 
 local M = {}
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waywall-0.2026.02.06/waywall/lua/init.lua 
new/waywall-0.2026.06.13/waywall/lua/init.lua
--- old/waywall-0.2026.02.06/waywall/lua/init.lua       2026-02-06 
22:56:05.000000000 +0100
+++ new/waywall-0.2026.06.13/waywall/lua/init.lua       2026-06-13 
20:02:32.000000000 +0200
@@ -184,7 +184,11 @@
 
     local waywall = require("waywall")
     waywall.listen("load", function()
-        autogen_text = waywall.text(autogen_notice, { x = 10, y = 10, size = 1 
})
+        local autogen_opts = {}
+        autogen_opts.x = 10
+        autogen_opts.y = 10
+        autogen_opts.size = 1
+        autogen_text = waywall.text(autogen_notice, autogen_opts)
     end)
 end
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waywall-0.2026.02.06/waywall/main.c 
new/waywall-0.2026.06.13/waywall/main.c
--- old/waywall-0.2026.02.06/waywall/main.c     2026-02-06 22:56:05.000000000 
+0100
+++ new/waywall-0.2026.06.13/waywall/main.c     2026-06-13 20:02:32.000000000 
+0200
@@ -8,11 +8,11 @@
 #include "util/debug.h"
 #include "util/log.h"
 #include "util/prelude.h"
+#include "util/sched.h"
 #include "util/syscall.h"
 #include "util/sysinfo.h"
 #include "wrap.h"
 #include <errno.h>
-#include <sched.h>
 #include <signal.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -227,21 +227,6 @@
     }
 }
 
-static void
-set_realtime() {
-    int priority = sched_get_priority_min(SCHED_RR);
-    if (priority == -1) {
-        ww_log_errno(LOG_ERROR, "failed to get minimum priority for SCHED_RR");
-        return;
-    }
-
-    const struct sched_param param = {.sched_priority = priority};
-    if (sched_setscheduler(getpid(), SCHED_RR, &param) == -1) {
-        ww_log_errno(LOG_WARN, "failed to set scheduler priority");
-        return;
-    }
-}
-
 int
 main(int argc, char **argv) {
     util_log_init();
@@ -304,7 +289,7 @@
             return 1;
         }
 
-        set_realtime();
+        util_sched_realtime();
         return cmd_wrap(profile, allow_mc_x11, subcommand);
     } else {
         print_help(argv[0]);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waywall-0.2026.02.06/waywall/meson.build 
new/waywall-0.2026.06.13/waywall/meson.build
--- old/waywall-0.2026.02.06/waywall/meson.build        2026-02-06 
22:56:05.000000000 +0100
+++ new/waywall-0.2026.06.13/waywall/meson.build        2026-06-13 
20:02:32.000000000 +0200
@@ -32,6 +32,7 @@
   'util/log.c',
   'util/png.c',
   'util/prelude.c',
+  'util/sched.c',
   'util/str.c',
   'util/syscall.c',
   'util/sysinfo.c',
@@ -55,4 +56,5 @@
 
   dependencies: waywall_deps,
   include_directories: includes,
+  install: true,
 )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waywall-0.2026.02.06/waywall/server/gl.c 
new/waywall-0.2026.06.13/waywall/server/gl.c
--- old/waywall-0.2026.02.06/waywall/server/gl.c        2026-02-06 
22:56:05.000000000 +0100
+++ new/waywall-0.2026.06.13/waywall/server/gl.c        2026-06-13 
20:02:32.000000000 +0200
@@ -4,8 +4,8 @@
 #include "server/backend.h"
 #include "server/buffer.h"
 #include "server/server.h"
-#include "server/ui.h"
 #include "server/surface.h"
+#include "server/ui.h"
 #include "server/wp_linux_dmabuf.h"
 #include "util/alloc.h"
 #include "util/log.h"
@@ -236,9 +236,23 @@
     wl_egl_window_resize(gl->surface.window, gl->server->ui->render_width,
                          gl->server->ui->render_height, 0, 0);
 
-    wp_viewport_set_destination(gl->surface.viewport, gl->server->ui->width, 
gl->server->ui->height);
+    wp_viewport_set_destination(gl->surface.viewport, gl->server->ui->width,
+                                gl->server->ui->height);
+}
+
+static void
+on_frame_callback_done(void *data, struct wl_callback *callback, uint32_t 
callback_data) {
+    struct server_gl *gl = data;
+
+    gl->surface.swaps_since_frame_cb = 0;
+    gl->surface.frame_callback = nullptr;
+    wl_callback_destroy(callback);
 }
 
+static const struct wl_callback_listener frame_callback_listener = {
+    .done = on_frame_callback_done,
+};
+
 static bool
 egl_getproc(void *out, const char *name) {
     void *addr = (void *)eglGetProcAddress(name);
@@ -677,6 +691,10 @@
     wl_subsurface_destroy(gl->surface.subsurface);
     wl_surface_destroy(gl->surface.remote);
 
+    if (gl->surface.frame_callback) {
+        wl_callback_destroy(gl->surface.frame_callback);
+    }
+
     // Destroy EGL resources.
     eglMakeCurrent(gl->egl.display, EGL_NO_SURFACE, EGL_NO_SURFACE, 
EGL_NO_CONTEXT);
     eglDestroyContext(gl->egl.display, gl->egl.ctx);
@@ -764,6 +782,19 @@
 
 void
 server_gl_swap_buffers(struct server_gl *gl) {
+    // HACK: NVIDIA bug workaround. Check git blame for details.
+    if (gl->surface.frame_callback) {
+        gl->surface.swaps_since_frame_cb++;
+    } else {
+        gl->surface.frame_callback = wl_surface_frame(gl->surface.remote);
+        check_alloc(gl->surface.frame_callback);
+
+        wl_callback_add_listener(gl->surface.frame_callback, 
&frame_callback_listener, gl);
+    }
+    if (gl->surface.swaps_since_frame_cb > 64) {
+        return;
+    }
+
     eglSwapInterval(gl->egl.display, 0);
     eglSwapBuffers(gl->egl.display, gl->surface.egl);
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waywall-0.2026.02.06/waywall/server/surface.c 
new/waywall-0.2026.06.13/waywall/server/surface.c
--- old/waywall-0.2026.02.06/waywall/server/surface.c   2026-02-06 
22:56:05.000000000 +0100
+++ new/waywall-0.2026.06.13/waywall/server/surface.c   2026-06-13 
20:02:32.000000000 +0200
@@ -1,5 +1,6 @@
 #include "server/surface.h"
 #include "server/buffer.h"
+#include "time.h"
 #include "util/alloc.h"
 #include "util/log.h"
 #include "util/prelude.h"
@@ -23,7 +24,9 @@
 surface_frame_resource_destroy(struct wl_resource *resource) {
     struct server_surface_frame *frame = wl_resource_get_user_data(resource);
 
-    wl_callback_destroy(frame->remote);
+    if (frame->remote) {
+        wl_callback_destroy(frame->remote);
+    }
     free(frame);
 }
 
@@ -31,13 +34,23 @@
 on_surface_frame_done(void *data, struct wl_callback *wl, uint32_t 
callback_data) {
     struct server_surface_frame *frame = data;
 
+    frame->surface->swaps_since_frame_cb = 0;
+
     wl_callback_send_done(frame->resource, callback_data);
+    wl_resource_destroy(frame->resource);
 }
 
 static const struct wl_callback_listener surface_frame_listener = {
     .done = on_surface_frame_done,
 };
 
+static uint32_t
+current_time() {
+    struct timespec now;
+    clock_gettime(CLOCK_MONOTONIC, &now);
+    return (uint32_t)((uint64_t)now.tv_sec * 1000 + (uint64_t)now.tv_nsec / 
1000000);
+}
+
 static void
 surface_state_clear(struct server_surface_state *state) {
     struct wl_array damage = state->damage;
@@ -100,9 +113,12 @@
 surface_attach(struct wl_client *client, struct wl_resource *resource,
                struct wl_resource *buffer_resource, int32_t x, int32_t y) {
     struct server_surface *surface = wl_resource_get_user_data(resource);
-    struct server_buffer *buffer = 
server_buffer_from_resource(buffer_resource);
+    struct server_buffer *buffer = nullptr;
+    if (buffer_resource) {
+        buffer = server_buffer_from_resource(buffer_resource);
+    }
 
-    // If a nullptr buffer (no buffer) is being attached, skip the checks.
+    // If a null buffer (no buffer) is being attached, skip the checks.
     if (!buffer) {
         surface_state_set_buffer(&surface->pending, nullptr);
         surface->pending.present |= SURFACE_STATE_BUFFER;
@@ -143,7 +159,11 @@
                           0);
 
         surface_state_set_buffer(&surface->current, surface->pending.buffer);
-        server_buffer_lock(surface->current.buffer);
+        surface->swaps_since_frame_cb++;
+
+        if (surface->current.buffer) {
+            server_buffer_lock(surface->current.buffer);
+        }
     }
     if (surface->pending.present & SURFACE_STATE_DAMAGE) {
         struct server_surface_damage *dmg;
@@ -201,6 +221,14 @@
 surface_frame(struct wl_client *client, struct wl_resource *resource, uint32_t 
id) {
     struct server_surface *surface = wl_resource_get_user_data(resource);
 
+    // HACK: NVIDIA bug workaround. Check git blame for details.
+    if (surface->swaps_since_frame_cb > 64) {
+        struct wl_resource *resource = wl_resource_create(client, 
&wl_callback_interface, 1, id);
+        wl_callback_send_done(resource, current_time());
+        wl_resource_destroy(resource);
+        return;
+    }
+
     struct server_surface_frame *frame = zalloc(1, sizeof(*frame));
 
     frame->resource = wl_resource_create(client, &wl_callback_interface, 1, 
id);
@@ -210,6 +238,8 @@
     frame->remote = wl_surface_frame(surface->remote);
     check_alloc(frame->remote);
     wl_callback_add_listener(frame->remote, &surface_frame_listener, frame);
+
+    frame->surface = surface;
 }
 
 static void
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waywall-0.2026.02.06/waywall/server/wl_seat.c 
new/waywall-0.2026.06.13/waywall/server/wl_seat.c
--- old/waywall-0.2026.02.06/waywall/server/wl_seat.c   2026-02-06 
22:56:05.000000000 +0100
+++ new/waywall-0.2026.06.13/waywall/server/wl_seat.c   2026-06-13 
20:02:32.000000000 +0200
@@ -2,14 +2,13 @@
 #include "config/config.h"
 #include "server/backend.h"
 #include "server/server.h"
-#include "server/ui.h"
 #include "server/surface.h"
+#include "server/ui.h"
 #include "server/xwayland.h"
 #include "util/alloc.h"
 #include "util/debug.h"
 #include "util/log.h"
 #include "util/prelude.h"
-#include "util/serial.h"
 #include "util/str.h"
 #include "util/syscall.h"
 #include <inttypes.h>
@@ -83,6 +82,11 @@
     return (uint32_t)((uint64_t)now.tv_sec * 1000 + (uint64_t)now.tv_nsec / 
1000000);
 }
 
+static inline uint32_t
+next_serial(struct wl_resource *resource) {
+    return 
wl_display_next_serial(wl_client_get_display(wl_resource_get_client(resource)));
+}
+
 static void
 get_pointer_offset(struct server_seat *seat, double *x, double *y) {
     ww_assert(seat->input_focus);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waywall-0.2026.02.06/waywall/server/xdg_shell.c 
new/waywall-0.2026.06.13/waywall/server/xdg_shell.c
--- old/waywall-0.2026.02.06/waywall/server/xdg_shell.c 2026-02-06 
22:56:05.000000000 +0100
+++ new/waywall-0.2026.06.13/waywall/server/xdg_shell.c 2026-06-13 
20:02:32.000000000 +0200
@@ -1,8 +1,9 @@
 #include "server/xdg_shell.h"
 #include "server/server.h"
-#include "server/ui.h"
 #include "server/surface.h"
+#include "server/ui.h"
 #include "util/alloc.h"
+#include "util/list.h"
 #include "util/prelude.h"
 #include "xdg-shell-server-protocol.h"
 #include <inttypes.h>
@@ -313,6 +314,8 @@
     server_surface_set_role(xdg_surface->parent, &xdg_surface_role, nullptr);
     wl_list_remove(&xdg_surface->link);
 
+    list_uint32_destroy(&xdg_surface->serials);
+
     free(xdg_surface);
 }
 
@@ -320,13 +323,20 @@
 xdg_surface_ack_configure(struct wl_client *client, struct wl_resource 
*resource, uint32_t serial) {
     struct server_xdg_surface *xdg_surface = 
wl_resource_get_user_data(resource);
 
-    if (serial_ring_consume(&xdg_surface->serials, serial) != 0) {
+    ssize_t i = 0;
+    for (; i < xdg_surface->serials.len; i++) {
+        if (xdg_surface->serials.data[i] == serial) {
+            break;
+        }
+    }
+    if (i == xdg_surface->serials.len) {
         wl_resource_post_error(resource, XDG_SURFACE_ERROR_INVALID_SERIAL,
                                "invalid serial %" PRIu32 " given to 
xdg_surface.ack_configure",
                                serial);
         return;
     }
 
+    list_uint32_remove_range(&xdg_surface->serials, 0, i + 1);
     xdg_surface->initial_ack = true;
 }
 
@@ -425,6 +435,8 @@
     wl_resource_set_implementation(xdg_surface->resource, &xdg_surface_impl, 
xdg_surface,
                                    xdg_surface_resource_destroy);
 
+    xdg_surface->serials = list_uint32_create();
+
     wl_list_insert(&xdg_client->surfaces, &xdg_surface->link);
     xdg_surface->xdg_wm_base = xdg_client;
     xdg_surface->parent = surface;
@@ -498,11 +510,10 @@
 
 void
 server_xdg_surface_send_configure(struct server_xdg_surface *xdg_surface) {
-    uint32_t serial = next_serial(xdg_surface->resource);
-    if (serial_ring_push(&xdg_surface->serials, serial) != 0) {
-        wl_resource_post_no_memory(xdg_surface->resource);
-        return;
-    }
+    uint32_t serial = wl_display_next_serial(
+        wl_client_get_display(wl_resource_get_client(xdg_surface->resource)));
+
+    list_uint32_append(&xdg_surface->serials, serial);
     xdg_surface_send_configure(xdg_surface->resource, serial);
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waywall-0.2026.02.06/waywall/util/prelude.c 
new/waywall-0.2026.06.13/waywall/util/prelude.c
--- old/waywall-0.2026.02.06/waywall/util/prelude.c     2026-02-06 
22:56:05.000000000 +0100
+++ new/waywall-0.2026.06.13/waywall/util/prelude.c     2026-06-13 
20:02:32.000000000 +0200
@@ -13,5 +13,5 @@
     fprintf(stderr, "\n");
 
     fflush(stderr);
-    exit(EXIT_FAILURE);
+    abort();
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waywall-0.2026.02.06/waywall/util/sched.c 
new/waywall-0.2026.06.13/waywall/util/sched.c
--- old/waywall-0.2026.02.06/waywall/util/sched.c       1970-01-01 
01:00:00.000000000 +0100
+++ new/waywall-0.2026.06.13/waywall/util/sched.c       2026-06-13 
20:02:32.000000000 +0200
@@ -0,0 +1,61 @@
+#include "util/log.h"
+#include <pthread.h>
+
+/*
+ * This code is based on sway's code for managing scheduler priority.
+ *
+ * Copyright (c) 2016-2017 Drew DeVault
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a 
copy of
+ * this software and associated documentation files (the "Software"), to deal 
in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
copies
+ * of the Software, and to permit persons to whom the Software is furnished to 
do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in 
all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
THE
+ * SOFTWARE.
+ */
+
+static int orig_sched_scheduler;
+static struct sched_param orig_sched_params;
+
+static void
+on_fork() {
+    int ret = pthread_setschedparam(pthread_self(), orig_sched_scheduler, 
&orig_sched_params);
+    if (ret != 0) {
+        ww_log_errno(LOG_ERROR, "failed to reset scheduler priority for child 
process");
+    }
+}
+
+void
+util_sched_realtime() {
+    int ret = pthread_getschedparam(pthread_self(), &orig_sched_scheduler, 
&orig_sched_params);
+    if (ret != 0) {
+        ww_log_errno(LOG_ERROR, "failed to get original scheduling policy");
+        return;
+    }
+
+    ww_log(LOG_INFO, "original scheduling policy: %d (priority %d)", 
orig_sched_scheduler,
+           orig_sched_params.sched_priority);
+
+    int priority = sched_get_priority_min(SCHED_RR);
+    ww_assert(priority != -1);
+
+    const struct sched_param param = {.sched_priority = priority};
+    if (pthread_setschedparam(pthread_self(), SCHED_RR, &param) != 0) {
+        ww_log_errno(LOG_WARN, "failed to set scheduler priority");
+        return;
+    }
+
+    ww_log(LOG_INFO, "using SCHED_RR with priority %d", priority);
+    pthread_atfork(NULL, NULL, on_fork);
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/waywall-0.2026.02.06/waywall/util/str.c 
new/waywall-0.2026.06.13/waywall/util/str.c
--- old/waywall-0.2026.02.06/waywall/util/str.c 2026-02-06 22:56:05.000000000 
+0100
+++ new/waywall-0.2026.06.13/waywall/util/str.c 2026-06-13 20:02:32.000000000 
+0200
@@ -167,7 +167,7 @@
 
 ssize_t
 str_index(str s, char needle, ssize_t start) {
-    char *ptr = memchr(s.data + start, needle, s.len - start);
+    const char *ptr = memchr(s.data + start, needle, s.len - start);
 
     return (ptr ? ptr - s.data : -1);
 }

Reply via email to