1
/****************************************************************************
2
**
3
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4
** All rights reserved.
5
** Contact: Nokia Corporation (qt-info@nokia.com)
6
**
7
** This file is part of the QtCore module of the Qt Toolkit.
8
**
9
** $QT_BEGIN_LICENSE:LGPL$
10
** GNU Lesser General Public License Usage
11
** This file may be used under the terms of the GNU Lesser General Public
12
** License version 2.1 as published by the Free Software Foundation and
13
** appearing in the file LICENSE.LGPL included in the packaging of this
14
** file. Please review the following information to ensure the GNU Lesser
15
** General Public License version 2.1 requirements will be met:
16
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17
**
18
** In addition, as a special exception, Nokia gives you certain additional
19
** rights. These rights are described in the Nokia Qt LGPL Exception
20
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21
**
22
** GNU General Public License Usage
23
** Alternatively, this file may be used under the terms of the GNU General
24
** Public License version 3.0 as published by the Free Software Foundation
25
** and appearing in the file LICENSE.GPL included in the packaging of this
26
** file. Please review the following information to ensure the GNU General
27
** Public License version 3.0 requirements will be met:
28
** http://www.gnu.org/copyleft/gpl.html.
29
**
30
** Other Usage
31
** Alternatively, this file may be used in accordance with the terms and
32
** conditions contained in a signed written agreement between you and Nokia.
33
**
34
**
35
**
36
**
37
**
38
** $QT_END_LICENSE$
39
**
40
****************************************************************************/
41
42
#include "qeventdispatcher_win_p.h"
43
44
#include "qcoreapplication.h"
45
#include "qhash.h"
46
#include <private/qsystemlibrary_p.h>
47
#include "qpair.h"
48
#include "qset.h"
49
#include "qsocketnotifier.h"
50
#include "qvarlengtharray.h"
51
#include "qwineventnotifier_p.h"
52
53
#include "qabstracteventdispatcher_p.h"
54
#include "qcoreapplication_p.h"
55
#include <private/qthread_p.h>
56
57
QT_BEGIN_NAMESPACE
58
59
HINSTANCE qWinAppInst();
60
extern uint qGlobalPostedEventsCount();
61
62
#ifndef TIME_KILL_SYNCHRONOUS
63
#  define TIME_KILL_SYNCHRONOUS 0x0100
64
#endif
65
66
#ifndef QS_RAWINPUT
67
# ifdef Q_OS_WINCE
68
#  define QS_RAWINPUT 0x0000
69
# else
70
#  define QS_RAWINPUT 0x0400
71
# endif
72
#endif
73
74
#ifndef WM_TOUCH
75
#  define WM_TOUCH 0x0240
76
#endif
77
#ifndef QT_NO_GESTURES
78
#ifndef WM_GESTURE
79
#  define WM_GESTURE 0x0119
80
#endif
81
#ifndef WM_GESTURENOTIFY
82
#  define WM_GESTURENOTIFY 0x011A
83
#endif
84
#endif // QT_NO_GESTURES
85
86
enum {
87
    WM_QT_SOCKETNOTIFIER = WM_USER,
88
    WM_QT_SENDPOSTEDEVENTS = WM_USER + 1,
89
    SendPostedEventsWindowsTimerId = ~1u
90
};
91
92
#if defined(Q_OS_WINCE)
93
QT_BEGIN_INCLUDE_NAMESPACE
94
#include <winsock.h>
95
// Asynchronous Winsocks ------------------------------------------
96
#ifndef QT_NO_THREAD
97
#include <qthread.h>
98
#include <qmap.h>
99
#include <qmutex.h>
100
QT_END_INCLUDE_NAMESPACE
101
102
//#define QCE_ASYNC_DEBUG
103
104
namespace {
105
    class SocketAsyncHandler;
106
107
    class SocketAsyncHandler : public QThread
108
    {
109
    public:
110
        SocketAsyncHandler();
111
        ~SocketAsyncHandler();
112
        void run();
113
        void select(SOCKET sock, HWND handle, unsigned int msg, long ev);
114
        void removeSelect(SOCKET sock);
115
        void safeRemove(SOCKET sock);
116
    private:
117
        struct SockInfo {
118
            HWND handle;
119
            unsigned int msg;
120
            long ev;
121
        };
122
        QMap<SOCKET, SockInfo> sockets;
123
        QMutex mutex;
124
        QWaitCondition cond;
125
        bool supposedToDie;
126
    };
127
128
    SocketAsyncHandler::SocketAsyncHandler()
129
        : supposedToDie(false)
130
    {
131
    }
132
133
    SocketAsyncHandler::~SocketAsyncHandler()
134
    {
135
        mutex.lock();
136
        supposedToDie = true;
137
        mutex.unlock();
138
        cond.wakeOne();
139
        wait();
140
        while (sockets.size() > 0)
141
            removeSelect(sockets.begin().key());
142
    }
143
144
    void SocketAsyncHandler::removeSelect(SOCKET sock)
145
    {
146
        if (!sockets.contains(sock))
147
            return;
148
        sockets.remove(sock);
149
        return;
150
    }
151
152
    void SocketAsyncHandler::safeRemove(SOCKET sock)
153
    {
154
        QMutexLocker locker(&mutex);
155
        removeSelect(sock);
156
    }
157
158
    void SocketAsyncHandler::select(SOCKET sock, HWND handle, unsigned int msg, long ev)
159
    {
160
        QMutexLocker locker(&mutex);
161
162
        if (sockets.contains(sock))
163
            sockets.remove(sock);
164
165
        SockInfo info;
166
        info.handle = handle;
167
        info.msg = msg;
168
        info.ev = ev;
169
        sockets.insert(sock, info);
170
        cond.wakeOne();
171
    }
172
173
    void SocketAsyncHandler::run()
174
    {
175
        do {
176
            mutex.lock();
177
178
            while (!supposedToDie && sockets.isEmpty()) {
179
                cond.wait(&mutex);
180
            }
181
182
            if (supposedToDie) {
183
                mutex.unlock();
184
                break;
185
            }
186
187
            // Copy current items to reduce lock time
188
            // and to be able to use SendMessage
189
            QMap<SOCKET, SockInfo> currentSockets = sockets;
190
            mutex.unlock();
191
192
            fd_set readS, writeS, exS;
193
            FD_ZERO(&readS);
194
            FD_ZERO(&writeS);
195
            FD_ZERO(&exS);
196
197
            int maxFd = 0;
198
199
            for (QMap<SOCKET, SockInfo>::iterator it = currentSockets.begin(); it != currentSockets.end(); ++it) {
200
                const SockInfo &info = it.value();
201
                int socket = it.key();
202
                maxFd = qMax(maxFd, socket);
203
204
                if ((info.ev & FD_READ) || (info.ev & FD_CLOSE) || (info.ev & FD_ACCEPT))
205
                    FD_SET(socket, &readS);
206
                if ((info.ev & FD_WRITE)|| (info.ev & FD_CONNECT))
207
                    FD_SET(socket, &writeS);
208
                if (info.ev & FD_OOB)
209
                    FD_SET(socket, &exS);
210
            }
211
212
            timeval timeout;
213
            timeout.tv_sec = 0;
214
            timeout.tv_usec = 50000;
215
            int result = ::select(maxFd + 1, &readS, &writeS, &exS, &timeout);
216
            if (result > 0) {
217
                HWND handle;
218
                unsigned int tmpMsg;
219
                SOCKET sock;
220
                HRESULT ret;
221
                for (QMap<SOCKET, SockInfo>::const_iterator it = currentSockets.constBegin();
222
                    it != currentSockets.constEnd(); ++it) {
223
                        handle = (*it).handle;
224
                        tmpMsg = (*it).msg;
225
                        sock = it.key();
226
                        if (FD_ISSET(sock, &readS))
227
                            ret = SendMessage(handle, tmpMsg, sock, FD_READ);
228
229
                        if (FD_ISSET(sock, &writeS))
230
                            ret = SendMessage(handle, tmpMsg, sock, FD_WRITE);
231
232
                        if (FD_ISSET(sock, &exS))
233
                            ret = SendMessage(handle, tmpMsg, sock, FD_OOB);
234
                }
235
            }
236
237
#ifdef QCE_ASYNC_DEBUG
238
            else if (result == 0) { //timeout
239
                qDebug("    WSAAsync select timeout");
240
            } else if (result < 0) { // SocketError
241
                // This might happen because of two reasons
242
                // 1. We already closed a socket in between the copy and the select
243
                //    and thus select() returns an error
244
                // 2. Something is really wrong, then
245
                //    ### Loop on all descriptors, try to select and remove the
246
                //    ### broken one.
247
                qWarning("WSAAsync select error %d", WSAGetLastError());
248
            }
249
#endif
250
        } while(true);
251
    }
252
} // namespace
253
254
Q_GLOBAL_STATIC(SocketAsyncHandler, qt_async_handler)
255
256
int WSAAsyncSelect(SOCKET sock, HWND handle, unsigned int msg, long ev)
257
{
258
    if (sock == 0 || handle == 0 || handle == INVALID_HANDLE_VALUE) {
259
        WSASetLastError(WSAEINVAL);
260
        return SOCKET_ERROR;
261
    }
262
263
    if (msg == 0 && ev == 0)
264
        qt_async_handler()->safeRemove(sock);
265
    else
266
        qt_async_handler()->select(sock, handle, msg, ev);
267
268
    qt_async_handler()->start(QThread::LowPriority);
269
    WSASetLastError(0);
270
    return 0;
271
}
272
#else // QT_NO_THREAD
273
int WSAAsyncSelect(SOCKET, HWND, unsigned int, long)
274
{
275
    return SOCKET_ERROR;
276
}
277
#endif
278
#endif // Q_OS_WINCE
279
280
class QEventDispatcherWin32Private;
281
282
struct QSockNot {
283
    QSocketNotifier *obj;
284
    int fd;
285
};
286
typedef QHash<int, QSockNot *> QSNDict;
287
288
struct WinTimerInfo {                           // internal timer info
289
    QObject *dispatcher;
290
    int timerId;
291
    int interval;
292
    QObject *obj;                               // - object to receive events
293
    bool inTimerEvent;
294
    int fastTimerId;
295
};
296
297
class QZeroTimerEvent : public QTimerEvent
298
{
299
public:
300
    inline QZeroTimerEvent(int timerId)
301
        : QTimerEvent(timerId)
302
    { t = QEvent::ZeroTimerEvent; }
303
};
304
305
typedef QList<WinTimerInfo*>  WinTimerVec;      // vector of TimerInfo structs
306
typedef QHash<int, WinTimerInfo*> WinTimerDict; // fast dict of timers
307
308
#if !defined(DWORD_PTR) && !defined(Q_WS_WIN64)
309
#define DWORD_PTR DWORD
310
#endif
311
312
typedef MMRESULT(WINAPI *ptimeSetEvent)(UINT, UINT, LPTIMECALLBACK, DWORD_PTR, UINT);
313
typedef MMRESULT(WINAPI *ptimeKillEvent)(UINT);
314
315
static ptimeSetEvent qtimeSetEvent = 0;
316
static ptimeKillEvent qtimeKillEvent = 0;
317
318
LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp);
319
320
static void resolveTimerAPI()
321
{
322
    static bool triedResolve = false;
323
    if (!triedResolve) {
324
#ifndef Q_OS_WINCE
325
        QSystemLibrary library(QLatin1String("Mmtimer"));
326
#else
327
        QSystemLibrary library(QLatin1String("winmm"));
328
#endif
329
        if (library.load()) {
330
            qtimeSetEvent = (ptimeSetEvent)library.resolve("timeSetEvent");
331
            qtimeKillEvent = (ptimeKillEvent)library.resolve("timeKillEvent");
332
        }
333
334
        triedResolve = true;
335
    }
336
}
337
338
339
class QEventDispatcherWin32Private : public QAbstractEventDispatcherPrivate
340
{
341
    Q_DECLARE_PUBLIC(QEventDispatcherWin32)
342
public:
343
    QEventDispatcherWin32Private();
344
    ~QEventDispatcherWin32Private();
345
346
    DWORD threadId;
347
348
    bool interrupt;
349
350
    // internal window handle used for socketnotifiers/timers/etc
351
    HWND internalHwnd;
352
    HHOOK getMessageHook;
353
354
    // for controlling when to send posted events
355
    QAtomicInt serialNumber;
356
    int lastSerialNumber, sendPostedEventsWindowsTimerId;
357
    QAtomicInt wakeUps;
358
359
    // timers
360
    WinTimerVec timerVec;
361
    WinTimerDict timerDict;
362
    void registerTimer(WinTimerInfo *t);
363
    void unregisterTimer(WinTimerInfo *t, bool closingDown = false);
364
    void sendTimerEvent(int timerId);
365
366
    // socket notifiers
367
    QSNDict sn_read;
368
    QSNDict sn_write;
369
    QSNDict sn_except;
370
    void doWsaAsyncSelect(int socket);
371
372
    QList<QWinEventNotifier *> winEventNotifierList;
373
    void activateEventNotifier(QWinEventNotifier * wen);
374
375
    QList<MSG> queuedUserInputEvents;
376
    QList<MSG> queuedSocketEvents;
377
};
378
379
QEventDispatcherWin32Private::QEventDispatcherWin32Private()
380
    : threadId(GetCurrentThreadId()), interrupt(false), internalHwnd(0), getMessageHook(0),
