Skip to content

Commit

Permalink
distinguish left/right shift; test
Browse files Browse the repository at this point in the history
  • Loading branch information
eagleoflqj committed Jun 16, 2024
1 parent d1c83e1 commit 4d65ff0
Show file tree
Hide file tree
Showing 12 changed files with 144 additions and 41 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:

- name: Lint
run: |
find macosfrontend macosnotifications webpanel src -name '*.cpp' -o -name '*.h' | xargs clang-format -Werror --dry-run -style=file:fcitx5/.clang-format
find macosfrontend macosnotifications webpanel src tests -name '*.cpp' -o -name '*.h' | xargs clang-format -Werror --dry-run -style=file:fcitx5/.clang-format
swift-format lint --configuration .swift-format.json -rs macosfrontend macosnotifications src assets
./check-code-style.sh
file assets/zh-Hans.lproj/Localizable.strings | grep UTF-16
Expand Down
Binary file modified assets/zh-Hans.lproj/Localizable.strings
Binary file not shown.
66 changes: 38 additions & 28 deletions macosfrontend/keycode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,17 @@ static struct {
{OSX_VK_SHIFT_R, 54},
};

static struct {
uint32_t osxModifier;
fcitx::KeyState fcitxModifier;
} modifier_mappings[] = {
{OSX_MODIFIER_CAPSLOCK, fcitx::KeyState::CapsLock},
{OSX_MODIFIER_SHIFT, fcitx::KeyState::Shift},
{OSX_MODIFIER_CONTROL, fcitx::KeyState::Ctrl},
{OSX_MODIFIER_OPTION, fcitx::KeyState::Alt},
{OSX_MODIFIER_COMMAND, fcitx::KeyState::Super},
};

