File indexing completed on 2024-05-05 05:00:43
0001 /* 0002 This file is part of the KDE project 0003 0004 Copyright (C) 2016 by Oleg Chernovskiy <kanedias@xaker.ru> 0005 0006 This program is free software; you can redistribute it and/or 0007 modify it under the terms of the GNU General Public 0008 License as published by the Free Software Foundation; either 0009 version 2 of the License, or (at your option) any later version. 0010 0011 This program is distributed in the hope that it will be useful, 0012 but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 General Public License for more details. 0015 0016 You should have received a copy of the GNU General Public License 0017 along with this program; see the file COPYING. If not, write to 0018 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0019 Boston, MA 02110-1301, USA. 0020 */ 0021 0022 #include "x11events.h" 0023 0024 #include <QApplication> 0025 #include <QGlobalStatic> 0026 #include <QtGui/private/qtx11extras_p.h> 0027 0028 #include <X11/Xutil.h> 0029 #include <X11/keysym.h> 0030 #include <X11/extensions/XTest.h> 0031 0032 enum { 0033 LEFTSHIFT = 1, 0034 RIGHTSHIFT = 2, 0035 ALTGR = 4 0036 }; 0037 0038 class EventData 0039 { 0040 public: 0041 EventData(); 0042 0043 //keyboard 0044 Display *dpy = nullptr; 0045 signed char modifiers[0x100] = {}; 0046 KeyCode keycodes[0x100] = {}; 0047 KeyCode leftShiftCode = 0; 0048 KeyCode rightShiftCode = 0; 0049 KeyCode altGrCode = 0; 0050 char modifierState = 0; 0051 0052 //mouse 0053 int buttonMask = 0; 0054 int x = 0; 0055 int y = 0; 0056 0057 private: 0058 void init(); 0059 }; 0060 0061 Q_GLOBAL_STATIC(EventData, data) 0062 0063 EventData::EventData() 0064 { 0065 init(); 0066 } 0067 0068 void EventData::init() 0069 { 0070 buttonMask = 0; 0071 0072 dpy = QX11Info::display(); 0073 //initialize keycodes 0074 KeySym key, *keymap; 0075 int i, j, minkey, maxkey, syms_per_keycode; 0076 0077 memset(modifiers, -1, sizeof(modifiers)); 0078 0079 XDisplayKeycodes(dpy, &minkey, &maxkey); 0080 Q_ASSERT(minkey >= 8); 0081 Q_ASSERT(maxkey < 256); 0082 keymap = (KeySym *) XGetKeyboardMapping(dpy, minkey, 0083 (maxkey - minkey + 1), 0084 &syms_per_keycode); 0085 Q_ASSERT(keymap); 0086 0087 for (i = minkey; i <= maxkey; i++) { 0088 for (j = 0; j < syms_per_keycode; j++) { 0089 key = keymap[(i-minkey)*syms_per_keycode+j]; 0090 0091 if (key >= ' ' && key < 0x100 && i == XKeysymToKeycode(dpy, key)) { 0092 keycodes[key] = i; 0093 modifiers[key] = j; 0094 } 0095 } 0096 } 0097 0098 leftShiftCode = XKeysymToKeycode(dpy, XK_Shift_L); 0099 rightShiftCode = XKeysymToKeycode(dpy, XK_Shift_R); 0100 altGrCode = XKeysymToKeycode(dpy, XK_Mode_switch); 0101 0102 XFree((char *)keymap); 0103 } 0104 0105 /* this function adjusts the modifiers according to mod (as from modifiers) and data->modifierState */ 0106 static void tweakModifiers(signed char mod, bool down) 0107 { 0108 bool isShift = data->modifierState & (LEFTSHIFT | RIGHTSHIFT); 0109 0110 if (mod < 0) { 0111 return; 0112 } 0113 0114 if (isShift && mod != 1) { 0115 if (data->modifierState & LEFTSHIFT) { 0116 XTestFakeKeyEvent(data->dpy, data->leftShiftCode, 0117 down, CurrentTime); 0118 } 0119 0120 if (data->modifierState & RIGHTSHIFT) { 0121 XTestFakeKeyEvent(data->dpy, data->rightShiftCode, 0122 down, CurrentTime); 0123 } 0124 } 0125 0126 if (!isShift && mod == 1) { 0127 XTestFakeKeyEvent(data->dpy, data->leftShiftCode, 0128 down, CurrentTime); 0129 } 0130 0131 if ((data->modifierState & ALTGR) && mod != 2) { 0132 XTestFakeKeyEvent(data->dpy, data->altGrCode, 0133 !down, CurrentTime); 0134 } 0135 0136 if (!(data->modifierState & ALTGR) && mod == 2) { 0137 XTestFakeKeyEvent(data->dpy, data->altGrCode, 0138 down, CurrentTime); 0139 } 0140 } 0141 0142 void X11EventHandler::handleKeyboard(bool down, rfbKeySym keySym) 0143 { 0144 #define ADJUSTMOD(sym,state) \ 0145 if(keySym==sym) { if(down) data->modifierState|=state; else data->modifierState&=~state; } 0146 0147 if (QX11Info::isPlatformX11()) { 0148 ADJUSTMOD(XK_Shift_L, LEFTSHIFT); 0149 ADJUSTMOD(XK_Shift_R, RIGHTSHIFT); 0150 ADJUSTMOD(XK_Mode_switch, ALTGR); 0151 0152 if (keySym >= ' ' && keySym < 0x100) { 0153 KeyCode k; 0154 0155 if (down) { 0156 tweakModifiers(data->modifiers[keySym], True); 0157 } 0158 0159 k = data->keycodes[keySym]; 0160 0161 if (k != NoSymbol) { 0162 XTestFakeKeyEvent(data->dpy, k, down, CurrentTime); 0163 } 0164 0165 if (down) { 0166 tweakModifiers(data->modifiers[keySym], False); 0167 } 0168 } else { 0169 KeyCode k = XKeysymToKeycode(data->dpy, keySym); 0170 0171 if (k != NoSymbol) { 0172 XTestFakeKeyEvent(data->dpy, k, down, CurrentTime); 0173 } 0174 } 0175 } 0176 /* 0177 // Wayland platform and pipweire plugin in use 0178 if (KrfbConfig::preferredFrameBufferPlugin() == QStringLiteral("pw")) { 0179 0180 }*/ 0181 } 0182 0183 void X11EventHandler::handlePointer(int buttonMask, int x, int y) 0184 { 0185 if (QX11Info::isPlatformX11()) { 0186 XTestFakeMotionEvent(data->dpy, 0, x, y, CurrentTime); 0187 0188 for (int i = 0; i < 5; i++) { 0189 if ((data->buttonMask&(1 << i)) != (buttonMask&(1 << i))) { 0190 XTestFakeButtonEvent(data->dpy, 0191 i + 1, 0192 (buttonMask&(1 << i)) ? True : False, 0193 CurrentTime); 0194 } 0195 } 0196 0197 data->buttonMask = buttonMask; 0198 } 0199 }