Skip to content

Instantly share code, notes, and snippets.

@rhoot

rhoot/sway.patch Secret

Last active September 4, 2023 16:58
Show Gist options
  • Save rhoot/dcead8b195054387c067919fef499c5c to your computer and use it in GitHub Desktop.
Save rhoot/dcead8b195054387c067919fef499c5c to your computer and use it in GitHub Desktop.
Sway VRR cursor
diff --git a/include/sway/output.h b/include/sway/output.h
index 50d90d25..6e9f7aef 100644
--- a/include/sway/output.h
+++ b/include/sway/output.h
@@ -8,6 +8,7 @@
#include "config.h"
#include "sway/tree/node.h"
#include "sway/tree/view.h"
+#include <pixman.h>
struct sway_server;
struct sway_container;
@@ -58,6 +59,7 @@ struct sway_output {
int max_render_time; // In milliseconds
struct wl_event_source *repaint_timer;
bool gamma_lut_changed;
+ pixman_region32_t cursor_damage;
};
struct sway_output_non_desktop {
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index 476bfd25..759e9cab 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -571,6 +571,9 @@ static int output_repaint_timer_handler(void *data) {
return 0;
}
+ wlr_damage_ring_add(&output->damage_ring, &output->cursor_damage);
+ pixman_region32_clear(&output->cursor_damage);
+
struct sway_workspace *workspace = output->current.active_workspace;
if (workspace == NULL) {
return 0;
@@ -601,7 +604,17 @@ static int output_repaint_timer_handler(void *data) {
pending.committed |= WLR_OUTPUT_STATE_DAMAGE;
get_frame_damage(output, &pending.damage);
- if (fullscreen_con && fullscreen_con->view && !debug.noscanout) {
+ const bool adaptive_sync = output->wlr_output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED;
+ const bool has_fullscreen_view = fullscreen_con && fullscreen_con->view;
+ const bool no_cursor_move_frames = output->wlr_output->no_frames_for_cursor_moves;
+
+ if (has_fullscreen_view && adaptive_sync && !no_cursor_move_frames) {
+ output->wlr_output->no_frames_for_cursor_moves = true;
+ } else if ((!has_fullscreen_view || !adaptive_sync) && no_cursor_move_frames) {
+ output->wlr_output->no_frames_for_cursor_moves = false;
+ }
+
+ if (has_fullscreen_view && !debug.noscanout) {
// Try to scan-out the fullscreen view
static bool last_scanned_out = false;
bool scanned_out =
@@ -688,9 +701,19 @@ static void handle_damage(struct wl_listener *listener, void *user_data) {
struct sway_output *output =
wl_container_of(listener, output, damage);
struct wlr_output_event_damage *event = user_data;
- if (wlr_damage_ring_add(&output->damage_ring, event->damage)) {
- wlr_output_schedule_frame(output->wlr_output);
+
+ pixman_region32_t clipped;
+ pixman_region32_init(&clipped);
+ pixman_region32_intersect_rect(&clipped, event->damage,
+ 0, 0, output->damage_ring.width, output->damage_ring.height);
+ bool intersects = pixman_region32_not_empty(&clipped);
+ if (intersects) {
+ pixman_region32_union(&output->cursor_damage, &output->cursor_damage, &clipped);
+ if (!output->wlr_output->no_frames_for_cursor_moves) {
+ wlr_output_schedule_frame(output->wlr_output);
+ }
}
+ pixman_region32_fini(&clipped);
}
static void handle_frame(struct wl_listener *listener, void *user_data) {
diff --git a/sway/tree/output.c b/sway/tree/output.c
index eccab2f7..626d81a3 100644
--- a/sway/tree/output.c
+++ b/sway/tree/output.c
@@ -94,6 +94,7 @@ struct sway_output *output_create(struct wlr_output *wlr_output) {
wlr_output->data = output;
output->detected_subpixel = wlr_output->subpixel;
output->scale_filter = SCALE_FILTER_NEAREST;
+ pixman_region32_init(&output->cursor_damage);
wl_signal_init(&output->events.disable);
@@ -241,6 +242,7 @@ void output_destroy(struct sway_output *output) {
list_free(output->workspaces);
list_free(output->current.workspaces);
wl_event_source_remove(output->repaint_timer);
+ pixman_region32_fini(&output->cursor_damage);
free(output);
}
diff --git a/backend/drm/drm.c b/backend/drm/drm.c
index a4853ffa..9ede73bf 100644
--- a/backend/drm/drm.c
+++ b/backend/drm/drm.c
@@ -976,7 +976,8 @@ static bool drm_connector_set_cursor(struct wlr_output *output,
conn->cursor_height = buffer->height;
}
- wlr_output_update_needs_frame(output);
+ if (!output->no_frames_for_cursor_moves)
+ wlr_output_update_needs_frame(output);
return true;
}
@@ -1006,7 +1007,8 @@ static bool drm_connector_move_cursor(struct wlr_output *output,
conn->cursor_x = box.x;
conn->cursor_y = box.y;
- wlr_output_update_needs_frame(output);
+ if (!output->no_frames_for_cursor_moves)
+ wlr_output_update_needs_frame(output);
return true;
}
diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h
index aa3d7a18..8e321dae 100644
--- a/include/wlr/types/wlr_output.h
+++ b/include/wlr/types/wlr_output.h
@@ -148,6 +148,7 @@ struct wlr_output {
// damage for cursors and fullscreen surface, in output-local coordinates
bool frame_pending;
float transform_matrix[9];
+ bool no_frames_for_cursor_moves;
// true for example with VR headsets
bool non_desktop;
@rhoot
Copy link
Author

rhoot commented Aug 25, 2023

@GrabbenD I generally pass -C to makepkg just to make sure it doesn't have some weird state from a previous build, since it clones a git repo. The packages are fast to build anyway.

The way I have it set up is:

  1. Download the PKGBUILDs for sway-git and wlroots-git with yay:

    yay -G wlroots-git sway-git
  2. Copy wlroots.patch into the wlroots-git dir that yay created, and sway.patch into the sway-git dir it created.

  3. Update wlroots-git/PKGBUILD to make it apply the patch:

    Click for diff
    diff --git a/PKGBUILD b/PKGBUILD
    index 78db8bc..0e7ed53 100644
    --- a/PKGBUILD
    +++ b/PKGBUILD
    @@ -32,8 +32,8 @@ makedepends=(
            vulkan-headers
            wayland-protocols
            xorgproto)
    -source=("${pkgname}::git+${url}.git")
    -md5sums=('SKIP')
    +source=("${pkgname}::git+${url}.git" wlroots.patch)
    +md5sums=('SKIP' SKIP)
     
     _builddir="build"
     _builddir_pkgver="build-pkgver"
    @@ -48,6 +48,8 @@ _meson_setup () {
     
     prepare () {
            _meson_setup "${_builddir_pkgver}"
    +       cd "$pkgname"
    +       patch -p1 < ../wlroots.patch
     }
     
     pkgver () {
  4. Update sway-git/PKGBUILD to make it apply the patch:

    Click for diff
    diff --git a/PKGBUILD b/PKGBUILD
    index b9c83cb..682099c 100644
    --- a/PKGBUILD
    +++ b/PKGBUILD
    @@ -40,9 +40,11 @@ backup=(etc/sway/config)
     arch=("i686" "x86_64")
     url="https://swaywm.org"
     source=("${pkgname%-*}::git+https://github.com/swaywm/sway.git"
    -       50-systemd-user.conf)
    +       50-systemd-user.conf
    +       sway.patch)
     sha512sums=('SKIP'
    -            'c2b7d808f4231f318e03789015624fd4cf32b81434b15406570b4e144c0defc54e216d881447e6fd9fc18d7da608cccb61c32e0e1fab2f1fe2750acf812d3137')
    +            'c2b7d808f4231f318e03789015624fd4cf32b81434b15406570b4e144c0defc54e216d881447e6fd9fc18d7da608cccb61c32e0e1fab2f1fe2750acf812d3137'
    +            'SKIP')
     provides=("sway")
     conflicts=("sway")
     options=(debug)
    @@ -53,6 +55,11 @@ pkgver() {
            printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
     }
     
    +prepare() {
    +       cd "$_pkgname"
    +       patch -p1 < ../sway.patch
    +}
    +
     build() {
            arch-meson \
                    -Dsd-bus-provider=libsystemd \
  5. Build and install both packages:

    cd wlroots-git
    makepkg -Csfi
    cd ../sway-git
    makepkg -Csfi

This compiled just fine with latest -git!
If I don't include patch --directory=wlroots -p1 < ../wlroots.patch in sway-git-wlroots-git/PKGBUILD I get the error from my comment above which confirms that Sway was never using my locally compiled Wlroots from earlier attempts?

I can't really say whether you were using your locally built one or not before honestly. But it makes sense that you'd need to patch wlroots too if you've bundled wlroots into the same package as sway at least. 🤷

Those build errors are entirely unrelated to the patch though. It doesn't modify anything that could cause those errors. It's possible the hashes you picked for wlroots and sway are just incompatible? If you switch to using the sway-git and wlroots-git packages instead they will clone the latest master branch each time you build it, so you never have to update the hashes. Though atm the sway-git package is broken in AUR, so you'd also have to fix that too:

Click to expand
diff --git a/PKGBUILD b/PKGBUILD
index b9c83cb..682099c 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -68,9 +75,9 @@ package() {
 
         cd "$_pkgname"
        install -Dm644 "LICENSE" "$pkgdir/usr/share/licenses/$pkgname/LICENSE"
-       for util in autoname-workspaces.py inactive-windows-transparency.py grimshot; do
-               install -Dm755 "contrib/$util" -t "$pkgdir/usr/share/$pkgname/scripts"
-       done
 }
 
 post_upgrade() {

Edit: Actually the first set of errors are related I guess. They imply that you weren't building against the right version of wlroots yeah. If you weren't getting those errors before you must have used the correct version of it before too.

@GrabbenD
Copy link

Thank you 🙏

@czak
Copy link

czak commented Sep 4, 2023

The PKGBUILD for sway-git has had several updates in the past few days.

Changes to get this to build:

  • No need to remove the autoname-workspaces.py stuff
  • Use $pkgname instead of $_pkgname in prepare

@GrabbenD
Copy link

GrabbenD commented Sep 4, 2023

Is this gist still relevant?
There's a new approach to this issue here: swaywm/sway#6832 (comment)

Either way this gist can be kept for archival purposes 🙂

@czak
Copy link

czak commented Sep 4, 2023

Oh thanks for the tip! I was directed to these patches somewhere and wasn't aware there's other work going on.

@GrabbenD
Copy link

GrabbenD commented Sep 4, 2023

Glad to help
Also make sure to try it without direct scanout, made a huge difference for me
swaywm/sway#7714 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment