Repository: hyprwm/Hyprland
Pull request #9481: feat(input): add flip_x and flip_y for touchpad
Author: login: ghost
Labels: name: core
name: config
name: managers
name: protocols
name: devices
Created: 2025-02-24T22:50:57Z | Merged: 2025-03-03T20:56:01Z

fixes #8795 

Linked issue #8795: Add transform variable to input:touchpad
### Description

The variable is present for input:touchdevice but not for input:touchpad, would it be possible to add it? I sometimes use my laptop like a book, and using the touchpad is a real pain.

Thanks
Linked issue comments: user: login: vaxerski
created_at: 2024-12-21T16:40:55Z
body: a matrix here doesn't make sense as IIRC touchpad is reported relative by the driver. We could add a flip_y and flip_x tho
author_association: MEMBER
user: login: ghost
created_at: 2025-02-24T22:29:37Z
body: i'm going to implement this, do we still want this tho?

> a matrix here doesn't make sense as IIRC touchpad is reported relative by the driver. We could add a flip_y and flip_x tho
author_association: NONE
user: login: aphelei
created_at: 2025-03-04T11:23:50Z
body: @nnyyxxxx 

I did 
```
hyprctl keyword input:touchpad:flip_x true
hyprctl keyword input:touchpad:flip_y true
```
but it changes nothing. Maybe that I misunderstood something ?

I noticed that my touchpad device (laptop and tablet) are listed under mouse and not under touch. Is that expected ? I currently have no mouse connected.


<details> <summary>hyprctl devices</summary>

```
aphe@aphe ~ $ hyprctl devices
mice:
    Mouse at 561e9f962d50:
        elan06fa:00-04f3:3140-mouse
            default speed: 0.00000
    Mouse at 561ea08dd3d0:
        elan06fa:00-04f3:3140-touchpad
            default speed: 0.00000
    Mouse at 561ea08ff780:
        keyd-virtual-pointer
            default speed: 0.00000
    Mouse at 561ea08c1280:
        wacom-intuos-pro-m-finger
            default speed: 0.00000


Keyboards:
    Keyboard at 561e9f95e180:
        power-button
            rules: r "", m "", l "be", v "", o ""
            active keymap: Belgian
            capsLock: no
            numLock: no
            main: no
    Keyboard at 561ea08fa580:
        video-bus
            rules: r "", m "", l "be", v "", o ""
            active keymap: Belgian
            capsLock: no
            numLock: no
            main: no
    Keyboard at 561ea0070d90:
        power-button-1
            rules: r "", m "", l "be", v "", o ""
            active keymap: Belgian
            capsLock: no
            numLock: no
            main: no
    Keyboard at 561e9f829e70:
        ideapad-extra-buttons
            rules: r "", m "", l "be", v "", o ""
            active keymap: Belgian
            capsLock: no
            numLock: no
            main: no
    Keyboard at 561e9f7f7c90:
        at-translated-set-2-keyboard
            rules: r "", m "", l "be", v "", o ""
            active keymap: Belgian
            capsLock: no
            numLock: no
            main: no
    Keyboard at 561e9f671250:
        keyd-virtual-keyboard
            rules: r "", m "", l "be", v "", o ""
            active keymap: Belgian
            capsLock: no
            numLock: no
            main: yes


Tablets:
    Tablet Pad at 561e9f72ac50 (belongs to 0 -> )
    Tablet at 561ea0811ac0:
        wacom-intuos-pro-m-pen
            size: 224x148mm


Touch:


Switches:
    Switch Device at 561ea098bc20:
        Lid Switch
```

</details>

Thank you as always :)
author_association: CONTRIBUTOR
user: login: ghost
created_at: 2025-03-04T11:33:30Z
body: simple logical error on my part that wasn't caught in code review:

if (!e.mouse && e.device)

If not mouse then do this, or that. not sure.
author_association: NONE
user: login: ghost
created_at: 2025-03-04T11:51:42Z
body: also one thing to note is that i couldnt test it because i dont have a touchpad / laptop

removing the !e.mouse check works on mouse too, do we really want this? or is there some other solution?
author_association: NONE
user: login: ghost
created_at: 2025-03-04T12:00:37Z
body: for now you can use this patch until it gets merged :)

