Rabbit Remote Control 0.1.0-alpha
Loading...
Searching...
No Matches
NativeEventFilterUnix.cpp
1#include "NativeEventFilterUnix.h"
2
3#if defined(Q_OS_WIN)
4#include <windows.h>
5#endif
6
7#include <QApplication>
8#include <QLoggingCategory>
9#include <QKeyEvent>
10
11static Q_LOGGING_CATEGORY(log, "Client.NativeEventFilter")
12
13#include <xcb/xcb.h>
14#include <xcb/xcb_keysyms.h>
15#define XK_MISCELLANY
16// the X11 headers on some systems. See: [Xlib 键符号](https://www.x.org/releases/X11R7.7/doc/libX11/XKB/xkblib.html)
17#include <X11/keysymdef.h>
18
19/*
20int GetKeySym(xcb_key_press_event_t* event, xcb_keysym_t& keysym)
21{
22 xcb_connection_t *connection = xcb_connect(NULL, NULL);
23 // 连接到 X server
24 if (xcb_connection_has_error(connection)) {
25 qCritical(log) << "Don't connect X server";
26 return -1;
27 }
28 // 初始化 Key Symbols
29 xcb_key_symbols_t *key_symbols = xcb_key_symbols_alloc(connection);
30 if (!key_symbols) {
31 qCritical(log) << "无法分配键符表";
32 return -2;
33 }
34 // 将 keycode 转换为 keysym
35 keysym = xcb_key_symbols_get_keysym(key_symbols, event->detail, 0);
36 // 处理 Shift 组合键
37 if (event->state & XCB_MOD_MASK_SHIFT) {
38 keysym = xcb_key_symbols_get_keysym(key_symbols, event->detail, 1);
39 }
40 qDebug(log) << "keycode:" << event->detail << "keySym:" << keysym;
41 // 清理
42 xcb_key_symbols_free(key_symbols);
43 xcb_disconnect(connection);
44 return 0;
45}
46
47void
48print_modifiers (uint32_t mask)
49{
50 const char **mod, *mods[] = {
51 "Shift", "Lock", "Ctrl", "Alt",
52 "Mod2", "Mod3", "Mod4", "Mod5",
53 "Button1", "Button2", "Button3", "Button4", "Button5"
54 };
55 qDebug(log) << "Modifier mask: ";
56 for (mod = mods ; mask; mask >>= 1, mod++)
57 if (mask & 1)
58 qDebug(log) << *mod;
59}
60*/
61
62Qt::KeyboardModifiers GetModifiers(uint32_t mask)
63{
64 Qt::KeyboardModifiers modifiers = Qt::NoModifier;
65 if(XCB_KEY_BUT_MASK_SHIFT & mask)
66 modifiers |= Qt::ShiftModifier;
67 if(XCB_KEY_BUT_MASK_CONTROL & mask)
68 modifiers |= Qt::ControlModifier;
69 if(XCB_KEY_BUT_MASK_MOD_1 & mask)
70 modifiers |= Qt::AltModifier;
71 return modifiers;
72}
73
74bool CNativeEventFilterUnix::HandleKey(
75 xcb_keysym_t keysym, QEvent::Type type, Qt::KeyboardModifiers modifiers)
76{
77 int bRet = false;
78 if(!m_pParameterPlugin
79 || m_pParameterPlugin->GetNativeWindowReceiveKeyboard()) {
80 qDebug(log) << "Native window receive keyboard.";
81 return false;
82 }
83
84 int key = 0;
85 switch (keysym) {
86 case XK_Tab:
87 key = Qt::Key_Tab;
88 bRet = true;
89 break;
90 case XK_Meta_L:
91 case XK_Meta_R:
92 key = Qt::Key_Meta;
93 bRet = true;
94 break;
95 case XK_Alt_L:
96 case XK_Alt_R:
97 key = Qt::Key_Alt;
98 bRet = true;
99 break;
100 case XK_Super_L:
101 key = Qt::Key_Super_L;
102 bRet = true;
103 break;
104 case XK_Super_R:
105 key = Qt::Key_Super_R;
106 bRet = true;
107 break;
108 default:
109 break;
110 }
111
112 if(bRet) {
113 CFrmViewer* focus = qobject_cast<CFrmViewer*>(QApplication::focusWidget());
114 if(focus) {
115
116 QKeyEvent* keyEvent = new QKeyEvent(type, key, modifiers);
117 /*
118 QApplication::postEvent(focus, keyEvent);
119 return true;//*/
120 switch(type)
121 {
122 case QEvent::KeyPress:
123 emit focus->sigKeyPressEvent(keyEvent);
124 break;
125 case QEvent::KeyRelease:
126 emit focus->sigKeyReleaseEvent(keyEvent);
127 break;
128 default:
129 break;
130 }
131 return true;
132 }
133 QKeyEvent* keyEvent = new QKeyEvent(type, key, modifiers);
134 qDebug(log) << "Process:" << keyEvent;
135 }
136 return false;
137}
138
139bool CNativeEventFilterUnix::HandleEvent(xcb_generic_event_t* event)
140{
141 bool bRet = false;
142
143 switch (event->response_type & ~0x80) {
144 case XCB_KEY_PRESS: {
145 xcb_key_press_event_t *ke = (xcb_key_press_event_t *)event;
146 //print_modifiers(ke->state);
147 int nRet = 0;
148 xcb_keysym_t keysym;
149 nRet = GetKeySym(ke, keysym);
150 if(nRet)
151 break;
152 /*
153 qDebug(log) << "Press Key:" << ke->detail << keysym << GetModifiers(ke->state) << "pressed in window " << ke->event
154 << "root:" << ke->root;//*/
155 bRet = HandleKey(keysym, QEvent::KeyPress, GetModifiers(ke->state));
156 break;
157 }
158 case XCB_KEY_RELEASE: {
159 xcb_key_release_event_t *ke = (xcb_key_release_event_t *)event;
160 //print_modifiers(ke->state);
161 int nRet = 0;
162 xcb_keysym_t keysym;
163 nRet = GetKeySym(ke, keysym);
164 if(nRet)
165 break;
166 /*
167 qDebug(log) << "Release Key:" << ke->detail << keysym << GetModifiers(ke->state) << "pressed in window " << ke->event
168 << "root:" << ke->root;//*/
169 bRet = HandleKey(keysym, QEvent::KeyRelease, GetModifiers(ke->state));
170 break;
171 }
172 default:
173 break;
174 }
175
176 return bRet;
177}
178
179int CNativeEventFilterUnix::GetKeySym(xcb_key_press_event_t *event, xcb_keysym_t &keysym)
180{
181 int nRet = 0;
182 // 将 keycode 转换为 keysym
183 keysym = xcb_key_symbols_get_keysym(m_pKeySymbols, event->detail, 0);
184 // 处理 Shift 组合键
185 if (event->state & XCB_MOD_MASK_SHIFT) {
186 keysym = xcb_key_symbols_get_keysym(m_pKeySymbols, event->detail, 1);
187 }
188 //qDebug(log) << "keycode:" << event->detail << "keySym:" << keysym;
189 return nRet;
190}
191
192CNativeEventFilterUnix::CNativeEventFilterUnix(CParameterPlugin *pPara)
193 : m_pParameterPlugin(pPara)
194{
195 m_pConnect = xcb_connect(NULL, NULL);
196 // 连接到 X server
197 if (xcb_connection_has_error(m_pConnect)) {
198 qCritical(log) << "Don't connect X server";
199 return;
200 }
201
202 // 初始化 Key Symbols
203 m_pKeySymbols = xcb_key_symbols_alloc(m_pConnect);
204 if (!m_pKeySymbols) {
205 qCritical(log) << "无法分配键符表";
206 return;
207 }
208}
209
210CNativeEventFilterUnix::~CNativeEventFilterUnix()
211{
212 // 清理
213 if(m_pKeySymbols)
214 xcb_key_symbols_free(m_pKeySymbols);
215 xcb_disconnect(m_pConnect);
216}
217
218#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
219bool CNativeEventFilterUnix::nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result)
220#else
221bool CNativeEventFilterUnix::nativeEventFilter(const QByteArray &eventType, void *message, long *result)
222#endif
223{
224 //qDebug(log) << "eventType:" << eventType;
225
226 if (eventType == "xcb_generic_event_t") {
227 xcb_generic_event_t* e = static_cast<xcb_generic_event_t *>(message);
228 return HandleEvent(e);
229 }
230#if defined(Q_OS_WIN)
231 if (eventType == "windows_generic_MSG" || eventType == "windows_dispatcher_MSG")
232 {
233 MSG *pMsg = reinterpret_cast<MSG *>(message);
234
235 }
236#endif
237 return false;
238}
A widget which displays output image from a CConnectDesktop and sends input keypresses and mouse acti...
Definition FrmViewer.h:48
Global parameters of plugins.