source: trunk/src/gui/kernel/qwidget_pm.cpp@ 603

Last change on this file since 603 was 603, checked in by Dmitry A. Kuminov, 15 years ago

gui: Fixed assertion at #1125 in qwidget.cpp (due to an attempt to re-instantiate QDesktopWidget during application termination).

File size: 94.0 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** Copyright (C) 2009 netlabs.org. OS/2 parts.
8**
9** This file is part of the QtGui module of the Qt Toolkit.
10**
11** $QT_BEGIN_LICENSE:LGPL$
12** Commercial Usage
13** Licensees holding valid Qt Commercial licenses may use this file in
14** accordance with the Qt Commercial License Agreement provided with the
15** Software or, alternatively, in accordance with the terms contained in
16** a written agreement between you and Nokia.
17**
18** GNU Lesser General Public License Usage
19** Alternatively, this file may be used under the terms of the GNU Lesser
20** General Public License version 2.1 as published by the Free Software
21** Foundation and appearing in the file LICENSE.LGPL included in the
22** packaging of this file. Please review the following information to
23** ensure the GNU Lesser General Public License version 2.1 requirements
24** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25**
26** In addition, as a special exception, Nokia gives you certain additional
27** rights. These rights are described in the Nokia Qt LGPL Exception
28** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29**
30** GNU General Public License Usage
31** Alternatively, this file may be used under the terms of the GNU
32** General Public License version 3.0 as published by the Free Software
33** Foundation and appearing in the file LICENSE.GPL included in the
34** packaging of this file. Please review the following information to
35** ensure the GNU General Public License version 3.0 requirements will be
36** met: http://www.gnu.org/copyleft/gpl.html.
37**
38** If you have questions regarding the use of this file, please contact
39** Nokia at [email protected].
40** $QT_END_LICENSE$
41**
42****************************************************************************/
43
44#include "qt_os2.h"
45
46#include "qdebug.h"
47
48#include "qwidget.h"
49#include "qwidget_p.h"
50
51#include "qapplication.h"
52#include "qdesktopwidget.h"
53#include "qevent.h"
54
55#include "private/qapplication_p.h"
56#include "private/qbackingstore_p.h"
57#include "private/qwindowsurface_raster_p.h"
58
59//#define QT_DEBUGWINCREATEDESTROY
60//#define QT_DEBUGWIDGETMASK
61
62QT_BEGIN_NAMESPACE
63
64static QWidget *mouseGrb = 0;
65static QCursor *mouseGrbCur = 0;
66static QWidget *keyboardGrb = 0;
67
68// defined in qapplication_pm.cpp
69extern bool qt_nograb();
70extern MRESULT EXPENTRY QtWndProc(HWND, ULONG, MPARAM, MPARAM);
71extern PFNWP QtOldFrameProc;
72extern MRESULT EXPENTRY QtFrameProc(HWND, ULONG, MPARAM, MPARAM);
73extern PFNWP QtOldFrameCtlProcs[FID_HORZSCROLL - FID_SYSMENU + 1];
74extern MRESULT EXPENTRY QtFrameCtlProc(HWND, ULONG, MPARAM, MPARAM);
75
76#if !defined(QT_NO_SESSIONMANAGER)
77bool qt_about_to_destroy_wnd = false;
78#endif
79
80typedef QSet<QString> WinClassNameHash;
81Q_GLOBAL_STATIC(WinClassNameHash, winclassNames)
82
83// register window class
84static const QString qt_reg_winclass(QWidget *w)
85{
86 int flags = w->windowFlags();
87 int type = flags & Qt::WindowType_Mask;
88
89 QString cname;
90 ULONG style = 0;
91
92 if (type == Qt::Popup || type == Qt::ToolTip) {
93 cname = QLatin1String("QPopup");
94 style |= CS_SAVEBITS;
95 } else if (w->isWindow()) {
96 // this class is for top level widgets which are client HWNDs of a
97 // WC_FRAME parent HWND internally maintaned for them
98 cname = QLatin1String("QWindow");
99 } else {
100 cname = QLatin1String("QWidget");
101 }
102
103 if (winclassNames()->contains(cname)) // already registered in our list
104 return cname;
105
106 // QT_EXTRAWINDATASIZE is defined in qwindowdefs_pm.h
107 WinRegisterClass(0, cname.toLatin1(), QtWndProc, style, QT_EXTRAWINDATASIZE);
108
109 winclassNames()->insert(cname);
110 return cname;
111
112 // Note: there is no need to unregister private window classes registered by
113 // this function -- it is done automatically upon process termination.
114}
115
116/*!
117 \internal
118
119 Extended version of WinQueryClipRegion(). If the given window has a clip
120 region, the given region will receive a copy of the clip region clipped to
121 the current window rectangle. If there is no clip region, the given region
122 will contain only the window rectangle on return.
123 */
124void qt_WinQueryClipRegionOrRect(HWND hwnd, HRGN hrgn)
125{
126 RECTL rcl;
127 WinQueryWindowRect(hwnd, &rcl);
128
129 HPS hps = qt_display_ps();
130 GpiSetRegion(hps, hrgn, 1, &rcl);
131 if (WinQueryClipRegion(hwnd, 0) != QCRGN_NO_CLIP_REGION) {
132 HRGN hrgnTemp = GpiCreateRegion(hps, 0, NULL);
133 WinQueryClipRegion(hwnd, hrgnTemp);
134 GpiCombineRegion(hps, hrgn, hrgnTemp, hrgn, CRGN_AND);
135 GpiDestroyRegion(hps, hrgnTemp);
136 }
137}
138
139/*!
140 \internal
141
142 Extended version of WinInvalidateRegion(): invalidates the specified region
143 of the given window and regions of children from \a hwndFrom to \a hwndTo
144 if they intersect with the invalid region. If either of child window
145 handles is NULLHANDLE, children are not invalidated at all. Also, HWND_TOP
146 can be used as \a hwndFrom, HWND_BOTTOM \a can be used as \a hwndTo.
147 */
148static BOOL qt_WinInvalidateRegionEx(HWND hwnd, HRGN hrgn,
149 HWND hwndFrom, HWND hwndTo)
150{
151#if defined(QT_DEBUGWIDGETMASK)
152 qDebug("qt_WinInvalidateRegionEx: hwnd=%s hwndFrom=%08lX hwndTo=%08lX",
153 qStrHWND(hwnd).toUtf8().constData(), hwndFrom, hwndTo);
154#endif
155
156 if (hwndFrom == HWND_TOP)
157 hwndFrom = WinQueryWindow(hwnd, QW_TOP);
158 if (hwndTo == HWND_BOTTOM)
159 hwndTo = WinQueryWindow(hwnd, QW_BOTTOM);
160
161 if (hwndFrom == 0 || hwndTo == 0)
162 return WinInvalidateRegion(hwnd, hrgn, FALSE);
163
164 if (WinQueryWindow(hwndFrom, QW_PARENT) != hwnd ||
165 WinQueryWindow(hwndTo, QW_PARENT) != hwnd)
166 return FALSE;
167
168 HPS hps = qt_display_ps();
169
170 SWP swp;
171 HWND child = hwndFrom;
172 HRGN hrgnChild = GpiCreateRegion(hps, 0, NULL);
173 HRGN hrgnInv = GpiCreateRegion(hps, 0, NULL);
174 GpiCombineRegion(hps, hrgnInv, hrgn, 0, CRGN_COPY);
175
176 LONG cmplx = RGN_RECT;
177
178 while (child) {
179 WinQueryWindowPos(child, &swp);
180#if defined(QT_DEBUGWIDGETMASK)
181 qDebug(" child=%s [fl=%08lX]", qStrHWND(child).toUtf8().constData(),
182 swp.fl);
183#endif
184 // proceed only if not hidden
185 if (swp.fl & SWP_SHOW) {
186 // get sibling's bounds (clip region or rect)
187 qt_WinQueryClipRegionOrRect(child, hrgnChild);
188 // translate the region to the parent's coordinate system
189 POINTL ptl = { swp.x, swp.y };
190 GpiOffsetRegion(hps, hrgnChild, &ptl);
191 // intersect the child's region with the invalid one
192 // and invalidate if not NULL
193 cmplx = GpiCombineRegion(hps, hrgnChild, hrgnChild, hrgnInv,
194 CRGN_AND);
195 if (cmplx != RGN_NULL) {
196 POINTL ptl2 = { -swp.x, -swp.y };
197 GpiOffsetRegion(hps, hrgnChild, &ptl2);
198 WinInvalidateRegion(child, hrgnChild, TRUE);
199 GpiOffsetRegion(hps, hrgnChild, &ptl);
200 // substract the invalidated area from the widget's region
201 // (no need to invalidate it any more)
202 cmplx = GpiCombineRegion(hps, hrgnInv, hrgnInv, hrgnChild,
203 CRGN_DIFF);
204#if defined(QT_DEBUGWIDGETMASK)
205 qDebug(" processed");
206#endif
207 // finish if nothing left
208 if (cmplx == RGN_NULL)
209 break;
210 }
211 }
212 // iterate to the next window (below)
213 if (child == hwndTo)
214 break;
215 child = WinQueryWindow(child, QW_NEXT);
216 }
217
218 BOOL ok = (cmplx == RGN_NULL) || (child == hwndTo);
219
220 if (ok) {
221 // invalidate what's left invalid after substracting children
222 WinInvalidateRegion(hwnd, hrgnInv, FALSE);
223 }
224
225 GpiDestroyRegion(hps, hrgnInv);
226 GpiDestroyRegion(hps, hrgnChild);
227
228 return ok;
229}
230
231/** \internal flags for qt_WinProcessWindowObstacles() */
232enum {
233 PWO_Children = 0x01,
234 PWO_Sibings = 0x02,
235 PWO_Ancestors = 0x04,
236 PWO_Screen = 0x08,
237 PWO_TopLevel = 0x80000000,
238 // PWO_Default is suitable in most cases (for simple paint operations)