381
      serialNumber(0), lastSerialNumber(0), sendPostedEventsWindowsTimerId(0), wakeUps(0)
382
{
383
    resolveTimerAPI();
384
}
385
386
QEventDispatcherWin32Private::~QEventDispatcherWin32Private()
387
{
388
    if (internalHwnd)
389
        DestroyWindow(internalHwnd);
390
    QString className = QLatin1String("QEventDispatcherWin32_Internal_Widget") + QString::number(quintptr(qt_internal_proc));
391
    UnregisterClass((wchar_t*)className.utf16(), qWinAppInst());
392
}
393
394
void QEventDispatcherWin32Private::activateEventNotifier(QWinEventNotifier * wen)
395
{
396
    QEvent event(QEvent::WinEventAct);
397
    QCoreApplication::sendEvent(wen, &event);
398
}
399
400
// ### Qt 5: remove
401
Q_CORE_EXPORT bool winPeekMessage(MSG* msg, HWND hWnd, UINT wMsgFilterMin,
402
                     UINT wMsgFilterMax, UINT wRemoveMsg)
403
{
404
    return PeekMessage(msg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
405
}
406
407
// ### Qt 5: remove
408
Q_CORE_EXPORT bool winPostMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
409
{
410
    return PostMessage(hWnd, msg, wParam, lParam);
411
}
412
413
// ### Qt 5: remove
414
Q_CORE_EXPORT bool winGetMessage(MSG* msg, HWND hWnd, UINT wMsgFilterMin,
415
                     UINT wMsgFilterMax)
416
{
417
    return GetMessage(msg, hWnd, wMsgFilterMin, wMsgFilterMax);
418
}
419
420
// This function is called by a workerthread
421
void WINAPI QT_WIN_CALLBACK qt_fast_timer_proc(uint timerId, uint /*reserved*/, DWORD_PTR user, DWORD_PTR /*reserved*/, DWORD_PTR /*reserved*/)
422
{
423
    if (!timerId) // sanity check
424
        return;
425
    WinTimerInfo *t = (WinTimerInfo*)user;
426
    Q_ASSERT(t);
427
    QCoreApplication::postEvent(t->dispatcher, new QTimerEvent(t->timerId));
428
}
429
430
LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp)
431
{
432
    if (message == WM_NCCREATE)
433
        return true;
434
435
    MSG msg;
436
    msg.hwnd = hwnd;
437
    msg.message = message;
438
    msg.wParam = wp;
439
    msg.lParam = lp;
440
    QCoreApplication *app = QCoreApplication::instance();
441
    long result;
442
    if (!app) {
443
        if (message == WM_TIMER)
444
            KillTimer(hwnd, wp);
445
        return 0;
446
    } else if (app->filterEvent(&msg, &result)) {
447
        return result;
448
    }
449
450
#ifdef GWLP_USERDATA
451
    QEventDispatcherWin32 *q = (QEventDispatcherWin32 *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
452
#else
453
    QEventDispatcherWin32 *q = (QEventDispatcherWin32 *) GetWindowLong(hwnd, GWL_USERDATA);
454
#endif
455
    QEventDispatcherWin32Private *d = 0;
456
    if (q != 0)
457
        d = q->d_func();
458
459
    if (message == WM_QT_SOCKETNOTIFIER) {
460
        // socket notifier message
461
        int type = -1;
462
        switch (WSAGETSELECTEVENT(lp)) {
463
        case FD_READ:
464
        case FD_CLOSE:
465
        case FD_ACCEPT:
466
            type = 0;
467
            break;
468
        case FD_WRITE:
469
        case FD_CONNECT:
470
            type = 1;
471
            break;
472
        case FD_OOB:
473
            type = 2;
474
            break;
475
        }
476
        if (type >= 0) {
477
            Q_ASSERT(d != 0);
478
            QSNDict *sn_vec[3] = { &d->sn_read, &d->sn_write, &d->sn_except };
479
            QSNDict *dict = sn_vec[type];
480
481
            QSockNot *sn = dict ? dict->value(wp) : 0;
482
            if (sn) {
483
                QEvent event(QEvent::SockAct);
484
                QCoreApplication::sendEvent(sn->obj, &event);
485
            }
486
        }
487
        return 0;
488
    } else if (message == WM_QT_SENDPOSTEDEVENTS
489
               // we also use a Windows timer to send posted events when the message queue is full
490
               || (message == WM_TIMER
491
                   && d->sendPostedEventsWindowsTimerId != 0
492
                   && wp == (uint)d->sendPostedEventsWindowsTimerId)) {
493
        int localSerialNumber = d->serialNumber;
494
        if (localSerialNumber != d->lastSerialNumber) {
495
            d->lastSerialNumber = localSerialNumber;
496
            QCoreApplicationPrivate::sendPostedEvents(0, 0, d->threadData);
497
        }
498
        return 0;
499
    } else if (message == WM_TIMER) {
500
        Q_ASSERT(d != 0);
501
        d->sendTimerEvent(wp);
502
        return 0;
503
    }
504
505
    return DefWindowProc(hwnd, message, wp, lp);
506
}
507
508
LRESULT QT_WIN_CALLBACK qt_GetMessageHook(int code, WPARAM wp, LPARAM lp)
509
{
510
    if (wp == PM_REMOVE) {
511
        QEventDispatcherWin32 *q = qobject_cast<QEventDispatcherWin32 *>(QAbstractEventDispatcher::instance());
512
        Q_ASSERT(q != 0);
513
        if (q) {
514
            MSG *msg = (MSG *) lp;
515
            QEventDispatcherWin32Private *d = q->d_func();
516
            int localSerialNumber = d->serialNumber;
517
            if (HIWORD(GetQueueStatus(QS_TIMER | QS_INPUT | QS_RAWINPUT)) == 0) {
518
                // no more input or timer events in the message queue, we can allow posted events to be sent normally now
519
                if (d->sendPostedEventsWindowsTimerId != 0) {
520
                    // stop the timer to send posted events, since we now allow the WM_QT_SENDPOSTEDEVENTS message
521
                    KillTimer(d->internalHwnd, d->sendPostedEventsWindowsTimerId);
522
                    d->sendPostedEventsWindowsTimerId = 0;
523
                }
524
                (void) d->wakeUps.fetchAndStoreRelease(0);
525
                if (localSerialNumber != d->lastSerialNumber
526
                    // if this message IS the one that triggers sendPostedEvents(), no need to post it again
527
                    && (msg->hwnd != d->internalHwnd
528
                        || msg->message != WM_QT_SENDPOSTEDEVENTS)) {
529
                    PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS, 0, 0);
530
                }
531
            } else if (d->sendPostedEventsWindowsTimerId == 0
532
                       && localSerialNumber != d->lastSerialNumber) {
533
                // start a special timer to continue delivering posted events while
534
                // there are still input and timer messages in the message queue
535
                d->sendPostedEventsWindowsTimerId = SetTimer(d->internalHwnd,
536
                                                             SendPostedEventsWindowsTimerId,
537
                                                             0, // we specify zero, but Windows uses USER_TIMER_MINIMUM
538
                                                             NULL);
539
                // we don't check the return value of SetTimer()... if creating the timer failed, there's little
540
                // we can do. we just have to accept that posted events will be starved
541
            }
542
        }
543
    }
544
#ifdef Q_OS_WINCE
545
    Q_UNUSED(code);
546
    return 0;
547
#else
548
    return CallNextHookEx(0, code, wp, lp);
549
#endif
550
}
551
552
static HWND qt_create_internal_window(const QEventDispatcherWin32 *eventDispatcher)
553
{
554
    // make sure that multiple Qt's can coexist in the same process
555
    QString className = QLatin1String("QEventDispatcherWin32_Internal_Widget") + QString::number(quintptr(qt_internal_proc));
556
557
    WNDCLASS wc;
558
    wc.style = 0;
559
    wc.lpfnWndProc = qt_internal_proc;
560
    wc.cbClsExtra = 0;
561
    wc.cbWndExtra = 0;
562
    wc.hInstance = qWinAppInst();
563
    wc.hIcon = 0;
564
    wc.hCursor = 0;
565
    wc.hbrBackground = 0;
566
    wc.lpszMenuName = NULL;
567
    wc.lpszClassName = reinterpret_cast<const wchar_t *> (className.utf16());
568
569
    RegisterClass(&wc);
570
    HWND wnd = CreateWindow(wc.lpszClassName,  // classname
571
                            wc.lpszClassName,  // window name
572
                            0,                 // style
573
                            0, 0, 0, 0,        // geometry
574
                            0,                 // parent
575
                            0,                 // menu handle
576
                            qWinAppInst(),     // application
577
                            0);                // windows creation data.
578
579
    if (!wnd) {
580
        qWarning("QEventDispatcher: Failed to create QEventDispatcherWin32 internal window: %d\n", (int)GetLastError());
581
    }
582
583
#ifdef GWLP_USERDATA
584
    SetWindowLongPtr(wnd, GWLP_USERDATA, (LONG_PTR)eventDispatcher);
585
#else
586
    SetWindowLong(wnd, GWL_USERDATA, (LONG)eventDispatcher);
587
#endif
588
589
    return wnd;
590
}
591
592
void QEventDispatcherWin32Private::registerTimer(WinTimerInfo *t)
593
{
594
    Q_ASSERT(internalHwnd);
595
596
    Q_Q(QEventDispatcherWin32);
597
598
    int ok = 0;
599
    if (t->interval > 20 || !t->interval || !qtimeSetEvent) {
600
        ok = 1;
601
        if (!t->interval)  // optimization for single-shot-zero-timer
602
            QCoreApplication::postEvent(q, new QZeroTimerEvent(t->timerId));
603
        else
604
            ok = SetTimer(internalHwnd, t->timerId, (uint) t->interval, 0);
605
    } else {
606
        ok = t->fastTimerId = qtimeSetEvent(t->interval, 1, qt_fast_timer_proc, (DWORD_PTR)t,
607
                                            TIME_CALLBACK_FUNCTION | TIME_PERIODIC | TIME_KILL_SYNCHRONOUS);
608
        if (ok == 0) { // fall back to normal timer if no more multimedia timers available
609
            ok = SetTimer(internalHwnd, t->timerId, (uint) t->interval, 0);
610
        }
611
    }
612
613
    if (ok == 0)
614
        qErrnoWarning("QEventDispatcherWin32::registerTimer: Failed to create a timer");
615
}
616
617
void QEventDispatcherWin32Private::unregisterTimer(WinTimerInfo *t, bool closingDown)
618
{
619
    // mark timer as unused
620
    if (!QObjectPrivate::get(t->obj)->inThreadChangeEvent && !closingDown)
621
        QAbstractEventDispatcherPrivate::releaseTimerId(t->timerId);
622
623
    if (t->interval == 0) {
624
        QCoreApplicationPrivate::removePostedTimerEvent(t->dispatcher, t->timerId);
625
    } else if (t->fastTimerId != 0) {
626
        qtimeKillEvent(t->fastTimerId);
627
        QCoreApplicationPrivate::removePostedTimerEvent(t->dispatcher, t->timerId);
628
    } else if (internalHwnd) {
629
        KillTimer(internalHwnd, t->timerId);
630
    }
631
    delete t;
632
}
633
634
void QEventDispatcherWin32Private::sendTimerEvent(int timerId)
635
{
636
    WinTimerInfo *t = timerDict.value(timerId);
637
    if (t && !t->inTimerEvent) {
638
        // send event, but don't allow it to recurse
639
        t->inTimerEvent = true;
640
641
        QTimerEvent e(t->timerId);
642
        QCoreApplication::sendEvent(t->obj, &e);
643
644
        // timer could have been removed
645
        t = timerDict.value(timerId);
646
        if (t) {
647
            t->inTimerEvent = false;
648
        }
649
    }
650
}
651
652
void QEventDispatcherWin32Private::doWsaAsyncSelect(int socket)
653
{
654
    Q_ASSERT(internalHwnd);
655
    int sn_event = 0;
656
    if (sn_read.contains(socket))
657
        sn_event |= FD_READ | FD_CLOSE | FD_ACCEPT;
658
    if (sn_write.contains(socket))
659
        sn_event |= FD_WRITE | FD_CONNECT;
660
    if (sn_except.contains(socket))
661
        sn_event |= FD_OOB;
662
    // BoundsChecker may emit a warning for WSAAsyncSelect when sn_event == 0
663
    // This is a BoundsChecker bug and not a Qt bug
664
    WSAAsyncSelect(socket, internalHwnd, sn_event ? WM_QT_SOCKETNOTIFIER : 0, sn_event);
665
}
666
667
void QEventDispatcherWin32::createInternalHwnd()
668
{
669
    Q_D(QEventDispatcherWin32);
670
671
    Q_ASSERT(!d->internalHwnd);
672
    if (d->internalHwnd)
673
        return;
674
    d->internalHwnd = qt_create_internal_window(this);
675
676
#ifndef Q_OS_WINCE
677
    // setup GetMessage hook needed to drive our posted events
678
    d->getMessageHook = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC) qt_GetMessageHook, NULL, GetCurrentThreadId());
