-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
364 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
sudo apt install qtbase5-dev qt5-qmake qt5-default qtscript5-dev qttools5-dev-tools libqt5x11extras5-dev pkg-config libxcb1-dev libx11-dev | ||
|
||
1)获取CapsLock大小写键状态(使用X11,在pro文件里添加 LIBS += -lX11) | ||
2)获取按键事件,如windows键(Qt::Key_Meta) | ||
3)输入法数据QEvent::InputMethod |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
isEqual(QT_MAJOR_VERSION, 5) { | ||
QT += widgets gui core x11extras | ||
} | ||
|
||
TARGET = keyboard-monitor | ||
TEMPLATE = app | ||
|
||
target.path = /usr/bin | ||
target.source += $$TARGET | ||
|
||
CONFIG += c++14 | ||
CONFIG += qt warn_on | ||
CONFIG += release | ||
CONFIG += link_pkgconfig | ||
PKGCONFIG += xcb | ||
|
||
LIBS += -lX11 | ||
|
||
# The following define makes your compiler emit warnings if you use | ||
# any feature of Qt which has been marked as deprecated (the exact warnings | ||
# depend on your compiler). Please consult the documentation of the | ||
# deprecated API in order to know how to port your code away from it. | ||
DEFINES += QT_DEPRECATED_WARNINGS | ||
|
||
# You can also make your code fail to compile if you use deprecated APIs. | ||
# In order to do so, uncomment the following line. | ||
# You can also select to disable deprecated APIs only up to a certain version of Qt. | ||
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 | ||
|
||
QMAKE_CFLAGS += -D_GNU_SOURCE | ||
QMAKE_CPPFLAGS *= $(shell dpkg-buildflags --get CPPFLAGS) | ||
QMAKE_CFLAGS *= $(shell dpkg-buildflags --get CFLAGS) | ||
QMAKE_CXXFLAGS *= $(shell dpkg-buildflags --get CXXFLAGS) | ||
QMAKE_LFLAGS *= $(shell dpkg-buildflags --get LDFLAGS) | ||
|
||
unix { | ||
UI_DIR = .ui | ||
MOC_DIR = .moc | ||
OBJECTS_DIR = .obj | ||
} | ||
|
||
SOURCES += \ | ||
main.cpp \ | ||
widget.cpp \ | ||
native-event-filter-factory.cpp | ||
|
||
HEADERS += \ | ||
widget.h \ | ||
native-event-filter-factory.h |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
#include "widget.h" | ||
#include "native-event-filter-factory.h" | ||
#include <QApplication> | ||
|
||
int main(int argc, char *argv[]) | ||
{ | ||
QApplication a(argc, argv); | ||
// a.installNativeEventFilter(NativeEventFilterFactory::getEventFilter()); | ||
Widget w; | ||
w.show(); | ||
|
||
return a.exec(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
#include "native-event-filter-factory.h" | ||
|
||
#include <QByteArray> | ||
#include <QAbstractNativeEventFilter> | ||
#include <QString> | ||
#include <QObject> | ||
#include <QDebug> | ||
|
||
#include <X11/XKBlib.h> | ||
#include <xcb/xcb.h> | ||
#include <xcb/xproto.h> //xcb_button_release_event_t xcb_button_release_event_t xcb_key_press_event_t | ||
|
||
|
||
class NativeEventFilter : public QAbstractNativeEventFilter { | ||
public: | ||
|
||
NativeEventFilter() : entered(false) { | ||
|
||
|
||
} | ||
|
||
bool nativeEventFilter(const QByteArray& eventType, | ||
void* message, | ||
long*) override { | ||
QString event_type = QString(eventType); | ||
|
||
if (event_type == "xcb_generic_event_t") {//XCB(Linux) 这里只处理了键盘事件XCB_KEY_PRESS | ||
// if (eventType.compare("xcb_generic_event_t") == 0) { | ||
xcb_generic_event_t* ev = static_cast<xcb_generic_event_t*>(message); | ||
|
||
int evType = (ev->response_type & ~0x80); | ||
// qDebug() << "xcb_generic_event_t===========" << evType; | ||
|
||
if (evType == XCB_ENTER_NOTIFY) { | ||
qDebug() << "XCB_ENTER_NOTIFY==========="; | ||
entered = true; | ||
} | ||
else if (evType == XCB_LEAVE_NOTIFY) { | ||
qDebug() << "XCB_LEAVE_NOTIFY==========="; | ||
entered = false; | ||
} | ||
else if (evType == XCB_BUTTON_PRESS) { | ||
qDebug() << "XCB_BUTTON_PRESS==========="; | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
/*NativeEventFilter *getInstance(void) | ||
{ | ||
static NativeEventFilter m_instance; | ||
return &m_instance; | ||
// const NativeEventFilter* m_instance = static_cast<const NativeEventFilter*>(); | ||
// return const_cast<NativeEventFilter*>(m_instance); | ||
}*/ | ||
|
||
private: | ||
bool entered; | ||
}; | ||
|
||
|
||
QAbstractNativeEventFilter* NativeEventFilterFactory::getEventFilter() | ||
{ | ||
// return NativeEventFilter::getInstance(); | ||
NativeEventFilter *m_instance = new NativeEventFilter(); | ||
return m_instance; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
#pragma once | ||
|
||
#include <QAbstractNativeEventFilter> | ||
|
||
class NativeEventFilterFactory { | ||
public: | ||
static QAbstractNativeEventFilter *getEventFilter(); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,188 @@ | ||
#include "widget.h" | ||
|
||
#include <QEvent> | ||
#include <QGuiApplication> | ||
#include <QInputMethodEvent> | ||
#include <QInputMethod> | ||
#include <QTransform> | ||
#include <QPoint> | ||
#include <QCursor> | ||
#include <QClipboard> | ||
#include <QVBoxLayout> | ||
#include <QLineEdit> | ||
#include <QLabel> | ||
#include <QDebug> | ||
|
||
#include <X11/XKBlib.h> | ||
//解决QEvent::Type中enum和Xlib中#defines同名的冲突,比如Qt中的QEvent::KeyPress与Xlib中的#define KeyPress 2(定义在X.h文件中) | ||
#undef KeyPress | ||
#undef KeyRelease | ||
#undef FocusIn | ||
#undef FocusOut | ||
|
||
Widget::Widget(QWidget *parent) | ||
: QWidget(parent) | ||
, m_lineEdit(new QLineEdit(this)) | ||
, m_label(new QLabel(this)) | ||
{ | ||
this->setAttribute(Qt::WA_InputMethodEnabled); | ||
this->setFocusPolicy(Qt::StrongFocus); | ||
this->setFixedSize(400, 300); | ||
installEventFilter(this); | ||
|
||
m_lineEdit->setEchoMode(QLineEdit::Password); | ||
connect(m_lineEdit, &QLineEdit::textChanged, this, &Widget::onLineEditTextChanged); | ||
|
||
QVBoxLayout *layout = new QVBoxLayout; | ||
layout->setContentsMargins(0, 0, 0, 0); | ||
layout->setSpacing(20); | ||
layout->addWidget(m_lineEdit); | ||
layout->addWidget(m_label); | ||
this->setLayout(layout); | ||
|
||
checkStatus(); | ||
} | ||
|
||
Widget::~Widget() | ||
{ | ||
|
||
} | ||
|
||
// http://stackoverflow.com/questions/2968336/qt-password-field-warn-about-caps-lock | ||
bool Widget::checkStatusStatus() | ||
{ | ||
Display* d = XOpenDisplay((char*)0); | ||
bool caps_state = false; | ||
if (d) { | ||
unsigned n; | ||
XkbGetIndicatorState(d, XkbUseCoreKbd, &n); | ||
caps_state = (n & 0x01) == 1; | ||
} | ||
return caps_state; | ||
} | ||
|
||
void Widget::checkStatus() | ||
{ | ||
if (checkStatusStatus()) { | ||
m_label->setText("Caps Lock is on"); | ||
} | ||
else { | ||
m_label->setText("Caps Lock is off"); | ||
} | ||
} | ||
|
||
void Widget::onLineEditTextChanged(const QString &text) | ||
{ | ||
Q_UNUSED(text); | ||
|
||
checkStatus(); | ||
} | ||
|
||
bool Widget::eventFilter(QObject *watched, QEvent *event) | ||
{ | ||
if (event->type() == QEvent::InputMethod) {//让QLineEdit失去焦点后进行输入法测试 | ||
QInputMethodEvent* e = (QInputMethodEvent*) event; | ||
if(!hasFocus()) {//失去焦点时,输入法事件优先于FocusOut事件被处理 | ||
e->setCommitString(""); | ||
} | ||
else { | ||
qDebug() << "InputMethod preeditString:" << e->preeditString() << ", commitString:" << e->commitString(); | ||
QInputMethod* im = QGuiApplication::inputMethod(); | ||
QTransform t; | ||
//QPoint p((0 - this->width()) / 2 + 20, 0 - this->height()); | ||
QPoint p(0, 0); | ||
QCursor cursor; | ||
QPoint position(this->mapToGlobal(QPoint(20, 0))); | ||
cursor.setPos(position); | ||
this->setCursor(cursor); | ||
t.translate(p.x(), p.y()); | ||
|
||
QGuiApplication::inputMethod()->setInputItemTransform(t); | ||
QGuiApplication::inputMethod()->setInputItemRectangle(this->rect()); | ||
QGuiApplication::inputMethod()->update(Qt::ImQueryInput); | ||
|
||
// qDebug() << "anchor " << im->anchorRectangle(); | ||
// qDebug() << "cursor " << im->cursorRectangle(); | ||
// qDebug() << "direction " << im->inputDirection(); | ||
// qDebug() << "itemclip " << im->inputItemClipRectangle(); | ||
// qDebug() << "itemrectangle " << im->inputItemRectangle(); | ||
// qDebug() << "animating " << im->isAnimating(); | ||
// qDebug() << "visible " << im->isVisible(); | ||
// qDebug() << "keyboard " << im->keyboardRectangle(); | ||
// qDebug() << this->inputMethodQuery(Qt::ImAnchorPosition); | ||
// qDebug() << this->inputMethodQuery(Qt::ImAnchorRectangle); | ||
} | ||
} | ||
else if (event->type() == QEvent::KeyPress) { | ||
//qDebug() << "QEvent::KeyPress"; | ||
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event); | ||
if (keyEvent) { | ||
qDebug() << "keyEvent->text():" << keyEvent->text() << ",key():" << keyEvent->key(); | ||
|
||
if (keyEvent->key() == Qt::Key_Meta) {//windows key | ||
qDebug() << "Key_Meta"; | ||
} | ||
else if (keyEvent->key() == Qt::Key_Home) { | ||
qDebug() << "Key_Home"; | ||
} | ||
else if (keyEvent->key() == Qt::Key_CapsLock) { | ||
qDebug() << "Key_CapsLock"; | ||
} | ||
else if (keyEvent->key() == Qt::Key_NumLock) { | ||
qDebug() << "Key_NumLock"; | ||
} | ||
else if (keyEvent->key() == Qt::Key_Left) { | ||
qDebug() << "Key_Left"; | ||
} | ||
else if (keyEvent->key() == Qt::Key_Right) { | ||
qDebug() << "Key_Right"; | ||
} | ||
else if (keyEvent->key() == Qt::Key_Up) { | ||
qDebug() << "Key_Up"; | ||
} | ||
else if (keyEvent->key() == Qt::Key_Down) { | ||
qDebug() << "Key_Down"; | ||
} | ||
else if (keyEvent->key() == Qt::Key_End) { | ||
qDebug() << "Key_End"; | ||
} | ||
else if (keyEvent->key() == Qt::Key_7) { | ||
qDebug() << "7"; | ||
} | ||
else if (keyEvent->key() == Qt::Key_4) { | ||
qDebug() << "4"; | ||
} | ||
else if (keyEvent->key() == Qt::Key_6) { | ||
qDebug() << "6"; | ||
} | ||
else if (keyEvent->key() == Qt::Key_8) { | ||
qDebug() << "8"; | ||
} | ||
else if (keyEvent->key() == Qt::Key_2) { | ||
qDebug() << "2"; | ||
} | ||
else if (keyEvent->key() == Qt::Key_1) { | ||
qDebug() << "1"; | ||
} | ||
} | ||
} | ||
else if (event->type() == QEvent::KeyRelease) { | ||
//qDebug() << "QEvent::KeyRelease"; | ||
} | ||
else if (event->type() == QEvent::MouseButtonPress) { | ||
qDebug() << "QEvent::MouseButtonPress"; | ||
} | ||
else if (event->type() == QEvent::MouseButtonRelease) { | ||
qDebug() << "QEvent::MouseButtonRelease"; | ||
} | ||
else if (event->type() == QEvent::MouseMove) { | ||
qDebug() << "QEvent::MouseMove"; | ||
} | ||
else if (event->type() == QEvent::FocusIn) { | ||
//qDebug() << "QEvent::FocusIn"; | ||
} | ||
else if (event->type() == QEvent::FocusOut) { | ||
//qDebug() << "QEvent::FocusOut"; | ||
} | ||
return QWidget::eventFilter(watched, event); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
#ifndef WIDGET_H | ||
#define WIDGET_H | ||
|
||
#include <QWidget> | ||
#include <QKeyEvent> | ||
|
||
class QLineEdit; | ||
class QLabel; | ||
|
||
class Widget : public QWidget | ||
{ | ||
Q_OBJECT | ||
|
||
public: | ||
Widget(QWidget *parent = 0); | ||
~Widget(); | ||
|
||
bool checkStatusStatus(); | ||
void checkStatus(); | ||
|
||
public slots: | ||
void onLineEditTextChanged(const QString &text); | ||
|
||
protected: | ||
bool eventFilter(QObject *watched, QEvent *event) Q_DECL_OVERRIDE; | ||
|
||
private: | ||
QLineEdit *m_lineEdit; | ||
QLabel *m_label; | ||
}; | ||
|
||
#endif // WIDGET_H |