source: trunk/src/gui/kernel/qwidget_win.cpp

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

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 74.1 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the QtGui module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qapplication.h"
43#include "qapplication_p.h"
44#include "qbitmap.h"
45#include "qcursor.h"
46#include "qdesktopwidget.h"
47#include "qevent.h"
48#include "qimage.h"
49#include "qlayout.h"
50#include "qpainter.h"
51#include "qstack.h"
52#include "qt_windows.h"
53#include "qwidget.h"
54#include "qwidget_p.h"
55#include "private/qbackingstore_p.h"
56#include "private/qwindowsurface_raster_p.h"
57
58#include "qscrollbar.h"
59#include "qabstractscrollarea.h"
60#include <private/qabstractscrollarea_p.h>
61
62#include <qdebug.h>
63
64#include <private/qapplication_p.h>
65#include <private/qwininputcontext_p.h>
66#include <private/qpaintengine_raster_p.h>
67#include <private/qsystemlibrary_p.h>
68
69#if defined(Q_WS_WINCE)
70#include "qguifunctions_wince.h"
71QT_USE_NAMESPACE
72extern void qt_wince_maximize(QWidget *widget); //defined in qguifunctions_wince.cpp
73extern void qt_wince_unmaximize(QWidget *widget); //defined in qguifunctions_wince.cpp
74extern void qt_wince_minimize(HWND hwnd); //defined in qguifunctions_wince.cpp
75extern void qt_wince_full_screen(HWND hwnd, bool fullScreen, UINT swpf); //defined in qguifunctions_wince.cpp
76extern bool qt_wince_is_mobile(); //defined in qguifunctions_wince.cpp
77#endif
78
79typedef BOOL (WINAPI *PtrSetLayeredWindowAttributes)(HWND hwnd, COLORREF crKey, BYTE bAlpha, DWORD dwFlags);
80static PtrSetLayeredWindowAttributes ptrSetLayeredWindowAttributes = 0;
81
82#ifndef QT_NO_DIRECTDRAW
83#include <ddraw.h>
84#include <private/qimage_p.h>
85static IDirectDraw *qt_ddraw_object;
86static IDirectDrawSurface *qt_ddraw_primary;
87#endif
88
89
90
91#if defined(QT_NON_COMMERCIAL)
92#include "qnc_win.h"
93#endif
94
95#if !defined(WS_EX_TOOLWINDOW)
96#define WS_EX_TOOLWINDOW 0x00000080
97#endif
98
99#if !defined(GWLP_WNDPROC)
100#define GWLP_WNDPROC GWL_WNDPROC
101#endif
102
103//#define TABLET_DEBUG
104#define PACKETDATA (PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE \
105 | PK_ORIENTATION | PK_CURSOR | PK_Z)
106#define PACKETMODE 0
107#include <wintab.h>
108#include <pktdef.h>
109
110QT_BEGIN_NAMESPACE
111
112typedef HCTX (API *PtrWTOpen)(HWND, LPLOGCONTEXT, BOOL);
113typedef BOOL (API *PtrWTClose)(HCTX);
114typedef UINT (API *PtrWTInfo)(UINT, UINT, LPVOID);
115typedef BOOL (API *PtrWTEnable)(HCTX, BOOL);
116typedef BOOL (API *PtrWTOverlap)(HCTX, BOOL);
117typedef int (API *PtrWTPacketsGet)(HCTX, int, LPVOID);
118typedef BOOL (API *PtrWTGet)(HCTX, LPLOGCONTEXT);
119typedef int (API *PtrWTQueueSizeGet)(HCTX);
120typedef BOOL (API *PtrWTQueueSizeSet)(HCTX, int);
121
122static PtrWTOpen ptrWTOpen = 0;
123static PtrWTClose ptrWTClose = 0;
124static PtrWTInfo ptrWTInfo = 0;
125static PtrWTQueueSizeGet ptrWTQueueSizeGet = 0;
126static PtrWTQueueSizeSet ptrWTQueueSizeSet = 0;
127#ifndef QT_NO_TABLETEVENT
128static void init_wintab_functions();
129static void qt_tablet_init();
130static void qt_tablet_cleanup();
131#endif // QT_NO_TABLETEVENT
132extern HCTX qt_tablet_context;
133extern bool qt_tablet_tilt_support;
134
135static QWidget *qt_tablet_widget = 0;
136QWidget* qt_get_tablet_widget()
137{
138 return qt_tablet_widget;
139}
140
141extern bool qt_is_gui_used;
142
143#ifndef QT_NO_TABLETEVENT
144static void init_wintab_functions()
145{
146#if defined(Q_OS_WINCE)
147 return;
148#else
149 if (!qt_is_gui_used)
150 return;
151 QSystemLibrary library(QLatin1String("wintab32"));
152 ptrWTOpen = (PtrWTOpen)library.resolve("WTOpenW");
153 ptrWTInfo = (PtrWTInfo)library.resolve("WTInfoW");
154 ptrWTClose = (PtrWTClose)library.resolve("WTClose");
155 ptrWTQueueSizeGet = (PtrWTQueueSizeGet)library.resolve("WTQueueSizeGet");
156 ptrWTQueueSizeSet = (PtrWTQueueSizeSet)library.resolve("WTQueueSizeSet");
157#endif // Q_OS_WINCE
158}
159
160static void qt_tablet_init()
161{
162 static bool firstTime = true;
163 if (!firstTime)
164 return;
165 firstTime = false;
166 qt_tablet_widget = new QWidget(0);
167 qt_tablet_widget->createWinId();
168 qt_tablet_widget->setObjectName(QLatin1String("Qt internal tablet widget"));
169 // We don't need this internal widget to appear in QApplication::topLevelWidgets()
170 if (QWidgetPrivate::allWidgets)
171 QWidgetPrivate::allWidgets->remove(qt_tablet_widget);
172 LOGCONTEXT lcMine;
173 qAddPostRoutine(qt_tablet_cleanup);
174 struct tagAXIS tpOri[3];
175 init_wintab_functions();
176 if (ptrWTInfo && ptrWTOpen && ptrWTQueueSizeGet && ptrWTQueueSizeSet) {
177 // make sure we have WinTab
178 if (!ptrWTInfo(0, 0, NULL)) {
179#ifdef TABLET_DEBUG
180 qWarning("QWidget: Wintab services not available");
181#endif
182 return;
183 }
184
185 // some tablets don't support tilt, check if it is possible,
186 qt_tablet_tilt_support = ptrWTInfo(WTI_DEVICES, DVC_ORIENTATION, &tpOri);
187 if (qt_tablet_tilt_support) {
188 // check for azimuth and altitude
189 qt_tablet_tilt_support = tpOri[0].axResolution && tpOri[1].axResolution;
190 }
191 // build our context from the default context
192 ptrWTInfo(WTI_DEFSYSCTX, 0, &lcMine);
193 // Go for the raw coordinates, the tablet event will return good stuff
194 lcMine.lcOptions |= CXO_MESSAGES | CXO_CSRMESSAGES;
195 lcMine.lcPktData = PACKETDATA;
196 lcMine.lcPktMode = PACKETMODE;
197 lcMine.lcMoveMask = PACKETDATA;
198 lcMine.lcOutOrgX = 0;
199 lcMine.lcOutExtX = lcMine.lcInExtX;
200 lcMine.lcOutOrgY = 0;
201 lcMine.lcOutExtY = -lcMine.lcInExtY;
202 qt_tablet_context = ptrWTOpen(qt_tablet_widget->winId(), &lcMine, true);
203#ifdef TABLET_DEBUG
204 qDebug("Tablet is %p", qt_tablet_context);
205#endif
206 if (!qt_tablet_context) {
207#ifdef TABLET_DEBUG
208 qWarning("QWidget: Failed to open the tablet");
209#endif
210 return;
211 }
212 // Set the size of the Packet Queue to the correct size...
213 int currSize = ptrWTQueueSizeGet(qt_tablet_context);
214 if (!ptrWTQueueSizeSet(qt_tablet_context, QT_TABLET_NPACKETQSIZE)) {
215 // Ideally one might want to use a smaller
216 // multiple, but for now, since we managed to destroy
217 // the existing Q with the previous call, set it back
218 // to the other size, which should work. If not,
219 // there will be trouble.
220 if (!ptrWTQueueSizeSet(qt_tablet_context, currSize)) {
221 Q_ASSERT_X(0, "Qt::Internal", "There is no packet queue for"
222 " the tablet. The tablet will not work");
223 }
224 }
225 }
226}
227
228static void qt_tablet_cleanup()
229{
230 if (ptrWTClose)
231 ptrWTClose(qt_tablet_context);
232 delete qt_tablet_widget;
233 qt_tablet_widget = 0;
234}
235#endif // QT_NO_TABLETEVENT
236
237const QString qt_reg_winclass(QWidget *w); // defined in qapplication_win.cpp
238
239#ifndef QT_NO_DRAGANDDROP
240void qt_olednd_unregister(QWidget* widget, QOleDropTarget *dst); // dnd_win
241QOleDropTarget* qt_olednd_register(QWidget* widget);
242#endif
243
244extern bool qt_nograb();
245extern HRGN qt_win_bitmapToRegion(const QBitmap& bitmap);
246
247static QWidget *mouseGrb = 0;
248static QCursor *mouseGrbCur = 0;
249static QWidget *keyboardGrb = 0;
250static HHOOK journalRec = 0;
251
252extern "C" LRESULT QT_WIN_CALLBACK QtWndProc(HWND, UINT, WPARAM, LPARAM);
253
254#define XCOORD_MAX 16383
255#define WRECT_MAX 16383
256
257/*****************************************************************************
258 QWidget member functions
259 *****************************************************************************/
260
261#ifndef Q_WS_WINCE
262void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyOldWindow)
263{
264 Q_Q(QWidget);
265 static int sw = -1, sh = -1;
266
267 Qt::WindowType type = q->windowType();
268 Qt::WindowFlags flags = data.window_flags;
269
270 bool topLevel = (flags & Qt::Window);
271 bool popup = (type == Qt::Popup);
272 bool dialog = (type == Qt::Dialog
273 || type == Qt::Sheet
274 || (flags & Qt::MSWindowsFixedSizeDialogHint));
275 bool desktop = (type == Qt::Desktop);
276 bool tool = (type == Qt::Tool || type == Qt::Drawer);
277
278 HINSTANCE appinst = qWinAppInst();
279 HWND parentw, destroyw = 0;
280 WId id = 0;
281
282 QString windowClassName = qt_reg_winclass(q);
283
284 if (!window) // always initialize
285 initializeWindow = true;
286
287 if (popup)
288 flags |= Qt::WindowStaysOnTopHint; // a popup stays on top
289
290 if (sw < 0) { // get the (primary) screen size
291 sw = GetSystemMetrics(SM_CXSCREEN);
292 sh = GetSystemMetrics(SM_CYSCREEN);
293 }
294
295 if (desktop && !q->testAttribute(Qt::WA_DontShowOnScreen)) { // desktop widget
296 popup = false; // force this flags off
297 data.crect.setRect(GetSystemMetrics(76 /* SM_XVIRTUALSCREEN */), GetSystemMetrics(77 /* SM_YVIRTUALSCREEN */),
298 GetSystemMetrics(78 /* SM_CXVIRTUALSCREEN */), GetSystemMetrics(79 /* SM_CYVIRTUALSCREEN */));
299 }
300
301 parentw = q->parentWidget() ? q->parentWidget()->effectiveWinId() : 0;
302
303 QString title;
304 int style = WS_CHILD;
305 int exsty = 0;
306
307 if (window) {
308 style = GetWindowLong(window, GWL_STYLE);
309 if (!style)
310 qErrnoWarning("QWidget::create: GetWindowLong failed");
311 topLevel = false; // #### needed for some IE plugins??
312 } else if (popup || (type == Qt::ToolTip) || (type == Qt::SplashScreen)) {
313 style = WS_POPUP;
314 } else if (topLevel && !desktop) {
315 if (flags & Qt::FramelessWindowHint)
316 style = WS_POPUP; // no border
317 else if (flags & Qt::WindowTitleHint)
318 style = WS_OVERLAPPED;
319 else
320 style = 0;
321 }
322 if (!desktop) {
323 // if (!testAttribute(Qt::WA_PaintUnclipped))
324 // ### Commented out for now as it causes some problems, but
325 // this should be correct anyway, so dig some more into this
326#ifndef Q_FLATTEN_EXPOSE
327 style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN ;
328#endif
329 if (topLevel) {
330 if ((type == Qt::Window || dialog || tool)) {
331 if (!(flags & Qt::FramelessWindowHint)) {
332 if (!(flags & Qt::MSWindowsFixedSizeDialogHint)) {
333 style |= WS_THICKFRAME;
334 if(!(flags &
335 ( Qt::WindowSystemMenuHint
336 | Qt::WindowTitleHint
337 | Qt::WindowMinMaxButtonsHint
338 | Qt::WindowCloseButtonHint
339 | Qt::WindowContextHelpButtonHint)))
340 style |= WS_POPUP;
341 } else {
342 style |= WS_POPUP | WS_DLGFRAME;
343 }
344 }
345 if (flags & Qt::WindowTitleHint)
346 style |= WS_CAPTION;
347 if (flags & Qt::WindowSystemMenuHint)
348 style |= WS_SYSMENU;
349 if (flags & Qt::WindowMinimizeButtonHint)
350 style |= WS_MINIMIZEBOX;
351 if (shouldShowMaximizeButton())
352 style |= WS_MAXIMIZEBOX;
353 if (tool)
354 exsty |= WS_EX_TOOLWINDOW;
355 if (flags & Qt::WindowContextHelpButtonHint)
356 exsty |= WS_EX_CONTEXTHELP;
357 } else {
358 exsty |= WS_EX_TOOLWINDOW;
359 }
360 }
361 }
362
363 if (flags & Qt::WindowTitleHint) {
364 title = q->isWindow() ? qAppName() : q->objectName();
365 }
366
367 // The Qt::WA_WState_Created flag is checked by translateConfigEvent() in
368 // qapplication_win.cpp. We switch it off temporarily to avoid move
369 // and resize events during creationt
370 q->setAttribute(Qt::WA_WState_Created, false);
371
372 if (window) { // override the old window
373 if (destroyOldWindow)
374 destroyw = data.winid;
375 id = window;
376 setWinId(window);
377 LONG res = SetWindowLong(window, GWL_STYLE, style);
378 if (!res)
379 qErrnoWarning("QWidget::create: Failed to set window style");
380#ifdef _WIN64
381 res = SetWindowLongPtr( window, GWLP_WNDPROC, (LONG_PTR)QtWndProc );
382#else
383 res = SetWindowLong( window, GWL_WNDPROC, (LONG)QtWndProc );
384#endif
385 if (!res)
386 qErrnoWarning("QWidget::create: Failed to set window procedure");
387 } else if (desktop) { // desktop widget
388 id = GetDesktopWindow();
389// QWidget *otherDesktop = QWidget::find(id); // is there another desktop?
390// if (otherDesktop && otherDesktop->testWFlags(Qt::WPaintDesktop)) {
391// otherDesktop->d_func()->setWinId(0); // remove id from widget mapper
392// d->setWinId(id); // make sure otherDesktop is
393// otherDesktop->d_func()->setWinId(id); // found first
394// } else {
395 setWinId(id);
396// }
397 } else if (topLevel) { // create top-level widget
398 if (popup)
399 parentw = 0;
400
401 const bool wasMoved = q->testAttribute(Qt::WA_Moved);
402 int x = wasMoved ? data.crect.left() : CW_USEDEFAULT;
403 int y = wasMoved ? data.crect.top() : CW_USEDEFAULT;
404 int w = CW_USEDEFAULT;
405 int h = CW_USEDEFAULT;
406
407 // Adjust for framestrut when needed
408 RECT rect = {0,0,0,0};
409 bool isVisibleOnScreen = !q->testAttribute(Qt::WA_DontShowOnScreen);
410 if (isVisibleOnScreen && AdjustWindowRectEx(&rect, style & ~WS_OVERLAPPED, FALSE, exsty)) {
411 QTLWExtra *td = maybeTopData();
412 if (wasMoved && (td && !td->posFromMove)) {
413 x = data.crect.x() + rect.left;
414 y = data.crect.y() + rect.top;
415 }
416
417 if (q->testAttribute(Qt::WA_Resized)) {
418 w = data.crect.width() + (rect.right - rect.left);
419 h = data.crect.height() + (rect.bottom - rect.top);
420 }
421 }
422 //update position & initial size of POPUP window
423 if (isVisibleOnScreen && topLevel && initializeWindow && (style & WS_POPUP)) {
424 if (!q->testAttribute(Qt::WA_Resized)) {
425 w = sw/2;
426 h = 4*sh/10;
427 }
428 if (!wasMoved) {
429 x = sw/2 - w/2;
430 y = sh/2 - h/2;
431 }
432 }
433
434 id = CreateWindowEx(exsty, reinterpret_cast<const wchar_t *>(windowClassName.utf16()),
435 reinterpret_cast<const wchar_t *>(title.utf16()), style,
436 x, y, w, h,
437 parentw, NULL, appinst, NULL);
438 if (!id)
439 qErrnoWarning("QWidget::create: Failed to create window");
440 setWinId(id);
441 if ((flags & Qt::WindowStaysOnTopHint) || (type == Qt::ToolTip)) {
442 SetWindowPos(id, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
443 if (flags & Qt::WindowStaysOnBottomHint)
444 qWarning() << "QWidget: Incompatible window flags: the window can't be on top and on bottom at the same time";
445 } else if (flags & Qt::WindowStaysOnBottomHint)
446 SetWindowPos(id, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
447 winUpdateIsOpaque();
448 } else if (q->testAttribute(Qt::WA_NativeWindow) || paintOnScreen()) { // create child widget
449 id = CreateWindowEx(exsty, reinterpret_cast<const wchar_t *>(windowClassName.utf16()),
450 reinterpret_cast<const wchar_t *>(title.utf16()), style,
451 data.crect.left(), data.crect.top(), data.crect.width(), data.crect.height(),
452 parentw, NULL, appinst, NULL);
453 if (!id)
454 qErrnoWarning("QWidget::create: Failed to create window");
455 SetWindowPos(id, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
456 setWinId(id);
457 }
458
459 if (desktop) {
460 q->setAttribute(Qt::WA_WState_Visible);
461 } else if (topLevel && !q->testAttribute(Qt::WA_DontShowOnScreen)) {
462 RECT cr;
463 GetClientRect(id, &cr);
464 // one cannot trust cr.left and cr.top, use a correction POINT instead
465 POINT pt;
466 pt.x = 0;
467 pt.y = 0;
468 ClientToScreen(id, &pt);
469
470 if (data.crect.width() == 0 || data.crect.height() == 0) {
471 data.crect = QRect(pt.x, pt.y, data.crect.width(), data.crect.height());
472 } else {
473 data.crect = QRect(QPoint(pt.x, pt.y),
474 QPoint(pt.x + cr.right - 1, pt.y + cr.bottom - 1));
475 }
476
477 if (data.fstrut_dirty) {
478 // be nice to activeqt
479 updateFrameStrut();
480 }
481 }
482
483 if (topLevel) {
484 if (data.window_flags & Qt::CustomizeWindowHint
485 && data.window_flags & Qt::WindowTitleHint) {
486 HMENU systemMenu = GetSystemMenu((HWND)q->internalWinId(), FALSE);
487 if (data.window_flags & Qt::WindowCloseButtonHint)
488 EnableMenuItem(systemMenu, SC_CLOSE, MF_BYCOMMAND|MF_ENABLED);
489 else
490 EnableMenuItem(systemMenu, SC_CLOSE, MF_BYCOMMAND|MF_GRAYED);
491 }
492 }
493
494 q->setAttribute(Qt::WA_WState_Created); // accept move/resize events
495 hd = 0; // no display context
496
497 if (q->testAttribute(Qt::WA_AcceptTouchEvents))
498 registerTouchWindow();
499
500 if (window) { // got window from outside
501 if (IsWindowVisible(window))
502 q->setAttribute(Qt::WA_WState_Visible);
503 else
504 q->setAttribute(Qt::WA_WState_Visible, false);
505 }
506
507 if (extra && !extra->mask.isEmpty())
508 setMask_sys(extra->mask);
509
510#if defined(QT_NON_COMMERCIAL)
511 QT_NC_WIDGET_CREATE
512#endif
513
514 if (q->hasFocus() && q->testAttribute(Qt::WA_InputMethodEnabled))
515 q->inputContext()->setFocusWidget(q);
516
517 if (destroyw) {
518 DestroyWindow(destroyw);
519 }
520
521#ifndef QT_NO_TABLETEVENT
522 if (q != qt_tablet_widget && QWidgetPrivate::mapper)
523 qt_tablet_init();
524#endif // QT_NO_TABLETEVENT
525
526 if (q->testAttribute(Qt::WA_DropSiteRegistered))
527 registerDropSite(true);
528
529 if (maybeTopData() && maybeTopData()->opacity != 255)
530 q->setWindowOpacity(maybeTopData()->opacity/255.);
531
532 if (topLevel && (data.crect.width() == 0 || data.crect.height() == 0)) {
533 q->setAttribute(Qt::WA_OutsideWSRange, true);
534 }
535
536 if (!topLevel && q->testAttribute(Qt::WA_NativeWindow) && q->testAttribute(Qt::WA_Mapped)) {
537 Q_ASSERT(q->internalWinId());
538 ShowWindow(q->internalWinId(), SW_SHOW);
539 }
540}
541
542#endif //Q_WS_WINCE
543
544
545void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
546{
547 Q_D(QWidget);
548 d->aboutToDestroy();
549 if (!isWindow() && parentWidget())
550 parentWidget()->d_func()->invalidateBuffer(d->effectiveRectFor(geometry()));
551 d->deactivateWidgetCleanup();
552 if (testAttribute(Qt::WA_WState_Created)) {
553 setAttribute(Qt::WA_WState_Created, false);
554 for(int i = 0; i < d->children.size(); ++i) { // destroy all widget children
555 register QObject *obj = d->children.at(i);
556 if (obj->isWidgetType())
557 ((QWidget*)obj)->destroy(destroySubWindows,
558 destroySubWindows);
559 }
560 if (mouseGrb == this)
561 releaseMouse();
562 if (keyboardGrb == this)
563 releaseKeyboard();
564 if (testAttribute(Qt::WA_ShowModal)) // just be sure we leave modal
565 QApplicationPrivate::leaveModal(this);
566 else if ((windowType() == Qt::Popup))
567 qApp->d_func()->closePopup(this);
568 if (destroyWindow && !(windowType() == Qt::Desktop) && internalWinId()) {
569 DestroyWindow(internalWinId());
570 }
571#ifdef Q_WS_WINCE
572 if (destroyWindow && (windowType() == Qt::Desktop) && !GetDesktopWindow()) {
573 DestroyWindow(internalWinId());
574 }
575
576#endif
577 QT_TRY {
578 d->setWinId(0);
579 } QT_CATCH (const std::bad_alloc &) {
580 // swallow - destructors must not throw
581 }
582 }
583}
584
585void QWidgetPrivate::reparentChildren()
586{
587 Q_Q(QWidget);
588 QObjectList chlist = q->children();
589 for(int i = 0; i < chlist.size(); ++i) { // reparent children
590 QObject *obj = chlist.at(i);
591 if (obj->isWidgetType()) {
592 QWidget *w = (QWidget *)obj;
593 if ((w->windowType() == Qt::Popup)) {
594 ;
595 } else if (w->isWindow()) {
596 bool showIt = w->isVisible();
597 QPoint old_pos = w->pos();
598 w->setParent(q, w->windowFlags());
599 w->move(old_pos);
600 if (showIt)
601 w->show();
602 } else {
603 w->d_func()->invalidateBuffer(w->rect());
604 SetParent(w->effectiveWinId(), q->effectiveWinId());
605 w->d_func()->reparentChildren();
606 }
607 }
608 }
609}
610
611void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f)
612{
613 Q_Q(QWidget);
614 bool wasCreated = q->testAttribute(Qt::WA_WState_Created);
615 if (q->isVisible() && q->parentWidget() && parent != q->parentWidget())
616 q->parentWidget()->d_func()->invalidateBuffer(effectiveRectFor(q->geometry()));
617
618 WId old_winid = data.winid;
619 // hide and reparent our own window away. Otherwise we might get
620 // destroyed when emitting the child remove event below. See QWorkspace.
621 if (q->isVisible() && data.winid) {
622 ShowWindow(data.winid, SW_HIDE);
623 SetParent(data.winid, 0);
624 }
625 bool dropSiteWasRegistered = false;
626 if (q->testAttribute(Qt::WA_DropSiteRegistered)) {
627 dropSiteWasRegistered = true;
628 q->setAttribute(Qt::WA_DropSiteRegistered, false); // ole dnd unregister (we will register again below)
629 }
630
631 if ((q->windowType() == Qt::Desktop))
632 old_winid = 0;
633 setWinId(0);
634
635 QObjectPrivate::setParent_helper(parent);
636 bool explicitlyHidden = q->testAttribute(Qt::WA_WState_Hidden) && q->testAttribute(Qt::WA_WState_ExplicitShowHide);
637
638 data.window_flags = f;
639 data.fstrut_dirty = true;
640 q->setAttribute(Qt::WA_WState_Created, false);
641 q->setAttribute(Qt::WA_WState_Visible, false);
642 q->setAttribute(Qt::WA_WState_Hidden, false);
643 adjustFlags(data.window_flags, q);
644 // keep compatibility with previous versions, we need to preserve the created state
645 // (but we recreate the winId for the widget being reparented, again for compatibility)
646 if (wasCreated || (!q->isWindow() && parent->testAttribute(Qt::WA_WState_Created)))
647 createWinId();
648 if (q->isWindow() || (!parent || parent->isVisible()) || explicitlyHidden)
649 q->setAttribute(Qt::WA_WState_Hidden);
650 q->setAttribute(Qt::WA_WState_ExplicitShowHide, explicitlyHidden);
651
652 if (wasCreated) {
653 reparentChildren();
654 }
655
656 if (extra && !extra->mask.isEmpty()) {
657 QRegion r = extra->mask;
658 extra->mask = QRegion();
659 q->setMask(r);
660 }
661 if (extra && extra->topextra && !extra->topextra->caption.isEmpty()) {
662 setWindowIcon_sys(true);
663 setWindowTitle_helper(extra->topextra->caption);
664 }
665 if (old_winid)
666 DestroyWindow(old_winid);
667
668 if (q->testAttribute(Qt::WA_AcceptDrops) || dropSiteWasRegistered
669 || (!q->isWindow() && q->parentWidget() && q->parentWidget()->testAttribute(Qt::WA_DropSiteRegistered)))
670 q->setAttribute(Qt::WA_DropSiteRegistered, true);
671
672#ifdef Q_WS_WINCE
673 // Show borderless toplevel windows in tasklist & NavBar
674 if (!parent) {
675 QString txt = q->windowTitle().isEmpty()?qAppName():q->windowTitle();
676 SetWindowText(q->internalWinId(), (wchar_t*)txt.utf16());
677 }
678#endif
679 invalidateBuffer(q->rect());
680}
681
682
683QPoint QWidget::mapToGlobal(const QPoint &pos) const
684{
685 Q_D(const QWidget);
686 QWidget *parentWindow = window();
687 QWExtra *extra = parentWindow->d_func()->extra;
688 if (!isVisible() || parentWindow->isMinimized() || !testAttribute(Qt::WA_WState_Created) || !internalWinId()
689 || (extra
690#ifndef QT_NO_GRAPHICSVIEW
691 && extra->proxyWidget
692#endif //QT_NO_GRAPHICSVIEW
693 )) {
694 if (extra && extra->topextra && extra->topextra->embedded) {
695 QPoint pt = mapTo(parentWindow, pos);
696 POINT p = {pt.x(), pt.y()};
697 ClientToScreen(parentWindow->effectiveWinId(), &p);
698 return QPoint(p.x, p.y);
699 } else {
700 QPoint toGlobal = mapTo(parentWindow, pos) + parentWindow->pos();
701 // Adjust for window decorations
702 toGlobal += parentWindow->geometry().topLeft() - parentWindow->frameGeometry().topLeft();
703 return toGlobal;
704 }
705 }
706 POINT p;
707 QPoint tmp = d->mapToWS(pos);
708 p.x = tmp.x();
709 p.y = tmp.y();
710 ClientToScreen(internalWinId(), &p);
711 return QPoint(p.x, p.y);
712}
713
714QPoint QWidget::mapFromGlobal(const QPoint &pos) const
715{
716 Q_D(const QWidget);
717 QWidget *parentWindow = window();
718 QWExtra *extra = parentWindow->d_func()->extra;
719 if (!isVisible() || parentWindow->isMinimized() || !testAttribute(Qt::WA_WState_Created) || !internalWinId()
720 || (extra
721#ifndef QT_NO_GRAPHICSVIEW
722 && extra->proxyWidget
723#endif //QT_NO_GRAPHICSVIEW
724 )) {
725 if (extra && extra->topextra && extra->topextra->embedded) {
726 POINT p = {pos.x(), pos.y()};
727 ScreenToClient(parentWindow->effectiveWinId(), &p);
728 return mapFrom(parentWindow, QPoint(p.x, p.y));
729 } else {
730 QPoint fromGlobal = mapFrom(parentWindow, pos - parentWindow->pos());
731 // Adjust for window decorations
732 fromGlobal -= parentWindow->geometry().topLeft() - parentWindow->frameGeometry().topLeft();
733 return fromGlobal;
734 }
735 }
736 POINT p;
737 p.x = pos.x();
738 p.y = pos.y();
739 ScreenToClient(internalWinId(), &p);
740 return d->mapFromWS(QPoint(p.x, p.y));
741}
742
743void QWidgetPrivate::updateSystemBackground() {}
744
745#ifndef QT_NO_CURSOR
746void QWidgetPrivate::setCursor_sys(const QCursor &cursor)
747{
748 Q_UNUSED(cursor);
749 Q_Q(QWidget);
750 qt_win_set_cursor(q, false);
751}
752
753void QWidgetPrivate::unsetCursor_sys()
754{
755 Q_Q(QWidget);
756 qt_win_set_cursor(q, false);
757}
758#endif
759
760void QWidgetPrivate::setWindowTitle_sys(const QString &caption)
761{
762 Q_Q(QWidget);
763 if (!q->isWindow())
764 return;
765
766 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
767 SetWindowText(q->internalWinId(), (wchar_t*)caption.utf16());
768}
769
770HICON qt_createIcon(QIcon icon, int xSize, int ySize, QPixmap **cache)
771{
772 HICON result = 0;
773 if (!icon.isNull()) { // valid icon
774 QSize size = icon.actualSize(QSize(xSize, ySize));
775 QPixmap pm = icon.pixmap(size);
776 if (pm.isNull())
777 return 0;
778
779 result = pm.toWinHICON();
780
781 if (cache) {
782 delete *cache;
783 *cache = new QPixmap(pm);;
784 }
785 }
786 return result;
787}
788
789void QWidgetPrivate::setWindowIcon_sys(bool forceReset)
790{
791 Q_Q(QWidget);
792 if (!q->testAttribute(Qt::WA_WState_Created) || !q->isWindow())
793 return;
794 QTLWExtra* x = topData();
795 if (x->iconPixmap && !forceReset)
796 // already been set
797 return;
798
799 if (x->winIconBig) {
800 DestroyIcon(x->winIconBig);
801 x->winIconBig = 0;
802 }
803 if (x->winIconSmall) {
804 DestroyIcon(x->winIconSmall);
805 x->winIconSmall = 0;
806 }
807
808 x->winIconSmall = qt_createIcon(q->windowIcon(),
809 GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON),
810 &(x->iconPixmap));
811 x->winIconBig = qt_createIcon(q->windowIcon(),
812 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON),
813 &(x->iconPixmap));
814 if (x->winIconBig) {
815 SendMessage(q->internalWinId(), WM_SETICON, 0 /* ICON_SMALL */, (LPARAM)x->winIconSmall);
816 SendMessage(q->internalWinId(), WM_SETICON, 1 /* ICON_BIG */, (LPARAM)x->winIconBig);
817 } else {
818 SendMessage(q->internalWinId(), WM_SETICON, 0 /* ICON_SMALL */, (LPARAM)x->winIconSmall);
819 SendMessage(q->internalWinId(), WM_SETICON, 1 /* ICON_BIG */, (LPARAM)x->winIconSmall);
820 }
821}
822
823
824void QWidgetPrivate::setWindowIconText_sys(const QString &iconText)
825{
826 Q_UNUSED(iconText);
827}
828
829
830QCursor *qt_grab_cursor()
831{
832 return mouseGrbCur;
833}
834
835// The procedure does nothing, but is required for mousegrabbing to work
836#ifndef Q_WS_WINCE
837LRESULT QT_WIN_CALLBACK qJournalRecordProc(int nCode, WPARAM wParam, LPARAM lParam)
838{
839 return CallNextHookEx(journalRec, nCode, wParam, lParam);
840}
841#endif //Q_WS_WINCE
842
843/* Works only as long as pointer is inside the application's window,
844 which is good enough for QDockWidget.
845
846 Doesn't call SetWindowsHookEx() - this function causes a system-wide
847 freeze if any other app on the system installs a hook and fails to
848 process events. */
849void QWidgetPrivate::grabMouseWhileInWindow()
850{
851 Q_Q(QWidget);
852 if (!qt_nograb()) {
853 if (mouseGrb)
854 mouseGrb->releaseMouse();
855 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
856 SetCapture(q->effectiveWinId());
857 mouseGrb = q;
858#ifndef QT_NO_CURSOR
859 mouseGrbCur = new QCursor(mouseGrb->cursor());
860#endif
861 }
862}
863
864#ifndef Q_WS_WINCE
865void QWidget::grabMouse()
866{
867 if (!qt_nograb()) {
868 if (mouseGrb)
869 mouseGrb->releaseMouse();
870 journalRec = SetWindowsHookEx(WH_JOURNALRECORD, (HOOKPROC)qJournalRecordProc, GetModuleHandle(0), 0);
871 Q_ASSERT(testAttribute(Qt::WA_WState_Created));
872 SetCapture(effectiveWinId());
873 mouseGrb = this;
874#ifndef QT_NO_CURSOR
875 mouseGrbCur = new QCursor(mouseGrb->cursor());
876#endif
877 }
878}
879
880#ifndef QT_NO_CURSOR
881void QWidget::grabMouse(const QCursor &cursor)
882{
883 if (!qt_nograb()) {
884 if (mouseGrb)
885 mouseGrb->releaseMouse();
886 journalRec = SetWindowsHookEx(WH_JOURNALRECORD, (HOOKPROC)qJournalRecordProc, GetModuleHandle(0), 0);
887 Q_ASSERT(testAttribute(Qt::WA_WState_Created));
888 SetCapture(effectiveWinId());
889 mouseGrbCur = new QCursor(cursor);
890 SetCursor(mouseGrbCur->handle());
891 mouseGrb = this;
892 }
893}
894#endif
895
896void QWidget::releaseMouse()
897{
898 if (!qt_nograb() && mouseGrb == this) {
899 ReleaseCapture();
900 if (journalRec) {
901 UnhookWindowsHookEx(journalRec);
902 journalRec = 0;
903 }
904 if (mouseGrbCur) {
905 delete mouseGrbCur;
906 mouseGrbCur = 0;
907 }
908 mouseGrb = 0;
909 }
910}
911#endif
912
913void QWidget::grabKeyboard()
914{
915 if (!qt_nograb()) {
916 if (keyboardGrb)
917 keyboardGrb->releaseKeyboard();
918 keyboardGrb = this;
919 }
920}
921
922void QWidget::releaseKeyboard()
923{
924 if (!qt_nograb() && keyboardGrb == this)
925 keyboardGrb = 0;
926}
927
928
929QWidget *QWidget::mouseGrabber()
930{
931 return mouseGrb;
932}
933
934QWidget *QWidget::keyboardGrabber()
935{
936 return keyboardGrb;
937}
938
939void QWidget::activateWindow()
940{
941 window()->createWinId();
942 SetForegroundWindow(window()->internalWinId());
943}
944
945#ifndef Q_WS_WINCE
946void QWidget::setWindowState(Qt::WindowStates newstate)
947{
948 Q_D(QWidget);
949 Qt::WindowStates oldstate = windowState();
950 if (oldstate == newstate)
951 return;
952
953 int max = SW_MAXIMIZE;
954 int min = SW_MINIMIZE;
955
956 int normal = SW_SHOWNOACTIVATE;
957 if (newstate & Qt::WindowActive) {
958 max = SW_SHOWMAXIMIZED;
959 min = SW_SHOWMINIMIZED;
960 normal = SW_SHOWNORMAL;
961 }
962
963 if (isWindow()) {
964 createWinId();
965 Q_ASSERT(testAttribute(Qt::WA_WState_Created));
966
967 // Ensure the initial size is valid, since we store it as normalGeometry below.
968 if (!testAttribute(Qt::WA_Resized) && !isVisible())
969 adjustSize();
970
971 if ((oldstate & Qt::WindowMaximized) != (newstate & Qt::WindowMaximized)) {
972 if (newstate & Qt::WindowMaximized && !(oldstate & Qt::WindowFullScreen))
973 d->topData()->normalGeometry = geometry();
974 if (isVisible() && !(newstate & Qt::WindowMinimized)) {
975 ShowWindow(internalWinId(), (newstate & Qt::WindowMaximized) ? max : normal);
976 if (!(newstate & Qt::WindowFullScreen)) {
977 QRect r = d->topData()->normalGeometry;
978 if (!(newstate & Qt::WindowMaximized) && r.width() >= 0) {
979 if (pos() != r.topLeft() || size() !=r.size()) {
980 d->topData()->normalGeometry = QRect(0,0,-1,-1);
981 setGeometry(r);
982 }
983 }
984 } else {
985 d->updateFrameStrut();
986 }
987 }
988 }
989
990 if ((oldstate & Qt::WindowFullScreen) != (newstate & Qt::WindowFullScreen)) {
991 if (newstate & Qt::WindowFullScreen) {
992 if (d->topData()->normalGeometry.width() < 0 && !(oldstate & Qt::WindowMaximized))
993 d->topData()->normalGeometry = geometry();
994 d->topData()->savedFlags = Qt::WindowFlags(GetWindowLong(internalWinId(), GWL_STYLE));
995#ifndef Q_FLATTEN_EXPOSE
996 UINT style = WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_POPUP;
997#else
998 UINT style = WS_POPUP;
999#endif
1000 if (ulong(d->topData()->savedFlags) & WS_SYSMENU)
1001 style |= WS_SYSMENU;
1002 if (isVisible())
1003 style |= WS_VISIBLE;
1004 SetWindowLong(internalWinId(), GWL_STYLE, style);
1005 QRect r = QApplication::desktop()->screenGeometry(this);
1006 UINT swpf = SWP_FRAMECHANGED;
1007 if (newstate & Qt::WindowActive)
1008 swpf |= SWP_NOACTIVATE;
1009
1010 SetWindowPos(internalWinId(), HWND_TOP, r.left(), r.top(), r.width(), r.height(), swpf);
1011 d->updateFrameStrut();
1012 } else {
1013 UINT style = d->topData()->savedFlags;
1014 if (isVisible())
1015 style |= WS_VISIBLE;
1016 SetWindowLong(internalWinId(), GWL_STYLE, style);
1017
1018 UINT swpf = SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE;
1019 if (newstate & Qt::WindowActive)
1020 swpf |= SWP_NOACTIVATE;
1021 SetWindowPos(internalWinId(), 0, 0, 0, 0, 0, swpf);
1022 d->updateFrameStrut();
1023
1024 // preserve maximized state
1025 if (isVisible())
1026 ShowWindow(internalWinId(), (newstate & Qt::WindowMaximized) ? max : normal);
1027
1028 if (!(newstate & Qt::WindowMaximized)) {
1029 QRect r = d->topData()->normalGeometry;
1030 d->topData()->normalGeometry = QRect(0,0,-1,-1);
1031 if (r.isValid())
1032 setGeometry(r);
1033 }
1034 }
1035 }
1036
1037 if ((oldstate & Qt::WindowMinimized) != (newstate & Qt::WindowMinimized)) {
1038 if (isVisible())
1039 ShowWindow(internalWinId(), (newstate & Qt::WindowMinimized) ? min :
1040 (newstate & Qt::WindowMaximized) ? max : normal);
1041 }
1042 }
1043 data->window_state = newstate;
1044 QWindowStateChangeEvent e(oldstate);
1045 QApplication::sendEvent(this, &e);
1046}
1047#endif //Q_WS_WINCE
1048
1049
1050/*
1051 \internal
1052 Platform-specific part of QWidget::hide().
1053*/
1054
1055void QWidgetPrivate::hide_sys()
1056{
1057 Q_Q(QWidget);
1058 deactivateWidgetCleanup();
1059 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
1060#ifdef Q_WS_WINCE
1061 if (!qt_wince_is_mobile() && q->isFullScreen()) {
1062 HWND handle = FindWindow(L"HHTaskBar", L"");
1063 if (handle) {
1064 ShowWindow(handle, 1);
1065 EnableWindow(handle, true);
1066 }
1067 }
1068#endif
1069 if (q->windowFlags() != Qt::Desktop) {
1070 if ((q->windowFlags() & Qt::Popup) == Qt::Popup && q->internalWinId())
1071 ShowWindow(q->internalWinId(), SW_HIDE);
1072 else if (q->internalWinId())
1073 SetWindowPos(q->internalWinId(),0, 0,0,0,0, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER);
1074 }
1075 if (q->isWindow()) {
1076 if (QWidgetBackingStore *bs = maybeBackingStore())
1077 bs->releaseBuffer();
1078 } else {
1079 invalidateBuffer(q->rect());
1080 }
1081 q->setAttribute(Qt::WA_Mapped, false);
1082}
1083
1084
1085/*
1086 \internal
1087 Platform-specific part of QWidget::show().
1088*/
1089#ifndef Q_WS_WINCE
1090void QWidgetPrivate::show_sys()
1091{
1092 Q_Q(QWidget);
1093#if defined(QT_NON_COMMERCIAL)
1094 QT_NC_SHOW_WINDOW
1095#endif
1096 if (q->testAttribute(Qt::WA_OutsideWSRange))
1097 return;
1098 q->setAttribute(Qt::WA_Mapped);
1099 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
1100
1101 if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
1102 invalidateBuffer(q->rect());
1103 return;
1104 }
1105
1106 if (data.window_flags & Qt::Window) {
1107 QTLWExtra *extra = topData();
1108 if (!extra->hotkeyRegistered) {
1109 // Try to set the hotkey using information from STARTUPINFO
1110 STARTUPINFO startupInfo;
1111 GetStartupInfo(&startupInfo);
1112 // If STARTF_USEHOTKEY is set, hStdInput is the virtual keycode
1113 if (startupInfo.dwFlags & 0x00000200) {
1114 WPARAM hotKey = (WPARAM)startupInfo.hStdInput;
1115 SendMessage(data.winid, WM_SETHOTKEY, hotKey, 0);
1116 }
1117 extra->hotkeyRegistered = 1;
1118 }
1119 }
1120
1121 int sm = SW_SHOWNORMAL;
1122 bool fakedMaximize = false;
1123 if (q->isWindow()) {
1124 if (q->isMinimized()) {
1125 sm = SW_SHOWMINIMIZED;
1126 if (!IsWindowVisible(q->internalWinId()))
1127 sm = SW_SHOWMINNOACTIVE;
1128 } else if (q->isMaximized()) {
1129 sm = SW_SHOWMAXIMIZED;
1130 // Windows will not behave correctly when we try to maximize a window which does not
1131 // have minimize nor maximize buttons in the window frame. Windows would then ignore
1132 // non-available geometry, and rather maximize the widget to the full screen, minus the
1133 // window frame (caption). So, we do a trick here, by adding a maximize button before
1134 // maximizing the widget, and then remove the maximize button afterwards.
1135 Qt::WindowFlags &flags = data.window_flags;
1136 if (flags & Qt::WindowTitleHint &&
1137 !(flags & (Qt::WindowMinMaxButtonsHint | Qt::FramelessWindowHint))) {
1138 fakedMaximize = TRUE;
1139 int style = GetWindowLong(q->internalWinId(), GWL_STYLE);
1140 SetWindowLong(q->internalWinId(), GWL_STYLE, style | WS_MAXIMIZEBOX);
1141 }
1142 }
1143 }
1144 if (q->testAttribute(Qt::WA_ShowWithoutActivating)
1145 || (q->windowType() == Qt::Popup)
1146 || (q->windowType() == Qt::ToolTip)
1147 || (q->windowType() == Qt::Tool)) {
1148 sm = SW_SHOWNOACTIVATE;
1149 }
1150
1151
1152 if (q->internalWinId())
1153 ShowWindow(q->internalWinId(), sm);
1154
1155 if (fakedMaximize) {
1156 int style = GetWindowLong(q->internalWinId(), GWL_STYLE);
1157 SetWindowLong(q->internalWinId(), GWL_STYLE, style & ~WS_MAXIMIZEBOX);
1158 SetWindowPos(q->internalWinId(), 0, 0, 0, 0, 0,
1159 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER
1160 | SWP_FRAMECHANGED);
1161 }
1162
1163 if (q->internalWinId()) {
1164 if (IsIconic(q->internalWinId()))
1165 data.window_state |= Qt::WindowMinimized;
1166 if (IsZoomed(q->internalWinId()))
1167 data.window_state |= Qt::WindowMaximized;
1168 // This is to resolve the problem where popups are opened from the
1169 // system tray and not being implicitly activated
1170 if (q->windowType() == Qt::Popup &&
1171 !q->parentWidget() && !qApp->activeWindow())
1172 q->activateWindow();
1173 }
1174
1175 winSetupGestures();
1176
1177 invalidateBuffer(q->rect());
1178}
1179#endif //Q_WS_WINCE
1180
1181void QWidgetPrivate::setFocus_sys()
1182{
1183 Q_Q(QWidget);
1184 if (q->testAttribute(Qt::WA_WState_Created) && q->window()->windowType() != Qt::Popup)
1185 SetFocus(q->effectiveWinId());
1186}
1187
1188void QWidgetPrivate::raise_sys()
1189{
1190 Q_Q(QWidget);
1191 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
1192 if (q->internalWinId())
1193 SetWindowPos(q->internalWinId(), HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
1194}
1195
1196void QWidgetPrivate::lower_sys()
1197{
1198 Q_Q(QWidget);
1199 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
1200 if (q->internalWinId())
1201 SetWindowPos(q->internalWinId(), HWND_BOTTOM, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
1202 invalidateBuffer(q->rect());
1203}
1204
1205void QWidgetPrivate::stackUnder_sys(QWidget* w)
1206{
1207 Q_Q(QWidget);
1208 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
1209 if (q->internalWinId() && w->internalWinId())
1210 SetWindowPos(q->internalWinId(), w->internalWinId() , 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
1211 invalidateBuffer(q->rect());
1212}
1213
1214
1215/*
1216 Helper function for non-toplevel widgets. Helps to map Qt's 32bit
1217 coordinate system to Windpws's 16bit coordinate system.
1218
1219 This code is duplicated from the X11 code, so any changes there
1220 should also (most likely) be reflected here.
1221
1222 (In all comments below: s/X/Windows/g)
1223 */
1224
1225void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &)
1226{
1227 Q_Q(QWidget);
1228 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
1229
1230 /*
1231 There are up to four different coordinate systems here:
1232 Qt coordinate system for this widget.
1233 X coordinate system for this widget (relative to wrect).
1234 Qt coordinate system for parent
1235 X coordinate system for parent (relative to parent's wrect).
1236 */
1237 QRect validRange(-XCOORD_MAX,-XCOORD_MAX, 2*XCOORD_MAX, 2*XCOORD_MAX);
1238 QRect wrectRange(-WRECT_MAX,-WRECT_MAX, 2*WRECT_MAX, 2*WRECT_MAX);
1239 QRect wrect;
1240 //xrect is the X geometry of my X widget. (starts out in parent's Qt coord sys, and ends up in parent's X coord sys)
1241 QRect xrect = data.crect;
1242
1243 const QWidget *const parent = q->parentWidget();
1244 QRect parentWRect = parent->data->wrect;
1245
1246 if (parentWRect.isValid()) {
1247 // parent is clipped, and we have to clip to the same limit as parent
1248 if (!parentWRect.contains(xrect)) {
1249 xrect &= parentWRect;
1250 wrect = xrect;
1251 //translate from parent's to my Qt coord sys
1252 wrect.translate(-data.crect.topLeft());
1253 }
1254 //translate from parent's Qt coords to parent's X coords
1255 xrect.translate(-parentWRect.topLeft());
1256
1257 } else {
1258 // parent is not clipped, we may or may not have to clip
1259
1260 if (data.wrect.isValid() && QRect(QPoint(),data.crect.size()).contains(data.wrect)) {
1261 // This is where the main optimization is: we are already
1262 // clipped, and if our clip is still valid, we can just
1263 // move our window, and do not need to move or clip
1264 // children
1265
1266 QRect vrect = xrect & parent->rect();
1267 vrect.translate(-data.crect.topLeft()); //the part of me that's visible through parent, in my Qt coords
1268 if (data.wrect.contains(vrect)) {
1269 xrect = data.wrect;
1270 xrect.translate(data.crect.topLeft());
1271 if (q->internalWinId())
1272 MoveWindow(q->internalWinId(), xrect.x(), xrect.y(), xrect.width(), xrect.height(), true);
1273 return;
1274 }
1275 }
1276
1277 if (!validRange.contains(xrect)) {
1278 // we are too big, and must clip
1279 xrect &=wrectRange;
1280 wrect = xrect;
1281 wrect.translate(-data.crect.topLeft());
1282 //parent's X coord system is equal to parent's Qt coord
1283 //sys, so we don't need to map xrect.
1284 }
1285
1286 }
1287
1288
1289 // unmap if we are outside the valid window system coord system
1290 bool outsideRange = !xrect.isValid();
1291 bool mapWindow = false;
1292 if (q->testAttribute(Qt::WA_OutsideWSRange) != outsideRange) {
1293 q->setAttribute(Qt::WA_OutsideWSRange, outsideRange);
1294 if (outsideRange) {
1295 if (q->internalWinId())
1296 ShowWindow(q->internalWinId(), SW_HIDE);
1297 q->setAttribute(Qt::WA_Mapped, false);
1298 } else if (!q->isHidden()) {
1299 mapWindow = true;
1300 }
1301 }
1302
1303 if (outsideRange)
1304 return;
1305
1306 bool jump = (data.wrect != wrect);
1307 data.wrect = wrect;
1308
1309 // and now recursively for all children...
1310 for (int i = 0; i < children.size(); ++i) {
1311 QObject *object = children.at(i);
1312 if (object->isWidgetType()) {
1313 QWidget *w = static_cast<QWidget *>(object);
1314 if (!w->isWindow() && w->testAttribute(Qt::WA_WState_Created))
1315 w->d_func()->setWSGeometry();
1316 }
1317 }
1318
1319 // move ourselves to the new position and map (if necessary) after
1320 // the movement. Rationale: moving unmapped windows is much faster
1321 // than moving mapped windows
1322 if (q->internalWinId()) {
1323 if (!parent->internalWinId())
1324 xrect.translate(parent->mapTo(q->nativeParentWidget(), QPoint(0, 0)));
1325 MoveWindow(q->internalWinId(), xrect.x(), xrect.y(), xrect.width(), xrect.height(), !jump);
1326 }
1327 if (mapWindow && !dontShow) {
1328 q->setAttribute(Qt::WA_Mapped);
1329 if (q->internalWinId())
1330 ShowWindow(q->internalWinId(), SW_SHOWNOACTIVATE);
1331 }
1332
1333 if (jump && q->internalWinId())
1334 InvalidateRect(q->internalWinId(), 0, false);
1335
1336}
1337
1338//
1339// The internal qWinRequestConfig, defined in qapplication_win.cpp, stores move,
1340// resize and setGeometry requests for a widget that is already
1341// processing a config event. The purpose is to avoid recursion.
1342//
1343void qWinRequestConfig(WId, int, int, int, int, int);
1344
1345void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
1346{
1347 Q_Q(QWidget);
1348 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
1349 if (extra) { // any size restrictions?
1350 w = qMin(w,extra->maxw);
1351 h = qMin(h,extra->maxh);
1352 w = qMax(w,extra->minw);
1353 h = qMax(h,extra->minh);
1354 }
1355 if (q->isWindow())
1356 topData()->normalGeometry = QRect(0, 0, -1, -1);
1357
1358 QSize oldSize(q->size());
1359 QPoint oldPos(q->pos());
1360
1361 if (!q->isWindow())
1362 isMove = (data.crect.topLeft() != QPoint(x, y));
1363 bool isResize = w != oldSize.width() || h != oldSize.height();
1364
1365 if (!isMove && !isResize)
1366 return;
1367
1368 if (isResize && !q->testAttribute(Qt::WA_StaticContents) && q->internalWinId())
1369 ValidateRgn(q->internalWinId(), 0);
1370
1371#ifdef Q_WS_WINCE
1372 // On Windows CE we can't just fiddle around with the window state.
1373 // Too much magic in setWindowState.
1374 if (isResize && q->isMaximized())
1375 q->setWindowState(q->windowState() & ~Qt::WindowMaximized);
1376#else
1377 if (isResize)
1378 data.window_state &= ~Qt::WindowMaximized;
1379#endif
1380
1381 if (data.window_state & Qt::WindowFullScreen) {
1382 QTLWExtra *top = topData();
1383
1384 if (q->isWindow()) {
1385 // We need to update these flags when we remove the full screen state
1386 // or the frame will not be updated
1387 UINT style = top->savedFlags;
1388 if (q->isVisible())
1389 style |= WS_VISIBLE;
1390 SetWindowLong(q->internalWinId(), GWL_STYLE, style);
1391
1392 UINT swpf = SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE;
1393 if (data.window_state & Qt::WindowActive)
1394 swpf |= SWP_NOACTIVATE;
1395 SetWindowPos(q->internalWinId(), 0, 0, 0, 0, 0, swpf);
1396 updateFrameStrut();
1397 }
1398 data.window_state &= ~Qt::WindowFullScreen;
1399 topData()->savedFlags = 0;
1400 }
1401
1402 QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
1403 const bool inTopLevelResize = tlwExtra ? tlwExtra->inTopLevelResize : false;
1404 const bool isTranslucentWindow = !isOpaque && ptrUpdateLayeredWindowIndirect && (data.window_flags & Qt::FramelessWindowHint)
1405 && GetWindowLong(q->internalWinId(), GWL_EXSTYLE) & Q_WS_EX_LAYERED;
1406
1407 if (q->testAttribute(Qt::WA_WState_ConfigPending)) { // processing config event
1408 if (q->internalWinId())
1409 qWinRequestConfig(q->internalWinId(), isMove ? 2 : 1, x, y, w, h);
1410 } else {
1411 if (!q->testAttribute(Qt::WA_DontShowOnScreen))
1412 q->setAttribute(Qt::WA_WState_ConfigPending);
1413 if (q->windowType() == Qt::Desktop) {
1414 data.crect.setRect(x, y, w, h);
1415 } else if (q->isWindow()) {
1416 QRect fs(frameStrut());
1417 if (extra) {
1418 fs.setLeft(x - fs.left());
1419 fs.setTop(y - fs.top());
1420 fs.setRight((x + w - 1) + fs.right());
1421 fs.setBottom((y + h - 1) + fs.bottom());
1422 }
1423 if (w == 0 || h == 0) {
1424 q->setAttribute(Qt::WA_OutsideWSRange, true);
1425 if (q->isVisible() && q->testAttribute(Qt::WA_Mapped))
1426 hide_sys();
1427 data.crect = QRect(x, y, w, h);
1428 } else if (q->isVisible() && q->testAttribute(Qt::WA_OutsideWSRange)) {
1429 q->setAttribute(Qt::WA_OutsideWSRange, false);
1430
1431 // put the window in its place and show it
1432 MoveWindow(q->internalWinId(), fs.x(), fs.y(), fs.width(), fs.height(), true);
1433 RECT rect;
1434 if (!q->testAttribute(Qt::WA_DontShowOnScreen)) {
1435 GetClientRect(q->internalWinId(), &rect);
1436 data.crect.setRect(x, y, rect.right - rect.left, rect.bottom - rect.top);
1437 } else {
1438 data.crect.setRect(x, y, w, h);
1439 }
1440
1441 show_sys();
1442 } else if (!q->testAttribute(Qt::WA_DontShowOnScreen)) {
1443 q->setAttribute(Qt::WA_OutsideWSRange, false);
1444#ifndef Q_WS_WINCE
1445 // If the window is hidden and in maximized state or minimized, instead of moving the
1446 // window, set the normal position of the window.
1447 WINDOWPLACEMENT wndpl;
1448 GetWindowPlacement(q->internalWinId(), &wndpl);
1449 if ((wndpl.showCmd == SW_MAXIMIZE && !IsWindowVisible(q->internalWinId())) || wndpl.showCmd == SW_SHOWMINIMIZED) {
1450 RECT normal = {fs.x(), fs.y(), fs.x()+fs.width(), fs.y()+fs.height()};
1451 wndpl.rcNormalPosition = normal;
1452 wndpl.showCmd = wndpl.showCmd == SW_SHOWMINIMIZED ? SW_SHOWMINIMIZED : SW_HIDE;
1453 SetWindowPlacement(q->internalWinId(), &wndpl);
1454 } else {
1455#else
1456 if (data.window_state & Qt::WindowMaximized) {
1457 qt_wince_maximize(q);
1458 } else {
1459#endif
1460 MoveWindow(q->internalWinId(), fs.x(), fs.y(), fs.width(), fs.height(), true);
1461 }
1462 if (!q->isVisible())
1463 InvalidateRect(q->internalWinId(), 0, FALSE);
1464 RECT rect;
1465 // If the layout has heightForWidth, the MoveWindow() above can
1466 // change the size/position, so refresh them.
1467
1468 if (isTranslucentWindow) {
1469 data.crect.setRect(x, y, w, h);
1470 } else {
1471 GetClientRect(q->internalWinId(), &rect);
1472 RECT rcNormalPosition ={0};
1473 // Use (0,0) as window position for embedded ActiveQt controls.
1474 if (!tlwExtra || !tlwExtra->embedded)
1475 GetWindowRect(q->internalWinId(), &rcNormalPosition);
1476 QRect fStrut(frameStrut());
1477 data.crect.setRect(rcNormalPosition.left + fStrut.left(),
1478 rcNormalPosition.top + fStrut.top(),
1479 rect.right - rect.left,
1480 rect.bottom - rect.top);
1481 isResize = data.crect.size() != oldSize;
1482 }
1483 } else {
1484 q->setAttribute(Qt::WA_OutsideWSRange, false);
1485 data.crect.setRect(x, y, w, h);
1486 }
1487 } else {
1488 QRect oldGeom(data.crect);
1489 data.crect.setRect(x, y, w, h);
1490 if (q->isVisible() && (!inTopLevelResize || q->internalWinId())) {
1491 // Top-level resize optimization does not work for native child widgets;
1492 // disable it for this particular widget.
1493 if (inTopLevelResize)
1494 tlwExtra->inTopLevelResize = false;
1495
1496 if (!isResize)
1497 moveRect(QRect(oldPos, oldSize), x - oldPos.x(), y - oldPos.y());
1498 else
1499 invalidateBuffer_resizeHelper(oldPos, oldSize);
1500
1501 if (inTopLevelResize)
1502 tlwExtra->inTopLevelResize = true;
1503 }
1504 if (q->testAttribute(Qt::WA_WState_Created))
1505 setWSGeometry();
1506 }
1507 q->setAttribute(Qt::WA_WState_ConfigPending, false);
1508 }
1509
1510 if (q->isWindow() && q->isVisible() && isResize && !inTopLevelResize) {
1511 invalidateBuffer(q->rect()); //after the resize
1512 }
1513
1514 // Process events immediately rather than in translateConfigEvent to
1515 // avoid windows message process delay.
1516 if (q->isVisible()) {
1517 if (isMove && q->pos() != oldPos) {
1518 QMoveEvent e(q->pos(), oldPos);
1519 QApplication::sendEvent(q, &e);
1520 }
1521 if (isResize) {
1522 static bool slowResize = qgetenv("QT_SLOW_TOPLEVEL_RESIZE").toInt();
1523 // If we have a backing store with static contents, we have to disable the top-level
1524 // resize optimization in order to get invalidated regions for resized widgets.
1525 // The optimization discards all invalidateBuffer() calls since we're going to
1526 // repaint everything anyways, but that's not the case with static contents.
1527 const bool setTopLevelResize = !slowResize && q->isWindow() && extra && extra->topextra
1528 && !extra->topextra->inTopLevelResize
1529 && (!extra->topextra->backingStore
1530 || !extra->topextra->backingStore->hasStaticContents());
1531 if (setTopLevelResize)
1532 extra->topextra->inTopLevelResize = true;
1533 QResizeEvent e(q->size(), oldSize);
1534 QApplication::sendEvent(q, &e);
1535 if (setTopLevelResize)
1536 extra->topextra->inTopLevelResize = false;
1537 }
1538 } else {
1539 if (isMove && q->pos() != oldPos)
1540 q->setAttribute(Qt::WA_PendingMoveEvent, true);
1541 if (isResize)
1542 q->setAttribute(Qt::WA_PendingResizeEvent, true);
1543 }
1544}
1545
1546bool QWidgetPrivate::shouldShowMaximizeButton()
1547{
1548 if (data.window_flags & Qt::MSWindowsFixedSizeDialogHint)
1549 return false;
1550 // if the user explicitly asked for the maximize button, we try to add
1551 // it even if the window has fixed size.
1552 if (data.window_flags & Qt::CustomizeWindowHint &&
1553 data.window_flags & Qt::WindowMaximizeButtonHint)
1554 return true;
1555 if (extra) {
1556 if ((extra->maxw && extra->maxw != QWIDGETSIZE_MAX && extra->maxw != QLAYOUTSIZE_MAX)
1557 || (extra->maxh && extra->maxh != QWIDGETSIZE_MAX && extra->maxh != QLAYOUTSIZE_MAX))
1558 return false;
1559 }
1560 return data.window_flags & Qt::WindowMaximizeButtonHint;
1561}
1562
1563void QWidgetPrivate::winUpdateIsOpaque()
1564{
1565#ifndef Q_WS_WINCE
1566 Q_Q(QWidget);
1567
1568 if (!q->isWindow() || !q->testAttribute(Qt::WA_TranslucentBackground))
1569 return;
1570
1571 if ((data.window_flags & Qt::FramelessWindowHint) == 0)
1572 return;
1573
1574 if (!isOpaque && ptrUpdateLayeredWindowIndirect) {
1575 SetWindowLong(q->internalWinId(), GWL_EXSTYLE,
1576 GetWindowLong(q->internalWinId(), GWL_EXSTYLE) | Q_WS_EX_LAYERED);
1577 } else {
1578 SetWindowLong(q->internalWinId(), GWL_EXSTYLE,
1579 GetWindowLong(q->internalWinId(), GWL_EXSTYLE) & ~Q_WS_EX_LAYERED);
1580 }
1581#endif
1582}
1583
1584void QWidgetPrivate::setConstraints_sys()
1585{
1586#ifndef Q_WS_WINCE_WM
1587 Q_Q(QWidget);
1588 if (q->isWindow() && q->testAttribute(Qt::WA_WState_Created)) {
1589 int style = GetWindowLong(q->internalWinId(), GWL_STYLE);
1590 if (shouldShowMaximizeButton())
1591 style |= WS_MAXIMIZEBOX;
1592 else
1593 style &= ~WS_MAXIMIZEBOX;
1594 SetWindowLong(q->internalWinId(), GWL_STYLE, style);
1595 }
1596#endif
1597}
1598
1599void QWidgetPrivate::scroll_sys(int dx, int dy)
1600{
1601 Q_Q(QWidget);
1602 scrollChildren(dx, dy);
1603
1604 if (!paintOnScreen()) {
1605 scrollRect(q->rect(), dx, dy);
1606 } else {
1607 UINT flags = SW_INVALIDATE;
1608 if (!q->testAttribute(Qt::WA_OpaquePaintEvent))
1609 flags |= SW_ERASE;
1610 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
1611 ScrollWindowEx(q->internalWinId(), dx, dy, 0, 0, 0, 0, flags);
1612 UpdateWindow(q->internalWinId());
1613 }
1614}
1615
1616void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r)
1617{
1618 Q_Q(QWidget);
1619
1620 if (!paintOnScreen()) {
1621 scrollRect(r, dx, dy);
1622 } else {
1623 RECT wr;
1624 wr.top = r.top();
1625 wr.left = r.left();
1626 wr.bottom = r.bottom()+1;
1627 wr.right = r.right()+1;
1628
1629 UINT flags = SW_INVALIDATE;
1630 if (!q->testAttribute(Qt::WA_OpaquePaintEvent))
1631 flags |= SW_ERASE;
1632 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
1633 ScrollWindowEx(q->internalWinId(), dx, dy, &wr, &wr, 0, 0, flags);
1634 UpdateWindow(q->internalWinId());
1635 }
1636}
1637
1638extern Q_GUI_EXPORT HDC qt_win_display_dc();
1639
1640int QWidget::metric(PaintDeviceMetric m) const
1641{
1642 Q_D(const QWidget);
1643 int val;
1644 if (m == PdmWidth) {
1645 val = data->crect.width();
1646 } else if (m == PdmHeight) {
1647 val = data->crect.height();
1648 } else {
1649 HDC gdc = qt_win_display_dc();
1650 switch (m) {
1651 case PdmDpiX:
1652 case PdmPhysicalDpiX:
1653 if (d->extra && d->extra->customDpiX)
1654 val = d->extra->customDpiX;
1655 else if (d->parent)
1656 val = static_cast<QWidget *>(d->parent)->metric(m);
1657 else
1658 val = GetDeviceCaps(gdc, LOGPIXELSX);
1659 break;
1660 case PdmDpiY:
1661 case PdmPhysicalDpiY:
1662 if (d->extra && d->extra->customDpiY)
1663 val = d->extra->customDpiY;
1664 else if (d->parent)
1665 val = static_cast<QWidget *>(d->parent)->metric(m);
1666 else
1667 val = GetDeviceCaps(gdc, LOGPIXELSY);
1668 break;
1669 case PdmWidthMM:
1670 val = data->crect.width()
1671 * GetDeviceCaps(gdc, HORZSIZE)
1672 / GetDeviceCaps(gdc, HORZRES);
1673 break;
1674 case PdmHeightMM:
1675 val = data->crect.height()
1676 * GetDeviceCaps(gdc, VERTSIZE)
1677 / GetDeviceCaps(gdc, VERTRES);
1678 break;
1679 case PdmNumColors:
1680 if (GetDeviceCaps(gdc, RASTERCAPS) & RC_PALETTE)
1681 val = GetDeviceCaps(gdc, SIZEPALETTE);
1682 else {
1683 HDC hd = d->hd ? HDC(d->hd) : gdc;
1684 int bpp = GetDeviceCaps(hd, BITSPIXEL);
1685 if (bpp == 32)
1686 val = INT_MAX; // ### this is bogus, it should be 2^24 colors for 32 bit as well
1687 else if(bpp<=8)
1688 val = GetDeviceCaps(hd, NUMCOLORS);
1689 else
1690 val = 1 << (bpp * GetDeviceCaps(hd, PLANES));
1691 }
1692 break;
1693 case PdmDepth:
1694 val = GetDeviceCaps(gdc, BITSPIXEL);
1695 break;
1696 default:
1697 val = 0;
1698 qWarning("QWidget::metric: Invalid metric command");
1699 }
1700 }
1701 return val;
1702}
1703
1704void QWidgetPrivate::createSysExtra()
1705{
1706#ifndef QT_NO_DRAGANDDROP
1707 extra->dropTarget = 0;
1708#endif
1709}
1710
1711#ifndef Q_WS_WINCE
1712void QWidgetPrivate::deleteSysExtra()
1713{
1714}
1715#endif //Q_WS_WINCE
1716
1717void QWidgetPrivate::createTLSysExtra()
1718{
1719 extra->topextra->hotkeyRegistered = 0;
1720 extra->topextra->savedFlags = 0;
1721 extra->topextra->winIconBig = 0;
1722 extra->topextra->winIconSmall = 0;
1723}
1724
1725void QWidgetPrivate::deleteTLSysExtra()
1726{
1727 if (extra->topextra->winIconSmall)
1728 DestroyIcon(extra->topextra->winIconSmall);
1729 if (extra->topextra->winIconBig)
1730 DestroyIcon(extra->topextra->winIconBig);
1731}
1732
1733void QWidgetPrivate::registerDropSite(bool on)
1734{
1735 Q_Q(QWidget);
1736 if (!q->testAttribute(Qt::WA_WState_Created))
1737 return;
1738 // Enablement is defined by d->extra->dropTarget != 0.
1739 if (on) {
1740 // Turn on.
1741 createExtra();
1742#ifndef QT_NO_DRAGANDDROP
1743 if (!q->internalWinId())
1744 q->nativeParentWidget()->d_func()->createExtra();
1745 QWExtra *extra = extraData();
1746 if (!extra->dropTarget)
1747 extra->dropTarget = registerOleDnd(q);
1748#endif
1749 } else {
1750 // Turn off.
1751 QWExtra *extra = extraData();
1752#ifndef QT_NO_DRAGANDDROP
1753 if (extra && extra->dropTarget) {
1754 unregisterOleDnd(q, extra->dropTarget);
1755 extra->dropTarget = 0;
1756 }
1757#endif
1758 }
1759}
1760
1761#ifndef QT_NO_DRAGANDDROP
1762QOleDropTarget* QWidgetPrivate::registerOleDnd(QWidget *widget)
1763{
1764 QOleDropTarget *dropTarget = new QOleDropTarget(widget);
1765 Q_ASSERT(widget->testAttribute(Qt::WA_WState_Created));
1766 if (!widget->internalWinId()) {
1767 QWidget *nativeParent = widget->nativeParentWidget();
1768 Q_ASSERT(nativeParent);
1769 QWExtra *nativeExtra = nativeParent->d_func()->extra;
1770 Q_ASSERT(nativeExtra);
1771 if (!nativeParent->acceptDrops())
1772 nativeParent->setAcceptDrops(true);
1773 if (!nativeExtra->oleDropWidgets.contains(widget))
1774 nativeExtra->oleDropWidgets.append(widget);
1775 if (!nativeExtra->dropTarget) {
1776 nativeExtra->dropTarget = registerOleDnd(nativeParent);
1777 Q_ASSERT(nativeExtra->dropTarget);
1778#ifndef Q_OS_WINCE
1779 CoLockObjectExternal(nativeExtra->dropTarget, false, true);
1780#endif
1781 RegisterDragDrop(nativeParent->internalWinId(), nativeExtra->dropTarget);
1782 }
1783 } else {
1784 RegisterDragDrop(widget->internalWinId(), dropTarget);
1785#ifndef Q_OS_WINCE
1786 CoLockObjectExternal(dropTarget, true, true);
1787#endif
1788 }
1789 return dropTarget;
1790}
1791
1792void QWidgetPrivate::unregisterOleDnd(QWidget *widget, QOleDropTarget *dropTarget)
1793{
1794 dropTarget->releaseQt();
1795 dropTarget->Release();
1796 Q_ASSERT(widget->testAttribute(Qt::WA_WState_Created));
1797 if (!widget->internalWinId()) {
1798 QWidget *nativeParent = widget->nativeParentWidget();
1799 Q_ASSERT(nativeParent);
1800 QWExtra *nativeExtra = nativeParent->d_func()->extra;
1801 Q_ASSERT(nativeExtra);
1802 nativeExtra->oleDropWidgets.removeAll(widget);
1803 nativeExtra->oleDropWidgets.removeAll(static_cast<QWidget *>(0));
1804 if (nativeExtra->oleDropWidgets.isEmpty() && nativeExtra->dropTarget
1805 && !nativeParent->testAttribute(Qt::WA_DropSiteRegistered)) {
1806#ifndef Q_OS_WINCE
1807 CoLockObjectExternal(nativeExtra->dropTarget, false, true);
1808#endif
1809 RevokeDragDrop(nativeParent->internalWinId());
1810 nativeExtra->dropTarget = 0;
1811 }
1812 } else {
1813#ifndef Q_OS_WINCE
1814 CoLockObjectExternal(dropTarget, false, true);
1815#endif
1816 RevokeDragDrop(widget->internalWinId());
1817 }
1818}
1819
1820#endif //QT_NO_DRAGANDDROP
1821
1822// from qregion_win.cpp
1823extern HRGN qt_tryCreateRegion(QRegion::RegionType type, int left, int top, int right, int bottom);
1824void QWidgetPrivate::setMask_sys(const QRegion &region)
1825{
1826 Q_Q(QWidget);
1827 if (!q->internalWinId())
1828 return;
1829
1830 if (region.isEmpty()) {
1831 SetWindowRgn(q->internalWinId(), 0, true);
1832 return;
1833 }
1834
1835 // Since SetWindowRegion takes ownership, and we need to translate,
1836 // we take a copy.
1837 HRGN wr = qt_tryCreateRegion(QRegion::Rectangle, 0,0,0,0);
1838 CombineRgn(wr, region.handle(), 0, RGN_COPY);
1839
1840 QPoint offset = (q->isWindow()
1841 ? frameStrut().topLeft()
1842 : QPoint(0, 0));
1843 OffsetRgn(wr, offset.x(), offset.y());
1844
1845 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
1846 if (!SetWindowRgn(data.winid, wr, true))
1847 DeleteObject(wr);
1848}
1849
1850void QWidgetPrivate::updateFrameStrut()
1851{
1852 Q_Q(QWidget);
1853
1854 if (!q->testAttribute(Qt::WA_WState_Created))
1855 return;
1856
1857 if (!q->internalWinId()) {
1858 data.fstrut_dirty = false;
1859 return;
1860 }
1861
1862 RECT rect = {0,0,0,0};
1863
1864 QTLWExtra *top = topData();
1865 uint exstyle = GetWindowLong(q->internalWinId(), GWL_EXSTYLE);
1866 uint style = GetWindowLong(q->internalWinId(), GWL_STYLE);
1867#ifndef Q_WS_WINCE
1868 if (AdjustWindowRectEx(&rect, style & ~(WS_OVERLAPPED), FALSE, exstyle)) {
1869#else
1870 if (AdjustWindowRectEx(&rect, style, FALSE, exstyle)) {
1871#endif
1872 top->frameStrut.setCoords(-rect.left, -rect.top, rect.right, rect.bottom);
1873 data.fstrut_dirty = false;
1874 }
1875}
1876
1877#ifndef Q_WS_WINCE
1878void QWidgetPrivate::setWindowOpacity_sys(qreal level)
1879{
1880 Q_Q(QWidget);
1881
1882 if (!isOpaque && ptrUpdateLayeredWindow && (data.window_flags & Qt::FramelessWindowHint)) {
1883 if (GetWindowLong(q->internalWinId(), GWL_EXSTYLE) & Q_WS_EX_LAYERED) {
1884 BLENDFUNCTION blend = {AC_SRC_OVER, 0, (int)(255.0 * level), AC_SRC_ALPHA};
1885 ptrUpdateLayeredWindow(q->internalWinId(), NULL, NULL, NULL, NULL, NULL, 0, &blend, Q_ULW_ALPHA);
1886 }
1887 return;
1888 }
1889
1890 static bool function_resolved = false;
1891 if (!function_resolved) {
1892 ptrSetLayeredWindowAttributes =
1893 (PtrSetLayeredWindowAttributes) QSystemLibrary::resolve(QLatin1String("user32"),
1894 "SetLayeredWindowAttributes");
1895 function_resolved = true;
1896 }
1897
1898 if (!ptrSetLayeredWindowAttributes)
1899 return;
1900
1901 int wl = GetWindowLong(q->internalWinId(), GWL_EXSTYLE);
1902
1903 if (level != 1.0) {
1904 if ((wl&Q_WS_EX_LAYERED) == 0)
1905 SetWindowLong(q->internalWinId(), GWL_EXSTYLE, wl | Q_WS_EX_LAYERED);
1906 } else if (wl&Q_WS_EX_LAYERED) {
1907 SetWindowLong(q->internalWinId(), GWL_EXSTYLE, wl & ~Q_WS_EX_LAYERED);
1908 }
1909 ptrSetLayeredWindowAttributes(q->internalWinId(), 0, (int)(level * 255), Q_LWA_ALPHA);
1910}
1911#endif //Q_WS_WINCE
1912
1913// class QGlobalRasterPaintEngine: public QRasterPaintEngine
1914// {
1915// public:
1916// inline QGlobalRasterPaintEngine() : QRasterPaintEngine() { setFlushOnEnd(false); }
1917// };
1918// Q_GLOBAL_STATIC(QGlobalRasterPaintEngine, globalRasterPaintEngine)
1919
1920
1921#ifndef QT_NO_DIRECTDRAW
1922static uchar *qt_primary_surface_bits;
1923static int qt_primary_surface_stride;
1924static QImage::Format qt_primary_surface_format;
1925
1926void qt_win_initialize_directdraw()
1927{
1928 HRESULT res;
1929
1930 // Some initialization...
1931 if (!qt_ddraw_object) {
1932 res = DirectDrawCreate(0, &qt_ddraw_object, 0);
1933
1934 if (res != DD_OK)
1935 qWarning("DirectDrawCreate failed: %d", res);
1936
1937 qt_ddraw_object->SetCooperativeLevel(0, DDSCL_NORMAL);
1938
1939 DDSURFACEDESC surfaceDesc;
1940 memset(&surfaceDesc, 0, sizeof(DDSURFACEDESC));
1941
1942 surfaceDesc.dwSize = sizeof(DDSURFACEDESC);
1943 surfaceDesc.dwFlags = DDSD_CAPS;
1944 surfaceDesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
1945
1946 res = qt_ddraw_object->CreateSurface(&surfaceDesc, &qt_ddraw_primary, 0);
1947 if (res != DD_OK)
1948 qWarning("CreateSurface failed: %d", res);
1949
1950 memset(&surfaceDesc, 0, sizeof(DDSURFACEDESC));
1951 surfaceDesc.dwSize = sizeof(DDSURFACEDESC);
1952 res = qt_ddraw_primary->Lock(0, &surfaceDesc, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, 0);
1953 if (res != DD_OK)
1954 qWarning("Locking surface failed: %d", res);
1955
1956 if (surfaceDesc.ddpfPixelFormat.dwFlags == DDPF_RGB) {
1957 qt_primary_surface_bits = (uchar *) surfaceDesc.lpSurface;
1958 qt_primary_surface_stride = surfaceDesc.lPitch;
1959 qt_primary_surface_format = QImage::Format_RGB32;
1960 } else {
1961 qWarning("QWidget painting: unsupported device depth for onscreen painting...\n");
1962 }
1963
1964 qt_ddraw_primary->Unlock(0);
1965 }
1966}
1967
1968class QOnScreenRasterPaintEngine : public QRasterPaintEngine
1969{
1970public:
1971 // The image allocated here leaks... Fix if this code is ifdef'ed
1972 // in
1973 QOnScreenRasterPaintEngine()
1974 : QRasterPaintEngine(new QImage(qt_primary_surface_bits,
1975 QApplication::desktop()->width(),
1976 QApplication::desktop()->height(),
1977 qt_primary_surface_stride,
1978 qt_primary_surface_format))
1979 {
1980 device = static_cast<QImage *>(d_func()->device);
1981 }
1982
1983 bool begin(QPaintDevice *)
1984 {
1985 QRegion clip = systemClip();
1986 originalSystemClip = clip;
1987 clip.translate(widget->mapToGlobal(QPoint(0, 0)));
1988 setSystemClip(clip);
1989
1990 QRect bounds = clip.boundingRect();
1991 DDSURFACEDESC surface;
1992 surface.dwSize = sizeof(DDSURFACEDESC);
1993 HRESULT res = qt_ddraw_primary->Lock((RECT *) &bounds, &surface, DDLOCK_WAIT, 0);
1994 if (res != DD_OK) {
1995 qWarning("QWidget painting: locking onscreen bits failed: %d\n", res);
1996 return false;
1997 }
1998
1999 if (surface.lpSurface == qt_primary_surface_bits) {
2000 qt_primary_surface_bits = (uchar *) surface.lpSurface;
2001 device->data_ptr()->data = qt_primary_surface_bits;
2002 }
2003
2004 return QRasterPaintEngine::begin(device);
2005 }
2006
2007 bool end()
2008 {
2009 HRESULT res = qt_ddraw_primary->Unlock(0);
2010 if (res != DD_OK)
2011 qWarning("QWidget::paint, failed to unlock DirectDraw surface: %d", res);
2012 bool ok = QRasterPaintEngine::end();
2013 setSystemClip(originalSystemClip);
2014 return ok;
2015 }
2016
2017 QPoint coordinateOffset() const {
2018 return -widget->mapToGlobal(QPoint(0, 0));
2019 }
2020
2021 const QWidget *widget;
2022 QImage *device;
2023 QRegion originalSystemClip;
2024};
2025Q_GLOBAL_STATIC(QOnScreenRasterPaintEngine, onScreenPaintEngine)
2026#else
2027void qt_win_initialize_directdraw() { }
2028#endif
2029
2030QPaintEngine *QWidget::paintEngine() const
2031{
2032#ifndef QT_NO_DIRECTDRAW
2033 QOnScreenRasterPaintEngine *pe = onScreenPaintEngine();
2034 pe->widget = this;
2035 return pe;
2036#endif
2037
2038 // We set this bit which is checked in setAttribute for
2039 // Qt::WA_PaintOnScreen. We do this to allow these two scenarios:
2040 //
2041 // 1. Users accidentally set Qt::WA_PaintOnScreen on X and port to
2042 // windows which would mean suddenly their widgets stop working.
2043 //
2044 // 2. Users set paint on screen and subclass paintEngine() to
2045 // return 0, in which case we have a "hole" in the backingstore
2046 // allowing use of GDI or DirectX directly.
2047 //
2048 // 1 is WRONG, but to minimize silent failures, we have set this
2049 // bit to ignore the setAttribute call. 2. needs to be
2050 // supported because its our only means of embeddeding native
2051 // graphics stuff.
2052 const_cast<QWidgetPrivate *>(d_func())->noPaintOnScreen = 1;
2053
2054 return 0;
2055}
2056
2057QWindowSurface *QWidgetPrivate::createDefaultWindowSurface_sys()
2058{
2059 Q_Q(QWidget);
2060 return new QRasterWindowSurface(q);
2061}
2062
2063void QWidgetPrivate::setModal_sys()
2064{
2065}
2066
2067void QWidgetPrivate::registerTouchWindow()
2068{
2069 Q_Q(QWidget);
2070
2071 // enable WM_TOUCH* messages on our window
2072 if (q->testAttribute(Qt::WA_WState_Created)
2073 && QApplicationPrivate::RegisterTouchWindow
2074 && q->windowType() != Qt::Desktop)
2075 QApplicationPrivate::RegisterTouchWindow(q->effectiveWinId(), 0);
2076}
2077
2078void QWidgetPrivate::winSetupGestures()
2079{
2080#if !defined(QT_NO_GESTURES) && !defined(QT_NO_NATIVE_GESTURES)
2081 Q_Q(QWidget);
2082 if (!q || !q->isVisible() || !nativeGesturePanEnabled)
2083 return;
2084
2085 if (!QApplicationPrivate::HasTouchSupport)
2086 return;
2087 QApplicationPrivate *qAppPriv = QApplicationPrivate::instance();
2088 if (!qAppPriv->SetGestureConfig)
2089 return;
2090 WId winid = q->internalWinId();
2091
2092 bool needh = false;
2093 bool needv = false;
2094 bool singleFingerPanEnabled = false;
2095
2096#ifndef QT_NO_SCROLLAREA
2097 if (QAbstractScrollArea *asa = qobject_cast<QAbstractScrollArea*>(q->parent())) {
2098 QScrollBar *hbar = asa->horizontalScrollBar();
2099 QScrollBar *vbar = asa->verticalScrollBar();
2100 Qt::ScrollBarPolicy hbarpolicy = asa->horizontalScrollBarPolicy();
2101 Qt::ScrollBarPolicy vbarpolicy = asa->verticalScrollBarPolicy();
2102 needh = (hbarpolicy == Qt::ScrollBarAlwaysOn ||
2103 (hbarpolicy == Qt::ScrollBarAsNeeded && hbar->minimum() < hbar->maximum()));
2104 needv = (vbarpolicy == Qt::ScrollBarAlwaysOn ||
2105 (vbarpolicy == Qt::ScrollBarAsNeeded && vbar->minimum() < vbar->maximum()));
2106 singleFingerPanEnabled = asa->d_func()->singleFingerPanEnabled;
2107 if (!winid) {
2108 winid = q->winId(); // enforces the native winid on the viewport
2109 }
2110 }
2111#endif //QT_NO_SCROLLAREA
2112 if (winid) {
2113 GESTURECONFIG gc[1];
2114 memset(gc, 0, sizeof(gc));
2115 gc[0].dwID = GID_PAN;
2116 if (nativeGesturePanEnabled) {
2117 gc[0].dwWant = GC_PAN;
2118 if (needv && singleFingerPanEnabled)
2119 gc[0].dwWant |= GC_PAN_WITH_SINGLE_FINGER_VERTICALLY;
2120 else
2121 gc[0].dwBlock |= GC_PAN_WITH_SINGLE_FINGER_VERTICALLY;
2122 if (needh && singleFingerPanEnabled)
2123 gc[0].dwWant |= GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY;
2124 else
2125 gc[0].dwBlock |= GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY;
2126 } else {
2127 gc[0].dwBlock = GC_PAN;
2128 }
2129
2130 qAppPriv->SetGestureConfig(winid, 0, sizeof(gc)/sizeof(gc[0]), gc, sizeof(gc[0]));
2131 }
2132#endif
2133}
2134
2135QT_END_NAMESPACE
2136
2137#ifdef Q_WS_WINCE
2138# include "qwidget_wince.cpp"
2139#endif
Note: See TracBrowser for help on using the repository browser.