bool WindowsRemoteInput::handlePacket(const NetworkPacket &np)
{
float dx = np.get(QStringLiteral("dx"), 0);
float dy = np.get(QStringLiteral("dy"), 0);
bool isSingleClick = np.get(QStringLiteral("singleclick"), false);
bool isDoubleClick = np.get(QStringLiteral("doubleclick"), false);
bool isMiddleClick = np.get(QStringLiteral("middleclick"), false);
bool isRightClick = np.get(QStringLiteral("rightclick"), false);
bool isSingleHold = np.get(QStringLiteral("singlehold"), false);
bool isSingleRelease = np.get(QStringLiteral("singlerelease"), false);
bool isScroll = np.get(QStringLiteral("scroll"), false);
QString key = np.get(QStringLiteral("key"), QLatin1String(""));
int specialKey = np.get(QStringLiteral("specialKey"), 0);
if (isSingleClick || isDoubleClick || isMiddleClick || isRightClick || isSingleHold || isScroll || isSingleRelease || !key.isEmpty() || specialKey) {
INPUT input = {0};
input.type = INPUT_MOUSE;
if (isSingleClick) {
input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
::SendInput(1, &input, sizeof(INPUT));
input.mi.dwFlags = MOUSEEVENTF_LEFTUP;
::SendInput(1, &input, sizeof(INPUT));
} else if (isDoubleClick) {
input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
::SendInput(1, &input, sizeof(INPUT));
input.mi.dwFlags = MOUSEEVENTF_LEFTUP;
::SendInput(1, &input, sizeof(INPUT));
input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
::SendInput(1, &input, sizeof(INPUT));
input.mi.dwFlags = MOUSEEVENTF_LEFTUP;
::SendInput(1, &input, sizeof(INPUT));
} else if (isMiddleClick) {
input.mi.dwFlags = MOUSEEVENTF_MIDDLEDOWN;
::SendInput(1, &input, sizeof(INPUT));
input.mi.dwFlags = MOUSEEVENTF_MIDDLEUP;
::SendInput(1, &input, sizeof(INPUT));
} else if (isRightClick) {
input.mi.dwFlags = MOUSEEVENTF_RIGHTDOWN;
::SendInput(1, &input, sizeof(INPUT));
input.mi.dwFlags = MOUSEEVENTF_RIGHTUP;
::SendInput(1, &input, sizeof(INPUT));
} else if (isSingleHold) {
input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
::SendInput(1, &input, sizeof(INPUT));
} else if (isSingleRelease) {
input.mi.dwFlags = MOUSEEVENTF_LEFTUP;
::SendInput(1, &input, sizeof(INPUT));
} else if (isScroll) {
input.mi.dwFlags = MOUSEEVENTF_WHEEL;
input.mi.mouseData = dy;
::SendInput(1, &input, sizeof(INPUT));
} else if (!key.isEmpty() || specialKey) {
input.type = INPUT_KEYBOARD;
input.ki.time = 0;
input.ki.dwExtraInfo = 0;
input.ki.wScan = 0;
input.ki.dwFlags = 0;
bool ctrl = np.get(QStringLiteral("ctrl"), false);
bool alt = np.get(QStringLiteral("alt"), false);
bool shift = np.get(QStringLiteral("shift"), false);
bool super = np.get(QStringLiteral("super"), false);
if (ctrl) {
input.ki.wVk = VK_LCONTROL;
::SendInput(1, &input, sizeof(INPUT));
}
if (alt) {
input.ki.wVk = VK_LMENU;
::SendInput(1, &input, sizeof(INPUT));
}
if (shift) {
input.ki.wVk = VK_LSHIFT;
::SendInput(1, &input, sizeof(INPUT));
}
if (super) {
input.ki.wVk = VK_LWIN;
::SendInput(1, &input, sizeof(INPUT));
}
if (specialKey) {
if (specialKey >= (int)arraySize(SpecialKeysMap)) {
qWarning() << "Unsupported special key identifier";
return false;
}
input.ki.wVk = SpecialKeysMap[specialKey];
::SendInput(1, &input, sizeof(INPUT));
input.ki.dwFlags = KEYEVENTF_KEYUP;
::SendInput(1, &input, sizeof(INPUT));
} else {
for (int i = 0; i < key.length(); i++) {
wchar_t inputChar = (wchar_t)key.at(i).unicode();
short inputVk = VkKeyScanExW(inputChar, GetKeyboardLayout(0));
if (inputVk != -1) {
// Uses virtual keycodes so key combinations work
input.ki.wScan = 0;
input.ki.dwFlags = 0;
if (inputVk & 0x100) {
input.ki.wVk = VK_LSHIFT;
::SendInput(1, &input, sizeof(INPUT));
}
if (inputVk & 0x200) {
input.ki.wVk = VK_LCONTROL;
::SendInput(1, &input, sizeof(INPUT));
}
if (inputVk & 0x400) {
input.ki.wVk = VK_LMENU;
::SendInput(1, &input, sizeof(INPUT));
}
input.ki.wVk = inputVk & 0xFF;
::SendInput(1, &input, sizeof(INPUT));
input.ki.dwFlags = KEYEVENTF_KEYUP;
::SendInput(1, &input, sizeof(INPUT));
if ((inputVk & 0x100) && !shift) {
input.ki.wVk = VK_LSHIFT;
::SendInput(1, &input, sizeof(INPUT));
}
if ((inputVk & 0x200) && !ctrl) {
input.ki.wVk = VK_LCONTROL;
::SendInput(1, &input, sizeof(INPUT));
}
if ((inputVk & 0x400) && !alt) {
input.ki.wVk = VK_LMENU;
::SendInput(1, &input, sizeof(INPUT));
}
} else {
// Falls back to KEYEVENTF_UNICODE
input.ki.wVk = 0;
input.ki.wScan = inputChar;
input.ki.dwFlags = KEYEVENTF_UNICODE;
::SendInput(1, &input, sizeof(INPUT));
input.ki.dwFlags = KEYEVENTF_KEYUP | KEYEVENTF_UNICODE;
::SendInput(1, &input, sizeof(INPUT));
}
}
}
input.ki.dwFlags = KEYEVENTF_KEYUP;
input.ki.wScan = 0;
if (ctrl) {
input.ki.wVk = VK_LCONTROL;
::SendInput(1, &input, sizeof(INPUT));
}
if (alt) {
input.ki.wVk = VK_LMENU;
::SendInput(1, &input, sizeof(INPUT));
}
if (shift) {
input.ki.wVk = VK_LSHIFT;
::SendInput(1, &input, sizeof(INPUT));
}
if (super) {
input.ki.wVk = VK_LWIN;
::SendInput(1, &input, sizeof(INPUT));
}
}
} else { // Is a mouse move event
POINT point;
if (GetCursorPos(&point)) {
return SetCursorPos(point.x + (int)dx, point.y + (int)dy);
} else {
return false;
}
}
return true;
}
This code creates an input object from an existing network package and sends it to the other end. It takes the x and y coordinates of the mouse and returns true.