diff options
Diffstat (limited to 'src/gui/kernel/qwidget_qws.cpp')
-rw-r--r-- | src/gui/kernel/qwidget_qws.cpp | 1198 |
1 files changed, 1198 insertions, 0 deletions
diff --git a/src/gui/kernel/qwidget_qws.cpp b/src/gui/kernel/qwidget_qws.cpp new file mode 100644 index 0000000..1445f57 --- /dev/null +++ b/src/gui/kernel/qwidget_qws.cpp @@ -0,0 +1,1198 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qcursor.h" +#include "qapplication.h" +#include "qapplication_p.h" +#include "qpainter.h" +#include "qbitmap.h" +#include "qimage.h" +#include "qhash.h" +#include "qstack.h" +#include "qlayout.h" +#include "qtextcodec.h" +#include "qinputcontext.h" +#include "qdesktopwidget.h" + +#include "qwsdisplay_qws.h" +#include "private/qwsdisplay_qws_p.h" +#include "qscreen_qws.h" +#include "qwsmanager_qws.h" +#include <private/qwsmanager_p.h> +#include <private/qbackingstore_p.h> +#include <private/qwindowsurface_qws_p.h> +#include <private/qwslock_p.h> +#include "qpaintengine.h" + +#include "qdebug.h" + +#include "qwidget_p.h" + +QT_BEGIN_NAMESPACE + +QT_USE_NAMESPACE + +extern int *qt_last_x; +extern int *qt_last_y; +extern WId qt_last_cursor; +extern bool qws_overrideCursor; +extern QWidget *qt_pressGrab; +extern QWidget *qt_mouseGrb; + +static QWidget *keyboardGrb = 0; + +static int takeLocalId() +{ + static int n=-1000; + return --n; +} + +class QWSServer; +extern QWSServer *qwsServer; + +static inline bool isServerProcess() +{ + return (qwsServer != 0); +} + +/***************************************************************************** + QWidget member functions + *****************************************************************************/ + +void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool /*destroyOldWindow*/) +{ + Q_Q(QWidget); + Qt::WindowType type = q->windowType(); + + // Make sure the WindowTitleHint is on if any of the title bar hints are set + // Note: This might be moved to cross-platform QWidgetPrivate::adjustFlags() + if ( !(data.window_flags & Qt::CustomizeWindowHint) && ( + (data.window_flags & Qt::WindowSystemMenuHint) || + (data.window_flags & Qt::WindowContextHelpButtonHint) || + (data.window_flags & Qt::WindowMinimizeButtonHint) || + (data.window_flags & Qt::WindowMaximizeButtonHint) || + (data.window_flags & Qt::WindowCloseButtonHint) ) ) { + data.window_flags |= Qt::WindowTitleHint; + } + + // Decoration plugins on QWS don't support switching on the close button on its own + if (data.window_flags & Qt::WindowCloseButtonHint) + data.window_flags |= Qt::WindowSystemMenuHint; + + Qt::WindowFlags flags = data.window_flags; + + data.alloc_region_index = -1; + + // we don't have a "Drawer" window type + if (type == Qt::Drawer) { + type = Qt::Widget; + flags &= ~Qt::WindowType_Mask; + } + + + 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::SplashScreen || type == Qt::ToolTip); + + +#ifndef QT_NO_WARNING_OUTPUT + static bool toolWarningShown = false; + if (!toolWarningShown && type == Qt::Tool && !(flags & Qt::FramelessWindowHint)) { + qWarning("Qt for Embedded Linux " QT_VERSION_STR " does not support tool windows with frames.\n" + "This behavior will change in a later release. To ensure compatibility with\n" + "future versions, use (Qt::Tool | Qt::FramelessWindowHint)."); + toolWarningShown = true; + } +#endif + + WId id; + QWSDisplay* dpy = QWidget::qwsDisplay(); + + if (!window) // always initialize + initializeWindow = true; + + // use the size of the primary screen to determine the default window size + QList<QScreen *> screens = qt_screen->subScreens(); + if (screens.isEmpty()) + screens.append(qt_screen); + int sw = screens[0]->width(); + int sh = screens[0]->height(); + + if (desktop) { // desktop widget + dialog = popup = false; // force these flags off + data.crect.setRect(0, 0, sw, sh); + } else if (topLevel && !q->testAttribute(Qt::WA_Resized)) { + int width = sw / 2; + int height = 4 * sh / 10; + if (extra) { + width = qMax(qMin(width, extra->maxw), extra->minw); + height = qMax(qMin(height, extra->maxh), extra->minh); + } + data.crect.setSize(QSize(width, height)); + } + + if (window) { // override the old window + id = window; + setWinId(window); + } else if (desktop) { // desktop widget + id = (WId)-2; // id = root window +#if 0 + QWidget *otherDesktop = q->find(id); // is there another desktop? + if (otherDesktop && otherDesktop->testWFlags(Qt::WPaintDesktop)) { + otherDesktop->d_func()->setWinId(0); // remove id from widget mapper + setWinId(id); // make sure otherDesktop is + otherDesktop->d_func()->setWinId(id); // found first + } else +#endif + { + setWinId(id); + } + } else { + id = topLevel ? dpy->takeId() : takeLocalId(); + setWinId(id); // set widget id/handle + hd + } + + + bool hasFrame = true; + if (topLevel) { + if (desktop || popup || tool || q->testAttribute(Qt::WA_DontShowOnScreen)) + hasFrame = false; + else + hasFrame = !(flags & Qt::FramelessWindowHint); + } + if (desktop) { + q->setAttribute(Qt::WA_WState_Visible); + } else if (topLevel) { // set X cursor + //QCursor *oc = QApplication::overrideCursor(); + if (initializeWindow) { + //XXX XDefineCursor(dpy, winid, oc ? oc->handle() : cursor().handle()); + } + QWidget::qwsDisplay()->nameRegion(q->internalWinId(), q->objectName(), q->windowTitle()); + } + + if (topLevel) { + createTLExtra(); + QTLWExtra *topextra = extra->topextra; +#ifndef QT_NO_QWS_MANAGER + if (hasFrame) { + // get size of wm decoration and make the old crect the new frect + QRect cr = data.crect; + QRegion r = QApplication::qwsDecoration().region(q, cr) | cr; + QRect br(r.boundingRect()); + topextra->frameStrut.setCoords(cr.x() - br.x(), + cr.y() - br.y(), + br.right() - cr.right(), + br.bottom() - cr.bottom()); + if (!q->testAttribute(Qt::WA_Moved) || topextra->posFromMove) + data.crect.translate(topextra->frameStrut.left(), topextra->frameStrut.top()); + if (!topData()->qwsManager) { + topData()->qwsManager = new QWSManager(q); + if((q->data->window_state & ~Qt::WindowActive) == Qt::WindowMaximized) + topData()->qwsManager->maximize(); + } + + } else if (topData()->qwsManager) { + delete topData()->qwsManager; + topData()->qwsManager = 0; + data.crect.translate(-topextra->frameStrut.left(), -topextra->frameStrut.top()); + topextra->frameStrut.setCoords(0, 0, 0, 0); + } +#endif + if (!topextra->caption.isEmpty()) + setWindowTitle_helper(topextra->caption); + + //XXX If we are session managed, inform the window manager about it + } else { + if (extra && extra->topextra) { // already allocated due to reparent? + extra->topextra->frameStrut.setCoords(0, 0, 0, 0); + } + //updateRequestedRegion(mapToGlobal(QPoint(0,0))); + } +} + + +void QWidget::destroy(bool destroyWindow, bool destroySubWindows) +{ + Q_D(QWidget); + + if (!isWindow() && parentWidget()) + parentWidget()->d_func()->invalidateBuffer(geometry()); + + d->deactivateWidgetCleanup(); + if (testAttribute(Qt::WA_WState_Created)) { + setAttribute(Qt::WA_WState_Created, false); + QObjectList childObjects = children(); + for (int i = 0; i < childObjects.size(); ++i) { + QObject *obj = childObjects.at(i); + if (obj->isWidgetType()) + static_cast<QWidget*>(obj)->destroy(destroySubWindows, + destroySubWindows); + } + releaseMouse(); + if (qt_pressGrab == this) + qt_pressGrab = 0; + + 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 (d->ic) { + delete d->ic; + d->ic =0; + } else { + // release previous focus information participating with + // preedit preservation of qic -- while we still have a winId + QInputContext *qic = inputContext(); + if (qic) + qic->widgetDestroyed(this); + } + + if ((windowType() == Qt::Desktop)) { + } else { + if (parentWidget() && parentWidget()->testAttribute(Qt::WA_WState_Created)) { + d->hide_sys(); + } + if (destroyWindow && isWindow()) { + d->extra->topextra->backingStore->windowSurface->setGeometry(QRect()); + qwsDisplay()->destroyRegion(internalWinId()); + } + } + d->setWinId(0); + } +} + + +void QWidgetPrivate::setParent_sys(QWidget *newparent, 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(q->geometry()); +#ifndef QT_NO_CURSOR + QCursor oldcurs; + bool setcurs=q->testAttribute(Qt::WA_SetCursor); + if (setcurs) { + oldcurs = q->cursor(); + q->unsetCursor(); + } +#endif + + WId old_winid = data.winid; + if ((q->windowType() == Qt::Desktop)) + old_winid = 0; + + if (!q->isWindow() && q->parentWidget() && q->parentWidget()->testAttribute(Qt::WA_WState_Created)) + hide_sys(); + + setWinId(0); + + if (parent != newparent) { + QWidget *oldparent = q->parentWidget(); + QObjectPrivate::setParent_helper(newparent); + if (oldparent) { +// oldparent->d_func()->setChildrenAllocatedDirty(); +// oldparent->data->paintable_region_dirty = true; + } + if (newparent) { +// newparent->d_func()->setChildrenAllocatedDirty(); +// newparent->data->paintable_region_dirty = true; + //@@@@@@@ + } + } + Qt::FocusPolicy fp = q->focusPolicy(); + QSize s = q->size(); + //QBrush bgc = background(); // save colors + bool explicitlyHidden = q->testAttribute(Qt::WA_WState_Hidden) && q->testAttribute(Qt::WA_WState_ExplicitShowHide); + + data.window_flags = f; + 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() && newparent->testAttribute(Qt::WA_WState_Created))) + createWinId(); + if (q->isWindow() || (!newparent || newparent->isVisible()) || explicitlyHidden) + q->setAttribute(Qt::WA_WState_Hidden); + q->setAttribute(Qt::WA_WState_ExplicitShowHide, explicitlyHidden); + + if (q->isWindow()) { + QRect fs = frameStrut(); + data.crect = QRect(fs.left(), fs.top(), s.width(), s.height()); + if ((data.window_flags & Qt::FramelessWindowHint) && extra && extra->topextra) + extra->topextra->frameStrut.setCoords(0, 0, 0, 0); + } else { + data.crect = QRect(0, 0, s.width(), s.height()); + } + + q->setFocusPolicy(fp); + if (extra && !extra->mask.isEmpty()) { + QRegion r = extra->mask; + extra->mask = QRegion(); + q->setMask(r); + } + if ((int)old_winid > 0) { + QWidget::qwsDisplay()->destroyRegion(old_winid); + extra->topextra->backingStore->windowSurface->setGeometry(QRect()); + } +#ifndef QT_NO_CURSOR + if (setcurs) { + q->setCursor(oldcurs); + } +#endif +} + + +QPoint QWidget::mapToGlobal(const QPoint &pos) const +{ + int x=pos.x(), y=pos.y(); + const QWidget* w = this; + while (w) { + x += w->data->crect.x(); + y += w->data->crect.y(); + w = w->isWindow() ? 0 : w->parentWidget(); + } + return QPoint(x, y); +} + +QPoint QWidget::mapFromGlobal(const QPoint &pos) const +{ + int x=pos.x(), y=pos.y(); + const QWidget* w = this; + while (w) { + x -= w->data->crect.x(); + y -= w->data->crect.y(); + w = w->isWindow() ? 0 : w->parentWidget(); + } + return QPoint(x, y); +} + +#if 0 // ##### +void QWidget::setMicroFocusHint(int x, int y, int width, int height, + bool text, QFont *) +{ + if (QRect(x, y, width, height) != microFocusHint()) { + d->createExtra(); + d->extra->micro_focus_hint.setRect(x, y, width, height); + } +#ifndef QT_NO_QWS_INPUTMETHODS + if (text) { + QWidget *tlw = window(); + int winid = tlw->internalWinId(); + QPoint p(x, y + height); + QPoint gp = mapToGlobal(p); + + QRect r = QRect(mapToGlobal(QPoint(0,0)), + size()); + + r.setBottom(tlw->geometry().bottom()); + + //qDebug("QWidget::setMicroFocusHint %d %d %d %d", r.x(), + // r.y(), r.width(), r.height()); + QInputContext::setMicroFocusWidget(this); + + qwsDisplay()->setIMInfo(winid, gp.x(), gp.y(), r); + + //send font info, ###if necessary + qwsDisplay()->setInputFont(winid, font()); + } +#endif +} +#endif + +void QWidgetPrivate::updateSystemBackground() {} + +#ifndef QT_NO_CURSOR +void QWidgetPrivate::setCursor_sys(const QCursor &cursor) +{ + Q_UNUSED(cursor); + Q_Q(QWidget); + if (q->isVisible()) + updateCursor(); +} + +void QWidgetPrivate::unsetCursor_sys() +{ + Q_Q(QWidget); + if (q->isVisible()) + updateCursor(); +} +#endif //QT_NO_CURSOR + +void QWidgetPrivate::setWindowTitle_sys(const QString &caption) +{ + Q_Q(QWidget); + QWidget::qwsDisplay()->setWindowCaption(q, caption); +} + +void QWidgetPrivate::setWindowIcon_sys(bool /*forceReset*/) +{ +#if 0 + QTLWExtra* x = d->topData(); + delete x->icon; + x->icon = 0; + QBitmap mask; + if (unscaledPixmap.isNull()) { + } else { + QImage unscaledIcon = unscaledPixmap.toImage(); + QPixmap pixmap = + QPixmap::fromImage(unscaledIcon.scale(16, 16, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); + x->icon = new QPixmap(pixmap); + mask = pixmap.mask() ? *pixmap.mask() : pixmap.createHeuristicMask(); + } +#endif +} + +void QWidgetPrivate::setWindowIconText_sys(const QString &iconText) +{ + Q_UNUSED(iconText); +} + +void QWidget::grabMouse() +{ + if (qt_mouseGrb) + qt_mouseGrb->releaseMouse(); + + qwsDisplay()->grabMouse(this,true); + + qt_mouseGrb = this; + qt_pressGrab = 0; +} + +#ifndef QT_NO_CURSOR +void QWidget::grabMouse(const QCursor &cursor) +{ + if (qt_mouseGrb) + qt_mouseGrb->releaseMouse(); + + qwsDisplay()->grabMouse(this,true); + qwsDisplay()->selectCursor(this, cursor.handle()); + qt_mouseGrb = this; + qt_pressGrab = 0; +} +#endif + +void QWidget::releaseMouse() +{ + if (qt_mouseGrb == this) { + qwsDisplay()->grabMouse(this,false); + qt_mouseGrb = 0; + } +} + +void QWidget::grabKeyboard() +{ + if (keyboardGrb) + keyboardGrb->releaseKeyboard(); + qwsDisplay()->grabKeyboard(this, true); + keyboardGrb = this; +} + +void QWidget::releaseKeyboard() +{ + if (keyboardGrb == this) { + qwsDisplay()->grabKeyboard(this, false); + keyboardGrb = 0; + } +} + + +QWidget *QWidget::mouseGrabber() +{ + if (qt_mouseGrb) + return qt_mouseGrb; + return qt_pressGrab; +} + + +QWidget *QWidget::keyboardGrabber() +{ + return keyboardGrb; +} + +void QWidget::activateWindow() +{ + QWidget *tlw = window(); + if (tlw->isVisible()) { + Q_ASSERT(tlw->testAttribute(Qt::WA_WState_Created)); + qwsDisplay()->requestFocus(tlw->internalWinId(), true); + } +} + +/* + Should we require that q is a toplevel window ??? + + Used by QWSManager + */ +void QWidgetPrivate::blitToScreen(const QRegion &globalrgn) +{ + Q_Q(QWidget); + QWidget *win = q->window(); + QBrush bgBrush = win->palette().brush(win->backgroundRole()); + bool opaque = bgBrush.style() == Qt::NoBrush || bgBrush.isOpaque(); + QWidget::qwsDisplay()->repaintRegion(win->data->winid, win->windowFlags(), opaque, globalrgn); +} + +void QWidgetPrivate::show_sys() +{ + Q_Q(QWidget); + q->setAttribute(Qt::WA_Mapped); + if (q->testAttribute(Qt::WA_DontShowOnScreen)) { + invalidateBuffer(q->rect()); + return; + } + + if (q->isWindow()) { + + if (QWindowSurface *surface = q->windowSurface()) { + const QRect frameRect = q->frameGeometry(); + if (surface->geometry() != frameRect) + surface->setGeometry(frameRect); + } + + QRegion r = localRequestedRegion(); +#ifndef QT_NO_QWS_MANAGER + if (extra && extra->topextra && extra->topextra->qwsManager) { + r.translate(data.crect.topLeft()); + r += extra->topextra->qwsManager->region(); + r.translate(-data.crect.topLeft()); + } +#endif + data.fstrut_dirty = true; + invalidateBuffer(r); + if (!q->testAttribute(Qt::WA_ShowWithoutActivating) + && q->windowType() != Qt::Popup + && q->windowType() != Qt::Tool + && q->windowType() != Qt::ToolTip) { + QWidget::qwsDisplay()->requestFocus(data.winid,true); + } + bool staysontop = + (q->windowFlags() & Qt::WindowStaysOnTopHint) + || q->windowType() == Qt::Popup; + if (!staysontop && q->parentWidget()) { // if our parent stays on top, so must we + QWidget *ptl = q->parentWidget()->window(); + if (ptl && (ptl->windowFlags() & Qt::WindowStaysOnTopHint)) + staysontop = true; + } + + QWSChangeAltitudeCommand::Altitude altitude; + altitude = staysontop ? QWSChangeAltitudeCommand::StaysOnTop : QWSChangeAltitudeCommand::Raise; + QWidget::qwsDisplay()->setAltitude(data.winid, altitude, true); + if (!q->objectName().isEmpty()) { + QWidget::qwsDisplay()->setWindowCaption(q, q->windowTitle()); + } + } +#ifdef Q_BACKINGSTORE_SUBSURFACES + else if ( extra && extra->topextra && extra->topextra->windowSurface) { + QWSWindowSurface *surface; + surface = static_cast<QWSWindowSurface*>(q->windowSurface()); + const QPoint p = q->mapToGlobal(QPoint()); + surface->setGeometry(QRect(p, q->size())); + } +#endif + + if (!q->window()->data->in_show) { + invalidateBuffer(q->rect()); + } +} + + +void QWidgetPrivate::hide_sys() +{ + Q_Q(QWidget); + deactivateWidgetCleanup(); + + if (q->isWindow()) { + q->releaseMouse(); +// requestWindowRegion(QRegion()); + + extra->topextra->backingStore->releaseBuffer(); + + + QWidget::qwsDisplay()->requestFocus(data.winid,false); + } else { + QWidget *p = q->parentWidget(); + if (p &&p->isVisible()) { + invalidateBuffer(q->rect()); + } + } +} + + + +static Qt::WindowStates effectiveState(Qt::WindowStates state) + { + if (state & Qt::WindowMinimized) + return Qt::WindowMinimized; + else if (state & Qt::WindowFullScreen) + return Qt::WindowFullScreen; + else if (state & Qt::WindowMaximized) + return Qt::WindowMaximized; + return Qt::WindowNoState; + } + +void QWidgetPrivate::setMaxWindowState_helper() +{ + // in_set_window_state is usually set in setWindowState(), but this + // function is used in other functions as well + // (e.g QApplicationPrivate::setMaxWindowRect()) + const uint old_state = data.in_set_window_state; + data.in_set_window_state = 1; + +#ifndef QT_NO_QWS_MANAGER + if (extra && extra->topextra && extra->topextra->qwsManager) + extra->topextra->qwsManager->maximize(); + else +#endif + { + Q_Q(QWidget); + const QDesktopWidget *desktop = QApplication::desktop(); + const int screen = desktop->screenNumber(q); + const QRect maxWindowRect = desktop->availableGeometry(screen); + q->setGeometry(maxWindowRect); + } + data.in_set_window_state = old_state; +} + +void QWidgetPrivate::setFullScreenSize_helper() +{ + Q_Q(QWidget); + + const uint old_state = data.in_set_window_state; + data.in_set_window_state = 1; + + const QRect screen = qApp->desktop()->screenGeometry(qApp->desktop()->screenNumber(q)); + q->move(screen.topLeft()); + q->resize(screen.size()); + + data.in_set_window_state = old_state; +} + +void QWidget::setWindowState(Qt::WindowStates newstate) +{ + Q_D(QWidget); + Qt::WindowStates oldstate = windowState(); + if (oldstate == newstate) + return; + if (isWindow() && !testAttribute(Qt::WA_WState_Created)) + create(); + + data->window_state = newstate; + data->in_set_window_state = 1; + bool needShow = false; + Qt::WindowStates newEffectiveState = effectiveState(newstate); + Qt::WindowStates oldEffectiveState = effectiveState(oldstate); + if (isWindow() && newEffectiveState != oldEffectiveState) { + d->createTLExtra(); + if (oldEffectiveState == Qt::WindowNoState) { //normal + d->topData()->normalGeometry = geometry(); + } else if (oldEffectiveState == Qt::WindowFullScreen) { + setParent(0, d->topData()->savedFlags); + needShow = true; + } else if (oldEffectiveState == Qt::WindowMinimized) { + needShow = true; + } + + if (newEffectiveState == Qt::WindowMinimized) { + //### not ideal... + hide(); + needShow = false; + } else if (newEffectiveState == Qt::WindowFullScreen) { + d->topData()->savedFlags = windowFlags(); + setParent(0, Qt::FramelessWindowHint | (windowFlags() & Qt::WindowStaysOnTopHint)); + d->setFullScreenSize_helper(); + raise(); + needShow = true; + } else if (newEffectiveState == Qt::WindowMaximized) { + createWinId(); + d->setMaxWindowState_helper(); + } else { //normal + QRect r = d->topData()->normalGeometry; + if (r.width() >= 0) { + d->topData()->normalGeometry = QRect(0,0,-1,-1); + setGeometry(r); + } + } + } + data->in_set_window_state = 0; + + if (needShow) + show(); + + if (newstate & Qt::WindowActive) + activateWindow(); + + QWindowStateChangeEvent e(oldstate); + QApplication::sendEvent(this, &e); +} + +void QWidgetPrivate::setFocus_sys() +{ + +} + +void QWidgetPrivate::raise_sys() +{ + Q_Q(QWidget); + //@@@ transaction + if (q->isWindow()) { + Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); + QWidget::qwsDisplay()->setAltitude(q->internalWinId(), + QWSChangeAltitudeCommand::Raise); + // XXX: subsurfaces? +#ifdef QT_NO_WINDOWGROUPHINT +#else + QObjectList childObjects = q->children(); + if (!childObjects.isEmpty()) { + QWidgetList toraise; + for (int i = 0; i < childObjects.size(); ++i) { + QObject *obj = childObjects.at(i); + if (obj->isWidgetType()) { + QWidget* w = static_cast<QWidget*>(obj); + if (w->isWindow()) + toraise.append(w); + } + } + + for (int i = 0; i < toraise.size(); ++i) { + QWidget *w = toraise.at(i); + if (w->isVisible()) + w->raise(); + } + } +#endif // QT_NO_WINDOWGROUPHINT + } +} + +void QWidgetPrivate::lower_sys() +{ + Q_Q(QWidget); + if (q->isWindow()) { + Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); + QWidget::qwsDisplay()->setAltitude(data.winid, + QWSChangeAltitudeCommand::Lower); + } else if (QWidget *p = q->parentWidget()) { + setDirtyOpaqueRegion(); + p->d_func()->invalidateBuffer(q->geometry()); + } +} + +void QWidgetPrivate::stackUnder_sys(QWidget*) +{ + Q_Q(QWidget); + if (QWidget *p = q->parentWidget()) { + setDirtyOpaqueRegion(); + p->d_func()->invalidateBuffer(q->geometry()); + } +} + +void QWidgetPrivate::moveSurface(QWindowSurface *surface, const QPoint &offset) +{ + QWSWindowSurface *s = static_cast<QWSWindowSurface*>(surface); + if (!s->move(offset)) + s->invalidateBuffer(); + + QWSDisplay::instance()->moveRegion(s->winId(), offset.x(), offset.y()); +} + +void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove) +{ + Q_Q(QWidget); + 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); + } + + QPoint oldp = q->geometry().topLeft(); + QSize olds = q->size(); + QRect r(x, y, w, h); + + bool isResize = olds != r.size(); + isMove = oldp != r.topLeft(); //### why do we have isMove as a parameter? + + // We only care about stuff that changes the geometry, or may + // cause the window manager to change its state + if (r.size() == olds && oldp == r.topLeft()) + return; + + if (!data.in_set_window_state) { + q->data->window_state &= ~Qt::WindowMaximized; + q->data->window_state &= ~Qt::WindowFullScreen; + if (q->isWindow()) + topData()->normalGeometry = QRect(0, 0, -1, -1); + } + QPoint oldPos = q->pos(); + data.crect = r; + + if ((q->windowType() == Qt::Desktop)) + return; + + if (q->isVisible()) { + + bool toplevelMove = false; + QWSWindowSurface *surface = 0; + + if (q->isWindow()) { + //### ConfigPending not implemented, do we need it? + //setAttribute(Qt::WA_WState_ConfigPending); + const QWidgetBackingStore *bs = maybeBackingStore(); + if (bs) + surface = static_cast<QWSWindowSurface*>(bs->windowSurface); + if (isMove && !isResize && surface) { + const QPoint offset(x - oldp.x(), y - oldp.y()); + moveSurface(surface, offset); + toplevelMove = true; //server moves window, but we must send moveEvent, which might trigger painting + +#ifdef Q_BACKINGSTORE_SUBSURFACES + QList<QWindowSurface*> surfaces = bs->subSurfaces; + for (int i = 0; i < surfaces.size(); ++i) + moveSurface(surfaces.at(i), offset); +#endif + } else { + updateFrameStrut(); + } + } + + if (!toplevelMove) { + if (q->isWindow()) { + if (surface) + surface->setGeometry(q->frameGeometry()); + else + invalidateBuffer(q->rect()); //### + +#ifdef Q_BACKINGSTORE_SUBSURFACES + // XXX: should not resize subsurfaces. Children within a layout + // will be resized automatically while children with a static + // geometry should get a new clip region instead. + const QRect clipRect = q->geometry(); + QWidgetBackingStore *bs = maybeBackingStore(); + QList<QWindowSurface*> surfaces = bs->subSurfaces; + for (int i = 0; i < surfaces.size(); ++i) { + QWSWindowSurface *s = static_cast<QWSWindowSurface*>(surfaces.at(i)); + QRect srect = s->geometry(); + s->setGeometry(clipRect & srect); + } +#endif + } +#ifdef Q_BACKINGSTORE_SUBSURFACES + // XXX: merge this case with the isWindow() case + else if (maybeTopData() && maybeTopData()->windowSurface) { + QWSWindowSurface *surface; + surface = static_cast<QWSWindowSurface*>(q->windowSurface()); + if (isMove && !isResize) { + moveSurface(surface, QPoint(x - oldp.x(), y - oldp.y())); + } else { + const QPoint p = q->mapToGlobal(QPoint()); + surface->setGeometry(QRect(p, QSize(w, h))); + } + } +#endif + else { + if (isMove && !isResize) + moveRect(QRect(oldPos, olds), x - oldPos.x(), y - oldPos.y()); + else + invalidateBuffer_resizeHelper(oldPos, olds); + } + } + + //### must have frame geometry correct before sending move/resize events + if (isMove) { + QMoveEvent e(q->pos(), oldPos); + QApplication::sendEvent(q, &e); + } + if (isResize) { + QResizeEvent e(r.size(), olds); + QApplication::sendEvent(q, &e); + } + + } else { // not visible + if (isMove && q->pos() != oldPos) + q->setAttribute(Qt::WA_PendingMoveEvent, true); + if (isResize) + q->setAttribute(Qt::WA_PendingResizeEvent, true); + } +} + +void QWidgetPrivate::setConstraints_sys() +{ +} + +QScreen* QWidgetPrivate::getScreen() const +{ + Q_Q(const QWidget); + + const QList<QScreen*> subScreens = qt_screen->subScreens(); + if (subScreens.isEmpty() || q->windowType() == Qt::Desktop) + return qt_screen; + + const int screen = QApplication::desktop()->screenNumber(q); + + return qt_screen->subScreens().at(screen < 0 ? 0 : screen); +} + +void QWidgetPrivate::scroll_sys(int dx, int dy) +{ + Q_Q(QWidget); + scrollChildren(dx, dy); + scrollRect(q->rect(), dx, dy); +} + +void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r) +{ + scrollRect(r, dx, dy); +} + +int QWidget::metric(PaintDeviceMetric m) const +{ + Q_D(const QWidget); + + int val; + if (m == PdmWidth) { + val = data->crect.width(); + } else if (m == PdmWidthMM) { + const QScreen *screen = d->getScreen(); + val = data->crect.width() * screen->physicalWidth() / screen->width(); + } else if (m == PdmHeight) { + val = data->crect.height(); + } else if (m == PdmHeightMM) { + const QScreen *screen = d->getScreen(); + val = data->crect.height() * screen->physicalHeight() / screen->height(); + } else if (m == PdmDepth) { + return qwsDisplay()->depth(); + } else if (m == PdmDpiX || m == PdmPhysicalDpiX) { + if (d->extra && d->extra->customDpiX) + return d->extra->customDpiX; + else if (d->parent) + return static_cast<QWidget *>(d->parent)->metric(m); + const QScreen *screen = d->getScreen(); + return qRound(screen->width() / double(screen->physicalWidth() / 25.4)); + } else if (m == PdmDpiY || m == PdmPhysicalDpiY) { + if (d->extra && d->extra->customDpiY) + return d->extra->customDpiY; + else if (d->parent) + return static_cast<QWidget *>(d->parent)->metric(m); + const QScreen *screen = d->getScreen(); + return qRound(screen->height() / double(screen->physicalHeight() / 25.4)); + } else { + val = QPaintDevice::metric(m);// XXX + } + return val; +} + +void QWidgetPrivate::createSysExtra() +{ +} + +void QWidgetPrivate::deleteSysExtra() +{ +} + +void QWidgetPrivate::createTLSysExtra() +{ +} + +void QWidgetPrivate::deleteTLSysExtra() +{ +} + +void QWidgetPrivate::registerDropSite(bool on) +{ + Q_UNUSED(on); +} + +QRegion QWidgetPrivate::localRequestedRegion() const +{ + Q_Q(const QWidget); + QRegion r(q->rect()); + if (extra && !extra->mask.isEmpty()) + r &= extra->mask; + + return r; +} + +QRegion QWidgetPrivate::localAllocatedRegion() const +{ + Q_Q(const QWidget); + + QWidgetBackingStore *wbs = q->window()->d_func()->maybeBackingStore(); + + QWindowSurface *ws = wbs ? wbs->windowSurface : 0; + if (!ws) + return QRegion(); + QRegion r = static_cast<QWSWindowSurface*>(ws)->clipRegion(); + if (!q->isWindow()) { + QPoint off = q->mapTo(q->window(), QPoint()); + r &= localRequestedRegion().translated(off); + r.translate(-off); + } + return r; +} + +inline bool QRect::intersects(const QRect &r) const +{ + return (qMax(x1, r.x1) <= qMin(x2, r.x2) && + qMax(y1, r.y1) <= qMin(y2, r.y2)); +} + +void QWidgetPrivate::setMask_sys(const QRegion ®ion) +{ + Q_UNUSED(region); + Q_Q(QWidget); + + if (!q->isVisible() || !q->isWindow()) + return; + + data.fstrut_dirty = true; + invalidateBuffer(q->rect()); + QWindowSurface *surface = extra->topextra->backingStore->windowSurface; + if (surface) { + // QWSWindowSurface::setGeometry() returns without doing anything + // if old geom == new geom. Therefore, we need to reset the old value. + surface->QWindowSurface::setGeometry(QRect()); + surface->setGeometry(q->frameGeometry()); + } +} + +void QWidgetPrivate::updateFrameStrut() +{ + Q_Q(QWidget); + + if(!q->isVisible() || (q->windowType() == Qt::Desktop)) { + data.fstrut_dirty = q->isVisible(); + return; + } + +#ifndef QT_NO_QWS_MANAGER + if (extra && extra->topextra && extra->topextra->qwsManager) { + QTLWExtra *topextra = extra->topextra; + const QRect oldFrameStrut = topextra->frameStrut; + const QRect contents = data.crect; + QRegion r = localRequestedRegion().translated(contents.topLeft()); + r += extra->topextra->qwsManager->region(); + const QRect frame = r.boundingRect(); + + topextra->frameStrut.setCoords(contents.left() - frame.left(), + contents.top() - frame.top(), + frame.right() - contents.right(), + frame.bottom() - contents.bottom()); + topextra->qwsManager->repaintRegion(QDecoration::All, QDecoration::Normal); + } +#endif + data.fstrut_dirty = false; +} + +#ifndef QT_NO_CURSOR +void QWidgetPrivate::updateCursor() const +{ + Q_Q(const QWidget); + + if (QApplication::overrideCursor()) + return; + + if (qt_last_x + && (!QWidget::mouseGrabber() || QWidget::mouseGrabber() == q) + && qt_last_cursor != (WId)q->cursor().handle()) + { + const QPoint pos(*qt_last_x, *qt_last_y); + const QPoint offset = q->mapToGlobal(QPoint()); + if (!localAllocatedRegion().contains(pos - offset)) + return; + + const QWidget *w = q->childAt(q->mapFromGlobal(pos)); + if (!w || w->cursor().handle() == q->cursor().handle()) + QWidget::qwsDisplay()->selectCursor(const_cast<QWidget*>(q), + q->cursor().handle()); + } +} +#endif + +void QWidgetPrivate::setWindowOpacity_sys(qreal level) +{ + Q_Q(QWidget); + Q_UNUSED(level); + createWinId(); + QWidget::qwsDisplay()->setOpacity(q->data->winid, topData()->opacity); +} + +//static QSingleCleanupHandler<QWSPaintEngine> qt_paintengine_cleanup_handler; +//static QWSPaintEngine *qt_widget_paintengine = 0; +QPaintEngine *QWidget::paintEngine() const +{ + qWarning("QWidget::paintEngine: Should no longer be called"); + return 0; //##### @@@ +// if (!qt_widget_paintengine) { +// qt_widget_paintengine = new QRasterPaintEngine(); +// qt_paintengine_cleanup_handler.set(&qt_widget_paintengine); +// } +// if (qt_widget_paintengine->isActive()) { +// if (d->extraPaintEngine) +// return d->extraPaintEngine; +// const_cast<QWidget *>(this)->d_func()->extraPaintEngine = new QRasterPaintEngine(); +// return d->extraPaintEngine; +// } +// return qt_widget_paintengine; +} + +QWindowSurface *QWidgetPrivate::createDefaultWindowSurface_sys() +{ + Q_Q(QWidget); + if (q->windowType() == Qt::Desktop) + return 0; + q->ensurePolished(); + return qt_screen->createSurface(q); +} + +void QWidgetPrivate::setModal_sys() +{ +} + + +QT_END_NAMESPACE |