Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package aquamarine for openSUSE:Factory 
checked in at 2025-07-17 17:18:45
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/aquamarine (Old)
 and      /work/SRC/openSUSE:Factory/.aquamarine.new.8875 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "aquamarine"

Thu Jul 17 17:18:45 2025 rev:7 rq:1293861 version:0.9.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/aquamarine/aquamarine.changes    2025-03-25 
22:17:56.332353063 +0100
+++ /work/SRC/openSUSE:Factory/.aquamarine.new.8875/aquamarine.changes  
2025-07-17 17:19:58.402767863 +0200
@@ -1,0 +2,26 @@
+Wed Jul 16 12:35:08 UTC 2025 - Florian "sp1rit" <sp1...@disroot.org>
+
+- Update to aquamarine-0.9.1:
+  * A small patch release fixing builds with hl <= 0.49
+  * Fixes:
+    - backend: don't use a shorthand for SP
+    - Avoid unnecessary modeset
+
+- Changes from aquamarine aquamarine-0.9.0:
+  * A new major update, breaking ABI, but bringing a lot of
+    improvements
+  * Fixes:
+    - swapchain: fix age
+    - wayland: don't force swapchain length
+    - backend: Fix compiler warnings
+    - Restore hdr metadata after vt switch
+    - atomic: fix compiler warning with string
+    - clang-tidy: fix some errors
+  * Other:
+    - a few small renderer optimisations
+    - depend on gles3 and use vertex array objects
+    - reduce a bit of local temporar copies going around in renderer
+    - Use typed signals from hyprutils
+    - optimize blitting and use gles3 shaders
+
+-------------------------------------------------------------------

Old:
----
  aquamarine-0.8.0.tar.xz

New:
----
  aquamarine-0.9.1.tar.xz

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

Other differences:
------------------
++++++ aquamarine.spec ++++++
--- /var/tmp/diff_new_pack.Dz6X00/_old  2025-07-17 17:19:59.430810706 +0200
+++ /var/tmp/diff_new_pack.Dz6X00/_new  2025-07-17 17:19:59.430810706 +0200
@@ -16,18 +16,19 @@
 #
 
 
-%define sover   7
+%define sover   8
 %define _description %{expand:
 Aquamarine is a very light linux rendering backend library. It
 provides basic abstractions for an application to render on a Wayland
 session (in a window) or a native DRM session.}
 Name:           aquamarine
-Version:        0.8.0
+Version:        0.9.1
 Release:        0
 Summary:        Rendering backend library
 License:        BSD-3-Clause
 URL:            https://github.com/hyprwm/aquamarine
 Source0:        %{name}-%{version}.tar.xz
+BuildRequires:  Mesa-libGLESv3-devel
 BuildRequires:  cmake
 BuildRequires:  gcc-c++
 BuildRequires:  pkgconfig
@@ -36,7 +37,7 @@
 BuildRequires:  pkgconfig(gl)
 BuildRequires:  pkgconfig(glesv2)
 BuildRequires:  pkgconfig(hwdata)
-BuildRequires:  pkgconfig(hyprutils) >= 0.5.2
+BuildRequires:  pkgconfig(hyprutils) >= 0.8.0
 BuildRequires:  pkgconfig(libdisplay-info)
 BuildRequires:  pkgconfig(libdrm)
 BuildRequires:  pkgconfig(libinput) >= 1.26.0

++++++ aquamarine-0.8.0.tar.xz -> aquamarine-0.9.1.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aquamarine-0.8.0/.clang-tidy 
new/aquamarine-0.9.1/.clang-tidy
--- old/aquamarine-0.8.0/.clang-tidy    2025-03-16 23:00:48.000000000 +0100
+++ new/aquamarine-0.9.1/.clang-tidy    2025-07-07 17:58:11.000000000 +0200
@@ -1,12 +1,12 @@
 WarningsAsErrors: '*'
 HeaderFilterRegex: '.*\.hpp'
-FormatStyle: file
+FormatStyle: 'file'
 Checks: >
   -*,
   bugprone-*,
   -bugprone-easily-swappable-parameters,
-  -bugprone-forward-declararion-namespace,
-  -bugprone-forward-declararion-namespace,
+  -bugprone-forward-declaration-namespace,
+  -bugprone-forward-declaration-namespace,
   -bugprone-macro-parentheses,
   -bugprone-narrowing-conversions,
   -bugprone-branch-clone,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aquamarine-0.8.0/.github/workflows/nix.yml 
new/aquamarine-0.9.1/.github/workflows/nix.yml
--- old/aquamarine-0.8.0/.github/workflows/nix.yml      2025-03-16 
23:00:48.000000000 +0100
+++ new/aquamarine-0.9.1/.github/workflows/nix.yml      2025-07-07 
17:58:11.000000000 +0200
@@ -13,7 +13,35 @@
     steps:
     - uses: actions/checkout@v3
 
-    - uses: cachix/install-nix-action@v26
+    - name: Install Nix
+      uses: nixbuild/nix-quick-install-action@v31
+      with:
+        nix_conf: |
+          keep-env-derivations = true
+          keep-outputs = true
+
+    - name: Restore and save Nix store
+      uses: nix-community/cache-nix-action@v6
+      with:
+        # restore and save a cache using this key
+        primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', 
'**/flake.lock') }}
+        # if there's no cache hit, restore a cache by this prefix
+        restore-prefixes-first-match: nix-${{ runner.os }}-
+        # collect garbage until the Nix store size (in bytes) is at most this 
number
+        # before trying to save a new cache
+        # 1G = 1073741824
+        gc-max-store-size-linux: 1G
+        # do purge caches
+        purge: true
+        # purge all versions of the cache
+        purge-prefixes: nix-${{ runner.os }}-
+        # created more than this number of seconds ago
+        purge-created: 0
+        # or, last accessed more than this number of seconds ago
+        # relative to the start of the `Post Restore and save Nix store` phase
+        purge-last-accessed: 0
+        # except any version with the key that is the same as the `primary-key`
+        purge-primary-key: never
 
     # not needed (yet)
     # - uses: cachix/cachix-action@v12
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aquamarine-0.8.0/CMakeLists.txt 
new/aquamarine-0.9.1/CMakeLists.txt
--- old/aquamarine-0.8.0/CMakeLists.txt 2025-03-16 23:00:48.000000000 +0100
+++ new/aquamarine-0.9.1/CMakeLists.txt 2025-07-07 17:58:11.000000000 +0200
@@ -19,7 +19,7 @@
 set(LIBDIR ${CMAKE_INSTALL_FULL_LIBDIR})
 
 find_package(PkgConfig REQUIRED)
-find_package(OpenGL REQUIRED COMPONENTS "GLES2")
+find_package(OpenGL REQUIRED COMPONENTS "GLES3")
 find_package(hyprwayland-scanner 0.4.0 REQUIRED)
 pkg_check_modules(
   deps
@@ -29,7 +29,7 @@
   libinput>=1.26.0
   wayland-client
   wayland-protocols
-  hyprutils>=0.5.2
+  hyprutils>=0.8.0
   pixman-1
   libdrm
   gbm
@@ -65,7 +65,7 @@
   PUBLIC "./include"
   PRIVATE "./src" "./src/include" "./protocols" "${CMAKE_BINARY_DIR}")
 set_target_properties(aquamarine PROPERTIES VERSION ${AQUAMARINE_VERSION}
-                                            SOVERSION 7)
+                                            SOVERSION 8)
 target_link_libraries(aquamarine OpenGL::EGL OpenGL::OpenGL PkgConfig::deps)
 
 check_include_file("sys/timerfd.h" HAS_TIMERFD)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aquamarine-0.8.0/VERSION new/aquamarine-0.9.1/VERSION
--- old/aquamarine-0.8.0/VERSION        2025-03-16 23:00:48.000000000 +0100
+++ new/aquamarine-0.9.1/VERSION        2025-07-07 17:58:11.000000000 +0200
@@ -1 +1 @@
-0.8.0
+0.9.1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aquamarine-0.8.0/flake.lock 
new/aquamarine-0.9.1/flake.lock
--- old/aquamarine-0.8.0/flake.lock     2025-03-16 23:00:48.000000000 +0100
+++ new/aquamarine-0.9.1/flake.lock     2025-07-07 17:58:11.000000000 +0200
@@ -10,11 +10,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1741534688,
-        "narHash": "sha256-EV3945SnjOCuRVbGRghsWx/9D89FyshnSO1Q6/TuQ14=",
+        "lastModified": 1750960192,
+        "narHash": "sha256-AbaeiQAFq66XRMkhnwzxe8uZO2d81RdqO2XuuMzZU8U=",
         "owner": "hyprwm",
         "repo": "hyprutils",
