Browse Source

MouseSettings: Add option to reverse buttons

Add option to reverse primary and secondary buttons in Mouse Settings.
- WindowServer.ini: add default entry
- switch-mouse-buttons.png: new icon for settings entry
- Mouse.gml/MouseWidget.*: new settings dialog
- ClientConnection/WindowManager/Server: window message for settings
- EventLoop.cpp: swap buttons 1 and 2 if settings are on
Andrew Pardoe 3 years ago
parent
commit
0e68550c05

+ 1 - 0
Base/etc/WindowServer.ini

@@ -20,6 +20,7 @@ Name=Default
 AccelerationFactor=1.0
 ScrollStepSize=4
 CursorTheme=Default
+ButtonsSwitched=0
 
 [Graphics]
 OverlayRectShadow=/res/graphics/overlay-rect-shadow.png

BIN
Base/res/graphics/switch-mouse-buttons.png


+ 35 - 0
Userland/Applications/MouseSettings/Mouse.gml

@@ -158,4 +158,39 @@
             }
         }
     }
+
+    @GUI::GroupBox {
+        title: "Button configuration"
+        fixed_height: 60
+
+        layout: @GUI::VerticalBoxLayout {
+            margins: [16, 8, 8]
+            spacing: 2
+        }
+
+        @GUI::Widget {
+            layout: @GUI::HorizontalBoxLayout {
+                spacing: 16
+            }
+
+            @GUI::Label {
+                fixed_width: 32
+                fixed_height: 32
+                name: "switch_buttons_image_label"
+            }
+
+            @GUI::Label {
+                text: "Switch primary and secondary buttons"
+                fixed_width: 201
+                text_alignment: "CenterLeft"
+                name: "switch_buttons_label"
+            }
+
+            @GUI::CheckBox {
+                name: "switch_buttons_input"
+                fixed_width: 14
+
+            }
+        }
+    }    
 }

+ 6 - 0
Userland/Applications/MouseSettings/MouseWidget.cpp

@@ -51,6 +51,10 @@ MouseWidget::MouseWidget()
         m_double_click_speed_label->set_text(String::formatted("{} ms", speed));
     };
     m_double_click_speed_slider->set_value(GUI::WindowServerConnection::the().get_double_click_speed());
+    m_switch_buttons_checkbox = *find_descendant_of_type_named<GUI::CheckBox>("switch_buttons_input");
+    m_switch_buttons_checkbox->set_checked(GUI::WindowServerConnection::the().get_buttons_switched());
+    auto& switch_buttons_image_label = *find_descendant_of_type_named<GUI::Label>("switch_buttons_image_label");
+    switch_buttons_image_label.set_icon(Gfx::Bitmap::try_load_from_file("/res/graphics/switch-mouse-buttons.png"));
 }
 
 void MouseWidget::update_window_server()
@@ -59,6 +63,7 @@ void MouseWidget::update_window_server()
     GUI::WindowServerConnection::the().async_set_mouse_acceleration(factor);
     GUI::WindowServerConnection::the().async_set_scroll_step_size(m_scroll_length_spinbox->value());
     GUI::WindowServerConnection::the().async_set_double_click_speed(m_double_click_speed_slider->value());
+    GUI::WindowServerConnection::the().async_set_buttons_switched(m_switch_buttons_checkbox->is_checked());
 }
 
 void MouseWidget::reset_default_values()
@@ -66,6 +71,7 @@ void MouseWidget::reset_default_values()
     m_speed_slider->set_value(speed_slider_scale);
     m_scroll_length_spinbox->set_value(default_scroll_length);
     m_double_click_speed_slider->set_value(double_click_speed_default);
+    m_switch_buttons_checkbox->set_checked(false);
     update_window_server();
 }
 

+ 2 - 0
Userland/Applications/MouseSettings/MouseWidget.h

@@ -6,6 +6,7 @@
 
 #pragma once
 
+#include <LibGUI/CheckBox.h>
 #include <LibGUI/Window.h>
 
 #include "DoubleClickArrowWidget.h"
@@ -26,5 +27,6 @@ private:
     RefPtr<GUI::SpinBox> m_scroll_length_spinbox;
     RefPtr<GUI::HorizontalSlider> m_double_click_speed_slider;
     RefPtr<GUI::Label> m_double_click_speed_label;
+    RefPtr<GUI::CheckBox> m_switch_buttons_checkbox;
     RefPtr<MouseSettings::DoubleClickArrowWidget> m_double_click_arrow_widget;
 };

+ 10 - 0
Userland/Services/WindowServer/ClientConnection.cpp

@@ -921,6 +921,16 @@ Messages::WindowServer::GetDoubleClickSpeedResponse ClientConnection::get_double
     return WindowManager::the().double_click_speed();
 }
 
