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"