瀏覽代碼

Kernel: Allow remapping Caps Lock to Control (#6883)

We use a global setting to determine if Caps Lock should be remapped to
Control because we don't care how keyboard events come in, just that they
should be massaged into different scan codes.

The `proc` filesystem is able to manipulate this global variable using
the `sysctl` utility like so:

```
# sysctl caps_lock_to_ctrl=1
```
Spencer Dixon 4 年之前
父節點
當前提交
0f89e47a1a

+ 1 - 0
Kernel/Devices/HID/HIDManagement.cpp

@@ -12,6 +12,7 @@
 
 namespace Kernel {
 
+Atomic<bool> g_caps_lock_remapped_to_ctrl;
 static AK::Singleton<HIDManagement> s_the;
 
 // clang-format off

+ 3 - 0
Kernel/Devices/HID/HIDManagement.h

@@ -6,6 +6,7 @@
 
 #pragma once
 
+#include <AK/Atomic.h>
 #include <AK/CircularQueue.h>
 #include <AK/NonnullRefPtrVector.h>
 #include <AK/RefPtr.h>
@@ -20,6 +21,8 @@
 
 namespace Kernel {
 
+extern Atomic<bool> g_caps_lock_remapped_to_ctrl;
+
 class HIDDevice;
 class I8042Controller;
 class MouseDevice;

+ 7 - 1
Kernel/Devices/HID/KeyboardDevice.cpp

@@ -234,9 +234,15 @@ void KeyboardDevice::key_state_changed(u8 scan_code, bool pressed)
         }
     }
 
-    if (key == Key_CapsLock && pressed)
+    if (!g_caps_lock_remapped_to_ctrl && key == Key_CapsLock && pressed)
         m_caps_lock_on = !m_caps_lock_on;
 
+    if (g_caps_lock_remapped_to_ctrl && key == Key_CapsLock)
+        m_caps_lock_to_ctrl_pressed = pressed;
+
+    if (g_caps_lock_remapped_to_ctrl)
+        update_modifier(Mod_Ctrl, m_caps_lock_to_ctrl_pressed);
+
     Event event;
     event.key = key;
     event.scancode = m_has_e0_prefix ? 0xe000 + scan_code : scan_code;

+ 1 - 0
Kernel/Devices/HID/KeyboardDevice.h

@@ -53,6 +53,7 @@ protected:
     virtual const char* class_name() const override { return "KeyboardDevice"; }
 
     u8 m_modifiers { 0 };
+    bool m_caps_lock_to_ctrl_pressed { false };
     bool m_caps_lock_on { false };
     bool m_num_lock_on { false };
     bool m_has_e0_prefix { false };

+ 6 - 0
Kernel/FileSystem/ProcFS.cpp

@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
+ * Copyright (c) 2021, Spencer Dixon <spencercdixon@gmail.com>
  *
  * SPDX-License-Identifier: BSD-2-Clause
  */
@@ -970,6 +971,7 @@ bool ProcFS::initialize()
 {
     static Lockable<bool>* kmalloc_stack_helper;
     static Lockable<bool>* ubsan_deadly_helper;
+    static Lockable<bool>* caps_lock_to_ctrl_helper;
 
     if (kmalloc_stack_helper == nullptr) {
         kmalloc_stack_helper = new Lockable<bool>();
@@ -982,6 +984,10 @@ bool ProcFS::initialize()
         ProcFS::add_sys_bool("ubsan_is_deadly", *ubsan_deadly_helper, [] {
             UBSanitizer::g_ubsan_is_deadly = ubsan_deadly_helper->resource();
         });
+        caps_lock_to_ctrl_helper = new Lockable<bool>();
+        ProcFS::add_sys_bool("caps_lock_to_ctrl", *caps_lock_to_ctrl_helper, [] {
+            Kernel::g_caps_lock_remapped_to_ctrl.exchange(caps_lock_to_ctrl_helper->resource());
+        });
     }
     return true;
 }