source: trunk/src/gui/kernel/qapplication_win.cpp@ 744

Last change on this file since 744 was 651, checked in by Dmitry A. Kuminov, 16 years ago

trunk: Merged in qt 4.6.2 sources.

File size: 149.0 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtGui module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#ifdef Q_WS_WINCE
43#include "qguifunctions_wince.h"
44#include "qmenubar.h"
45extern bool qt_wince_is_mobile(); //defined in qguifunctions_wince.cpp
46extern bool qt_wince_is_high_dpi(); //defined in qguifunctions_wince.cpp
47extern bool qt_wince_is_smartphone(); //defined in qguifunctions_wince.cpp
48extern bool qt_wince_is_pocket_pc(); //defined in qguifunctions_wince.cpp
49extern void qt_wince_hide_taskbar(HWND hwnd); //defined in qguifunctions_wince.cpp
50#endif
51#ifdef Q_WS_WINCE_WM
52#include <windowsm.h>
53#include <tpcshell.h>
54#ifdef QT_WINCE_GESTURES
55#include <gesture.h>
56#endif
57#endif
58
59#include "qapplication.h"
60#include "qdesktopwidget.h"
61#include "qevent.h"
62#include "private/qeventdispatcher_win_p.h"
63#include "qeventloop.h"
64#include "qclipboard.h"
65#include "qcursor.h"
66#include "qdatetime.h"
67#include "qpointer.h"
68#include "qhash.h"
69#include "qlibrary.h"
70#include "qmetaobject.h"
71#include "qmime.h"
72#include "qpainter.h"
73#include "qpixmapcache.h"
74#include "qsessionmanager.h"
75#include "qstyle.h"
76#include "qwhatsthis.h" // ######## dependency
77#include "qwidget.h"
78#include "qcolormap.h"
79#include "qlayout.h"
80#include "qtooltip.h"
81#include "qt_windows.h"
82#if defined(QT_NON_COMMERCIAL)
83#include "qnc_win.h"
84#endif
85#include "private/qwininputcontext_p.h"
86#include "private/qcursor_p.h"
87#include "private/qmath_p.h"
88#include "private/qapplication_p.h"
89#include "private/qbackingstore_p.h"
90#include "private/qwindowsurface_raster_p.h"
91#include "qdebug.h"
92#include <private/qkeymapper_p.h>
93#include <private/qlocale_p.h>
94#include "qevent_p.h"
95
96//#define ALIEN_DEBUG
97
98#ifndef QT_NO_THREAD
99#include "qmutex.h"
100#endif
101
102#ifndef QT_NO_ACCESSIBILITY
103#include "qaccessible.h"
104
105#include <oleacc.h>
106#ifndef WM_GETOBJECT
107#define WM_GETOBJECT 0x003D
108#endif
109#endif // QT_NO_ACCESSIBILITY
110
111#if !defined(WINABLEAPI)
112# if defined(Q_WS_WINCE)
113# include <bldver.h>
114# endif
115# include <winable.h>
116#endif
117
118#ifndef WM_TOUCH
119# define WM_TOUCH 0x0240
120
121# define TOUCHEVENTF_MOVE 0x0001
122# define TOUCHEVENTF_DOWN 0x0002
123# define TOUCHEVENTF_UP 0x0004
124# define TOUCHEVENTF_INRANGE 0x0008
125# define TOUCHEVENTF_PRIMARY 0x0010
126# define TOUCHEVENTF_NOCOALESCE 0x0020
127# define TOUCHEVENTF_PEN 0x0040
128# define TOUCHEVENTF_PALM 0x0080
129
130# define TOUCHINPUTMASKF_TIMEFROMSYSTEM 0x0001
131# define TOUCHINPUTMASKF_EXTRAINFO 0x0002
132# define TOUCHINPUTMASKF_CONTACTAREA 0x0004
133
134typedef struct tagTOUCHINPUT
135{
136 LONG x;
137 LONG y;
138 HANDLE hSource;
139 DWORD dwID;
140 DWORD dwFlags;
141 DWORD dwMask;
142 DWORD dwTime;
143 ULONG_PTR dwExtraInfo;
144 DWORD cxContact;
145 DWORD cyContact;
146} TOUCHINPUT, *PTOUCHINPUT;
147
148#endif
149
150#include <windowsx.h>
151#include <limits.h>
152#include <string.h>
153#include <ctype.h>
154#include <stdio.h>
155#include <math.h>
156
157#define PACKETDATA (PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE \
158 | PK_ORIENTATION | PK_CURSOR | PK_Z)
159#define PACKETMODE 0
160
161#include <wintab.h>
162#ifndef CSR_TYPE
163#define CSR_TYPE 20 // Some old Wacom wintab.h may not provide this constant.
164#endif
165#include <pktdef.h>
166
167#if defined(__CYGWIN32__)
168#define __INSIDE_CYGWIN32__
169#include <mywinsock.h>
170#endif
171
172#ifndef IMR_RECONVERTSTRING
173#define IMR_RECONVERTSTRING 4
174#endif
175
176#ifndef IMR_CONFIRMRECONVERTSTRING
177#define IMR_CONFIRMRECONVERTSTRING 0x0005
178#endif
179QT_BEGIN_NAMESPACE
180
181#ifdef Q_WS_WINCE
182#ifndef SHRG_RETURNCMD
183struct SHRGINFO {
184 DWORD cbSize;
185 HWND hwndClient;
186 POINT ptDown;
187 DWORD dwFlags;
188};
189#define GN_CONTEXTMENU 1000
190#define SHRG_RETURNCMD 0x00000001
191#define SHRG_NOANIMATION 0x00000010
192#endif
193
194#ifndef SPI_SETSIPINFO
195#define SPI_SETSIPINFO 224
196#endif
197
198typedef DWORD (API *AygRecognizeGesture)(SHRGINFO*);
199static AygRecognizeGesture ptrRecognizeGesture = 0;
200static bool aygResolved = false;
201static void resolveAygLibs()
202{
203 if (!aygResolved) {
204 aygResolved = true;
205 QLibrary ayglib(QLatin1String("aygshell"));
206 if (!ayglib.load())
207 return;
208 ptrRecognizeGesture = (AygRecognizeGesture) ayglib.resolve("SHRecognizeGesture");
209 }
210}
211
212#endif
213
214#ifndef SPI_SETFONTSMOOTHINGTYPE
215# define SPI_SETFONTSMOOTHINGTYPE 0x200B
216#endif
217#ifndef SPI_GETFONTSMOOTHINGTYPE
218# define SPI_GETFONTSMOOTHINGTYPE 0x200A
219#endif
220#ifndef FE_FONTSMOOTHINGCLEARTYPE
221# define FE_FONTSMOOTHINGCLEARTYPE 0x0002
222#endif
223
224Q_GUI_EXPORT bool qt_cleartype_enabled;
225Q_GUI_EXPORT bool qt_win_owndc_required; // CS_OWNDC is required if we use the GL graphicssystem as default
226
227typedef HCTX (API *PtrWTOpen)(HWND, LPLOGCONTEXT, BOOL);
228typedef BOOL (API *PtrWTClose)(HCTX);
229typedef UINT (API *PtrWTInfo)(UINT, UINT, LPVOID);
230typedef BOOL (API *PtrWTEnable)(HCTX, BOOL);
231typedef BOOL (API *PtrWTOverlap)(HCTX, BOOL);
232typedef int (API *PtrWTPacketsGet)(HCTX, int, LPVOID);
233typedef BOOL (API *PtrWTGet)(HCTX, LPLOGCONTEXT);
234typedef int (API *PtrWTQueueSizeGet)(HCTX);
235typedef BOOL (API *PtrWTQueueSizeSet)(HCTX, int);
236
237static PtrWTInfo ptrWTInfo = 0;
238static PtrWTEnable ptrWTEnable = 0;
239static PtrWTOverlap ptrWTOverlap = 0;
240static PtrWTPacketsGet ptrWTPacketsGet = 0;
241static PtrWTGet ptrWTGet = 0;
242
243static PACKET localPacketBuf[QT_TABLET_NPACKETQSIZE]; // our own tablet packet queue.
244HCTX qt_tablet_context; // the hardware context for the tablet (like a window handle)
245bool qt_tablet_tilt_support;
246
247#ifndef QT_NO_TABLETEVENT
248static void tabletInit(const quint64 uniqueId, const UINT csr_type, HCTX hTab);
249static void tabletUpdateCursor(QTabletDeviceData &tdd, const UINT currentCursor);
250static void initWinTabFunctions(); // resolve the WINTAB api functions
251#endif // QT_NO_TABLETEVENT
252
253
254#ifndef QT_NO_ACCESSIBILITY
255extern IAccessible *qt_createWindowsAccessible(QAccessibleInterface *object);
256#endif // QT_NO_ACCESSIBILITY
257
258extern bool qt_tabletChokeMouse;
259extern QWidget* qt_get_tablet_widget();
260extern bool qt_sendSpontaneousEvent(QObject*, QEvent*);
261extern QRegion qt_dirtyRegion(QWidget *);
262
263typedef QHash<quint64, QTabletDeviceData> QTabletCursorInfo;
264Q_GLOBAL_STATIC(QTabletCursorInfo, tCursorInfo)
265QTabletDeviceData currentTabletPointer;
266
267// from qregion_win.cpp
268extern HRGN qt_tryCreateRegion(QRegion::RegionType type, int left, int top, int right, int bottom);
269
270// support for on-the-fly changes of the XP theme engine
271#ifndef WM_THEMECHANGED
272#define WM_THEMECHANGED 0x031A
273#endif
274#ifndef COLOR_MENUHILIGHT
275#define COLOR_MENUHILIGHT 29
276#define COLOR_MENUBAR 30
277#endif
278
279// support for xbuttons
280#ifndef WM_XBUTTONDOWN
281#define WM_XBUTTONDOWN 0x020B
282#define WM_XBUTTONUP 0x020C
283#define WM_XBUTTONDBLCLK 0x020D
284#endif
285#ifndef GET_KEYSTATE_WPARAM
286#define GET_KEYSTATE_WPARAM(wParam) (LOWORD(wParam))
287#define GET_XBUTTON_WPARAM(wParam) (HIWORD(wParam))
288#define XBUTTON1 0x0001
289#define XBUTTON2 0x0002
290#endif
291#ifndef MK_XBUTTON1
292#define MK_XBUTTON1 0x0020
293#define MK_XBUTTON2 0x0040
294#endif
295
296// support for multi-media-keys
297#ifndef WM_APPCOMMAND
298#define WM_APPCOMMAND 0x0319
299#endif
300
301#ifndef FAPPCOMMAND_MOUSE
302#define FAPPCOMMAND_MOUSE 0x8000
303#define FAPPCOMMAND_KEY 0
304#define FAPPCOMMAND_OEM 0x1000
305#define FAPPCOMMAND_MASK 0xF000
306#define GET_APPCOMMAND_LPARAM(lParam) ((short)(HIWORD(lParam) & ~FAPPCOMMAND_MASK))
307#define GET_DEVICE_LPARAM(lParam) ((WORD)(HIWORD(lParam) & FAPPCOMMAND_MASK))
308#define GET_MOUSEORKEY_LPARAM GET_DEVICE_LPARAM
309#define GET_FLAGS_LPARAM(lParam) (LOWORD(lParam))
310#define GET_KEYSTATE_LPARAM(lParam) GET_FLAGS_LPARAM(lParam)
311
312#define APPCOMMAND_BROWSER_BACKWARD 1
313#define APPCOMMAND_BROWSER_FORWARD 2
314#define APPCOMMAND_BROWSER_REFRESH 3
315#define APPCOMMAND_BROWSER_STOP 4
316#define APPCOMMAND_BROWSER_SEARCH 5
317#define APPCOMMAND_BROWSER_FAVORITES 6
318#define APPCOMMAND_BROWSER_HOME 7
319#define APPCOMMAND_VOLUME_MUTE 8
320#define APPCOMMAND_VOLUME_DOWN 9
321#define APPCOMMAND_VOLUME_UP 10
322#define APPCOMMAND_MEDIA_NEXTTRACK 11
323#define APPCOMMAND_MEDIA_PREVIOUSTRACK 12
324#define APPCOMMAND_MEDIA_STOP 13
325#define APPCOMMAND_MEDIA_PLAY_PAUSE 14
326#define APPCOMMAND_LAUNCH_MAIL 15
327#define APPCOMMAND_LAUNCH_MEDIA_SELECT 16
328#define APPCOMMAND_LAUNCH_APP1 17
329#define APPCOMMAND_LAUNCH_APP2 18
330#define APPCOMMAND_BASS_DOWN 19
331#define APPCOMMAND_BASS_BOOST 20
332#define APPCOMMAND_BASS_UP 21
333#define APPCOMMAND_TREBLE_DOWN 22
334#define APPCOMMAND_TREBLE_UP 23
335#endif // FAPPCOMMAND_MOUSE
336
337// New commands from Windows XP (some even Sp1)
338#ifndef APPCOMMAND_MICROPHONE_VOLUME_MUTE
339#define APPCOMMAND_MICROPHONE_VOLUME_MUTE 24
340#define APPCOMMAND_MICROPHONE_VOLUME_DOWN 25
341#define APPCOMMAND_MICROPHONE_VOLUME_UP 26
342#define APPCOMMAND_HELP 27
343#define APPCOMMAND_FIND 28
344#define APPCOMMAND_NEW 29
345#define APPCOMMAND_OPEN 30
346#define APPCOMMAND_CLOSE 31
347#define APPCOMMAND_SAVE 32
348#define APPCOMMAND_PRINT 33
349#define APPCOMMAND_UNDO 34
350#define APPCOMMAND_REDO 35
351#define APPCOMMAND_COPY 36
352#define APPCOMMAND_CUT 37
353#define APPCOMMAND_PASTE 38
354#define APPCOMMAND_REPLY_TO_MAIL 39
355#define APPCOMMAND_FORWARD_MAIL 40
356#define APPCOMMAND_SEND_MAIL 41
357#define APPCOMMAND_SPELL_CHECK 42
358#define APPCOMMAND_DICTATE_OR_COMMAND_CONTROL_TOGGLE 43
359#define APPCOMMAND_MIC_ON_OFF_TOGGLE 44
360#define APPCOMMAND_CORRECTION_LIST 45
361#define APPCOMMAND_MEDIA_PLAY 46
362#define APPCOMMAND_MEDIA_PAUSE 47
363#define APPCOMMAND_MEDIA_RECORD 48
364#define APPCOMMAND_MEDIA_FAST_FORWARD 49
365#define APPCOMMAND_MEDIA_REWIND 50
366#define APPCOMMAND_MEDIA_CHANNEL_UP 51
367#define APPCOMMAND_MEDIA_CHANNEL_DOWN 52
368#endif // APPCOMMAND_MICROPHONE_VOLUME_MUTE
369
370#if (_WIN32_WINNT < 0x0400)
371// This struct is defined in winuser.h if the _WIN32_WINNT >= 0x0400 -- in the
372// other cases we have to define it on our own.
373typedef struct tagTRACKMOUSEEVENT {
374 DWORD cbSize;
375 DWORD dwFlags;
376 HWND hwndTrack;
377 DWORD dwHoverTime;
378} TRACKMOUSEEVENT, *LPTRACKMOUSEEVENT;
379#endif
380#ifndef WM_MOUSELEAVE
381#define WM_MOUSELEAVE 0x02A3
382#endif
383
384QT_BEGIN_INCLUDE_NAMESPACE
385#include "private/qwidget_p.h"
386QT_END_INCLUDE_NAMESPACE
387
388static int translateButtonState(int s, int type, int button);
389
390// ##### get rid of this!
391QRgb qt_colorref2qrgb(COLORREF col)
392{
393 return qRgb(GetRValue(col),GetGValue(col),GetBValue(col));
394}
395
396
397/*****************************************************************************
398 Internal variables and functions
399 *****************************************************************************/
400
401static HWND curWin = 0; // current window
402static HDC displayDC = 0; // display device context
403
404// Session management
405static bool sm_blockUserInput = false;
406static bool sm_smActive = false;
407extern QSessionManager* qt_session_manager_self;
408static bool sm_cancel;
409
410static bool replayPopupMouseEvent = false; // replay handling when popups close
411
412// ignore the next release event if return from a modal widget
413Q_GUI_EXPORT bool qt_win_ignoreNextMouseReleaseEvent = false;
414
415
416#if defined(QT_DEBUG)
417static bool appNoGrab = false; // mouse/keyboard grabbing
418#endif
419
420static bool app_do_modal = false; // modal mode
421extern QWidgetList *qt_modal_stack;
422extern QDesktopWidget *qt_desktopWidget;
423static QPointer<QWidget> popupButtonFocus;
424static bool qt_try_modal(QWidget *, MSG *, int& ret);
425
426QWidget *qt_button_down = 0; // widget got last button-down
427QPointer<QWidget> qt_last_mouse_receiver = 0;
428
429static HWND autoCaptureWnd = 0;
430static HWND imeParentWnd = 0;
431static void setAutoCapture(HWND); // automatic capture
432static void releaseAutoCapture();
433
434static void unregWinClasses();
435
436extern QCursor *qt_grab_cursor();
437
438#if defined(Q_WS_WIN)
439#define __export
440#endif
441
442extern "C" LRESULT CALLBACK QtWndProc(HWND, UINT, WPARAM, LPARAM);
443
444class QETWidget : public QWidget // event translator widget
445{
446public:
447 QWExtra *xtra() { return d_func()->extraData(); }
448 QTLWExtra *topData() { return d_func()->topData(); }
449 QTLWExtra *maybeTopData() { return d_func()->maybeTopData(); }
450 void syncBackingStore(const QRegion &rgn) { d_func()->syncBackingStore(rgn); }
451 void syncBackingStore() { d_func()->syncBackingStore(); }
452 QWidgetData *dataPtr() { return data; }
453 QWidgetPrivate *dptr() { return d_func(); }
454 QRect frameStrut() const { return d_func()->frameStrut(); }
455 bool winEvent(MSG *m, long *r) { return QWidget::winEvent(m, r); }
456 void markFrameStrutDirty() { data->fstrut_dirty = 1; }
457 bool translateMouseEvent(const MSG &msg);
458 bool translateWheelEvent(const MSG &msg);
459 bool translatePaintEvent(const MSG &msg);
460 bool translateConfigEvent(const MSG &msg);
461 bool translateCloseEvent(const MSG &msg);
462 bool translateTabletEvent(const MSG &msg, PACKET *localPacketBuf, int numPackets);
463 bool translateGestureEvent(const MSG &msg, const GESTUREINFO &gi);
464 void repolishStyle(QStyle &style);
465 inline void showChildren(bool spontaneous) { d_func()->showChildren(spontaneous); }
466 inline void hideChildren(bool spontaneous) { d_func()->hideChildren(spontaneous); }
467 inline uint testWindowState(uint teststate){ return dataPtr()->window_state & teststate; }
468 inline void setWindowTitle_helper(const QString &title) { d_func()->setWindowTitle_helper(title); }
469 inline void forceUpdate() {
470 QTLWExtra *tlwExtra = window()->d_func()->maybeTopData();
471 if (tlwExtra && tlwExtra->backingStore)
472 tlwExtra->backingStore->markDirty(rect(), this, true, true);
473 }
474};
475
476// need to get default font?
477extern bool qt_app_has_font;
478
479extern QFont qt_LOGFONTtoQFont(LOGFONT& lf,bool scale);
480
481static void qt_set_windows_color_resources()
482{
483 // Do the color settings
484 QPalette pal;
485 pal.setColor(QPalette::WindowText,
486 QColor(qt_colorref2qrgb(GetSysColor(COLOR_WINDOWTEXT))));
487 pal.setColor(QPalette::Button,
488 QColor(qt_colorref2qrgb(GetSysColor(COLOR_BTNFACE))));
489 pal.setColor(QPalette::Light,
490 QColor(qt_colorref2qrgb(GetSysColor(COLOR_BTNHIGHLIGHT))));
491 pal.setColor(QPalette::Dark,
492 QColor(qt_colorref2qrgb(GetSysColor(COLOR_BTNSHADOW))));
493 pal.setColor(QPalette::Mid, pal.button().color().darker(150));
494 pal.setColor(QPalette::Text,
495 QColor(qt_colorref2qrgb(GetSysColor(COLOR_WINDOWTEXT))));
496 pal.setColor(QPalette::BrightText,
497 QColor(qt_colorref2qrgb(GetSysColor(COLOR_BTNHIGHLIGHT))));
498 pal.setColor(QPalette::Base,
499 QColor(qt_colorref2qrgb(GetSysColor(COLOR_WINDOW))));
500 pal.setColor(QPalette::Window,
501 QColor(qt_colorref2qrgb(GetSysColor(COLOR_BTNFACE))));
502 pal.setColor(QPalette::ButtonText,
503 QColor(qt_colorref2qrgb(GetSysColor(COLOR_BTNTEXT))));
504 pal.setColor(QPalette::Midlight,
505 QColor(qt_colorref2qrgb(GetSysColor(COLOR_3DLIGHT))));
506 pal.setColor(QPalette::Shadow,
507 QColor(qt_colorref2qrgb(GetSysColor(COLOR_3DDKSHADOW))));
508 pal.setColor(QPalette::Highlight,
509 QColor(qt_colorref2qrgb(GetSysColor(COLOR_HIGHLIGHT))));
510 pal.setColor(QPalette::HighlightedText,
511 QColor(qt_colorref2qrgb(GetSysColor(COLOR_HIGHLIGHTTEXT))));
512
513#if defined(Q_WS_WINCE)
514 // ### hardcoded until I find out how to get it from the system settings.
515 pal.setColor(QPalette::LinkVisited, pal.highlight().color().dark(150));
516 pal.setColor(QPalette::Link, pal.highlight().color().light(130));
517 // Background == Base on Windows CE
518 if (qt_wince_is_smartphone() || qt_wince_is_pocket_pc())
519 pal.setColor(QPalette::Background, pal.base().color());
520#else
521 pal.setColor(QPalette::Link, Qt::blue);
522 pal.setColor(QPalette::LinkVisited, Qt::magenta);
523#endif
524
525
526
527 pal.setColor(QPalette::Inactive, QPalette::Button, pal.button().color());
528 pal.setColor(QPalette::Inactive, QPalette::Window, pal.background().color());
529 pal.setColor(QPalette::Inactive, QPalette::Light, pal.light().color());
530 pal.setColor(QPalette::Inactive, QPalette::Dark, pal.dark().color());
531
532 if (pal.midlight() == pal.button())
533 pal.setColor(QPalette::Midlight, pal.button().color().lighter(110));
534 if (pal.background() != pal.base()) {
535 pal.setColor(QPalette::Inactive, QPalette::Highlight, pal.color(QPalette::Inactive, QPalette::Window));
536 pal.setColor(QPalette::Inactive, QPalette::HighlightedText, pal.color(QPalette::Inactive, QPalette::Text));
537 }
538
539 const QColor bg = pal.background().color();
540 const QColor fg = pal.foreground().color(), btn = pal.button().color();
541 QColor disabled((fg.red()+btn.red())/2,(fg.green()+btn.green())/2,
542 (fg.blue()+btn.blue())/2);
543 pal.setColorGroup(QPalette::Disabled, pal.foreground(), pal.button(), pal.light(),
544 pal.dark(), pal.mid(), pal.text(), pal.brightText(), pal.base(), pal.background() );
545 pal.setColor(QPalette::Disabled, QPalette::WindowText, disabled);
546 pal.setColor(QPalette::Disabled, QPalette::Text, disabled);
547 pal.setColor(QPalette::Disabled, QPalette::ButtonText, disabled);
548 pal.setColor(QPalette::Disabled, QPalette::Highlight,
549 QColor(qt_colorref2qrgb(GetSysColor(COLOR_HIGHLIGHT))));
550 pal.setColor(QPalette::Disabled, QPalette::HighlightedText,
551 QColor(qt_colorref2qrgb(GetSysColor(COLOR_HIGHLIGHTTEXT))));
552 pal.setColor(QPalette::Disabled, QPalette::Base, bg);
553
554 QApplicationPrivate::setSystemPalette(pal);
555
556 QApplicationPrivate::initializeWidgetPaletteHash();
557
558 QColor ttip(qt_colorref2qrgb(GetSysColor(COLOR_INFOBK)));
559
560 QColor ttipText(qt_colorref2qrgb(GetSysColor(COLOR_INFOTEXT)));
561 {
562#ifndef QT_NO_TOOLTIP
563 QPalette tiplabel(pal);
564 tiplabel.setColor(QPalette::All, QPalette::Button, ttip);
565 tiplabel.setColor(QPalette::All, QPalette::Window, ttip);
566 tiplabel.setColor(QPalette::All, QPalette::Text, ttipText);
567 tiplabel.setColor(QPalette::All, QPalette::WindowText, ttipText);
568 tiplabel.setColor(QPalette::All, QPalette::ButtonText, ttipText);
569 tiplabel.setColor(QPalette::All, QPalette::Button, ttip);
570 tiplabel.setColor(QPalette::All, QPalette::Window, ttip);
571 tiplabel.setColor(QPalette::All, QPalette::Text, ttipText);
572 tiplabel.setColor(QPalette::All, QPalette::WindowText, ttipText);
573 tiplabel.setColor(QPalette::All, QPalette::ButtonText, ttipText);
574 const QColor fg = tiplabel.foreground().color(), btn = tiplabel.button().color();
575 QColor disabled((fg.red()+btn.red())/2,(fg.green()+btn.green())/2,
576 (fg.blue()+btn.blue())/2);
577 tiplabel.setColor(QPalette::Disabled, QPalette::WindowText, disabled);
578 tiplabel.setColor(QPalette::Disabled, QPalette::Text, disabled);
579 tiplabel.setColor(QPalette::Disabled, QPalette::Base, Qt::white);
580 tiplabel.setColor(QPalette::Disabled, QPalette::BrightText, Qt::white);
581 QToolTip::setPalette(tiplabel);
582#endif //QT_NO_TOOLTIP
583 }
584}
585
586static void qt_set_windows_font_resources()
587{
588#ifndef Q_WS_WINCE
589 NONCLIENTMETRICS ncm;
590 ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICS, lfMessageFont) + sizeof(LOGFONT);
591 SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize , &ncm, 0);
592
593 QFont menuFont = qt_LOGFONTtoQFont(ncm.lfMenuFont, true);
594 QFont messageFont = qt_LOGFONTtoQFont(ncm.lfMessageFont, true);
595 QFont statusFont = qt_LOGFONTtoQFont(ncm.lfStatusFont, true);
596 QFont titleFont = qt_LOGFONTtoQFont(ncm.lfCaptionFont, true);
597
598 LOGFONT lfIconTitleFont;
599 SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0);
600 QFont iconTitleFont = qt_LOGFONTtoQFont(lfIconTitleFont, true);
601
602 QApplication::setFont(menuFont, "QMenu");
603 QApplication::setFont(menuFont, "QMenuBar");
604 QApplication::setFont(messageFont, "QMessageBox");
605 QApplication::setFont(statusFont, "QTipLabel");
606 QApplication::setFont(statusFont, "QStatusBar");
607 QApplication::setFont(titleFont, "Q3TitleBar");
608 QApplication::setFont(titleFont, "QWorkspaceTitleBar");
609 QApplication::setFont(iconTitleFont, "QAbstractItemView");
610 QApplication::setFont(iconTitleFont, "QDockWidgetTitle");
611
612#else
613 LOGFONT lf;
614 HGDIOBJ stockFont = GetStockObject(SYSTEM_FONT);
615 GetObject(stockFont, sizeof(lf), &lf);
616 QFont systemFont = qt_LOGFONTtoQFont(lf, true);
617 QApplicationPrivate::setSystemFont(systemFont);
618 QFont smallerFont = systemFont;
619 if (qt_wince_is_mobile()) {
620 smallerFont.setPointSize(systemFont.pointSize()-1);
621 QApplication::setFont(smallerFont, "QTabBar");
622 smallerFont.setBold(true);
623 QApplication::setFont(smallerFont, "QAbstractButton");
624 }
625#endif// Q_WS_WINCE
626}
627
628static void qt_win_read_cleartype_settings()
629{
630 UINT result = 0;
631#ifdef Q_OS_WINCE
632 if (SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &result, 0))
633 qt_cleartype_enabled = result;
634#else
635 if (SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE, 0, &result, 0))
636 qt_cleartype_enabled = (result == FE_FONTSMOOTHINGCLEARTYPE);
637#endif
638}
639
640
641static void qt_set_windows_resources()
642{
643 if (QApplication::type() != QApplication::Tty)
644 (void) QApplication::style(); // trigger creation of application style
645 qt_set_windows_font_resources();
646 qt_set_windows_color_resources();
647}
648
649void QApplicationPrivate::initializeWidgetPaletteHash()
650{
651 QPalette pal = *QApplicationPrivate::sys_pal;
652 QColor menuCol(qt_colorref2qrgb(GetSysColor(COLOR_MENU)));
653 QColor menuText(qt_colorref2qrgb(GetSysColor(COLOR_MENUTEXT)));
654 BOOL isFlat = false;
655 if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP
656 && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based))
657 SystemParametersInfo(SPI_GETFLATMENU, 0, &isFlat, 0);
658 QPalette menu(pal);
659 // we might need a special color group for the menu.
660 menu.setColor(QPalette::Active, QPalette::Button, menuCol);
661 menu.setColor(QPalette::Active, QPalette::Text, menuText);
662 menu.setColor(QPalette::Active, QPalette::WindowText, menuText);
663 menu.setColor(QPalette::Active, QPalette::ButtonText, menuText);
664 const QColor fg = menu.foreground().color(), btn = menu.button().color();
665 QColor disabled(qt_colorref2qrgb(GetSysColor(COLOR_GRAYTEXT)));
666 menu.setColor(QPalette::Disabled, QPalette::WindowText, disabled);
667 menu.setColor(QPalette::Disabled, QPalette::Text, disabled);
668 menu.setColor(QPalette::Disabled, QPalette::Highlight,
669 QColor(qt_colorref2qrgb(GetSysColor(
670 (QSysInfo::WindowsVersion >= QSysInfo::WV_XP
671 && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based)
672 && isFlat ? COLOR_MENUHILIGHT : COLOR_HIGHLIGHT))));
673 menu.setColor(QPalette::Disabled, QPalette::HighlightedText, disabled);
674 menu.setColor(QPalette::Disabled, QPalette::Button,
675 menu.color(QPalette::Active, QPalette::Button));
676 menu.setColor(QPalette::Inactive, QPalette::Button,
677 menu.color(QPalette::Active, QPalette::Button));
678 menu.setColor(QPalette::Inactive, QPalette::Text,
679 menu.color(QPalette::Active, QPalette::Text));
680 menu.setColor(QPalette::Inactive, QPalette::WindowText,
681 menu.color(QPalette::Active, QPalette::WindowText));
682 menu.setColor(QPalette::Inactive, QPalette::ButtonText,
683 menu.color(QPalette::Active, QPalette::ButtonText));
684 menu.setColor(QPalette::Inactive, QPalette::Highlight,
685 menu.color(QPalette::Active, QPalette::Highlight));
686 menu.setColor(QPalette::Inactive, QPalette::HighlightedText,
687 menu.color(QPalette::Active, QPalette::HighlightedText));
688 menu.setColor(QPalette::Inactive, QPalette::ButtonText,
689 pal.color(QPalette::Inactive, QPalette::Dark));
690 QApplication::setPalette(menu, "QMenu");
691
692 if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP
693 && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based) && isFlat) {
694 QColor menubar(qt_colorref2qrgb(GetSysColor(COLOR_MENUBAR)));
695 menu.setColor(QPalette::Active, QPalette::Button, menubar);
696 menu.setColor(QPalette::Disabled, QPalette::Button, menubar);
697 menu.setColor(QPalette::Inactive, QPalette::Button, menubar);
698 }
699 QApplication::setPalette(menu, "QMenuBar");
700}
701
702/*****************************************************************************
703 qt_init() - initializes Qt for Windows
704 *****************************************************************************/
705
706typedef BOOL (WINAPI *PtrSetProcessDPIAware) (VOID);
707static PtrSetProcessDPIAware ptrSetProcessDPIAware = 0;
708PtrUpdateLayeredWindow ptrUpdateLayeredWindow = 0;
709PtrUpdateLayeredWindowIndirect ptrUpdateLayeredWindowIndirect = 0;
710static BOOL WINAPI qt_updateLayeredWindowIndirect(HWND hwnd, const Q_UPDATELAYEREDWINDOWINFO *info)
711{
712 return (*ptrUpdateLayeredWindow)(hwnd, info->hdcDst, info->pptDst, info->psize, info->hdcSrc,
713 info->pptSrc, info->crKey, info->pblend, info->dwFlags);
714}
715
716void qt_init(QApplicationPrivate *priv, int)
717{
718
719 int argc = priv->argc;
720 char **argv = priv->argv;
721 int i, j;
722
723 // Get command line params
724
725 j = argc ? 1 : 0;
726 for (i=1; i<argc; i++) {
727 if (argv[i] && *argv[i] != '-') {
728 argv[j++] = argv[i];
729 continue;
730 }
731#if defined(QT_DEBUG)
732 if (qstrcmp(argv[i], "-nograb") == 0)
733 appNoGrab = !appNoGrab;
734 else
735#endif // QT_DEBUG
736 argv[j++] = argv[i];
737 }
738 if(j < priv->argc) {
739 priv->argv[j] = 0;
740 priv->argc = j;
741 }
742
743#ifndef Q_WS_WINCE
744 // No message boxes but important ones
745 SetErrorMode(SetErrorMode(0) | SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
746#endif
747
748#ifndef Q_WS_WINCE
749 // Initialize OLE/COM
750 // S_OK means success and S_FALSE means that it has already
751 // been initialized
752 HRESULT r;
753 r = OleInitialize(0);
754 if (r != S_OK && r != S_FALSE) {
755 qWarning("Qt: Could not initialize OLE (error %x)", (unsigned int)r);
756 }
757#endif
758
759 // Misc. initialization
760#if defined(QT_DEBUG) && !defined(Q_WS_WINCE)
761 GdiSetBatchLimit(1);
762#endif
763
764 // initialize key mapper
765 QKeyMapper::changeKeyboard();
766
767 QColormap::initialize();
768 QFont::initialize();
769#ifndef QT_NO_CURSOR
770 QCursorData::initialize();
771#endif
772 qApp->setObjectName(priv->appName());
773
774 // default font
775#ifndef Q_WS_WINCE
776 HGDIOBJ stockFont = GetStockObject(DEFAULT_GUI_FONT);
777#else
778 HGDIOBJ stockFont = GetStockObject(SYSTEM_FONT);
779#endif
780
781 LOGFONT lf;
782 GetObject(stockFont, sizeof(lf), &lf);
783 QFont systemFont = qt_LOGFONTtoQFont(lf, true);
784
785#ifndef Q_WS_WINCE
786 if (systemFont.family() == QLatin1String("MS Shell Dlg")) {
787 systemFont.setFamily(QLatin1String("MS Shell Dlg 2"));
788 }
789#endif
790
791 QApplicationPrivate::setSystemFont(systemFont);
792
793 // QFont::locale_init(); ### Uncomment when it does something on Windows
794
795 if (QApplication::desktopSettingsAware())
796 qt_set_windows_resources();
797
798#ifndef QT_NO_TABLETEVENT
799 initWinTabFunctions();
800#endif // QT_NO_TABLETEVENT
801 QApplicationPrivate::inputContext = new QWinInputContext(0);
802
803 // Read the initial cleartype settings...
804 qt_win_read_cleartype_settings();
805 qt_win_owndc_required = false;
806
807 extern void qt_win_initialize_directdraw();
808 qt_win_initialize_directdraw();
809
810#ifndef Q_OS_WINCE
811 ptrUpdateLayeredWindowIndirect =
812 (PtrUpdateLayeredWindowIndirect) QLibrary::resolve(QLatin1String("user32"),
813 "UpdateLayeredWindowIndirect");
814 ptrUpdateLayeredWindow =
815 (PtrUpdateLayeredWindow) QLibrary::resolve(QLatin1String("user32"),
816 "UpdateLayeredWindow");
817
818 if (ptrUpdateLayeredWindow && !ptrUpdateLayeredWindowIndirect)
819 ptrUpdateLayeredWindowIndirect = qt_updateLayeredWindowIndirect;
820
821 // Notify Vista and Windows 7 that we support highter DPI settings
822 ptrSetProcessDPIAware = (PtrSetProcessDPIAware)
823 QLibrary::resolve(QLatin1String("user32"), "SetProcessDPIAware");
824 if (ptrSetProcessDPIAware)
825 ptrSetProcessDPIAware();
826#endif
827
828 priv->GetGestureInfo = 0;
829 priv->GetGestureExtraArgs = 0;
830 priv->CloseGestureInfoHandle = 0;
831 priv->SetGestureConfig = 0;
832 priv->GetGestureConfig = 0;
833 priv->BeginPanningFeedback = 0;
834 priv->UpdatePanningFeedback = 0;
835 priv->EndPanningFeedback = 0;
836
837#if defined(Q_WS_WINCE_WM) && defined(QT_WINCE_GESTURES)
838 priv->GetGestureInfo = (PtrGetGestureInfo) &TKGetGestureInfo;
839 priv->GetGestureExtraArgs = (PtrGetGestureExtraArgs) &TKGetGestureExtraArguments;
840#elif !defined(Q_WS_WINCE)
841 #if !defined(QT_NO_NATIVE_GESTURES)
842 priv->GetGestureInfo =
843 (PtrGetGestureInfo)QLibrary::resolve(QLatin1String("user32"),
844 "GetGestureInfo");
845 priv->GetGestureExtraArgs =
846 (PtrGetGestureExtraArgs)QLibrary::resolve(QLatin1String("user32"),
847 "GetGestureExtraArgs");
848 priv->CloseGestureInfoHandle =
849 (PtrCloseGestureInfoHandle)QLibrary::resolve(QLatin1String("user32"),
850 "CloseGestureInfoHandle");
851 priv->SetGestureConfig =
852 (PtrSetGestureConfig)QLibrary::resolve(QLatin1String("user32"),
853 "SetGestureConfig");
854 priv->GetGestureConfig =
855 (PtrGetGestureConfig)QLibrary::resolve(QLatin1String("user32"),
856 "GetGestureConfig");
857 #endif // QT_NO_NATIVE_GESTURES
858 priv->BeginPanningFeedback =
859 (PtrBeginPanningFeedback)QLibrary::resolve(QLatin1String("uxtheme"),
860 "BeginPanningFeedback");
861 priv->UpdatePanningFeedback =
862 (PtrUpdatePanningFeedback)QLibrary::resolve(QLatin1String("uxtheme"),
863 "UpdatePanningFeedback");
864 priv->EndPanningFeedback =
865 (PtrEndPanningFeedback)QLibrary::resolve(QLatin1String("uxtheme"),
866 "EndPanningFeedback");
867#endif
868}
869
870/*****************************************************************************
871 qt_cleanup() - cleans up when the application is finished
872 *****************************************************************************/
873
874void qt_cleanup()
875{
876 unregWinClasses();
877 QPixmapCache::clear();
878
879#ifndef QT_NO_CURSOR
880 QCursorData::cleanup();
881#endif
882 QFont::cleanup();
883 QColormap::cleanup();
884 if (displayDC) {
885 ReleaseDC(0, displayDC);
886 displayDC = 0;
887 }
888
889 delete QApplicationPrivate::inputContext;
890 QApplicationPrivate::inputContext = 0;
891
892#ifndef Q_WS_WINCE
893 // Deinitialize OLE/COM
894 OleUninitialize();
895#endif
896}
897
898
899/*****************************************************************************
900 Platform specific global and internal functions
901 *****************************************************************************/
902
903Q_GUI_EXPORT HDC qt_win_display_dc() // get display DC
904{
905 Q_ASSERT(qApp && qApp->thread() == QThread::currentThread());
906 if (!displayDC)
907 displayDC = GetDC(0);
908 return displayDC;
909}
910
911bool qt_nograb() // application no-grab option
912{
913#if defined(QT_DEBUG)
914 return appNoGrab;
915#else
916 return false;
917#endif
918}
919
920typedef QHash<QString, int> WinClassNameHash;
921Q_GLOBAL_STATIC(WinClassNameHash, winclassNames)
922
923const QString qt_reg_winclass(QWidget *w) // register window class
924{
925 int flags = w->windowFlags();
926 int type = flags & Qt::WindowType_Mask;
927
928 uint style;
929 bool icon;
930 QString cname;
931 if (flags & Qt::MSWindowsOwnDC) {
932 cname = QLatin1String("QWidgetOwnDC");
933 style = CS_DBLCLKS;
934#ifndef Q_WS_WINCE
935 style |= CS_OWNDC;
936#endif
937 icon = true;
938 } else if (type == Qt::Tool || type == Qt::ToolTip){
939 style = CS_DBLCLKS;
940 if (w->inherits("QTipLabel") || w->inherits("QAlphaWidget")) {
941 if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP
942 && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based)) {
943 style |= CS_DROPSHADOW;
944 }
945 cname = QLatin1String("QToolTip");
946 } else {
947 cname = QLatin1String("QTool");
948 }
949#ifndef Q_WS_WINCE
950 style |= CS_SAVEBITS;
951#endif
952 icon = false;
953 } else if (type == Qt::Popup) {
954 cname = QLatin1String("QPopup");
955 style = CS_DBLCLKS;
956#ifndef Q_WS_WINCE
957 style |= CS_SAVEBITS;
958#endif
959 if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP
960 && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based))
961 style |= CS_DROPSHADOW;
962 icon = false;
963 } else {
964 cname = QLatin1String("QWidget");
965 style = CS_DBLCLKS;
966 icon = true;
967 }
968
969#ifndef Q_WS_WINCE
970 // force CS_OWNDC when the GL graphics system is
971 // used as the default renderer
972 if (qt_win_owndc_required)
973 style |= CS_OWNDC;
974#endif
975
976#ifdef Q_OS_WINCE
977 // We need to register the classes with the
978 // unique ID on WinCE to make sure we can
979 // move the windows to the front when starting
980 // a second instance.
981 wchar_t uniqueAppID[MAX_PATH];
982 GetModuleFileName(0, uniqueAppID, MAX_PATH);
983 cname = QString::number(RegisterWindowMessage(
984 (const wchar_t *) QString::fromWCharArray(uniqueAppID).toLower().replace(QLatin1Char('\\'),
985 QLatin1Char('_')).utf16()));
986#endif
987
988 // since multiple Qt versions can be used in one process
989 // each one has to have window class names with a unique name
990 // The first instance gets the unmodified name; if the class
991 // has already been registered by another instance of Qt then
992 // add an instance-specific ID, the address of the window proc.
993 static int classExists = -1;
994
995 if (classExists == -1) {
996 WNDCLASS wcinfo;
997 classExists = GetClassInfo((HINSTANCE)qWinAppInst(), (wchar_t*)cname.utf16(), &wcinfo);
998 classExists = classExists && wcinfo.lpfnWndProc != QtWndProc;
999 }
1000
1001 if (classExists)
1002 cname += QString::number((quintptr)QtWndProc);
1003
1004 if (winclassNames()->contains(cname)) // already registered in our list
1005 return cname;
1006
1007 WNDCLASS wc;
1008 wc.style = style;
1009 wc.lpfnWndProc = (WNDPROC)QtWndProc;
1010 wc.cbClsExtra = 0;
1011 wc.cbWndExtra = 0;
1012 wc.hInstance = qWinAppInst();
1013 if (icon) {
1014 wc.hIcon = (HICON)LoadImage(qWinAppInst(), L"IDI_ICON1", IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);
1015#ifndef Q_WS_WINCE
1016 if (!wc.hIcon)
1017 wc.hIcon = (HICON)LoadImage(0, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED);
1018#endif
1019 } else {
1020 wc.hIcon = 0;
1021 }
1022 wc.hCursor = 0;
1023#ifndef Q_WS_WINCE
1024 wc.hbrBackground = (HBRUSH)GetSysColorBrush(COLOR_WINDOW);
1025#else
1026 wc.hbrBackground = 0;
1027#endif
1028 wc.lpszMenuName = 0;
1029 wc.lpszClassName = (wchar_t*)cname.utf16();
1030
1031 ATOM atom = RegisterClass(&wc);
1032
1033#ifndef QT_NO_DEBUG
1034 if (!atom)
1035 qErrnoWarning("QApplication::regClass: Registering window class failed.");
1036#else
1037 Q_UNUSED(atom);
1038#endif
1039
1040 winclassNames()->insert(cname, 1);
1041 return cname;
1042}
1043
1044Q_GUI_EXPORT const QString qt_getRegisteredWndClass()
1045{
1046 QWidget w;
1047 return qt_reg_winclass(&w);
1048}
1049
1050static void unregWinClasses()
1051{
1052 WinClassNameHash *hash = winclassNames();
1053 QHash<QString, int>::ConstIterator it = hash->constBegin();
1054 while (it != hash->constEnd()) {
1055 UnregisterClass((wchar_t*)it.key().utf16(), qWinAppInst());
1056 ++it;
1057 }
1058 hash->clear();
1059}
1060
1061
1062/*****************************************************************************
1063 Safe configuration (move,resize,setGeometry) mechanism to avoid
1064 recursion when processing messages.
1065 *****************************************************************************/
1066
1067struct QWinConfigRequest {
1068 WId id; // widget to be configured
1069 int req; // 0=move, 1=resize, 2=setGeo
1070 int x, y, w, h; // request parameters
1071};
1072
1073static QList<QWinConfigRequest*> *configRequests = 0;
1074
1075void qWinRequestConfig(WId id, int req, int x, int y, int w, int h)
1076{
1077 if (!configRequests) // create queue
1078 configRequests = new QList<QWinConfigRequest*>;
1079 QWinConfigRequest *r = new QWinConfigRequest;
1080 r->id = id; // create new request
1081 r->req = req;
1082 r->x = x;
1083 r->y = y;
1084 r->w = w;
1085 r->h = h;
1086 configRequests->append(r); // store request in queue
1087}
1088
1089static void qWinProcessConfigRequests() // perform requests in queue
1090{
1091 if (!configRequests)
1092 return;
1093 QWinConfigRequest *r;
1094 for (;;) {
1095 if (configRequests->isEmpty())
1096 break;
1097 r = configRequests->takeLast();
1098 QWidget *w = QWidget::find(r->id);
1099 QRect rect(r->x, r->y, r->w, r->h);
1100 int req = r->req;
1101 delete r;
1102
1103 if ( w ) { // widget exists
1104 if (w->testAttribute(Qt::WA_WState_ConfigPending))
1105 return; // biting our tail
1106 if (req == 0)
1107 w->move(rect.topLeft());
1108 else if (req == 1)
1109 w->resize(rect.size());
1110 else
1111 w->setGeometry(rect);
1112 }
1113 }
1114 delete configRequests;
1115 configRequests = 0;
1116}
1117
1118
1119/*****************************************************************************
1120 GUI event dispatcher
1121 *****************************************************************************/
1122
1123class QGuiEventDispatcherWin32 : public QEventDispatcherWin32
1124{
1125 Q_DECLARE_PRIVATE(QEventDispatcherWin32)
1126public:
1127 QGuiEventDispatcherWin32(QObject *parent = 0);
1128 bool processEvents(QEventLoop::ProcessEventsFlags flags);
1129};
1130
1131QGuiEventDispatcherWin32::QGuiEventDispatcherWin32(QObject *parent)
1132 : QEventDispatcherWin32(parent)
1133{
1134 createInternalHwnd();
1135}
1136
1137bool QGuiEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
1138{
1139 if (!QEventDispatcherWin32::processEvents(flags))
1140 return false;
1141
1142 if (configRequests) // any pending configs?
1143 qWinProcessConfigRequests();
1144
1145 return true;
1146}
1147
1148void QApplicationPrivate::createEventDispatcher()
1149{
1150 Q_Q(QApplication);
1151 if (q->type() != QApplication::Tty)
1152 eventDispatcher = new QGuiEventDispatcherWin32(q);
1153 else
1154 eventDispatcher = new QEventDispatcherWin32(q);
1155}
1156
1157/*****************************************************************************
1158 Platform specific QApplication members
1159 *****************************************************************************/
1160
1161#ifdef QT3_SUPPORT
1162void QApplication::setMainWidget(QWidget *mainWidget)
1163{
1164 QApplicationPrivate::main_widget = mainWidget;
1165 if (QApplicationPrivate::main_widget && windowIcon().isNull()
1166 && QApplicationPrivate::main_widget->testAttribute(Qt::WA_SetWindowIcon))
1167 setWindowIcon(QApplicationPrivate::main_widget->windowIcon());
1168}
1169#endif
1170
1171#ifndef QT_NO_CURSOR
1172
1173/*****************************************************************************
1174 QApplication cursor stack
1175 *****************************************************************************/
1176
1177void QApplication::setOverrideCursor(const QCursor &cursor)
1178{
1179 qApp->d_func()->cursor_list.prepend(cursor);
1180 SetCursor(qApp->d_func()->cursor_list.first().handle());
1181}
1182
1183void QApplication::restoreOverrideCursor()
1184{
1185 if (qApp->d_func()->cursor_list.isEmpty())
1186 return;
1187 qApp->d_func()->cursor_list.removeFirst();
1188
1189 if (!qApp->d_func()->cursor_list.isEmpty()) {
1190 SetCursor(qApp->d_func()->cursor_list.first().handle());
1191 } else {
1192 QWidget *w = QWidget::find(curWin);
1193 if (w)
1194 SetCursor(w->cursor().handle());
1195 else
1196 SetCursor(QCursor(Qt::ArrowCursor).handle());
1197 }
1198}
1199
1200#endif
1201
1202/*
1203 Internal function called from QWidget::setCursor()
1204 force is true if this function is called from dispatchEnterLeave, it means that the
1205 mouse is actually directly under this widget.
1206*/
1207
1208#ifndef QT_NO_CURSOR
1209void qt_win_set_cursor(QWidget *w, bool force)
1210{
1211 static QPointer<QWidget> lastUnderMouse = 0;
1212 if (force) {
1213 lastUnderMouse = w;
1214 } else if (w->testAttribute(Qt::WA_WState_Created) && lastUnderMouse
1215 && lastUnderMouse->effectiveWinId() == w->effectiveWinId()) {
1216 w = lastUnderMouse;
1217 }
1218
1219 if (!curWin && w && w->internalWinId())
1220 return;
1221 QWidget* cW = w && !w->internalWinId() ? w : QWidget::find(curWin);
1222 if (!cW || cW->window() != w->window() ||
1223 !cW->isVisible() || !cW->underMouse() || QApplication::overrideCursor())
1224 return;
1225
1226 SetCursor(cW->cursor().handle());
1227}
1228#endif // QT_NO_CURSOR
1229
1230Qt::KeyboardModifiers qt_win_getKeyboardModifiers()
1231{
1232 Qt::KeyboardModifiers modifiers = Qt::NoModifier;
1233 if (GetKeyState(VK_SHIFT) < 0)
1234 modifiers |= Qt::ShiftModifier;
1235 if (GetKeyState(VK_CONTROL) < 0)
1236 modifiers |= Qt::ControlModifier;
1237 if (GetKeyState(VK_MENU) < 0)
1238 modifiers |= Qt::AltModifier;
1239 return modifiers;
1240}
1241
1242/*****************************************************************************
1243 Routines to find a Qt widget from a screen position
1244 *****************************************************************************/
1245
1246QWidget *QApplication::topLevelAt(const QPoint &pos)
1247{
1248 POINT p;
1249 HWND win;
1250 QWidget *w;
1251 p.x = pos.x();
1252 p.y = pos.y();
1253 win = WindowFromPoint(p);
1254 if (!win)
1255 return 0;
1256
1257 w = QWidget::find(win);
1258 while (!w && win) {
1259 win = GetParent(win);
1260 w = QWidget::find(win);
1261 }
1262 return w ? w->window() : 0;
1263}
1264
1265void QApplication::beep()
1266{
1267 MessageBeep(MB_OK);
1268}
1269
1270static void alert_widget(QWidget *widget, int duration)
1271{
1272#ifdef Q_OS_WINCE
1273 Q_UNUSED(widget);
1274 Q_UNUSED(duration);
1275#else
1276 bool stopFlash = duration < 0;
1277
1278 if (widget && (!widget->isActiveWindow() || stopFlash)) {
1279 DWORD timeOut = GetCaretBlinkTime();
1280 if (timeOut <= 0)
1281 timeOut = 250;
1282
1283 UINT flashCount;
1284 if (duration == 0)
1285 flashCount = 10;
1286 else
1287 flashCount = duration/timeOut;
1288
1289 FLASHWINFO info;
1290 info.cbSize = sizeof(info);
1291 info.hwnd = widget->window()->winId();
1292 info.dwFlags = stopFlash ? FLASHW_STOP : FLASHW_TRAY;
1293 info.dwTimeout = stopFlash ? 0 : timeOut;
1294 info.uCount = stopFlash ? 0 : flashCount;
1295
1296 FlashWindowEx(&info);
1297 }
1298#endif
1299}
1300
1301void QApplication::alert(QWidget *widget, int duration)
1302{
1303 if (!QApplicationPrivate::checkInstance("alert"))
1304 return;
1305
1306 if (widget) {
1307 alert_widget(widget, duration);
1308 } else {
1309 const QWidgetList toplevels(topLevelWidgets());
1310 for (int i = 0; i < toplevels.count(); ++i) {
1311 QWidget *topLevel = toplevels.at(i);
1312 alert_widget(topLevel, duration);
1313 }
1314 }
1315}
1316
1317QString QApplicationPrivate::appName() const
1318{
1319 return QCoreApplicationPrivate::appName();
1320}
1321
1322
1323/*****************************************************************************
1324 Main event loop
1325 *****************************************************************************/
1326
1327extern uint qGlobalPostedEventsCount();
1328
1329void QApplication::winFocus(QWidget *widget, bool gotFocus)
1330{
1331 if (d_func()->inPopupMode()) // some delayed focus event to ignore
1332 return;
1333 if (gotFocus) {
1334 setActiveWindow(widget);
1335 if (QApplicationPrivate::active_window
1336 && (QApplicationPrivate::active_window->windowType() == Qt::Dialog)) {
1337 // raise the entire application, not just the dialog
1338 QWidget* mw = QApplicationPrivate::active_window;
1339#ifndef Q_WS_WINCE
1340 while(mw->parentWidget() && (mw->windowType() == Qt::Dialog))
1341 mw = mw->parentWidget()->window();
1342 if (mw->testAttribute(Qt::WA_WState_Created) && mw != QApplicationPrivate::active_window)
1343 SetWindowPos(mw->internalWinId(), HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
1344#else
1345 // On Desktop Windows, we set the first parent of the dialog on top
1346 // Child windows will be automatically set above again.
1347 // On Windows CE we pass no parent in CreateWindowEx as otherwise
1348 // dialogs get embedded into the parent window. Thus we need to
1349 // manually iterate and reactivate all windows from bottom up.
1350 QList<QWidget*> raiseList;
1351 raiseList.push_back(mw);
1352 while(mw->parentWidget() && (mw->windowType() == Qt::Dialog)) {
1353 mw = mw->parentWidget()->window();
1354 raiseList.push_back(mw);
1355 }
1356 while(!raiseList.isEmpty()) {
1357 mw = raiseList.takeLast();
1358 if (mw->testAttribute(Qt::WA_WState_Created)) {
1359 HWND state = HWND_TOP;
1360 if (mw->windowFlags() & Qt::WindowStaysOnBottomHint)
1361 state = HWND_BOTTOM;
1362 else if (mw->windowFlags() & Qt::WindowStaysOnTopHint)
1363 state = HWND_TOPMOST;
1364 SetWindowPos(mw->internalWinId(), state, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
1365 }
1366 }
1367#endif
1368 }
1369 } else {
1370 setActiveWindow(0);
1371 }
1372}
1373
1374
1375//
1376// QtWndProc() receives all messages from the main event loop
1377//
1378
1379static bool inLoop = false;
1380static int inputcharset = CP_ACP;
1381
1382#define RETURN(x) { inLoop=false;return x; }
1383
1384static bool qt_is_translatable_mouse_event(UINT message)
1385{
1386 return (((message >= WM_MOUSEFIRST && message <= WM_MOUSELAST) ||
1387 (message >= WM_XBUTTONDOWN && message <= WM_XBUTTONDBLCLK))
1388 && message != WM_MOUSEWHEEL
1389 && message != WM_MOUSEHWHEEL)
1390
1391#ifndef Q_WS_WINCE
1392 || (message >= WM_NCMOUSEMOVE && message <= WM_NCMBUTTONDBLCLK)
1393#endif
1394 ;
1395}
1396
1397extern "C"
1398LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1399{
1400 bool result = true;
1401 QEvent::Type evt_type = QEvent::None;
1402 QETWidget *widget = 0;
1403
1404 // there is no need to process pakcets from tablet unless
1405 // it is actually on the tablet, a flag to let us know...
1406 int nPackets; // the number of packets we get from the queue
1407
1408 long res = 0;
1409 if (!qApp) // unstable app state
1410 RETURN(QWinInputContext::DefWindowProc(hwnd,message,wParam,lParam))
1411
1412 QScopedLoopLevelCounter loopLevelCounter(QThreadData::get2(qApp->thread()));
1413
1414#if 0
1415 // make sure we update widgets also when the user resizes
1416 if (inLoop && qApp->loopLevel())
1417 qApp->sendPostedEvents(0, QEvent::Paint);
1418#endif
1419
1420 inLoop = true;
1421
1422 MSG msg;
1423 msg.hwnd = hwnd; // create MSG structure
1424 msg.message = message; // time and pt fields ignored
1425 msg.wParam = wParam;
1426 msg.lParam = lParam;
1427 msg.pt.x = GET_X_LPARAM(lParam);
1428 msg.pt.y = GET_Y_LPARAM(lParam);
1429 // If it's a non-client-area message the coords are screen coords, otherwise they are
1430 // client coords.
1431#ifndef Q_WS_WINCE
1432 if (message < WM_NCMOUSEMOVE || message > WM_NCMBUTTONDBLCLK)
1433#endif
1434 ClientToScreen(msg.hwnd, &msg.pt);
1435
1436 /*
1437 // sometimes the autograb is not released, so the clickevent is sent
1438 // to the wrong window. We ignore this for now, because it doesn't
1439 // cause any problems.
1440 if (msg.message == WM_LBUTTONDOWN || msg.message == WM_RBUTTONDOWN || msg.message == WM_MBUTTONDOWN) {
1441 HWND handle = WindowFromPoint(msg.pt);
1442 if (msg.hwnd != handle) {
1443 msg.hwnd = handle;
1444 hwnd = handle;
1445 }
1446 }
1447 */
1448
1449#if defined(QT_NON_COMMERCIAL)
1450 QT_NC_WNDPROC
1451#endif
1452
1453 // send through app filter
1454 if (qApp->filterEvent(&msg, &res))
1455 return res;
1456
1457 // close any opened ime candidate window (enabled only on a popup widget)
1458 if (imeParentWnd && QApplication::activePopupWidget()
1459 && (message == WM_MBUTTONDOWN || message == WM_XBUTTONDOWN
1460 || message == WM_LBUTTONDOWN || message == WM_RBUTTONDOWN
1461#ifndef Q_WS_WINCE
1462 || message == WM_NCMBUTTONDOWN || message == WM_NCLBUTTONDOWN
1463 || message == WM_NCRBUTTONDOWN)) {
1464#else
1465 )) {
1466#endif
1467 ::SendMessage(imeParentWnd, WM_IME_ENDCOMPOSITION, 0, 0);
1468 }
1469
1470 switch (message) {
1471#ifndef Q_WS_WINCE
1472 case WM_QUERYENDSESSION: {
1473 if (sm_smActive) // bogus message from windows
1474 RETURN(true);
1475
1476 sm_smActive = true;
1477 sm_blockUserInput = true; // prevent user-interaction outside interaction windows
1478 sm_cancel = false;
1479 if (qt_session_manager_self)
1480 qApp->commitData(*qt_session_manager_self);
1481 if (lParam & ENDSESSION_LOGOFF) {
1482 _flushall();
1483 }
1484 RETURN(!sm_cancel);
1485 }
1486 case WM_ENDSESSION: {
1487 sm_smActive = false;
1488 sm_blockUserInput = false;
1489 bool endsession = (bool) wParam;
1490
1491 // we receive the message for each toplevel window included internal hidden ones,
1492 // but the aboutToQuit signal should be emitted only once.
1493 QApplicationPrivate *qAppPriv = QApplicationPrivate::instance();
1494 if (endsession && !qAppPriv->aboutToQuitEmitted) {
1495 qAppPriv->aboutToQuitEmitted = true;
1496 int index = QApplication::staticMetaObject.indexOfSignal("aboutToQuit()");
1497 qApp->qt_metacall(QMetaObject::InvokeMetaMethod, index,0);
1498 // since the process will be killed immediately quit() has no real effect
1499 QApplication::quit();
1500 }
1501
1502 RETURN(0);
1503 }
1504 case WM_DISPLAYCHANGE:
1505 if (QApplication::type() == QApplication::Tty)
1506 break;
1507 if (qt_desktopWidget) {
1508 qt_desktopWidget->move(GetSystemMetrics(76), GetSystemMetrics(77));
1509 QSize sz(GetSystemMetrics(78), GetSystemMetrics(79));
1510 if (sz == qt_desktopWidget->size()) {
1511 // a screen resized without changing size of the virtual desktop
1512 QResizeEvent rs(sz, qt_desktopWidget->size());
1513 QApplication::sendEvent(qt_desktopWidget, &rs);
1514 } else {
1515 qt_desktopWidget->resize(sz);
1516 }
1517 }
1518 break;
1519#endif
1520
1521 case WM_SETTINGCHANGE:
1522#ifdef Q_WS_WINCE
1523 // CE SIP hide/show
1524 if (wParam == SPI_SETSIPINFO) {
1525 QResizeEvent re(QSize(0, 0), QSize(0, 0)); // Calculated by QDesktopWidget
1526 QApplication::sendEvent(qt_desktopWidget, &re);
1527 break;
1528 }
1529#endif
1530 // ignore spurious XP message when user logs in again after locking
1531 if (QApplication::type() == QApplication::Tty)
1532 break;
1533 if (QApplication::desktopSettingsAware() && wParam != SPI_SETWORKAREA) {
1534 widget = (QETWidget*)QWidget::find(hwnd);
1535 if (widget) {
1536 if (wParam == SPI_SETNONCLIENTMETRICS)
1537 widget->markFrameStrutDirty();
1538 }
1539 }
1540 else if (qt_desktopWidget && wParam == SPI_SETWORKAREA) {
1541 qt_desktopWidget->move(GetSystemMetrics(76), GetSystemMetrics(77));
1542 QSize sz(GetSystemMetrics(78), GetSystemMetrics(79));
1543 if (sz == qt_desktopWidget->size()) {
1544 // a screen resized without changing size of the virtual desktop
1545 QResizeEvent rs(sz, qt_desktopWidget->size());
1546 QApplication::sendEvent(qt_desktopWidget, &rs);
1547 } else {
1548 qt_desktopWidget->resize(sz);
1549 }
1550 }
1551
1552 if (wParam == SPI_SETFONTSMOOTHINGTYPE) {
1553 qt_win_read_cleartype_settings();
1554 foreach (QWidget *w, QApplication::topLevelWidgets()) {
1555 if (!w->isVisible())
1556 continue;
1557 ((QETWidget *) w)->forceUpdate();
1558 }
1559 }
1560
1561 break;
1562 case WM_SYSCOLORCHANGE:
1563 if (QApplication::type() == QApplication::Tty)
1564 break;
1565 if (QApplication::desktopSettingsAware()) {
1566 widget = (QETWidget*)QWidget::find(hwnd);
1567 if (widget && !widget->parentWidget())
1568 qt_set_windows_color_resources();
1569 }
1570 break;
1571
1572 case WM_LBUTTONDOWN:
1573 case WM_MBUTTONDOWN:
1574 case WM_RBUTTONDOWN:
1575 case WM_XBUTTONDOWN:
1576 if (qt_win_ignoreNextMouseReleaseEvent)
1577 qt_win_ignoreNextMouseReleaseEvent = false;
1578 break;
1579
1580 case WM_LBUTTONUP:
1581 case WM_MBUTTONUP:
1582 case WM_RBUTTONUP:
1583 case WM_XBUTTONUP:
1584 if (qt_win_ignoreNextMouseReleaseEvent) {
1585 qt_win_ignoreNextMouseReleaseEvent = false;
1586 if (qt_button_down && qt_button_down->internalWinId() == autoCaptureWnd) {
1587 releaseAutoCapture();
1588 qt_button_down = 0;
1589 }
1590
1591 RETURN(0);
1592 }
1593 break;
1594
1595 default:
1596 break;
1597 }
1598
1599 if (!widget)
1600 widget = (QETWidget*)QWidget::find(hwnd);
1601 if (!widget) // don't know this widget
1602 goto do_default;
1603
1604 if (app_do_modal) { // modal event handling
1605 int ret = 0;
1606 if (!qt_try_modal(widget, &msg, ret))
1607 RETURN(ret);
1608 }
1609
1610 res = 0;
1611 if (widget->winEvent(&msg, &res)) // send through widget filter
1612 RETURN(res);
1613
1614 if (qt_is_translatable_mouse_event(message)) {
1615 if (QApplication::activePopupWidget() != 0) { // in popup mode
1616 POINT curPos = msg.pt;
1617 QWidget* w = QApplication::widgetAt(curPos.x, curPos.y);
1618 if (w)
1619 widget = (QETWidget*)w;
1620 }
1621
1622 if (!qt_tabletChokeMouse) {
1623 result = widget->translateMouseEvent(msg); // mouse event
1624#if defined(Q_WS_WINCE) && !defined(QT_NO_CONTEXTMENU)
1625 if (message == WM_LBUTTONDOWN && widget != QApplication::activePopupWidget()) {
1626 QWidget* alienWidget = widget;
1627 if ((alienWidget != QApplication::activePopupWidget()) && (alienWidget->contextMenuPolicy() != Qt::PreventContextMenu)) {
1628 QPoint pos(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
1629 QPoint globalPos(msg.pt.x, msg.pt.y);
1630 // In case we are using Alien, then the widget to
1631 // send the context menu event is a different one
1632 if (!alienWidget->testAttribute(Qt::WA_NativeWindow) && !alienWidget->testAttribute(Qt::WA_PaintOnScreen)) {
1633 alienWidget = QApplication::widgetAt(globalPos);
1634 if (alienWidget)
1635 pos = alienWidget->mapFromGlobal(globalPos);
1636 }
1637 if (alienWidget) {
1638 SHRGINFO shrg;
1639 shrg.cbSize = sizeof(shrg);
1640 shrg.hwndClient = hwnd;
1641 shrg.ptDown.x = GET_X_LPARAM(lParam);
1642 shrg.ptDown.y = GET_Y_LPARAM(lParam);
1643 shrg.dwFlags = SHRG_RETURNCMD | SHRG_NOANIMATION;
1644 resolveAygLibs();
1645 if (ptrRecognizeGesture && (ptrRecognizeGesture(&shrg) == GN_CONTEXTMENU)) {
1646 if (QApplication::activePopupWidget())
1647 QApplication::activePopupWidget()->close();
1648 QContextMenuEvent e(QContextMenuEvent::Mouse, pos, globalPos);
1649 result = qt_sendSpontaneousEvent(alienWidget, &e);
1650 }
1651 }
1652 }
1653 }
1654#endif
1655 } else {
1656 // Sometimes we only get a WM_MOUSEMOVE message
1657 // and sometimes we get both a WM_MOUSEMOVE and
1658 // a WM_LBUTTONDOWN/UP, this creates a spurious mouse
1659 // press/release event, using the PeekMessage
1660 // will help us fix this. This leaves us with a
1661 // question:
1662 // This effectively kills using the mouse AND the
1663 // tablet simultaneously, well creates wacky input.
1664 // Is this going to be a problem? (probably not)
1665 bool next_is_button = false;
1666 bool is_mouse_move = (message == WM_MOUSEMOVE);
1667 if (is_mouse_move) {
1668 MSG msg1;
1669 if (PeekMessage(&msg1, msg.hwnd, WM_MOUSEFIRST,
1670 WM_MOUSELAST, PM_NOREMOVE))
1671 next_is_button = (msg1.message == WM_LBUTTONUP
1672 || msg1.message == WM_LBUTTONDOWN);
1673 }
1674 if (!is_mouse_move || (is_mouse_move && !next_is_button))
1675 qt_tabletChokeMouse = false;
1676 }
1677 } else {
1678 switch (message) {
1679 case WM_TOUCH:
1680 result = QApplicationPrivate::instance()->translateTouchEvent(msg);
1681 break;
1682 case WM_KEYDOWN: // keyboard event
1683 case WM_SYSKEYDOWN:
1684 qt_keymapper_private()->updateKeyMap(msg);
1685 // fall-through intended
1686 case WM_KEYUP:
1687 case WM_SYSKEYUP:
1688#if Q_OS_WINCE_WM
1689 case WM_HOTKEY:
1690 if(HIWORD(msg.lParam) == VK_TBACK) {
1691 const bool hotKeyDown = !(LOWORD(msg.lParam) & MOD_KEYUP);
1692 msg.lParam = 0x69 << 16;
1693 msg.wParam = VK_BACK;
1694 if (hotKeyDown) {
1695 msg.message = WM_KEYDOWN;
1696 qt_keymapper_private()->updateKeyMap(msg);
1697 } else {
1698 msg.message = WM_KEYUP;
1699 }
1700 }
1701 // fall-through intended
1702#endif
1703 case WM_IME_CHAR:
1704 case WM_IME_KEYDOWN:
1705 case WM_CHAR: {
1706 MSG msg1;
1707 bool anyMsg = PeekMessage(&msg1, msg.hwnd, 0, 0, PM_NOREMOVE);
1708 if (anyMsg && msg1.message == WM_DEADCHAR) {
1709 result = true; // consume event since there is a dead char next
1710 break;
1711 }
1712 QWidget *g = QWidget::keyboardGrabber();
1713 if (g && qt_get_tablet_widget() && hwnd == qt_get_tablet_widget()->winId()) {
1714 // if we get an event for the internal tablet widget,
1715 // then don't send it to the keyboard grabber, but
1716 // send it to the widget itself (we don't use it right
1717 // now, just in case).
1718 g = 0;
1719 }
1720 if (g)
1721 widget = (QETWidget*)g;
1722 else if (QApplication::activePopupWidget())
1723 widget = (QETWidget*)QApplication::activePopupWidget()->focusWidget()
1724 ? (QETWidget*)QApplication::activePopupWidget()->focusWidget()
1725 : (QETWidget*)QApplication::activePopupWidget();
1726 else if (QApplication::focusWidget())
1727 widget = (QETWidget*)QApplication::focusWidget();
1728 else if (!widget || widget->internalWinId() == GetFocus()) // We faked the message to go to exactly that widget.
1729 widget = (QETWidget*)widget->window();
1730 if (widget->isEnabled())
1731 result = sm_blockUserInput
1732 ? true
1733 : qt_keymapper_private()->translateKeyEvent(widget, msg, g != 0);
1734 break;
1735 }
1736 case WM_SYSCHAR:
1737 result = true; // consume event
1738 break;
1739
1740 case WM_MOUSEWHEEL:
1741 case WM_MOUSEHWHEEL:
1742 result = widget->translateWheelEvent(msg);
1743 break;
1744
1745 case WM_APPCOMMAND:
1746 {
1747 uint cmd = GET_APPCOMMAND_LPARAM(lParam);
1748 uint uDevice = GET_DEVICE_LPARAM(lParam);
1749 uint dwKeys = GET_KEYSTATE_LPARAM(lParam);
1750
1751 int state = translateButtonState(dwKeys, QEvent::KeyPress, 0);
1752
1753 switch (uDevice) {
1754 case FAPPCOMMAND_KEY:
1755 {
1756 int key = 0;
1757
1758 switch(cmd) {
1759 case APPCOMMAND_BASS_BOOST:
1760 key = Qt::Key_BassBoost;
1761 break;
1762 case APPCOMMAND_BASS_DOWN:
1763 key = Qt::Key_BassDown;
1764 break;
1765 case APPCOMMAND_BASS_UP:
1766 key = Qt::Key_BassUp;
1767 break;
1768 case APPCOMMAND_TREBLE_DOWN:
1769 key = Qt::Key_TrebleDown;
1770 break;
1771 case APPCOMMAND_TREBLE_UP:
1772 key = Qt::Key_TrebleUp;
1773 break;
1774 case APPCOMMAND_HELP:
1775 key = Qt::Key_Help;
1776 break;
1777 case APPCOMMAND_FIND:
1778 key = Qt::Key_Search;
1779 break;
1780 default:
1781 break;
1782 }
1783 if (key) {
1784 bool res = false;
1785 QWidget *g = QWidget::keyboardGrabber();
1786 if (g)
1787 widget = (QETWidget*)g;
1788 else if (QApplication::focusWidget())
1789 widget = (QETWidget*)QApplication::focusWidget();
1790 else
1791 widget = (QETWidget*)widget->window();
1792 if (widget->isEnabled()) {
1793 res = QKeyMapper::sendKeyEvent(widget, g != 0, QEvent::KeyPress, key,
1794 Qt::KeyboardModifier(state),
1795 QString(), false, 0, 0, 0, 0);
1796 }
1797 if (res)
1798 return true;
1799 }
1800 }
1801 break;
1802
1803 default:
1804 break;
1805 }
1806
1807 result = false;
1808 }
1809 break;
1810
1811#ifndef Q_WS_WINCE
1812 case WM_NCHITTEST:
1813 if (widget->isWindow()) {
1814 QPoint pos = widget->mapFromGlobal(QPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
1815 // don't show resize-cursors for fixed-size widgets
1816 QRect fs = widget->frameStrut();
1817 if (!widget->isMinimized()) {
1818 if (widget->minimumHeight() == widget->maximumHeight()) {
1819 if (pos.y() < -(fs.top() - fs.left()))
1820 return HTCAPTION;
1821 if (pos.y() >= widget->height())
1822 return HTBORDER;
1823 }
1824 if (widget->minimumWidth() == widget->maximumWidth() && (pos.x() < 0 || pos.x() >= widget->width()))
1825 return HTBORDER;
1826 }
1827 }
1828
1829 result = false;
1830 break;
1831#endif
1832
1833 case WM_SYSCOMMAND: {
1834#ifndef Q_WS_WINCE
1835 bool window_state_change = false;
1836 Qt::WindowStates oldstate = Qt::WindowStates(widget->dataPtr()->window_state);
1837 // MSDN:In WM_SYSCOMMAND messages, the four low-order bits of the wParam parameter are
1838 // used internally by the system. To obtain the correct result when testing the value of
1839 // wParam, an application must combine the value 0xFFF0 with the wParam value by using
1840 // the bitwise AND operator.
1841 switch(0xfff0 & wParam) {
1842 case SC_CONTEXTHELP:
1843#ifndef QT_NO_WHATSTHIS
1844 QWhatsThis::enterWhatsThisMode();
1845#endif
1846 DefWindowProc(hwnd, WM_NCPAINT, 1, 0);
1847 break;
1848#if defined(QT_NON_COMMERCIAL)
1849 QT_NC_SYSCOMMAND
1850#endif
1851 case SC_MINIMIZE:
1852 window_state_change = true;
1853 widget->dataPtr()->window_state |= Qt::WindowMinimized;
1854 if (widget->isVisible()) {
1855 QHideEvent e;
1856 qt_sendSpontaneousEvent(widget, &e);
1857 widget->hideChildren(true);
1858 const QString title = widget->windowIconText();
1859 if (!title.isEmpty())
1860 widget->setWindowTitle_helper(title);
1861 }
1862 result = false;
1863 break;
1864 case SC_MAXIMIZE:
1865 if(widget->isWindow())
1866 widget->topData()->normalGeometry = widget->geometry();
1867 case SC_RESTORE:
1868 window_state_change = true;
1869 if ((0xfff0 & wParam) == SC_MAXIMIZE)
1870 widget->dataPtr()->window_state |= Qt::WindowMaximized;
1871 else if (!widget->isMinimized())
1872 widget->dataPtr()->window_state &= ~Qt::WindowMaximized;
1873
1874 if (widget->isMinimized()) {
1875 widget->dataPtr()->window_state &= ~Qt::WindowMinimized;
1876 widget->showChildren(true);
1877 QShowEvent e;
1878 qt_sendSpontaneousEvent(widget, &e);
1879 const QString title = widget->windowTitle();
1880 if (!title.isEmpty())
1881 widget->setWindowTitle_helper(title);
1882 }
1883 result = false;
1884 break;
1885 default:
1886 result = false;
1887 break;
1888 }
1889
1890 if (window_state_change) {
1891 QWindowStateChangeEvent e(oldstate);
1892 qt_sendSpontaneousEvent(widget, &e);
1893 }
1894#endif // #ifndef Q_OS_WINCE
1895
1896 break;
1897 }
1898
1899 case WM_SETTINGCHANGE:
1900 if ( QApplication::type() == QApplication::Tty )
1901 break;
1902
1903 if (!msg.wParam) {
1904 QString area = QString::fromWCharArray((wchar_t*)msg.lParam);
1905 if (area == QLatin1String("intl")) {
1906 QLocalePrivate::updateSystemPrivate();
1907 if (!widget->testAttribute(Qt::WA_SetLocale))
1908 widget->dptr()->setLocale_helper(QLocale(), true);
1909 }
1910 }
1911 else if (msg.wParam == SPI_SETICONTITLELOGFONT) {
1912 if (QApplication::desktopSettingsAware()) {
1913 widget = (QETWidget*)QWidget::find(hwnd);
1914 if (widget && !widget->parentWidget()) {
1915 qt_set_windows_font_resources();
1916 }
1917 }
1918 }
1919 break;
1920
1921 case WM_PAINT: // paint event
1922 case WM_ERASEBKGND: // erase window background
1923 result = widget->translatePaintEvent(msg);
1924 break;
1925
1926#ifndef Q_WS_WINCE
1927 case WM_ENTERSIZEMOVE:
1928 autoCaptureWnd = hwnd;
1929 break;
1930 case WM_EXITSIZEMOVE:
1931 autoCaptureWnd = 0;
1932 break;
1933#endif
1934 case WM_MOVE: // move window
1935 case WM_SIZE: // resize window
1936 result = widget->translateConfigEvent(msg);
1937 break;
1938
1939 case WM_ACTIVATEAPP:
1940 if (wParam == FALSE) {
1941 QApplication::setActiveWindow(0);
1942 // Another application was activated while our popups are open,
1943 // then close all popups. In case some popup refuses to close,
1944 // we give up after 1024 attempts (to avoid an infinite loop).
1945 int maxiter = 1024;
1946 QWidget *popup;
1947 while ((popup=QApplication::activePopupWidget()) && maxiter--)
1948 popup->close();
1949 }
1950 break;
1951
1952 case WM_ACTIVATE:
1953 if ( QApplication::type() == QApplication::Tty )
1954 break;
1955
1956 if (ptrWTOverlap && ptrWTEnable) {
1957 // cooperate with other tablet applications, but when
1958 // we get focus, I want to use the tablet...
1959 if (qt_tablet_context && GET_WM_ACTIVATE_STATE(wParam, lParam)) {
1960 if (ptrWTEnable(qt_tablet_context, true))
1961 ptrWTOverlap(qt_tablet_context, true);
1962 }
1963 }
1964 if (QApplication::activePopupWidget() && LOWORD(wParam) == WA_INACTIVE &&
1965 QWidget::find((HWND)lParam) == 0) {
1966 // Another application was activated while our popups are open,
1967 // then close all popups. In case some popup refuses to close,
1968 // we give up after 1024 attempts (to avoid an infinite loop).
1969 int maxiter = 1024;
1970 QWidget *popup;
1971 while ((popup=QApplication::activePopupWidget()) && maxiter--)
1972 popup->close();
1973 }
1974
1975 if (LOWORD(wParam) != WA_INACTIVE) {
1976 // WM_ACTIVATEAPP handles the "true" false case, as this is only when the application
1977 // loses focus. Doing it here would result in the widget getting focus to not know
1978 // where it got it from; it would simply get a 0 value as the old focus widget.
1979#ifdef Q_WS_WINCE
1980 {
1981#ifdef Q_WS_WINCE_WM
1982 // On Windows mobile we do not receive WM_SYSCOMMAND / SC_MINIMIZE messages.
1983 // Thus we have to unset the minimized state explicitly. We must do this for all
1984 // top-level widgets, because we get the HWND of a random widget here.
1985 foreach (QWidget* tlw, QApplication::topLevelWidgets()) {
1986 if (tlw->isMinimized())
1987 tlw->setWindowState(tlw->windowState() & ~Qt::WindowMinimized);
1988 }
1989#else
1990 // On Windows CE we do not receive WM_SYSCOMMAND / SC_MINIMIZE messages.
1991 // Thus we have to unset the minimized state explicitly.
1992 if (widget->windowState() & Qt::WindowMinimized)
1993 widget->setWindowState(widget->windowState() & ~Qt::WindowMinimized);
1994#endif // Q_WS_WINCE_WM
1995
1996#else
1997 if (!(widget->windowState() & Qt::WindowMinimized)) {
1998#endif
1999 // Ignore the activate message send by WindowsXP to a minimized window
2000#ifdef Q_WS_WINCE_WM
2001 if (widget->windowState() & Qt::WindowFullScreen)
2002 qt_wince_hide_taskbar(widget->winId());
2003#endif
2004 qApp->winFocus(widget, true);
2005 // reset any window alert flashes
2006 alert_widget(widget, -1);
2007 }
2008 }
2009
2010 // Windows tries to activate a modally blocked window.
2011 // This happens when restoring an application after "Show Desktop"
2012 if (app_do_modal && LOWORD(wParam) == WA_ACTIVE) {
2013 QWidget *top = 0;
2014 if (!QApplicationPrivate::tryModalHelper(widget, &top) && top && widget != top) {
2015 if (top->isVisible()) {
2016 top->activateWindow();
2017 } else {
2018 // This is the case when native file dialogs are shown
2019 QWidget *p = (top->parentWidget() ? top->parentWidget()->window() : 0);
2020 if (p && p->isVisible())
2021 p->activateWindow();
2022 }
2023 }
2024 }
2025 break;
2026
2027#ifndef Q_WS_WINCE
2028 case WM_MOUSEACTIVATE:
2029 if (widget->window()->windowType() == Qt::Tool) {
2030 QWidget *w = widget;
2031 if (!w->window()->focusWidget()) {
2032 while (w && (w->focusPolicy() & Qt::ClickFocus) == 0) {
2033 if (w->isWindow()) {
2034 QWidget *fw = w;
2035 while ((fw = fw->nextInFocusChain()) != w && fw->focusPolicy() == Qt::NoFocus)
2036 ;
2037 if (fw != w)
2038 break;
2039 QWidget *pw = w->parentWidget();
2040 while (pw) {
2041 pw = pw->window();
2042 if (pw && pw->isVisible() && pw->focusWidget()) {
2043 Q_ASSERT(pw->testAttribute(Qt::WA_WState_Created));
2044 SetWindowPos(pw->internalWinId(), HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
2045 break;
2046 }
2047 pw = pw->parentWidget();
2048 }
2049 RETURN(MA_NOACTIVATE);
2050 }
2051 w = w->parentWidget();
2052 }
2053 }
2054 }
2055 RETURN(MA_ACTIVATE);
2056 break;
2057#endif
2058 case WM_SHOWWINDOW:
2059 if (lParam == SW_PARENTOPENING) {
2060 if (widget->testAttribute(Qt::WA_WState_Hidden))
2061 RETURN(0);
2062 }
2063 if (widget->isWindow() && widget->testAttribute(Qt::WA_WState_Visible)
2064 && !widget->testWindowState(Qt::WindowMinimized)) {
2065 if (lParam == SW_PARENTOPENING) {
2066 QShowEvent e;
2067 qt_sendSpontaneousEvent(widget, &e);
2068 widget->showChildren(true);
2069 } else if (lParam == SW_PARENTCLOSING) {
2070 QHideEvent e;
2071 qt_sendSpontaneousEvent(widget, &e);
2072 widget->hideChildren(true);
2073 }
2074 }
2075 if (!wParam && autoCaptureWnd == widget->internalWinId())
2076 releaseAutoCapture();
2077 result = false;
2078 break;
2079
2080 case WM_PALETTECHANGED: // our window changed palette
2081 if (QColormap::hPal() && (WId)wParam == widget->internalWinId())
2082 RETURN(0); // otherwise: FALL THROUGH!
2083 // FALL THROUGH
2084 case WM_QUERYNEWPALETTE: // realize own palette
2085 if (QColormap::hPal()) {
2086 Q_ASSERT(widget->testAttribute(Qt::WA_WState_Created));
2087 HDC hdc = GetDC(widget->internalWinId());
2088 HPALETTE hpalOld = SelectPalette(hdc, QColormap::hPal(), FALSE);
2089 uint n = RealizePalette(hdc);
2090 if (n)
2091 InvalidateRect(widget->internalWinId(), 0, TRUE);
2092 SelectPalette(hdc, hpalOld, TRUE);
2093 RealizePalette(hdc);
2094 ReleaseDC(widget->internalWinId(), hdc);
2095 RETURN(n);
2096 }
2097 break;
2098 case WM_CLOSE: // close window
2099 widget->translateCloseEvent(msg);
2100 RETURN(0); // always handled
2101
2102 case WM_DESTROY: // destroy window
2103 if (hwnd == curWin) {
2104 QWidget *enter = QWidget::mouseGrabber();
2105 if (enter == widget)
2106 enter = 0;
2107 QApplicationPrivate::dispatchEnterLeave(enter, widget);
2108 curWin = enter ? enter->effectiveWinId() : 0;
2109 qt_last_mouse_receiver = enter;
2110 }
2111 if (widget == popupButtonFocus)
2112 popupButtonFocus = 0;
2113 result = false;
2114 break;
2115
2116#ifndef Q_WS_WINCE
2117 case WM_WINDOWPOSCHANGING:
2118 {
2119 result = false;
2120 if (widget->isWindow()) {
2121 WINDOWPOS *winPos = (WINDOWPOS *)lParam;
2122 if (widget->layout() && widget->layout()->hasHeightForWidth()
2123 && !(winPos->flags & (SWP_NOCOPYBITS | SWP_NOSIZE))) {
2124 QRect fs = widget->frameStrut();
2125 QRect rect = widget->geometry();
2126 QRect newRect = QRect(winPos->x + fs.left(),
2127 winPos->y + fs.top(),
2128 winPos->cx - fs.left() - fs.right(),
2129 winPos->cy - fs.top() - fs.bottom());
2130
2131 QSize newSize = QLayout::closestAcceptableSize(widget, newRect.size());
2132
2133 int dh = newSize.height() - newRect.height();
2134 int dw = newSize.width() - newRect.width();
2135 if (!dw && ! dh)
2136 break; // Size OK
2137
2138 if (rect.y() != newRect.y()) {
2139 newRect.setTop(newRect.top() - dh);
2140 } else {
2141 newRect.setBottom(newRect.bottom() + dh);
2142 }
2143
2144 if (rect.x() != newRect.x()) {
2145 newRect.setLeft(newRect.left() - dw);
2146 } else {
2147 newRect.setRight(newRect.right() + dw);
2148 }
2149
2150 winPos->x = newRect.x() - fs.left();
2151 winPos->y = newRect.y() - fs.top();
2152 winPos->cx = newRect.width() + fs.left() + fs.right();
2153 winPos->cy = newRect.height() + fs.top() + fs.bottom();
2154
2155 RETURN(0);
2156 }
2157 if (widget->windowFlags() & Qt::WindowStaysOnBottomHint) {
2158 winPos->hwndInsertAfter = HWND_BOTTOM;
2159 }
2160 }
2161 }
2162 break;
2163
2164 case WM_GETMINMAXINFO:
2165 if (widget->xtra()) {
2166 MINMAXINFO *mmi = (MINMAXINFO *)lParam;
2167 QWExtra *x = widget->xtra();
2168 QRect fs = widget->frameStrut();
2169 if ( x->minw > 0 )
2170 mmi->ptMinTrackSize.x = x->minw + fs.right() + fs.left();
2171 if ( x->minh > 0 )
2172 mmi->ptMinTrackSize.y = x->minh + fs.top() + fs.bottom();
2173 qint32 maxw = (x->maxw >= x->minw) ? x->maxw : x->minw;
2174 qint32 maxh = (x->maxh >= x->minh) ? x->maxh : x->minh;
2175 if ( maxw < QWIDGETSIZE_MAX ) {
2176 mmi->ptMaxTrackSize.x = maxw + fs.right() + fs.left();
2177 // windows with title bar have an implicit size limit of 112 pixels
2178 if (widget->windowFlags() & Qt::WindowTitleHint)
2179 mmi->ptMaxTrackSize.x = qMax<long>(mmi->ptMaxTrackSize.x, 112);
2180 }
2181 if ( maxh < QWIDGETSIZE_MAX )
2182 mmi->ptMaxTrackSize.y = maxh + fs.top() + fs.bottom();
2183 RETURN(0);
2184 }
2185 break;
2186
2187 case WM_CONTEXTMENU:
2188 {
2189 // it's not VK_APPS or Shift+F10, but a click in the NC area
2190 if (lParam != (int)0xffffffff) {
2191 result = false;
2192 break;
2193 }
2194
2195 QWidget *fw = QWidget::keyboardGrabber();
2196 if (!fw) {
2197 if (QApplication::activePopupWidget())
2198 fw = (QApplication::activePopupWidget()->focusWidget()
2199 ? QApplication::activePopupWidget()->focusWidget()
2200 : QApplication::activePopupWidget());
2201 else if (QApplication::focusWidget())
2202 fw = QApplication::focusWidget();
2203 else if (widget)
2204 fw = widget->window();
2205 }
2206 if (fw && fw->isEnabled()) {
2207 QPoint pos = fw->inputMethodQuery(Qt::ImMicroFocus).toRect().center();
2208 QContextMenuEvent e(QContextMenuEvent::Keyboard, pos, fw->mapToGlobal(pos),
2209 qt_win_getKeyboardModifiers());
2210 result = qt_sendSpontaneousEvent(fw, &e);
2211 }
2212 }
2213 break;
2214#endif
2215
2216 case WM_IME_STARTCOMPOSITION:
2217 case WM_IME_ENDCOMPOSITION:
2218 case WM_IME_COMPOSITION: {
2219 QWidget *fw = QApplication::focusWidget();
2220 QWinInputContext *im = fw ? qobject_cast<QWinInputContext *>(fw->inputContext()) : 0;
2221 if (fw && im) {
2222 if(message == WM_IME_STARTCOMPOSITION)
2223 result = im->startComposition();
2224 else if (message == WM_IME_ENDCOMPOSITION)
2225 result = im->endComposition();
2226 else if (message == WM_IME_COMPOSITION)
2227 result = im->composition(lParam);
2228 }
2229 break;
2230 }
2231 case WM_IME_REQUEST: {
2232 QWidget *fw = QApplication::focusWidget();
2233 QWinInputContext *im = fw ? qobject_cast<QWinInputContext *>(fw->inputContext()) : 0;
2234 if (fw && im) {
2235 if(wParam == IMR_RECONVERTSTRING) {
2236 int ret = im->reconvertString((RECONVERTSTRING *)lParam);
2237 if (ret == -1) {
2238 result = false;
2239 } else {
2240 return ret;
2241 }
2242 } else if (wParam == IMR_CONFIRMRECONVERTSTRING) {
2243 RETURN(TRUE);
2244 } else {
2245 // in all other cases, call DefWindowProc()
2246 result = false;
2247 }
2248 }
2249 break;
2250 }
2251#ifndef Q_WS_WINCE
2252 case WM_CHANGECBCHAIN:
2253 case WM_DRAWCLIPBOARD:
2254#endif
2255 case WM_RENDERFORMAT:
2256 case WM_RENDERALLFORMATS:
2257#ifndef QT_NO_CLIPBOARD
2258 case WM_DESTROYCLIPBOARD:
2259 if (qt_clipboard) {
2260 QClipboardEvent e(reinterpret_cast<QEventPrivate *>(&msg));
2261 qt_sendSpontaneousEvent(qt_clipboard, &e);
2262 RETURN(0);
2263 }
2264 result = false;
2265 break;
2266#endif //QT_NO_CLIPBOARD
2267#ifndef QT_NO_ACCESSIBILITY
2268 case WM_GETOBJECT:
2269 {
2270 // Ignoring all requests while starting up
2271 if (QApplication::startingUp() || QApplication::closingDown() || (DWORD)lParam != OBJID_CLIENT) {
2272 result = false;
2273 break;
2274 }
2275
2276 typedef LRESULT (WINAPI *PtrLresultFromObject)(REFIID, WPARAM, LPUNKNOWN);
2277 static PtrLresultFromObject ptrLresultFromObject = 0;
2278 static bool oleaccChecked = false;
2279
2280 if (!oleaccChecked) {
2281 oleaccChecked = true;
2282#if !defined(Q_OS_WINCE)
2283 ptrLresultFromObject = (PtrLresultFromObject)QLibrary::resolve(QLatin1String("oleacc.dll"), "LresultFromObject");
2284#endif
2285 }
2286 if (ptrLresultFromObject) {
2287 QAccessibleInterface *acc = QAccessible::queryAccessibleInterface(widget);
2288 if (!acc) {
2289 result = false;
2290 break;
2291 }
2292
2293 // and get an instance of the IAccessibile implementation
2294 IAccessible *iface = qt_createWindowsAccessible(acc);
2295 res = ptrLresultFromObject(IID_IAccessible, wParam, iface); // ref == 2
2296 iface->Release(); // the client will release the object again, and then it will destroy itself
2297
2298 if (res > 0)
2299 RETURN(res);
2300 }
2301 }
2302 result = false;
2303 break;
2304 case WM_GETTEXT:
2305 if (!widget->isWindow()) {
2306 int ret = 0;
2307 QAccessibleInterface *acc = QAccessible::queryAccessibleInterface(widget);
2308 if (acc) {
2309 QString text = acc->text(QAccessible::Name, 0);
2310 if (text.isEmpty())
2311 text = widget->objectName();
2312 ret = qMin<int>(wParam - 1, text.size());
2313 text.resize(ret);
2314 memcpy((void *)lParam, text.utf16(), (text.size() + 1) * sizeof(ushort));
2315 delete acc;
2316 }
2317 if (!ret) {
2318 result = false;
2319 break;
2320 }
2321 RETURN(ret);
2322 }
2323 result = false;
2324 break;
2325#endif
2326 case WT_PACKET:
2327 if (ptrWTPacketsGet) {
2328 if ((nPackets = ptrWTPacketsGet(qt_tablet_context, QT_TABLET_NPACKETQSIZE, &localPacketBuf))) {
2329 result = widget->translateTabletEvent(msg, localPacketBuf, nPackets);
2330 }
2331 }
2332 break;
2333 case WT_PROXIMITY:
2334
2335 #ifndef QT_NO_TABLETEVENT
2336 if (ptrWTPacketsGet && ptrWTInfo) {
2337 const bool enteredProximity = LOWORD(lParam) != 0;
2338 PACKET proximityBuffer[1]; // we are only interested in the first packet in this case
2339 const int totalPacks = ptrWTPacketsGet(qt_tablet_context, 1, proximityBuffer);
2340 if (totalPacks > 0) {
2341 const UINT currentCursor = proximityBuffer[0].pkCursor;
2342
2343 UINT csr_physid;
2344 ptrWTInfo(WTI_CURSORS + currentCursor, CSR_PHYSID, &csr_physid);
2345 UINT csr_type;
2346 ptrWTInfo(WTI_CURSORS + currentCursor, CSR_TYPE, &csr_type);
2347 const UINT deviceIdMask = 0xFF6; // device type mask && device color mask
2348 quint64 uniqueId = (csr_type & deviceIdMask);
2349 uniqueId = (uniqueId << 32) | csr_physid;
2350
2351 // initialising and updating the cursor should be done in response to
2352 // WT_CSRCHANGE. We do it in WT_PROXIMITY because some wintab never send
2353 // the event WT_CSRCHANGE even if asked with CXO_CSRMESSAGES
2354 const QTabletCursorInfo *const globalCursorInfo = tCursorInfo();
2355 if (!globalCursorInfo->contains(uniqueId))
2356 tabletInit(uniqueId, csr_type, qt_tablet_context);
2357
2358 currentTabletPointer = globalCursorInfo->value(uniqueId);
2359 tabletUpdateCursor(currentTabletPointer, currentCursor);
2360 }
2361 qt_tabletChokeMouse = false;
2362
2363 QTabletEvent tabletProximity(enteredProximity ? QEvent::TabletEnterProximity
2364 : QEvent::TabletLeaveProximity,
2365 QPoint(), QPoint(), QPointF(), currentTabletPointer.currentDevice, currentTabletPointer.currentPointerType, 0, 0,
2366 0, 0, 0, 0, 0, currentTabletPointer.llId);
2367 QApplication::sendEvent(qApp, &tabletProximity);
2368 }
2369 #endif // QT_NO_TABLETEVENT
2370
2371 break;
2372#ifdef Q_WS_WINCE_WM
2373 case WM_SETFOCUS: {
2374 HIMC hC;
2375 hC = ImmGetContext(hwnd);
2376 ImmSetOpenStatus(hC, TRUE);
2377 ImmEscape(NULL, hC, IME_ESC_SET_MODE, (LPVOID)IM_SPELL);
2378 result = false;
2379 }
2380 break;
2381#endif
2382 case WM_KILLFOCUS:
2383 if (!QWidget::find((HWND)wParam)) { // we don't get focus, so unset it now
2384 if (!widget->hasFocus()) // work around Windows bug after minimizing/restoring
2385 widget = (QETWidget*)QApplication::focusWidget();
2386 HWND focus = ::GetFocus();
2387 //if there is a current widget and the new widget belongs to the same toplevel window
2388 //or if the current widget was embedded into non-qt window (i.e. we won't get WM_ACTIVATEAPP)
2389 //then we clear the focus on the widget
2390 //in case the new widget belongs to a different widget hierarchy, clearing the focus
2391 //will be handled because the active window will change
2392 const bool embedded = widget && ((QETWidget*)widget->window())->topData()->embedded;
2393 if (widget && (embedded || ::IsChild(widget->window()->internalWinId(), focus))) {
2394 widget->clearFocus();
2395 result = true;
2396 } else {
2397 result = false;
2398 }
2399 } else {
2400 result = false;
2401 }
2402 break;
2403 case WM_THEMECHANGED:
2404 if ((widget->windowType() == Qt::Desktop) || !qApp || QApplication::closingDown()
2405 || QApplication::type() == QApplication::Tty)
2406 break;
2407
2408 if (widget->testAttribute(Qt::WA_WState_Polished))
2409 QApplication::style()->unpolish(widget);
2410
2411 if (widget->testAttribute(Qt::WA_WState_Polished))
2412 QApplication::style()->polish(widget);
2413 widget->repolishStyle(*QApplication::style());
2414 if (widget->isVisible())
2415 widget->update();
2416 break;
2417
2418#ifndef Q_WS_WINCE
2419 case WM_INPUTLANGCHANGE: {
2420 wchar_t info[7];
2421 if (!GetLocaleInfo(MAKELCID(lParam, SORT_DEFAULT), LOCALE_IDEFAULTANSICODEPAGE, info, 6)) {
2422 inputcharset = CP_ACP;
2423 } else {
2424 inputcharset = QString::fromWCharArray(info).toInt();
2425 }
2426 QKeyMapper::changeKeyboard();
2427 break;
2428 }
2429#else
2430 case WM_COMMAND: {
2431 bool OkCommand = (LOWORD(wParam) == 0x1);
2432 bool CancelCommand = (LOWORD(wParam) == 0x2);
2433 if (OkCommand)
2434 QApplication::postEvent(widget, new QEvent(QEvent::OkRequest));
2435 if (CancelCommand)
2436 QApplication::postEvent(widget, new QEvent(QEvent::Close));
2437 else
2438#ifndef QT_NO_MENUBAR
2439 QMenuBar::wceCommands(LOWORD(wParam), (HWND) lParam);
2440#endif
2441 result = true;
2442 }
2443 break;
2444 case WM_HELP:
2445 QApplication::postEvent(widget, new QEvent(QEvent::HelpRequest));
2446 result = true;
2447 break;
2448#endif
2449
2450 case WM_MOUSELEAVE:
2451 // We receive a mouse leave for curWin, meaning
2452 // the mouse was moved outside our widgets
2453 if (widget->internalWinId() == curWin) {
2454 bool dispatch = !widget->underMouse();
2455 // hasMouse is updated when dispatching enter/leave,
2456 // so test if it is actually up-to-date
2457 if (!dispatch) {
2458 QRect geom = widget->geometry();
2459 if (widget->parentWidget() && !widget->isWindow()) {
2460 QPoint gp = widget->parentWidget()->mapToGlobal(widget->pos());
2461 geom.setX(gp.x());
2462 geom.setY(gp.y());
2463 }
2464 QPoint cpos = QCursor::pos();
2465 dispatch = !geom.contains(cpos);
2466 if ( !dispatch && !QWidget::mouseGrabber()) {
2467 QWidget *hittest = QApplication::widgetAt(cpos);
2468 dispatch = !hittest || hittest->internalWinId() != curWin;
2469 }
2470 if (!dispatch) {
2471 HRGN hrgn = qt_tryCreateRegion(QRegion::Rectangle, 0,0,0,0);
2472 if (GetWindowRgn(curWin, hrgn) != ERROR) {
2473 QPoint lcpos = widget->mapFromGlobal(cpos);
2474 dispatch = !PtInRegion(hrgn, lcpos.x(), lcpos.y());
2475 }
2476 DeleteObject(hrgn);
2477 }
2478 }
2479 if (dispatch) {
2480 if (qt_last_mouse_receiver && !qt_last_mouse_receiver->internalWinId())
2481 QApplicationPrivate::dispatchEnterLeave(0, qt_last_mouse_receiver);
2482 else
2483 QApplicationPrivate::dispatchEnterLeave(0, QWidget::find((WId)curWin));
2484 curWin = 0;
2485 qt_last_mouse_receiver = 0;
2486 }
2487 }
2488 break;
2489
2490 case WM_CANCELMODE:
2491 {
2492 // this goes through QMenuBar's event filter
2493 QEvent e(QEvent::ActivationChange);
2494 QApplication::sendEvent(qApp, &e);
2495 }
2496 break;
2497
2498 case WM_IME_NOTIFY:
2499 // special handling for ime, only for widgets in a popup
2500 if (wParam == IMN_OPENCANDIDATE) {
2501 imeParentWnd = hwnd;
2502 if (QApplication::activePopupWidget()) {
2503 // temporarily disable the mouse grab to allow mouse input in
2504 // the ime candidate window. The actual handle is untouched
2505 if (autoCaptureWnd)
2506 ReleaseCapture();
2507 }
2508 } else if (wParam == IMN_CLOSECANDIDATE) {
2509 imeParentWnd = 0;
2510 if (QApplication::activePopupWidget()) {
2511 // undo the action above, when candidate window is closed
2512 if (autoCaptureWnd)
2513 SetCapture(autoCaptureWnd);
2514 }
2515 }
2516 result = false;
2517 break;
2518 case WM_GESTURE: {
2519 GESTUREINFO gi;
2520 memset(&gi, 0, sizeof(GESTUREINFO));
2521 gi.cbSize = sizeof(GESTUREINFO);
2522
2523 QApplicationPrivate *qAppPriv = QApplicationPrivate::instance();
2524 BOOL bResult = false;
2525 if (qAppPriv->GetGestureInfo)
2526 bResult = qAppPriv->GetGestureInfo((HANDLE)msg.lParam, &gi);
2527 if (bResult) {
2528 if (gi.dwID == GID_BEGIN) {
2529 // find the alien widget for the gesture position.
2530 // This might not be accurate as the position is the center
2531 // point of two fingers for multi-finger gestures.
2532 QPoint pt(gi.ptsLocation.x, gi.ptsLocation.y);
2533 QWidget *w = widget->childAt(widget->mapFromGlobal(pt));
2534 qAppPriv->gestureWidget = w ? w : widget;
2535 }
2536 if (qAppPriv->gestureWidget)
2537 static_cast<QETWidget*>(qAppPriv->gestureWidget)->translateGestureEvent(msg, gi);
2538 if (qAppPriv->CloseGestureInfoHandle)
2539 qAppPriv->CloseGestureInfoHandle((HANDLE)msg.lParam);
2540 if (gi.dwID == GID_END)
2541 qAppPriv->gestureWidget = 0;
2542 } else {
2543 DWORD dwErr = GetLastError();
2544 if (dwErr > 0)
2545 qWarning() << "translateGestureEvent: error = " << dwErr;
2546 }
2547 result = true;
2548 break;
2549 }
2550 default:
2551 result = false; // event was not processed
2552 break;
2553 }
2554 }
2555
2556 if (evt_type != QEvent::None) { // simple event
2557 QEvent e(evt_type);
2558 result = qt_sendSpontaneousEvent(widget, &e);
2559 }
2560
2561 if (result)
2562 RETURN(false);
2563
2564do_default:
2565 RETURN(QWinInputContext::DefWindowProc(hwnd,message,wParam,lParam))
2566}
2567
2568
2569/*****************************************************************************
2570 Modal widgets; We have implemented our own modal widget mechanism
2571 to get total control.
2572 A modal widget without a parent becomes application-modal.
2573 A modal widget with a parent becomes modal to its parent and grandparents..
2574
2575 QApplicationPrivate::enterModal()
2576 Enters modal state
2577 Arguments:
2578 QWidget *widget A modal widget
2579
2580 QApplicationPrivate::leaveModal()
2581 Leaves modal state for a widget
2582 Arguments:
2583 QWidget *widget A modal widget
2584 *****************************************************************************/
2585
2586bool QApplicationPrivate::modalState()
2587{
2588 return app_do_modal;
2589}
2590
2591void QApplicationPrivate::enterModal_sys(QWidget *widget)
2592{
2593 if (!qt_modal_stack)
2594 qt_modal_stack = new QWidgetList;
2595
2596 releaseAutoCapture();
2597 ClipCursor(0);
2598 QWidget *leave = qt_last_mouse_receiver;
2599 if (!leave)
2600 leave = QWidget::find((WId)curWin);
2601 QApplicationPrivate::dispatchEnterLeave(0, leave);
2602 qt_modal_stack->insert(0, widget);
2603 app_do_modal = true;
2604 curWin = 0;
2605 qt_last_mouse_receiver = 0;
2606 qt_win_ignoreNextMouseReleaseEvent = false;
2607}
2608
2609void QApplicationPrivate::leaveModal_sys(QWidget *widget)
2610{
2611 if (qt_modal_stack && qt_modal_stack->removeAll(widget)) {
2612 if (qt_modal_stack->isEmpty()) {
2613 delete qt_modal_stack;
2614 qt_modal_stack = 0;
2615 QPoint p(QCursor::pos());
2616 app_do_modal = false; // necessary, we may get recursively into qt_try_modal below
2617 QWidget* w = QApplication::widgetAt(p.x(), p.y());
2618 QWidget *leave = qt_last_mouse_receiver;
2619 if (!leave)
2620 leave = QWidget::find((WId)curWin);
2621 if (QWidget *grabber = QWidget::mouseGrabber()) {
2622 w = grabber;
2623 if (leave == w)
2624 leave = 0;
2625 }
2626 QApplicationPrivate::dispatchEnterLeave(w, leave); // send synthetic enter event
2627 curWin = w ? w->effectiveWinId() : 0;
2628 qt_last_mouse_receiver = w;
2629 }
2630 qt_win_ignoreNextMouseReleaseEvent = true;
2631 }
2632 app_do_modal = qt_modal_stack != 0;
2633}
2634
2635bool qt_try_modal(QWidget *widget, MSG *msg, int& ret)
2636{
2637#if defined(Q_OS_WINCE)
2638 Q_UNUSED(ret);
2639#endif
2640 QWidget * top = 0;
2641
2642 if (QApplicationPrivate::tryModalHelper(widget, &top))
2643 return true;
2644
2645 int type = msg->message;
2646
2647 bool block_event = false;
2648#ifndef Q_WS_WINCE
2649 if (type != WM_NCHITTEST) {
2650#endif
2651 if ((type >= WM_MOUSEFIRST && type <= WM_MOUSELAST) ||
2652 type == WM_MOUSEWHEEL || type == WM_MOUSEHWHEEL ||
2653 type == WM_MOUSELEAVE ||
2654 (type >= WM_KEYFIRST && type <= WM_KEYLAST)
2655#ifndef Q_WS_WINCE
2656 || type == WM_NCMOUSEMOVE
2657#endif
2658 ) {
2659 if (type == WM_MOUSEMOVE
2660#ifndef Q_WS_WINCE
2661 || type == WM_NCMOUSEMOVE
2662#endif
2663 ) {
2664#ifndef QT_NO_CURSOR
2665 QCursor *c = qt_grab_cursor();
2666 if (!c)
2667 c = QApplication::overrideCursor();
2668 if (c) // application cursor defined
2669 SetCursor(c->handle());
2670 else
2671 SetCursor(QCursor(Qt::ArrowCursor).handle());
2672#endif // QT_NO_CURSOR
2673 }
2674 block_event = true;
2675 } else if (type == WM_CLOSE) {
2676 block_event = true;
2677 }
2678#ifndef Q_WS_WINCE
2679 else if (type == WM_MOUSEACTIVATE || type == WM_NCLBUTTONDOWN){
2680 if (!top->isActiveWindow()) {
2681 top->activateWindow();
2682 } else {
2683 QApplication::beep();
2684 }
2685 block_event = true;
2686 ret = MA_NOACTIVATEANDEAT;
2687 } else if (type == WM_SYSCOMMAND) {
2688 if (!(msg->wParam == SC_RESTORE && widget->isMinimized()))
2689 block_event = true;
2690 }
2691 }
2692#endif
2693
2694 return !block_event;
2695}
2696
2697
2698/*****************************************************************************
2699 Popup widget mechanism
2700
2701 openPopup()
2702 Adds a widget to the list of popup widgets
2703 Arguments:
2704 QWidget *widget The popup widget to be added
2705
2706 closePopup()
2707 Removes a widget from the list of popup widgets
2708 Arguments:
2709 QWidget *widget The popup widget to be removed
2710 *****************************************************************************/
2711
2712void QApplicationPrivate::openPopup(QWidget *popup)
2713{
2714 if (!QApplicationPrivate::popupWidgets)
2715 QApplicationPrivate::popupWidgets = new QWidgetList;
2716 QApplicationPrivate::popupWidgets->append(popup);
2717 if (!popup->isEnabled())
2718 return;
2719
2720 // close any opened 'ime candidate window'
2721 if (imeParentWnd)
2722 ::SendMessage(imeParentWnd, WM_IME_ENDCOMPOSITION, 0, 0);
2723
2724 if (QApplicationPrivate::popupWidgets->count() == 1 && !qt_nograb()) {
2725 Q_ASSERT(popup->testAttribute(Qt::WA_WState_Created));
2726 setAutoCapture(popup->internalWinId()); // grab mouse/keyboard
2727 }
2728 // Popups are not focus-handled by the window system (the first
2729 // popup grabbed the keyboard), so we have to do that manually: A
2730 // new popup gets the focus
2731 if (popup->focusWidget()) {
2732 popup->focusWidget()->setFocus(Qt::PopupFocusReason);
2733 } else if (QApplicationPrivate::popupWidgets->count() == 1) { // this was the first popup
2734 if (QWidget *fw = QApplication::focusWidget()) {
2735 QFocusEvent e(QEvent::FocusOut, Qt::PopupFocusReason);
2736 QApplication::sendEvent(fw, &e);
2737 }
2738 }
2739}
2740
2741void QApplicationPrivate::closePopup(QWidget *popup)
2742{
2743 if (!QApplicationPrivate::popupWidgets)
2744 return;
2745 QApplicationPrivate::popupWidgets->removeAll(popup);
2746 POINT curPos;
2747 GetCursorPos(&curPos);
2748
2749 // close any opened 'ime candidate window'
2750 if (imeParentWnd)
2751 ::SendMessage(imeParentWnd, WM_IME_ENDCOMPOSITION, 0, 0);
2752
2753 if (QApplicationPrivate::popupWidgets->isEmpty()) { // this was the last popup
2754 delete QApplicationPrivate::popupWidgets;
2755 QApplicationPrivate::popupWidgets = 0;
2756 replayPopupMouseEvent = (!popup->geometry().contains(QPoint(curPos.x, curPos.y))
2757 && !popup->testAttribute(Qt::WA_NoMouseReplay));
2758 if (!popup->isEnabled())
2759 return;
2760 if (!qt_nograb()) // grabbing not disabled
2761 releaseAutoCapture();
2762 QWidget *fw = QApplicationPrivate::active_window ? QApplicationPrivate::active_window->focusWidget()
2763 : QApplication::focusWidget();
2764 if (fw) {
2765 if (fw != QApplication::focusWidget()) {
2766 fw->setFocus(Qt::PopupFocusReason);
2767 } else {
2768 QFocusEvent e(QEvent::FocusIn, Qt::PopupFocusReason);
2769 QApplication::sendEvent(fw, &e);
2770 }
2771 }
2772 } else {
2773 // Popups are not focus-handled by the window system (the
2774 // first popup grabbed the keyboard), so we have to do that
2775 // manually: A popup was closed, so the previous popup gets
2776 // the focus.
2777 QWidget* aw = QApplicationPrivate::popupWidgets->last();
2778 if (QApplicationPrivate::popupWidgets->count() == 1) {
2779 Q_ASSERT(aw->testAttribute(Qt::WA_WState_Created));
2780 setAutoCapture(aw->internalWinId());
2781 }
2782 if (QWidget *fw = aw->focusWidget())
2783 fw->setFocus(Qt::PopupFocusReason);
2784 }
2785}
2786
2787
2788
2789
2790/*****************************************************************************
2791 Event translation; translates Windows events to Qt events
2792 *****************************************************************************/
2793
2794//
2795// Auto-capturing for mouse press and mouse release
2796//
2797
2798static void setAutoCapture(HWND h)
2799{
2800 if (autoCaptureWnd)
2801 releaseAutoCapture();
2802 autoCaptureWnd = h;
2803 SetCapture(h);
2804}
2805
2806static void releaseAutoCapture()
2807{
2808 if (autoCaptureWnd) {
2809 ReleaseCapture();
2810 autoCaptureWnd = 0;
2811 }
2812}
2813
2814
2815//
2816// Mouse event translation
2817//
2818// Non-client mouse messages are not translated
2819//
2820
2821static const ushort mouseTbl[] = {
2822 WM_MOUSEMOVE, QEvent::MouseMove, 0,
2823 WM_LBUTTONDOWN, QEvent::MouseButtonPress, Qt::LeftButton,
2824 WM_LBUTTONUP, QEvent::MouseButtonRelease, Qt::LeftButton,
2825 WM_LBUTTONDBLCLK, QEvent::MouseButtonDblClick, Qt::LeftButton,
2826 WM_RBUTTONDOWN, QEvent::MouseButtonPress, Qt::RightButton,
2827 WM_RBUTTONUP, QEvent::MouseButtonRelease, Qt::RightButton,
2828 WM_RBUTTONDBLCLK, QEvent::MouseButtonDblClick, Qt::RightButton,
2829 WM_MBUTTONDOWN, QEvent::MouseButtonPress, Qt::MidButton,
2830 WM_MBUTTONUP, QEvent::MouseButtonRelease, Qt::MidButton,
2831 WM_MBUTTONDBLCLK, QEvent::MouseButtonDblClick, Qt::MidButton,
2832 // use XButton1 for now, the real X button is decided later
2833 WM_XBUTTONDOWN, QEvent::MouseButtonPress, Qt::XButton1,
2834 WM_XBUTTONUP, QEvent::MouseButtonRelease, Qt::XButton1,
2835 WM_XBUTTONDBLCLK, QEvent::MouseButtonDblClick, Qt::XButton1,
2836
2837#ifndef Q_WS_WINCE
2838 WM_NCMOUSEMOVE, QEvent::NonClientAreaMouseMove, 0,
2839 WM_NCLBUTTONDOWN, QEvent::NonClientAreaMouseButtonPress, Qt::LeftButton,
2840 WM_NCLBUTTONUP, QEvent::NonClientAreaMouseButtonRelease, Qt::LeftButton,
2841 WM_NCLBUTTONDBLCLK, QEvent::NonClientAreaMouseButtonDblClick, Qt::LeftButton,
2842 WM_NCRBUTTONDOWN, QEvent::NonClientAreaMouseButtonPress, Qt::RightButton,
2843 WM_NCRBUTTONUP, QEvent::NonClientAreaMouseButtonRelease, Qt::RightButton,
2844 WM_NCRBUTTONDBLCLK, QEvent::NonClientAreaMouseButtonDblClick, Qt::RightButton,
2845 WM_NCMBUTTONDOWN, QEvent::NonClientAreaMouseButtonPress, Qt::MidButton,
2846 WM_NCMBUTTONUP, QEvent::NonClientAreaMouseButtonRelease, Qt::MidButton,
2847 WM_NCMBUTTONDBLCLK, QEvent::NonClientAreaMouseButtonDblClick, Qt::MidButton,
2848#endif
2849
2850 0, 0, 0
2851};
2852
2853static int translateButtonState(int s, int type, int button)
2854{
2855 Q_UNUSED(type);
2856 Q_UNUSED(button);
2857 int bst = 0;
2858 if (s & MK_LBUTTON)
2859 bst |= Qt::LeftButton;
2860 if (s & MK_MBUTTON)
2861 bst |= Qt::MidButton;
2862 if (s & MK_RBUTTON)
2863 bst |= Qt::RightButton;
2864 if (s & MK_SHIFT)
2865 bst |= Qt::ShiftModifier;
2866 if (s & MK_CONTROL)
2867 bst |= Qt::ControlModifier;
2868
2869 if (s & MK_XBUTTON1)
2870 bst |= Qt::XButton1;
2871 if (s & MK_XBUTTON2)
2872 bst |= Qt::XButton2;
2873
2874 if (GetKeyState(VK_MENU) < 0)
2875 bst |= Qt::AltModifier;
2876
2877 if ((GetKeyState(VK_LWIN) < 0) ||
2878 (GetKeyState(VK_RWIN) < 0))
2879 bst |= Qt::MetaModifier;
2880
2881 return bst;
2882}
2883
2884void qt_win_eatMouseMove()
2885{
2886 // after closing a windows dialog with a double click (i.e. open a file)
2887 // the message queue still contains a dubious WM_MOUSEMOVE message where
2888 // the left button is reported to be down (wParam != 0).
2889 // remove all those messages (usually 1) and post the last one with a
2890 // reset button state
2891
2892 MSG msg = {0, 0, 0, 0, 0, {0, 0} };
2893 while (PeekMessage(&msg, 0, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE))
2894 ;
2895 if (msg.message == WM_MOUSEMOVE)
2896 PostMessage(msg.hwnd, msg.message, 0, msg.lParam);
2897}
2898
2899// In DnD, the mouse release event never appears, so the
2900// mouse button state machine must be manually reset
2901void QApplication::winMouseButtonUp()
2902{
2903 qt_button_down = 0;
2904 releaseAutoCapture();
2905}
2906
2907void QETWidget::repolishStyle(QStyle &)
2908{
2909 QEvent e(QEvent::StyleChange);
2910 QApplication::sendEvent(this, &e);
2911}
2912
2913bool QETWidget::translateMouseEvent(const MSG &msg)
2914{
2915 if (!isWindow() && testAttribute(Qt::WA_NativeWindow))
2916 Q_ASSERT(internalWinId());
2917
2918 static QPoint pos;
2919 static POINT gpos={-1,-1};
2920 QEvent::Type type; // event parameters
2921 int button;
2922 int state;
2923 int i;
2924
2925 if (sm_blockUserInput) //block user interaction during session management
2926 return true;
2927
2928 // Compress mouse move events
2929 if (msg.message == WM_MOUSEMOVE) {
2930 MSG mouseMsg;
2931 while (PeekMessage(&mouseMsg, msg.hwnd, WM_MOUSEFIRST,
2932 WM_MOUSELAST, PM_NOREMOVE)) {
2933 if (mouseMsg.message == WM_MOUSEMOVE) {
2934#define PEEKMESSAGE_IS_BROKEN 1
2935#ifdef PEEKMESSAGE_IS_BROKEN
2936 // Since the Windows PeekMessage() function doesn't
2937 // correctly return the wParam for WM_MOUSEMOVE events
2938 // if there is a key release event in the queue
2939 // _before_ the mouse event, we have to also consider
2940 // key release events (kls 2003-05-13):
2941 MSG keyMsg;
2942 bool done = false;
2943 while (PeekMessage(&keyMsg, 0, WM_KEYFIRST, WM_KEYLAST,
2944 PM_NOREMOVE)) {
2945 if (keyMsg.time < mouseMsg.time) {
2946 if ((keyMsg.lParam & 0xC0000000) == 0x40000000) {
2947 PeekMessage(&keyMsg, 0, keyMsg.message,
2948 keyMsg.message, PM_REMOVE);
2949 } else {
2950 done = true;
2951 break;
2952 }
2953 } else {
2954 break; // no key event before the WM_MOUSEMOVE event
2955 }
2956 }
2957 if (done)
2958 break;
2959#else
2960 // Actually the following 'if' should work instead of
2961 // the above key event checking, but apparently
2962 // PeekMessage() is broken :-(
2963 if (mouseMsg.wParam != msg.wParam)
2964 break; // leave the message in the queue because
2965 // the key state has changed
2966#endif
2967 MSG *msgPtr = (MSG *)(&msg);
2968 // Update the passed in MSG structure with the
2969 // most recent one.
2970 msgPtr->lParam = mouseMsg.lParam;
2971 msgPtr->wParam = mouseMsg.wParam;
2972 msgPtr->pt = mouseMsg.pt;
2973 // Remove the mouse move message
2974 PeekMessage(&mouseMsg, msg.hwnd, WM_MOUSEMOVE,
2975 WM_MOUSEMOVE, PM_REMOVE);
2976 } else {
2977 break; // there was no more WM_MOUSEMOVE event
2978 }
2979 }
2980 }
2981
2982 for (i=0; (UINT)mouseTbl[i] != msg.message && mouseTbl[i]; i += 3)
2983 ;
2984 if (!mouseTbl[i])
2985 return false;
2986 type = (QEvent::Type)mouseTbl[++i]; // event type
2987 button = mouseTbl[++i]; // which button
2988 if (button == Qt::XButton1) {
2989 switch(GET_XBUTTON_WPARAM(msg.wParam)) {
2990 case XBUTTON1:
2991 button = Qt::XButton1;
2992 break;
2993 case XBUTTON2:
2994 button = Qt::XButton2;
2995 break;
2996 }
2997 }
2998 state = translateButtonState(msg.wParam, type, button); // button state
2999 const QPoint widgetPos = mapFromGlobal(QPoint(msg.pt.x, msg.pt.y));
3000 QWidget *alienWidget = !internalWinId() ? this : childAt(widgetPos);
3001 if (alienWidget && alienWidget->internalWinId())
3002 alienWidget = 0;
3003
3004 if (type == QEvent::MouseMove || type == QEvent::NonClientAreaMouseMove
3005 || type == QEvent::TabletMove) {
3006
3007 if (!(state & Qt::MouseButtonMask))
3008 qt_button_down = 0;
3009#ifndef QT_NO_CURSOR
3010 QCursor *c = qt_grab_cursor();
3011 if (!c)
3012 c = QApplication::overrideCursor();
3013 if (c) // application cursor defined
3014 SetCursor(c->handle());
3015 else if (type != QEvent::NonClientAreaMouseMove && !qt_button_down) {
3016 // use widget cursor if widget is enabled
3017 QWidget *w = alienWidget ? alienWidget : this;
3018 while (!w->isWindow() && !w->isEnabled())
3019 w = w->parentWidget();
3020 SetCursor(w->cursor().handle());
3021 }
3022#endif // QT_NO_CURSOR
3023
3024 HWND id = effectiveWinId();
3025 QWidget *mouseGrabber = QWidget::mouseGrabber();
3026 QWidget *activePopupWidget = QApplication::activePopupWidget();
3027 if (mouseGrabber) {
3028 if (!activePopupWidget || (activePopupWidget == this && !rect().contains(widgetPos)))
3029 id = mouseGrabber->effectiveWinId();
3030 } else if (type == QEvent::NonClientAreaMouseMove) {
3031 id = 0;
3032 }
3033
3034 if (curWin != id) { // new current window
3035 if (id == 0) {
3036 QWidget *leave = qt_last_mouse_receiver;
3037 if (!leave)
3038 leave = QWidget::find(curWin);
3039 QApplicationPrivate::dispatchEnterLeave(0, leave);
3040 qt_last_mouse_receiver = 0;
3041 curWin = 0;
3042 } else {
3043 QWidget *leave = 0;
3044 if (curWin && qt_last_mouse_receiver)
3045 leave = qt_last_mouse_receiver;
3046 else
3047 leave = QWidget::find(curWin);
3048 QWidget *enter = alienWidget ? alienWidget : this;
3049 if (mouseGrabber && activePopupWidget) {
3050 if (leave != mouseGrabber)
3051 enter = mouseGrabber;
3052 else
3053 enter = activePopupWidget == this ? this : mouseGrabber;
3054 }
3055 QApplicationPrivate::dispatchEnterLeave(enter, leave);
3056 qt_last_mouse_receiver = enter;
3057 curWin = enter ? enter->effectiveWinId() : 0;
3058 }
3059#ifndef Q_OS_WINCE
3060
3061 if (curWin != 0) {
3062 static bool trackMouseEventLookup = false;
3063 typedef BOOL (WINAPI *PtrTrackMouseEvent)(LPTRACKMOUSEEVENT);
3064 static PtrTrackMouseEvent ptrTrackMouseEvent = 0;
3065 if (!trackMouseEventLookup) {
3066 trackMouseEventLookup = true;
3067 ptrTrackMouseEvent = (PtrTrackMouseEvent)QLibrary::resolve(QLatin1String("comctl32"), "_TrackMouseEvent");
3068 }
3069 if (ptrTrackMouseEvent && !qApp->d_func()->inPopupMode()) {
3070 // We always have to set the tracking, since
3071 // Windows detects more leaves than we do..
3072 TRACKMOUSEEVENT tme;
3073 tme.cbSize = sizeof(TRACKMOUSEEVENT);
3074 tme.dwFlags = 0x00000002; // TME_LEAVE
3075 tme.hwndTrack = curWin; // Track on window receiving msgs
3076 tme.dwHoverTime = (DWORD)-1; // HOVER_DEFAULT
3077 ptrTrackMouseEvent(&tme);
3078 }
3079 }
3080#endif // Q_OS_WINCE
3081 }
3082
3083 POINT curPos = msg.pt;
3084 if (curPos.x == gpos.x && curPos.y == gpos.y)
3085 return true; // same global position
3086 gpos = curPos;
3087
3088 Q_ASSERT(testAttribute(Qt::WA_WState_Created));
3089 ScreenToClient(internalWinId(), &curPos);
3090
3091 pos.rx() = curPos.x;
3092 pos.ry() = curPos.y;
3093 pos = d_func()->mapFromWS(pos);
3094 } else {
3095 gpos = msg.pt;
3096 pos = mapFromGlobal(QPoint(gpos.x, gpos.y));
3097
3098 // mouse button pressed
3099 if (!qt_button_down && (type == QEvent::MouseButtonPress || type == QEvent::MouseButtonDblClick)) {
3100 QWidget *tlw = window();
3101 if (QWidget *child = tlw->childAt(mapTo(tlw, pos)))
3102 qt_button_down = child;
3103 else
3104 qt_button_down = this;
3105 }
3106 }
3107
3108 bool res = false;
3109
3110 bool nonClientAreaEvent = type >= QEvent::NonClientAreaMouseMove
3111 && type <= QEvent::NonClientAreaMouseButtonDblClick;
3112
3113 if (qApp->d_func()->inPopupMode()) { // in popup mode
3114
3115 if (nonClientAreaEvent)
3116 return false;
3117
3118 replayPopupMouseEvent = false;
3119 QWidget* activePopupWidget = QApplication::activePopupWidget();
3120 QWidget *target = activePopupWidget;
3121 const QPoint globalPos(gpos.x, gpos.y);
3122
3123 if (target != this) {
3124 if ((windowType() == Qt::Popup) && rect().contains(pos) && 0)
3125 target = this;
3126 else // send to last popup
3127 pos = target->mapFromGlobal(globalPos);
3128 }
3129 QWidget *popupChild = target->childAt(pos);
3130 bool releaseAfter = false;
3131 switch (type) {
3132 case QEvent::MouseButtonPress:
3133 case QEvent::MouseButtonDblClick:
3134 popupButtonFocus = popupChild;
3135 break;
3136 case QEvent::MouseButtonRelease:
3137 case QEvent::TabletRelease:
3138
3139 releaseAfter = true;
3140 break;
3141 default:
3142 break; // nothing for mouse move
3143 }
3144
3145 if (target->isEnabled()) {
3146 if (popupButtonFocus) {
3147 target = popupButtonFocus;
3148 } else if (popupChild) {
3149 target = popupChild;
3150 }
3151
3152 pos = target->mapFromGlobal(globalPos);
3153 QMouseEvent e(type, pos, globalPos,
3154 Qt::MouseButton(button),
3155 Qt::MouseButtons(state & Qt::MouseButtonMask),
3156 Qt::KeyboardModifiers(state & Qt::KeyboardModifierMask));
3157 res = QApplicationPrivate::sendMouseEvent(target, &e, alienWidget, this, &qt_button_down,
3158 qt_last_mouse_receiver);
3159 res = res && e.isAccepted();
3160 } else {
3161 // close disabled popups when a mouse button is pressed or released
3162 switch (type) {
3163 case QEvent::MouseButtonPress:
3164 case QEvent::MouseButtonDblClick:
3165 case QEvent::MouseButtonRelease:
3166 target->close();
3167 break;
3168 default:
3169 break;
3170 }
3171 }
3172
3173 if (releaseAfter) {
3174 popupButtonFocus = 0;
3175 qt_button_down = 0;
3176 }
3177
3178 if (type == QEvent::MouseButtonPress
3179 && QApplication::activePopupWidget() != activePopupWidget
3180 && replayPopupMouseEvent) {
3181 // the popup dissappeared. Replay the event
3182 QWidget* w = QApplication::widgetAt(gpos.x, gpos.y);
3183 if (w && !QApplicationPrivate::isBlockedByModal(w)) {
3184 Q_ASSERT(w->testAttribute(Qt::WA_WState_Created));
3185 HWND hwndTarget = w->effectiveWinId();
3186 if (QWidget::mouseGrabber() == 0)
3187 setAutoCapture(hwndTarget);
3188 if (!w->isActiveWindow())
3189 w->activateWindow();
3190 POINT widgetpt = gpos;
3191 ScreenToClient(hwndTarget, &widgetpt);
3192 LPARAM lParam = MAKELPARAM(widgetpt.x, widgetpt.y);
3193 PostMessage(hwndTarget, msg.message, msg.wParam, lParam);
3194 }
3195 } else if (type == QEvent::MouseButtonRelease && button == Qt::RightButton
3196 && QApplication::activePopupWidget() == activePopupWidget) {
3197 // popup still alive and received right-button-release
3198#if !defined(QT_NO_CONTEXTMENU)
3199 QContextMenuEvent e2(QContextMenuEvent::Mouse, pos, globalPos,
3200 qt_win_getKeyboardModifiers());
3201 bool res2 = QApplication::sendSpontaneousEvent( target, &e2 );
3202 if (!res) // RMB not accepted
3203 res = res2 && e2.isAccepted();
3204#endif
3205 }
3206 } else { // not popup mode
3207 int bs = state & Qt::MouseButtonMask;
3208 if ((type == QEvent::MouseButtonPress ||
3209 type == QEvent::MouseButtonDblClick) && bs == button) {
3210 Q_ASSERT(testAttribute(Qt::WA_WState_Created));
3211 if (QWidget::mouseGrabber() == 0)
3212 setAutoCapture(internalWinId());
3213 } else if (type == QEvent::MouseButtonRelease && bs == 0) {
3214 if (QWidget::mouseGrabber() == 0)
3215 releaseAutoCapture();
3216 }
3217
3218 const QPoint globalPos(gpos.x,gpos.y);
3219 QWidget *widget = QApplicationPrivate::pickMouseReceiver(this, globalPos, pos, type,
3220 Qt::MouseButtons(bs),
3221 qt_button_down, alienWidget);
3222 if (!widget)
3223 return false; // don't send event
3224
3225 QMouseEvent e(type, pos, globalPos, Qt::MouseButton(button),
3226 Qt::MouseButtons(state & Qt::MouseButtonMask),
3227 Qt::KeyboardModifiers(state & Qt::KeyboardModifierMask));
3228
3229 res = QApplicationPrivate::sendMouseEvent(widget, &e, alienWidget, this, &qt_button_down,
3230 qt_last_mouse_receiver);
3231
3232 // non client area events are only informational, you cannot "handle" them
3233 res = res && e.isAccepted() && !nonClientAreaEvent;
3234#if !defined(QT_NO_CONTEXTMENU)
3235 if (type == QEvent::MouseButtonRelease && button == Qt::RightButton) {
3236 QContextMenuEvent e2(QContextMenuEvent::Mouse, pos, globalPos,
3237 qt_win_getKeyboardModifiers());
3238 bool res2 = QApplication::sendSpontaneousEvent(widget, &e2);
3239 if (!res)
3240 res = res2 && e2.isAccepted();
3241 }
3242#endif
3243
3244 if (type != QEvent::MouseMove)
3245 pos.rx() = pos.ry() = -9999; // init for move compression
3246 }
3247 return res;
3248}
3249
3250bool QETWidget::translateWheelEvent(const MSG &msg)
3251{
3252 int state = 0;
3253
3254 if (sm_blockUserInput) // block user interaction during session management
3255 return true;
3256
3257 state = translateButtonState(GET_KEYSTATE_WPARAM(msg.wParam), 0, 0);
3258
3259 int delta;
3260 if (msg.message == WM_MOUSEWHEEL || msg.message == WM_MOUSEHWHEEL)
3261 delta = (short) HIWORD (msg.wParam);
3262 else
3263 delta = (int) msg.wParam;
3264
3265 Qt::Orientation orient = (msg.message == WM_MOUSEHWHEEL || state&Qt::AltModifier
3266#if 0
3267 // disabled for now - Trenton's one-wheel mouse makes trouble...
3268 // "delta" for usual wheels is +-120. +-240 seems to indicate
3269 // the second wheel see more recent MSDN for WM_MOUSEWHEEL
3270
3271 ( // <- parantheses added to make update happy, remove if the
3272 // #if 0 is removed
3273 || delta == 240 || delta == -240)?Qt::Horizontal:Vertical;
3274 if (delta == 240 || delta == -240)
3275 delta /= 2;
3276#endif
3277 ) ? Qt::Horizontal : Qt::Vertical;
3278
3279 // according to the MSDN documentation on WM_MOUSEHWHEEL:
3280 // a positive value indicates that the wheel was rotated to the right;
3281 // a negative value indicates that the wheel was rotated to the left.
3282 // Qt defines this value as the exact opposite, so we have to flip the value!
3283 if (msg.message == WM_MOUSEHWHEEL)
3284 delta = -delta;
3285
3286 QPoint globalPos;
3287
3288 globalPos.rx() = (short)LOWORD (msg.lParam);
3289 globalPos.ry() = (short)HIWORD (msg.lParam);
3290
3291
3292 // if there is a widget under the mouse and it is not shadowed
3293 // by modality, we send the event to it first
3294 int ret = 0;
3295 QWidget* w = QApplication::widgetAt(globalPos);
3296 if (!w || !qt_try_modal(w, (MSG*)&msg, ret)) {
3297 //synaptics touchpad shows its own widget at this position
3298 //so widgetAt() will fail with that HWND, try child of this widget
3299 w = this->childAt(this->mapFromGlobal(globalPos));
3300 if (!w)
3301 w = this;
3302 }
3303
3304 // send the event to the widget or its ancestors
3305 {
3306 QWidget* popup = QApplication::activePopupWidget();
3307 if (popup && w->window() != popup)
3308 popup->close();
3309#ifndef QT_NO_WHEELEVENT
3310 QWheelEvent e(w->mapFromGlobal(globalPos), globalPos, delta,
3311 Qt::MouseButtons(state & Qt::MouseButtonMask),
3312 Qt::KeyboardModifier(state & Qt::KeyboardModifierMask), orient);
3313
3314 if (QApplication::sendSpontaneousEvent(w, &e))
3315#else
3316 Q_UNUSED(orient);
3317#endif //QT_NO_WHEELEVENT
3318 return true;
3319 }
3320
3321 // send the event to the widget that has the focus or its ancestors, if different
3322 if (w != QApplication::focusWidget() && (w = QApplication::focusWidget())) {
3323 QWidget* popup = QApplication::activePopupWidget();
3324 if (popup && w->window() != popup)
3325 popup->close();
3326#ifndef QT_NO_WHEELEVENT
3327 QWheelEvent e(w->mapFromGlobal(globalPos), globalPos, delta,
3328 Qt::MouseButtons(state & Qt::MouseButtonMask),
3329 Qt::KeyboardModifier(state & Qt::KeyboardModifierMask), orient);
3330 if (QApplication::sendSpontaneousEvent(w, &e))
3331#endif //QT_NO_WHEELEVENT
3332 return true;
3333 }
3334 return false;
3335}
3336
3337
3338//
3339// Windows Wintab to QTabletEvent translation
3340//
3341
3342// the following is adapted from the wintab syspress example (public domain)
3343/* -------------------------------------------------------------------------- */
3344// Initialize the "static" information of a cursor device (pen, airbrush, etc).
3345// The QTabletDeviceData is initialized with the data that do not change in time
3346// (number of button, type of device, etc) but do not initialize the variable data
3347// (e.g.: pen or eraser)
3348#ifndef QT_NO_TABLETEVENT
3349
3350static void tabletInit(const quint64 uniqueId, const UINT csr_type, HCTX hTab)
3351{
3352 Q_ASSERT(ptrWTInfo);
3353 Q_ASSERT(ptrWTGet);
3354
3355 Q_ASSERT(!tCursorInfo()->contains(uniqueId));
3356
3357 /* browse WinTab's many info items to discover pressure handling. */
3358 AXIS np;
3359 LOGCONTEXT lc;
3360
3361 /* get the current context for its device variable. */
3362 ptrWTGet(hTab, &lc);
3363
3364 /* get the size of the pressure axis. */
3365 QTabletDeviceData tdd;
3366 tdd.llId = uniqueId;
3367
3368 ptrWTInfo(WTI_DEVICES + lc.lcDevice, DVC_NPRESSURE, &np);
3369 tdd.minPressure = int(np.axMin);
3370 tdd.maxPressure = int(np.axMax);
3371
3372 ptrWTInfo(WTI_DEVICES + lc.lcDevice, DVC_TPRESSURE, &np);
3373 tdd.minTanPressure = int(np.axMin);
3374 tdd.maxTanPressure = int(np.axMax);
3375
3376 LOGCONTEXT lcMine;
3377
3378 /* get default region */
3379 ptrWTInfo(WTI_DEFCONTEXT, 0, &lcMine);
3380
3381 tdd.minX = 0;
3382 tdd.maxX = int(lcMine.lcInExtX) - int(lcMine.lcInOrgX);
3383
3384 tdd.minY = 0;
3385 tdd.maxY = int(lcMine.lcInExtY) - int(lcMine.lcInOrgY);
3386
3387 tdd.minZ = 0;
3388 tdd.maxZ = int(lcMine.lcInExtZ) - int(lcMine.lcInOrgZ);
3389
3390 const uint cursorTypeBitMask = 0x0F06; // bitmask to find the specific cursor type (see Wacom FAQ)
3391 if (((csr_type & 0x0006) == 0x0002) && ((csr_type & cursorTypeBitMask) != 0x0902)) {
3392 tdd.currentDevice = QTabletEvent::Stylus;
3393 } else {
3394 switch (csr_type & cursorTypeBitMask) {
3395 case 0x0802:
3396 tdd.currentDevice = QTabletEvent::Stylus;
3397 break;
3398 case 0x0902:
3399 tdd.currentDevice = QTabletEvent::Airbrush;
3400 break;
3401 case 0x0004:
3402 tdd.currentDevice = QTabletEvent::FourDMouse;
3403 break;
3404 case 0x0006:
3405 tdd.currentDevice = QTabletEvent::Puck;
3406 break;
3407 case 0x0804:
3408 tdd.currentDevice = QTabletEvent::RotationStylus;
3409 break;
3410 default:
3411 tdd.currentDevice = QTabletEvent::NoDevice;
3412 }
3413 }
3414 tCursorInfo()->insert(uniqueId, tdd);
3415}
3416#endif // QT_NO_TABLETEVENT
3417
3418// Update the "dynamic" informations of a cursor device (pen, airbrush, etc).
3419// The dynamic information is the information of QTabletDeviceData that can change
3420// in time (eraser or pen if a device is turned around).
3421#ifndef QT_NO_TABLETEVENT
3422
3423static void tabletUpdateCursor(QTabletDeviceData &tdd, const UINT currentCursor)
3424{
3425 switch (currentCursor % 3) { // %3 for dual track
3426 case 0:
3427 tdd.currentPointerType = QTabletEvent::Cursor;
3428 break;
3429 case 1:
3430 tdd.currentPointerType = QTabletEvent::Pen;
3431 break;
3432 case 2:
3433 tdd.currentPointerType = QTabletEvent::Eraser;
3434 break;
3435 default:
3436 tdd.currentPointerType = QTabletEvent::UnknownPointer;
3437 }
3438}
3439#endif // QT_NO_TABLETEVENT
3440
3441bool QETWidget::translateTabletEvent(const MSG &msg, PACKET *localPacketBuf,
3442 int numPackets)
3443{
3444 Q_UNUSED(msg);
3445 POINT ptNew;
3446 static DWORD btnNew, btnOld, btnChange;
3447 qreal prsNew;
3448 ORIENTATION ort;
3449 static bool button_pressed = false;
3450 int i,
3451 tiltX,
3452 tiltY;
3453 bool sendEvent = false;
3454 QEvent::Type t;
3455 int z = 0;
3456 qreal rotation = 0.0;
3457 qreal tangentialPressure;
3458
3459 // the most common event that we get...
3460 t = QEvent::TabletMove;
3461 for (i = 0; i < numPackets; i++) {
3462 // get the unique ID of the device...
3463 btnOld = btnNew;
3464 btnNew = localPacketBuf[i].pkButtons;
3465 btnChange = btnOld ^ btnNew;
3466
3467 if (btnNew & btnChange) {
3468 button_pressed = true;
3469 t = QEvent::TabletPress;
3470 }
3471 ptNew.x = UINT(localPacketBuf[i].pkX);
3472 ptNew.y = UINT(localPacketBuf[i].pkY);
3473#ifndef QT_NO_TABLETEVENT
3474 z = (currentTabletPointer.currentDevice == QTabletEvent::FourDMouse) ? UINT(localPacketBuf[i].pkZ) : 0;
3475#else
3476 Q_UNUSED(z);
3477#endif // QT_NO_TABLETEVENT
3478 prsNew = 0.0;
3479 QRect desktopArea = QApplication::desktop()->geometry();
3480 QPointF hiResGlobal = currentTabletPointer.scaleCoord(ptNew.x, ptNew.y, desktopArea.left(),
3481 desktopArea.width(), desktopArea.top(),
3482 desktopArea.height());
3483
3484 if (btnNew) {
3485#ifndef QT_NO_TABLETEVENT
3486 if (currentTabletPointer.currentPointerType == QTabletEvent::Pen || currentTabletPointer.currentPointerType == QTabletEvent::Eraser)
3487 prsNew = localPacketBuf[i].pkNormalPressure
3488 / qreal(currentTabletPointer.maxPressure
3489 - currentTabletPointer.minPressure);
3490 else
3491#endif // QT_NO_TABLETEVENT
3492 prsNew = 0;
3493 } else if (button_pressed) {
3494 // One button press, should only give one button release
3495 t = QEvent::TabletRelease;
3496 button_pressed = false;
3497 }
3498 QPoint globalPos(qRound(hiResGlobal.x()), qRound(hiResGlobal.y()));
3499
3500 if (t == QEvent::TabletPress)
3501 {
3502 qt_button_down = QApplication::widgetAt(globalPos);
3503 }
3504
3505 // make sure the tablet event get's sent to the proper widget...
3506 QWidget *w = 0;
3507
3508 if (qt_button_down)
3509 w = qt_button_down; // Pass it to the thing that's grabbed it.
3510 else
3511 w = QApplication::widgetAt(globalPos);
3512
3513 if (!w)
3514 w = this;
3515
3516 if (t == QEvent::TabletRelease)
3517 {
3518 if (qt_win_ignoreNextMouseReleaseEvent) {
3519 qt_win_ignoreNextMouseReleaseEvent = false;
3520 if (qt_button_down && qt_button_down->internalWinId() == autoCaptureWnd) {
3521 releaseAutoCapture();
3522 qt_button_down = 0;
3523 }
3524 }
3525
3526 }
3527
3528 QPoint localPos = w->mapFromGlobal(globalPos);
3529#ifndef QT_NO_TABLETEVENT
3530 if (currentTabletPointer.currentDevice == QTabletEvent::Airbrush) {
3531 tangentialPressure = localPacketBuf[i].pkTangentPressure
3532 / qreal(currentTabletPointer.maxTanPressure
3533 - currentTabletPointer.minTanPressure);
3534 } else {
3535 tangentialPressure = 0.0;
3536 }
3537#else
3538 tangentialPressure = 0.0;
3539#endif // QT_NO_TABLETEVENT
3540
3541 if (!qt_tablet_tilt_support) {
3542 tiltX = tiltY = 0;
3543 rotation = 0.0;
3544 } else {
3545 ort = localPacketBuf[i].pkOrientation;
3546 // convert from azimuth and altitude to x tilt and y tilt
3547 // what follows is the optimized version. Here are the equations
3548 // I used to get to this point (in case things change :)
3549 // X = sin(azimuth) * cos(altitude)
3550 // Y = cos(azimuth) * cos(altitude)
3551 // Z = sin(altitude)
3552 // X Tilt = arctan(X / Z)
3553 // Y Tilt = arctan(Y / Z)
3554 double radAzim = (ort.orAzimuth / 10) * (Q_PI / 180);
3555 //double radAlt = abs(ort.orAltitude / 10) * (Q_PI / 180);
3556 double tanAlt = tan((abs(ort.orAltitude / 10)) * (Q_PI / 180));
3557
3558 double degX = atan(sin(radAzim) / tanAlt);
3559 double degY = atan(cos(radAzim) / tanAlt);
3560 tiltX = int(degX * (180 / Q_PI));
3561 tiltY = int(-degY * (180 / Q_PI));
3562 rotation = ort.orTwist;
3563 }
3564#ifndef QT_NO_TABLETEVENT
3565 QTabletEvent e(t, localPos, globalPos, hiResGlobal, currentTabletPointer.currentDevice,
3566 currentTabletPointer.currentPointerType, prsNew, tiltX, tiltY,
3567 tangentialPressure, rotation, z, QApplication::keyboardModifiers(), currentTabletPointer.llId);
3568 sendEvent = QApplication::sendSpontaneousEvent(w, &e);
3569#endif // QT_NO_TABLETEVENT
3570 }
3571 return sendEvent;
3572}
3573
3574extern bool qt_is_gui_used;
3575
3576
3577#ifndef QT_NO_TABLETEVENT
3578
3579static void initWinTabFunctions()
3580{
3581#if defined(Q_OS_WINCE)
3582 return;
3583#else
3584 if (!qt_is_gui_used)
3585 return;
3586
3587 QLibrary library(QLatin1String("wintab32"));
3588 if (library.load()) {
3589 ptrWTInfo = (PtrWTInfo)library.resolve("WTInfoW");
3590 ptrWTGet = (PtrWTGet)library.resolve("WTGetW");
3591 ptrWTEnable = (PtrWTEnable)library.resolve("WTEnable");
3592 ptrWTOverlap = (PtrWTEnable)library.resolve("WTOverlap");
3593 ptrWTPacketsGet = (PtrWTPacketsGet)library.resolve("WTPacketsGet");
3594 }
3595#endif // Q_OS_WINCE
3596}
3597#endif // QT_NO_TABLETEVENT
3598
3599
3600//
3601// Paint event translation
3602//
3603bool QETWidget::translatePaintEvent(const MSG &msg)
3604{
3605 if (!isWindow() && testAttribute(Qt::WA_NativeWindow))
3606 Q_ASSERT(internalWinId());
3607
3608 Q_ASSERT(testAttribute(Qt::WA_WState_Created));
3609 if (!GetUpdateRect(internalWinId(), 0, FALSE)) { // The update bounding rect is invalid
3610 d_func()->hd = 0;
3611 setAttribute(Qt::WA_PendingUpdate, false);
3612 return false;
3613 }
3614
3615 if (msg.message == WM_ERASEBKGND)
3616 return true;
3617
3618 setAttribute(Qt::WA_PendingUpdate, false);
3619 const QRegion dirtyInBackingStore(qt_dirtyRegion(this));
3620 // Make sure the invalidated region contains the region we're about to repaint.
3621 // BeginPaint will set the clip to the invalidated region and it is impossible
3622 // to enlarge it afterwards (only shrink it). Using GetDCEx is not suffient
3623 // as it may return an invalid context (especially on Windows Vista).
3624 if (!dirtyInBackingStore.isEmpty())
3625 InvalidateRgn(internalWinId(), dirtyInBackingStore.handle(), false);
3626 PAINTSTRUCT ps;
3627 d_func()->hd = BeginPaint(internalWinId(), &ps);
3628
3629 const QRect updateRect(QPoint(ps.rcPaint.left, ps.rcPaint.top),
3630 QPoint(ps.rcPaint.right, ps.rcPaint.bottom));
3631
3632 // Mapping region from system to qt (32 bit) coordinate system.
3633 d_func()->syncBackingStore(updateRect.translated(data->wrect.topLeft()));
3634
3635 d_func()->hd = 0;
3636 EndPaint(internalWinId(), &ps);
3637
3638 return true;
3639}
3640
3641//
3642// Window move and resize (configure) events
3643//
3644
3645bool QETWidget::translateConfigEvent(const MSG &msg)
3646{
3647 if (!testAttribute(Qt::WA_WState_Created)) // in QWidget::create()
3648 return true;
3649 if (testAttribute(Qt::WA_WState_ConfigPending))
3650 return true;
3651 if (testAttribute(Qt::WA_DontShowOnScreen))
3652 return true;
3653 if (!isWindow())
3654 return true;
3655 setAttribute(Qt::WA_WState_ConfigPending); // set config flag
3656 QRect cr = geometry();
3657 if (msg.message == WM_SIZE) { // resize event
3658 WORD a = LOWORD(msg.lParam);
3659 WORD b = HIWORD(msg.lParam);
3660 QSize oldSize = size();
3661 QSize newSize(a, b);
3662#ifdef Q_WS_WINCE_WM
3663 if (isFullScreen() && (oldSize.width() == newSize.height()) && (oldSize.height() == newSize.width()))
3664 qt_wince_hide_taskbar(internalWinId());
3665#endif
3666 cr.setSize(newSize);
3667 if (msg.wParam != SIZE_MINIMIZED)
3668 data->crect = cr;
3669 if (isWindow()) { // update title/icon text
3670 d_func()->createTLExtra();
3671 // Capture SIZE_MINIMIZED without preceding WM_SYSCOMMAND
3672 // (like Windows+M)
3673 if (msg.wParam == SIZE_MINIMIZED && !isMinimized()) {
3674#ifndef Q_WS_WINCE
3675 const QString title = windowIconText();
3676 if (!title.isEmpty())
3677 d_func()->setWindowTitle_helper(title);
3678#endif
3679 data->window_state |= Qt::WindowMinimized;
3680 if (isVisible()) {
3681 QHideEvent e;
3682 QApplication::sendSpontaneousEvent(this, &e);
3683 hideChildren(true);
3684 }
3685 } else if (msg.wParam != SIZE_MINIMIZED && isMinimized()) {
3686#ifndef Q_WS_WINCE
3687 const QString title = windowTitle();
3688 if (!title.isEmpty())
3689 d_func()->setWindowTitle_helper(title);
3690#endif
3691 data->window_state &= ~Qt::WindowMinimized;
3692 showChildren(true);
3693 QShowEvent e;
3694 QApplication::sendSpontaneousEvent(this, &e);
3695 }
3696 }
3697 if (msg.wParam != SIZE_MINIMIZED && oldSize != newSize) {
3698 if (isVisible()) {
3699 QTLWExtra *tlwExtra = maybeTopData();
3700 static bool slowResize = qgetenv("QT_SLOW_TOPLEVEL_RESIZE").toInt();
3701 const bool hasStaticContents = tlwExtra && tlwExtra->backingStore
3702 && tlwExtra->backingStore->hasStaticContents();
3703 // If we have a backing store with static contents, we have to disable the top-level
3704 // resize optimization in order to get invalidated regions for resized widgets.
3705 // The optimization discards all invalidateBuffer() calls since we're going to
3706 // repaint everything anyways, but that's not the case with static contents.
3707 if (!slowResize && tlwExtra && !hasStaticContents)
3708 tlwExtra->inTopLevelResize = true;
3709 QResizeEvent e(newSize, oldSize);
3710 QApplication::sendSpontaneousEvent(this, &e);
3711 if (d_func()->paintOnScreen()) {
3712 QRegion updateRegion(rect());
3713 if (testAttribute(Qt::WA_StaticContents))
3714 updateRegion -= QRect(0, 0, oldSize.width(), oldSize.height());
3715 d_func()->syncBackingStore(updateRegion);
3716 } else {
3717 d_func()->syncBackingStore();
3718 }
3719 if (!slowResize && tlwExtra)
3720 tlwExtra->inTopLevelResize = false;
3721 } else {
3722 QResizeEvent *e = new QResizeEvent(newSize, oldSize);
3723 QApplication::postEvent(this, e);
3724 }
3725 }
3726} else if (msg.message == WM_MOVE) { // move event
3727 int a = (int) (short) LOWORD(msg.lParam);
3728 int b = (int) (short) HIWORD(msg.lParam);
3729 QPoint oldPos = geometry().topLeft();
3730 QPoint newCPos(a, b);
3731 // Ignore silly Windows move event to wild pos after iconify.
3732#if !defined(Q_WS_WINCE)
3733 if (!IsIconic(internalWinId()) && newCPos != oldPos) {
3734#endif
3735 cr.moveTopLeft(newCPos);
3736 data->crect = cr;
3737 if (isVisible()) {
3738 QMoveEvent e(newCPos, oldPos); // cpos (client position)
3739 QApplication::sendSpontaneousEvent(this, &e);
3740 } else {
3741 QMoveEvent * e = new QMoveEvent(newCPos, oldPos);
3742 QApplication::postEvent(this, e);
3743 }
3744#if !defined(Q_WS_WINCE)
3745 }
3746#endif
3747 }
3748 setAttribute(Qt::WA_WState_ConfigPending, false); // clear config flag
3749 return true;
3750}
3751
3752
3753//
3754// Close window event translation.
3755//
3756// This class is a friend of QApplication because it needs to emit the
3757// lastWindowClosed() signal when the last top level widget is closed.
3758//
3759
3760bool QETWidget::translateCloseEvent(const MSG &)
3761{
3762 return d_func()->close_helper(QWidgetPrivate::CloseWithSpontaneousEvent);
3763}
3764
3765bool QETWidget::translateGestureEvent(const MSG &, const GESTUREINFO &gi)
3766{
3767 const QPoint widgetPos = QPoint(gi.ptsLocation.x, gi.ptsLocation.y);
3768 QWidget *alienWidget = !internalWinId() ? this : childAt(widgetPos);
3769 if (alienWidget && alienWidget->internalWinId())
3770 alienWidget = 0;
3771 QWidget *widget = alienWidget ? alienWidget : this;
3772
3773 QNativeGestureEvent event;
3774 event.sequenceId = gi.dwSequenceID;
3775 event.position = QPoint(gi.ptsLocation.x, gi.ptsLocation.y);
3776 event.argument = gi.ullArguments;
3777
3778 switch (gi.dwID) {
3779 case GID_BEGIN:
3780 event.gestureType = QNativeGestureEvent::GestureBegin;
3781 break;
3782 case GID_END:
3783 event.gestureType = QNativeGestureEvent::GestureEnd;
3784 break;
3785 case GID_ZOOM:
3786 event.gestureType = QNativeGestureEvent::Zoom;
3787 break;
3788 case GID_PAN:
3789 event.gestureType = QNativeGestureEvent::Pan;
3790 break;
3791 case GID_ROTATE:
3792 event.gestureType = QNativeGestureEvent::Rotate;
3793 break;
3794 case GID_TWOFINGERTAP:
3795 case GID_ROLLOVER:
3796 default:
3797 break;
3798 }
3799 if (event.gestureType != QNativeGestureEvent::None)
3800 qt_sendSpontaneousEvent(widget, &event);
3801 return true;
3802}
3803
3804
3805void QApplication::setCursorFlashTime(int msecs)
3806{
3807 SetCaretBlinkTime(msecs / 2);
3808 QApplicationPrivate::cursor_flash_time = msecs;
3809}
3810
3811
3812int QApplication::cursorFlashTime()
3813{
3814 int blink = (int)GetCaretBlinkTime();
3815 if (!blink)
3816 return QApplicationPrivate::cursor_flash_time;
3817 if (blink > 0)
3818 return 2*blink;
3819 return 0;
3820}
3821
3822
3823void QApplication::setDoubleClickInterval(int ms)
3824{
3825#ifndef Q_WS_WINCE
3826 SetDoubleClickTime(ms);
3827#endif
3828 QApplicationPrivate::mouse_double_click_time = ms;
3829}
3830
3831int QApplication::doubleClickInterval()
3832{
3833 int ms = GetDoubleClickTime();
3834 if (ms != 0)
3835 return ms;
3836 return QApplicationPrivate::mouse_double_click_time;
3837}
3838
3839
3840void QApplication::setKeyboardInputInterval(int ms)
3841{
3842 QApplicationPrivate::keyboard_input_time = ms;
3843}
3844
3845int QApplication::keyboardInputInterval()
3846{
3847 // FIXME: get from the system
3848 return QApplicationPrivate::keyboard_input_time;
3849}
3850
3851#ifndef QT_NO_WHEELEVENT
3852void QApplication::setWheelScrollLines(int n)
3853{
3854#ifdef SPI_SETWHEELSCROLLLINES
3855 if (n < 0)
3856 n = 0;
3857 SystemParametersInfo(SPI_SETWHEELSCROLLLINES, (uint)n, 0, 0);
3858#else
3859 QApplicationPrivate::wheel_scroll_lines = n;
3860#endif
3861}
3862
3863int QApplication::wheelScrollLines()
3864{
3865#ifdef SPI_GETWHEELSCROLLLINES
3866 uint i = 3;
3867 SystemParametersInfo(SPI_GETWHEELSCROLLLINES, sizeof(uint), &i, 0);
3868 if (i > INT_MAX)
3869 i = INT_MAX;
3870 return i;
3871#else
3872 return QApplicationPrivate::wheel_scroll_lines;
3873#endif
3874}
3875#endif //QT_NO_WHEELEVENT
3876
3877static bool effect_override = false;
3878
3879void QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable)
3880{
3881 effect_override = true;
3882 switch (effect) {
3883 case Qt::UI_AnimateMenu:
3884 QApplicationPrivate::animate_menu = enable;
3885 break;
3886 case Qt::UI_FadeMenu:
3887 QApplicationPrivate::fade_menu = enable;
3888 break;
3889 case Qt::UI_AnimateCombo:
3890 QApplicationPrivate::animate_combo = enable;
3891 break;
3892 case Qt::UI_AnimateTooltip:
3893 QApplicationPrivate::animate_tooltip = enable;
3894 break;
3895 case Qt::UI_FadeTooltip:
3896 QApplicationPrivate::fade_tooltip = enable;
3897 break;
3898 case Qt::UI_AnimateToolBox:
3899 QApplicationPrivate::animate_toolbox = enable;
3900 break;
3901 default:
3902 QApplicationPrivate::animate_ui = enable;
3903 break;
3904 }
3905}
3906
3907bool QApplication::isEffectEnabled(Qt::UIEffect effect)
3908{
3909 if (QColormap::instance().depth() < 16)
3910 return false;
3911
3912 if (!effect_override && desktopSettingsAware()) {
3913 // we know that they can be used when we are here
3914 BOOL enabled = false;
3915 UINT api;
3916 switch (effect) {
3917 case Qt::UI_AnimateMenu:
3918 api = SPI_GETMENUANIMATION;
3919 break;
3920 case Qt::UI_FadeMenu:
3921 api = SPI_GETMENUFADE;
3922 break;
3923 case Qt::UI_AnimateCombo:
3924 api = SPI_GETCOMBOBOXANIMATION;
3925 break;
3926 case Qt::UI_AnimateTooltip:
3927 api = SPI_GETTOOLTIPANIMATION;
3928 break;
3929 case Qt::UI_FadeTooltip:
3930 api = SPI_GETTOOLTIPFADE;
3931 break;
3932 default:
3933 api = SPI_GETUIEFFECTS;
3934 break;
3935 }
3936 SystemParametersInfo(api, 0, &enabled, 0);
3937 return enabled;
3938 }
3939
3940 switch(effect) {
3941 case Qt::UI_AnimateMenu:
3942 return QApplicationPrivate::animate_menu;
3943 case Qt::UI_FadeMenu:
3944 return QApplicationPrivate::fade_menu;
3945 case Qt::UI_AnimateCombo:
3946 return QApplicationPrivate::animate_combo;
3947 case Qt::UI_AnimateTooltip:
3948 return QApplicationPrivate::animate_tooltip;
3949 case Qt::UI_FadeTooltip:
3950 return QApplicationPrivate::fade_tooltip;
3951 case Qt::UI_AnimateToolBox:
3952 return QApplicationPrivate::animate_toolbox;
3953 default:
3954 return QApplicationPrivate::animate_ui;
3955 }
3956}
3957
3958#ifndef QT_NO_SESSIONMANAGER
3959
3960bool QSessionManager::allowsInteraction()
3961{
3962 sm_blockUserInput = false;
3963 return true;
3964}
3965
3966bool QSessionManager::allowsErrorInteraction()
3967{
3968 sm_blockUserInput = false;
3969 return true;
3970}
3971
3972void QSessionManager::release()
3973{
3974 if (sm_smActive)
3975 sm_blockUserInput = true;
3976}
3977
3978void QSessionManager::cancel()
3979{
3980 sm_cancel = true;
3981}
3982
3983#endif //QT_NO_SESSIONMANAGER
3984
3985
3986PtrRegisterTouchWindow QApplicationPrivate::RegisterTouchWindow = 0;
3987PtrGetTouchInputInfo QApplicationPrivate::GetTouchInputInfo = 0;
3988PtrCloseTouchInputHandle QApplicationPrivate::CloseTouchInputHandle = 0;
3989
3990void QApplicationPrivate::initializeMultitouch_sys()
3991{
3992 QLibrary library(QLatin1String("user32"));
3993 // MinGW (g++ 3.4.5) accepts only C casts.
3994 RegisterTouchWindow = (PtrRegisterTouchWindow)(library.resolve("RegisterTouchWindow"));
3995 GetTouchInputInfo = (PtrGetTouchInputInfo)(library.resolve("GetTouchInputInfo"));
3996 CloseTouchInputHandle = (PtrCloseTouchInputHandle)(library.resolve("CloseTouchInputHandle"));
3997
3998 touchInputIDToTouchPointID.clear();
3999}
4000
4001void QApplicationPrivate::cleanupMultitouch_sys()
4002{
4003 touchInputIDToTouchPointID.clear();
4004}
4005
4006bool QApplicationPrivate::translateTouchEvent(const MSG &msg)
4007{
4008 QWidget *widgetForHwnd = QWidget::find(msg.hwnd);
4009 if (!widgetForHwnd)
4010 return false;
4011
4012 QRect screenGeometry = QApplication::desktop()->screenGeometry(widgetForHwnd);
4013
4014 QList<QTouchEvent::TouchPoint> touchPoints;
4015
4016 QVector<TOUCHINPUT> winTouchInputs(msg.wParam);
4017 memset(winTouchInputs.data(), 0, sizeof(TOUCHINPUT) * winTouchInputs.count());
4018 Qt::TouchPointStates allStates = 0;
4019 QApplicationPrivate::GetTouchInputInfo((HANDLE) msg.lParam, msg.wParam, winTouchInputs.data(), sizeof(TOUCHINPUT));
4020 for (int i = 0; i < winTouchInputs.count(); ++i) {
4021 const TOUCHINPUT &touchInput = winTouchInputs.at(i);
4022
4023 int touchPointID = touchInputIDToTouchPointID.value(touchInput.dwID, -1);
4024 if (touchPointID == -1) {
4025 touchPointID = touchInputIDToTouchPointID.count();
4026 touchInputIDToTouchPointID.insert(touchInput.dwID, touchPointID);
4027 }
4028
4029 QTouchEvent::TouchPoint touchPoint(touchPointID);
4030
4031 // update state
4032 QPointF screenPos(qreal(touchInput.x) / qreal(100.), qreal(touchInput.y) / qreal(100.));
4033 QRectF screenRect;
4034 if (touchInput.dwMask & TOUCHINPUTMASKF_CONTACTAREA)
4035 screenRect.setSize(QSizeF(qreal(touchInput.cxContact) / qreal(100.),
4036 qreal(touchInput.cyContact) / qreal(100.)));
4037 screenRect.moveCenter(screenPos);
4038
4039 Qt::TouchPointStates state;
4040 if (touchInput.dwFlags & TOUCHEVENTF_DOWN) {
4041 state = Qt::TouchPointPressed;
4042 } else if (touchInput.dwFlags & TOUCHEVENTF_UP) {
4043 state = Qt::TouchPointReleased;
4044 } else {
4045 state = (screenPos == touchPoint.screenPos()
4046 ? Qt::TouchPointStationary
4047 : Qt::TouchPointMoved);
4048 }
4049 if (touchInput.dwFlags & TOUCHEVENTF_PRIMARY)
4050 state |= Qt::TouchPointPrimary;
4051 touchPoint.setState(state);
4052 touchPoint.setScreenRect(screenRect);
4053 touchPoint.setNormalizedPos(QPointF(screenPos.x() / screenGeometry.width(),
4054 screenPos.y() / screenGeometry.height()));
4055
4056 allStates |= state;
4057
4058 touchPoints.append(touchPoint);
4059 }
4060 QApplicationPrivate::CloseTouchInputHandle((HANDLE) msg.lParam);
4061
4062 if ((allStates & Qt::TouchPointStateMask) == Qt::TouchPointReleased) {
4063 // all touch points released, forget the ids we've seen, they may not be reused
4064 touchInputIDToTouchPointID.clear();
4065 }
4066
4067 translateRawTouchEvent(widgetForHwnd, QTouchEvent::TouchScreen, touchPoints);
4068 return true;
4069}
4070
4071QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.