source: branches/4.5.1/src/gui/kernel/qapplication_win.cpp

Last change on this file was 2, checked in by Dmitry A. Kuminov, 17 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

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