/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qapplication.h"
#include "qapplication_p.h"
#include "qbitmap.h"
#include "qcursor.h"
#include "qdesktopwidget.h"
#include "qevent.h"
#include "qimage.h"
#include "qlayout.h"
#include "qlibrary.h"
#include "qpainter.h"
#include "qstack.h"
#include "qt_windows.h"
#include "qwidget.h"
#include "qwidget_p.h"
#include "private/qbackingstore_p.h"
#include "private/qwindowsurface_raster_p.h"
#include "qscrollbar.h"
#include "qabstractscrollarea.h"
#include <private/qabstractscrollarea_p.h>
#include <qdebug.h>
#include <private/qapplication_p.h>
#include <private/qwininputcontext_p.h>
#include <private/qpaintengine_raster_p.h>
#if defined(Q_WS_WINCE)
#include "qguifunctions_wince.h"
QT_USE_NAMESPACE
extern void qt_wince_maximize(QWidget *widget); //defined in qguifunctions_wince.cpp
extern void qt_wince_unmaximize(QWidget *widget); //defined in qguifunctions_wince.cpp
extern void qt_wince_minimize(HWND hwnd); //defined in qguifunctions_wince.cpp
extern void qt_wince_full_screen(HWND hwnd, bool fullScreen, UINT swpf); //defined in qguifunctions_wince.cpp
extern bool qt_wince_is_mobile(); //defined in qguifunctions_wince.cpp
#endif
typedef BOOL (WINAPI *PtrSetLayeredWindowAttributes)(HWND hwnd, COLORREF crKey, BYTE bAlpha, DWORD dwFlags);
static PtrSetLayeredWindowAttributes ptrSetLayeredWindowAttributes = 0;
#ifndef QT_NO_DIRECTDRAW
#include <ddraw.h>
#include <private/qimage_p.h>
static IDirectDraw *qt_ddraw_object;
static IDirectDrawSurface *qt_ddraw_primary;
#endif
#if defined(QT_NON_COMMERCIAL)
#include "qnc_win.h"
#endif
#if !defined(WS_EX_TOOLWINDOW)
#define WS_EX_TOOLWINDOW 0x00000080
#endif
#if !defined(GWLP_WNDPROC)
#define GWLP_WNDPROC GWL_WNDPROC
#endif
//#define TABLET_DEBUG
#define PACKETDATA (PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE \
| PK_ORIENTATION | PK_CURSOR | PK_Z)
#define PACKETMODE 0
#include <wintab.h>
#include <pktdef.h>
QT_BEGIN_NAMESPACE
typedef HCTX (API *PtrWTOpen)(HWND, LPLOGCONTEXT, BOOL);
typedef BOOL (API *PtrWTClose)(HCTX);
typedef UINT (API *PtrWTInfo)(UINT, UINT, LPVOID);
typedef BOOL (API *PtrWTEnable)(HCTX, BOOL);
typedef BOOL (API *PtrWTOverlap)(HCTX, BOOL);
typedef int (API *PtrWTPacketsGet)(HCTX, int, LPVOID);
typedef BOOL (API *PtrWTGet)(HCTX, LPLOGCONTEXT);
typedef int (API *PtrWTQueueSizeGet)(HCTX);
typedef BOOL (API *PtrWTQueueSizeSet)(HCTX, int);
static PtrWTOpen ptrWTOpen = 0;
static PtrWTClose ptrWTClose = 0;
static PtrWTInfo ptrWTInfo = 0;
static PtrWTQueueSizeGet ptrWTQueueSizeGet = 0;
static PtrWTQueueSizeSet ptrWTQueueSizeSet = 0;
#ifndef QT_NO_TABLETEVENT
static void init_wintab_functions();
static void qt_tablet_init();
static void qt_tablet_cleanup();
#endif // QT_NO_TABLETEVENT
extern HCTX qt_tablet_context;
extern bool qt_tablet_tilt_support;
static QWidget *qt_tablet_widget = 0;
QWidget* qt_get_tablet_widget()
{
return qt_tablet_widget;
}
extern bool qt_is_gui_used;
#ifndef QT_NO_TABLETEVENT
static void init_wintab_functions()
{
#if defined(Q_OS_WINCE)
return;
#else
if (!qt_is_gui_used)
return;
QLibrary library(QLatin1String("wintab32"));
ptrWTOpen = (PtrWTOpen)library.resolve("WTOpenW");
ptrWTInfo = (PtrWTInfo)library.resolve("WTInfoW");
ptrWTClose = (PtrWTClose)library.resolve("WTClose");
ptrWTQueueSizeGet = (PtrWTQueueSizeGet)library.resolve("WTQueueSizeGet");
ptrWTQueueSizeSet = (PtrWTQueueSizeSet)library.resolve("WTQueueSizeSet");
#endif // Q_OS_WINCE
}
static void qt_tablet_init()
{
static bool firstTime = true;
if (!firstTime)
return;
firstTime = false;
qt_tablet_widget = new QWidget(0);
qt_tablet_widget->createWinId();
qt_tablet_widget->setObjectName(QLatin1String("Qt internal tablet widget"));
// We dont need this internal widget to appear in QApplication::topLevelWidgets()
if (QWidgetPrivate::allWidgets)
QWidgetPrivate::allWidgets->remove(qt_tablet_widget);
LOGCONTEXT lcMine;
qAddPostRoutine(qt_tablet_cleanup);
struct tagAXIS tpOri[3];
init_wintab_functions();
if (ptrWTInfo && ptrWTOpen && ptrWTQueueSizeGet && ptrWTQueueSizeSet) {
// make sure we have WinTab
if (!ptrWTInfo(0, 0, NULL)) {
#ifdef TABLET_DEBUG
qWarning("QWidget: Wintab services not available");
#endif
return;
}
// some tablets don't support tilt, check if it is possible,
qt_tablet_tilt_support = ptrWTInfo(WTI_DEVICES, DVC_ORIENTATION, &tpOri);
if (qt_tablet_tilt_support) {
// check for azimuth and altitude
qt_tablet_tilt_support = tpOri[0].axResolution && tpOri[1].axResolution;
}
// build our context from the default context
ptrWTInfo(WTI_DEFSYSCTX, 0, &lcMine);
// Go for the raw coordinates, the tablet event will return good stuff
lcMine.lcOptions |= CXO_MESSAGES | CXO_CSRMESSAGES;
lcMine.lcPktData = PACKETDATA;
lcMine.lcPktMode = PACKETMODE;
lcMine.lcMoveMask = PACKETDATA;
lcMine.lcOutOrgX = 0;
lcMine.lcOutExtX = lcMine.lcInExtX;
lcMine.lcOutOrgY = 0;
lcMine.lcOutExtY = -lcMine.lcInExtY;
qt_tablet_context = ptrWTOpen(qt_tablet_widget->winId(), &lcMine, true);
#ifdef TABLET_DEBUG
qDebug("Tablet is %p", qt_tablet_context);
#endif
if (!qt_tablet_context) {
#ifdef TABLET_DEBUG
qWarning("QWidget: Failed to open the tablet");
#endif
return;
}
// Set the size of the Packet Queue to the correct size...
int currSize = ptrWTQueueSizeGet(qt_tablet_context);
if (!ptrWTQueueSizeSet(qt_tablet_context, QT_TABLET_NPACKETQSIZE)) {
// Ideally one might want to use a smaller
// multiple, but for now, since we managed to destroy
// the existing Q with the previous call, set it back
// to the other size, which should work. If not,
// there will be trouble.
if (!ptrWTQueueSizeSet(qt_tablet_context, currSize)) {
Q_ASSERT_X(0, "Qt::Internal", "There is no packet queue for"
" the tablet. The tablet will not work");
}
}
}
}
static void qt_tablet_cleanup()
{
if (ptrWTClose)
ptrWTClose(qt_tablet_context);
delete qt_tablet_widget;
qt_tablet_widget = 0;
}
#endif // QT_NO_TABLETEVENT
const QString qt_reg_winclass(QWidget *w); // defined in qapplication_win.cpp
#ifndef QT_NO_DRAGANDDROP
void qt_olednd_unregister(QWidget* widget, QOleDropTarget *dst); // dnd_win
QOleDropTarget* qt_olednd_register(QWidget* widget);
#endif
extern bool qt_nograb();
extern HRGN qt_win_bitmapToRegion(const QBitmap& bitmap);
static QWidget *mouseGrb = 0;
static QCursor *mouseGrbCur = 0;
static QWidget *keyboardGrb = 0;
static HHOOK journalRec = 0;
extern "C" LRESULT QT_WIN_CALLBACK QtWndProc(HWND, UINT, WPARAM, LPARAM);
#define XCOORD_MAX 16383
#define WRECT_MAX 16383
/*****************************************************************************
QWidget member functions
*****************************************************************************/
#ifndef Q_WS_WINCE
void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyOldWindow)
{
Q_Q(QWidget);
static int sw = -1, sh = -1;
Qt::WindowType type = q->windowType();
Qt::WindowFlags flags = data.window_flags;
bool topLevel = (flags & Qt::Window);
bool popup = (type == Qt::Popup);
bool dialog = (type == Qt::Dialog
|| type == Qt::Sheet
|| (flags & Qt::MSWindowsFixedSizeDialogHint));
bool desktop = (type == Qt::Desktop);
bool tool = (type == Qt::Tool || type == Qt::Drawer);
HINSTANCE appinst = qWinAppInst();
HWND parentw, destroyw = 0;
WId id = 0;
QString windowClassName = qt_reg_winclass(q);
if (!window) // always initialize
initializeWindow = true;
if (popup)
flags |= Qt::WindowStaysOnTopHint; // a popup stays on top
if (sw < 0) { // get the (primary) screen size
sw = GetSystemMetrics(SM_CXSCREEN);
sh = GetSystemMetrics(SM_CYSCREEN);
}
if (desktop && !q->testAttribute(Qt::WA_DontShowOnScreen)) { // desktop widget
popup = false; // force this flags off
data.crect.setRect(GetSystemMetrics(76 /* SM_XVIRTUALSCREEN */), GetSystemMetrics(77 /* SM_YVIRTUALSCREEN */),
GetSystemMetrics(78 /* SM_CXVIRTUALSCREEN */), GetSystemMetrics(79 /* SM_CYVIRTUALSCREEN */));
}
parentw = q->parentWidget() ? q->parentWidget()->effectiveWinId() : 0;
QString title;
int style = WS_CHILD;
int exsty = 0;
if (window) {
style = GetWindowLong(window, GWL_STYLE);
if (!style)
qErrnoWarning("QWidget::create: GetWindowLong failed");
topLevel = false; // #### needed for some IE plugins??
} else if (popup || (type == Qt::ToolTip) || (type == Qt::SplashScreen)) {
style = WS_POPUP;
} else if (topLevel && !desktop) {
if (flags & Qt::FramelessWindowHint)
style = WS_POPUP; // no border
else if (flags & Qt::WindowTitleHint)
style = WS_OVERLAPPED;
else
style = 0;
}
if (!desktop) {
// if (!testAttribute(Qt::WA_PaintUnclipped))
// ### Commented out for now as it causes some problems, but
// this should be correct anyway, so dig some more into this
#ifndef Q_FLATTEN_EXPOSE
style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN ;
#endif
if (topLevel) {
if ((type == Qt::Window || dialog || tool)) {
if (!(flags & Qt::FramelessWindowHint)) {
if (!(flags & Qt::MSWindowsFixedSizeDialogHint)) {
style |= WS_THICKFRAME;
if(!(flags &
( Qt::WindowSystemMenuHint
| Qt::WindowTitleHint
| Qt::WindowMinMaxButtonsHint
| Qt::WindowCloseButtonHint
| Qt::WindowContextHelpButtonHint)))
style |= WS_POPUP;
} else {
style |= WS_POPUP | WS_DLGFRAME;
}
}
if (flags & Qt::WindowTitleHint)
style |= WS_CAPTION;
if (flags & Qt::WindowSystemMenuHint)
style |= WS_SYSMENU;
if (flags & Qt::WindowMinimizeButtonHint)
style |= WS_MINIMIZEBOX;
if (shouldShowMaximizeButton())
style |= WS_MAXIMIZEBOX;
if (tool)
exsty |= WS_EX_TOOLWINDOW;
if (flags & Qt::WindowContextHelpButtonHint)
exsty |= WS_EX_CONTEXTHELP;
} else {
exsty |= WS_EX_TOOLWINDOW;
}
}
}
if (flags & Qt::WindowTitleHint) {
title = q->isWindow() ? qAppName() : q->objectName();
}
// The Qt::WA_WState_Created flag is checked by translateConfigEvent() in
// qapplication_win.cpp. We switch it off temporarily to avoid move
// and resize events during creationt
q->setAttribute(Qt::WA_WState_Created, false);
if (window) { // override the old window
if (destroyOldWindow)
destroyw = data.winid;
id = window;
setWinId(window);
LONG res = SetWindowLong(window, GWL_STYLE, style);
if (!res)
qErrnoWarning("QWidget::create: Failed to set window style");
#ifdef _WIN64
res = SetWindowLongPtr( window, GWLP_WNDPROC, (LONG_PTR)QtWndProc );
#else
res = SetWindowLong( window, GWL_WNDPROC, (LONG)QtWndProc );
#endif
if (!res)
qErrnoWarning("QWidget::create: Failed to set window procedure");
} else if (desktop) { // desktop widget
id = GetDesktopWindow();
// QWidget *otherDesktop = QWidget::find(id); // is there another desktop?
// if (otherDesktop && otherDesktop->testWFlags(Qt::WPaintDesktop)) {
// otherDesktop->d_func()->setWinId(0); // remove id from widget mapper
// d->setWinId(id); // make sure otherDesktop is
// otherDesktop->d_func()->setWinId(id); // found first
// } else {
setWinId(id);
// }
} else if (topLevel) { // create top-level widget
if (popup)
parentw = 0;
const bool wasMoved = q->testAttribute(Qt::WA_Moved);
int x = wasMoved ? data.crect.left() : CW_USEDEFAULT;
int y = wasMoved ? data.crect.top() : CW_USEDEFAULT;
int w = CW_USEDEFAULT;
int h = CW_USEDEFAULT;
// Adjust for framestrut when needed
RECT rect = {0,0,0,0};
bool isVisibleOnScreen = !q->testAttribute(Qt::WA_DontShowOnScreen);
if (isVisibleOnScreen && AdjustWindowRectEx(&rect, style & ~WS_OVERLAPPED, FALSE, exsty)) {
QTLWExtra *td = maybeTopData();
if (wasMoved && (td && !td->posFromMove)) {
x = data.crect.x() + rect.left;
y = data.crect.y() + rect.top;
}
if (q->testAttribute(Qt::WA_Resized)) {
w = data.crect.width() + (rect.right - rect.left);
h = data.crect.height() + (rect.bottom - rect.top);
}
}
//update position & initial size of POPUP window
if (isVisibleOnScreen && topLevel && initializeWindow && (style & WS_POPUP)) {
if (!q->testAttribute(Qt::WA_Resized)) {
w = sw/2;
h = 4*sh/10;
}
if (!wasMoved) {
x = sw/2 - w/2;
y = sh/2 - h/2;
}
}
id = CreateWindowEx(exsty, reinterpret_cast<const wchar_t *>(windowClassName.utf16()),
reinterpret_cast<const wchar_t *>(title.utf16()), style,
x, y, w, h,
parentw, NULL, appinst, NULL);
if (!id)
qErrnoWarning("QWidget::create: Failed to create window");
setWinId(id);
if ((flags & Qt::WindowStaysOnTopHint) || (type == Qt::ToolTip)) {
SetWindowPos(id, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
if (flags & Qt::WindowStaysOnBottomHint)
qWarning() << "QWidget: Incompatible window flags: the window can't be on top and on bottom at the same time";
} else if (flags & Qt::WindowStaysOnBottomHint)
SetWindowPos(id, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
winUpdateIsOpaque();
} else if (q->testAttribute(Qt::WA_NativeWindow) || paintOnScreen()) { // create child widget
id = CreateWindowEx(exsty, reinterpret_cast<const wchar_t *>(windowClassName.utf16()),
reinterpret_cast<const wchar_t *>(title.utf16()), style,
data.crect.left(), data.crect.top(), data.crect.width(), data.crect.height(),
parentw, NULL, appinst, NULL);
if (!id)
qErrnoWarning("QWidget::create: Failed to create window");
SetWindowPos(id, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
setWinId(id);
}
if (desktop) {
q->setAttribute(Qt::WA_WState_Visible);
} else if (topLevel && !q->testAttribute(Qt::WA_DontShowOnScreen)) {
RECT cr;
GetClientRect(id, &cr);
// one cannot trust cr.left and cr.top, use a correction POINT instead
POINT pt;
pt.x = 0;
pt.y = 0;
ClientToScreen(id, &pt);
if (data.crect.width() == 0 || data.crect.height() == 0) {
data.crect = QRect(pt.x, pt.y, data.crect.width(), data.crect.height());
} else {
data.crect = QRect(QPoint(pt.x, pt.y),
QPoint(pt.x + cr.right - 1, pt.y + cr.bottom - 1));
}
if (data.fstrut_dirty) {
// be nice to activeqt
updateFrameStrut();
}
}
if (topLevel) {
if (data.window_flags & Qt::CustomizeWindowHint
&& data.window_flags & Qt::WindowTitleHint) {
HMENU systemMenu = GetSystemMenu((HWND)q->internalWinId(), FALSE);
if (data.window_flags & Qt::WindowCloseButtonHint)
EnableMenuItem(systemMenu, SC_CLOSE, MF_BYCOMMAND|MF_ENABLED);
else
EnableMenuItem(systemMenu, SC_CLOSE, MF_BYCOMMAND|MF_GRAYED);
}
}
q->setAttribute(Qt::WA_WState_Created); // accept move/resize events
hd = 0; // no display context
if (q->testAttribute(Qt::WA_AcceptTouchEvents))
registerTouchWindow();
if (window) { // got window from outside
if (IsWindowVisible(window))
q->setAttribute(Qt::WA_WState_Visible);
else
q->setAttribute(Qt::WA_WState_Visible, false);
}
if (extra && !extra->mask.isEmpty())
setMask_sys(extra->mask);
#if defined(QT_NON_COMMERCIAL)
QT_NC_WIDGET_CREATE
#endif
if (q->hasFocus() && q->testAttribute(Qt::WA_InputMethodEnabled))
q->inputContext()->setFocusWidget(q);
if (destroyw) {
DestroyWindow(destroyw);
}
#ifndef QT_NO_TABLETEVENT
if (q != qt_tablet_widget && QWidgetPrivate::mapper)
qt_tablet_init();
#endif // QT_NO_TABLETEVENT
if (q->testAttribute(Qt::WA_DropSiteRegistered))
registerDropSite(true);
if (maybeTopData() && maybeTopData()->opacity != 255)
q->setWindowOpacity(maybeTopData()->opacity/255.);
if (topLevel && (data.crect.width() == 0 || data.crect.height() == 0)) {
q->setAttribute(Qt::WA_OutsideWSRange, true);
}
if (!topLevel && q->testAttribute(Qt::WA_NativeWindow) && q->testAttribute(Qt::WA_Mapped)) {
Q_ASSERT(q->internalWinId());
ShowWindow(q->internalWinId(), SW_SHOW);
}
}
#endif //Q_WS_WINCE
void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
{
Q_D(QWidget);
d->aboutToDestroy();
if (!isWindow() && parentWidget())
parentWidget()->d_func()->invalidateBuffer(d->effectiveRectFor(geometry()));
d->deactivateWidgetCleanup();
if (testAttribute(Qt::WA_WState_Created)) {
setAttribute(Qt::WA_WState_Created, false);
for(int i = 0; i < d->children.size(); ++i) { // destroy all widget children
register QObject *obj = d->children.at(i);
if (obj->isWidgetType())
((QWidget*)obj)->destroy(destroySubWindows,
destroySubWindows);
}
if (mouseGrb == this)
releaseMouse();
if (keyboardGrb == this)
releaseKeyboard();
if (testAttribute(Qt::WA_ShowModal)) // just be sure we leave modal
QApplicationPrivate::leaveModal(this);
else if ((windowType() == Qt::Popup))
qApp->d_func()->closePopup(this);
if (destroyWindow && !(windowType() == Qt::Desktop) && internalWinId()) {
DestroyWindow(internalWinId());
}
#ifdef Q_WS_WINCE
if (destroyWindow && (windowType() == Qt::Desktop) && !GetDesktopWindow()) {
DestroyWindow(internalWinId());
}
#endif
QT_TRY {
d->setWinId(0);
} QT_CATCH (const std::bad_alloc &) {
// swallow - destructors must not throw
}
}
}
void QWidgetPrivate::reparentChildren()
{
Q_Q(QWidget);
QObjectList chlist = q->children();
for(int i = 0; i < chlist.size(); ++i) { // reparent children
QObject *obj = chlist.at(i);
if (obj->isWidgetType()) {
QWidget *w = (QWidget *)obj;
if ((w->windowType() == Qt::Popup)) {
;
} else if (w->isWindow()) {
bool showIt = w->isVisible();
QPoint old_pos = w->pos();
w->setParent(q, w->windowFlags());
w->move(old_pos);
if (showIt)
w->show();
} else {
w->d_func()->invalidateBuffer(w->rect());
SetParent(w->effectiveWinId(), q->effectiveWinId());
w->d_func()->reparentChildren();
}
}
}
}
void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f)
{
Q_Q(QWidget);
bool wasCreated = q->testAttribute(Qt::WA_WState_Created);
if (q->isVisible() && q->parentWidget() && parent != q->parentWidget())
q->parentWidget()->d_func()->invalidateBuffer(effectiveRectFor(q->geometry()));
WId old_winid = data.winid;
// hide and reparent our own window away. Otherwise we might get
// destroyed when emitting the child remove event below. See QWorkspace.
if (q->isVisible() && data.winid) {
ShowWindow(data.winid, SW_HIDE);
SetParent(data.winid, 0);
}
bool dropSiteWasRegistered = false;
if (q->testAttribute(Qt::WA_DropSiteRegistered)) {
dropSiteWasRegistered = true;
q->setAttribute(Qt::WA_DropSiteRegistered, false); // ole dnd unregister (we will register again below)
}
if ((q->windowType() == Qt::Desktop))
old_winid = 0;
setWinId(0);
QObjectPrivate::setParent_helper(parent);
bool explicitlyHidden = q->testAttribute(Qt::WA_WState_Hidden) && q->testAttribute(Qt::WA_WState_ExplicitShowHide);
data.window_flags = f;
data.fstrut_dirty = true;
q->setAttribute(Qt::WA_WState_Created, false);
q->setAttribute(Qt::WA_WState_Visible, false);
q->setAttribute(Qt::WA_WState_Hidden, false);
adjustFlags(data.window_flags, q);
// keep compatibility with previous versions, we need to preserve the created state
// (but we recreate the winId for the widget being reparented, again for compatibility)
if (wasCreated || (!q->isWindow() && parent->testAttribute(Qt::WA_WState_Created)))
createWinId();
if (q->isWindow() || (!parent || parent->isVisible()) || explicitlyHidden)
q->setAttribute(Qt::WA_WState_Hidden);
q->setAttribute(Qt::WA_WState_ExplicitShowHide, explicitlyHidden);
if (wasCreated) {
reparentChildren();
}
if (extra && !extra->mask.isEmpty()) {
QRegion r = extra->mask;
extra->mask = QRegion();
q->setMask(r);
}
if (extra && extra->topextra && !extra->topextra->caption.isEmpty()) {
setWindowIcon_sys(true);
setWindowTitle_helper(extra->topextra->caption);
}
if (old_winid)
DestroyWindow(old_winid);
if (q->testAttribute(Qt::WA_AcceptDrops) || dropSiteWasRegistered
|| (!q->isWindow() && q->parentWidget() && q->parentWidget()->testAttribute(Qt::WA_DropSiteRegistered)))
q->setAttribute(Qt::WA_DropSiteRegistered, true);
#ifdef Q_WS_WINCE
// Show borderless toplevel windows in tasklist & NavBar
if (!parent) {
QString txt = q->windowTitle().isEmpty()?qAppName():q->windowTitle();
SetWindowText(q->internalWinId(), (wchar_t*)txt.utf16());
}
#endif
invalidateBuffer(q->rect());
}
QPoint QWidget::mapToGlobal(const QPoint &pos) const
{
Q_D(const QWidget);
QWidget *parentWindow = window();
QWExtra *extra = parentWindow->d_func()->extra;
if (!isVisible() || parentWindow->isMinimized() || !testAttribute(Qt::WA_WState_Created) || !internalWinId()
|| (extra
#ifndef QT_NO_GRAPHICSVIEW
&& extra->proxyWidget
#endif //QT_NO_GRAPHICSVIEW
)) {
if (extra && extra->topextra && extra->topextra->embedded) {
QPoint pt = mapTo(parentWindow, pos);
POINT p = {pt.x(), pt.y()};
ClientToScreen(parentWindow->effectiveWinId(), &p);
return QPoint(p.x, p.y);
} else {
QPoint toGlobal = mapTo(parentWindow, pos) + parentWindow->pos();
// Adjust for window decorations
toGlobal += parentWindow->geometry().topLeft() - parentWindow->frameGeometry().topLeft();
return toGlobal;
}
}
POINT p;
QPoint tmp = d->mapToWS(pos);
p.x = tmp.x();
p.y = tmp.y();
ClientToScreen(internalWinId(), &p);
return QPoint(p.x, p.y);
}
QPoint QWidget::mapFromGlobal(const QPoint &pos) const
{
Q_D(const QWidget);
QWidget *parentWindow = window();
QWExtra *extra = parentWindow->d_func()->extra;
if (!isVisible() || parentWindow->isMinimized() || !testAttribute(Qt::WA_WState_Created) || !internalWinId()
|| (extra
#ifndef QT_NO_GRAPHICSVIEW
&& extra->proxyWidget
#endif //QT_NO_GRAPHICSVIEW
)) {
if (extra && extra->topextra && extra->topextra->embedded) {
POINT p = {pos.x(), pos.y()};
ScreenToClient(parentWindow->effectiveWinId(), &p);
return mapFrom(parentWindow, QPoint(p.x, p.y));
} else {
QPoint fromGlobal = mapFrom(parentWindow, pos - parentWindow->pos());
// Adjust for window decorations
fromGlobal -= parentWindow->geometry().topLeft() - parentWindow->frameGeometry().topLeft();
return fromGlobal;
}
}
POINT p;
p.x = pos.x();
p.y = pos.y();
ScreenToClient(internalWinId(), &p);
return d->mapFromWS(QPoint(p.x, p.y));
}
void QWidgetPrivate::updateSystemBackground() {}
#ifndef QT_NO_CURSOR
void QWidgetPrivate::setCursor_sys(const QCursor &cursor)
{
Q_UNUSED(cursor);
Q_Q(QWidget);
qt_win_set_cursor(q, false);
}
void QWidgetPrivate::unsetCursor_sys()
{
Q_Q(QWidget);
qt_win_set_cursor(q, false);
}
#endif
void QWidgetPrivate::setWindowTitle_sys(const QString &caption)
{
Q_Q(QWidget);
if (!q->isWindow())
return;
Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
SetWindowText(q->internalWinId(), (wchar_t*)caption.utf16());
}
HICON qt_createIcon(QIcon icon, int xSize, int ySize, QPixmap **cache)
{
HICON result = 0;
if (!icon.isNull()) { // valid icon
QSize size = icon.actualSize(QSize(xSize, ySize));
QPixmap pm = icon.pixmap(size);
if (pm.isNull())
return 0;
result = pm.toWinHICON();
if (cache) {
delete *cache;
*cache = new QPixmap(pm);;
}
}
return result;
}
void QWidgetPrivate::setWindowIcon_sys(bool forceReset)
{
Q_Q(QWidget);
if (!q->testAttribute(Qt::WA_WState_Created) || !q->isWindow())
return;
QTLWExtra* x = topData();
if (x->iconPixmap && !forceReset)
// already been set
return;
if (x->winIconBig) {
DestroyIcon(x->winIconBig);
x->winIconBig = 0;
}
if (x->winIconSmall) {
DestroyIcon(x->winIconSmall);
x->winIconSmall = 0;
}
x->winIconSmall = qt_createIcon(q->windowIcon(),
GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON),
&(x->iconPixmap));
x->winIconBig = qt_createIcon(q->windowIcon(),
GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON),
&(x->iconPixmap));
if (x->winIconBig) {
SendMessage(q->internalWinId(), WM_SETICON, 0 /* ICON_SMALL */, (LPARAM)x->winIconSmall);
SendMessage(q->internalWinId(), WM_SETICON, 1 /* ICON_BIG */, (LPARAM)x->winIconBig);
} else {
SendMessage(q->internalWinId(), WM_SETICON, 0 /* ICON_SMALL */, (LPARAM)x->winIconSmall);
SendMessage(q->internalWinId(), WM_SETICON, 1 /* ICON_BIG */, (LPARAM)x->winIconSmall);
}
}
void QWidgetPrivate::setWindowIconText_sys(const QString &iconText)
{
Q_UNUSED(iconText);
}
QCursor *qt_grab_cursor()
{
return mouseGrbCur;
}
// The procedure does nothing, but is required for mousegrabbing to work
#ifndef Q_WS_WINCE
LRESULT QT_WIN_CALLBACK qJournalRecordProc(int nCode, WPARAM wParam, LPARAM lParam)
{
return CallNextHookEx(journalRec, nCode, wParam, lParam);
}
#endif //Q_WS_WINCE
/* Works only as long as pointer is inside the application's window,
which is good enough for QDockWidget.
Doesn't call SetWindowsHookEx() - this function causes a system-wide
freeze if any other app on the system installs a hook and fails to
process events. */
void QWidgetPrivate::grabMouseWhileInWindow()
{
Q_Q(QWidget);
if (!qt_nograb()) {
if (mouseGrb)
mouseGrb->releaseMouse();
Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
SetCapture(q->effectiveWinId());
mouseGrb = q;
#ifndef QT_NO_CURSOR
mouseGrbCur = new QCursor(mouseGrb->cursor());
#endif
}
}
#ifndef Q_WS_WINCE
void QWidget::grabMouse()
{
if (!qt_nograb()) {
if (mouseGrb)
mouseGrb->releaseMouse();
journalRec = SetWindowsHookEx(WH_JOURNALRECORD, (HOOKPROC)qJournalRecordProc, GetModuleHandle(0), 0);
Q_ASSERT(testAttribute(Qt::WA_WState_Created));
SetCapture(effectiveWinId());
mouseGrb = this;
#ifndef QT_NO_CURSOR
mouseGrbCur = new QCursor(mouseGrb->cursor());
#endif
}
}
#ifndef QT_NO_CURSOR
void QWidget::grabMouse(const QCursor &cursor)
{
if (!qt_nograb()) {
if (mouseGrb)
mouseGrb->releaseMouse();
journalRec = SetWindowsHookEx(WH_JOURNALRECORD, (HOOKPROC)qJournalRecordProc, GetModuleHandle(0), 0);
Q_ASSERT(testAttribute(Qt::WA_WState_Created));
SetCapture(effectiveWinId());
mouseGrbCur = new QCursor(cursor);
SetCursor(mouseGrbCur->handle());
mouseGrb = this;
}
}
#endif
void QWidget::releaseMouse()
{
if (!qt_nograb() && mouseGrb == this) {
ReleaseCapture();
if (journalRec) {
UnhookWindowsHookEx(journalRec);
journalRec = 0;
}
if (mouseGrbCur) {
delete mouseGrbCur;
mouseGrbCur = 0;
}
mouseGrb = 0;
}
}
#endif
void QWidget::grabKeyboard()
{
if (!qt_nograb()) {
if (keyboardGrb)
keyboardGrb->releaseKeyboard();
keyboardGrb = this;
}
}
void QWidget::releaseKeyboard()
{
if (!qt_nograb() && keyboardGrb == this)
keyboardGrb = 0;
}
QWidget *QWidget::mouseGrabber()
{
return mouseGrb;
}
QWidget *QWidget::keyboardGrabber()
{
return keyboardGrb;
}
void QWidget::activateWindow()
{
window()->createWinId();
SetForegroundWindow(window()->internalWinId());
}
#ifndef Q_WS_WINCE
void QWidget::setWindowState(Qt::WindowStates newstate)
{
Q_D(QWidget);
Qt::WindowStates oldstate = windowState();
if (oldstate == newstate)
return;
int max = SW_MAXIMIZE;
int min = SW_MINIMIZE;
int normal = SW_SHOWNOACTIVATE;
if (newstate & Qt::WindowActive) {
max = SW_SHOWMAXIMIZED;
min = SW_SHOWMINIMIZED;
normal = SW_SHOWNORMAL;
}
if (isWindow()) {
createWinId();
Q_ASSERT(testAttribute(Qt::WA_WState_Created));
// Ensure the initial size is valid, since we store it as normalGeometry below.
if (!testAttribute(Qt::WA_Resized) && !isVisible())
adjustSize();
if ((oldstate & Qt::WindowMaximized) != (newstate & Qt::WindowMaximized)) {
if (newstate & Qt::WindowMaximized && !(oldstate & Qt::WindowFullScreen))
d->topData()->normalGeometry = geometry();
if (isVisible() && !(newstate & Qt::WindowMinimized)) {
ShowWindow(internalWinId(), (newstate & Qt::WindowMaximized) ? max : normal);
if (!(newstate & Qt::WindowFullScreen)) {
QRect r = d->topData()->normalGeometry;
if (!(newstate & Qt::WindowMaximized) && r.width() >= 0) {
if (pos() != r.topLeft() || size() !=r.size()) {
d->topData()->normalGeometry = QRect(0,0,-1,-1);
setGeometry(r);
}
}
} else {
d->updateFrameStrut();
}
}
}
if ((oldstate & Qt::WindowFullScreen) != (newstate & Qt::WindowFullScreen)) {
if (newstate & Qt::WindowFullScreen) {
if (d->topData()->normalGeometry.width() < 0 && !(oldstate & Qt::WindowMaximized))
d->topData()->normalGeometry = geometry();
d->topData()->savedFlags = Qt::WindowFlags(GetWindowLong(internalWinId(), GWL_STYLE));
#ifndef Q_FLATTEN_EXPOSE
UINT style = WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_POPUP;
#else
UINT style = WS_POPUP;
#endif
if (ulong(d->topData()->savedFlags) & WS_SYSMENU)
style |= WS_SYSMENU;
if (isVisible())
style |= WS_VISIBLE;
SetWindowLong(internalWinId(), GWL_STYLE, style);
QRect r = QApplication::desktop()->screenGeometry(this);
UINT swpf = SWP_FRAMECHANGED;
if (newstate & Qt::WindowActive)
swpf |= SWP_NOACTIVATE;
SetWindowPos(internalWinId(), HWND_TOP, r.left(), r.top(), r.width(), r.height(), swpf);
d->updateFrameStrut();
} else {
UINT style = d->topData()->savedFlags;
if (isVisible())
style |= WS_VISIBLE;
SetWindowLong(internalWinId(), GWL_STYLE, style);
UINT swpf = SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE;
if (newstate & Qt::WindowActive)
swpf |= SWP_NOACTIVATE;
SetWindowPos(internalWinId(), 0, 0, 0, 0, 0, swpf);
d->updateFrameStrut();
// preserve maximized state
if (isVisible())
ShowWindow(internalWinId(), (newstate & Qt::WindowMaximized) ? max : normal);
if (!(newstate & Qt::WindowMaximized)) {
QRect r = d->topData()->normalGeometry;
d->topData()->normalGeometry = QRect(0,0,-1,-1);
if (r.isValid())
setGeometry(r);
}
}
}
if ((oldstate & Qt::WindowMinimized) != (newstate & Qt::WindowMinimized)) {
if (isVisible())
ShowWindow(internalWinId(), (newstate & Qt::WindowMinimized) ? min :
(newstate & Qt::WindowMaximized) ? max : normal);
}
}
data->window_state = newstate;
QWindowStateChangeEvent e(oldstate);
QApplication::sendEvent(this, &e);
}
#endif //Q_WS_WINCE
/*
\internal
Platform-specific part of QWidget::hide().
*/
void QWidgetPrivate::hide_sys()
{
Q_Q(QWidget);
deactivateWidgetCleanup();
Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
#ifdef Q_WS_WINCE
if (!qt_wince_is_mobile() && q->isFullScreen()) {
HWND handle = FindWindow(L"HHTaskBar", L"");
if (handle) {
ShowWindow(handle, 1);
EnableWindow(handle, true);
}
}
#endif
if (q->windowFlags() != Qt::Desktop) {
if ((q->windowFlags() & Qt::Popup) && q->internalWinId())
ShowWindow(q->internalWinId(), SW_HIDE);
else if (q->internalWinId())
SetWindowPos(q->internalWinId(),0, 0,0,0,0, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER);
}
if (q->isWindow()) {
if (QWidgetBackingStore *bs = maybeBackingStore())
bs->releaseBuffer();
} else {
invalidateBuffer(q->rect());
}
q->setAttribute(Qt::WA_Mapped, false);
}
/*
\internal
Platform-specific part of QWidget::show().
*/
#ifndef Q_WS_WINCE
void QWidgetPrivate::show_sys()
{
Q_Q(QWidget);
#if defined(QT_NON_COMMERCIAL)
QT_NC_SHOW_WINDOW
#endif
if (q->testAttribute(Qt::WA_OutsideWSRange))
return;
q->setAttribute(Qt::WA_Mapped);
Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
invalidateBuffer(q->rect());
return;
}
if (data.window_flags & Qt::Window) {
QTLWExtra *extra = topData();
if (!extra->hotkeyRegistered) {
// Try to set the hotkey using information from STARTUPINFO
STARTUPINFO startupInfo;
GetStartupInfo(&startupInfo);
// If STARTF_USEHOTKEY is set, hStdInput is the virtual keycode
if (startupInfo.dwFlags & 0x00000200) {
WPARAM hotKey = (WPARAM)startupInfo.hStdInput;
SendMessage(data.winid, WM_SETHOTKEY, hotKey, 0);
}
extra->hotkeyRegistered = 1;
}
}
int sm = SW_SHOWNORMAL;
bool fakedMaximize = false;
if (q->isWindow()) {
if (q->isMinimized()) {
sm = SW_SHOWMINIMIZED;
if (!IsWindowVisible(q->internalWinId()))
sm = SW_SHOWMINNOACTIVE;
} else if (q->isMaximized()) {
sm = SW_SHOWMAXIMIZED;
// Windows will not behave correctly when we try to maximize a window which does not
// have minimize nor maximize buttons in the window frame. Windows would then ignore
// non-available geometry, and rather maximize the widget to the full screen, minus the
// window frame (caption). So, we do a trick here, by adding a maximize button before
// maximizing the widget, and then remove the maximize button afterwards.
Qt::WindowFlags &flags = data.window_flags;
if (flags & Qt::WindowTitleHint &&
!(flags & (Qt::WindowMinMaxButtonsHint | Qt::FramelessWindowHint))) {
fakedMaximize = TRUE;
int style = GetWindowLong(q->internalWinId(), GWL_STYLE);
SetWindowLong(q->internalWinId(), GWL_STYLE, style | WS_MAXIMIZEBOX);
}
}
}
if (q->testAttribute(Qt::WA_ShowWithoutActivating)
|| (q->windowType() == Qt::Popup)
|| (q->windowType() == Qt::ToolTip)
|| (q->windowType() == Qt::Tool)) {
sm = SW_SHOWNOACTIVATE;
}
if (q->internalWinId())
ShowWindow(q->internalWinId(), sm);
if (fakedMaximize) {
int style = GetWindowLong(q->internalWinId(), GWL_STYLE);
SetWindowLong(q->internalWinId(), GWL_STYLE, style & ~WS_MAXIMIZEBOX);
SetWindowPos(q->internalWinId(), 0, 0, 0, 0, 0,
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER
| SWP_FRAMECHANGED);
}
if (q->internalWinId()) {
if (IsIconic(q->internalWinId()))
data.window_state |= Qt::WindowMinimized;
if (IsZoomed(q->internalWinId()))
data.window_state |= Qt::WindowMaximized;
// This is to resolve the problem where popups are opened from the
// system tray and not being implicitly activated
if (q->windowType() == Qt::Popup &&
!q->parentWidget() && !qApp->activeWindow())
q->activateWindow();
}
winSetupGestures();
invalidateBuffer(q->rect());
}
#endif //Q_WS_WINCE
void QWidgetPrivate::setFocus_sys()
{
Q_Q(QWidget);
if (q->testAttribute(Qt::WA_WState_Created) && q->window()->windowType() != Qt::Popup)
SetFocus(q->effectiveWinId());
}
void QWidgetPrivate::raise_sys()
{
Q_Q(QWidget);
Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
if (q->internalWinId())
SetWindowPos(q->internalWinId(), HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
}
void QWidgetPrivate::lower_sys()
{
Q_Q(QWidget);
Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
if (q->internalWinId())
SetWindowPos(q->internalWinId(), HWND_BOTTOM, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
invalidateBuffer(q->rect());
}
void QWidgetPrivate::stackUnder_sys(QWidget* w)
{
Q_Q(QWidget);
Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
if (q->internalWinId() && w->internalWinId())
SetWindowPos(q->internalWinId(), w->internalWinId() , 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
invalidateBuffer(q->rect());
}
/*
Helper function for non-toplevel widgets. Helps to map Qt's 32bit
coordinate system to Windpws's 16bit coordinate system.
This code is duplicated from the X11 code, so any changes there
should also (most likely) be reflected here.
(In all comments below: s/X/Windows/g)
*/
void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &)
{
Q_Q(QWidget);
Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
/*
There are up to four different coordinate systems here:
Qt coordinate system for this widget.
X coordinate system for this widget (relative to wrect).
Qt coordinate system for parent
X coordinate system for parent (relative to parent's wrect).
*/
QRect validRange(-XCOORD_MAX,-XCOORD_MAX, 2*XCOORD_MAX, 2*XCOORD_MAX);
QRect wrectRange(-WRECT_MAX,-WRECT_MAX, 2*WRECT_MAX, 2*WRECT_MAX);
QRect wrect;
//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)
QRect xrect = data.crect;
const QWidget *const parent = q->parentWidget();
QRect parentWRect = parent->data->wrect;
if (parentWRect.isValid()) {
// parent is clipped, and we have to clip to the same limit as parent
if (!parentWRect.contains(xrect)) {
xrect &= parentWRect;
wrect = xrect;
//translate from parent's to my Qt coord sys
wrect.translate(-data.crect.topLeft());
}
//translate from parent's Qt coords to parent's X coords
xrect.translate(-parentWRect.topLeft());
} else {
// parent is not clipped, we may or may not have to clip
if (data.wrect.isValid() && QRect(QPoint(),data.crect.size()).contains(data.wrect)) {
// This is where the main optimization is: we are already
// clipped, and if our clip is still valid, we can just
// move our window, and do not need to move or clip
// children
QRect vrect = xrect & parent->rect();
vrect.translate(-data.crect.topLeft()); //the part of me that's visible through parent, in my Qt coords
if (data.wrect.contains(vrect)) {
xrect = data.wrect;
xrect.translate(data.crect.topLeft());
if (q->internalWinId())
MoveWindow(q->internalWinId(), xrect.x(), xrect.y(), xrect.width(), xrect.height(), true);
return;
}
}
if (!validRange.contains(xrect)) {
// we are too big, and must clip
xrect &=wrectRange;
wrect = xrect;
wrect.translate(-data.crect.topLeft());
//parent's X coord system is equal to parent's Qt coord
//sys, so we don't need to map xrect.
}
}
// unmap if we are outside the valid window system coord system
bool outsideRange = !xrect.isValid();
bool mapWindow = false;
if (q->testAttribute(Qt::WA_OutsideWSRange) != outsideRange) {
q->setAttribute(Qt::WA_OutsideWSRange, outsideRange);
if (outsideRange) {
if (q->internalWinId())
ShowWindow(q->internalWinId(), SW_HIDE);
q->setAttribute(Qt::WA_Mapped, false);
} else if (!q->isHidden()) {
mapWindow = true;
}
}
if (outsideRange)
return;
bool jump = (data.wrect != wrect);
data.wrect = wrect;
// and now recursively for all children...
for (int i = 0; i < children.size(); ++i) {
QObject *object = children.at(i);
if (object->isWidgetType()) {
QWidget *w = static_cast<QWidget *>(object);
if (!w->isWindow() && w->testAttribute(Qt::WA_WState_Created))
w->d_func()->setWSGeometry();
}
}
// move ourselves to the new position and map (if necessary) after
// the movement. Rationale: moving unmapped windows is much faster
// than moving mapped windows
if (q->internalWinId()) {
if (!parent->internalWinId())
xrect.translate(parent->mapTo(q->nativeParentWidget(), QPoint(0, 0)));
MoveWindow(q->internalWinId(), xrect.x(), xrect.y(), xrect.width(), xrect.height(), !jump);
}
if (mapWindow && !dontShow) {
q->setAttribute(Qt::WA_Mapped);
if (q->internalWinId())
ShowWindow(q->internalWinId(), SW_SHOWNOACTIVATE);
}
if (jump && q->internalWinId())
InvalidateRect(q->internalWinId(), 0, false);
}
//
// The internal qWinRequestConfig, defined in qapplication_win.cpp, stores move,
// resize and setGeometry requests for a widget that is already
// processing a config event. The purpose is to avoid recursion.
//
void qWinRequestConfig(WId, int, int, int, int, int);
void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
{
Q_Q(QWidget);
Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
if (extra) { // any size restrictions?
w = qMin(w,extra->maxw);
h = qMin(h,extra->maxh);
w = qMax(w,extra->minw);
h = qMax(h,extra->minh);
}
if (q->isWindow())
topData()->normalGeometry = QRect(0, 0, -1, -1);
QSize oldSize(q->size());
QPoint oldPos(q->pos());
if (!q->isWindow())
isMove = (data.crect.topLeft() != QPoint(x, y));
bool isResize = w != oldSize.width() || h != oldSize.height();
if (!isMove && !isResize)
return;
if (isResize && !q->testAttribute(Qt::WA_StaticContents) && q->internalWinId())
ValidateRgn(q->internalWinId(), 0);
#ifdef Q_WS_WINCE
// On Windows CE we can't just fiddle around with the window state.
// Too much magic in setWindowState.
if (isResize && q->isMaximized())
q->setWindowState(q->windowState() & ~Qt::WindowMaximized);
#else
if (isResize)
data.window_state &= ~Qt::WindowMaximized;
#endif
if (data.window_state & Qt::WindowFullScreen) {
QTLWExtra *top = topData();
if (q->isWindow()) {
// We need to update these flags when we remove the full screen state
// or the frame will not be updated
UINT style = top->savedFlags;
if (q->isVisible())
style |= WS_VISIBLE;
SetWindowLong(q->internalWinId(), GWL_STYLE, style);
UINT swpf = SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE;
if (data.window_state & Qt::WindowActive)
swpf |= SWP_NOACTIVATE;
SetWindowPos(q->internalWinId(), 0, 0, 0, 0, 0, swpf);
updateFrameStrut();
}
data.window_state &= ~Qt::WindowFullScreen;
topData()->savedFlags = 0;
}
QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
const bool inTopLevelResize = tlwExtra ? tlwExtra->inTopLevelResize : false;
const bool isTranslucentWindow = !isOpaque && ptrUpdateLayeredWindowIndirect && (data.window_flags & Qt::FramelessWindowHint)
&& GetWindowLong(q->internalWinId(), GWL_EXSTYLE) & Q_WS_EX_LAYERED;
if (q->testAttribute(Qt::WA_WState_ConfigPending)) { // processing config event
if (q->internalWinId())
qWinRequestConfig(q->internalWinId(), isMove ? 2 : 1, x, y, w, h);
} else {
if (!q->testAttribute(Qt::WA_DontShowOnScreen))
q->setAttribute(Qt::WA_WState_ConfigPending);
if (q->windowType() == Qt::Desktop) {
data.crect.setRect(x, y, w, h);
} else if (q->isWindow()) {
QRect fs(frameStrut());
if (extra) {
fs.setLeft(x - fs.left());
fs.setTop(y - fs.top());
fs.setRight((x + w - 1) + fs.right());
fs.setBottom((y + h - 1) + fs.bottom());
}
if (w == 0 || h == 0) {
q->setAttribute(Qt::WA_OutsideWSRange, true);
if (q->isVisible() && q->testAttribute(Qt::WA_Mapped))
hide_sys();
data.crect = QRect(x, y, w, h);
} else if (q->isVisible() && q->testAttribute(Qt::WA_OutsideWSRange)) {
q->setAttribute(Qt::WA_OutsideWSRange, false);
// put the window in its place and show it
MoveWindow(q->internalWinId(), fs.x(), fs.y(), fs.width(), fs.height(), true);
RECT rect;
if (!q->testAttribute(Qt::WA_DontShowOnScreen)) {
GetClientRect(q->internalWinId(), &rect);
data.crect.setRect(x, y, rect.right - rect.left, rect.bottom - rect.top);
} else {
data.crect.setRect(x, y, w, h);
}
show_sys();
} else if (!q->testAttribute(Qt::WA_DontShowOnScreen)) {
q->setAttribute(Qt::WA_OutsideWSRange, false);
#ifndef Q_WS_WINCE
// If the window is hidden and in maximized state or minimized, instead of moving the
// window, set the normal position of the window.
WINDOWPLACEMENT wndpl;
GetWindowPlacement(q->internalWinId(), &wndpl);
if ((wndpl.showCmd == SW_MAXIMIZE && !IsWindowVisible(q->internalWinId())) || wndpl.showCmd == SW_SHOWMINIMIZED) {
RECT normal = {fs.x(), fs.y(), fs.x()+fs.width(), fs.y()+fs.height()};
wndpl.rcNormalPosition = normal;
wndpl.showCmd = wndpl.showCmd == SW_SHOWMINIMIZED ? SW_SHOWMINIMIZED : SW_HIDE;
SetWindowPlacement(q->internalWinId(), &wndpl);
} else {
#else
if (data.window_state & Qt::WindowMaximized) {
qt_wince_maximize(q);
} else {
#endif
MoveWindow(q->internalWinId(), fs.x(), fs.y(), fs.width(), fs.height(), true);
}
if (!q->isVisible())
InvalidateRect(q->internalWinId(), 0, FALSE);
RECT rect;
// If the layout has heightForWidth, the MoveWindow() above can
// change the size/position, so refresh them.
if (isTranslucentWindow) {
data.crect.setRect(x, y, w, h);
} else {
GetClientRect(q->internalWinId(), &rect);
RECT rcNormalPosition ={0};
// Use (0,0) as window position for embedded ActiveQt controls.
if (!tlwExtra || !tlwExtra->embedded)
GetWindowRect(q->internalWinId(), &rcNormalPosition);
QRect fStrut(frameStrut());
data.crect.setRect(rcNormalPosition.left + fStrut.left(),
rcNormalPosition.top + fStrut.top(),
rect.right - rect.left,
rect.bottom - rect.top);
isResize = data.crect.size() != oldSize;
}
} else {
q->setAttribute(Qt::WA_OutsideWSRange, false);
data.crect.setRect(x, y, w, h);
}
} else {
QRect oldGeom(data.crect);
data.crect.setRect(x, y, w, h);
if (q->isVisible() && (!inTopLevelResize || q->internalWinId())) {
// Top-level resize optimization does not work for native child widgets;
// disable it for this particular widget.
if (inTopLevelResize)
tlwExtra->inTopLevelResize = false;
if (!isResize)
moveRect(QRect(oldPos, oldSize), x - oldPos.x(), y - oldPos.y());
else
invalidateBuffer_resizeHelper(oldPos, oldSize);
if (inTopLevelResize)
tlwExtra->inTopLevelResize = true;
}
if (q->testAttribute(Qt::WA_WState_Created))
setWSGeometry();
}
q->setAttribute(Qt::WA_WState_ConfigPending, false);
}
if (q->isWindow() && q->isVisible() && isResize && !inTopLevelResize) {
invalidateBuffer(q->rect()); //after the resize
}
// Process events immediately rather than in translateConfigEvent to
// avoid windows message process delay.
if (q->isVisible()) {
if (isMove && q->pos() != oldPos) {
QMoveEvent e(q->pos(), oldPos);
QApplication::sendEvent(q, &e);
}
if (isResize) {
static bool slowResize = qgetenv("QT_SLOW_TOPLEVEL_RESIZE").toInt();
// If we have a backing store with static contents, we have to disable the top-level
// resize optimization in order to get invalidated regions for resized widgets.
// The optimization discards all invalidateBuffer() calls since we're going to
// repaint everything anyways, but that's not the case with static contents.
const bool setTopLevelResize = !slowResize && q->isWindow() && extra && extra->topextra
&& !extra->topextra->inTopLevelResize
&& (!extra->topextra->backingStore
|| !extra->topextra->backingStore->hasStaticContents());
if (setTopLevelResize)
extra->topextra->inTopLevelResize = true;
QResizeEvent e(q->size(), oldSize);
QApplication::sendEvent(q, &e);
if (setTopLevelResize)
extra->topextra->inTopLevelResize = false;
}
} else {
if (isMove && q->pos() != oldPos)
q->setAttribute(Qt::WA_PendingMoveEvent, true);
if (isResize)
q->setAttribute(Qt::WA_PendingResizeEvent, true);
}
}
bool QWidgetPrivate::shouldShowMaximizeButton()
{
if (data.window_flags & Qt::MSWindowsFixedSizeDialogHint)
return false;
// if the user explicitely asked for the maximize button, we try to add
// it even if the window has fixed size.
if (data.window_flags & Qt::CustomizeWindowHint &&
data.window_flags & Qt::WindowMaximizeButtonHint)
return true;
if (extra) {
if ((extra->maxw && extra->maxw != QWIDGETSIZE_MAX && extra->maxw != QLAYOUTSIZE_MAX)
|| (extra->maxh && extra->maxh != QWIDGETSIZE_MAX && extra->maxh != QLAYOUTSIZE_MAX))
return false;
}
return data.window_flags & Qt::WindowMaximizeButtonHint;
}
void QWidgetPrivate::winUpdateIsOpaque()
{
#ifndef Q_WS_WINCE
Q_Q(QWidget);
if (!q->isWindow() || !q->testAttribute(Qt::WA_TranslucentBackground))
return;
if ((data.window_flags & Qt::FramelessWindowHint) == 0)
return;
if (!isOpaque && ptrUpdateLayeredWindowIndirect) {
SetWindowLong(q->internalWinId(), GWL_EXSTYLE,
GetWindowLong(q->internalWinId(), GWL_EXSTYLE) | Q_WS_EX_LAYERED);
} else {
SetWindowLong(q->internalWinId(), GWL_EXSTYLE,
GetWindowLong(q->internalWinId(), GWL_EXSTYLE) & ~Q_WS_EX_LAYERED);
}
#endif
}
void QWidgetPrivate::setConstraints_sys()
{
#ifndef Q_WS_WINCE_WM
Q_Q(QWidget);
if (q->isWindow() && q->testAttribute(Qt::WA_WState_Created)) {
int style = GetWindowLong(q->internalWinId(), GWL_STYLE);
if (shouldShowMaximizeButton())
style |= WS_MAXIMIZEBOX;
else
style &= ~WS_MAXIMIZEBOX;
SetWindowLong(q->internalWinId(), GWL_STYLE, style);
}
#endif
}
void QWidgetPrivate::scroll_sys(int dx, int dy)
{
Q_Q(QWidget);
scrollChildren(dx, dy);
if (!paintOnScreen()) {
scrollRect(q->rect(), dx, dy);
} else {
UINT flags = SW_INVALIDATE;
if (!q->testAttribute(Qt::WA_OpaquePaintEvent))
flags |= SW_ERASE;
Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
ScrollWindowEx(q->internalWinId(), dx, dy, 0, 0, 0, 0, flags);
UpdateWindow(q->internalWinId());
}
}
void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r)
{
Q_Q(QWidget);
if (!paintOnScreen()) {
scrollRect(r, dx, dy);
} else {
RECT wr;
wr.top = r.top();
wr.left = r.left();
wr.bottom = r.bottom()+1;
wr.right = r.right()+1;
UINT flags = SW_INVALIDATE;
if (!q->testAttribute(Qt::WA_OpaquePaintEvent))
flags |= SW_ERASE;
Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
ScrollWindowEx(q->internalWinId(), dx, dy, &wr, &wr, 0, 0, flags);
UpdateWindow(q->internalWinId());
}
}
extern Q_GUI_EXPORT HDC qt_win_display_dc();
int QWidget::metric(PaintDeviceMetric m) const
{
Q_D(const QWidget);
int val;
if (m == PdmWidth) {
val = data->crect.width();
} else if (m == PdmHeight) {
val = data->crect.height();
} else {
HDC gdc = qt_win_display_dc();
switch (m) {
case PdmDpiX:
case PdmPhysicalDpiX:
if (d->extra && d->extra->customDpiX)
val = d->extra->customDpiX;
else if (d->parent)
val = static_cast<QWidget *>(d->parent)->metric(m);
else
val = GetDeviceCaps(gdc, LOGPIXELSX);
break;
case PdmDpiY:
case PdmPhysicalDpiY:
if (d->extra && d->extra->customDpiY)
val = d->extra->customDpiY;
else if (d->parent)
val = static_cast<QWidget *>(d->parent)->metric(m);
else
val = GetDeviceCaps(gdc, LOGPIXELSY);
break;
case PdmWidthMM:
val = data->crect.width()
* GetDeviceCaps(gdc, HORZSIZE)
/ GetDeviceCaps(gdc, HORZRES);
break;
case PdmHeightMM:
val = data->crect.height()
* GetDeviceCaps(gdc, VERTSIZE)
/ GetDeviceCaps(gdc, VERTRES);
break;
case PdmNumColors:
if (GetDeviceCaps(gdc, RASTERCAPS) & RC_PALETTE)
val = GetDeviceCaps(gdc, SIZEPALETTE);
else {
HDC hd = d->hd ? HDC(d->hd) : gdc;
int bpp = GetDeviceCaps(hd, BITSPIXEL);
if (bpp == 32)
val = INT_MAX; // ### this is bogus, it should be 2^24 colors for 32 bit as well
else if(bpp<=8)
val = GetDeviceCaps(hd, NUMCOLORS);
else
val = 1 << (bpp * GetDeviceCaps(hd, PLANES));
}
break;
case PdmDepth:
val = GetDeviceCaps(gdc, BITSPIXEL);
break;
default:
val = 0;
qWarning("QWidget::metric: Invalid metric command");
}
}
return val;
}
void QWidgetPrivate::createSysExtra()
{
#ifndef QT_NO_DRAGANDDROP
extra->dropTarget = 0;
#endif
}
#ifndef Q_WS_WINCE
void QWidgetPrivate::deleteSysExtra()
{
}
#endif //Q_WS_WINCE
void QWidgetPrivate::createTLSysExtra()
{
extra->topextra->hotkeyRegistered = 0;
extra->topextra->savedFlags = 0;
extra->topextra->winIconBig = 0;
extra->topextra->winIconSmall = 0;
}
void QWidgetPrivate::deleteTLSysExtra()
{
if (extra->topextra->winIconSmall)
DestroyIcon(extra->topextra->winIconSmall);
if (extra->topextra->winIconBig)
DestroyIcon(extra->topextra->winIconBig);
}
void QWidgetPrivate::registerDropSite(bool on)
{
Q_Q(QWidget);
if (!q->testAttribute(Qt::WA_WState_Created))
return;
// Enablement is defined by d->extra->dropTarget != 0.
if (on) {
// Turn on.
createExtra();
#ifndef QT_NO_DRAGANDDROP
if (!q->internalWinId())
q->nativeParentWidget()->d_func()->createExtra();
QWExtra *extra = extraData();
if (!extra->dropTarget)
extra->dropTarget = registerOleDnd(q);
#endif
} else {
// Turn off.
QWExtra *extra = extraData();
#ifndef QT_NO_DRAGANDDROP
if (extra && extra->dropTarget) {
unregisterOleDnd(q, extra->dropTarget);
extra->dropTarget = 0;
}
#endif
}
}
#ifndef QT_NO_DRAGANDDROP
QOleDropTarget* QWidgetPrivate::registerOleDnd(QWidget *widget)
{
QOleDropTarget *dropTarget = new QOleDropTarget(widget);
Q_ASSERT(widget->testAttribute(Qt::WA_WState_Created));
if (!widget->internalWinId()) {
QWidget *nativeParent = widget->nativeParentWidget();
Q_ASSERT(nativeParent);
QWExtra *nativeExtra = nativeParent->d_func()->extra;
Q_ASSERT(nativeExtra);
if (!nativeParent->acceptDrops())
nativeParent->setAcceptDrops(true);
if (!nativeExtra->oleDropWidgets.contains(widget))
nativeExtra->oleDropWidgets.append(widget);
if (!nativeExtra->dropTarget) {
nativeExtra->dropTarget = registerOleDnd(nativeParent);
Q_ASSERT(nativeExtra->dropTarget);
#ifndef Q_OS_WINCE
CoLockObjectExternal(nativeExtra->dropTarget, false, true);
#endif
RegisterDragDrop(nativeParent->internalWinId(), nativeExtra->dropTarget);
}
} else {
RegisterDragDrop(widget->internalWinId(), dropTarget);
#ifndef Q_OS_WINCE
CoLockObjectExternal(dropTarget, true, true);
#endif
}
return dropTarget;
}
void QWidgetPrivate::unregisterOleDnd(QWidget *widget, QOleDropTarget *dropTarget)
{
dropTarget->releaseQt();
dropTarget->Release();
Q_ASSERT(widget->testAttribute(Qt::WA_WState_Created));
if (!widget->internalWinId()) {
QWidget *nativeParent = widget->nativeParentWidget();
Q_ASSERT(nativeParent);
QWExtra *nativeExtra = nativeParent->d_func()->extra;
Q_ASSERT(nativeExtra);
nativeExtra->oleDropWidgets.removeAll(widget);
nativeExtra->oleDropWidgets.removeAll(static_cast<QWidget *>(0));
if (nativeExtra->oleDropWidgets.isEmpty() && nativeExtra->dropTarget
&& !nativeParent->testAttribute(Qt::WA_DropSiteRegistered)) {
#ifndef Q_OS_WINCE
CoLockObjectExternal(nativeExtra->dropTarget, false, true);
#endif
RevokeDragDrop(nativeParent->internalWinId());
nativeExtra->dropTarget = 0;
}
} else {
#ifndef Q_OS_WINCE
CoLockObjectExternal(dropTarget, false, true);
#endif
RevokeDragDrop(widget->internalWinId());
}
}
#endif //QT_NO_DRAGANDDROP
// from qregion_win.cpp
extern HRGN qt_tryCreateRegion(QRegion::RegionType type, int left, int top, int right, int bottom);
void QWidgetPrivate::setMask_sys(const QRegion ®ion)
{
Q_Q(QWidget);
if (!q->internalWinId())
return;
if (region.isEmpty()) {
SetWindowRgn(q->internalWinId(), 0, true);
return;
}
// Since SetWindowRegion takes ownership, and we need to translate,
// we take a copy.
HRGN wr = qt_tryCreateRegion(QRegion::Rectangle, 0,0,0,0);
CombineRgn(wr, region.handle(), 0, RGN_COPY);
QPoint offset = (q->isWindow()
? frameStrut().topLeft()
: QPoint(0, 0));
OffsetRgn(wr, offset.x(), offset.y());
Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
if (!SetWindowRgn(data.winid, wr, true))
DeleteObject(wr);
}
void QWidgetPrivate::updateFrameStrut()
{
Q_Q(QWidget);
if (!q->testAttribute(Qt::WA_WState_Created))
return;
if (!q->internalWinId()) {
data.fstrut_dirty = false;
return;
}
RECT rect = {0,0,0,0};
QTLWExtra *top = topData();
uint exstyle = GetWindowLong(q->internalWinId(), GWL_EXSTYLE);
uint style = GetWindowLong(q->internalWinId(), GWL_STYLE);
#ifndef Q_WS_WINCE
if (AdjustWindowRectEx(&rect, style & ~(WS_OVERLAPPED), FALSE, exstyle)) {
#else
if (AdjustWindowRectEx(&rect, style, FALSE, exstyle)) {
#endif
top->frameStrut.setCoords(-rect.left, -rect.top, rect.right, rect.bottom);
data.fstrut_dirty = false;
}
}
#ifndef Q_WS_WINCE
void QWidgetPrivate::setWindowOpacity_sys(qreal level)
{
Q_Q(QWidget);
if (!isOpaque && ptrUpdateLayeredWindow && (data.window_flags & Qt::FramelessWindowHint)) {
if (GetWindowLong(q->internalWinId(), GWL_EXSTYLE) & Q_WS_EX_LAYERED) {
BLENDFUNCTION blend = {AC_SRC_OVER, 0, (int)(255.0 * level), AC_SRC_ALPHA};
ptrUpdateLayeredWindow(q->internalWinId(), NULL, NULL, NULL, NULL, NULL, 0, &blend, Q_ULW_ALPHA);
}
return;
}
static bool function_resolved = false;
if (!function_resolved) {
ptrSetLayeredWindowAttributes =
(PtrSetLayeredWindowAttributes) QLibrary::resolve(QLatin1String("user32"),
"SetLayeredWindowAttributes");
function_resolved = true;
}
if (!ptrSetLayeredWindowAttributes)
return;
int wl = GetWindowLong(q->internalWinId(), GWL_EXSTYLE);
if (level != 1.0) {
if ((wl&Q_WS_EX_LAYERED) == 0)
SetWindowLong(q->internalWinId(), GWL_EXSTYLE, wl | Q_WS_EX_LAYERED);
} else if (wl&Q_WS_EX_LAYERED) {
SetWindowLong(q->internalWinId(), GWL_EXSTYLE, wl & ~Q_WS_EX_LAYERED);
}
ptrSetLayeredWindowAttributes(q->internalWinId(), 0, (int)(level * 255), Q_LWA_ALPHA);
}
#endif //Q_WS_WINCE
// class QGlobalRasterPaintEngine: public QRasterPaintEngine
// {
// public:
// inline QGlobalRasterPaintEngine() : QRasterPaintEngine() { setFlushOnEnd(false); }
// };
// Q_GLOBAL_STATIC(QGlobalRasterPaintEngine, globalRasterPaintEngine)
#ifndef QT_NO_DIRECTDRAW
static uchar *qt_primary_surface_bits;
static int qt_primary_surface_stride;
static QImage::Format qt_primary_surface_format;
void qt_win_initialize_directdraw()
{
HRESULT res;
// Some initialization...
if (!qt_ddraw_object) {
res = DirectDrawCreate(0, &qt_ddraw_object, 0);
if (res != DD_OK)
qWarning("DirectDrawCreate failed: %d", res);
qt_ddraw_object->SetCooperativeLevel(0, DDSCL_NORMAL);
DDSURFACEDESC surfaceDesc;
memset(&surfaceDesc, 0, sizeof(DDSURFACEDESC));
surfaceDesc.dwSize = sizeof(DDSURFACEDESC);
surfaceDesc.dwFlags = DDSD_CAPS;
surfaceDesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
res = qt_ddraw_object->CreateSurface(&surfaceDesc, &qt_ddraw_primary, 0);
if (res != DD_OK)
qWarning("CreateSurface failed: %d", res);
memset(&surfaceDesc, 0, sizeof(DDSURFACEDESC));
surfaceDesc.dwSize = sizeof(DDSURFACEDESC);
res = qt_ddraw_primary->Lock(0, &surfaceDesc, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, 0);
if (res != DD_OK)
qWarning("Locking surface failed: %d", res);
if (surfaceDesc.ddpfPixelFormat.dwFlags == DDPF_RGB) {
qt_primary_surface_bits = (uchar *) surfaceDesc.lpSurface;
qt_primary_surface_stride = surfaceDesc.lPitch;
qt_primary_surface_format = QImage::Format_RGB32;
} else {
qWarning("QWidget painting: unsupported device depth for onscreen painting...\n");
}
qt_ddraw_primary->Unlock(0);
}
}
class QOnScreenRasterPaintEngine : public QRasterPaintEngine
{
public:
// The image allocated here leaks... Fix if this code is ifdef'ed
// in
QOnScreenRasterPaintEngine()
: QRasterPaintEngine(new QImage(qt_primary_surface_bits,
QApplication::desktop()->width(),
QApplication::desktop()->height(),
qt_primary_surface_stride,
qt_primary_surface_format))
{
device = static_cast<QImage *>(d_func()->device);
}
bool begin(QPaintDevice *)
{
QRegion clip = systemClip();
originalSystemClip = clip;
clip.translate(widget->mapToGlobal(QPoint(0, 0)));
setSystemClip(clip);
QRect bounds = clip.boundingRect();
DDSURFACEDESC surface;
surface.dwSize = sizeof(DDSURFACEDESC);
HRESULT res = qt_ddraw_primary->Lock((RECT *) &bounds, &surface, DDLOCK_WAIT, 0);
if (res != DD_OK) {
qWarning("QWidget painting: locking onscreen bits failed: %d\n", res);
return false;
}
if (surface.lpSurface == qt_primary_surface_bits) {
qt_primary_surface_bits = (uchar *) surface.lpSurface;
device->data_ptr()->data = qt_primary_surface_bits;
}
return QRasterPaintEngine::begin(device);
}
bool end()
{
HRESULT res = qt_ddraw_primary->Unlock(0);
if (res != DD_OK)
qWarning("QWidget::paint, failed to unlock DirectDraw surface: %d", res);
bool ok = QRasterPaintEngine::end();
setSystemClip(originalSystemClip);
return ok;
}
QPoint coordinateOffset() const {
return -widget->mapToGlobal(QPoint(0, 0));
}
const QWidget *widget;
QImage *device;
QRegion originalSystemClip;
};
Q_GLOBAL_STATIC(QOnScreenRasterPaintEngine, onScreenPaintEngine)
#else
void qt_win_initialize_directdraw() { }
#endif
QPaintEngine *QWidget::paintEngine() const
{
#ifndef QT_NO_DIRECTDRAW
QOnScreenRasterPaintEngine *pe = onScreenPaintEngine();
pe->widget = this;
return pe;
#endif
// We set this bit which is checked in setAttribute for
// Qt::WA_PaintOnScreen. We do this to allow these two scenarios:
//
// 1. Users accidentally set Qt::WA_PaintOnScreen on X and port to
// windows which would mean suddenly their widgets stop working.
//
// 2. Users set paint on screen and subclass paintEngine() to
// return 0, in which case we have a "hole" in the backingstore
// allowing use of GDI or DirectX directly.
//
// 1 is WRONG, but to minimize silent failures, we have set this
// bit to ignore the setAttribute call. 2. needs to be
// supported because its our only means of embeddeding native
// graphics stuff.
const_cast<QWidgetPrivate *>(d_func())->noPaintOnScreen = 1;
return 0;
}
QWindowSurface *QWidgetPrivate::createDefaultWindowSurface_sys()
{
Q_Q(QWidget);
return new QRasterWindowSurface(q);
}
void QWidgetPrivate::setModal_sys()
{
}
void QWidgetPrivate::registerTouchWindow()
{
Q_Q(QWidget);
// enable WM_TOUCH* messages on our window
if (q->testAttribute(Qt::WA_WState_Created)
&& QApplicationPrivate::RegisterTouchWindow
&& q->windowType() != Qt::Desktop)
QApplicationPrivate::RegisterTouchWindow(q->effectiveWinId(), 0);
}
void QWidgetPrivate::winSetupGestures()
{
#if !defined(QT_NO_GESTURES) && !defined(QT_NO_NATIVE_GESTURES)
Q_Q(QWidget);
if (!q || !q->isVisible() || !nativeGesturePanEnabled)
return;
if (!QApplicationPrivate::HasTouchSupport)
return;
QApplicationPrivate *qAppPriv = QApplicationPrivate::instance();
if (!qAppPriv->SetGestureConfig)
return;
WId winid = q->internalWinId();
bool needh = false;
bool needv = false;
bool singleFingerPanEnabled = false;
#ifndef QT_NO_SCROLLAREA
if (QAbstractScrollArea *asa = qobject_cast<QAbstractScrollArea*>(q->parent())) {
QScrollBar *hbar = asa->horizontalScrollBar();
QScrollBar *vbar = asa->verticalScrollBar();
Qt::ScrollBarPolicy hbarpolicy = asa->horizontalScrollBarPolicy();
Qt::ScrollBarPolicy vbarpolicy = asa->verticalScrollBarPolicy();
needh = (hbarpolicy == Qt::ScrollBarAlwaysOn ||
(hbarpolicy == Qt::ScrollBarAsNeeded && hbar->minimum() < hbar->maximum()));
needv = (vbarpolicy == Qt::ScrollBarAlwaysOn ||
(vbarpolicy == Qt::ScrollBarAsNeeded && vbar->minimum() < vbar->maximum()));
singleFingerPanEnabled = asa->d_func()->singleFingerPanEnabled;
if (!winid) {
winid = q->winId(); // enforces the native winid on the viewport
}
}
#endif //QT_NO_SCROLLAREA
if (winid) {
GESTURECONFIG gc[1];
memset(gc, 0, sizeof(gc));
gc[0].dwID = GID_PAN;
if (nativeGesturePanEnabled) {
gc[0].dwWant = GC_PAN;
if (needv && singleFingerPanEnabled)
gc[0].dwWant |= GC_PAN_WITH_SINGLE_FINGER_VERTICALLY;
else
gc[0].dwBlock |= GC_PAN_WITH_SINGLE_FINGER_VERTICALLY;
if (needh && singleFingerPanEnabled)
gc[0].dwWant |= GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY;
else
gc[0].dwBlock |= GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY;
} else {
gc[0].dwBlock = GC_PAN;
}
qAppPriv->SetGestureConfig(winid, 0, sizeof(gc)/sizeof(gc[0]), gc, sizeof(gc[0]));
}
#endif
}
QT_END_NAMESPACE
#ifdef Q_WS_WINCE
# include "qwidget_wince.cpp"
#endif