File indexing completed on 2024-04-21 04:56:50

0001 /**
0002  * SPDX-FileCopyrightText: 2018 Albert Vaca Cintora <albertvaka@gmail.com>
0003  *
0004  * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005  */
0006 
0007 #include "windowsremoteinput.h"
0008 
0009 #include <QCursor>
0010 #include <QDebug>
0011 
0012 #include <Windows.h>
0013 
0014 // Translation table to keep in sync within all the implementations
0015 int SpecialKeysMap[] = {
0016     0, // Invalid
0017     VK_BACK, // 1
0018     VK_TAB, // 2
0019     VK_RETURN, // 3
0020     VK_LEFT, // 4
0021     VK_UP, // 5
0022     VK_RIGHT, // 6
0023     VK_DOWN, // 7
0024     VK_PRIOR, // 8
0025     VK_NEXT, // 9
0026     VK_HOME, // 10
0027     VK_END, // 11
0028     VK_RETURN, // 12
0029     VK_DELETE, // 13
0030     VK_ESCAPE, // 14
0031     VK_SNAPSHOT, // 15
0032     VK_SCROLL, // 16
0033     0, // 17
0034     0, // 18
0035     0, // 19
0036     0, // 20
0037     VK_F1, // 21
0038     VK_F2, // 22
0039     VK_F3, // 23
0040     VK_F4, // 24
0041     VK_F5, // 25
0042     VK_F6, // 26
0043     VK_F7, // 27
0044     VK_F8, // 28
0045     VK_F9, // 29
0046     VK_F10, // 30
0047     VK_F11, // 31
0048     VK_F12, // 32
0049 };
0050 
0051 template<typename T, size_t N>
0052 size_t arraySize(T (&arr)[N])
0053 {
0054     (void)arr;
0055     return N;
0056 }
0057 
0058 WindowsRemoteInput::WindowsRemoteInput(QObject *parent)
0059     : AbstractRemoteInput(parent)
0060 {
0061 }
0062 
0063 bool WindowsRemoteInput::handlePacket(const NetworkPacket &np)
0064 {
0065     float dx = np.get<float>(QStringLiteral("dx"), 0);
0066     float dy = np.get<float>(QStringLiteral("dy"), 0);
0067 
0068     bool isSingleClick = np.get<bool>(QStringLiteral("singleclick"), false);
0069     bool isDoubleClick = np.get<bool>(QStringLiteral("doubleclick"), false);
0070     bool isMiddleClick = np.get<bool>(QStringLiteral("middleclick"), false);
0071     bool isRightClick = np.get<bool>(QStringLiteral("rightclick"), false);
0072     bool isSingleHold = np.get<bool>(QStringLiteral("singlehold"), false);
0073     bool isSingleRelease = np.get<bool>(QStringLiteral("singlerelease"), false);
0074     bool isScroll = np.get<bool>(QStringLiteral("scroll"), false);
0075     QString key = np.get<QString>(QStringLiteral("key"), QLatin1String(""));
0076     int specialKey = np.get<int>(QStringLiteral("specialKey"), 0);
0077 
0078     if (isSingleClick || isDoubleClick || isMiddleClick || isRightClick || isSingleHold || isScroll || isSingleRelease || !key.isEmpty() || specialKey) {
0079         INPUT input = {0};
0080         input.type = INPUT_MOUSE;
0081 
0082         if (isSingleClick) {
0083             input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
0084             ::SendInput(1, &input, sizeof(INPUT));
0085             input.mi.dwFlags = MOUSEEVENTF_LEFTUP;
0086             ::SendInput(1, &input, sizeof(INPUT));
0087         } else if (isDoubleClick) {
0088             input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
0089             ::SendInput(1, &input, sizeof(INPUT));
0090             input.mi.dwFlags = MOUSEEVENTF_LEFTUP;
0091             ::SendInput(1, &input, sizeof(INPUT));
0092             input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
0093             ::SendInput(1, &input, sizeof(INPUT));
0094             input.mi.dwFlags = MOUSEEVENTF_LEFTUP;
0095             ::SendInput(1, &input, sizeof(INPUT));
0096         } else if (isMiddleClick) {
0097             input.mi.dwFlags = MOUSEEVENTF_MIDDLEDOWN;
0098             ::SendInput(1, &input, sizeof(INPUT));
0099             input.mi.dwFlags = MOUSEEVENTF_MIDDLEUP;
0100             ::SendInput(1, &input, sizeof(INPUT));
0101         } else if (isRightClick) {
0102             input.mi.dwFlags = MOUSEEVENTF_RIGHTDOWN;
0103             ::SendInput(1, &input, sizeof(INPUT));
0104             input.mi.dwFlags = MOUSEEVENTF_RIGHTUP;
0105             ::SendInput(1, &input, sizeof(INPUT));
0106         } else if (isSingleHold) {
0107             input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
0108             ::SendInput(1, &input, sizeof(INPUT));
0109         } else if (isSingleRelease) {
0110             input.mi.dwFlags = MOUSEEVENTF_LEFTUP;
0111             ::SendInput(1, &input, sizeof(INPUT));
0112         } else if (isScroll) {
0113             input.mi.dwFlags = MOUSEEVENTF_WHEEL;
0114             input.mi.mouseData = dy;
0115             ::SendInput(1, &input, sizeof(INPUT));
0116 
0117         } else if (!key.isEmpty() || specialKey) {
0118             input.type = INPUT_KEYBOARD;
0119 
0120             input.ki.time = 0;
0121             input.ki.dwExtraInfo = 0;
0122             input.ki.wScan = 0;
0123             input.ki.dwFlags = 0;
0124 
0125             bool ctrl = np.get<bool>(QStringLiteral("ctrl"), false);
0126             bool alt = np.get<bool>(QStringLiteral("alt"), false);
0127             bool shift = np.get<bool>(QStringLiteral("shift"), false);
0128             bool super = np.get<bool>(QStringLiteral("super"), false);
0129 
0130             if (ctrl) {
0131                 input.ki.wVk = VK_LCONTROL;
0132                 ::SendInput(1, &input, sizeof(INPUT));
0133             }
0134             if (alt) {
0135                 input.ki.wVk = VK_LMENU;
0136                 ::SendInput(1, &input, sizeof(INPUT));
0137             }
0138             if (shift) {
0139                 input.ki.wVk = VK_LSHIFT;
0140                 ::SendInput(1, &input, sizeof(INPUT));
0141             }
0142             if (super) {
0143                 input.ki.wVk = VK_LWIN;
0144                 ::SendInput(1, &input, sizeof(INPUT));
0145             }
0146 
0147             if (specialKey) {
0148                 if (specialKey >= (int)arraySize(SpecialKeysMap)) {
0149                     qWarning() << "Unsupported special key identifier";
0150                     return false;
0151                 }
0152 
0153                 input.ki.wVk = SpecialKeysMap[specialKey];
0154                 ::SendInput(1, &input, sizeof(INPUT));
0155 
0156                 input.ki.dwFlags = KEYEVENTF_KEYUP;
0157                 ::SendInput(1, &input, sizeof(INPUT));
0158 
0159             } else {
0160                 for (int i = 0; i < key.length(); i++) {
0161                     wchar_t inputChar = (wchar_t)key.at(i).unicode();
0162                     short inputVk = VkKeyScanExW(inputChar, GetKeyboardLayout(0));
0163 
0164                     if (inputVk != -1) {
0165                         // Uses virtual keycodes so key combinations work
0166                         input.ki.wScan = 0;
0167                         input.ki.dwFlags = 0;
0168 
0169                         if (inputVk & 0x100) {
0170                             input.ki.wVk = VK_LSHIFT;
0171                             ::SendInput(1, &input, sizeof(INPUT));
0172                         }
0173                         if (inputVk & 0x200) {
0174                             input.ki.wVk = VK_LCONTROL;
0175                             ::SendInput(1, &input, sizeof(INPUT));
0176                         }
0177                         if (inputVk & 0x400) {
0178                             input.ki.wVk = VK_LMENU;
0179                             ::SendInput(1, &input, sizeof(INPUT));
0180                         }
0181 
0182                         input.ki.wVk = inputVk & 0xFF;
0183                         ::SendInput(1, &input, sizeof(INPUT));
0184 
0185                         input.ki.dwFlags = KEYEVENTF_KEYUP;
0186                         ::SendInput(1, &input, sizeof(INPUT));
0187 
0188                         if ((inputVk & 0x100) && !shift) {
0189                             input.ki.wVk = VK_LSHIFT;
0190                             ::SendInput(1, &input, sizeof(INPUT));
0191                         }
0192                         if ((inputVk & 0x200) && !ctrl) {
0193                             input.ki.wVk = VK_LCONTROL;
0194                             ::SendInput(1, &input, sizeof(INPUT));
0195                         }
0196                         if ((inputVk & 0x400) && !alt) {
0197                             input.ki.wVk = VK_LMENU;
0198                             ::SendInput(1, &input, sizeof(INPUT));
0199                         }
0200 
0201                     } else {
0202                         // Falls back to KEYEVENTF_UNICODE
0203                         input.ki.wVk = 0;
0204                         input.ki.wScan = inputChar;
0205                         input.ki.dwFlags = KEYEVENTF_UNICODE;
0206                         ::SendInput(1, &input, sizeof(INPUT));
0207 
0208                         input.ki.dwFlags = KEYEVENTF_KEYUP | KEYEVENTF_UNICODE;
0209                         ::SendInput(1, &input, sizeof(INPUT));
0210                     }
0211                 }
0212             }
0213 
0214             input.ki.dwFlags = KEYEVENTF_KEYUP;
0215             input.ki.wScan = 0;
0216 
0217             if (ctrl) {
0218                 input.ki.wVk = VK_LCONTROL;
0219                 ::SendInput(1, &input, sizeof(INPUT));
0220             }
0221             if (alt) {
0222                 input.ki.wVk = VK_LMENU;
0223                 ::SendInput(1, &input, sizeof(INPUT));
0224             }
0225             if (shift) {
0226                 input.ki.wVk = VK_LSHIFT;
0227                 ::SendInput(1, &input, sizeof(INPUT));
0228             }
0229             if (super) {
0230                 input.ki.wVk = VK_LWIN;
0231                 ::SendInput(1, &input, sizeof(INPUT));
0232             }
0233         }
0234 
0235     } else { // Is a mouse move event
0236         POINT point;
0237         if (GetCursorPos(&point)) {
0238             return SetCursorPos(point.x + (int)dx, point.y + (int)dy);
0239         } else {
0240             return false;
0241         }
0242     }
0243     return true;
0244 }
0245 
0246 bool WindowsRemoteInput::hasKeyboardSupport()
0247 {
0248     return true;
0249 }
0250 
0251 #include "moc_windowsremoteinput.cpp"