From 07878e25293175ca5b8c5572d38e7c3c7e918e92 Mon Sep 17 00:00:00 2001
From: meizhigang <meizhigang@kylinsec.com.cn>
Date: Sat, 8 Jul 2023 17:23:47 +0800
Subject: [PATCH] fix(keyboard):Add capslock and numlock tips switch
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

 - 添加大小写和数字键提示开关

 Related #9379
---
 ...com.kylinsec.kiran.keyboard.gschema.xml.in | 10 +++
 include/error-i.h                             |  2 +
 lib/base/error.cpp                            |  6 ++
 ....kylinsec.Kiran.SessionDaemon.Keyboard.xml | 29 +++++++++
 .../keyboard/keyboard-manager.cpp             | 63 +++++++++++++++++--
 .../inputdevices/keyboard/keyboard-manager.h  | 22 +++++--
 .../inputdevices/keyboard/keyboard-plugin.cpp |  4 ++
 .../keyboard/modifier-lock-manager.cpp        | 18 +++++-
 .../keyboard/modifier-lock-manager.h          | 14 ++++-
 po/zh_CN.po                                   |  8 +++
 10 files changed, 163 insertions(+), 13 deletions(-)

diff --git a/data/schemas/com.kylinsec.kiran.keyboard.gschema.xml.in b/data/schemas/com.kylinsec.kiran.keyboard.gschema.xml.in
index 05e948a..b29449d 100644
--- a/data/schemas/com.kylinsec.kiran.keyboard.gschema.xml.in
+++ b/data/schemas/com.kylinsec.kiran.keyboard.gschema.xml.in
@@ -6,6 +6,16 @@
             <description>Whether enable capslock and numlock windows tips.</description>
         </key>
 
+        <key name="capslock-tips-enabled" type="b">
+            <default>false</default>
+            <description>Whether enable capslock tips.</description>
+        </key>
+
+        <key name="numlock-tips-enabled" type="b">
+            <default>false</default>
+            <description>Whether enable numlock tips.</description>
+        </key>
+
         <key name="repeat-enabled" type="b">
             <default>true</default>
             <description>Whether repeat to trigger KeyPress and KeyRelease event when key is pressed.</description>
diff --git a/include/error-i.h b/include/error-i.h
index e34a504..9a81d3c 100644
--- a/include/error-i.h
+++ b/include/error-i.h
@@ -186,6 +186,8 @@ extern "C"
         ERROR_KEYBOARD_LAYOUT_OPTION_NOT_EXIST,
         ERROR_KEYBOARD_LAYOUT_OPTION_UPDATE_FAILED,
         ERROR_KEYBOARD_LAYOUT_OPTION_CLEAR_FAILED,
+        ERROR_KEYBOARD_SWITCH_CAPSLOCK_TIPS_FAILED,
+        ERROR_KEYBOARD_SWITCH_NUMLOCK_TIPS_FAILED,
 
         // Mouse
         ERROR_MOUSE_START = 0x230000,