679
    if (!d->getMessageHook) {
680
        qFatal("Qt: INTERNALL ERROR: failed to install GetMessage hook");
681
    }
682
#endif
683
684
    // register all socket notifiers
685
    QList<int> sockets = (d->sn_read.keys().toSet()
686
                          + d->sn_write.keys().toSet()
687
                          + d->sn_except.keys().toSet()).toList();
688
    for (int i = 0; i < sockets.count(); ++i)
689
        d->doWsaAsyncSelect(sockets.at(i));
690
691
    // start all normal timers
692
    for (int i = 0; i < d->timerVec.count(); ++i)
693
        d->registerTimer(d->timerVec.at(i));
694
695
    // trigger a call to sendPostedEvents()
696
    wakeUp();
697
}
698
699
QEventDispatcherWin32::QEventDispatcherWin32(QObject *parent)
700
    : QAbstractEventDispatcher(*new QEventDispatcherWin32Private, parent)
701
{
702
}
703
704
QEventDispatcherWin32::~QEventDispatcherWin32()
705
{
706
}
707
708
bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
709
{
710
    Q_D(QEventDispatcherWin32);
711
712
    if (!d->internalHwnd)
713
        createInternalHwnd();
714
715
    d->interrupt = false;
716
    emit awake();
717
718
    bool canWait;
719
    bool retVal = false;
720
    bool seenWM_QT_SENDPOSTEDEVENTS = false;
721
    bool needWM_QT_SENDPOSTEDEVENTS = false;
722
    do {
723
        DWORD waitRet = 0;
724
        HANDLE pHandles[MAXIMUM_WAIT_OBJECTS - 1];
725
        QVarLengthArray<MSG> processedTimers;
726
        while (!d->interrupt) {
727
            DWORD nCount = d->winEventNotifierList.count();
728
            Q_ASSERT(nCount < MAXIMUM_WAIT_OBJECTS - 1);
729
730
            MSG msg;
731
            bool haveMessage;
732
733
            if (!(flags & QEventLoop::ExcludeUserInputEvents) && !d->queuedUserInputEvents.isEmpty()) {
734
                // process queued user input events
735
                haveMessage = true;
736
                msg = d->queuedUserInputEvents.takeFirst();
737
            } else if(!(flags & QEventLoop::ExcludeSocketNotifiers) && !d->queuedSocketEvents.isEmpty()) {
738
                // process queued socket events
739
                haveMessage = true;
740
                msg = d->queuedSocketEvents.takeFirst();
741
            } else {
742
                haveMessage = PeekMessage(&msg, 0, 0, 0, PM_REMOVE);
743
                if (haveMessage && (flags & QEventLoop::ExcludeUserInputEvents)
744
                    && ((msg.message >= WM_KEYFIRST
745
                         && msg.message <= WM_KEYLAST)
746
                        || (msg.message >= WM_MOUSEFIRST
747
                            && msg.message <= WM_MOUSELAST)
748
                        || msg.message == WM_MOUSEWHEEL
749
                        || msg.message == WM_MOUSEHWHEEL
750
                        || msg.message == WM_TOUCH
751
#ifndef QT_NO_GESTURES
752
                        || msg.message == WM_GESTURE
753
                        || msg.message == WM_GESTURENOTIFY
754
#endif
755
                        || msg.message == WM_CLOSE)) {
756
                    // queue user input events for later processing
757
                    haveMessage = false;
758
                    d->queuedUserInputEvents.append(msg);
759
                }
760
                if (haveMessage && (flags & QEventLoop::ExcludeSocketNotifiers)
761
                    && (msg.message == WM_QT_SOCKETNOTIFIER && msg.hwnd == d->internalHwnd)) {
762
                    // queue socket events for later processing
763
                    haveMessage = false;
764
                    d->queuedSocketEvents.append(msg);
765
                }
766
            }
767
            if (!haveMessage) {
768
                // no message - check for signalled objects
769
                for (int i=0; i<(int)nCount; i++)
770
                    pHandles[i] = d->winEventNotifierList.at(i)->handle();
771
                waitRet = MsgWaitForMultipleObjectsEx(nCount, pHandles, 0, QS_ALLINPUT, MWMO_ALERTABLE);
772
                if ((haveMessage = (waitRet == WAIT_OBJECT_0 + nCount))) {
773
                    // a new message has arrived, process it
774
                    continue;
775
                }
776
            }
777
            if (haveMessage) {
778
#ifdef Q_OS_WINCE
779
                // WinCE doesn't support hooks at all, so we have to call this by hand :(
780
                (void) qt_GetMessageHook(0, PM_REMOVE, (LPARAM) &msg);
781
#endif
782
783
                if (d->internalHwnd == msg.hwnd && msg.message == WM_QT_SENDPOSTEDEVENTS) {
784
                    if (seenWM_QT_SENDPOSTEDEVENTS) {
785
                        // when calling processEvents() "manually", we only want to send posted
786
                        // events once
787
                        needWM_QT_SENDPOSTEDEVENTS = true;
788
                        continue;
789
                    }
790
                    seenWM_QT_SENDPOSTEDEVENTS = true;
791
                } else if (msg.message == WM_TIMER) {
792
                    // avoid live-lock by keeping track of the timers we've already sent
793
                    bool found = false;
794
                    for (int i = 0; !found && i < processedTimers.count(); ++i) {
795
                        const MSG processed = processedTimers.constData()[i];
796
                        found = (processed.wParam == msg.wParam && processed.hwnd == msg.hwnd && processed.lParam == msg.lParam);
797
                    }
798
                    if (found)
799
                        continue;
800
                    processedTimers.append(msg);
801
                } else if (msg.message == WM_QUIT) {
802
                    if (QCoreApplication::instance())
803
                        QCoreApplication::instance()->quit();
804
                    return false;
805
                }
806
807
                if (!filterEvent(&msg)) {
808
                    TranslateMessage(&msg);
809
                    DispatchMessage(&msg);
810
                }
811
            } else if (waitRet >= WAIT_OBJECT_0 && waitRet < WAIT_OBJECT_0 + nCount) {
812
                d->activateEventNotifier(d->winEventNotifierList.at(waitRet - WAIT_OBJECT_0));
813
            } else {
814
                // nothing todo so break
815
                break;
816
            }
817
            retVal = true;
818
        }
819
820
        // still nothing - wait for message or signalled objects
821
        canWait = (!retVal
822
                   && !d->interrupt
823
                   && (flags & QEventLoop::WaitForMoreEvents));
824
        if (canWait) {
825
            DWORD nCount = d->winEventNotifierList.count();
826
            Q_ASSERT(nCount < MAXIMUM_WAIT_OBJECTS - 1);
827
            for (int i=0; i<(int)nCount; i++)
828
                pHandles[i] = d->winEventNotifierList.at(i)->handle();
829
830
            emit aboutToBlock();
831
            waitRet = MsgWaitForMultipleObjectsEx(nCount, pHandles, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE | MWMO_INPUTAVAILABLE);
832
            emit awake();
833
            if (waitRet >= WAIT_OBJECT_0 && waitRet < WAIT_OBJECT_0 + nCount) {
834
                d->activateEventNotifier(d->winEventNotifierList.at(waitRet - WAIT_OBJECT_0));
835
                retVal = true;
836
            }
837
        }
838
    } while (canWait);
839
840
    if (!seenWM_QT_SENDPOSTEDEVENTS && (flags & QEventLoop::EventLoopExec) == 0) {
841
        // when called "manually", always send posted events
842
        QCoreApplicationPrivate::sendPostedEvents(0, 0, d->threadData);
843
    }
844
845
    if (needWM_QT_SENDPOSTEDEVENTS)
846
        PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS, 0, 0);
