diff --git a/README.ko.md b/README.ko.md index c79e2f3b..1573fcd6 100644 --- a/README.ko.md +++ b/README.ko.md @@ -34,7 +34,6 @@ - [x] XIM - [x] Wayland -- [x] GTK2 - [x] GTK3 - [x] GTK4 - [x] Qt5 diff --git a/README.md b/README.md index e091f051..442e019e 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,6 @@ Please contact us on [Discord](https://discord.gg/YPnEfZqC6y) or create github i - [x] XIM - [x] Wayland -- [x] GTK2 - [x] GTK3 - [x] GTK4 - [x] Qt5 diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index df17494f..81065a7c 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -7,6 +7,8 @@ * `FlexibleComposeOrder` can change jongseong order [#534](https://github.com/Riey/kime/issues/534) * Implement hanja candidate window [#383](https://github.com/Riey/kime/issues/383) * Builtin sebeolsik `3-90` and `3-91` changed with all jungseong to uncomposable except for `ㅑ`, `ㅕ`,`ㅡ`, `ㅜ(9)`, `ㅗ(/)` [#542](https://github.com/Riey/kime/issues/542) +* Respect NUMLOCK state [#591](https://github.com/Riey/kime/issues/591) +* Remove support GTK2 ### Improve diff --git a/nix/deps.nix b/nix/deps.nix index 1b4fc12c..27fd99cf 100644 --- a/nix/deps.nix +++ b/nix/deps.nix @@ -10,7 +10,6 @@ with pkgs; wayland libxkbcommon - gtk2 gtk3 gtk4 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 683bb35f..317c6e27 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,7 +3,6 @@ cmake_minimum_required(VERSION 3.13.0) project(kime VERSION 2.0.0) option(USE_SYSTEM_ENGINE "Use system engine file" OFF) -option(ENABLE_GTK2 "Enable GTK2 immodule" OFF) option(ENABLE_GTK3 "Enable GTK3 immodule" OFF) option(ENABLE_GTK4 "Enable GTK4 immodule" OFF) option(ENABLE_QT5 "Enable Qt5 immodule" OFF) @@ -27,9 +26,6 @@ set(OpenGL_GL_PREFERENCE GLVND) include(GNUInstallDirs) -if(${ENABLE_GTK2}) - add_subdirectory(frontends/gtk2) -endif() if(${ENABLE_GTK3}) add_subdirectory(frontends/gtk3) endif() diff --git a/src/engine/backend/src/keycode.rs b/src/engine/backend/src/keycode.rs index b91f1231..d3883f90 100644 --- a/src/engine/backend/src/keycode.rs +++ b/src/engine/backend/src/keycode.rs @@ -11,9 +11,10 @@ bitflags::bitflags! { #[repr(transparent)] pub struct ModifierState: u32 { const SHIFT = 0x1; - const CONTROL = 0x2; - const SUPER = 0x4; - const ALT = 0x8; + const NUMLOCK = 0x2; + const CONTROL = 0x4; + const SUPER = 0x8; + const ALT = 0x10; } } @@ -42,6 +43,27 @@ pub enum KeyCode { #[strum(to_string = "0")] Zero, + #[strum(to_string = "N1")] + NumOne, + #[strum(to_string = "N2")] + NumTwo, + #[strum(to_string = "N3")] + NumThree, + #[strum(to_string = "N4")] + NumFour, + #[strum(to_string = "N5")] + NumFive, + #[strum(to_string = "N6")] + NumSix, + #[strum(to_string = "N7")] + NumSeven, + #[strum(to_string = "N8")] + NumEight, + #[strum(to_string = "N9")] + NumNine, + #[strum(to_string = "N0")] + NumZero, + Minus, Equal, Backslash, @@ -127,16 +149,26 @@ pub enum KeyCode { impl KeyCode { pub const fn from_hardware_code(code: u16) -> Option { match code { - 10 | 87 => Some(Self::One), - 11 | 88 => Some(Self::Two), - 12 | 89 => Some(Self::Three), - 13 | 83 => Some(Self::Four), - 14 | 84 => Some(Self::Five), - 15 | 85 => Some(Self::Six), - 16 | 79 => Some(Self::Seven), - 17 | 80 => Some(Self::Eight), - 18 | 81 => Some(Self::Nine), - 19 | 90 => Some(Self::Zero), + 10 => Some(Self::One), + 87 => Some(Self::NumOne), + 11 => Some(Self::Two), + 88 => Some(Self::NumTwo), + 12 => Some(Self::Three), + 89 => Some(Self::NumThree), + 13 => Some(Self::Four), + 83 => Some(Self::NumFour), + 14 => Some(Self::Five), + 84 => Some(Self::NumFive), + 15 => Some(Self::Six), + 85 => Some(Self::NumSix), + 16 => Some(Self::Seven), + 79 => Some(Self::NumSeven), + 17 => Some(Self::Eight), + 80 => Some(Self::NumEight), + 18 => Some(Self::Nine), + 81 => Some(Self::NumNine), + 19 => Some(Self::Zero), + 90 => Some(Self::NumZero), 20 => Some(Self::Minus), 21 => Some(Self::Equal), 34 => Some(Self::OpenBracket), @@ -254,6 +286,10 @@ impl Key { pub const fn super_(code: KeyCode) -> Self { Self::new(code, ModifierState::SUPER) } + + pub const fn numlock(code: KeyCode) -> Self { + Self::new(code, ModifierState::NUMLOCK) + } } impl fmt::Display for Key { @@ -274,6 +310,10 @@ impl fmt::Display for Key { f.write_str("S-")?; } + if self.state.contains(ModifierState::NUMLOCK) { + f.write_str("N-")?; + } + write!(f, "{}", self.code) } } @@ -309,6 +349,12 @@ impl FromStr for Key { continue; } + if let Some(n) = s.strip_prefix("N-") { + s = n; + state |= ModifierState::NUMLOCK; + continue; + } + break; } @@ -346,4 +392,9 @@ fn key_parse() { assert_eq!("S-4".parse::().unwrap(), Key::shift(KeyCode::Four)); assert_eq!("C-Space".parse::().unwrap(), Key::ctrl(KeyCode::Space)); assert_eq!("M-X".parse::().unwrap(), Key::alt(KeyCode::X)); + assert_eq!("N-1".parse::().unwrap(), Key::numlock(KeyCode::One)); + assert_eq!( + "N-N1".parse::().unwrap(), + Key::numlock(KeyCode::NumOne) + ); } diff --git a/src/engine/backend/src/keymap.rs b/src/engine/backend/src/keymap.rs index aff55f27..0d2e16c7 100644 --- a/src/engine/backend/src/keymap.rs +++ b/src/engine/backend/src/keymap.rs @@ -12,7 +12,7 @@ use std::{ #[derive(Clone, Debug, PartialEq, Eq)] pub struct KeyMap { - arr: EnumMap; 2]>, + arr: EnumMap; 4]>, } impl Default for KeyMap { @@ -29,7 +29,10 @@ impl KeyMap { } pub fn get(&self, key: Key) -> Option { - if key.state.intersects(!ModifierState::SHIFT) { + if key + .state + .intersects(!(ModifierState::SHIFT | ModifierState::NUMLOCK)) + { None } else { // SAFETY: key.state <= 0x1 diff --git a/src/engine/capi/src/lib.rs b/src/engine/capi/src/lib.rs index 86f3ae6b..c67e8f23 100644 --- a/src/engine/capi/src/lib.rs +++ b/src/engine/capi/src/lib.rs @@ -6,7 +6,7 @@ pub use kime_engine_core::{ ModifierState, }; -pub const KIME_API_VERSION: usize = 6; +pub const KIME_API_VERSION: usize = 7; #[repr(C)] pub struct RustStr { diff --git a/src/engine/cffi/src/lib.rs b/src/engine/cffi/src/lib.rs index f9ad788a..5c354a2e 100644 --- a/src/engine/cffi/src/lib.rs +++ b/src/engine/cffi/src/lib.rs @@ -14,8 +14,8 @@ pub use kime_engine_config::{DaemonModule, EnumSet}; pub use ffi::{ IconColor, InputCategory, InputResult, InputResult_CONSUMED, InputResult_HAS_COMMIT, InputResult_HAS_PREEDIT, InputResult_LANGUAGE_CHANGED, InputResult_NOT_READY, ModifierState, - ModifierState_ALT, ModifierState_CONTROL, ModifierState_SHIFT, ModifierState_SUPER, - KIME_API_VERSION, + ModifierState_ALT, ModifierState_CONTROL, ModifierState_NUMLOCK, ModifierState_SHIFT, + ModifierState_SUPER, KIME_API_VERSION, }; pub fn check_api_version() -> bool { diff --git a/src/engine/core/tests/emoji.rs b/src/engine/core/tests/emoji.rs index 62de2e28..e01ac2d2 100644 --- a/src/engine/core/tests/emoji.rs +++ b/src/engine/core/tests/emoji.rs @@ -5,7 +5,7 @@ define_layout_test!("dubeolsik", LatinLayout::Qwerty, InputCategory::Latin); use kime_engine_core::ModifierState; -const EMOJI: Key = Key::new(E, ModifierState::from_bits_truncate(10)); +const EMOJI: Key = Key::new(E, ModifierState::CONTROL.union(ModifierState::ALT)); #[test] fn thinking() { diff --git a/src/engine/core/tests/math.rs b/src/engine/core/tests/math.rs index fd60eb0a..55b7e828 100644 --- a/src/engine/core/tests/math.rs +++ b/src/engine/core/tests/math.rs @@ -5,7 +5,7 @@ define_layout_test!("dubeolsik", LatinLayout::Qwerty, InputCategory::Latin); use kime_engine_core::ModifierState; -const MATH: Key = Key::new(Backslash, ModifierState::from_bits_truncate(10)); +const MATH: Key = Key::new(Backslash, ModifierState::CONTROL.union(ModifierState::ALT)); #[test] fn twice_backspace() { diff --git a/src/frontends/gtk2/CMakeLists.txt b/src/frontends/gtk2/CMakeLists.txt deleted file mode 100644 index 0e321b18..00000000 --- a/src/frontends/gtk2/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -find_package(PkgConfig REQUIRED) -pkg_check_modules(GTK2 gtk+-2.0) - -if(GTK2_FOUND) - add_library(kime-gtk2 SHARED src/gtk.c src/immodule.c src/str_buf.c) - - target_compile_definitions(kime-gtk2 PRIVATE GTK_DISABLE_DEPRECATED) - target_include_directories(kime-gtk2 PRIVATE ${GTK2_INCLUDE_DIRS} ${KIME_INCLUDE}) - target_link_directories(kime-gtk2 PRIVATE ${GTK2_LIBRARY_DIRS} ${KIME_LIB_DIRS}) - target_link_libraries(kime-gtk2 PRIVATE ${GTK2_LIBRARIES} ${KIME_ENGINE}) -endif() diff --git a/src/frontends/gtk3/CMakeLists.txt b/src/frontends/gtk3/CMakeLists.txt index 779e2f23..cbbb63ad 100644 --- a/src/frontends/gtk3/CMakeLists.txt +++ b/src/frontends/gtk3/CMakeLists.txt @@ -2,7 +2,7 @@ find_package(PkgConfig REQUIRED) pkg_check_modules(GTK3 gtk+-3.0) if(GTK3_FOUND) - add_library(kime-gtk3 SHARED ../gtk2/src/gtk.c ../gtk2/src/immodule.c ../gtk2/src/str_buf.c) + add_library(kime-gtk3 SHARED ./src/gtk.c ./src/immodule.c ./src/str_buf.c) target_include_directories(kime-gtk3 PRIVATE ${GTK3_INCLUDE_DIRS} ${KIME_INCLUDE}) target_link_directories(kime-gtk3 PRIVATE ${GTK3_LIBRARY_DIRS} ${KIME_LIB_DIRS}) diff --git a/src/frontends/gtk2/src/gtk.c b/src/frontends/gtk3/src/gtk.c similarity index 100% rename from src/frontends/gtk2/src/gtk.c rename to src/frontends/gtk3/src/gtk.c diff --git a/src/frontends/gtk2/src/immodule.c b/src/frontends/gtk3/src/immodule.c similarity index 95% rename from src/frontends/gtk2/src/immodule.c rename to src/frontends/gtk3/src/immodule.c index a9a3d516..4f1fbcd1 100644 --- a/src/frontends/gtk2/src/immodule.c +++ b/src/frontends/gtk3/src/immodule.c @@ -15,6 +15,18 @@ typedef GdkEvent EventType; #define GDK_ALT_MASK GDK_MOD1_MASK typedef GdkWindow ClientType; typedef GdkEventKey EventType; +#if GTK_CHECK_VERSION(3, 0, 0) +gboolean gdk_device_get_num_lock_state (GdkDevice *device) +{ + GdkKeymap *keymap = gdk_keymap_get_for_display(gdk_device_get_display(device)); + return gdk_keymap_get_num_lock_state(keymap); +} +#else +gboolean gdk_device_get_num_lock_state (GdkDevice *device) +{ + return FALSE; +} +#endif #endif static const guint NOT_ENGLISH_MASK = @@ -214,6 +226,7 @@ gboolean filter_keypress(GtkIMContext *im, EventType *key) { guint16 code = gdk_key_event_get_keycode(key); guint keyval = gdk_key_event_get_keyval(key); GdkModifierType state = gdk_event_get_modifier_state(key); + GdkDevice* device = gdk_event_get_device(key); #else if (key->type != GDK_KEY_PRESS) { return FALSE; @@ -221,6 +234,7 @@ gboolean filter_keypress(GtkIMContext *im, EventType *key) { guint16 code = key->hardware_keycode; guint keyval = key->keyval; GdkModifierType state = key->state; + GdkDevice* device = gdk_event_get_device((GdkEvent*)key); #endif // delayed event @@ -235,8 +249,14 @@ gboolean filter_keypress(GtkIMContext *im, EventType *key) { } } + gboolean numlock = gdk_device_get_num_lock_state(device); + KimeModifierState kime_state = 0; + if (numlock) { + kime_state |= KimeModifierState_NUMLOCK; + } + if (state & GDK_SHIFT_MASK) { kime_state |= KimeModifierState_SHIFT; } diff --git a/src/frontends/gtk2/src/immodule.h b/src/frontends/gtk3/src/immodule.h similarity index 100% rename from src/frontends/gtk2/src/immodule.h rename to src/frontends/gtk3/src/immodule.h diff --git a/src/frontends/gtk2/src/str_buf.c b/src/frontends/gtk3/src/str_buf.c similarity index 100% rename from src/frontends/gtk2/src/str_buf.c rename to src/frontends/gtk3/src/str_buf.c diff --git a/src/frontends/gtk2/src/str_buf.h b/src/frontends/gtk3/src/str_buf.h similarity index 100% rename from src/frontends/gtk2/src/str_buf.h rename to src/frontends/gtk3/src/str_buf.h diff --git a/src/frontends/gtk4/CMakeLists.txt b/src/frontends/gtk4/CMakeLists.txt index 232ec52f..2f3e3943 100644 --- a/src/frontends/gtk4/CMakeLists.txt +++ b/src/frontends/gtk4/CMakeLists.txt @@ -2,7 +2,7 @@ find_package(PkgConfig REQUIRED) pkg_check_modules(GTK4 QUIET gtk4) if(GTK4_FOUND) - add_library(kime-gtk4 SHARED src/gtk4.c ../gtk2/src/immodule.c ../gtk2/src/str_buf.c) + add_library(kime-gtk4 SHARED src/gtk4.c ../gtk3/src/immodule.c ../gtk3/src/str_buf.c) target_include_directories(kime-gtk4 PRIVATE ${GTK4_INCLUDE_DIRS} ${KIME_INCLUDE}) target_link_directories(kime-gtk4 PRIVATE ${GTK4_LIBRARY_DIRS} ${KIME_LIB_DIRS}) diff --git a/src/frontends/gtk4/src/gtk4.c b/src/frontends/gtk4/src/gtk4.c index e33dc8e7..2505a702 100644 --- a/src/frontends/gtk4/src/gtk4.c +++ b/src/frontends/gtk4/src/gtk4.c @@ -1,4 +1,4 @@ -#include "../../gtk2/src/immodule.h" +#include "../../gtk3/src/immodule.h" G_MODULE_EXPORT void g_io_module_load(GIOModule *module) { if (kime_api_version() != KimeKIME_API_VERSION) { diff --git a/src/frontends/qt5/src/input_context.cc b/src/frontends/qt5/src/input_context.cc index bd9ad96c..b01e43d5 100644 --- a/src/frontends/qt5/src/input_context.cc +++ b/src/frontends/qt5/src/input_context.cc @@ -65,6 +65,10 @@ bool KimeInputContext::filterEvent(const QEvent *event) { kime::ModifierState state = 0; + if (modifiers.testFlag(Qt::KeyboardModifier::KeypadModifier)) { + state |= kime::ModifierState_NUMLOCK; + } + if (modifiers.testFlag(Qt::KeyboardModifier::ControlModifier)) { state |= kime::ModifierState_CONTROL; } diff --git a/src/frontends/wayland/src/main.rs b/src/frontends/wayland/src/main.rs index 3f651a26..61ebcf79 100644 --- a/src/frontends/wayland/src/main.rs +++ b/src/frontends/wayland/src/main.rs @@ -16,11 +16,7 @@ use zwp_virtual_keyboard::virtual_keyboard_unstable_v1::{ zwp_virtual_keyboard_v1::ZwpVirtualKeyboardV1, }; -use kime_engine_cffi::{ - Config, InputEngine, InputResult, InputResult_CONSUMED, InputResult_HAS_COMMIT, - InputResult_HAS_PREEDIT, InputResult_LANGUAGE_CHANGED, InputResult_NOT_READY, ModifierState, - ModifierState_ALT, ModifierState_CONTROL, ModifierState_SHIFT, ModifierState_SUPER, -}; +use kime_engine_cffi::*; use mio::{unix::SourceFd, Events as MioEvents, Interest, Poll, Token}; use mio_timerfd::{ClockId, TimerFd}; @@ -320,6 +316,9 @@ impl KimeContext { if mods_depressed & 0x8 != 0 { self.mod_state |= ModifierState_ALT; } + if mods_depressed & 0x10 != 0 { + self.mod_state |= ModifierState_NUMLOCK; + } if mods_depressed & 0x40 != 0 { self.mod_state |= ModifierState_SUPER; } diff --git a/src/frontends/xim/src/handler.rs b/src/frontends/xim/src/handler.rs index ad36155c..7df673ee 100644 --- a/src/frontends/xim/src/handler.rs +++ b/src/frontends/xim/src/handler.rs @@ -11,11 +11,7 @@ use xim::{ InputStyle, Server, ServerHandler, }; -use kime_engine_cffi::{ - Config, InputEngine, InputResult_CONSUMED, InputResult_HAS_COMMIT, InputResult_HAS_PREEDIT, - InputResult_LANGUAGE_CHANGED, InputResult_NOT_READY, ModifierState_ALT, ModifierState_CONTROL, - ModifierState_SHIFT, ModifierState_SUPER, -}; +use kime_engine_cffi::*; pub struct KimeData { engine: InputEngine, @@ -345,6 +341,10 @@ impl ServerHandler> for KimeHandler { state |= ModifierState_ALT; } + if check_flag!(MOD2) { + state |= ModifierState_NUMLOCK; + } + if check_flag!(MOD4) { state |= ModifierState_SUPER; }