diff --git a/lib/base/error.cpp b/lib/base/error.cpp
index deecb06..b9d12d5 100644
--- a/lib/base/error.cpp
+++ b/lib/base/error.cpp
@@ -306,6 +306,12 @@ std::string CCError::get_error_desc(CCErrorCode error_code, bool attach_error_co
     case CCErrorCode::ERROR_KEYBOARD_LAYOUT_OPTION_CLEAR_FAILED:
         error_desc = _("Failed to clear the layout option.");
         break;
+    case CCErrorCode::ERROR_KEYBOARD_SWITCH_CAPSLOCK_TIPS_FAILED:
+        error_desc = _("Failed to switch the capslock tips.");
+        break;
+    case CCErrorCode::ERROR_KEYBOARD_SWITCH_NUMLOCK_TIPS_FAILED:
+        error_desc = _("Failed to switch the numlock tips.");
+        break;
     case CCErrorCode::ERROR_KEYBINDING_CUSTOM_SHORTCUT_NOT_EXIST:
         error_desc = _("The custom shortcut isn't exist.");
         break;
diff --git a/plugins/inputdevices/keyboard/com.kylinsec.Kiran.SessionDaemon.Keyboard.xml b/plugins/inputdevices/keyboard/com.kylinsec.Kiran.SessionDaemon.Keyboard.xml
index 4c7c1a9..9f535fa 100644
--- a/plugins/inputdevices/keyboard/com.kylinsec.Kiran.SessionDaemon.Keyboard.xml
+++ b/plugins/inputdevices/keyboard/com.kylinsec.Kiran.SessionDaemon.Keyboard.xml
@@ -48,6 +48,35 @@
             <description>clear layout option.</description>
         </method>
 
+        <method name="SwitchCapsLockTips">
+            <arg type="b" name="enabled" direction="in">
+                <summary>enable option.</summary>
+            </arg>
+            <description>Switch CapsLock Tips option.</description>
+        </method>
+
+        <method name="SwitchNumLockTips">
+            <arg type="b" name="enabled" direction="in">
+                <summary>enable option.</summary>
+            </arg>
+            <description>Switch NumLock tips option.</description>
+        </method>
+
+        <property name="modifier_lock_enabled" type="b" access="readwrite">
+            <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="true"/>
+            <description>Whether capslock and numlock is enabled.</description>
+        </property>
+
+        <property name="capslock_tips_enabled" type="b" access="readwrite">
+            <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="true"/>
+            <description>Whether capslock tips is enabled.</description>
+        </property>
+
+        <property name="numlock_tips_enabled" type="b" access="readwrite">
+            <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="true"/>
+            <description>Whether numlock tips is enabled.</description>
+        </property>
+
         <property name="repeat_enabled" type="b" access="readwrite">
             <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="true"/>
             <description>Whether repeat to trigger KeyPress and KeyRelease event when key is pressed.</description>
diff --git a/plugins/inputdevices/keyboard/keyboard-manager.cpp b/plugins/inputdevices/keyboard/keyboard-manager.cpp
index 2318a9e..734d310 100644
--- a/plugins/inputdevices/keyboard/keyboard-manager.cpp
+++ b/plugins/inputdevices/keyboard/keyboard-manager.cpp
@@ -26,6 +26,8 @@ namespace Kiran
 {
 #define KEYBOARD_SCHEMA_ID "com.kylinsec.kiran.keyboard"
 #define KEYBOARD_SCHEMA_MODIFIER_LOCK_ENABLED "modifier-lock-enabled"
+#define KEYBOARD_SCHEMA_CAPSLOCK_TIPS_ENABLED "capslock-tips-enabled"
+#define KEYBOARD_SCHEMA_NUMLOCK_TIPS_ENABLED "numlock-tips-enabled"
 #define KEYBOARD_SCHEMA_REPEAT_ENABLED "repeat-enabled"
 #define KEYBOARD_SCHEMA_REPEAT_DELAY "repeat-delay"
 #define KEYBOARD_SCHEMA_REPEAT_INTERVAL "repeat-interval"
@@ -43,11 +45,12 @@ namespace Kiran
 KeyboardManager::KeyboardManager() : dbus_connect_id_(0),
                                      object_register_id_(0),
                                      modifier_lock_enabled_(false),
+                                     capslock_tips_enabled_(false),
+                                     numlock_tips_enabled_(false),
                                      repeat_enabled_(true),
                                      repeat_delay_(500),
                                      repeat_interval_(30)
 {
-    this->modifier_lock_manager_ = std::make_shared<ModifierLockManager>();
     this->keyboard_settings_ = Gio::Settings::create(KEYBOARD_SCHEMA_ID);
 }
 
@@ -208,6 +211,26 @@ void KeyboardManager::ClearLayoutOption(MethodInvocation &invocation)
     invocation.ret();
 }
 
+void KeyboardManager::SwitchCapsLockTips(bool enabled, MethodInvocation &invocation)
+{
+    if (!this->capslock_tips_enabled_set(enabled))
+    {
+        DBUS_ERROR_REPLY_AND_RET(CCErrorCode::ERROR_KEYBOARD_SWITCH_CAPSLOCK_TIPS_FAILED);
+    }
+
+    invocation.ret();
+}
+
+void KeyboardManager::SwitchNumLockTips(bool enabled, MethodInvocation &invocation)
+{
+    if (!this->numlock_tips_enabled_set(enabled))
+    {
+        DBUS_ERROR_REPLY_AND_RET(CCErrorCode::ERROR_KEYBOARD_SWITCH_NUMLOCK_TIPS_FAILED);
+    }
+
+    invocation.ret();
+}
+
 #define AUTO_REPEAT_SET_HANDLER(prop, type1, key, type2)                                                           \
     bool KeyboardManager::prop##_setHandler(type1 value)                                                           \
     {                                                                                                              \
@@ -230,6 +253,31 @@ AUTO_REPEAT_SET_HANDLER(repeat_enabled, bool, KEYBOARD_SCHEMA_REPEAT_ENABLED, bo
 AUTO_REPEAT_SET_HANDLER(repeat_delay, gint32, KEYBOARD_SCHEMA_REPEAT_DELAY, int);
 AUTO_REPEAT_SET_HANDLER(repeat_interval, gint32, KEYBOARD_SCHEMA_REPEAT_INTERVAL, int);
 
+#define KEYBOARD_PROP_SET_HANDLER(prop, type1, key, type2)                                                           \
+    bool KeyboardManager::prop##_setHandler(type1 value)                                                           \
+    {                                                                                                              \
+        RETURN_VAL_IF_TRUE(value == this->prop##_, false);                                                         \
+        if (this->keyboard_settings_->get_##type2(key) != value)                                                   \
+        {                                                                                                          \
+            auto value_r = Glib::Variant<std::remove_cv<std::remove_reference<type1>::type>::type>::create(value); \
+            if (!this->keyboard_settings_->set_value(key, value_r))                                                \
+            {                                                                                                      \
+                return false;                                                                                      \
+            }                                                                                                      \
+        }                                                                                                          \
+        this->prop##_ = value;                                                                                     \
+        return true;                                                                                               \
+    }
+
+KEYBOARD_PROP_SET_HANDLER(capslock_tips_enabled, bool, KEYBOARD_SCHEMA_CAPSLOCK_TIPS_ENABLED, boolean);
+KEYBOARD_PROP_SET_HANDLER(numlock_tips_enabled, bool, KEYBOARD_SCHEMA_NUMLOCK_TIPS_ENABLED, boolean);
+
+bool KeyboardManager::modifier_lock_enabled_setHandler(bool value)
+{
+    // do nothing
+    return true;
+}
+
 bool KeyboardManager::layouts_setHandler(const std::vector<Glib::ustring> &value)
 {
     KLOG_PROFILE("value: %s.", StrUtils::join(value, ",").c_str());
@@ -294,11 +342,6 @@ void KeyboardManager::init()
     this->load_xkb_rules();
     this->set_all_props();
 
-    if (this->modifier_lock_enabled_)
-    {
-        this->modifier_lock_manager_->init();
-    }
-
     this->keyboard_settings_->signal_changed().connect(sigc::mem_fun(this, &KeyboardManager::settings_changed));
 
     this->dbus_connect_id_ = Gio::DBus::own_name(Gio::DBus::BUS_TYPE_SESSION,
@@ -315,6 +358,8 @@ void KeyboardManager::load_from_settings()
     if (this->keyboard_settings_)
     {
         this->modifier_lock_enabled_ = this->keyboard_settings_->get_boolean(KEYBOARD_SCHEMA_MODIFIER_LOCK_ENABLED);
+        this->capslock_tips_enabled_ = this->keyboard_settings_->get_boolean(KEYBOARD_SCHEMA_CAPSLOCK_TIPS_ENABLED);
+        this->numlock_tips_enabled_ = this->keyboard_settings_->get_boolean(KEYBOARD_SCHEMA_NUMLOCK_TIPS_ENABLED);
         this->repeat_enabled_ = this->keyboard_settings_->get_boolean(KEYBOARD_SCHEMA_REPEAT_ENABLED);
         this->repeat_delay_ = this->keyboard_settings_->get_int(KEYBOARD_SCHEMA_REPEAT_DELAY);
         this->repeat_interval_ = this->keyboard_settings_->get_int(KEYBOARD_SCHEMA_REPEAT_INTERVAL);
@@ -344,6 +389,12 @@ void KeyboardManager::settings_changed(const Glib::ustring &key)
     case CONNECT(KEYBOARD_SCHEMA_OPTIONS, _hash):
         this->options_set(this->keyboard_settings_->get_string_array(key));
         break;
+    case CONNECT(KEYBOARD_SCHEMA_CAPSLOCK_TIPS_ENABLED, _hash):
+        this->capslock_tips_enabled_set(this->keyboard_settings_->get_boolean(key));
+        break;
+    case CONNECT(KEYBOARD_SCHEMA_NUMLOCK_TIPS_ENABLED, _hash):
+        this->numlock_tips_enabled_set(this->keyboard_settings_->get_boolean(key));
+        break;
     default:
         break;
     }
diff --git a/plugins/inputdevices/keyboard/keyboard-manager.h b/plugins/inputdevices/keyboard/keyboard-manager.h
index b213169..50f88b6 100644
--- a/plugins/inputdevices/keyboard/keyboard-manager.h
+++ b/plugins/inputdevices/keyboard/keyboard-manager.h
@@ -16,8 +16,6 @@
 
 #include <keyboard_dbus_stub.h>
 
-#include "plugins/inputdevices/keyboard/modifier-lock-manager.h"
-//
 #include "plugins/inputdevices/common/device-helper.h"
 
 namespace Kiran
@@ -34,6 +32,10 @@ public:
 
     static void global_deinit() { delete instance_; };
 
+    bool is_modifier_lock_enabled() { return this->modifier_lock_enabled_; };
+    bool is_capslock_tips_enabled() { return this->capslock_tips_enabled_; };
+    bool is_numlock_tips_enabled() { return this->numlock_tips_enabled_; };
+
 protected:
     /* 添加键盘布局。键盘布局最多只能设置4个，如果超过4个则返回添加；
        如果布局不在GetValidLayouts返回的列表中，或者布局已经存在用户布局列表中，则返回添加失败；
@@ -59,12 +61,24 @@ protected:
     // 清理布局选项
     virtual void ClearLayoutOption(MethodInvocation &invocation);
 
+    // 大小写锁提示开关
+    virtual void SwitchCapsLockTips(bool enabled, MethodInvocation &invocation);
+
+    // 数字键盘锁提示开关
+    virtual void SwitchNumLockTips(bool enabled, MethodInvocation &invocation);
+
+    virtual bool modifier_lock_enabled_setHandler(bool value);
+    virtual bool capslock_tips_enabled_setHandler(bool value);
+    virtual bool numlock_tips_enabled_setHandler(bool value);
     virtual bool repeat_enabled_setHandler(bool value);
     virtual bool repeat_delay_setHandler(gint32 value);
     virtual bool repeat_interval_setHandler(gint32 value);
     virtual bool layouts_setHandler(const std::vector<Glib::ustring> &value);
     virtual bool options_setHandler(const std::vector<Glib::ustring> &value);
 
+    virtual bool modifier_lock_enabled_get() { return this->modifier_lock_enabled_; };
+    virtual bool capslock_tips_enabled_get() { return this->capslock_tips_enabled_; };
+    virtual bool numlock_tips_enabled_get() { return this->numlock_tips_enabled_; };
     virtual bool repeat_enabled_get() { return this->repeat_enabled_; };
     virtual gint32 repeat_delay_get() { return this->repeat_delay_; };
     virtual gint32 repeat_interval_get() { return this->repeat_interval_; };
@@ -90,8 +104,6 @@ private:
 private:
     static KeyboardManager *instance_;
 
-    std::shared_ptr<ModifierLockManager> modifier_lock_manager_;
-
     uint32_t dbus_connect_id_;
     uint32_t object_register_id_;
 
@@ -99,6 +111,8 @@ private:
     std::map<Glib::ustring, Glib::ustring> valid_layouts_;
 
     bool modifier_lock_enabled_;
+    bool capslock_tips_enabled_;
+    bool numlock_tips_enabled_;
     bool repeat_enabled_;
     int32_t repeat_delay_;
     int32_t repeat_interval_;
diff --git a/plugins/inputdevices/keyboard/keyboard-plugin.cpp b/plugins/inputdevices/keyboard/keyboard-plugin.cpp
index b428a03..a8d26bb 100644
--- a/plugins/inputdevices/keyboard/keyboard-plugin.cpp
+++ b/plugins/inputdevices/keyboard/keyboard-plugin.cpp
@@ -17,6 +17,8 @@
 #include <cstdio>
 
 #include <gtk3-log-i.h>
+#include "plugins/inputdevices/keyboard/modifier-lock-manager.h"
+//
 #include "plugins/inputdevices/keyboard/keyboard-manager.h"
 
 PLUGIN_EXPORT_FUNC_DEF(KeyboardPlugin);
@@ -50,6 +52,7 @@ void KeyboardPlugin::activate()
     }
 
     KeyboardManager::global_init();
+    ModifierLockManager::global_init(KeyboardManager::get_instance());
 }
 
 void KeyboardPlugin::deactivate()
@@ -66,6 +69,7 @@ void KeyboardPlugin::deactivate()
         }
     }
 
+    ModifierLockManager::global_deinit();
     KeyboardManager::global_deinit();
 }
 }  // namespace Kiran
\ No newline at end of file
diff --git a/plugins/inputdevices/keyboard/modifier-lock-manager.cpp b/plugins/inputdevices/keyboard/modifier-lock-manager.cpp
index 80d55df..775f01e 100644
--- a/plugins/inputdevices/keyboard/modifier-lock-manager.cpp
+++ b/plugins/inputdevices/keyboard/modifier-lock-manager.cpp
@@ -22,7 +22,7 @@
 
 namespace Kiran
 {
-ModifierLockManager::ModifierLockManager()
+ModifierLockManager::ModifierLockManager(KeyboardManager *keyboard_manager) : keyboard_manager_(keyboard_manager)
 {
 }
 
@@ -33,6 +33,18 @@ ModifierLockManager::~ModifierLockManager()
                              this);
 }
 
+ModifierLockManager *ModifierLockManager::instance_ = nullptr;
+
+void ModifierLockManager::global_init(KeyboardManager *keyboard_manager)
+{
+    instance_ = new ModifierLockManager(keyboard_manager);
+
+    if (keyboard_manager->is_modifier_lock_enabled())
+    {
+        instance_->init();
+    }
+}
+
 void ModifierLockManager::init()
 {
     Display *dpy = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
@@ -113,6 +125,8 @@ void ModifierLockManager::set_lock_action(KeyCode keycode, unsigned int mods)
 
     if (keycode == this->capslock_keycode_)
     {
+        RETURN_IF_FALSE(this->keyboard_manager_->is_capslock_tips_enabled());
+
         bool capslock_enable = !!(this->capslock_mask_ & mods);
         if (capslock_enable)
         {
@@ -125,6 +139,8 @@ void ModifierLockManager::set_lock_action(KeyCode keycode, unsigned int mods)
     }
     else if (keycode == this->numlock_keycode_)
     {
+        RETURN_IF_FALSE(this->keyboard_manager_->is_numlock_tips_enabled());
+
         bool numlock_enable = !!(this->numlock_mask_ & mods);
         if (numlock_enable)
         {
diff --git a/plugins/inputdevices/keyboard/modifier-lock-manager.h b/plugins/inputdevices/keyboard/modifier-lock-manager.h
index a321ddc..e9dd773 100644
--- a/plugins/inputdevices/keyboard/modifier-lock-manager.h
+++ b/plugins/inputdevices/keyboard/modifier-lock-manager.h
@@ -17,6 +17,7 @@
 #include <gdkmm.h>
 //
 #include <X11/Xlib.h>
+#include "plugins/inputdevices/keyboard/keyboard-manager.h"
 #include "plugins/inputdevices/keyboard/modifier-lock-window.h"
 
 namespace Kiran
@@ -24,12 +25,18 @@ namespace Kiran
 class ModifierLockManager
 {
 public:
-    ModifierLockManager();
+    ModifierLockManager(KeyboardManager *keyboard_manager);
     ~ModifierLockManager();
 
-    void init();
+    static ModifierLockManager *get_instance() { return instance_; };
+
+    static void global_init(KeyboardManager *keyboard_manager);
+
+    static void global_deinit() { delete instance_; };
 
 private:
+    void init();
+
     int xkb_init();
 
     void set_lock_action(KeyCode keycode, unsigned int mods);
@@ -37,6 +44,8 @@ private:
     static GdkFilterReturn window_event(GdkXEvent *gdk_event, GdkEvent *event, gpointer data);
 
 private:
+    static ModifierLockManager *instance_;
+
     int xkb_event_base_;
 
     unsigned int capslock_mask_;
@@ -44,6 +53,7 @@ private:
     KeyCode capslock_keycode_;
     KeyCode numlock_keycode_;
 
+    KeyboardManager *keyboard_manager_;
     ModifierLockWindow lock_window_;
 };
 
diff --git a/po/zh_CN.po b/po/zh_CN.po
index 6de1cbd..7362715 100644
--- a/po/zh_CN.po
+++ b/po/zh_CN.po
@@ -1247,3 +1247,11 @@ msgstr "电源管理"
 #: ../plugins/power/tray/kiran-power-status-icon.desktop.in.h:2
 msgid "Power management daemon"
 msgstr "电源管理后端"
+
+#: ../lib/base/error.cpp:310
+msgid "Failed to switch the capslock tips."
+msgstr "无法切换大小写锁提示。"
+
+#: ../lib/base/error.cpp:313
+msgid "Failed to switch the numlock tips."
+msgstr "无法切换数字锁提示。"
\ No newline at end of file
-- 
2.27.0