847
848
    return retVal;
849
}
850
851
bool QEventDispatcherWin32::hasPendingEvents()
852
{
853
    MSG msg;
854
    return qGlobalPostedEventsCount() || PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
855
}
856
857
void QEventDispatcherWin32::registerSocketNotifier(QSocketNotifier *notifier)
858
{
859
    Q_ASSERT(notifier);
860
    int sockfd = notifier->socket();
861
    int type = notifier->type();
862
#ifndef QT_NO_DEBUG
863
    if (sockfd < 0) {
864
        qWarning("QSocketNotifier: Internal error");
865
        return;
866
    } else if (notifier->thread() != thread() || thread() != QThread::currentThread()) {
867
        qWarning("QSocketNotifier: socket notifiers cannot be enabled from another thread");
868
        return;
869
    }
870
#endif
871
872
    Q_D(QEventDispatcherWin32);
873
    QSNDict *sn_vec[3] = { &d->sn_read, &d->sn_write, &d->sn_except };
874
    QSNDict *dict = sn_vec[type];
875
876
    if (QCoreApplication::closingDown()) // ### d->exitloop?
877
        return; // after sn_cleanup, don't reinitialize.
878
879
    if (dict->contains(sockfd)) {
880
        const char *t[] = { "Read", "Write", "Exception" };
881
    /* Variable "socket" below is a function pointer. */
882
        qWarning("QSocketNotifier: Multiple socket notifiers for "
883
                 "same socket %d and type %s", sockfd, t[type]);
884
    }
885
886
    QSockNot *sn = new QSockNot;
887
    sn->obj = notifier;
888
    sn->fd  = sockfd;
889
    dict->insert(sn->fd, sn);
890
891
    if (d->internalHwnd)
892
        d->doWsaAsyncSelect(sockfd);
893
}
894
895
void QEventDispatcherWin32::unregisterSocketNotifier(QSocketNotifier *notifier)
896
{
897
    Q_ASSERT(notifier);
898
    int sockfd = notifier->socket();
899
    int type = notifier->type();
900
#ifndef QT_NO_DEBUG
901
    if (sockfd < 0) {
902
        qWarning("QSocketNotifier: Internal error");
903
        return;
904
    } else if (notifier->thread() != thread() || thread() != QThread::currentThread()) {
905
        qWarning("QSocketNotifier: socket notifiers cannot be disabled from another thread");
906
        return;
907
    }
908
#endif
909
910
    Q_D(QEventDispatcherWin32);
911
    QSNDict *sn_vec[3] = { &d->sn_read, &d->sn_write, &d->sn_except };
912
    QSNDict *dict = sn_vec[type];
913
    QSockNot *sn = dict->value(sockfd);
914
    if (!sn)
915
        return;
916
917
    dict->remove(sockfd);
918
    delete sn;
919
920
    if (d->internalHwnd)
921
        d->doWsaAsyncSelect(sockfd);
922
}
923
924
void QEventDispatcherWin32::registerTimer(int timerId, int interval, QObject *object)
925
{
926
    if (timerId < 1 || interval < 0 || !object) {
927
        qWarning("QEventDispatcherWin32::registerTimer: invalid arguments");
928
        return;
929
    } else if (object->thread() != thread() || thread() != QThread::currentThread()) {
930
        qWarning("QObject::startTimer: timers cannot be started from another thread");
931
        return;
932
    }
933
934
    Q_D(QEventDispatcherWin32);
935
936
    register WinTimerInfo *t = new WinTimerInfo;
937
    t->dispatcher = this;
938
    t->timerId  = timerId;
939
    t->interval = interval;
940
    t->obj  = object;
941
    t->inTimerEvent = false;
942
    t->fastTimerId = 0;
943
944
    if (d->internalHwnd)
945
        d->registerTimer(t);
946
947
    d->timerVec.append(t);                      // store in timer vector
948
    d->timerDict.insert(t->timerId, t);          // store timers in dict
949
}
950
951
bool QEventDispatcherWin32::unregisterTimer(int timerId)
952
{
953
    if (timerId < 1) {
954
        qWarning("QEventDispatcherWin32::unregisterTimer: invalid argument");
955
        return false;
956
    }
957
    QThread *currentThread = QThread::currentThread();
958
    if (thread() != currentThread) {
959
        qWarning("QObject::killTimer: timers cannot be stopped from another thread");
960
        return false;
961
    }
962
963
    Q_D(QEventDispatcherWin32);
964
    if (d->timerVec.isEmpty() || timerId <= 0)
965
        return false;
966
967
    WinTimerInfo *t = d->timerDict.value(timerId);
968
    if (!t)
969
        return false;
970
971
    d->timerDict.remove(t->timerId);
972
    d->timerVec.removeAll(t);
973
    d->unregisterTimer(t);
974
    return true;
975
}
976
977
bool QEventDispatcherWin32::unregisterTimers(QObject *object)
978
{
979
    if (!object) {
980
        qWarning("QEventDispatcherWin32::unregisterTimers: invalid argument");
981
        return false;
982
    }
983
    QThread *currentThread = QThread::currentThread();
984
    if (object->thread() != thread() || thread() != currentThread) {
985
        qWarning("QObject::killTimers: timers cannot be stopped from another thread");
986
        return false;
987
    }
988
989
    Q_D(QEventDispatcherWin32);
990
    if (d->timerVec.isEmpty())
991
        return false;
992
    register WinTimerInfo *t;
993
    for (int i=0; i<d->timerVec.size(); i++) {
994
        t = d->timerVec.at(i);
995
        if (t && t->obj == object) {                // object found
996
            d->timerDict.remove(t->timerId);
997
            d->timerVec.removeAt(i);
998
            d->unregisterTimer(t);
999
            --i;
1000
        }
1001
    }
1002
    return true;
1003
}
1004
1005
QList<QEventDispatcherWin32::TimerInfo>
1006
QEventDispatcherWin32::registeredTimers(QObject *object) const
1007
{
1008
    if (!object) {
1009
        qWarning("QEventDispatcherWin32:registeredTimers: invalid argument");
1010
        return QList<TimerInfo>();
1011
    }
1012
1013
    Q_D(const QEventDispatcherWin32);
1014
    QList<TimerInfo> list;
1015
    for (int i = 0; i < d->timerVec.size(); ++i) {
1016
        const WinTimerInfo *t = d->timerVec.at(i);
1017
        if (t && t->obj == object)
1018
            list << TimerInfo(t->timerId, t->interval);
1019
    }
1020
    return list;
1021
}
1022
1023
bool QEventDispatcherWin32::registerEventNotifier(QWinEventNotifier *notifier)
1024
{
1025
    if (!notifier) {
1026
        qWarning("QWinEventNotifier: Internal error");
1027
        return false;
1028
    } else if (notifier->thread() != thread() || thread() != QThread::currentThread()) {
1029
        qWarning("QWinEventNotifier: event notifiers cannot be enabled from another thread");
1030
        return false;
1031
    }
1032
1033
    Q_D(QEventDispatcherWin32);
1034
1035
    if (d->winEventNotifierList.contains(notifier))
1036
        return true;
1037
1038
    if (d->winEventNotifierList.count() >= MAXIMUM_WAIT_OBJECTS - 2) {
1039
        qWarning("QWinEventNotifier: Cannot have more than %d enabled at one time", MAXIMUM_WAIT_OBJECTS - 2);
1040
        return false;
1041
    }
1042
    d->winEventNotifierList.append(notifier);
1043
    return true;
1044
}
1045
1046
void QEventDispatcherWin32::unregisterEventNotifier(QWinEventNotifier *notifier)
1047
{
1048
    if (!notifier) {
1049
        qWarning("QWinEventNotifier: Internal error");
1050
        return;
1051
    } else if (notifier->thread() != thread() || thread() != QThread::currentThread()) {
1052
        qWarning("QWinEventNotifier: event notifiers cannot be disabled from another thread");
1053
        return;
1054
    }
1055
1056
    Q_D(QEventDispatcherWin32);
1057
1058
    int i = d->winEventNotifierList.indexOf(notifier);
1059
    if (i != -1)
1060
        d->winEventNotifierList.takeAt(i);
1061
}
1062
1063
void QEventDispatcherWin32::activateEventNotifiers()
1064
{
1065
    Q_D(QEventDispatcherWin32);
1066
    //### this could break if events are removed/added in the activation
1067
    for (int i=0; i<d->winEventNotifierList.count(); i++) {
1068
#if !defined(Q_OS_WINCE)
1069
        if (WaitForSingleObjectEx(d->winEventNotifierList.at(i)->handle(), 0, TRUE) == WAIT_OBJECT_0)
1070
            d->activateEventNotifier(d->winEventNotifierList.at(i));
1071
#else
1072
        if (WaitForSingleObject(d->winEventNotifierList.at(i)->handle(), 0) == WAIT_OBJECT_0)
1073
            d->activateEventNotifier(d->winEventNotifierList.at(i));
1074
#endif
1075
    }
1076
}
1077
1078
void QEventDispatcherWin32::wakeUp()
1079
{
1080
    Q_D(QEventDispatcherWin32);
1081
    d->serialNumber.ref();
1082
    if (d->internalHwnd && d->wakeUps.testAndSetAcquire(0, 1)) {
1083
        // post a WM_QT_SENDPOSTEDEVENTS to this thread if there isn't one already pending
1084
        PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS, 0, 0);
1085
    }
