~ubuntu-branches/ubuntu/raring/mumble/raring

« back to all changes in this revision

Viewing changes to src/mumble/GlobalShortcut_win.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Thorvald Natvig, Patrick Matthäi, Thorvald Natvig
  • Date: 2011-02-19 22:58:58 UTC
  • mfrom: (9.1.15 sid)
  • Revision ID: james.westby@ubuntu.com-20110219225858-0xlftrf4z1z4jt9e
Tags: 1.2.3-1
[ Patrick Matthäi ]
* Do not build with non existant libpulse-dev on hurd-i386.

[ Thorvald Natvig ]
* New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
30
30
 
31
31
#include "GlobalShortcut_win.h"
32
32
#include "MainWindow.h"
 
33
#ifndef COMPAT_CLIENT
 
34
#include "Overlay.h"
 
35
#endif
33
36
#include "Global.h"
 
37
#include "../../overlay/HardHook.h"
34
38
 
35
39
#undef FAILED
36
40
#define FAILED(Status) (static_cast<HRESULT>(Status)<0)
37
41
 
38
42
#define DX_SAMPLE_BUFFER_SIZE 512
39
43
 
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++)
43
47
                val += a.Data4[i];
44
48
        return val;
45
49
}
46
50
 
 
51
#ifndef COMPAT_CLIENT
 
52
 
 
53
static HWND WINAPI HookWindowFromPoint(POINT p);
 
54
static BOOL WINAPI HookSetForegroundWindow(HWND hwnd);
 
55
 
 
56
static HardHook hhWindowFromPoint(reinterpret_cast<voidFunc>(::WindowFromPoint), reinterpret_cast<voidFunc>(HookWindowFromPoint));
 
57
static HardHook hhSetForegroundWindow(reinterpret_cast<voidFunc>(::SetForegroundWindow), reinterpret_cast<voidFunc>(HookSetForegroundWindow));
 
58
 
 
59
typedef HWND(__stdcall *WindowFromPointType)(POINT);
 
60
static HWND WINAPI HookWindowFromPoint(POINT p) {
 
61
        if (g.ocIntercept)
 
62
                return g.ocIntercept->qgv.winId();
 
63
 
 
64
        WindowFromPointType oWindowFromPoint = (WindowFromPointType) hhWindowFromPoint.call;
 
65
        hhWindowFromPoint.restore();
 
66
 
 
67
        HWND hwnd = oWindowFromPoint(p);
 
68
 
 
69
        hhWindowFromPoint.inject();
 
70
        return hwnd;
 
71
}
 
72
 
 
73
typedef BOOL(__stdcall *SetForegroundWindowType)(HWND);
 
74
static BOOL WINAPI HookSetForegroundWindow(HWND hwnd) {
 
75
        if (g.ocIntercept)
 
76
                return TRUE;
 
77
 
 
78
        SetForegroundWindowType oSetForegroundWindow = (SetForegroundWindowType) hhSetForegroundWindow.call;
 
79
        hhSetForegroundWindow.restore();
 
80
 
 
81
        BOOL ret = oSetForegroundWindow(hwnd);
 
82
 
 
83
        hhSetForegroundWindow.inject();
 
84
        return ret;
 
85
}
 
86
 
 
87
#endif
 
88
 
47
89
GlobalShortcutEngine *GlobalShortcutEngine::platformInit() {
48
90
        return new GlobalShortcutWin();
49
91
}
50
92
 
 
93
 
51
94
GlobalShortcutWin::GlobalShortcutWin() {
52
95
        pDI = NULL;
53
96
        uiHardwareDevices = 0;
 
97
 
 
98
        GetKeyboardState(ucKeyState);
 
99
 
54
100
        moveToThread(this);
55
101
        start(QThread::LowestPriority);
56
102
}
75
121
         * We need to do this because adding a new device requires a Window handle. (SetCooperativeLevel())
76
122
         */
77
123
        while (! g.mw)
78
 
                this->msleep(20);
 
124
                this->yieldCurrentThread();
79
125
 
80
126
        GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (wchar_t *) &HookKeyboard, &hSelf);
81
 
#ifdef QT_NO_DEBUG
 
127
 
82
128
        hhKeyboard = SetWindowsHookEx(WH_KEYBOARD_LL, HookKeyboard, hSelf, 0);
83
129
        hhMouse = SetWindowsHookEx(WH_MOUSE_LL, HookMouse, hSelf, 0);
 
130
 
 
131
#ifdef QT_NO_DEBUG
84
132
#endif
85
133
 
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;
 
159
 
 
160
#ifndef QT_NO_DEBUG
 
161
        static int safety = 0;
 
