From 7b6ac91dea7c3c59d3111d0607302e17d8fa1ffc Mon Sep 17 00:00:00 2001 From: liuyuanpeng Date: Wed, 12 Apr 2023 13:44:06 +0800 Subject: [PATCH] fix(keyboard): use QCoreApplication::sendEvent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Description:wayland下采用QCoreApplication::sendEvent方式来模拟按键事件 Log:https://gitee.com/openkylin/ukui-screensaver/issues/I5XAG9?from=project-issue --- VirtualKeyboard/CMakeLists.txt | 4 +- VirtualKeyboard/src/fakekeyboard.h | 114 +++++++++++++ VirtualKeyboard/src/keyboardwidget.cpp | 9 +- VirtualKeyboard/src/keyboardwidget.h | 4 +- VirtualKeyboard/src/qtkeyboard.cpp | 222 +++++++++++++++++++++++++ VirtualKeyboard/src/qtkeyboard.h | 49 ++++++ VirtualKeyboard/src/x11keyboard.cpp | 6 +- VirtualKeyboard/src/x11keyboard.h | 71 +------- src/fullbackgroundwidget.cpp | 3 - src/lockwidget.cpp | 8 +- 10 files changed, 405 insertions(+), 85 deletions(-) create mode 100644 VirtualKeyboard/src/fakekeyboard.h create mode 100644 VirtualKeyboard/src/qtkeyboard.cpp create mode 100644 VirtualKeyboard/src/qtkeyboard.h diff --git a/VirtualKeyboard/CMakeLists.txt b/VirtualKeyboard/CMakeLists.txt index 3c8a010..9f5355d 100644 --- a/VirtualKeyboard/CMakeLists.txt +++ b/VirtualKeyboard/CMakeLists.txt @@ -9,6 +9,7 @@ qt5_add_resources(VirtualKeyboard_SRC qt5_wrap_cpp(VirtualKeyboard_SRC src/vkstackedwidget.h + src/fakekeyboard.h ) set(VirtualKeyboard_SRC @@ -17,6 +18,7 @@ set(VirtualKeyboard_SRC src/keyboardwidget.cpp src/virtualkeyboard.cpp src/x11keyboard.cpp + src/qtkeyboard.cpp src/vkstackedwidget.cpp src/keyboard.qrc) @@ -26,4 +28,4 @@ include_directories( ) add_library(VirtualKeyboard STATIC ${VirtualKeyboard_SRC}) -target_link_libraries(VirtualKeyboard Qt5::Core Qt5::Widgets) +target_link_libraries(VirtualKeyboard Qt5::Core Qt5::Widgets Qt5::X11Extras) diff --git a/VirtualKeyboard/src/fakekeyboard.h b/VirtualKeyboard/src/fakekeyboard.h new file mode 100644 index 0000000..578e047 --- /dev/null +++ b/VirtualKeyboard/src/fakekeyboard.h @@ -0,0 +1,114 @@ +/** + * Copyright (C) 2018 Tianjin KYLIN Information Technology 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 2, 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301, USA. +**/ +#ifndef FAKEKEYBOARD_H +#define FAKEKEYBOARD_H + +#include +#include + +class Modifier : public QObject +{ + Q_OBJECT +public: + Modifier(){} + + enum MOD{ + UNKNOWN = -1, + CTRL, + SHIFT, + ALT, + SUPER + }; + Q_ENUM(MOD) + + static QString getModifierName(int mod) + { + QMetaEnum metaEnum = QMetaEnum::fromType(); + const char* modName = metaEnum.valueToKey(mod); + QString result = QString(modName).toLower(); + return result; + } + static MOD getModifier(const QString &modName) + { + QMetaEnum metaEnum = QMetaEnum::fromType(); + MOD mod = (MOD)metaEnum.keyToValue(modName.toUpper().toLocal8Bit().data()); + return mod; + } +}; + +class FuncKey : public QObject +{ + Q_OBJECT +public: + FuncKey(){} + + enum FUNCKEY { + UNKNOWN = -1, + SPACE = 0, + BACKSPACE, + ENTER, + HOME, + END, + PGUP, + PGDN, + INSERT, + DELETE, + UP, + DOWN, + LEFT, + RIGHT + }; + Q_ENUM(FUNCKEY) + static QString getKeyName(int key) + { + QMetaEnum metaEnum = QMetaEnum::fromType(); + const char* keyName = metaEnum.valueToKey(key); + QString result = QString(keyName).toLower(); + return result; + } + static FUNCKEY getKey(const QString &keyName) + { + QMetaEnum metaEnum = QMetaEnum::fromType(); + FUNCKEY key = (FUNCKEY)metaEnum.keyToValue(keyName.toUpper().toLocal8Bit().data()); + return key; + } +}; + +class FakeKeyboard : public QObject +{ + Q_OBJECT +public: + explicit FakeKeyboard(QObject *parent = nullptr) + : QObject(parent) + { + + } + + virtual void addModifier(Modifier::MOD mod) = 0; + virtual void removeModifier(Modifier::MOD mod) = 0; + virtual bool hasModifier(Modifier::MOD mod) = 0; + virtual QList getAllModifier() = 0; + virtual void clearModifier() = 0; + +public Q_SLOTS: + virtual void onKeyPressed(QChar c) = 0; + virtual void onKeyPressed(FuncKey::FUNCKEY key) = 0; +}; + +#endif // FAKEKEYBOARD_H diff --git a/VirtualKeyboard/src/keyboardwidget.cpp b/VirtualKeyboard/src/keyboardwidget.cpp index e97a710..1847d4f 100644 --- a/VirtualKeyboard/src/keyboardwidget.cpp +++ b/VirtualKeyboard/src/keyboardwidget.cpp @@ -21,6 +21,9 @@ #include #include #include +#include +#include "x11keyboard.h" +#include "qtkeyboard.h" #define SYMBOL_KEY_COUNT 29 #define SYMBOL_PAGE_COUNT 2 @@ -47,7 +50,11 @@ KeyboardWidget::KeyboardWidget(QWidget *parent) : isShift(false), page(0) { - vKeyboard = new X11Keyboard(this); + if(QX11Info::isPlatformX11()){ + vKeyboard = new X11Keyboard(this); + }else{ + vKeyboard = new QtKeyboard(this); + } connect(this, SIGNAL(keyPressed(QChar)), vKeyboard, SLOT(onKeyPressed(QChar))); connect(this, SIGNAL(keyPressed(FuncKey::FUNCKEY)), diff --git a/VirtualKeyboard/src/keyboardwidget.h b/VirtualKeyboard/src/keyboardwidget.h index 25591ae..1e48074 100644 --- a/VirtualKeyboard/src/keyboardwidget.h +++ b/VirtualKeyboard/src/keyboardwidget.h @@ -22,7 +22,7 @@ #include #include #include -#include "x11keyboard.h" +#include "fakekeyboard.h" namespace Ui { class KeyboardWidget; @@ -71,7 +71,7 @@ private: bool isShift; QTime shiftLastClicked; //shift键上次被点击的时间 int page; //当前是第几页的键盘 - X11Keyboard *vKeyboard; + FakeKeyboard *vKeyboard; }; #endif // KEYBOARDWIDGET_H diff --git a/VirtualKeyboard/src/qtkeyboard.cpp b/VirtualKeyboard/src/qtkeyboard.cpp new file mode 100644 index 0000000..4db7a76 --- /dev/null +++ b/VirtualKeyboard/src/qtkeyboard.cpp @@ -0,0 +1,222 @@ +/** + * Copyright (C) 2018 Tianjin KYLIN Information Technology 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 2, 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301, USA. +**/ +#include "qtkeyboard.h" +#include +#include +#include +#include +#include +#include + +QMap m_specialSymbolMap = { + {' ', Qt::Key_Space}, + {',', Qt::Key_Comma}, + {'.', Qt::Key_Period}, + {'\'', Qt::Key_QuoteLeft}, + {'@', Qt::Key_At}, + {'#', Qt::Key_NumberSign}, + {'$', Qt::Key_Dollar}, + {'%', Qt::Key_Percent}, + {'&', Qt::Key_Ampersand}, + {'*', Qt::Key_Asterisk}, + {'(', Qt::Key_ParenLeft}, + {')', Qt::Key_ParenRight}, + {'-', Qt::Key_Minus}, + {'+', Qt::Key_Plus}, + {'!', Qt::Key_Exclam}, + {'"', Qt::Key_QuoteDbl}, + {'<', Qt::Key_Less}, + {'>', Qt::Key_Greater}, + {':', Qt::Key_Colon}, + {';', Qt::Key_Semicolon}, + {'/', Qt::Key_Slash}, + {'?', Qt::Key_Question}, + {'=', Qt::Key_Equal}, + {'.', Qt::Key_Period}, /*XK_kana_middledot*/ + {'~', Qt::Key_AsciiTilde}, + {'`', Qt::Key_QuoteLeft}, + {'|', Qt::Key_Bar}, + {'^', Qt::Key_AsciiCircum}, + {'{', Qt::Key_BraceLeft}, + {'}', Qt::Key_BraceRight}, + {'[', Qt::Key_BracketLeft}, + {']', Qt::Key_BracketRight}, + {'_', Qt::Key_Underscore}, + {'\\', Qt::Key_Backslash}, +}; + +QMap m_funckeyMap = { + {FuncKey::SPACE, Qt::Key_Space}, + {FuncKey::BACKSPACE, Qt::Key_Backspace}, + {FuncKey::ENTER, Qt::Key_Enter}, + {FuncKey::HOME, Qt::Key_Home}, + {FuncKey::END, Qt::Key_End}, + {FuncKey::PGUP, Qt::Key_PageUp}, + {FuncKey::PGDN, Qt::Key_PageDown}, + {FuncKey::INSERT, Qt::Key_Insert}, + {FuncKey::DELETE, Qt::Key_Delete}, + {FuncKey::UP, Qt::Key_Up}, + {FuncKey::DOWN, Qt::Key_Down}, + {FuncKey::LEFT, Qt::Key_Left}, + {FuncKey::RIGHT, Qt::Key_Right} +}; + +QMap m_modifierMap = { + {Modifier::CTRL, Qt::ControlModifier}, + {Modifier::ALT, Qt::AltModifier}, + {Modifier::SUPER, Qt::MetaModifier}, + {Modifier::SHIFT, Qt::ShiftModifier} +}; + +QVector m_shiftKeyVec = {'~', '!', '@', '#', '$', '%', '^', '&', '*', + '(', ')', '_', '+', '{', '}', '|', ':', '"', + '>', '?'}; + +#define DRM_DIR "/sys/class/leds/" +#define CAPSLOCK_STATUS "capslock_state" + +/** + * @brief 判断大写键状态 + * @return true: 大写锁定 + */ +bool checkCapsLockState() +{ + QDir ledDir(DRM_DIR); + QStringList leds = ledDir.entryList(QDir::Dirs); + QString capsFile; + + for(int i = 0;i QtKeyboard::getAllModifier() +{ + return modList; +} + +void QtKeyboard::clearModifier() +{ + modList.clear(); +} + + +void QtKeyboard::onKeyPressed(QChar c) +{ + /*判断大写锁定打开时,转换字母大小写状态,与x11keyboard类逻辑保持一致*/ + if(checkCapsLockState() && c.isLetter()){ + if(c.isUpper()){ + c = c.toLower(); + } + else if(c.isLower()){ + c = c.toUpper(); + } + } + + if(c>='A' && c<='Z'){ + sendKey(c.toLatin1(),c); + }else if(c>='a' && c<='z'){ + sendKey(c.toLatin1() - 32,c); + }else if(c >= '0' && c<='9'){ + sendKey(c.toLatin1(),c); + }else if(m_specialSymbolMap.contains(c)){ + sendKey(m_specialSymbolMap[c],c); + }else { + sendKey(c.toLatin1(),c); + } +} + +void QtKeyboard::onKeyPressed(FuncKey::FUNCKEY key) +{ + int keysym = m_funckeyMap[key]; + /*这里的text根据实际按键得到的QEvent中的text内容打印*/ + if(key == FuncKey::SPACE){ + sendKey(keysym," "); + }else if(key == FuncKey::BACKSPACE){ + sendKey(keysym,"\b"); + }else if(key == FuncKey::ENTER){ + sendKey(keysym,"\r"); + }else if(key == FuncKey::INSERT){ + sendKey(keysym,"\u007F"); + }else{ + sendKey(keysym,""); + } +} + +void QtKeyboard::sendKey(const unsigned int keysym,const QString text) +{ + Qt::KeyboardModifiers modifier = Qt::NoModifier; + for(auto mod : modList){ + modifier = modifier | m_modifierMap[mod]; + } + + QWidget *objfous = QApplication::focusWidget(); + + if(objfous){ + QKeyEvent event1(QEvent::KeyPress, keysym + , modifier, text + , true, 1); + QKeyEvent event2(QEvent::KeyRelease, keysym + , modifier, text + , true, 1); + QCoreApplication::sendEvent(objfous, &event1); + QCoreApplication::sendEvent(objfous, &event2); + } + +} diff --git a/VirtualKeyboard/src/qtkeyboard.h b/VirtualKeyboard/src/qtkeyboard.h new file mode 100644 index 0000000..117fa58 --- /dev/null +++ b/VirtualKeyboard/src/qtkeyboard.h @@ -0,0 +1,49 @@ +/** + * Copyright (C) 2018 Tianjin KYLIN Information Technology 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 2, 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301, USA. +**/ +#ifndef QTKEYBOARD_H +#define QTKEYBOARD_H + +#include +#include +#include "fakekeyboard.h" + +class QtKeyboard : public FakeKeyboard +{ + Q_OBJECT +public: + explicit QtKeyboard(QObject *parent = nullptr); + ~QtKeyboard(); + void addModifier(Modifier::MOD mod); + void removeModifier(Modifier::MOD mod); + bool hasModifier(Modifier::MOD mod); + QList getAllModifier(); + void clearModifier(); + +public Q_SLOTS: + void onKeyPressed(QChar c); + void onKeyPressed(FuncKey::FUNCKEY key); + +private: + void sendKey(const unsigned int keyCode,const QString text); + +private: + QList modList; +}; + +#endif // QTKEYBOARD_H diff --git a/VirtualKeyboard/src/x11keyboard.cpp b/VirtualKeyboard/src/x11keyboard.cpp index 5e160ed..c396837 100644 --- a/VirtualKeyboard/src/x11keyboard.cpp +++ b/VirtualKeyboard/src/x11keyboard.cpp @@ -22,8 +22,6 @@ #include #include - - struct CharMap { QChar name; KeySym code; @@ -36,7 +34,7 @@ struct CharMap XSpecialSymbolMap[] { {'\'', XK_quoteright}, {'@', XK_at}, {'#', XK_numbersign}, - {'$', XK_dollar}, + {'$', XK_dollar}, {'%', XK_percent}, {'&', XK_ampersand}, {'*', XK_asterisk}, @@ -123,7 +121,7 @@ unsigned int keyCodeOfChar(QChar c) } X11Keyboard::X11Keyboard(QObject *parent) - : QObject(parent) + : FakeKeyboard(parent) { } diff --git a/VirtualKeyboard/src/x11keyboard.h b/VirtualKeyboard/src/x11keyboard.h index 42fd997..8116fd3 100644 --- a/VirtualKeyboard/src/x11keyboard.h +++ b/VirtualKeyboard/src/x11keyboard.h @@ -21,76 +21,9 @@ #include #include +#include "fakekeyboard.h" -class Modifier : public QObject -{ - Q_OBJECT -public: - Modifier(){} - - enum MOD{ - UNKNOWN = -1, - CTRL, - SHIFT, - ALT, - SUPER - }; - Q_ENUM(MOD) - - static QString getModifierName(int mod) - { - QMetaEnum metaEnum = QMetaEnum::fromType(); - const char* modName = metaEnum.valueToKey(mod); - QString result = QString(modName).toLower(); - return result; - } - static MOD getModifier(const QString &modName) - { - QMetaEnum metaEnum = QMetaEnum::fromType(); - MOD mod = (MOD)metaEnum.keyToValue(modName.toUpper().toLocal8Bit().data()); - return mod; - } -}; - -class FuncKey : public QObject -{ - Q_OBJECT -public: - FuncKey(){} - - enum FUNCKEY { - UNKNOWN = -1, - SPACE = 0, - BACKSPACE, - ENTER, - HOME, - END, - PGUP, - PGDN, - INSERT, - DELETE, - UP, - DOWN, - LEFT, - RIGHT - }; - Q_ENUM(FUNCKEY) - static QString getKeyName(int key) - { - QMetaEnum metaEnum = QMetaEnum::fromType(); - const char* keyName = metaEnum.valueToKey(key); - QString result = QString(keyName).toLower(); - return result; - } - static FUNCKEY getKey(const QString &keyName) - { - QMetaEnum metaEnum = QMetaEnum::fromType(); - FUNCKEY key = (FUNCKEY)metaEnum.keyToValue(keyName.toUpper().toLocal8Bit().data()); - return key; - } -}; - -class X11Keyboard : public QObject +class X11Keyboard : public FakeKeyboard { Q_OBJECT public: diff --git a/src/fullbackgroundwidget.cpp b/src/fullbackgroundwidget.cpp index 3e4e421..4486055 100644 --- a/src/fullbackgroundwidget.cpp +++ b/src/fullbackgroundwidget.cpp @@ -566,7 +566,6 @@ bool FullBackgroundWidget::nativeEventFilter(const QByteArray &eventType, void * //onGlobalKeyPress(xc->detail); } else if (responseType == XCB_KEY_RELEASE) { xcb_key_release_event_t *xc = reinterpret_cast(event); - qDebug()<<"---------------------XCB_KEY_RELEASE:"<detail; onGlobalKeyRelease(xc->detail); } else if(responseType == XCB_GE_GENERIC){ xcb_ge_generic_event_t *xc = reinterpret_cast(event); @@ -580,14 +579,12 @@ bool FullBackgroundWidget::nativeEventFilter(const QByteArray &eventType, void * int x = xc->root_x; int y = xc->root_y; onGlobalButtonPressed(x, y); - qDebug()<<"---------------------XCB_BUTTON_PRESS:"<(event); int x = xc->root_x; int y = xc->root_y; onGlobalButtonDrag(x, y); - qDebug()<<"---------------------XCB_MOTION_NOTIFY:"<setCursor(Qt::ArrowCursor); }); - if(QX11Info::isPlatformX11()){ +// if(QX11Info::isPlatformX11()){ //虚拟键盘 ui->btnKeyboard->setIcon(QIcon(":/image/assets/keyboard.svg")); ui->btnKeyboard->setFixedSize(48, 48); @@ -832,10 +832,11 @@ void LockWidget::initUI() connect(ui->btnKeyboard, &QPushButton::clicked, this, &LockWidget::showVirtualKeyboard); +/* } else { ui->btnKeyboard->hide(); } - +*/ //用户切换 if(displayManager->canSwitch()) { @@ -875,9 +876,6 @@ void LockWidget::netInPutStatus() void LockWidget::showVirtualKeyboard() { - if (!QX11Info::isPlatformX11()) { - return ; - } tabAt = LINEEDIT; setBottomBtnSheet(); tabAt = BOTTMBTN;