!21 解决屏幕键盘无法使用的问题

Merge pull request !21 from 刘远鹏/openkylin/yangtze
This commit is contained in:
杨敏 2023-04-12 06:03:38 +00:00 committed by Gitee
commit d8c01d07a4
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
10 changed files with 405 additions and 85 deletions

View File

@ -9,6 +9,7 @@ qt5_add_resources(VirtualKeyboard_SRC
qt5_wrap_cpp(VirtualKeyboard_SRC qt5_wrap_cpp(VirtualKeyboard_SRC
src/vkstackedwidget.h src/vkstackedwidget.h
src/fakekeyboard.h
) )
set(VirtualKeyboard_SRC set(VirtualKeyboard_SRC
@ -17,6 +18,7 @@ set(VirtualKeyboard_SRC
src/keyboardwidget.cpp src/keyboardwidget.cpp
src/virtualkeyboard.cpp src/virtualkeyboard.cpp
src/x11keyboard.cpp src/x11keyboard.cpp
src/qtkeyboard.cpp
src/vkstackedwidget.cpp src/vkstackedwidget.cpp
src/keyboard.qrc) src/keyboard.qrc)
@ -26,4 +28,4 @@ include_directories(
) )
add_library(VirtualKeyboard STATIC ${VirtualKeyboard_SRC}) add_library(VirtualKeyboard STATIC ${VirtualKeyboard_SRC})
target_link_libraries(VirtualKeyboard Qt5::Core Qt5::Widgets) target_link_libraries(VirtualKeyboard Qt5::Core Qt5::Widgets Qt5::X11Extras)

View File

@ -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 <QObject>
#include <QMetaEnum>
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<Modifier::MOD>();
const char* modName = metaEnum.valueToKey(mod);
QString result = QString(modName).toLower();
return result;
}
static MOD getModifier(const QString &modName)
{
QMetaEnum metaEnum = QMetaEnum::fromType<Modifier::MOD>();
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<FuncKey::FUNCKEY>();
const char* keyName = metaEnum.valueToKey(key);
QString result = QString(keyName).toLower();
return result;
}
static FUNCKEY getKey(const QString &keyName)
{
QMetaEnum metaEnum = QMetaEnum::fromType<FuncKey::FUNCKEY>();
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<Modifier::MOD> 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

View File

@ -20,6 +20,9 @@
#include <QDebug> #include <QDebug>
#include <QMap> #include <QMap>
#include <QVector> #include <QVector>
#include <QX11Info>
#include "x11keyboard.h"
#include "qtkeyboard.h"
#define SYMBOL_KEY_COUNT 29 #define SYMBOL_KEY_COUNT 29
#define SYMBOL_PAGE_COUNT 2 #define SYMBOL_PAGE_COUNT 2
@ -46,7 +49,11 @@ KeyboardWidget::KeyboardWidget(QWidget *parent) :
isShift(false), isShift(false),
page(0) page(0)
{ {
vKeyboard = new X11Keyboard(this); if(QX11Info::isPlatformX11()){
vKeyboard = new X11Keyboard(this);
}else{
vKeyboard = new QtKeyboard(this);
}
connect(this, SIGNAL(keyPressed(QChar)), connect(this, SIGNAL(keyPressed(QChar)),
vKeyboard, SLOT(onKeyPressed(QChar))); vKeyboard, SLOT(onKeyPressed(QChar)));
connect(this, SIGNAL(keyPressed(FuncKey::FUNCKEY)), connect(this, SIGNAL(keyPressed(FuncKey::FUNCKEY)),

View File

@ -21,7 +21,7 @@
#include <QWidget> #include <QWidget>
#include <QMap> #include <QMap>
#include <QTime> #include <QTime>
#include "x11keyboard.h" #include "fakekeyboard.h"
namespace Ui { namespace Ui {
class KeyboardWidget; class KeyboardWidget;
@ -70,7 +70,7 @@ private:
bool isShift; bool isShift;
QTime shiftLastClicked; //shift键上次被点击的时间 QTime shiftLastClicked; //shift键上次被点击的时间
int page; //当前是第几页的键盘 int page; //当前是第几页的键盘
X11Keyboard *vKeyboard; FakeKeyboard *vKeyboard;
}; };
#endif // KEYBOARDWIDGET_H #endif // KEYBOARDWIDGET_H

View File

@ -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 <QDebug>
#include <QWidget>
#include <QKeyEvent>
#include <QDir>
#include <QApplication>
#include <QCoreApplication>
QMap<QChar,int> 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<FuncKey::FUNCKEY, int> 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<Modifier::MOD, Qt::KeyboardModifier> m_modifierMap = {
{Modifier::CTRL, Qt::ControlModifier},
{Modifier::ALT, Qt::AltModifier},
{Modifier::SUPER, Qt::MetaModifier},
{Modifier::SHIFT, Qt::ShiftModifier}
};
QVector<QChar> 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<leds.count();i++){
if(leds.at(i).contains("capslock"))
capsFile = leds.at(i);
}
QFile drmStatusFile(DRM_DIR + capsFile + "/brightness");
if(drmStatusFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
QTextStream in(&drmStatusFile);
QString status = in.readLine();
if(status == "0") {
return false;
}else{
return true;
}
}
return false;
}
QtKeyboard::QtKeyboard(QObject *parent)
: FakeKeyboard(parent)
{
}
QtKeyboard::~QtKeyboard()
{
}
void QtKeyboard::addModifier(Modifier::MOD mod)
{
modList.push_back(mod);
}
void QtKeyboard::removeModifier(Modifier::MOD mod)
{
modList.removeOne(mod);
}
bool QtKeyboard::hasModifier(Modifier::MOD mod)
{
return modList.contains(mod);
}
QList<Modifier::MOD> 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);
}
}