162
 
 
163
        if ((++safety < 100) && (nCode >= 0)) {
 
164
#else
110
165
        if (nCode >= 0) {
 
166
#endif
 
167
                UINT msg = wParam;
 
168
                WPARAM w = key->vkCode;
 
169
                LPARAM l = 1 | (key->scanCode << 16);
 
170
                if (key->flags & LLKHF_EXTENDED)
 
171
                        l |= 0x1000000;
 
172
                if (wParam == WM_KEYUP)
 
173
                        l |= 0xC0000000;
 
174
 
 
175
                bool nomsg = false;
 
176
 
 
177
                switch (w) {
 
178
                        case VK_LCONTROL:
 
179
                        case VK_RCONTROL:
 
180
                                if ((msg == WM_KEYDOWN) || (msg == WM_SYSKEYDOWN))
 
181
                                        ucKeyState[w] |= 0x80;
 
182
                                else {
 
183
                                        ucKeyState[w] &= 0x7f;
 
184
 
 
185
                                        if ((ucKeyState[VK_LCONTROL] & 0x80) || (ucKeyState[VK_RCONTROL] & 0x80)) {
 
186
                                                nomsg = true;
 
187
                                                break;
 
188
                                        }
 
189
                                }
 
190
 
 
191
                                w = VK_CONTROL;
 
192
                                break;
 
193
                        case VK_LSHIFT:
 
194
                        case VK_RSHIFT:
 
195
                                if ((msg == WM_KEYDOWN) || (msg == WM_SYSKEYDOWN))
 
196
                                        ucKeyState[w] |= 0x80;
 
197
                                else {
 
198
                                        ucKeyState[w] &= 0x7f;
 
199
 
 
200
                                        if ((ucKeyState[VK_LSHIFT] & 0x80) || (ucKeyState[VK_RSHIFT] & 0x80)) {
 
201
                                                nomsg = true;
 
202
                                                break;
 
203
                                        }
 
204
                                }
 
205
 
 
206
                                w = VK_SHIFT;
 
207
                                break;
 
208
                        case VK_LMENU:
 
209
                        case VK_RMENU:
 
210
                                if ((msg == WM_KEYDOWN) || (msg == WM_SYSKEYDOWN))
 
211
                                        ucKeyState[w] |= 0x80;
 
212
                                else {
 
213
                                        ucKeyState[w] &= 0x7f;
 
214
 
 
215
                                        if ((ucKeyState[VK_LMENU] & 0x80) || (ucKeyState[VK_RMENU] & 0x80)) {
 
216
                                                nomsg = true;
 
217
                                                break;
 
218
                                        }
 
219
                                }
 
220
 
 
221
                                w = VK_MENU;
 
222
                                break;
 
223
                        default:
 
224
                                break;
 
225
                }
 
226
 
 
227
                if ((msg == WM_KEYDOWN) || (msg == WM_SYSKEYDOWN)) {
 
228
                        if (ucKeyState[w] & 0x80)
 
229
                                l |= 0x40000000;
 
230
                        ucKeyState[w] |= 0x80;
 
231
                } else if (((msg == WM_KEYUP) || (msg == WM_SYSKEYUP)) && !nomsg) {
 
232
                        ucKeyState[w] &= 0x7f;
 
233
                }
 
234
 
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;
115
239
                ql << keyid;
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));
 
242
 
 
243
#ifndef COMPAT_CLIENT
 
244
                if (! suppress && g.ocIntercept) {
 
245
                        HWND hwnd = g.ocIntercept->qgv.winId();
 
246
 
 
247
                        GUITHREADINFO gti;
 
248
                        ZeroMemory(&gti, sizeof(gti));
 
249
                        gti.cbSize = sizeof(gti);
 
250
                        ::GetGUIThreadInfo(::GetWindowThreadProcessId(hwnd, NULL), &gti);
 
251
 
 
252
                        if (gti.hwndFocus)
 
253
                                hwnd = gti.hwndFocus;
 
254
 
 
255
                        if (! nomsg)
 
256
                                ::PostMessage(hwnd, msg, w, l);
 
257
 
 
258
                        suppress = true;
 
259
                }
 
260
#endif
 
261
 
 
262
                if (suppress)
118
263
                        return 1;
 
264
 
119
265
        }
120
266
        return CallNextHookEx(gsw->hhKeyboard, nCode, wParam, lParam);
121
267
}
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;
 
273
 
