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

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

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

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