虚拟键盘支持小语种裸键盘输入

1. 为除了Fn键和输入法切换键之外的其他按键定义keycode值并定义对应的keysym值,
满足fcitx5对按键事件keycode和keysym的要求

2. 区分keycode和keysym。按键的keycode是固定不变的。动作键、修饰符键和功能键的
keysym需要由前端指定并在发生按键事件后传递给后端。数字键、符号键和字母键的keysym
是当前数字、符号或字母的unicode编码

3. 基于字符键CharKey实现的字母键、动作键和符号键等按键等支持按下和抬起事件,
满足fcitx5对按键事件完整性的要求

4. 基于临时开关键TemorarySwitchKey实现的修饰符键支持按下和抬起事件,满足fcitx5
对按键事件完整性的要求
This commit is contained in:
liulinsong 2023-09-04 17:09:55 +08:00 committed by hanteng
parent d7c4e63445
commit d753cad0ae
11 changed files with 224 additions and 89 deletions

View File

@ -41,5 +41,6 @@
<file>img/right.svg</file>
<file>img/up.svg</file>
<file>img/down.svg</file>
<file>qml/js/keycode.js</file>
</qresource>
</RCC>

View File

@ -17,6 +17,7 @@
import QtQuick 2.0
import "key/"
import "../qml/js/keycode.js" as Keycode
Column {
width: parent.width
@ -26,93 +27,93 @@ Column {
Row {
anchors.horizontalCenter: parent.horizontalCenter
spacing: virtualKeyboard.keySpacing
ActionKey{ label: "Esc" ;height: virtualKeyboard.keyHeight * 3/4}
SymbolKey{ label: "`"; shiftedText: "~"; height: virtualKeyboard.firstRowKeyHeight; }
FnSymbolKey{ label: "1"; shiftedText: "!"; fnValue:"F1" }
FnSymbolKey{ label: "2"; shiftedText: "@"; fnValue:"F2" }
FnSymbolKey{ label: "3"; shiftedText: "#"; fnValue:"F3" }
FnSymbolKey{ label: "4"; shiftedText: "$"; fnValue:"F4" }
FnSymbolKey{ label: "5"; shiftedText: "%"; fnValue:"F5" }
FnSymbolKey{ label: "6"; shiftedText: "^"; fnValue:"F6" }
FnSymbolKey{ label: "7"; shiftedText: "&"; fnValue:"F7" }
FnSymbolKey{ label: "8"; shiftedText: "*"; fnValue:"F8" }
FnSymbolKey{ label: "9"; shiftedText: "("; fnValue:"F9" }
FnSymbolKey{ label: "0"; shiftedText: ")"; fnValue:"F10" }
FnSymbolKey{ label: "-"; shiftedText: "_"; fnValue:"F11" }
FnSymbolKey{ label: "="; shiftedText: "+"; fnValue:"F12" }
BackspaceKey{}
ActionKey{ label: "Esc"; height: virtualKeyboard.keyHeight * 3/4; keycode: Keycode.KEY_ESC}
SymbolKey{ label: "`"; shiftedText: "~"; height: virtualKeyboard.firstRowKeyHeight; keycode: Keycode.KEY_GRAVE }
FnSymbolKey{ label: "1"; shiftedText: "!"; fnValue:"F1"; fnKeycode: Keycode.KEY_F1; numberKeycode: Keycode.KEY_1 }
FnSymbolKey{ label: "2"; shiftedText: "@"; fnValue:"F2"; fnKeycode: Keycode.KEY_F2; numberKeycode: Keycode.KEY_2 }
FnSymbolKey{ label: "3"; shiftedText: "#"; fnValue:"F3"; fnKeycode: Keycode.KEY_F3; numberKeycode: Keycode.KEY_3 }
FnSymbolKey{ label: "4"; shiftedText: "$"; fnValue:"F4"; fnKeycode: Keycode.KEY_F4; numberKeycode: Keycode.KEY_4 }
FnSymbolKey{ label: "5"; shiftedText: "%"; fnValue:"F5"; fnKeycode: Keycode.KEY_F5; numberKeycode: Keycode.KEY_5 }
FnSymbolKey{ label: "6"; shiftedText: "^"; fnValue:"F6"; fnKeycode: Keycode.KEY_F6; numberKeycode: Keycode.KEY_6 }
FnSymbolKey{ label: "7"; shiftedText: "&"; fnValue:"F7"; fnKeycode: Keycode.KEY_F7; numberKeycode: Keycode.KEY_7 }
FnSymbolKey{ label: "8"; shiftedText: "*"; fnValue:"F8"; fnKeycode: Keycode.KEY_F8; numberKeycode: Keycode.KEY_8 }
FnSymbolKey{ label: "9"; shiftedText: "("; fnValue:"F9"; fnKeycode: Keycode.KEY_F9; numberKeycode: Keycode.KEY_9 }
FnSymbolKey{ label: "0"; shiftedText: ")"; fnValue:"F10"; fnKeycode: Keycode.KEY_F10; numberKeycode: Keycode.KEY_0 }
FnSymbolKey{ label: "-"; shiftedText: "_"; fnValue:"F11"; fnKeycode: Keycode.KEY_F11; numberKeycode: Keycode.KEY_MINUS }
FnSymbolKey{ label: "="; shiftedText: "+"; fnValue:"F12"; fnKeycode: Keycode.KEY_F12; numberKeycode: Keycode.KEY_EQUAL }
BackspaceKey{ keycode: Keycode.KEY_BACKSPACE }
}
Row {
anchors.horizontalCenter: parent.horizontalCenter
spacing: virtualKeyboard.keySpacing
ActionKey{ label: "Tab"; width: virtualKeyboard.keyWidth*1.5 + virtualKeyboard.keySpacing; alignment: Text.AlignLeft }
LetterKey{ label: "q"; shiftedText: "Q" }
LetterKey{ label: "w"; shiftedText: "W" }
LetterKey{ label: "e"; shiftedText: "E" }
LetterKey{ label: "r"; shiftedText: "R" }
LetterKey{ label: "t"; shiftedText: "T" }
LetterKey{ label: "y"; shiftedText: "Y" }
LetterKey{ label: "u"; shiftedText: "U" }
LetterKey{ label: "i"; shiftedText: "I" }
LetterKey{ label: "o"; shiftedText: "O" }
LetterKey{ label: "p"; shiftedText: "P" }
SymbolKey{ label: "["; shiftedText: "{" }
SymbolKey{ label: "]"; shiftedText: "}" }
SymbolKey{ label: "\\"; shiftedText: "|" }
ActionKey{ label: "Del" }
ActionKey{ label: "Tab"; width: virtualKeyboard.keyWidth*1.5 + virtualKeyboard.keySpacing; alignment: Text.AlignLeft; keycode: Keycode.KEY_TAB }
LetterKey{ label: "q"; shiftedText: "Q"; keycode: Keycode.KEY_Q }
LetterKey{ label: "w"; shiftedText: "W"; keycode: Keycode.KEY_W }
LetterKey{ label: "e"; shiftedText: "E"; keycode: Keycode.KEY_E }
LetterKey{ label: "r"; shiftedText: "R"; keycode: Keycode.KEY_R }
LetterKey{ label: "t"; shiftedText: "T"; keycode: Keycode.KEY_T }
LetterKey{ label: "y"; shiftedText: "Y"; keycode: Keycode.KEY_Y }
LetterKey{ label: "u"; shiftedText: "U"; keycode: Keycode.KEY_U }
LetterKey{ label: "i"; shiftedText: "I"; keycode: Keycode.KEY_I }
LetterKey{ label: "o"; shiftedText: "O"; keycode: Keycode.KEY_O }
LetterKey{ label: "p"; shiftedText: "P"; keycode: Keycode.KEY_P }
SymbolKey{ label: "["; shiftedText: "{"; keycode: Keycode.KEY_LEFTBRACE }
SymbolKey{ label: "]"; shiftedText: "}"; keycode: Keycode.KEY_RIGHTBRACE }
SymbolKey{ label: "\\"; shiftedText: "|"; keycode: Keycode.KEY_BACKSLASH }
ActionKey{ label: "Del"; keycode: Keycode.KEY_DELETE }
}
Row {
anchors.horizontalCenter: parent.horizontalCenter
spacing: virtualKeyboard.keySpacing
CapslockKey{width: virtualKeyboard.keyWidth*2 + virtualKeyboard.keySpacing; alignment: Text.AlignLeft }
LetterKey{ label: "a"; shiftedText: "A" }
LetterKey{ label: "s"; shiftedText: "S" }
LetterKey{ label: "d"; shiftedText: "D" }
LetterKey{ label: "f"; shiftedText: "F" }
LetterKey{ label: "g"; shiftedText: "G" }
LetterKey{ label: "h"; shiftedText: "H" }
LetterKey{ label: "j"; shiftedText: "J" }
LetterKey{ label: "k"; shiftedText: "K" }
LetterKey{ label: "l"; shiftedText: "L" }
SymbolKey{ label: ";"; shiftedText: ":" }
SymbolKey{ label: "'"; shiftedText: "\"" }
EnterKey{}
CapslockKey{width: virtualKeyboard.keyWidth*2 + virtualKeyboard.keySpacing; alignment: Text.AlignLeft; keycode: Keycode.KEY_CAPSLOCK }
LetterKey{ label: "a"; shiftedText: "A"; keycode: Keycode.KEY_A }
LetterKey{ label: "s"; shiftedText: "S"; keycode: Keycode.KEY_S }
LetterKey{ label: "d"; shiftedText: "D"; keycode: Keycode.KEY_D }
LetterKey{ label: "f"; shiftedText: "F"; keycode: Keycode.KEY_F }
LetterKey{ label: "g"; shiftedText: "G"; keycode: Keycode.KEY_G }
LetterKey{ label: "h"; shiftedText: "H"; keycode: Keycode.KEY_H }
LetterKey{ label: "j"; shiftedText: "J"; keycode: Keycode.KEY_J }
LetterKey{ label: "k"; shiftedText: "K"; keycode: Keycode.KEY_K }
LetterKey{ label: "l"; shiftedText: "L"; keycode: Keycode.KEY_L }
SymbolKey{ label: ";"; shiftedText: ":"; keycode: Keycode.KEY_SEMICOLON }
SymbolKey{ label: "'"; shiftedText: "\""; keycode: Keycode.KEY_APOSTROPHE }
EnterKey{ keycode: Keycode.KEY_ENTER }
}
Row {
anchors.horizontalCenter: parent.horizontalCenter
spacing: virtualKeyboard.keySpacing
ShiftKey{width: virtualKeyboard.keyWidth*2.5 + virtualKeyboard.keySpacing*2; alignment: Text.AlignLeft }
LetterKey{ label: "z" ; shiftedText: "Z" }
LetterKey{ label: "x" ; shiftedText: "X" }
LetterKey{ label: "c" ; shiftedText: "C" }
LetterKey{ label: "v" ; shiftedText: "V" }
LetterKey{ label: "b" ; shiftedText: "B" }
LetterKey{ label: "n" ; shiftedText: "N" }
LetterKey{ label: "m" ; shiftedText: "M" }
SymbolKey{ label: ","; shiftedText: "<" }
SymbolKey{ label: "."; shiftedText: ">" }
SymbolKey{ label: "/"; shiftedText: "?" }
ActionKey{ label: "up"; actionKeyImgPath: "qrc:/img/up.svg" }
ShiftKey{ width: virtualKeyboard.keyWidth*2 + virtualKeyboard.keySpacing; alignment: Text.AlignRight }
ShiftKey{width: virtualKeyboard.keyWidth*2.5 + virtualKeyboard.keySpacing*2; alignment: Text.AlignLeft; keycode: Keycode.KEY_LEFTSHIFT }
LetterKey{ label: "z" ; shiftedText: "Z"; keycode: Keycode.KEY_Z }
LetterKey{ label: "x" ; shiftedText: "X"; keycode: Keycode.KEY_X }
LetterKey{ label: "c" ; shiftedText: "C"; keycode: Keycode.KEY_C }
LetterKey{ label: "v" ; shiftedText: "V"; keycode: Keycode.KEY_V }
LetterKey{ label: "b" ; shiftedText: "B"; keycode: Keycode.KEY_B }
LetterKey{ label: "n" ; shiftedText: "N"; keycode: Keycode.KEY_N }
LetterKey{ label: "m" ; shiftedText: "M"; keycode: Keycode.KEY_M }
SymbolKey{ label: ", "; shiftedText: "<"; keycode: Keycode.KEY_COMMA }
SymbolKey{ label: "."; shiftedText: ">"; keycode: Keycode.KEY_DOT }
SymbolKey{ label: "/"; shiftedText: "?"; keycode: Keycode.KEY_SLASH }
ActionKey{ label: "up"; actionKeyImgPath: "qrc:/img/up.svg"; keycode: Keycode.KEY_UP }
ShiftKey{ width: virtualKeyboard.keyWidth*2 + virtualKeyboard.keySpacing; alignment: Text.AlignRight; keycode: Keycode.KEY_RIGHTSHIFT }
}
Row {
anchors.horizontalCenter: parent.horizontalCenter
spacing: virtualKeyboard.keySpacing
CtrlKey{}
CtrlKey{ keycode: Keycode.KEY_LEFTCTRL }
FnKey{}
//win
// WinKey{}
AltKey{}
AltKey{ keycode: Keycode.KEY_LEFTALT }
ChangeImKey{}
SpaceKey{}
AltKey{}
ActionKey{ label: "left"; actionKeyImgPath: "qrc:/img/left.svg" }
ActionKey{ label: "down"; actionKeyImgPath: "qrc:/img/down.svg" }
ActionKey{ label: "right"; actionKeyImgPath: "qrc:/img/right.svg" }
CtrlKey{}
SpaceKey{ keycode: Keycode.KEY_SPACE }
AltKey{ keycode: Keycode.KEY_RIGHTALT }
ActionKey{ label: "left"; actionKeyImgPath: "qrc:/img/left.svg"; keycode: Keycode.KEY_LEFT }
ActionKey{ label: "down"; actionKeyImgPath: "qrc:/img/down.svg"; keycode: Keycode.KEY_DOWN }
ActionKey{ label: "right"; actionKeyImgPath: "qrc:/img/right.svg"; keycode: Keycode.KEY_RIGHT }
CtrlKey{ keycode: Keycode.KEY_RIGHTCTRL }
}
}

93
qml/js/keycode.js Normal file
View File

@ -0,0 +1,93 @@
/*
* Copyright 2023 KylinSoft Co., Ltd.
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
const KEY_ESC = 9;
const KEY_1 = 10;
const KEY_2 = 11;
const KEY_3 = 12;
const KEY_4 = 13;
const KEY_5 = 14;
const KEY_6 = 15;
const KEY_7 = 16;
const KEY_8 = 17;
const KEY_9 = 18;
const KEY_0 = 19;
const KEY_MINUS = 20;
const KEY_EQUAL = 21;
const KEY_BACKSPACE = 22;
const KEY_TAB = 23;
const KEY_Q = 24;
const KEY_W = 25;
const KEY_E = 26;
const KEY_R = 27;
const KEY_T = 28;
const KEY_Y = 29;
const KEY_U = 30;
const KEY_I = 31;
const KEY_O = 32;
const KEY_P = 33;
const KEY_LEFTBRACE = 34;
const KEY_RIGHTBRACE = 35;
const KEY_ENTER = 36;
const KEY_LEFTCTRL = 37;
const KEY_A = 38;
const KEY_S = 39;
const KEY_D = 40;
const KEY_F = 41;
const KEY_G = 42;
const KEY_H = 43;
const KEY_J = 44;
const KEY_K = 45;
const KEY_L = 46;
const KEY_SEMICOLON = 47;
const KEY_APOSTROPHE = 48;
const KEY_GRAVE = 49;
const KEY_LEFTSHIFT = 50;
const KEY_BACKSLASH = 51;
const KEY_Z = 52;
const KEY_X = 53;
const KEY_C = 54;
const KEY_V = 55;
const KEY_B = 56;
const KEY_N = 57;
const KEY_M = 58;
const KEY_COMMA = 59;
const KEY_DOT = 60;
const KEY_SLASH = 61;
const KEY_RIGHTSHIFT = 62;
const KEY_LEFTALT = 64;
const KEY_SPACE = 65;
const KEY_CAPSLOCK = 66;
const KEY_F1 = 67;
const KEY_F2 = 68;
const KEY_F3 = 69;
const KEY_F4 = 70;
const KEY_F5 = 71;
const KEY_F6 = 72;
const KEY_F7 = 73;
const KEY_F8 = 74;
const KEY_F9 = 75;
const KEY_F10 = 76;
const KEY_F11 = 95;
const KEY_F12 = 96;
const KEY_RIGHTCTRL = 105;
const KEY_RIGHTALT = 108;
const KEY_UP = 111;
const KEY_LEFT = 113;
const KEY_RIGHT = 114;
const KEY_DOWN = 116;
const KEY_DELETE = 119;

View File

@ -36,14 +36,11 @@ function getModifierKeyStates(){
return result
}
function getKeyCode(keyName){
var keyCodeList = {
function getKeysymByKeyLabel(keyLabel) {
var keysymMap = {
"esc": 0xff1b,
"tab": 0xff09,
"caps": 0xffe5,
"shift": 0xffe1,
"ctrl": 0xffe3,
"alt": 0xffe9,
"win": 0xffeb,
"backspace": 0xff08,
"enter": 0xff0d,
@ -66,13 +63,32 @@ function getKeyCode(keyName){
"f11": 0xffc8,
"f12": 0xffc9
}
if(keyCodeList.hasOwnProperty(keyName.toLowerCase())){
return keyCodeList[keyName.toLowerCase()]
}else{
return keyName[0].charCodeAt(0)
if (keysymMap.hasOwnProperty(keyLabel.toLowerCase())) {
return keysymMap[keyLabel.toLowerCase()]
}
return keyLabel[0].charCodeAt(0)
}
function getKeysymByKeycode(keycode) {
var keysymMap = {
"50": 0xffe1, // Shift_L
"62": 0xffe2, // Shift_R
"37": 0xffe3, // Ctrl_L
"105": 0xffe4, // Ctrl_R
"64": 0xffe9, // Alt_L
"108": 0xffea // Alt_R
}
if (keysymMap.hasOwnProperty(keycode)) {
return keysymMap[keycode]
}
return 0;
}

View File

@ -20,6 +20,7 @@ import QtQuick.Controls 2.0
import QtGraphicalEffects 1.0
ToolButton {
property int keycode
width: virtualKeyboard.keyWidth
height: virtualKeyboard.keyHeight
property string label: ""

View File

@ -28,9 +28,11 @@ SwitchKey {
} else {
virtualKeyboard.capslockState = "NORMAL"
}
var keysym = Utils.getKeysymByKeyLabel(label)
var modifierKeyState = Utils.getModifierKeyStates()
virtualKeyboard.processKeyEvent(label, Utils.getKeyCode(label), modifierKeyState, false, Date())
virtualKeyboard.processKeyEvent(label, Utils.getKeyCode(label), modifierKeyState, true, Date())
virtualKeyboard.processKeyEvent(keysym, keycode, modifierKeyState, false, Date())
virtualKeyboard.processKeyEvent(keysym, keycode, modifierKeyState, true, Date())
}
state: virtualKeyboard.capslockState

View File

@ -25,6 +25,20 @@ BaseKey {
property color pressedColor: virtualKeyboard.charKeyPressedColor
property color hoverColor: virtualKeyboard.charKeyHoverColor
function sendKeyEvent(isRelease) {
var keysym = Utils.getKeysymByKeyLabel(keyLabel.text)
var modifierKeyState = Utils.getModifierKeyStates()
virtualKeyboard.processKeyEvent(keysym, keycode, modifierKeyState, isRelease, Date())
}
function sendKeyPressEvent() {
sendKeyEvent(false)
}
function sendKeyReleaseEvent() {
sendKeyEvent(true);
}
MouseArea {
id: keyMouseArea
anchors.fill: parent
@ -33,15 +47,14 @@ BaseKey {
onReleased: {
keyBackground.state = "NORMAL"
timer.stop()
var modifierKeyState = Utils.getModifierKeyStates()
var keycode = Utils.getKeyCode(keyLabel.text)
virtualKeyboard.processKeyEvent(keyLabel.text, keycode, modifierKeyState, false, Date())
sendKeyReleaseEvent()
charKeyClicked()
}
onPressed: {
keyBackground.state = "PRESSED"
timer.start()
sendKeyPressEvent()
}
onEntered: {
@ -93,8 +106,7 @@ BaseKey {
interval: virtualKeyboard.longPressInterval
repeat: true
onTriggered: {
var modifierKeyState = Utils.getModifierKeyStates()
virtualKeyboard.processKeyEvent(keyLabel.text, Utils.getKeyCode(keyLabel.text), modifierKeyState, false, Date())
sendKeyPressEvent()
}
}
}

View File

@ -21,7 +21,11 @@ SymbolKey {
height: virtualKeyboard.firstRowKeyHeight
property string fnValue
property int fnKeycode
property int numberKeycode
keycode: virtualKeyboard.fnSymbolState == "FN" ? fnKeycode : numberKeycode
fontSize: virtualKeyboard.fnSymbolKeyFontSize
state: virtualKeyboard.fnSymbolState

View File

@ -27,12 +27,18 @@ SwitchKey {
switchKeyState = "OPEN"
} else {
switchKeyState = "NORMAL"
var keysym = Utils.getKeysymByKeycode(keycode);
var modifierKeyState = Utils.getModifierKeyStates()
virtualKeyboard.processKeyEvent(label, Utils.getKeyCode(label), modifierKeyState - Utils.getKeySym(label), false, Date())
virtualKeyboard.processKeyEvent(label, Utils.getKeyCode(label), modifierKeyState, true, Date())
virtualKeyboard.processKeyEvent(keysym, keycode, modifierKeyState, true, Date())
temporarySwitchKeyClicked()
}
temporarySwitchKeyReleased(switchKeyState)
}
keyMouseArea.onPressed: {
var keysym = Utils.getKeysymByKeycode(keycode);
var modifierKeyState = Utils.getModifierKeyStates()
virtualKeyboard.processKeyEvent(keysym, keycode, modifierKeyState - Utils.getKeySym(label), false, Date())
}
}

View File

@ -40,12 +40,11 @@ void VirtualKeyboardModel::setCurrentIM(const QString &imName) {
fcitx5Controller_->SetCurrentIM(imName);
}
void VirtualKeyboardModel::processKeyEvent(const QString & /*keyval*/,
int keycode, int state,
void VirtualKeyboardModel::processKeyEvent(int keysym, int keycode, int state,
bool isRelease, int time) {
virtualKeyboardBackendInterface_->asyncCall(
"ProcessKeyEvent", (uint)keycode, (uint)keycode, (uint)state, isRelease,
(uint)time);
virtualKeyboardBackendInterface_->asyncCall("ProcessKeyEvent", (uint)keysym,
(uint)keycode, (uint)state,
isRelease, (uint)time);
}
void VirtualKeyboardModel::initFcitx5Controller() {

View File

@ -54,8 +54,8 @@ public:
public:
Q_INVOKABLE void selectCandidate(int index);
Q_INVOKABLE void setCurrentIM(const QString &imName);
Q_INVOKABLE void processKeyEvent(const QString &keyval, int keycode,
int state, bool isRelease, int time);
Q_INVOKABLE void processKeyEvent(int keysym, int keycode, int state,
bool isRelease, int time);
signals:
void updatePreeditCaret(int index);