https://patch-diff.githubusercontent.com/raw/hyprwm/Hyprland/pull/9529.diff

@soufhehe 


author_association: NONE
user: login: aphelei
created_at: 2025-03-04T14:44:36Z
body: > for now you can use this patch until it gets merged :)
> 
> https://patch-diff.githubusercontent.com/raw/hyprwm/Hyprland/pull/9529.diff
> 
> [@soufhehe](https://github.com/soufhehe)

This works and mouse is not inverted 

another thing : is that possible to change scroll axis ? Set it to x instead of y
author_association: CONTRIBUTOR
user: login: aphelei
created_at: 2025-03-04T15:03:47Z
body: wait this is not what I expected. I wanted to invert x and y, so when `hyprctl -q keyword monitor eDP-1,1920x1080,0x420,1,transform,1` is used the touchpad is still usable because the monitor is vertical.


author_association: CONTRIBUTOR
user: login: ghost
created_at: 2025-03-04T15:17:49Z
body: what? flip_x and flip_y do:

flip_x:

if you drag your finger left on the touchpad then the cursor will move right

flip_y:

if you drag your finger down on the touchpad then the cursor will move up


and vice versa
author_association: NONE
user: login: ghost
created_at: 2025-03-04T15:23:34Z
body: > another thing : is that possible to change scroll axis ? Set it to x instead of y

i dont know the wiki probably has something
author_association: NONE
user: login: aphelei
created_at: 2025-03-04T16:03:29Z
body: > what? flip_x and flip_y do:
> 
> flip_x:
> 
> if you drag your finger left on the touchpad then the cursor will move right
> 
> flip_y:
> 
> if you drag your finger down on the touchpad then the cursor will move up
> 
> and vice versa


yes your code works fine but it's not what I expected

![Image](https://github.com/user-attachments/assets/8971918f-5eaf-4720-b092-d732aec6615e)
author_association: CONTRIBUTOR
user: login: ghost
created_at: 2025-03-04T16:06:14Z
body: idk i dont want to read that image

someone else can probably implement that
author_association: NONE
user: login: ghost
created_at: 2025-03-04T16:06:38Z
body: way too confusing for my small brain
author_association: NONE
user: login: aphelei
created_at: 2025-03-04T17:39:02Z
body: no worries, I'll try to do it


author_association: CONTRIBUTOR

Diff:
diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp
index 73579af09c9..1cb40705afa 100644
--- a/src/config/ConfigDescriptions.hpp
+++ b/src/config/ConfigDescriptions.hpp
@@ -608,6 +608,18 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
         .type        = CONFIG_OPTION_BOOL,
         .data        = SConfigOptionDescription::SBoolData{false},
     },
+    SConfigOptionDescription{
+        .value       = "input:touchpad:flip_x",
+        .description = "Inverts the horizontal movement of the touchpad",
+        .type        = CONFIG_OPTION_BOOL,
+        .data        = SConfigOptionDescription::SBoolData{false},
+    },
+    SConfigOptionDescription{
+        .value       = "input:touchpad:flip_y",
+        .description = "Inverts the vertical movement of the touchpad",
+        .type        = CONFIG_OPTION_BOOL,
+        .data        = SConfigOptionDescription::SBoolData{false},
+    },
 
     /*
      * input:touchdevice:
diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp
index 2f57a37f19b..087c2757550 100644
--- a/src/config/ConfigManager.cpp
+++ b/src/config/ConfigManager.cpp
@@ -602,6 +602,8 @@ CConfigManager::CConfigManager() {
     registerConfigVar("input:touchpad:tap-and-drag", Hyprlang::INT{1});
     registerConfigVar("input:touchpad:drag_lock", Hyprlang::INT{0});
     registerConfigVar("input:touchpad:scroll_factor", {1.f});
+    registerConfigVar("input:touchpad:flip_x", Hyprlang::INT{0});
+    registerConfigVar("input:touchpad:flip_y", Hyprlang::INT{0});
     registerConfigVar("input:touchdevice:transform", Hyprlang::INT{0});
     registerConfigVar("input:touchdevice:output", {"[[Auto]]"});
     registerConfigVar("input:touchdevice:enabled", Hyprlang::INT{1});
@@ -730,6 +732,8 @@ CConfigManager::CConfigManager() {
     m_pConfig->addSpecialConfigValue("device", "relative_input", Hyprlang::INT{0});           // only for tablets
     m_pConfig->addSpecialConfigValue("device", "active_area_position", Hyprlang::VEC2{0, 0}); // only for tablets
     m_pConfig->addSpecialConfigValue("device", "active_area_size", Hyprlang::VEC2{0, 0});     // only for tablets
+    m_pConfig->addSpecialConfigValue("device", "flip_x", Hyprlang::INT{0});                   // only for touchpads
+    m_pConfig->addSpecialConfigValue("device", "flip_y", Hyprlang::INT{0});                   // only for touchpads
 
     // keywords
     m_pConfig->registerHandler(&::handleExec, "exec", {false});
diff --git a/src/devices/IPointer.hpp b/src/devices/IPointer.hpp
index ea9cb9f45f2..19d91c6c121 100644
--- a/src/devices/IPointer.hpp
+++ b/src/devices/IPointer.hpp
@@ -17,9 +17,10 @@ class IPointer : public IHID {
     virtual SP<Aquamarine::IPointer> aq()        = 0;
 
     struct SMotionEvent {
-        uint32_t timeMs = 0;
-        Vector2D delta, unaccel;
-        bool     mouse = false;
+        uint32_t     timeMs = 0;
+        Vector2D     delta, unaccel;
+        bool         mouse = false;
+        SP<IPointer> device;
     };
 
     struct SMotionAbsoluteEvent {
@@ -109,6 +110,8 @@ class IPointer : public IHID {
 
     bool         connected   = false; // means connected to the cursor
     std::string  boundOutput = "";
+    bool         flipX       = false; // decide to invert horizontal movement
+    bool         flipY       = false; // decide to invert vertical movement
 
     WP<IPointer> self;
 };
diff --git a/src/devices/Mouse.cpp b/src/devices/Mouse.cpp
index 41652ce4568..87f6d33ba9d 100644
--- a/src/devices/Mouse.cpp
+++ b/src/devices/Mouse.cpp
@@ -27,6 +27,7 @@ CMouse::CMouse(SP<Aquamarine::IPointer> mouse_) : mouse(mouse_) {
             .delta   = E.delta,
             .unaccel = E.unaccel,
             .mouse   = true,
+            .device  = self.lock(),
         });
     });
 
diff --git a/src/devices/VirtualPointer.cpp b/src/devices/VirtualPointer.cpp
index 7cfb06313de..e98acd04f61 100644
--- a/src/devices/VirtualPointer.cpp
+++ b/src/devices/VirtualPointer.cpp
@@ -19,7 +19,11 @@ CVirtualPointer::CVirtualPointer(SP<CVirtualPointerV1Resource> resource) : point
         events.destroy.emit();
     });
 
-    listeners.motion         = pointer->events.move.registerListener([this](std::any d) { pointerEvents.motion.emit(d); });
+    listeners.motion         = pointer->events.move.registerListener([this](std::any d) {
+        auto E   = std::any_cast<SMotionEvent>(d);
+        E.device = self.lock();
+        pointerEvents.motion.emit(E);
+    });
     listeners.motionAbsolute = pointer->events.warp.registerListener([this](std::any d) {
         // we need to unpack the event and add our device here because it's required to calculate the position correctly
         auto E   = std::any_cast<SMotionAbsoluteEvent>(d);
diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp
index 1d16f9151f4..f260d134085 100644
--- a/src/managers/input/InputManager.cpp
+++ b/src/managers/input/InputManager.cpp
@@ -90,14 +90,28 @@ CInputManager::~CInputManager() {
 void CInputManager::onMouseMoved(IPointer::SMotionEvent e) {
     static auto PNOACCEL = CConfigValue<Hyprlang::INT>("input:force_no_accel");
 
-    const auto  DELTA = *PNOACCEL == 1 ? e.unaccel : e.delta;
+    Vector2D    delta   = e.delta;
+    Vector2D    unaccel = e.unaccel;
+
+    if (!e.mouse && e.device) {
+        if (e.device->flipX) {
+            delta.x   = -delta.x;
+            unaccel.x = -unaccel.x;
+        }
+        if (e.device->flipY) {
+            delta.y   = -delta.y;
+            unaccel.y = -unaccel.y;
+        }
+    }
+
+    const auto DELTA = *PNOACCEL == 1 ? unaccel : delta;
 
     if (g_pSeatManager->isPointerFrameSkipped)
-        g_pPointerManager->storeMovement((uint64_t)e.timeMs, DELTA, e.unaccel);
+        g_pPointerManager->storeMovement((uint64_t)e.timeMs, DELTA, unaccel);
     else
-        g_pPointerManager->setStoredMovement((uint64_t)e.timeMs, DELTA, e.unaccel);
+        g_pPointerManager->setStoredMovement((uint64_t)e.timeMs, DELTA, unaccel);
 
-    PROTO::relativePointer->sendRelativeMotion((uint64_t)e.timeMs * 1000, DELTA, e.unaccel);
+    PROTO::relativePointer->sendRelativeMotion((uint64_t)e.timeMs * 1000, DELTA, unaccel);
 
     if (e.mouse)
         recheckMouseWarpOnMouseInput();
@@ -1180,6 +1194,9 @@ void CInputManager::setPointerConfigs() {
             const auto LIBINPUTSENS = std::clamp(g_pConfigManager->getDeviceFloat(devname, "sensitivity", "input:sensitivity"), -1.f, 1.f);
             libinput_device_config_accel_set_speed(LIBINPUTDEV, LIBINPUTSENS);
 
+            m->flipX = g_pConfigManager->getDeviceInt(devname, "flip_x", "input:touchpad:flip_x") != 0;
+            m->flipY = g_pConfigManager->getDeviceInt(devname, "flip_y", "input:touchpad:flip_y") != 0;
+
             const auto ACCELPROFILE = g_pConfigManager->getDeviceString(devname, "accel_profile", "input:accel_profile");
             const auto SCROLLPOINTS = g_pConfigManager->getDeviceString(devname, "scroll_points", "input:scroll_points");
 
diff --git a/src/protocols/VirtualPointer.cpp b/src/protocols/VirtualPointer.cpp
index 33641a7bb9f..8dc4bab6084 100644
--- a/src/protocols/VirtualPointer.cpp
+++ b/src/protocols/VirtualPointer.cpp
@@ -19,6 +19,7 @@ CVirtualPointerV1Resource::CVirtualPointerV1Resource(SP<CZwlrVirtualPointerV1> r
             .timeMs  = timeMs,
             .delta   = {wl_fixed_to_double(dx), wl_fixed_to_double(dy)},
             .unaccel = {wl_fixed_to_double(dx), wl_fixed_to_double(dy)},
+            .device  = nullptr,
         });
     });
 


Reviews:
user: login: vaxerski
body: missing handling for absolute coordinate space devices. (e.g. tablets)
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-02-25T14:42:22Z
user: login: vaxerski
state: DISMISSED
author_association: MEMBER
submitted_at: 2025-02-27T14:24:48Z
state: COMMENTED
author_association: NONE
submitted_at: 2025-02-27T20:02:41Z
state: COMMENTED
author_association: NONE
submitted_at: 2025-02-27T20:14:27Z
user: login: vaxerski
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-01T18:37:11Z
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-02T01:19:05Z
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-02T01:42:17Z
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-02T02:02:07Z
user: login: vaxerski
body: thanks!
state: APPROVED
author_association: MEMBER
submitted_at: 2025-03-03T20:55:51Z

Review comments:
diff_hunk: @@ -716,6 +718,8 @@ CConfigManager::CConfigManager() {
     m_pConfig->addSpecialConfigValue("device", "tap-to-click", Hyprlang::INT{1});
     m_pConfig->addSpecialConfigValue("device", "tap-and-drag", Hyprlang::INT{1});
     m_pConfig->addSpecialConfigValue("device", "drag_lock", Hyprlang::INT{0});
+    m_pConfig->addSpecialConfigValue("device", "flip_x", Hyprlang::INT{0});
+    m_pConfig->addSpecialConfigValue("device", "flip_y", Hyprlang::INT{0});
path: src/config/ConfigManager.cpp
user: login: vaxerski
body: don't add a variable to leave it unused
created_at: 2025-02-27T14:24:43Z
author_association: MEMBER
diff_hunk: @@ -716,6 +718,8 @@ CConfigManager::CConfigManager() {
     m_pConfig->addSpecialConfigValue("device", "tap-to-click", Hyprlang::INT{1});
     m_pConfig->addSpecialConfigValue("device", "tap-and-drag", Hyprlang::INT{1});
     m_pConfig->addSpecialConfigValue("device", "drag_lock", Hyprlang::INT{0});
+    m_pConfig->addSpecialConfigValue("device", "flip_x", Hyprlang::INT{0});
+    m_pConfig->addSpecialConfigValue("device", "flip_y", Hyprlang::INT{0});
path: src/config/ConfigManager.cpp
body: huh my bad i just saw that everything else had a sepcial config value and decided to do the same
created_at: 2025-02-27T20:02:41Z
author_association: NONE
diff_hunk: @@ -716,6 +718,8 @@ CConfigManager::CConfigManager() {
     m_pConfig->addSpecialConfigValue("device", "tap-to-click", Hyprlang::INT{1});
     m_pConfig->addSpecialConfigValue("device", "tap-and-drag", Hyprlang::INT{1});
     m_pConfig->addSpecialConfigValue("device", "drag_lock", Hyprlang::INT{0});
+    m_pConfig->addSpecialConfigValue("device", "flip_x", Hyprlang::INT{0});
+    m_pConfig->addSpecialConfigValue("device", "flip_y", Hyprlang::INT{0});
path: src/config/ConfigManager.cpp
body: [7e6fd4f](https://github.com/hyprwm/Hyprland/pull/9481/commits/7e6fd4f39ec2e3fa43794c464a2a21f6ac7304f5) done
created_at: 2025-02-27T20:14:27Z
author_association: NONE
diff_hunk: @@ -730,6 +732,8 @@ CConfigManager::CConfigManager() {
     m_pConfig->addSpecialConfigValue("device", "relative_input", Hyprlang::INT{0});           // only for tablets
     m_pConfig->addSpecialConfigValue("device", "active_area_position", Hyprlang::VEC2{0, 0}); // only for tablets
     m_pConfig->addSpecialConfigValue("device", "active_area_size", Hyprlang::VEC2{0, 0});     // only for tablets
+    m_pConfig->addSpecialConfigValue("device", "flip_x", Hyprlang::INT{0});                   // only for touchpads (sigma)
path: src/config/ConfigManager.cpp
user: login: vaxerski
body: wtf is a sigma?
created_at: 2025-03-01T18:35:07Z
author_association: MEMBER
diff_hunk: @@ -90,14 +90,39 @@ CInputManager::~CInputManager() {
 void CInputManager::onMouseMoved(IPointer::SMotionEvent e) {
     static auto PNOACCEL = CConfigValue<Hyprlang::INT>("input:force_no_accel");
 
-    const auto  DELTA = *PNOACCEL == 1 ? e.unaccel : e.delta;
+    Vector2D    delta   = e.delta;
+    Vector2D    unaccel = e.unaccel;
+
+    if (!e.mouse) {
+        SP<IPointer> activePointer = nullptr;
path: src/managers/input/InputManager.cpp
user: login: vaxerski
body: this is wrong, add a field to `SMotionEvent` that holds a SP to the device and pass it like that
created_at: 2025-03-01T18:36:20Z
author_association: MEMBER
diff_hunk: @@ -109,6 +109,8 @@ class IPointer : public IHID {
 
     bool         connected   = false; // means connected to the cursor
     std::string  boundOutput = "";
+    bool         flip_x      = false; // decide to invert horizontal movement
path: src/devices/IPointer.hpp
user: login: vaxerski
body: no snake
created_at: 2025-03-01T18:36:34Z
author_association: MEMBER
diff_hunk: @@ -109,6 +109,8 @@ class IPointer : public IHID {
 
     bool         connected   = false; // means connected to the cursor
     std::string  boundOutput = "";
+    bool         flip_x      = false; // decide to invert horizontal movement
path: src/devices/IPointer.hpp
body: oh shiz got too caigjt up with my own project
created_at: 2025-03-02T01:19:04Z
author_association: NONE
diff_hunk: @@ -90,14 +90,39 @@ CInputManager::~CInputManager() {
 void CInputManager::onMouseMoved(IPointer::SMotionEvent e) {
     static auto PNOACCEL = CConfigValue<Hyprlang::INT>("input:force_no_accel");
 
-    const auto  DELTA = *PNOACCEL == 1 ? e.unaccel : e.delta;
+    Vector2D    delta   = e.delta;
+    Vector2D    unaccel = e.unaccel;
+
+    if (!e.mouse) {
+        SP<IPointer> activePointer = nullptr;
path: src/managers/input/InputManager.cpp
body: [923e668](https://github.com/hyprwm/Hyprland/pull/9481/commits/923e6688ff4a30cb739c4dc74acf98081c258415)
created_at: 2025-03-02T01:42:17Z
author_association: NONE
diff_hunk: @@ -730,6 +732,8 @@ CConfigManager::CConfigManager() {
     m_pConfig->addSpecialConfigValue("device", "relative_input", Hyprlang::INT{0});           // only for tablets
     m_pConfig->addSpecialConfigValue("device", "active_area_position", Hyprlang::VEC2{0, 0}); // only for tablets
     m_pConfig->addSpecialConfigValue("device", "active_area_size", Hyprlang::VEC2{0, 0});     // only for tablets
+    m_pConfig->addSpecialConfigValue("device", "flip_x", Hyprlang::INT{0});                   // only for touchpads (sigma)
path: src/config/ConfigManager.cpp
body: Σ
created_at: 2025-03-02T02:02:07Z
author_association: NONE

PR comments:
user: login: ghost
created_at: 2025-02-24T22:58:11Z
body: https://github.com/hyprwm/hyprland-wiki/pull/984
author_association: NONE
user: login: ghost
created_at: 2025-02-25T16:34:29Z
body: > missing handling for absolute coordinate space devices. (e.g. tablets)

shouldn't that be a separate option?
author_association: NONE
user: login: ghost
created_at: 2025-02-25T17:31:34Z
body: isnt tablet a separate set of config values 
![image](https://github.com/user-attachments/assets/bbdf239f-9afb-499f-a78c-46d7e2884f5d)

author_association: NONE
user: login: vaxerski
created_at: 2025-02-27T14:24:15Z
body: oh, right, my bad, this is only for touchpad.
author_association: MEMBER
user: login: vaxerski
created_at: 2025-02-27T14:25:08Z
body: oops approved on accident. Anyways, the device: variable is unused, you haven't implemented it.
author_association: MEMBER
user: login: vaxerski
created_at: 2025-02-28T01:29:35Z
body: I thought you'd implement it. Either that, or you need to add to the wiki MR in the device config section that flip_x and y dont have a device cfg
author_association: MEMBER
user: login: ghost
created_at: 2025-02-28T01:37:19Z
body: > I thought you'd implement it. Either that, or you need to add to the wiki MR in the device config section that flip_x and y dont have a device cfg

i honestly really dont know anything about "it" do you want me to implement it?

ill have to do some reading though unfortunately
author_association: NONE
user: login: ghost
created_at: 2025-02-28T01:40:54Z
body: or should i just leave this as is, and do this:

> or you need to add to the wiki MR in the device config section that flip_x and y dont have a device cfg
author_association: NONE
user: login: vaxerski
created_at: 2025-02-28T01:41:34Z
body: device configs, check how they are done. You call a different fn in the reload (device) configs fn and store the result in the pointer class
author_association: MEMBER
user: login: ghost
created_at: 2025-02-28T01:42:06Z
body: okay, ill draft this for now then. currently working on somethin else rn
author_association: NONE
user: login: ghost
created_at: 2025-03-01T10:27:42Z
body: check [e242ee6](https://github.com/hyprwm/Hyprland/pull/9481/commits/e242ee60b11e1820c89065cd687c29d332f2b0e7)
author_association: NONE
user: login: ghost
created_at: 2025-03-01T10:34:40Z
body: i did not do the standard approach because i am not sure that libinput has support for flipping axes
author_association: NONE
user: login: ghost
created_at: 2025-03-01T10:39:08Z
body: meh. i dont like this 
author_association: NONE
user: login: ghost
created_at: 2025-03-01T10:47:03Z
body: ok i believe i followed ur instructions correctly check [3f459a0](https://github.com/hyprwm/Hyprland/pull/9481/commits/3f459a0849dc92a32953090abed5de66953c6667)
author_association: NONE