31
31
#include "GlobalShortcut_win.h"
32
32
#include "MainWindow.h"
33
36
#include "Global.h"
37
#include "../../overlay/HardHook.h"
36
40
#define FAILED(Status) (static_cast<HRESULT>(Status)<0)
38
42
#define DX_SAMPLE_BUFFER_SIZE 512
40
uint qHash(const GUID &a) {
44
static uint qHash(const GUID &a) {
41
45
uint val = a.Data1 ^ a.Data2 ^ a.Data3;
42
46
for (int i=0;i<8;i++)
53
static HWND WINAPI HookWindowFromPoint(POINT p);
54
static BOOL WINAPI HookSetForegroundWindow(HWND hwnd);
56
static HardHook hhWindowFromPoint(reinterpret_cast<voidFunc>(::WindowFromPoint), reinterpret_cast<voidFunc>(HookWindowFromPoint));
57
static HardHook hhSetForegroundWindow(reinterpret_cast<voidFunc>(::SetForegroundWindow), reinterpret_cast<voidFunc>(HookSetForegroundWindow));
59
typedef HWND(__stdcall *WindowFromPointType)(POINT);
60
static HWND WINAPI HookWindowFromPoint(POINT p) {
62
return g.ocIntercept->qgv.winId();
64
WindowFromPointType oWindowFromPoint = (WindowFromPointType) hhWindowFromPoint.call;
65
hhWindowFromPoint.restore();
67
HWND hwnd = oWindowFromPoint(p);
69
hhWindowFromPoint.inject();
73
typedef BOOL(__stdcall *SetForegroundWindowType)(HWND);
74
static BOOL WINAPI HookSetForegroundWindow(HWND hwnd) {
78
SetForegroundWindowType oSetForegroundWindow = (SetForegroundWindowType) hhSetForegroundWindow.call;
79
hhSetForegroundWindow.restore();
81
BOOL ret = oSetForegroundWindow(hwnd);
83
hhSetForegroundWindow.inject();
47
89
GlobalShortcutEngine *GlobalShortcutEngine::platformInit() {
48
90
return new GlobalShortcutWin();
51
94
GlobalShortcutWin::GlobalShortcutWin() {
53
96
uiHardwareDevices = 0;
98
GetKeyboardState(ucKeyState);
54
100
moveToThread(this);
55
101
start(QThread::LowestPriority);
75
121
* We need to do this because adding a new device requires a Window handle. (SetCooperativeLevel())
124
this->yieldCurrentThread();
80
126
GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (wchar_t *) &HookKeyboard, &hSelf);
82
128
hhKeyboard = SetWindowsHookEx(WH_KEYBOARD_LL, HookKeyboard, hSelf, 0);
83
129
hhMouse = SetWindowsHookEx(WH_MOUSE_LL, HookMouse, hSelf, 0);
86
134
timer = new QTimer(this);
107
155
LRESULT CALLBACK GlobalShortcutWin::HookKeyboard(int nCode, WPARAM wParam, LPARAM lParam) {
108
156
GlobalShortcutWin *gsw=static_cast<GlobalShortcutWin *>(engine);
109
157
KBDLLHOOKSTRUCT *key=reinterpret_cast<KBDLLHOOKSTRUCT *>(lParam);
158
BYTE *ucKeyState = gsw->ucKeyState;
161
static int safety = 0;
163
if ((++safety < 100) && (nCode >= 0)) {
110
165
if (nCode >= 0) {
168
WPARAM w = key->vkCode;
169
LPARAM l = 1 | (key->scanCode << 16);
170
if (key->flags & LLKHF_EXTENDED)
172
if (wParam == WM_KEYUP)
180
if ((msg == WM_KEYDOWN) || (msg == WM_SYSKEYDOWN))
181
ucKeyState[w] |= 0x80;
183
ucKeyState[w] &= 0x7f;
185
if ((ucKeyState[VK_LCONTROL] & 0x80) || (ucKeyState[VK_RCONTROL] & 0x80)) {
195
if ((msg == WM_KEYDOWN) || (msg == WM_SYSKEYDOWN))
196
ucKeyState[w] |= 0x80;
198
ucKeyState[w] &= 0x7f;
200
if ((ucKeyState[VK_LSHIFT] & 0x80) || (ucKeyState[VK_RSHIFT] & 0x80)) {
210
if ((msg == WM_KEYDOWN) || (msg == WM_SYSKEYDOWN))
211
ucKeyState[w] |= 0x80;
213
ucKeyState[w] &= 0x7f;
215
if ((ucKeyState[VK_LMENU] & 0x80) || (ucKeyState[VK_RMENU] & 0x80)) {
227
if ((msg == WM_KEYDOWN) || (msg == WM_SYSKEYDOWN)) {
228
if (ucKeyState[w] & 0x80)
230
ucKeyState[w] |= 0x80;
231
} else if (((msg == WM_KEYUP) || (msg == WM_SYSKEYUP)) && !nomsg) {
232
ucKeyState[w] &= 0x7f;
111
235
QList<QVariant> ql;
112
236
unsigned int keyid = static_cast<unsigned int>((key->scanCode << 8) | 0x4);
113
237
if (key->flags & LLKHF_EXTENDED)
114
238
keyid |= 0x8000U;
116
240
ql << QVariant(QUuid(GUID_SysKeyboard));
117
if (gsw->handleButton(ql, !(key->flags & LLKHF_UP)))
241
bool suppress = gsw->handleButton(ql, !(key->flags & LLKHF_UP));
243
#ifndef COMPAT_CLIENT
244
if (! suppress && g.ocIntercept) {
245
HWND hwnd = g.ocIntercept->qgv.winId();
248
ZeroMemory(>i, sizeof(gti));
249
gti.cbSize = sizeof(gti);
250
::GetGUIThreadInfo(::GetWindowThreadProcessId(hwnd, NULL), >i);
253
hwnd = gti.hwndFocus;
256
::PostMessage(hwnd, msg, w, l);
120
266
return CallNextHookEx(gsw->hhKeyboard, nCode, wParam, lParam);
123
269
LRESULT CALLBACK GlobalShortcutWin::HookMouse(int nCode, WPARAM wParam, LPARAM lParam) {
124
270
GlobalShortcutWin *gsw=static_cast<GlobalShortcutWin *>(engine);
125
271
MSLLHOOKSTRUCT *mouse=reinterpret_cast<MSLLHOOKSTRUCT *>(lParam);
272
BYTE *ucKeyState = gsw->ucKeyState;
126
274
if (nCode >= 0) {
275
bool suppress = false;
280
ucKeyState[VK_LBUTTON] |= 0x80;
281
if (gsw->tDoubleClick.restart() < (QApplication::doubleClickInterval() * 1000ULL))
282
msg = WM_LBUTTONDBLCLK;
285
ucKeyState[VK_LBUTTON] &= 0x7f;
288
ucKeyState[VK_RBUTTON] |= 0x80;
291
ucKeyState[VK_RBUTTON] &= 0x7f;
294
ucKeyState[VK_MBUTTON] |= 0x80;
297
ucKeyState[VK_MBUTTON] &= 0x7f;
300
if ((mouse->mouseData >> 16) == XBUTTON1)
301
ucKeyState[VK_XBUTTON1] |= 0x80;
302
else if ((mouse->mouseData >> 16) == XBUTTON2)
303
ucKeyState[VK_XBUTTON2] |= 0x80;
306
if ((mouse->mouseData >> 16) == XBUTTON1)
307
ucKeyState[VK_XBUTTON1] &= 0x7f;
308
else if ((mouse->mouseData >> 16) == XBUTTON2)
309
ucKeyState[VK_XBUTTON2] &= 0x7f;
315
#ifndef COMPAT_CLIENT
320
int dx = mouse->pt.x - p.x;
321
int dy = mouse->pt.y - p.y;
323
g.ocIntercept->iMouseX = qBound<int>(0, g.ocIntercept->iMouseX + dx, g.ocIntercept->uiWidth - 1);
324
g.ocIntercept->iMouseY = qBound<int>(0, g.ocIntercept->iMouseY + dy, g.ocIntercept->uiHeight - 1);
327
LPARAM l = (static_cast<short>(g.ocIntercept->iMouseX) & 0xFFFF) | ((g.ocIntercept->iMouseY << 16) & 0xFFFF0000);
329
if (ucKeyState[VK_CONTROL] & 0x80)
331
if (ucKeyState[VK_LBUTTON] & 0x80)
333
if (ucKeyState[VK_MBUTTON] & 0x80)
335
if (ucKeyState[VK_RBUTTON] & 0x80)
337
if (ucKeyState[VK_SHIFT] & 0x80)
339
if (ucKeyState[VK_XBUTTON1] & 0x80)
341
if (ucKeyState[VK_XBUTTON2] & 0x80)
344
w |= (mouse->mouseData & 0xFFFF0000);
346
HWND hwnd = g.ocIntercept->qgv.winId();
349
ZeroMemory(>i, sizeof(gti));
350
gti.cbSize = sizeof(gti);
351
::GetGUIThreadInfo(::GetWindowThreadProcessId(hwnd, NULL), >i);
354
hwnd = gti.hwndCapture;
356
::PostMessage(hwnd, msg, w, l);
358
QMetaObject::invokeMethod(g.ocIntercept, "updateMouse", Qt::QueuedConnection);
127
364
bool down = false;
128
365
unsigned int btn = 0;
129
366
switch (wParam) {
153
390
QList<QVariant> ql;
154
391
ql << static_cast<unsigned int>((btn << 8) | 0x4);
155
392
ql << QVariant(QUuid(GUID_SysMouse));
156
if (gsw->handleButton(ql, down))
393
bool wantsuppress = gsw->handleButton(ql, down);
395
suppress = wantsuppress && (btn != 3);
160
400
return CallNextHookEx(gsw->hhMouse, nCode, wParam, lParam);
233
473
dipdw.dwData = DX_SAMPLE_BUFFER_SIZE;
235
475
if (FAILED(hr = id->pDID->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph)))
236
qFatal("GlobalShortcutWin::SetProperty");
476
qFatal("GlobalShortcutWin: SetProperty: %lx", hr);
238
478
qWarning("Adding device %s %s %s:%d", qPrintable(QUuid(id->guid).toString()),qPrintable(name),qPrintable(sname),id->qhNames.count());
239
479
cbgsw->qhInputDevices[id->guid] = id;