View File

@ -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 <QObject>
#include <QMetaEnum>
#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<Modifier::MOD> 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<Modifier::MOD> modList;
};
#endif // QTKEYBOARD_H

View File

@ -21,8 +21,6 @@
#include <X11/keysym.h> #include <X11/keysym.h>
#include <X11/extensions/XTest.h> #include <X11/extensions/XTest.h>
struct CharMap { struct CharMap {
QChar name; QChar name;
KeySym code; KeySym code;
@ -35,7 +33,7 @@ struct CharMap XSpecialSymbolMap[] {
{'\'', XK_quoteright}, {'\'', XK_quoteright},
{'@', XK_at}, {'@', XK_at},
{'#', XK_numbersign}, {'#', XK_numbersign},
{'$', XK_dollar}, {'$', XK_dollar},
{'%', XK_percent}, {'%', XK_percent},
{'&', XK_ampersand}, {'&', XK_ampersand},
{'*', XK_asterisk}, {'*', XK_asterisk},
@ -122,7 +120,7 @@ unsigned int keyCodeOfChar(QChar c)
} }
X11Keyboard::X11Keyboard(QObject *parent) X11Keyboard::X11Keyboard(QObject *parent)
: QObject(parent) : FakeKeyboard(parent)
{ {
} }

View File

@ -20,76 +20,9 @@
#include <QObject> #include <QObject>
#include <QMetaEnum> #include <QMetaEnum>
#include "fakekeyboard.h"
class Modifier : public QObject class X11Keyboard : public FakeKeyboard
{
Q_OBJECT
public:
Modifier(){}
enum MOD{
UNKNOWN = -1,
CTRL,
SHIFT,
ALT,
SUPER
};
Q_ENUM(MOD)
static QString getModifierName(int mod)
{
QMetaEnum metaEnum = QMetaEnum::fromType<Modifier::MOD>();
const char* modName = metaEnum.valueToKey(mod);
QString result = QString(modName).toLower();
return result;
}
static MOD getModifier(const QString &modName)
{
QMetaEnum metaEnum = QMetaEnum::fromType<Modifier::MOD>();
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<FuncKey::FUNCKEY>();
const char* keyName = metaEnum.valueToKey(key);
QString result = QString(keyName).toLower();
return result;
}
static FUNCKEY getKey(const QString &keyName)
{
QMetaEnum metaEnum = QMetaEnum::fromType<FuncKey::FUNCKEY>();
FUNCKEY key = (FUNCKEY)metaEnum.keyToValue(keyName.toUpper().toLocal8Bit().data());
return key;
}
};
class X11Keyboard : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:

View File

@ -566,7 +566,6 @@ bool FullBackgroundWidget::nativeEventFilter(const QByteArray &eventType, void *
//onGlobalKeyPress(xc->detail); //onGlobalKeyPress(xc->detail);
} else if (responseType == XCB_KEY_RELEASE) { } else if (responseType == XCB_KEY_RELEASE) {
xcb_key_release_event_t *xc = reinterpret_cast<xcb_key_release_event_t*>(event); xcb_key_release_event_t *xc = reinterpret_cast<xcb_key_release_event_t*>(event);
qDebug()<<"---------------------XCB_KEY_RELEASE:"<<xc->detail;
onGlobalKeyRelease(xc->detail); onGlobalKeyRelease(xc->detail);
} else if(responseType == XCB_GE_GENERIC){ } else if(responseType == XCB_GE_GENERIC){
xcb_ge_generic_event_t *xc = reinterpret_cast<xcb_ge_generic_event_t*>(event); xcb_ge_generic_event_t *xc = reinterpret_cast<xcb_ge_generic_event_t*>(event);
@ -580,14 +579,12 @@ bool FullBackgroundWidget::nativeEventFilter(const QByteArray &eventType, void *
int x = xc->root_x; int x = xc->root_x;
int y = xc->root_y; int y = xc->root_y;
onGlobalButtonPressed(x, y); onGlobalButtonPressed(x, y);
qDebug()<<"---------------------XCB_BUTTON_PRESS:"<<x<<","<<y;
} else if (responseType == XCB_BUTTON_RELEASE) { } else if (responseType == XCB_BUTTON_RELEASE) {
} else if (responseType == XCB_MOTION_NOTIFY) { //此处获取的是窗口外的鼠标移动 } else if (responseType == XCB_MOTION_NOTIFY) { //此处获取的是窗口外的鼠标移动
xcb_motion_notify_event_t *xc = reinterpret_cast<xcb_motion_notify_event_t*>(event); xcb_motion_notify_event_t *xc = reinterpret_cast<xcb_motion_notify_event_t*>(event);
int x = xc->root_x; int x = xc->root_x;
int y = xc->root_y; int y = xc->root_y;
onGlobalButtonDrag(x, y); onGlobalButtonDrag(x, y);
qDebug()<<"---------------------XCB_MOTION_NOTIFY:"<<x<<","<<y;
} }
return false; return false;
} }