+void ClientConnection::set_buttons_switched(bool switched)
+{
+    WindowManager::the().set_buttons_switched(switched);
+}
+
+Messages::WindowServer::GetButtonsSwitchedResponse ClientConnection::get_buttons_switched()
+{
+    return WindowManager::the().get_buttons_switched();
+}
+
 void ClientConnection::set_unresponsive(bool unresponsive)
 {
     if (m_unresponsive == unresponsive)

+ 2 - 0
Userland/Services/WindowServer/ClientConnection.h

@@ -160,6 +160,8 @@ private:
     virtual Messages::WindowServer::GetScreenBitmapAroundCursorResponse get_screen_bitmap_around_cursor(Gfx::IntSize const&) override;
     virtual void set_double_click_speed(i32) override;
     virtual Messages::WindowServer::GetDoubleClickSpeedResponse get_double_click_speed() override;
+    virtual void set_buttons_switched(bool) override;
+    virtual Messages::WindowServer::GetButtonsSwitchedResponse get_buttons_switched() override;
     virtual void set_window_modified(i32, bool) override;
     virtual Messages::WindowServer::IsWindowModifiedResponse is_window_modified(i32) override;
     virtual Messages::WindowServer::GetDesktopDisplayScaleResponse get_desktop_display_scale(u32) override;

+ 14 - 0
Userland/Services/WindowServer/EventLoop.cpp

@@ -106,6 +106,20 @@ void EventLoop::drain_mouse()
         if (packet.buttons != state.buttons) {
             state.buttons = packet.buttons;
             dbgln_if(WSMESSAGELOOP_DEBUG, "EventLoop: Mouse Button Event");
+
+            // Swap primary (1) and secondary (2) buttons if checked in Settings.
+            // Doing the swap here avoids all emulator and hardware issues.
+            if (WindowManager::the().get_buttons_switched()) {
+                bool has_primary = state.buttons & MousePacket::Button::LeftButton;
+                bool has_secondary = state.buttons & MousePacket::Button::RightButton;
+                state.buttons = state.buttons & ~(MousePacket::Button::LeftButton | MousePacket::Button::RightButton);
+                // Invert the buttons:
+                if (has_primary)
+                    state.buttons |= MousePacket::Button::RightButton;
+                if (has_secondary)
+                    state.buttons |= MousePacket::Button::LeftButton;
+            }
+
             screen_input.on_receive_mouse_data(state);
             state_is_sent = true;
             if (state.is_relative) {

+ 14 - 0
Userland/Services/WindowServer/WindowManager.cpp

@@ -71,6 +71,7 @@ void WindowManager::reload_config()
     apply_virtual_desktop_settings(virtual_desktop_rows, virtual_desktop_columns, false);
 
     m_double_click_speed = m_config->read_num_entry("Input", "DoubleClickSpeed", 250);
+    m_buttons_switched = m_config->read_bool_entry("Mouse", "ButtonsSwitched", false);
     apply_cursor_theme(m_config->read_entry("Mouse", "CursorTheme", "Default"));
 
     auto reload_graphic = [&](RefPtr<MultiScaleBitmaps>& bitmap, String const& name) {
@@ -274,6 +275,19 @@ int WindowManager::double_click_speed() const
     return m_double_click_speed;
 }
 
+void WindowManager::set_buttons_switched(bool switched)
+{
+    m_buttons_switched = switched;
+    dbgln("Saving mouse buttons switched state {} to config file at {}", switched, m_config->filename());
+    m_config->write_bool_entry("Mouse", "ButtonsSwitched", switched);
+    m_config->sync();
+}
+
+bool WindowManager::get_buttons_switched() const
+{
+    return m_buttons_switched;
+}
+
 WindowStack& WindowManager::window_stack_for_window(Window& window)
 {
     if (is_stationary_window_type(window.type()))

+ 3 - 0
Userland/Services/WindowServer/WindowManager.h

@@ -164,6 +164,8 @@ public:
     void set_scroll_step_size(unsigned);
     void set_double_click_speed(int);
     int double_click_speed() const;
+    void set_buttons_switched(bool);
+    bool get_buttons_switched() const;
 
     Window* set_active_input_window(Window*);
     void restore_active_input_window(Window*);
@@ -409,6 +411,7 @@ private:
     int m_double_click_speed { 0 };
     int m_max_distance_for_double_click { 4 };
     bool m_previous_event_was_super_keydown { false };
+    bool m_buttons_switched { false };
 
     WeakPtr<Window> m_hovered_window;
     WeakPtr<Window> m_highlight_window;

+ 3 - 0
Userland/Services/WindowServer/WindowServer.ipc

@@ -144,6 +144,9 @@ endpoint WindowServer
     set_double_click_speed(int speed) =|
     get_double_click_speed() => (int speed)
 
+    set_buttons_switched(bool switched) =|
+    get_buttons_switched() => (bool switched) 
+
     get_desktop_display_scale(u32 screen_index) => (int desktop_display_scale)
 
     set_flash_flush(bool enabled) =|