-        "rev": "dd1f720cbc2dbb3c71167c9598045dd3261d27b3",
+        "rev": "d844a08d830e87d023ba2838e645004cb08118f6",
         "type": "github"
       },
       "original": {
@@ -33,11 +33,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1739870480,
-        "narHash": "sha256-SiDN5BGxa/1hAsqhgJsS03C3t2QrLgBT8u+ENJ0Qzwc=",
+        "lastModified": 1750371869,
+        "narHash": "sha256-lGk4gLjgZQ/rndUkzmPYcgbHr8gKU5u71vyrjnwfpB4=",
         "owner": "hyprwm",
         "repo": "hyprwayland-scanner",
-        "rev": "206367a08dc5ac4ba7ad31bdca391d098082e64b",
+        "rev": "aa38edd6e3e277ae6a97ea83a69261a5c3aab9fd",
         "type": "github"
       },
       "original": {
@@ -48,11 +48,11 @@
     },
     "nixpkgs": {
       "locked": {
-        "lastModified": 1741379970,
-        "narHash": "sha256-Wh7esNh7G24qYleLvgOSY/7HlDUzWaL/n4qzlBePpiw=",
+        "lastModified": 1750776420,
+        "narHash": "sha256-/CG+w0o0oJ5itVklOoLbdn2dGB0wbZVOoDm4np6w09A=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "36fd87baa9083f34f7f5027900b62ee6d09b1f2f",
+        "rev": "30a61f056ac492e3b7cdcb69c1e6abdcf00e39cf",
         "type": "github"
       },
       "original": {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aquamarine-0.8.0/flake.nix 
new/aquamarine-0.9.1/flake.nix
--- old/aquamarine-0.8.0/flake.nix      2025-03-16 23:00:48.000000000 +0100
+++ new/aquamarine-0.9.1/flake.nix      2025-07-07 17:58:11.000000000 +0200
@@ -52,7 +52,7 @@
         inputs.hyprwayland-scanner.overlays.default
         (final: prev: {
           aquamarine = final.callPackage ./nix/default.nix {
-            stdenv = final.gcc14Stdenv;
+            stdenv = final.gcc15Stdenv;
             version = version + "+date=" + (mkDate (self.lastModifiedDate or 
"19700101")) + "_" + (self.shortRev or "dirty");
           };
           aquamarine-with-tests = final.aquamarine.override {doCheck = true;};
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/aquamarine-0.8.0/include/aquamarine/backend/Backend.hpp 
new/aquamarine-0.9.1/include/aquamarine/backend/Backend.hpp
--- old/aquamarine-0.8.0/include/aquamarine/backend/Backend.hpp 2025-03-16 
23:00:48.000000000 +0100
+++ new/aquamarine-0.9.1/include/aquamarine/backend/Backend.hpp 2025-07-07 
17:58:11.000000000 +0200
@@ -12,6 +12,15 @@
 #include "Session.hpp"
 
 namespace Aquamarine {
+    class IOutput;
+    class IPointer;
+    class IKeyboard;
+    class ITouch;
+    class ISwitch;
+    class ITablet;
+    class ITabletTool;
+    class ITabletPad;
+
     enum eBackendType : uint32_t {
         AQ_BACKEND_WAYLAND = 0,
         AQ_BACKEND_DRM,
@@ -123,16 +132,16 @@
         void onNewGpu(std::string path);
 
         struct {
-            Hyprutils::Signal::CSignal newOutput;
-            Hyprutils::Signal::CSignal newPointer;
-            Hyprutils::Signal::CSignal newKeyboard;
-            Hyprutils::Signal::CSignal newTouch;
-            Hyprutils::Signal::CSignal newSwitch;
-            Hyprutils::Signal::CSignal newTablet;
-            Hyprutils::Signal::CSignal newTabletTool;
-            Hyprutils::Signal::CSignal newTabletPad;
+            
Hyprutils::Signal::CSignalT<Hyprutils::Memory::CSharedPointer<IOutput>>     
newOutput;
+            
Hyprutils::Signal::CSignalT<Hyprutils::Memory::CSharedPointer<IPointer>>    
newPointer;
+            
Hyprutils::Signal::CSignalT<Hyprutils::Memory::CSharedPointer<IKeyboard>>   
newKeyboard;
+            
Hyprutils::Signal::CSignalT<Hyprutils::Memory::CSharedPointer<ITouch>>      
newTouch;
+            
Hyprutils::Signal::CSignalT<Hyprutils::Memory::CSharedPointer<ISwitch>>     
newSwitch;
+            
Hyprutils::Signal::CSignalT<Hyprutils::Memory::CSharedPointer<ITablet>>     
newTablet;
+            
Hyprutils::Signal::CSignalT<Hyprutils::Memory::CSharedPointer<ITabletTool>> 
newTabletTool;
+            
Hyprutils::Signal::CSignalT<Hyprutils::Memory::CSharedPointer<ITabletPad>>  
newTabletPad;
 
-            Hyprutils::Signal::CSignal pollFDsChanged;
+            Hyprutils::Signal::CSignalT<>                                      
         pollFDsChanged;
         } events;
 
         Hyprutils::Memory::CSharedPointer<IAllocator> primaryAllocator;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aquamarine-0.8.0/include/aquamarine/backend/DRM.hpp 
new/aquamarine-0.9.1/include/aquamarine/backend/DRM.hpp
--- old/aquamarine-0.8.0/include/aquamarine/backend/DRM.hpp     2025-03-16 
23:00:48.000000000 +0100
+++ new/aquamarine-0.9.1/include/aquamarine/backend/DRM.hpp     2025-07-07 
17:58:11.000000000 +0200
@@ -53,7 +53,7 @@
         bool                                                     active = true;
 
         struct {
-            Hyprutils::Signal::CSignal destroy;
+            Hyprutils::Signal::CSignalT<> destroy;
         } events;
 
       private:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/aquamarine-0.8.0/include/aquamarine/backend/Session.hpp 
new/aquamarine-0.9.1/include/aquamarine/backend/Session.hpp
--- old/aquamarine-0.8.0/include/aquamarine/backend/Session.hpp 2025-03-16 
23:00:48.000000000 +0100
+++ new/aquamarine-0.9.1/include/aquamarine/backend/Session.hpp 2025-07-07 
17:58:11.000000000 +0200
@@ -49,8 +49,8 @@
         };
 
         struct {
-            Hyprutils::Signal::CSignal change;
-            Hyprutils::Signal::CSignal remove;
+            Hyprutils::Signal::CSignalT<SChangeEvent> change;
+            Hyprutils::Signal::CSignalT<>             remove;
         } events;
 
       private:
@@ -224,9 +224,9 @@
         };
 
         struct {
-            Hyprutils::Signal::CSignal changeActive;
-            Hyprutils::Signal::CSignal addDrmCard;
-            Hyprutils::Signal::CSignal destroy;
+            Hyprutils::Signal::CSignalT<>                 changeActive;
+            Hyprutils::Signal::CSignalT<SAddDrmCardEvent> addDrmCard;
+            Hyprutils::Signal::CSignalT<>                 destroy;
         } events;
 
       private:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/aquamarine-0.8.0/include/aquamarine/buffer/Buffer.hpp 
new/aquamarine-0.9.1/include/aquamarine/buffer/Buffer.hpp
--- old/aquamarine-0.8.0/include/aquamarine/buffer/Buffer.hpp   2025-03-16 
23:00:48.000000000 +0100
+++ new/aquamarine-0.9.1/include/aquamarine/buffer/Buffer.hpp   2025-07-07 
17:58:11.000000000 +0200
@@ -66,8 +66,8 @@
         CAttachmentManager                             attachments;
 
         struct {
-            Hyprutils::Signal::CSignal destroy;
-            Hyprutils::Signal::CSignal backendRelease;
+            Hyprutils::Signal::CSignalT<> destroy;
+            Hyprutils::Signal::CSignalT<> backendRelease;
         } events;
 
       private:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aquamarine-0.8.0/include/aquamarine/input/Input.hpp 
new/aquamarine-0.9.1/include/aquamarine/input/Input.hpp
--- old/aquamarine-0.8.0/include/aquamarine/input/Input.hpp     2025-03-16 
23:00:48.000000000 +0100
+++ new/aquamarine-0.9.1/include/aquamarine/input/Input.hpp     2025-07-07 
17:58:11.000000000 +0200
@@ -28,9 +28,9 @@
         };
 
         struct {
-            Hyprutils::Signal::CSignal destroy;
-            Hyprutils::Signal::CSignal key;
-            Hyprutils::Signal::CSignal modifiers;
+            Hyprutils::Signal::CSignalT<>                destroy;
+            Hyprutils::Signal::CSignalT<SKeyEvent>       key;
+            Hyprutils::Signal::CSignalT<SModifiersEvent> modifiers;
         } events;
     };
 
@@ -128,23 +128,23 @@
         };
 
         struct {
-            Hyprutils::Signal::CSignal destroy;
-            Hyprutils::Signal::CSignal move;
-            Hyprutils::Signal::CSignal warp;
-            Hyprutils::Signal::CSignal button;
-            Hyprutils::Signal::CSignal axis;
-            Hyprutils::Signal::CSignal frame;
-
-            Hyprutils::Signal::CSignal swipeBegin;
-            Hyprutils::Signal::CSignal swipeUpdate;
-            Hyprutils::Signal::CSignal swipeEnd;
-
-            Hyprutils::Signal::CSignal pinchBegin;
-            Hyprutils::Signal::CSignal pinchUpdate;
-            Hyprutils::Signal::CSignal pinchEnd;
+            Hyprutils::Signal::CSignalT<>                  destroy;
+            Hyprutils::Signal::CSignalT<SMoveEvent>        move;
+            Hyprutils::Signal::CSignalT<SWarpEvent>        warp;
+            Hyprutils::Signal::CSignalT<SButtonEvent>      button;
+            Hyprutils::Signal::CSignalT<SAxisEvent>        axis;
+            Hyprutils::Signal::CSignalT<>                  frame;
+
+            Hyprutils::Signal::CSignalT<SSwipeBeginEvent>  swipeBegin;
+            Hyprutils::Signal::CSignalT<SSwipeUpdateEvent> swipeUpdate;
+            Hyprutils::Signal::CSignalT<SSwipeEndEvent>    swipeEnd;
+
+            Hyprutils::Signal::CSignalT<SPinchBeginEvent>  pinchBegin;
+            Hyprutils::Signal::CSignalT<SPinchUpdateEvent> pinchUpdate;
+            Hyprutils::Signal::CSignalT<SPinchEndEvent>    pinchEnd;
 
-            Hyprutils::Signal::CSignal holdBegin;
-            Hyprutils::Signal::CSignal holdEnd;
+            Hyprutils::Signal::CSignalT<SHoldBeginEvent>   holdBegin;
+            Hyprutils::Signal::CSignalT<SHoldEndEvent>     holdEnd;
         } events;
     };
 