fcitx::KeySym osx_unicode_to_fcitx_keysym(uint32_t unicode,
uint32_t osxModifiers,
uint16_t osxKeycode) {
Expand Down Expand Up @@ -235,25 +246,34 @@ uint16_t fcitx_keysym_to_osx_keycode(fcitx::KeySym sym) {

fcitx::KeyStates osx_modifiers_to_fcitx_keystates(unsigned int osxModifiers) {
fcitx::KeyStates ret{};
if (osxModifiers & OSX_MODIFIER_CAPSLOCK) {
ret |= fcitx::KeyState::CapsLock;
}
if (osxModifiers & OSX_MODIFIER_SHIFT) {
ret |= fcitx::KeyState::Shift;
}
if (osxModifiers & OSX_MODIFIER_CONTROL) {
ret |= fcitx::KeyState::Ctrl;
}
if (osxModifiers & OSX_MODIFIER_OPTION) {
ret |= fcitx::KeyState::Alt;
}
if (osxModifiers & OSX_MODIFIER_COMMAND) {
ret |= fcitx::KeyState::Super;
for (const auto &pair : modifier_mappings) {
if (osxModifiers & pair.osxModifier) {
ret |= pair.fcitxModifier;
}
}
return ret;
}

std::string fcitx_keysym_to_osx_keysym(fcitx::KeySym keySym) {
// No way to distinguish with normal number keys for shortcut in menu.
if (fcitx::Key{keySym}.isKeyPad()) {
return "";
}
// TODO: VSCode Run has many functional key shortcuts, so we can copy
// implementation from electron.
switch (keySym) {
// Hack for arrow
case FcitxKey_Left:
return "\u{1c}";
case FcitxKey_Right:
return "\u{1d}";
case FcitxKey_Up:
return "\u{1e}";
case FcitxKey_Down:
return "\u{1f}";
default:
break;
}
// keySymToString returns grave for `, which will be used as G by macOS.
auto sym = fcitx::Key::keySymToUTF8(keySym);
// Normalized fcitx key like Control+D will show and be counted as
Expand All @@ -266,20 +286,10 @@ std::string fcitx_keysym_to_osx_keysym(fcitx::KeySym keySym) {

uint32_t fcitx_keystates_to_osx_modifiers(fcitx::KeyStates ks) {
uint32_t ret{};
if (ks & fcitx::KeyState::CapsLock) {
ret |= OSX_MODIFIER_CAPSLOCK;
}
if (ks & fcitx::KeyState::Shift) {
ret |= OSX_MODIFIER_SHIFT;
}
if (ks & fcitx::KeyState::Ctrl) {
ret |= OSX_MODIFIER_CONTROL;
}
if (ks & fcitx::KeyState::Alt) {
ret |= OSX_MODIFIER_OPTION;
}
if (ks & fcitx::KeyState::Super) {
ret |= OSX_MODIFIER_COMMAND;
for (const auto &pair : modifier_mappings) {
if (ks & pair.fcitxModifier) {
ret |= pair.osxModifier;
}
}
return ret;
}
2 changes: 2 additions & 0 deletions macosfrontend/keycode.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,8 @@ fcitx::KeySym osx_unicode_to_fcitx_keysym(uint32_t unicode,
uint16_t osx_keycode_to_fcitx_keycode(uint16_t osxKeycode);
fcitx::KeyStates osx_modifiers_to_fcitx_keystates(uint32_t osxModifiers);

// Used for showing shortcut configuration and setting shortcut for menu items.
// No need to be complete and sometimes must be inaccurate (e.g. A -> a).
std::string fcitx_keysym_to_osx_keysym(fcitx::KeySym);
uint16_t fcitx_keysym_to_osx_keycode(fcitx::KeySym);
uint32_t fcitx_keystates_to_osx_modifiers(fcitx::KeyStates ks);
Expand Down
5 changes: 3 additions & 2 deletions src/config/keycode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ func keyToUnicode(_ key: String) -> UInt32 {
return usv[usv.startIndex].value
}

func macKeyToFcitxString(_ key: String, _ modifier: NSEvent.ModifierFlags, _ code: UInt16) -> String
func macKeyToFcitxString(_ key: String, _ modifiers: NSEvent.ModifierFlags, _ code: UInt16)
-> String
{
let unicode = keyToUnicode(key)
return String(osx_key_to_fcitx_string(unicode, UInt32(modifier.rawValue), code))
return String(osx_key_to_fcitx_string(unicode, UInt32(modifiers.rawValue), code))
}

func fcitxStringToMacShortcut(_ s: String) -> String {
Expand Down
3 changes: 2 additions & 1 deletion src/config/keyrecorder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ func shortcutRepr(_ key: String, _ modifiers: NSEvent.ModifierFlags, _ code: UIn
if modifiers.contains(.control) { desc += "" }
if modifiers.contains(.option) { desc += "" }
if modifiers.contains(.shift) {
if (modifiers.rawValue & 0x20104) == 0x20104 {
// Only when Shift is main key we distinguish L/R.
if code == 0x3c {
desc += "" // Shift_R
} else {
desc += "" // Shift_L
Expand Down
6 changes: 3 additions & 3 deletions src/config/optionviews.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ struct KeyOptionView: OptionView {
}.buttonStyle(.borderedProminent)
}
}.padding()
}
}.help(model.value.isEmpty ? NSLocalizedString("Click to record", comment: "") : model.value)
}
}

Expand Down Expand Up @@ -540,7 +540,7 @@ struct GroupOptionView: OptionView {
subLabel
.font(.title3)
.gridCellColumns(2)
.help(NSLocalizedString("Right click to reset this group.", comment: ""))
.help(NSLocalizedString("Right click to reset this group", comment: ""))
.contextMenu {
Button {
child.resetToDefault()
Expand All @@ -560,7 +560,7 @@ struct GroupOptionView: OptionView {
GridRow {
subLabel
.frame(minWidth: 100, maxWidth: 300, alignment: .trailing)
.help(NSLocalizedString("Right click to reset this item.", comment: ""))
.help(NSLocalizedString("Right click to reset this item", comment: ""))
.contextMenu {
Button {
child.resetToDefault()
Expand Down
4 changes: 0 additions & 4 deletions src/controller.swift
Original file line number Diff line number Diff line change
Expand Up @@ -269,10 +269,6 @@ struct FcitxAction: Codable {
title: String(repeating: "  ", count: depth) + desc,
action: #selector(FcitxInputController.activateFcitxAction),
keyEquivalent: hotkey?[0].sym ?? "")
// static let leftArrowKeyEquivalent = NSString(format: "%C", 0x001c) as String
// static let rightArrowKeyEquivalent = NSString(format: "%C", 0x001d) as String
// static let downArrowKeyEquivalent = NSString(format: "%C", 0x001f) as String
// static let upArrowKeyEquivalent = NSString(format: "%C", 0x001e) as String
item.keyEquivalentModifierMask = NSEvent.ModifierFlags(rawValue: hotkey?[0].states ?? 0)
item.target = target
item.representedObject = self
Expand Down
11 changes: 11 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,14 @@ add_executable(xml-parser testxmlparser.swift
${PROJECT_SOURCE_DIR}/src/config/xmlparser.swift
)
add_test(NAME xml-parser COMMAND xml-parser "${PROJECT_SOURCE_DIR}/tests/customphrase.plist")

add_executable(key-cpp testkey.cpp)
target_link_libraries(key-cpp Fcitx5Objs)
add_test(NAME key-cpp COMMAND key-cpp)

add_executable(key-swift testkey.swift
${PROJECT_SOURCE_DIR}/src/config/keycode.swift
${PROJECT_SOURCE_DIR}/src/config/keyrecorder.swift
)
target_link_libraries(key-swift Fcitx5Objs)
add_test(NAME key-swift COMMAND key-swift)
4 changes: 2 additions & 2 deletions tests/testconfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ int main() {
if (child["Option"] == "Behavior") {
for (const auto &grand_child : child["Children"]) {
if (grand_child["Option"] == "ActiveByDefault") {
assert(grand_child["Value"]
.get<std::string>() == value);
assert(grand_child["Value"].get<std::string>() ==
value);
break;
}
}
Expand Down
59 changes: 59 additions & 0 deletions tests/testkey.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#include <cassert>
#include "keycode.h"
#include "macosfrontend-public.h"

void test_osx_to_fcitx() {
assert(osx_unicode_to_fcitx_keysym('0', 0, 0) == FcitxKey_0);
assert(osx_unicode_to_fcitx_keysym('0', 0, OSX_VK_KEYPAD_0) ==
FcitxKey_KP_0);
assert(osx_unicode_to_fcitx_keysym('a', 0, 0) == FcitxKey_a);
assert(osx_unicode_to_fcitx_keysym('a', OSX_MODIFIER_SHIFT, 0) ==
FcitxKey_A);

assert(osx_keycode_to_fcitx_keycode(OSX_VK_KEY_0) == 11 + 8);
assert(osx_keycode_to_fcitx_keycode(OSX_VK_KEYPAD_0) == 82 + 8);
assert(osx_keycode_to_fcitx_keycode(OSX_VK_SHIFT_L) == 42 + 8);
assert(osx_keycode_to_fcitx_keycode(OSX_VK_SHIFT_R) == 54 + 8);

assert(
osx_modifiers_to_fcitx_keystates(OSX_MODIFIER_CONTROL |
OSX_MODIFIER_SHIFT) ==
(fcitx::KeyStates{} | fcitx::KeyState::Ctrl | fcitx::KeyState::Shift));
}

void test_fcitx_to_osx() {
assert(fcitx_keysym_to_osx_keysym(FcitxKey_Up) == "\u{1e}");
assert(fcitx_keysym_to_osx_keysym(FcitxKey_0) == "0");
assert(fcitx_keysym_to_osx_keysym(FcitxKey_KP_0) == "");
assert(fcitx_keysym_to_osx_keysym(FcitxKey_grave) == "`");
assert(fcitx_keysym_to_osx_keysym(FcitxKey_a) == "a");
assert(fcitx_keysym_to_osx_keysym(FcitxKey_A) == "a");

assert(fcitx_keysym_to_osx_keycode(FcitxKey_KP_0) == OSX_VK_KEYPAD_0);
assert(fcitx_keysym_to_osx_keycode(FcitxKey_Shift_L) == OSX_VK_SHIFT_L);
assert(fcitx_keysym_to_osx_keycode(FcitxKey_Shift_R) == OSX_VK_SHIFT_R);

assert(fcitx_keystates_to_osx_modifiers(fcitx::KeyStates{} |
fcitx::KeyState::Super |
fcitx::KeyState::Alt) ==
(OSX_MODIFIER_COMMAND | OSX_MODIFIER_OPTION));
}

void test_fcitx_string() {
assert(fcitx_string_to_osx_keysym("Left") == "\u{1c}");
assert(fcitx_string_to_osx_keysym("Control+0") == "0");
assert(fcitx_string_to_osx_keysym("Control+Shift+KP_0") == "");
assert(fcitx_string_to_osx_keysym("Control+slash") == "/");

assert(fcitx_string_to_osx_modifiers("Control+Super+K") ==
(OSX_MODIFIER_CONTROL | OSX_MODIFIER_COMMAND));

assert(fcitx_string_to_osx_keycode("Alt+Shift+Shift_L") == OSX_VK_SHIFT_L);
assert(fcitx_string_to_osx_keycode("Shift_R") == OSX_VK_SHIFT_R);
}

int main() {
test_osx_to_fcitx();
test_fcitx_to_osx();
test_fcitx_string();
}
23 changes: 23 additions & 0 deletions tests/testkey.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
func testMacToFcitx() {
assert(macKeyToFcitxString("a", .control, 0) == "Control+A")
assert(macKeyToFcitxString("A", .control.union(.shift), 0) == "Control+Shift+A")

assert(macKeyToFcitxString("", .option.union(.shift), 0x38) == "Alt+Shift+Shift_L")
assert(macKeyToFcitxString("", .command.union(.shift), 0x3c) == "Shift+Super+Shift_R")
}

func testFcitxToMac() {
assert(fcitxStringToMacShortcut("0") == "0")
assert(fcitxStringToMacShortcut("KP_0") == "🄋")
assert(fcitxStringToMacShortcut("Control+A") == "⌃A")
assert(fcitxStringToMacShortcut("Control+Shift+A") == "⌃⇧A")
assert(fcitxStringToMacShortcut("Shift+Super+Shift_L") == "⇧⌘")
assert(fcitxStringToMacShortcut("Alt+Shift+Shift_R") == "⌥⬆")
}

@_cdecl("main")
func main() -> Int {
testMacToFcitx()
testFcitxToMac()
return 0
}

0 comments on commit 4d65ff0

Please sign in to comment.