126
274
        if (nCode >= 0) {
 
275
                bool suppress = false;
 
276
                UINT msg = wParam;
 
277
 
 
278
                switch (msg) {
 
279
                        case WM_LBUTTONDOWN:
 
280
                                ucKeyState[VK_LBUTTON] |= 0x80;
 
281
                                if (gsw->tDoubleClick.restart() < (QApplication::doubleClickInterval() * 1000ULL))
 
282
                                        msg = WM_LBUTTONDBLCLK;
 
283
                                break;
 
284
                        case WM_LBUTTONUP:
 
285
                                ucKeyState[VK_LBUTTON] &= 0x7f;
 
286
                                break;
 
287
                        case WM_RBUTTONDOWN:
 
288
                                ucKeyState[VK_RBUTTON] |= 0x80;
 
289
                                break;
 
290
                        case WM_RBUTTONUP:
 
291
                                ucKeyState[VK_RBUTTON] &= 0x7f;
 
292
                                break;
 
293
                        case WM_MBUTTONDOWN:
 
294
                                ucKeyState[VK_MBUTTON] |= 0x80;
 
295
                                break;
 
296
                        case WM_MBUTTONUP:
 
297
                                ucKeyState[VK_MBUTTON] &= 0x7f;
 
298
                                break;
 
299
                        case WM_XBUTTONDOWN:
 
300
                                if ((mouse->mouseData >> 16) == XBUTTON1)
 
301
                                        ucKeyState[VK_XBUTTON1] |= 0x80;
 
302
                                else if ((mouse->mouseData >> 16) == XBUTTON2)
 
303
                                        ucKeyState[VK_XBUTTON2] |= 0x80;
 
304
                                break;
 
305
                        case WM_XBUTTONUP:
 
306
                                if ((mouse->mouseData >> 16) == XBUTTON1)
 
307
                                        ucKeyState[VK_XBUTTON1] &= 0x7f;
 
308
                                else if ((mouse->mouseData >> 16) == XBUTTON2)
 
309
                                        ucKeyState[VK_XBUTTON2] &= 0x7f;
 
310
                                break;
 
311
                        default:
 
312
                                break;
 
313
                }
 
314
 
 
315
#ifndef COMPAT_CLIENT
 
316
                if (g.ocIntercept) {
 
317
                        POINT p;
 
318
                        GetCursorPos(&p);
 
319
 
 
320
                        int dx = mouse->pt.x - p.x;
 
321
                        int dy = mouse->pt.y - p.y;
 
322
 
 
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);
 
325
 
 
326
                        WPARAM w = 0;
 
327
                        LPARAM l = (static_cast<short>(g.ocIntercept->iMouseX) & 0xFFFF) | ((g.ocIntercept->iMouseY << 16) & 0xFFFF0000);
 
328
 
 
329
                        if (ucKeyState[VK_CONTROL] & 0x80)
 
330
                                w |= MK_CONTROL;
 
331
                        if (ucKeyState[VK_LBUTTON] & 0x80)
 
332
                                w |= MK_LBUTTON;
 
333
                        if (ucKeyState[VK_MBUTTON] & 0x80)
 
334
                                w |= MK_MBUTTON;
 
335
                        if (ucKeyState[VK_RBUTTON] & 0x80)
 
336
                                w |= MK_RBUTTON;
 
337
                        if (ucKeyState[VK_SHIFT] & 0x80)
 
338
                                w |= MK_SHIFT;
 
339
                        if (ucKeyState[VK_XBUTTON1] & 0x80)
 
340
                                w |= MK_XBUTTON1;
 
341
                        if (ucKeyState[VK_XBUTTON2] & 0x80)
 
342
                                w |= MK_XBUTTON2;
 
343
 
 
344
                        w |= (mouse->mouseData & 0xFFFF0000);
 
345
 
 
346
                        HWND hwnd = g.ocIntercept->qgv.winId();
 
347
 
 
348
                        GUITHREADINFO gti;
 
349
                        ZeroMemory(&gti, sizeof(gti));
 
350
                        gti.cbSize = sizeof(gti);
 
351
                        ::GetGUIThreadInfo(::GetWindowThreadProcessId(hwnd, NULL), &gti);
 
352
 
 
353
                        if (gti.hwndCapture)
 
354
                                hwnd = gti.hwndCapture;
 
355
 
 
356
                        ::PostMessage(hwnd, msg, w, l);
 
357
 
 
358
                        QMetaObject::invokeMethod(g.ocIntercept, "updateMouse", Qt::QueuedConnection);
 
359
 
 
360
                        suppress = true;
 
361
                }
 
362
#endif
 
363
 
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))
157
 
                                return 1;
 
393
                        bool wantsuppress = gsw->handleButton(ql, down);
 
394
                        if (! suppress)
 
395
                                suppress = wantsuppress && (btn != 3);
158
396
                }
 
397
                if (suppress)
 
398
                        return 1;
159
399
        }
160
400
        return CallNextHookEx(gsw->hhMouse, nCode, wParam, lParam);
161
401
}
233
473
                dipdw.dwData            = DX_SAMPLE_BUFFER_SIZE;
234
474
 
235
475
                if (FAILED(hr = id->pDID->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph)))
236
 
                        qFatal("GlobalShortcutWin::SetProperty");
 
476
                        qFatal("GlobalShortcutWin: SetProperty: %lx", hr);
237
477
 
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;
330
570
bool GlobalShortcutWin::canSuppress() {
331
571
        return true;
332
572
}
 
573
 
 
574
void GlobalShortcutWin::prepareInput() {
 
575
        SetKeyboardState(ucKeyState);
 
576
}