Locking mouse to monitor for linux dual monitor gaming: when gamescope isn't an option

on blog at

I wanted to play Age of Empires 2: Definite Edition on my Debian 11 machine using amdgpu with an RX 580 8GB gpu and dual monitors. It works fine on steam but when I move my mouse to the right side of that monitor's screen to 'push' the map around in the RTS game the mouse instead slides off the game monitor and onto my second monitor. All of the online comments said to use gamescope like 'gamescope --force-grab-cursor -f -- %command% ' for this.

But unfortunately gamescope is literally an entire wayland environment that requires a dozen bleeding edge deps with tens of thousands of lines of code. For me it looked infeasible and I quickly gave up after my meson was too old. But mostly because of the hundreds of MB of source code for all the deps I knew would never compile.

superkuh@janus:~/app_installs/gamescope$ meson setup build/
The Meson build system
Version: 0.56.2
Source dir: /home/superkuh/app_installs/gamescope
Build dir: /home/superkuh/app_installs/gamescope/build
Build type: native build

meson.build:1:0: ERROR: Meson version is 0.56.2 but project requires >=0.58.0

So I looked for other, less involved options. Brute forcing it with xdotool was my first thought. Another I found was https://github.com/QQuark/WGrab which is very simple but it involves manually setting the window span with the mouse each time. So I went with xdotool. This 24 line perl script calling it completely solved my problem.

#!/usr/bin/perl
use strict;
use warnings;

my $X_MIN = 0;
my $X_MAX = 1919; # 1920px
my $Y_MIN = 0;
my $Y_MAX = 1079; # 1080px

while (1) {
    my $loc = `xdotool getmouselocation`;
    my ($x) = $loc =~ /x:(\d+)/;
    my ($y) = $loc =~ /y:(\d+)/;

    my $nx = $x < $X_MIN ? $X_MIN : ($x > $X_MAX ? $X_MAX : $x);
    my $ny = $y < $Y_MIN ? $Y_MIN : ($y > $Y_MAX ? $Y_MAX : $y);

    if ($nx != $x || $ny != $y) {
        system("xdotool mousemove $nx $ny");
    }

    select(undef, undef, undef, 0.02);  # 20ms polling
}

[comment on this post] Append "/@say/your message here" to the URL in the location bar and hit enter.

[webmention/pingback] Did you respond to this post? What's the URL?