/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see http://www.qt.io/terms-conditions. For further ** information use the contact form at http://www.qt.io/contact-us. ** ** 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 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** As a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, 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. ** ** $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 #include #include #include #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 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); 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); QObjectList childObjects = children(); for (int i = 0; i < childObjects.size(); ++i) { QObject *obj = childObjects.at(i); if (obj->isWidgetType()) static_cast(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); #ifndef QT_NO_IM 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 = QApplicationPrivate::inputContext; if (qic) qic->widgetDestroyed(this); } #endif //QT_NO_IM if ((windowType() == Qt::Desktop)) { } else { if (parentWidget() && parentWidget()->testAttribute(Qt::WA_WState_Created)) { d->hide_sys(); } if (destroyWindow && isWindow()) { if (d->extra && d->extra->topextra && d->extra->topextra->backingStore) d->extra->topextra->backingStore->windowSurface->setGeometry(QRect()); qwsDisplay()->destroyRegion(internalWinId()); } } QT_TRY { d->setWinId(0); } QT_CATCH (const std::bad_alloc &) { // swallow - destructors must not throw } } } 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(effectiveRectFor(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); } } 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 (!q->testAttribute(Qt::WA_ShowWithoutActivating) && q->windowType() != Qt::Popup && q->windowType() != Qt::Tool && q->windowType() != Qt::ToolTip) { QWidget::qwsDisplay()->requestFocus(data.winid,true); } 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); 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(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()); if (extra->topextra->backingStore) 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(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(effectiveRectFor(q->geometry())); } } void QWidgetPrivate::stackUnder_sys(QWidget*) { Q_Q(QWidget); if (QWidget *p = q->parentWidget()) { setDirtyOpaqueRegion(); p->d_func()->invalidateBuffer(effectiveRectFor(q->geometry())); } } void QWidgetPrivate::moveSurface(QWindowSurface *surface, const QPoint &offset) { QWSWindowSurface *s = static_cast(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(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 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 surfaces = bs->subSurfaces; for (int i = 0; i < surfaces.size(); ++i) { QWSWindowSurface *s = static_cast(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(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 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(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(d->parent)->metric(m); const QScreen *screen = d->getScreen(); return qRound(screen->height() / double(screen->physicalHeight() / 25.4)); } else if (m == PdmNumColors) { QScreen *screen = d->getScreen(); int ret = screen->colorCount(); if (!ret) { const int depth = qwsDisplay()->depth(); switch (depth) { case 1: ret = 2; break; case 8: ret = 256; break; case 16: ret = 65536; break; case 24: ret = 16777216; break; case 32: ret = 2147483647; break; } } return ret; } else { val = QPaintDevice::metric(m);// XXX } return val; } void QWidgetPrivate::createSysExtra() { } void QWidgetPrivate::deleteSysExtra() { } void QWidgetPrivate::createTLSysExtra() { #ifndef QT_NO_QWS_MANAGER extra->topextra->qwsManager = 0; #endif } 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(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(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 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(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