1086
}
1087
1088
void QEventDispatcherWin32::interrupt()
1089
{
1090
    Q_D(QEventDispatcherWin32);
1091
    d->interrupt = true;
1092
    wakeUp();
1093
}
1094
1095
void QEventDispatcherWin32::flush()
1096
{ }
1097
1098
void QEventDispatcherWin32::startingUp()
1099
{ }
1100
1101
void QEventDispatcherWin32::closingDown()
1102
{
1103
    Q_D(QEventDispatcherWin32);
1104
1105
    // clean up any socketnotifiers
1106
    while (!d->sn_read.isEmpty())
1107
        unregisterSocketNotifier((*(d->sn_read.begin()))->obj);
1108
    while (!d->sn_write.isEmpty())
1109
        unregisterSocketNotifier((*(d->sn_write.begin()))->obj);
1110
    while (!d->sn_except.isEmpty())
1111
        unregisterSocketNotifier((*(d->sn_except.begin()))->obj);
1112
1113
    // clean up any timers
1114
    for (int i = 0; i < d->timerVec.count(); ++i)
1115
        d->unregisterTimer(d->timerVec.at(i), true);
1116
    d->timerVec.clear();
1117
    d->timerDict.clear();
1118
1119
#ifndef Q_OS_WINCE
1120
    if (d->getMessageHook)
1121
        UnhookWindowsHookEx(d->getMessageHook);
1122
    d->getMessageHook = 0;
1123
#endif
1124
}
1125
1126
bool QEventDispatcherWin32::event(QEvent *e)
1127
{
1128
    Q_D(QEventDispatcherWin32);
1129
    if (e->type() == QEvent::ZeroTimerEvent) {
1130
        QZeroTimerEvent *zte = static_cast<QZeroTimerEvent*>(e);
1131
        WinTimerInfo *t = d->timerDict.value(zte->timerId());
1132
        if (t) {
1133
            t->inTimerEvent = true;
1134
1135
            QTimerEvent te(zte->timerId());
1136
            QCoreApplication::sendEvent(t->obj, &te);
1137
1138
            t = d->timerDict.value(zte->timerId());
1139
            if (t) {
1140
                if (t->interval == 0 && t->inTimerEvent) {
1141
                    // post the next zero timer event as long as the timer was not restarted
1142
                    QCoreApplication::postEvent(this, new QZeroTimerEvent(zte->timerId()));
1143
                }
1144
1145
                t->inTimerEvent = false;
1146
            }
1147
        }
1148
        return true;
1149
    } else if (e->type() == QEvent::Timer) {
1150
        QTimerEvent *te = static_cast<QTimerEvent*>(e);
1151
        d->sendTimerEvent(te->timerId());
1152
    }
1153
    return QAbstractEventDispatcher::event(e);
1154
}
1155
1156
QT_END_NAMESPACE