View File

@ -814,7 +814,7 @@ void LockWidget::initUI()
this->setCursor(Qt::ArrowCursor); this->setCursor(Qt::ArrowCursor);
}); });
if(QX11Info::isPlatformX11()){ // if(QX11Info::isPlatformX11()){
//虚拟键盘 //虚拟键盘
ui->btnKeyboard->setIcon(QIcon(":/image/assets/keyboard.svg")); ui->btnKeyboard->setIcon(QIcon(":/image/assets/keyboard.svg"));
ui->btnKeyboard->setFixedSize(48, 48); ui->btnKeyboard->setFixedSize(48, 48);
@ -832,10 +832,11 @@ void LockWidget::initUI()
connect(ui->btnKeyboard, &QPushButton::clicked, connect(ui->btnKeyboard, &QPushButton::clicked,
this, &LockWidget::showVirtualKeyboard); this, &LockWidget::showVirtualKeyboard);
/*
} else { } else {
ui->btnKeyboard->hide(); ui->btnKeyboard->hide();
} }
*/
//用户切换 //用户切换
if(displayManager->canSwitch()) if(displayManager->canSwitch())
{ {
@ -875,9 +876,6 @@ void LockWidget::netInPutStatus()
void LockWidget::showVirtualKeyboard() void LockWidget::showVirtualKeyboard()
{ {
if (!QX11Info::isPlatformX11()) {
return ;
}
tabAt = LINEEDIT; tabAt = LINEEDIT;
setBottomBtnSheet(); setBottomBtnSheet();
tabAt = BOTTMBTN; tabAt = BOTTMBTN;