@@ -182,12 +182,12 @@
         };
 
         struct {
-            Hyprutils::Signal::CSignal destroy;
-            Hyprutils::Signal::CSignal move;
-            Hyprutils::Signal::CSignal down;
-            Hyprutils::Signal::CSignal up;
-            Hyprutils::Signal::CSignal cancel;
-            Hyprutils::Signal::CSignal frame;
+            Hyprutils::Signal::CSignalT<>             destroy;
+            Hyprutils::Signal::CSignalT<SMotionEvent> move;
+            Hyprutils::Signal::CSignalT<SDownEvent>   down;
+            Hyprutils::Signal::CSignalT<SUpEvent>     up;
+            Hyprutils::Signal::CSignalT<SCancelEvent> cancel;
+            Hyprutils::Signal::CSignalT<>             frame;
         } events;
     };
 
@@ -213,8 +213,8 @@
         };
 
         struct {
-            Hyprutils::Signal::CSignal destroy;
-            Hyprutils::Signal::CSignal fire;
+            Hyprutils::Signal::CSignalT<>           destroy;
+            Hyprutils::Signal::CSignalT<SFireEvent> fire;
         } events;
     };
 
@@ -277,11 +277,11 @@
         };
 
         struct {
-            Hyprutils::Signal::CSignal axis;
-            Hyprutils::Signal::CSignal proximity;
-            Hyprutils::Signal::CSignal tip;
-            Hyprutils::Signal::CSignal button;
-            Hyprutils::Signal::CSignal destroy;
+            Hyprutils::Signal::CSignalT<SAxisEvent>      axis;
+            Hyprutils::Signal::CSignalT<SProximityEvent> proximity;
+            Hyprutils::Signal::CSignalT<STipEvent>       tip;
+            Hyprutils::Signal::CSignalT<SButtonEvent>    button;
+            Hyprutils::Signal::CSignalT<>                destroy;
         } events;
     };
 
@@ -321,7 +321,7 @@
         uint32_t capabilities = 0; // enum eTabletToolCapabilities
 
         struct {
-            Hyprutils::Signal::CSignal destroy;
+            Hyprutils::Signal::CSignalT<> destroy;
         } events;
     };
 
@@ -379,11 +379,11 @@
         };
 
         struct {
-            Hyprutils::Signal::CSignal destroy;
-            Hyprutils::Signal::CSignal button;
-            Hyprutils::Signal::CSignal ring;
-            Hyprutils::Signal::CSignal strip;
-            Hyprutils::Signal::CSignal attach;
+            Hyprutils::Signal::CSignalT<>             destroy;
+            Hyprutils::Signal::CSignalT<SButtonEvent> button;
+            Hyprutils::Signal::CSignalT<SRingEvent>   ring;
+            Hyprutils::Signal::CSignalT<SStripEvent>  strip;
+            Hyprutils::Signal::CSignalT<>             attach;
         } events;
     };
-}
\ No newline at end of file
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/aquamarine-0.8.0/include/aquamarine/output/Output.hpp 
new/aquamarine-0.9.1/include/aquamarine/output/Output.hpp
--- old/aquamarine-0.8.0/include/aquamarine/output/Output.hpp   2025-03-16 
23:00:48.000000000 +0100
+++ new/aquamarine-0.9.1/include/aquamarine/output/Output.hpp   2025-07-07 
17:58:11.000000000 +0200
@@ -209,12 +209,12 @@
         };
 
         struct {
-            Hyprutils::Signal::CSignal destroy;
-            Hyprutils::Signal::CSignal frame;
-            Hyprutils::Signal::CSignal needsFrame;
-            Hyprutils::Signal::CSignal present;
-            Hyprutils::Signal::CSignal commit;
-            Hyprutils::Signal::CSignal state;
+            Hyprutils::Signal::CSignalT<>              destroy;
+            Hyprutils::Signal::CSignalT<>              frame;
+            Hyprutils::Signal::CSignalT<>              needsFrame;
+            Hyprutils::Signal::CSignalT<SPresentEvent> present;
+            Hyprutils::Signal::CSignalT<>              commit;
+            Hyprutils::Signal::CSignalT<SStateEvent>   state;
         } events;
     };
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aquamarine-0.8.0/src/allocator/Swapchain.cpp 
new/aquamarine-0.9.1/src/allocator/Swapchain.cpp
--- old/aquamarine-0.8.0/src/allocator/Swapchain.cpp    2025-03-16 
23:00:48.000000000 +0100
+++ new/aquamarine-0.9.1/src/allocator/Swapchain.cpp    2025-07-07 
17:58:11.000000000 +0200
@@ -66,7 +66,7 @@
     lastAcquired = (lastAcquired + 1) % options.length;
 
     if (age)
-        *age = 1;
+        *age = options.length; // we always just rotate
 
     return buffers.at(lastAcquired);
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aquamarine-0.8.0/src/backend/Backend.cpp 
new/aquamarine-0.9.1/src/backend/Backend.cpp
--- old/aquamarine-0.8.0/src/backend/Backend.cpp        2025-03-16 
23:00:48.000000000 +0100
+++ new/aquamarine-0.9.1/src/backend/Backend.cpp        2025-07-07 
17:58:11.000000000 +0200
@@ -102,8 +102,7 @@
 bool Aquamarine::CBackend::start() {
     log(AQ_LOG_DEBUG, "Starting the Aquamarine backend!");
 
-    bool fallback = false;
-    int  started  = 0;
+    int  started = 0;
 
     auto optionsForType = [this](eBackendType type) -> 
SBackendImplementationOptions {
         for (auto const& o : implementationOptions) {
@@ -118,7 +117,6 @@
 
         if (!ok) {
             log(AQ_LOG_ERROR, std::format("Requested backend ({}) could not 
start, enabling fallbacks", backendTypeToName(implementations.at(i)->type())));
-            fallback = true;
             if 
(optionsForType(implementations.at(i)->type()).backendRequestMode == 
AQ_BACKEND_REQUEST_MANDATORY) {
                 log(AQ_LOG_CRITICAL, std::format("Requested backend ({}) could 
not start and it's mandatory, cannot continue!", 
backendTypeToName(implementations.at(i)->type())));
                 implementations.clear();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aquamarine-0.8.0/src/backend/Headless.cpp 
new/aquamarine-0.9.1/src/backend/Headless.cpp
--- old/aquamarine-0.8.0/src/backend/Headless.cpp       2025-03-16 
23:00:48.000000000 +0100
+++ new/aquamarine-0.9.1/src/backend/Headless.cpp       2025-07-07 
17:58:11.000000000 +0200
@@ -181,7 +181,6 @@
 void Aquamarine::CHeadlessBackend::updateTimerFD() {
     long long  lowestNs = TIMESPEC_NSEC_PER_SEC * 240 /* 240s, 4 mins */;
     const auto clocknow = std::chrono::steady_clock::now();
-    bool       any      = false;
 
     for (auto const& t : timers.timers) {
         auto delta = 
std::chrono::duration_cast<std::chrono::microseconds>(t.when - 
clocknow).count() * 1000 /* µs -> ns */;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aquamarine-0.8.0/src/backend/Session.cpp 
new/aquamarine-0.9.1/src/backend/Session.cpp
--- old/aquamarine-0.8.0/src/backend/Session.cpp        2025-03-16 
23:00:48.000000000 +0100
+++ new/aquamarine-0.9.1/src/backend/Session.cpp        2025-07-07 
17:58:11.000000000 +0200
@@ -620,7 +620,6 @@
             break;
         }
         case LIBINPUT_EVENT_TOUCH_FRAME: {
-            auto te = libinput_event_get_touch_event(e);
             hlDevice->touch->events.frame.emit();
             break;
         }
@@ -709,7 +708,8 @@
                 break;
             }
 
-            // fallthrough. If this is proximity in, also process axis.
+            // If this is proximity in, also process axis.
+            [[fallthrough]];
         }
         case LIBINPUT_EVENT_TABLET_TOOL_AXIS: {
             auto                tte  = libinput_event_get_tablet_tool_event(e);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aquamarine-0.8.0/src/backend/Wayland.cpp 
new/aquamarine-0.9.1/src/backend/Wayland.cpp
--- old/aquamarine-0.8.0/src/backend/Wayland.cpp        2025-03-16 
23:00:48.000000000 +0100
+++ new/aquamarine-0.9.1/src/backend/Wayland.cpp        2025-07-07 
17:58:11.000000000 +0200
@@ -542,8 +542,7 @@
 }
 
 bool Aquamarine::CWaylandOutput::commit() {
-    Vector2D pixelSize   = {};
-    uint32_t refreshRate = 0;
+    Vector2D pixelSize = {};
 
     if (state->internalState.customMode)
         pixelSize = state->internalState.customMode->pixelSize;
@@ -566,7 +565,7 @@
         return true;
     }
 
-    if (!swapchain->reconfigure(SSwapchainOptions{.length = 2, .size = 
pixelSize, .format = format})) {
+    if (!swapchain->reconfigure(SSwapchainOptions{.length = 
swapchain->currentOptions().length, .size = pixelSize, .format = format})) {
         backend->backend->log(AQ_LOG_ERROR, std::format("Output {}: pending 
state rejected: swapchain failed reconfiguring", name));
         return false;
     }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aquamarine-0.8.0/src/backend/drm/DRM.cpp 
new/aquamarine-0.9.1/src/backend/drm/DRM.cpp
--- old/aquamarine-0.8.0/src/backend/drm/DRM.cpp        2025-03-16 
23:00:48.000000000 +0100
+++ new/aquamarine-0.9.1/src/backend/drm/DRM.cpp        2025-07-07 
17:58:11.000000000 +0200
@@ -40,7 +40,7 @@
 #define SP CSharedPointer
 
 Aquamarine::CDRMBackend::CDRMBackend(SP<CBackend> backend_) : 
backend(backend_) {
-    listeners.sessionActivate = 
backend->session->events.changeActive.registerListener([this](std::any d) {
+    listeners.sessionActivate = 
backend->session->events.changeActive.listen([this] {
         if (backend->session->active) {
             // session got activated, we need to restore
             restoreAfterVT();
@@ -378,16 +378,18 @@
         if (!c->crtc || !c->output)
             continue;
 
+        auto&                   STATE = c->output->state->state();
+
         SDRMConnectorCommitData data = {
-            .mainFB   = nullptr,
-            .modeset  = true,
-            .blocking = true,
-            .flags    = 0,
-            .test     = false,
+            .mainFB      = nullptr,
+            .modeset     = true,
+            .blocking    = true,
+            .flags       = 0,
+            .test        = false,
+            .hdrMetadata = STATE.hdrMetadata,
         };
 
-        auto& STATE = c->output->state->state();
-        auto& MODE  = STATE.customMode ? STATE.customMode : STATE.mode;
+        auto& MODE = STATE.customMode ? STATE.customMode : STATE.mode;
 
         if (!MODE) {
             backend->log(AQ_LOG_WARNING, "drm: Connector {} has output but 
state has no mode, will send a reset state event later.");
@@ -734,8 +736,7 @@
 
     drmFreeVersion(drmVer);
 
-    listeners.gpuChange = gpu->events.change.registerListener([this](std::any 
d) {
-        auto E = std::any_cast<CSessionDevice::SChangeEvent>(d);
+    listeners.gpuChange = gpu->events.change.listen([this](const 
CSessionDevice::SChangeEvent& E) {
         if (E.type == CSessionDevice::AQ_SESSION_EVENT_CHANGE_HOTPLUG) {
             backend->log(AQ_LOG_DEBUG, std::format("drm: Got a hotplug event 
for {}", gpuName));
             recheckOutputs();
@@ -745,7 +746,7 @@
         }
     });
 
-    listeners.gpuRemove = gpu->events.remove.registerListener([this](std::any 
d) {
+    listeners.gpuRemove = gpu->events.remove.listen([this] {
         std::erase_if(backend->implementations, [this](const auto& impl) { 
return impl->drmFD() == this->drmFD(); });
         backend->events.pollFDsChanged.emit();
     });
@@ -894,7 +895,6 @@
 }
 
 bool Aquamarine::CDRMBackend::start() {
-    impl->reset();
     return true;
 }
 
@@ -2071,7 +2071,7 @@
 
     closeHandles();
 
-    listeners.destroyBuffer = 
buffer->events.destroy.registerListener([this](std::any d) {
+    listeners.destroyBuffer = buffer->events.destroy.listen([this] {
         drop();
         dead      = true;
         id        = 0;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aquamarine-0.8.0/src/backend/drm/Renderer.cpp 
new/aquamarine-0.9.1/src/backend/drm/Renderer.cpp
--- old/aquamarine-0.8.0/src/backend/drm/Renderer.cpp   2025-03-16 
23:00:48.000000000 +0100
+++ new/aquamarine-0.9.1/src/backend/drm/Renderer.cpp   2025-07-07 
17:58:11.000000000 +0200
@@ -9,10 +9,13 @@
 #include "Shared.hpp"
 #include "FormatUtils.hpp"
 #include <aquamarine/allocator/GBM.hpp>
+#include <hyprutils/os/FileDescriptor.hpp>
 
 using namespace Aquamarine;
 using namespace Hyprutils::Memory;
 using namespace Hyprutils::Math;
+using namespace Hyprutils::OS;
+
 #define SP CSharedPointer
 #define WP CWeakPointer
 
@@ -20,11 +23,13 @@
 #define GLCALL(__CALL__)                                                       
                                                                                
                    \
     {                                                                          
                                                                                
                    \
         __CALL__;                                                              
                                                                                
                    \
-        auto err = glGetError();                                               
                                                                                
                    \
-        if (err != GL_NO_ERROR) {                                              
                                                                                
                    \
-            backend->log(AQ_LOG_ERROR,                                         
                                                                                
                    \
-                         std::format("[GLES] Error in call at {}@{}: 0x{:x}", 
__LINE__,                                                                       
                     \
-                                     ([]() constexpr -> std::string { return 
std::string(__FILE__).substr(std::string(__FILE__).find_last_of('/') + 1); 
})(), err));               \
+        if (Aquamarine::isTrace()) {                                           
                                                                                
                    \
+            auto err = glGetError();                                           
                                                                                
                    \
+            if (err != GL_NO_ERROR) {                                          
                                                                                
                    \
+                backend->log(AQ_LOG_ERROR,                                     
                                                                                
                    \
+                             std::format("[GLES] Error in call at {}@{}: 
0x{:x}", __LINE__,                                                              
                          \
+                                         ([]() constexpr -> std::string { 
return std::string(__FILE__).substr(std::string(__FILE__).find_last_of('/') + 
1); })(), err));           \
+            }                                                                  
                                                                                
                    \
         }                                                                      
                                                                                
                    \
     }
 
@@ -78,10 +83,15 @@
 }
 
 inline const std::string VERT_SRC = R"#(
+#version 300 es
+precision highp float;
+
 uniform mat3 proj;
-attribute vec2 pos;
-attribute vec2 texcoord;
-varying vec2 v_texcoord;
+
+in vec2 pos;
+in vec2 texcoord;
+
+out vec2 v_texcoord;
 
 void main() {
     gl_Position = vec4(proj * vec3(pos, 1.0), 1.0);
@@ -89,22 +99,30 @@
 })#";
 
 inline const std::string FRAG_SRC = R"#(
+#version 300 es
 precision highp float;
-varying vec2 v_texcoord; // is in 0-1
+
+in vec2 v_texcoord;
+out vec4 fragColor;
+
 uniform sampler2D tex;
 
 void main() {
-    gl_FragColor = texture2D(tex, v_texcoord);
+    fragColor = texture(tex, v_texcoord);
 })#";
 
 inline const std::string FRAG_SRC_EXT = R"#(
-#extension GL_OES_EGL_image_external : require
+#version 300 es
+#extension GL_OES_EGL_image_external_essl3 : require
 precision highp float;
-varying vec2 v_texcoord; // is in 0-1
+
+in vec2 v_texcoord;
+out vec4 fragColor;
+
 uniform samplerExternalOES texture0;
 
 void main() {
-    gl_FragColor = texture2D(texture0, v_texcoord);
+    fragColor = texture(texture0, v_texcoord);
 })#";
 
 // ------------------- egl stuff
@@ -167,6 +185,54 @@
 
 // -------------------
 
+CDRMRenderer::SShader::~SShader() {
+    if (program == 0)
+        return;
+
+    if (shaderVao)
+        glDeleteVertexArrays(1, &shaderVao);
+
+    if (shaderVboPos)
+        glDeleteBuffers(1, &shaderVboPos);
+
+    if (shaderVboUv)
+        glDeleteBuffers(1, &shaderVboUv);
+
+    glDeleteProgram(program);
+    program = 0;
+}
+
+void CDRMRenderer::SShader::createVao() {
+    const float fullVerts[] = {
+        1, 0, // top right
+        0, 0, // top left
+        1, 1, // bottom right
+        0, 1, // bottom left
+    };
+
+    glGenVertexArrays(1, &shaderVao);
+    glBindVertexArray(shaderVao);
+
+    if (posAttrib != -1) {
+        glGenBuffers(1, &shaderVboPos);
+        glBindBuffer(GL_ARRAY_BUFFER, shaderVboPos);
+        glBufferData(GL_ARRAY_BUFFER, sizeof(fullVerts), fullVerts, 
GL_STATIC_DRAW);
+        glEnableVertexAttribArray(posAttrib);
+        glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
+    }
+
+    if (texAttrib != -1) {
+        glGenBuffers(1, &shaderVboUv);
+        glBindBuffer(GL_ARRAY_BUFFER, shaderVboUv);
+        glBufferData(GL_ARRAY_BUFFER, sizeof(fullVerts), fullVerts, 
GL_STATIC_DRAW);
+        glEnableVertexAttribArray(texAttrib);
+        glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
+    }
+
+    glBindVertexArray(0);
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+}
+
 EGLDeviceEXT CDRMRenderer::eglDeviceFromDRMFD(int drmFD) {
     EGLint nDevices = 0;
     if (!proc.eglQueryDevicesEXT(0, nullptr, &nDevices)) {
@@ -241,12 +307,19 @@
     }
 
     // if the driver doesn't mark linear as external, add it. It's allowed 
unless the driver says otherwise. (e.g. nvidia)
-    if (!linearIsExternal && std::ranges::find(mods, DRM_FORMAT_MOD_LINEAR) == 
mods.end() && mods.size() == 0)
+    if (!linearIsExternal && std::ranges::find(mods, DRM_FORMAT_MOD_LINEAR) == 
mods.end() && mods.empty())
         result.emplace_back(DRM_FORMAT_MOD_LINEAR, true);
 
     return result;
 }
 
+void CDRMRenderer::useProgram(GLuint prog) {
+    if (m_currentProgram == prog)
+        return;
+
+    GLCALL(glUseProgram(prog));
+}
+
 bool CDRMRenderer::initDRMFormats() {
     std::vector<EGLint> formats;
 
@@ -255,7 +328,7 @@
     formats.resize(len);
     proc.eglQueryDmaBufFormatsEXT(egl.display, len, formats.data(), &len);
 
-    if (formats.size() == 0) {
+    if (formats.empty()) {
         backend->log(AQ_LOG_ERROR, "EGL: Failed to get formats");
         return false;
     }
@@ -276,7 +349,7 @@
             mods = *ret;
         }
 
-        hasModifiers = hasModifiers || mods.size() > 0;
+        hasModifiers = hasModifiers || !mods.empty();
 
         // EGL can always do implicit modifiers.
         mods.emplace_back(DRM_FORMAT_MOD_INVALID, true);
@@ -365,7 +438,7 @@
     RASSERT(eglBindAPI(EGL_OPENGL_ES_API) != EGL_FALSE, "Couldn't bind to 
EGL's opengl ES API. This means your gpu driver f'd up. This is not a Hyprland 
or Aquamarine issue.");
 }
 
-void CDRMRenderer::initContext(bool GLES2) {
+void CDRMRenderer::initContext() {
     RASSERT(egl.display != nullptr && egl.display != EGL_NO_DISPLAY, 
"CDRMRenderer: Can't create EGL context without display");
 
     EGLint major, minor;
@@ -400,27 +473,15 @@
 
     auto attrsNoVer = attrs;
 
-    if (GLES2) {
-        attrs.push_back(EGL_CONTEXT_MAJOR_VERSION);
-        attrs.push_back(2);
-        attrs.push_back(EGL_CONTEXT_MINOR_VERSION);
-        attrs.push_back(0);
-    } else {
-        attrs.push_back(EGL_CONTEXT_MAJOR_VERSION);
-        attrs.push_back(3);
-        attrs.push_back(EGL_CONTEXT_MINOR_VERSION);
-        attrs.push_back(2);
-    }
+    attrs.push_back(EGL_CONTEXT_MAJOR_VERSION);
+    attrs.push_back(3);
+    attrs.push_back(EGL_CONTEXT_MINOR_VERSION);
+    attrs.push_back(2);
 
     attrs.push_back(EGL_NONE);
 
     egl.context = eglCreateContext(egl.display, EGL_NO_CONFIG_KHR, 
EGL_NO_CONTEXT, attrs.data());
     if (egl.context == EGL_NO_CONTEXT) {
-        if (GLES2) {
-            backend->log(AQ_LOG_ERROR, "CDRMRenderer: Can't create renderer, 
eglCreateContext failed with GLES 2.0");
-            return;
-        }
-
         backend->log(AQ_LOG_ERROR, "CDRMRenderer: eglCreateContext failed with 
GLES 3.2, retrying GLES 3.0");
 
         attrs = attrsNoVer;
@@ -458,7 +519,7 @@
         free(drmName);
     }
 
-    backend->log(AQ_LOG_DEBUG, std::format("Creating {}CDRMRenderer on gpu 
{}", GLES2 ? "GLES2 " : "", gpuName));
+    backend->log(AQ_LOG_DEBUG, std::format("Creating CDRMRenderer on gpu {}", 
gpuName));
     backend->log(AQ_LOG_DEBUG, std::format("Using: {}", 
(char*)glGetString(GL_VERSION)));
     backend->log(AQ_LOG_DEBUG, std::format("Vendor: {}", 
(char*)glGetString(GL_VENDOR)));
     backend->log(AQ_LOG_DEBUG, std::format("Renderer: {}", 
(char*)glGetString(GL_RENDERER)));
@@ -474,26 +535,28 @@
     if (!exts.EXT_image_dma_buf_import || !initDRMFormats())
         backend->log(AQ_LOG_ERROR, "CDRMRenderer: initDRMFormats failed, 
dma-buf won't work");
 
-    gl.shader.program = createProgram(VERT_SRC, FRAG_SRC);
-    if (gl.shader.program == 0)
+    shader.program = createProgram(VERT_SRC, FRAG_SRC);
+    if (shader.program == 0)
         backend->log(AQ_LOG_ERROR, "CDRMRenderer: texture shader failed");
 
-    gl.shader.proj      = glGetUniformLocation(gl.shader.program, "proj");
-    gl.shader.posAttrib = glGetAttribLocation(gl.shader.program, "pos");
-    gl.shader.texAttrib = glGetAttribLocation(gl.shader.program, "texcoord");
-    gl.shader.tex       = glGetUniformLocation(gl.shader.program, "tex");
+    shader.proj      = glGetUniformLocation(shader.program, "proj");
+    shader.posAttrib = glGetAttribLocation(shader.program, "pos");
+    shader.texAttrib = glGetAttribLocation(shader.program, "texcoord");
+    shader.tex       = glGetUniformLocation(shader.program, "tex");
+    shader.createVao();
 
-    gl.shaderExt.program = createProgram(VERT_SRC, FRAG_SRC_EXT);
-    if (gl.shaderExt.program == 0)
+    shaderExt.program = createProgram(VERT_SRC, FRAG_SRC_EXT);
+    if (shaderExt.program == 0)
         backend->log(AQ_LOG_ERROR, "CDRMRenderer: external texture shader 
failed");
 
-    gl.shaderExt.proj      = glGetUniformLocation(gl.shaderExt.program, 
"proj");
-    gl.shaderExt.posAttrib = glGetAttribLocation(gl.shaderExt.program, "pos");
-    gl.shaderExt.texAttrib = glGetAttribLocation(gl.shaderExt.program, 
"texcoord");
-    gl.shaderExt.tex       = glGetUniformLocation(gl.shaderExt.program, "tex");
+    shaderExt.proj      = glGetUniformLocation(shaderExt.program, "proj");
+    shaderExt.posAttrib = glGetAttribLocation(shaderExt.program, "pos");
+    shaderExt.texAttrib = glGetAttribLocation(shaderExt.program, "texcoord");
+    shaderExt.tex       = glGetUniformLocation(shaderExt.program, "tex");
+    shaderExt.createVao();
 }
 
-SP<CDRMRenderer> CDRMRenderer::attempt(SP<CBackend> backend_, int drmFD, bool 
GLES2) {
+SP<CDRMRenderer> CDRMRenderer::attempt(SP<CBackend> backend_, int drmFD) {
     SP<CDRMRenderer> renderer = SP<CDRMRenderer>(new CDRMRenderer());
     renderer->drmFD           = drmFD;
     renderer->backend         = backend_;
@@ -526,7 +589,7 @@
         return nullptr;
     }
 
-    renderer->initContext(GLES2);
+    renderer->initContext();
     if (renderer->egl.context == nullptr || renderer->egl.context == 
EGL_NO_CONTEXT)
         return nullptr;
 
@@ -535,7 +598,7 @@
     return renderer;
 }
 
-SP<CDRMRenderer> CDRMRenderer::attempt(SP<CBackend> backend_, 
Hyprutils::Memory::CSharedPointer<CGBMAllocator> allocator_, bool GLES2) {
+SP<CDRMRenderer> CDRMRenderer::attempt(SP<CBackend> backend_, 
Hyprutils::Memory::CSharedPointer<CGBMAllocator> allocator_) {
     SP<CDRMRenderer> renderer = SP<CDRMRenderer>(new CDRMRenderer());
     renderer->drmFD           = allocator_->drmFD();
     renderer->backend         = backend_;
@@ -562,7 +625,7 @@
         return nullptr;
     }
 
-    renderer->initContext(GLES2);
+    renderer->initContext();
     if (renderer->egl.context == nullptr || renderer->egl.context == 
EGL_NO_CONTEXT)
         return nullptr;
 
@@ -660,10 +723,10 @@
     return image;
 }
 
-SGLTex CDRMRenderer::glTex(Hyprutils::Memory::CSharedPointer<IBuffer> buffa) {
-    SGLTex     tex;
+CGLTex CDRMRenderer::glTex(Hyprutils::Memory::CSharedPointer<IBuffer> buffa) {
+    CGLTex      tex;
 
-    const auto dma = buffa->dmabuf();
+    const auto& dma = buffa->dmabuf();
 
     tex.image = createEGLImage(dma);
     if (tex.image == EGL_NO_IMAGE_KHR) {
@@ -685,11 +748,11 @@
 
     GLCALL(glGenTextures(1, &tex.texid));
 
-    GLCALL(glBindTexture(tex.target, tex.texid));
-    GLCALL(glTexParameteri(tex.target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
-    GLCALL(glTexParameteri(tex.target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
+    GLCALL(tex.bind());
+    GLCALL(tex.setTexParameter(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
+    GLCALL(tex.setTexParameter(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
     GLCALL(proc.glEGLImageTargetTexture2DOES(tex.target, tex.image));
-    GLCALL(glBindTexture(tex.target, 0));
+    GLCALL(tex.unbind());
 
     return tex;
 }
@@ -700,11 +763,11 @@
     CEglContextGuard eglContext(*this);
     auto             att = 
buf->attachments.get<CDRMRendererBufferAttachment>();
     if (!att) {
-        att = makeShared<CDRMRendererBufferAttachment>(self, buf, nullptr, 0, 
0, SGLTex{}, std::vector<uint8_t>());
+        att = makeShared<CDRMRendererBufferAttachment>(self, buf, nullptr, 0, 
0, CGLTex{}, std::vector<uint8_t>());
         buf->attachments.add(att);
     }
 
-    auto dma = buf->dmabuf();
+    const auto& dma = buf->dmabuf();
     if (!att->eglImage) {
         att->eglImage = createEGLImage(dma);
         if (att->eglImage == EGL_NO_IMAGE_KHR) {
@@ -733,26 +796,19 @@
     GLCALL(glBindFramebuffer(GL_FRAMEBUFFER, 0));
 }
 
-inline const float fullVerts[] = {
-    1, 0, // top right
-    0, 0, // top left
-    1, 1, // bottom right
-    0, 1, // bottom left
-};
-
 void CDRMRenderer::waitOnSync(int fd) {
     TRACE(backend->log(AQ_LOG_TRACE, std::format("EGL (waitOnSync): attempting 
to wait on fd {}", fd)));
 
-    std::vector<EGLint> attribs;
-    int                 dupFd = fcntl(fd, F_DUPFD_CLOEXEC, 0);
+    std::array<EGLint, 3> attribs;
+    int                   dupFd = fcntl(fd, F_DUPFD_CLOEXEC, 0);
     if (dupFd < 0) {
         backend->log(AQ_LOG_TRACE, "EGL (waitOnSync): failed to dup fd for 
wait");
         return;
     }
 
-    attribs.push_back(EGL_SYNC_NATIVE_FENCE_FD_ANDROID);
-    attribs.push_back(dupFd);
-    attribs.push_back(EGL_NONE);
+    attribs[0] = EGL_SYNC_NATIVE_FENCE_FD_ANDROID;
+    attribs[1] = dupFd;
+    attribs[2] = EGL_NONE;
 
     EGLSyncKHR sync = proc.eglCreateSyncKHR(egl.display, 
EGL_SYNC_NATIVE_FENCE_ANDROID, attribs.data());
     if (sync == EGL_NO_SYNC_KHR) {
@@ -819,7 +875,7 @@
 
 void CDRMRenderer::clearBuffer(IBuffer* buf) {
     CEglContextGuard eglContext(*this);
-    auto             dmabuf = buf->dmabuf();
+    const auto&      dmabuf = buf->dmabuf();
     GLuint           rboID = 0, fboID = 0;
 
     if (!dmabuf.success) {
@@ -850,8 +906,6 @@
     glClearColor(0.F, 0.F, 0.F, 1.F);
     glClear(GL_COLOR_BUFFER_BIT);
 
-    glFlush();
-
     GLCALL(glBindFramebuffer(GL_FRAMEBUFFER, 0));
     GLCALL(glBindRenderbuffer(GL_RENDERBUFFER, 0));
 
@@ -868,7 +922,7 @@
         return {};
     }
 
-    if (waitFD >= 0) {
+    if (waitFD >= 0 && !CFileDescriptor::isReadable(waitFD)) {
         // wait on a provided explicit fence
         waitOnSync(waitFD);
     }
@@ -878,8 +932,8 @@
     // both from and to have the same AQ_ATTACHMENT_DRM_RENDERER_DATA.
     // Those buffers always come from different swapchains, so it's OK.
 
-    SGLTex             fromTex;
-    auto               fromDma = from->dmabuf();
+    WP<CGLTex>         fromTex;
+    const auto&        fromDma = from->dmabuf();
     std::span<uint8_t> intermediateBuf;
     {
         auto attachment = 
from->attachments.get<CDRMRendererBufferAttachment>();
@@ -889,21 +943,22 @@
             intermediateBuf = attachment->intermediateBuf;
         }
 
-        if (!fromTex.image && intermediateBuf.empty()) {
+        if ((!fromTex || !fromTex->image) && intermediateBuf.empty()) {
             backend->log(AQ_LOG_DEBUG, "EGL (blit): No attachment in from, 
creating a new image");
-            fromTex = glTex(from);
 
-            attachment = makeShared<CDRMRendererBufferAttachment>(self, from, 
nullptr, 0, 0, fromTex, std::vector<uint8_t>());
+            attachment = makeShared<CDRMRendererBufferAttachment>(self, from, 
nullptr, 0, 0, glTex(from), std::vector<uint8_t>());
             from->attachments.add(attachment);
 
-            if (!fromTex.image && primaryRenderer) {
+            if (!attachment->tex->image && primaryRenderer) {
                 backend->log(AQ_LOG_DEBUG, "EGL (blit): Failed to create image 
from source buffer directly, allocating intermediate buffer");
                 static_assert(PIXEL_BUFFER_FORMAT == GL_RGBA); // If the pixel 
buffer format changes, the below size calculation probably needs to as well.
                 attachment->intermediateBuf.resize(fromDma.size.x * 
fromDma.size.y * 4);
-                intermediateBuf = attachment->intermediateBuf;
-                fromTex.target  = GL_TEXTURE_2D;
-                GLCALL(glGenTextures(1, &fromTex.texid));
+                intermediateBuf         = attachment->intermediateBuf;
+                attachment->tex->target = GL_TEXTURE_2D;
+                GLCALL(glGenTextures(1, &attachment->tex->texid));
             }
+
+            fromTex = attachment->tex;
         }
 
         if (!intermediateBuf.empty() && primaryRenderer) {
@@ -913,15 +968,15 @@
     }
 
     TRACE(backend->log(AQ_LOG_TRACE,
-                       std::format("EGL (blit): fromTex id {}, image 0x{:x}, 
target {}", fromTex.texid, (uintptr_t)fromTex.image,
-                                   fromTex.target == GL_TEXTURE_2D ? 
"GL_TEXTURE_2D" : "GL_TEXTURE_EXTERNAL_OES")));
+                       std::format("EGL (blit): fromTex id {}, image 0x{:x}, 
target {}", fromTex->texid, (uintptr_t)fromTex->image,
+                                   fromTex->target == GL_TEXTURE_2D ? 
"GL_TEXTURE_2D" : "GL_TEXTURE_EXTERNAL_OES")));
 
     // then, get a rbo from our to buffer
     // if it has an attachment, use that
 
     EGLImageKHR rboImage = nullptr;
     GLuint      rboID = 0, fboID = 0;
-    auto        toDma = to->dmabuf();
+    const auto& toDma = to->dmabuf();
 
     if (!verifyDestinationDMABUF(toDma)) {
         backend->log(AQ_LOG_ERROR, "EGL (blit): failed to blit: destination 
dmabuf unsupported");
@@ -960,12 +1015,10 @@
                 return {};
             }
 
-            to->attachments.add(makeShared<CDRMRendererBufferAttachment>(self, 
to, rboImage, fboID, rboID, SGLTex{}, std::vector<uint8_t>()));
+            to->attachments.add(makeShared<CDRMRendererBufferAttachment>(self, 
to, rboImage, fboID, rboID, CGLTex{}, std::vector<uint8_t>()));
         }
     }
 
-    glFlush();
-
     TRACE(backend->log(AQ_LOG_TRACE, std::format("EGL (blit): rboImage 
0x{:x}", (uintptr_t)rboImage)));
 
     GLCALL(glBindRenderbuffer(GL_RENDERBUFFER, rboID));
@@ -986,7 +1039,7 @@
     float monitorProj[9];
     matrixIdentity(base);
 
-    auto& SHADER = fromTex.target == GL_TEXTURE_2D ? gl.shader : gl.shaderExt;
+    auto& SHADER = fromTex->target == GL_TEXTURE_2D ? shader : shaderExt;
 
     // KMS uses flipped y, we have to do FLIPPED_180
     matrixTranslate(base, toDma.size.x / 2.0, toDma.size.y / 2.0);
@@ -1000,18 +1053,21 @@
     float glMtx[9];
     matrixMultiply(glMtx, monitorProj, mtx);
 
-    GLCALL(glViewport(0, 0, toDma.size.x, toDma.size.y));
+    static Vector2D lastViewportSize = {-1, -1};
+    if (lastViewportSize != toDma.size) {
+        GLCALL(glViewport(0, 0, toDma.size.x, toDma.size.y));
+        lastViewportSize = toDma.size;
+    }
 
     GLCALL(glActiveTexture(GL_TEXTURE0));
-    GLCALL(glBindTexture(fromTex.target, fromTex.texid));
-
-    GLCALL(glTexParameteri(fromTex.target, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
-    GLCALL(glTexParameteri(fromTex.target, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
+    GLCALL(fromTex->bind());
+    GLCALL(fromTex->setTexParameter(GL_TEXTURE_MAG_FILTER, GL_NEAREST));
+    GLCALL(fromTex->setTexParameter(GL_TEXTURE_MIN_FILTER, GL_NEAREST));
 
     if (!intermediateBuf.empty())
-        GLCALL(glTexImage2D(fromTex.target, 0, PIXEL_BUFFER_FORMAT, 
fromDma.size.x, fromDma.size.y, 0, PIXEL_BUFFER_FORMAT, GL_UNSIGNED_BYTE, 
intermediateBuf.data()));
+        GLCALL(glTexImage2D(fromTex->target, 0, PIXEL_BUFFER_FORMAT, 
fromDma.size.x, fromDma.size.y, 0, PIXEL_BUFFER_FORMAT, GL_UNSIGNED_BYTE, 
intermediateBuf.data()));
 
-    GLCALL(glUseProgram(SHADER.program));
+    useProgram(SHADER.program);
     GLCALL(glDisable(GL_BLEND));
     GLCALL(glDisable(GL_SCISSOR_TEST));
 
@@ -1019,22 +1075,12 @@
     GLCALL(glUniformMatrix3fv(SHADER.proj, 1, GL_FALSE, glMtx));
 
     GLCALL(glUniform1i(SHADER.tex, 0));
-
-    GLCALL(glVertexAttribPointer(SHADER.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, 
fullVerts));
-    GLCALL(glVertexAttribPointer(SHADER.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, 
fullVerts));
-
-    GLCALL(glEnableVertexAttribArray(SHADER.posAttrib));
-    GLCALL(glEnableVertexAttribArray(SHADER.texAttrib));
+    GLCALL(glBindVertexArray(SHADER.shaderVao));
 
     GLCALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
 
-    GLCALL(glDisableVertexAttribArray(SHADER.posAttrib));
-    GLCALL(glDisableVertexAttribArray(SHADER.texAttrib));
-
-    GLCALL(glBindTexture(fromTex.target, 0));
-
-    // rendered, cleanup
-    glFlush();
+    GLCALL(glBindVertexArray(0));
+    GLCALL(fromTex->unbind());
 
     // get an explicit sync fd for the secondary gpu.
     // when we pass buffers between gpus we should always use explicit sync,
@@ -1053,16 +1099,16 @@
     TRACE(backend->log(AQ_LOG_TRACE,
                        std::format("EGL (onBufferAttachmentDrop): dropping fbo 
{} rbo {} image 0x{:x}", attachment->fbo, attachment->rbo, 
(uintptr_t)attachment->eglImage)));
 
-    if (attachment->tex.texid)
-        GLCALL(glDeleteTextures(1, &attachment->tex.texid));
+    if (attachment->tex && attachment->tex->texid)
+        GLCALL(glDeleteTextures(1, &attachment->tex->texid));
     if (attachment->rbo)
         GLCALL(glDeleteRenderbuffers(1, &attachment->rbo));
     if (attachment->fbo)
         GLCALL(glDeleteFramebuffers(1, &attachment->fbo));
     if (attachment->eglImage)
         proc.eglDestroyImageKHR(egl.display, attachment->eglImage);
-    if (attachment->tex.image)
-        proc.eglDestroyImageKHR(egl.display, attachment->tex.image);
+    if (attachment->tex && attachment->tex->image)
+        proc.eglDestroyImageKHR(egl.display, attachment->tex->image);
 }
 
 bool CDRMRenderer::verifyDestinationDMABUF(const SDMABUFAttrs& attrs) {
@@ -1085,8 +1131,43 @@
     return false;
 }
 
+constexpr std::optional<size_t> CGLTex::getCacheStateIndex(GLenum pname) {
+    switch (pname) {
+        case GL_TEXTURE_WRAP_S: return TEXTURE_PAR_WRAP_S;
+        case GL_TEXTURE_WRAP_T: return TEXTURE_PAR_WRAP_T;
+        case GL_TEXTURE_MAG_FILTER: return TEXTURE_PAR_MAG_FILTER;
+        case GL_TEXTURE_MIN_FILTER: return TEXTURE_PAR_MIN_FILTER;
+        default: return std::nullopt;
+    }
+}
+
+void CGLTex::bind() {
+    glBindTexture(target, texid);
+}
+
+void CGLTex::unbind() {
+    glBindTexture(target, 0);
+}
+
+void CGLTex::setTexParameter(GLenum pname, GLint param) {
+    const auto cacheIndex = getCacheStateIndex(pname);
+
+    if (!cacheIndex) {
+        glTexParameteri(target, pname, param);
+        return;
+    }
+
+    const auto idx = cacheIndex.value();
+
+    if (m_cachedStates[idx] == param)
+        return;
+
+    m_cachedStates[idx] = param;
+    glTexParameteri(target, pname, param);
+}
+
 
CDRMRendererBufferAttachment::CDRMRendererBufferAttachment(Hyprutils::Memory::CWeakPointer<CDRMRenderer>
 renderer_, Hyprutils::Memory::CSharedPointer<IBuffer> buffer,
-                                                           EGLImageKHR image, 
GLuint fbo_, GLuint rbo_, SGLTex tex_, std::vector<uint8_t> intermediateBuf_) :
-    eglImage(image), fbo(fbo_), rbo(rbo_), tex(tex_), 
intermediateBuf(intermediateBuf_), renderer(renderer_) {
-    bufferDestroy = buffer->events.destroy.registerListener([this](std::any d) 
{ renderer->onBufferAttachmentDrop(this); });
+                                                           EGLImageKHR image, 
GLuint fbo_, GLuint rbo_, CGLTex&& tex_, std::vector<uint8_t> intermediateBuf_) 
:
+    eglImage(image), fbo(fbo_), rbo(rbo_), 
tex(makeUnique<CGLTex>(std::move(tex_))), intermediateBuf(intermediateBuf_), 
renderer(renderer_) {
+    bufferDestroy = buffer->events.destroy.listen([this] { 
renderer->onBufferAttachmentDrop(this); });
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aquamarine-0.8.0/src/backend/drm/Renderer.hpp 
new/aquamarine-0.9.1/src/backend/drm/Renderer.hpp
--- old/aquamarine-0.8.0/src/backend/drm/Renderer.hpp   2025-03-16 
23:00:48.000000000 +0100
+++ new/aquamarine-0.9.1/src/backend/drm/Renderer.hpp   2025-07-07 
17:58:11.000000000 +0200
@@ -4,7 +4,9 @@
 #include "FormatUtils.hpp"
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
-#include <GLES2/gl2.h>
+#include <GLES3/gl3.h>
+#include <GLES3/gl3ext.h>
+#define __gl2_h_ // define guard for gl2ext.h
 #include <GLES2/gl2ext.h>
 #include <gbm.h>
 #include <optional>
@@ -16,23 +18,40 @@
 
     class CGBMAllocator;
 
-    struct SGLTex {
+    class CGLTex {
+      public:
+        CGLTex() = default;
+        void     bind();
+        void     unbind();
+        void     setTexParameter(GLenum pname, GLint param);
         EGLImage image  = nullptr;
         GLuint   texid  = 0;
         GLuint   target = GL_TEXTURE_2D;
+
+      private:
+        enum eTextureParam : uint8_t {
+            TEXTURE_PAR_WRAP_S = 0,
+            TEXTURE_PAR_WRAP_T,
+            TEXTURE_PAR_MAG_FILTER,
+            TEXTURE_PAR_MIN_FILTER,
+            TEXTURE_PAR_LAST,
+        };
+
+        inline constexpr std::optional<size_t>             
getCacheStateIndex(GLenum pname);
+        std::array<std::optional<GLint>, TEXTURE_PAR_LAST> m_cachedStates;
     };
 
     class CDRMRendererBufferAttachment : public IAttachment {
       public:
         
CDRMRendererBufferAttachment(Hyprutils::Memory::CWeakPointer<CDRMRenderer> 
renderer_, Hyprutils::Memory::CSharedPointer<IBuffer> buffer, EGLImageKHR 
image, GLuint fbo_,
-                                     GLuint rbo_, SGLTex tex, 
std::vector<uint8_t> intermediateBuf_);
+                                     GLuint rbo_, CGLTex&& tex, 
std::vector<uint8_t> intermediateBuf_);
         virtual ~CDRMRendererBufferAttachment() {
             ;
         }
 
         EGLImageKHR                                   eglImage = nullptr;
         GLuint                                        fbo = 0, rbo = 0;
-        SGLTex                                        tex;
+        Hyprutils::Memory::CUniquePointer<CGLTex>     tex;
         Hyprutils::Signal::CHyprSignalListener        bufferDestroy;
         std::vector<uint8_t>                          intermediateBuf;
 
@@ -66,9 +85,9 @@
       public:
         ~CDRMRenderer();
 
-        static Hyprutils::Memory::CSharedPointer<CDRMRenderer> 
attempt(Hyprutils::Memory::CSharedPointer<CBackend> backend_, int drmFD, bool 
GLES2 = true);
+        static Hyprutils::Memory::CSharedPointer<CDRMRenderer> 
attempt(Hyprutils::Memory::CSharedPointer<CBackend> backend_, int drmFD);
         static Hyprutils::Memory::CSharedPointer<CDRMRenderer> 
attempt(Hyprutils::Memory::CSharedPointer<CBackend>      backend_,
-                                                                       
Hyprutils::Memory::CSharedPointer<CGBMAllocator> allocator_, bool GLES2 = true);
+                                                                       
Hyprutils::Memory::CSharedPointer<CGBMAllocator> allocator_);
 
         int                                                    drmFD = -1;
 
@@ -84,12 +103,14 @@
 
         void onBufferAttachmentDrop(CDRMRendererBufferAttachment* attachment);
 
-        struct {
-            struct SShader {
-                GLuint program = 0;
-                GLint  proj = -1, tex = -1, posAttrib = -1, texAttrib = -1;
-            } shader, shaderExt;
-        } gl;
+        struct SShader {
+            ~SShader();
+            void   createVao();
+
+            GLuint program = 0;
+            GLint  proj = -1, tex = -1, posAttrib = -1, texAttrib = -1;
+            GLuint shaderVao = 0, shaderVboPos = 0, shaderVboUv = 0;
+        } shader, shaderExt;
 
         struct {
             PFNEGLGETPLATFORMDISPLAYEXTPROC               
eglGetPlatformDisplayEXT               = nullptr;
@@ -128,7 +149,7 @@
             int        lastBlitSyncFD = -1;
         } egl;
 
-        SGLTex                                        
glTex(Hyprutils::Memory::CSharedPointer<IBuffer> buf);
+        CGLTex                                        
glTex(Hyprutils::Memory::CSharedPointer<IBuffer> buf);
         void                                          
readBuffer(Hyprutils::Memory::CSharedPointer<IBuffer> buf, std::span<uint8_t> 
out);
 
         Hyprutils::Memory::CWeakPointer<CDRMRenderer> self;
@@ -144,11 +165,13 @@
 
         void                                                  loadEGLAPI();
         EGLDeviceEXT                                          
eglDeviceFromDRMFD(int drmFD);
-        void                                                  initContext(bool 
GLES2);
+        void                                                  initContext();
         void                                                  initResources();
         bool                                                  initDRMFormats();
         std::optional<std::vector<std::pair<uint64_t, bool>>> 
getModsForFormat(EGLint format);
         bool                                                  hasModifiers = 
false;
+        void                                                  
useProgram(GLuint prog);
+        GLuint                                                m_currentProgram 
= 0;
 
         Hyprutils::Memory::CWeakPointer<CBackend>             backend;
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aquamarine-0.8.0/src/backend/drm/impl/Atomic.cpp 
new/aquamarine-0.9.1/src/backend/drm/impl/Atomic.cpp
--- old/aquamarine-0.8.0/src/backend/drm/impl/Atomic.cpp        2025-03-16 
23:00:48.000000000 +0100
+++ new/aquamarine-0.9.1/src/backend/drm/impl/Atomic.cpp        2025-07-07 
17:58:11.000000000 +0200
@@ -5,6 +5,7 @@
 #include <xf86drm.h>
 #include <xf86drmMode.h>
 #include <sys/mman.h>
+#include <sstream>
 #include "Shared.hpp"
 #include "aquamarine/output/Output.hpp"
 
@@ -99,8 +100,19 @@
     TRACE(backend->log(AQ_LOG_TRACE, std::format("atomic addConnector values: 
CRTC {}, mode {}", enable ? connector->crtc->id : 0, data.atomic.modeBlob)));
 
     conn = connector;
+    if (enable) {
+        drmModeModeInfo* currentMode = connector->getCurrentMode();
+        bool             modeDiffers = true;
+        if (currentMode) {
+            modeDiffers = memcmp(currentMode, &data.modeInfo, 
sizeof(drmModeModeInfo)) != 0;
+            free(currentMode);
+        }
 
-    addConnectorModeset(connector, data);
+        if (modeDiffers)
+            addConnectorModeset(connector, data);
+    } else 
+        addConnectorModeset(connector, data);
+    
     addConnectorCursor(connector, data);
 
     add(connector->id, connector->props.crtc_id, enable ? connector->crtc->id 
: 0);
@@ -180,7 +192,7 @@
     const auto& STATE  = connector->output->state->state();
     const bool  enable = STATE.enabled && data.mainFB;
 
-    add(connector->crtc->id, connector->crtc->props.mode_id, 
data.atomic.modeBlob);
+    add(connector->crtc->id, connector->crtc->props.mode_id, enable ? 
data.atomic.modeBlob : 0);
     data.atomic.blobbed = true;
 
     if (!enable)
@@ -223,20 +235,20 @@
 
 bool Aquamarine::CDRMAtomicRequest::commit(uint32_t flagssss) {
     static auto flagsToStr = [](uint32_t flags) {
-        std::string result;
+        std::ostringstream result;
         if (flags & DRM_MODE_ATOMIC_ALLOW_MODESET)
-            result += "ATOMIC_ALLOW_MODESET ";
+            result << "ATOMIC_ALLOW_MODESET ";
         if (flags & DRM_MODE_ATOMIC_NONBLOCK)
-            result += "ATOMIC_NONBLOCK ";
+            result << "ATOMIC_NONBLOCK ";
         if (flags & DRM_MODE_ATOMIC_TEST_ONLY)
-            result += "ATOMIC_TEST_ONLY ";
+            result << "ATOMIC_TEST_ONLY ";
         if (flags & DRM_MODE_PAGE_FLIP_EVENT)
-            result += "PAGE_FLIP_EVENT ";
+            result << "PAGE_FLIP_EVENT ";
         if (flags & DRM_MODE_PAGE_FLIP_ASYNC)
-            result += "PAGE_FLIP_ASYNC ";
+            result << "PAGE_FLIP_ASYNC ";
         if (flags & (~DRM_MODE_ATOMIC_FLAGS))
-            result += " + invalid...";
-        return result;
+            result << " + invalid...";
+        return result.str();
     };
 
     if (failed) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aquamarine-0.8.0/tests/SimpleWindow.cpp 
new/aquamarine-0.9.1/tests/SimpleWindow.cpp
--- old/aquamarine-0.8.0/tests/SimpleWindow.cpp 2025-03-16 23:00:48.000000000 
+0100
+++ new/aquamarine-0.9.1/tests/SimpleWindow.cpp 2025-07-07 17:58:11.000000000 
+0200
@@ -60,29 +60,23 @@
 
     auto aqBackend = Aquamarine::CBackend::create(implementations, options);
 
-    newOutputListener = 
aqBackend->events.newOutput.registerListener([](std::any data) {
-        output = std::any_cast<SP<Aquamarine::IOutput>>(data);
+    newOutputListener = aqBackend->events.newOutput.listen([](const 
SP<Aquamarine::IOutput> newOutput) {
+        output = newOutput;
 
         std::cout << "[Client] Got a new output named " << output->name << 
"\n";
 
-        outputFrameListener = 
output->events.frame.registerListener([](std::any data) { onFrame(); });
-        outputStateListener = 
output->events.state.registerListener([](std::any data) { 
onState(std::any_cast<Aquamarine::IOutput::SStateEvent>(data)); });
+        outputFrameListener = output->events.frame.listen([] { onFrame(); });
+        outputStateListener = output->events.state.listen([](const 
Aquamarine::IOutput::SStateEvent& event) { onState(event); });
     });
 
-    newMouseListener = aqBackend->events.newPointer.registerListener([] 
(std::any pointer) {
-        auto p = std::any_cast<SP<Aquamarine::IPointer>>(pointer);
-        mouseMotionListener = p->events.warp.registerListener([] (std::any 
data) {
-            auto e = std::any_cast<Aquamarine::IPointer::SWarpEvent>(data);
-            std::cout << "[Client] Mouse warped to " << std::format("{}", 
e.absolute) << "\n";
-        });
+    newMouseListener = aqBackend->events.newPointer.listen([](const 
SP<Aquamarine::IPointer>& pointer) {
+        mouseMotionListener = pointer->events.warp.listen(
+            [](const Aquamarine::IPointer::SWarpEvent& event) { std::cout << 
"[Client] Mouse warped to " << std::format("{}", event.absolute) << "\n"; });
     });
 
-    newKeyboardListener = aqBackend->events.newKeyboard.registerListener([] 
(std::any keeb) {
-        auto k = std::any_cast<SP<Aquamarine::IKeyboard>>(keeb);
-        keyboardKeyListener = k->events.key.registerListener([] (std::any 
data) {
-            auto e = std::any_cast<Aquamarine::IKeyboard::SKeyEvent>(data);
-            std::cout << "[Client] Key " << std::format("{}", e.key) << " 
state: " << e.pressed << " \n";
-        });
+    newKeyboardListener = aqBackend->events.newKeyboard.listen([](const 
SP<Aquamarine::IKeyboard>& keyboard) {
+        keyboardKeyListener = keyboard->events.key.listen(
+            [](const Aquamarine::IKeyboard::SKeyEvent& event) { std::cout << 
"[Client] Key " << std::format("{}", event.key) << " state: " << event.pressed 
<< " \n"; });
     });
 
     if (!aqBackend || !aqBackend->start()) {
@@ -94,4 +88,4 @@
     // aqBackend->enterLoop();
 
     return 0;
-}
\ No newline at end of file
+}

++++++ aquamarine.obsinfo ++++++
--- /var/tmp/diff_new_pack.Dz6X00/_old  2025-07-17 17:19:59.558816040 +0200
+++ /var/tmp/diff_new_pack.Dz6X00/_new  2025-07-17 17:19:59.558816040 +0200
@@ -1,5 +1,5 @@
 name: aquamarine
-version: 0.8.0
-mtime: 1742162448
-commit: 1c8fa0bf04d706698311cf595e80bbd6d3697956
+version: 0.9.1
+mtime: 1751903891
+commit: 664b2766bc624a62901b241fbdb19d0d0e790f38
 

Reply via email to