diff options
Diffstat (limited to 'src/widgets')
-rw-r--r-- | src/widgets/dialogs/qdialog.cpp | 6 | ||||
-rw-r--r-- | src/widgets/itemviews/qabstractitemview.cpp | 3 | ||||
-rw-r--r-- | src/widgets/kernel/qdesktopwidget.cpp | 99 | ||||
-rw-r--r-- | src/widgets/kernel/qdesktopwidget_p.h | 16 | ||||
-rw-r--r-- | src/widgets/kernel/qopenglwidget.cpp | 4 | ||||
-rw-r--r-- | src/widgets/kernel/qwidgetbackingstore.cpp | 22 | ||||
-rw-r--r-- | src/widgets/kernel/qwidgetbackingstore_p.h | 2 | ||||
-rw-r--r-- | src/widgets/kernel/qwidgetwindow.cpp | 8 | ||||
-rw-r--r-- | src/widgets/styles/qfusionstyle.cpp | 3 | ||||
-rw-r--r-- | src/widgets/styles/qmacstyle_mac.mm | 4 | ||||
-rw-r--r-- | src/widgets/styles/qwindowsstyle.cpp | 3 | ||||
-rw-r--r-- | src/widgets/styles/qwindowsvistastyle.cpp | 2 | ||||
-rw-r--r-- | src/widgets/styles/qwindowsxpstyle.cpp | 3 | ||||
-rw-r--r-- | src/widgets/widgets/qmenu.cpp | 13 | ||||
-rw-r--r-- | src/widgets/widgets/qwidgetlinecontrol.cpp | 19 | ||||
-rw-r--r-- | src/widgets/widgets/qwidgetlinecontrol_p.h | 5 |
16 files changed, 142 insertions, 70 deletions
diff --git a/src/widgets/dialogs/qdialog.cpp b/src/widgets/dialogs/qdialog.cpp index 74d138442a..464a1e139e 100644 --- a/src/widgets/dialogs/qdialog.cpp +++ b/src/widgets/dialogs/qdialog.cpp @@ -846,6 +846,12 @@ void QDialog::adjustPosition(QWidget* w) if (p.y() < desk.y()) p.setY(desk.y()); + // QTBUG-52735: Manually set the correct target screen since scaling in a + // subsequent call to QWindow::resize() may otherwise use the wrong factor + // if the screen changed notification is still in an event queue. + if (QWindow *window = windowHandle()) + window->setScreen(QGuiApplication::screens().at(scrn)); + move(p); } diff --git a/src/widgets/itemviews/qabstractitemview.cpp b/src/widgets/itemviews/qabstractitemview.cpp index 0ab2e1860c..42e0cc7585 100644 --- a/src/widgets/itemviews/qabstractitemview.cpp +++ b/src/widgets/itemviews/qabstractitemview.cpp @@ -3671,6 +3671,9 @@ void QAbstractItemView::startDrag(Qt::DropActions supportedActions) defaultDropAction = Qt::CopyAction; if (drag->exec(supportedActions, defaultDropAction) == Qt::MoveAction) d->clearOrRemove(); + // Reset the drop indicator + d->dropIndicatorRect = QRect(); + d->dropIndicatorPosition = OnItem; } } #endif // QT_NO_DRAGANDDROP diff --git a/src/widgets/kernel/qdesktopwidget.cpp b/src/widgets/kernel/qdesktopwidget.cpp index fceb061867..ece673337a 100644 --- a/src/widgets/kernel/qdesktopwidget.cpp +++ b/src/widgets/kernel/qdesktopwidget.cpp @@ -46,6 +46,21 @@ QT_BEGIN_NAMESPACE +QDesktopScreenWidget::QDesktopScreenWidget(QScreen *screen, const QRect &geometry) + : QWidget(Q_NULLPTR, Qt::Desktop), m_screen(screen) +{ + setVisible(false); + if (QWindow *winHandle = windowHandle()) + winHandle->setScreen(screen); + setScreenGeometry(geometry); +} + +void QDesktopScreenWidget::setScreenGeometry(const QRect &geometry) +{ + m_geometry = geometry; + setGeometry(geometry); +} + int QDesktopScreenWidget::screenNumber() const { const QDesktopWidgetPrivate *desktopWidgetP @@ -80,54 +95,76 @@ const QRect QDesktopWidget::availableGeometry(const QWidget *widget) const return rect; } +QDesktopScreenWidget *QDesktopWidgetPrivate::widgetForScreen(QScreen *qScreen) const +{ + foreach (QDesktopScreenWidget *widget, screens) { + if (widget->screen() == qScreen) + return widget; + } + return Q_NULLPTR; +} + void QDesktopWidgetPrivate::_q_updateScreens() { Q_Q(QDesktopWidget); const QList<QScreen *> screenList = QGuiApplication::screens(); const int targetLength = screenList.length(); - const int oldLength = screens.length(); - - // Add or remove screen widgets as necessary - while (screens.size() > targetLength) - delete screens.takeLast(); - - for (int currentLength = screens.size(); currentLength < targetLength; ++currentLength) { - QScreen *qScreen = screenList.at(currentLength); - QDesktopScreenWidget *screenWidget = new QDesktopScreenWidget; - screenWidget->setGeometry(qScreen->geometry()); - QObject::connect(qScreen, SIGNAL(geometryChanged(QRect)), - q, SLOT(_q_updateScreens()), Qt::QueuedConnection); - QObject::connect(qScreen, SIGNAL(availableGeometryChanged(QRect)), - q, SLOT(_q_availableGeometryChanged()), Qt::QueuedConnection); - QObject::connect(qScreen, SIGNAL(destroyed()), - q, SLOT(_q_updateScreens()), Qt::QueuedConnection); - screens.append(screenWidget); - } + bool screenCountChanged = false; + // Re-build our screens list. This is the easiest way to later compute which signals to emit. + // Create new screen widgets as necessary. While iterating, keep the old list in place so + // that widgetForScreen works. + // Furthermore, we note which screens have changed, and compute the overall virtual geometry. + QList<QDesktopScreenWidget *> newScreens; + QList<int> changedScreens; QRegion virtualGeometry; - // update the geometry of each screen widget, determine virtual geometry, - // set the new screen for window handle and emit change signals afterwards. - QList<int> changedScreens; - for (int i = 0; i < screens.length(); i++) { - QDesktopScreenWidget *screenWidget = screens.at(i); + for (int i = 0; i < targetLength; ++i) { QScreen *qScreen = screenList.at(i); - QWindow *winHandle = screenWidget->windowHandle(); - if (winHandle && winHandle->screen() != qScreen) - winHandle->setScreen(qScreen); const QRect screenGeometry = qScreen->geometry(); - if (screenGeometry != screenWidget->geometry()) { - screenWidget->setGeometry(screenGeometry); - changedScreens.push_back(i); + QDesktopScreenWidget *screenWidget = widgetForScreen(qScreen); + if (screenWidget) { + // an old screen. update geometry and remember the index in the *new* list + if (screenGeometry != screenWidget->screenGeometry()) { + screenWidget->setScreenGeometry(screenGeometry); + changedScreens.push_back(i); + } + } else { + // a new screen, create a widget and connect the signals. + screenWidget = new QDesktopScreenWidget(qScreen, screenGeometry); + QObject::connect(qScreen, SIGNAL(geometryChanged(QRect)), + q, SLOT(_q_updateScreens()), Qt::QueuedConnection); + QObject::connect(qScreen, SIGNAL(availableGeometryChanged(QRect)), + q, SLOT(_q_availableGeometryChanged()), Qt::QueuedConnection); + QObject::connect(qScreen, SIGNAL(destroyed()), + q, SLOT(_q_updateScreens()), Qt::QueuedConnection); + screenCountChanged = true; } + // record all the screens and the overall geometry. + newScreens.push_back(screenWidget); virtualGeometry += screenGeometry; } + // Now we apply the accumulated updates. + screens.swap(newScreens); // now [newScreens] is the old screen list + Q_ASSERT(screens.size() == targetLength); q->setGeometry(virtualGeometry.boundingRect()); - if (oldLength != targetLength) - emit q->screenCountChanged(targetLength); + // Delete the QDesktopScreenWidget that are not used any more. + foreach (QDesktopScreenWidget *screen, newScreens) { + if (!screens.contains(screen)) { + delete screen; + screenCountChanged = true; + } + } + // Finally, emit the signals. + if (screenCountChanged) { + // Notice that we trigger screenCountChanged even if a screen was removed and another one added, + // in which case the total number of screens did not change. This is the only way for applications + // to notice that a screen was swapped out against another one. + emit q->screenCountChanged(targetLength); + } foreach (int changedScreen, changedScreens) emit q->resized(changedScreen); } diff --git a/src/widgets/kernel/qdesktopwidget_p.h b/src/widgets/kernel/qdesktopwidget_p.h index 7c68ad9b31..a590024b7c 100644 --- a/src/widgets/kernel/qdesktopwidget_p.h +++ b/src/widgets/kernel/qdesktopwidget_p.h @@ -61,12 +61,19 @@ QT_BEGIN_NAMESPACE class QDesktopScreenWidget : public QWidget { Q_OBJECT public: - QDesktopScreenWidget() : QWidget(Q_NULLPTR, Qt::Desktop) - { - setVisible(false); - } + explicit QDesktopScreenWidget(QScreen *screen, const QRect &geometry); int screenNumber() const; + void setScreenGeometry(const QRect &geometry); + + QScreen *screen() const { return m_screen.data(); } + QRect screenGeometry() const { return m_geometry; } + +private: + // The widget updates its screen and geometry automatically. We need to save them separately + // to detect changes, and trigger the appropriate signals. + const QPointer<QScreen> m_screen; + QRect m_geometry; }; class QDesktopWidgetPrivate : public QWidgetPrivate { @@ -76,6 +83,7 @@ public: ~QDesktopWidgetPrivate() { qDeleteAll(screens); } void _q_updateScreens(); void _q_availableGeometryChanged(); + QDesktopScreenWidget *widgetForScreen(QScreen *qScreen) const; QList<QDesktopScreenWidget *> screens; }; diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp index 5071c56763..124c8c000a 100644 --- a/src/widgets/kernel/qopenglwidget.cpp +++ b/src/widgets/kernel/qopenglwidget.cpp @@ -910,8 +910,10 @@ void QOpenGLWidgetPrivate::resizeViewportFramebuffer() if (!initialized) return; - if (!fbo || q->size() * q->devicePixelRatioF() != fbo->size()) + if (!fbo || q->size() * q->devicePixelRatioF() != fbo->size()) { recreateFbo(); + q->update(); + } } /*! diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp index 7c9ac5571c..ecaba584f2 100644 --- a/src/widgets/kernel/qwidgetbackingstore.cpp +++ b/src/widgets/kernel/qwidgetbackingstore.cpp @@ -992,8 +992,18 @@ static QPlatformTextureList *widgetTexturesFor(QWidget *tlw, QWidget *widget) static bool switchableWidgetComposition = QGuiApplicationPrivate::instance()->platformIntegration() ->hasCapability(QPlatformIntegration::SwitchableWidgetComposition); - if (!switchableWidgetComposition) + if (!switchableWidgetComposition +// The Windows compositor handles fullscreen OpenGL window specially. Besides +// having trouble with popups, it also has issues with flip-flopping between +// OpenGL-based and normal flushing. Therefore, stick with GL for fullscreen +// windows. (QTBUG-53515) +#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) && !defined(Q_OS_WINCE) + || tlw->windowState().testFlag(Qt::WindowFullScreen) +#endif + ) + { return qt_dummy_platformTextureList(); + } } return 0; @@ -1192,10 +1202,20 @@ void QWidgetBackingStore::doSync() // We know for sure that the widget isn't overlapped if 'isMoved' is true. if (!wd->isMoved) wd->subtractOpaqueSiblings(wd->dirty, &hasDirtySiblingsAbove); + + // Make a copy of the widget's dirty region, to restore it in case there is an opaque + // render-to-texture child that completely covers the widget, because otherwise the + // render-to-texture child won't be visible, due to its parent widget not being redrawn + // with a proper blending mask. + const QRegion dirtyBeforeSubtractedOpaqueChildren = wd->dirty; + // Scrolled and moved widgets must draw all children. if (!wd->isScrolled && !wd->isMoved) wd->subtractOpaqueChildren(wd->dirty, w->rect()); + if (wd->dirty.isEmpty() && wd->textureChildSeen) + wd->dirty = dirtyBeforeSubtractedOpaqueChildren; + if (wd->dirty.isEmpty()) { resetWidget(w); continue; diff --git a/src/widgets/kernel/qwidgetbackingstore_p.h b/src/widgets/kernel/qwidgetbackingstore_p.h index a7dbfafc05..dc20446047 100644 --- a/src/widgets/kernel/qwidgetbackingstore_p.h +++ b/src/widgets/kernel/qwidgetbackingstore_p.h @@ -116,7 +116,7 @@ public: inline bool isDirty() const { - return !(dirtyWidgets.isEmpty() && dirty.isEmpty()); + return !(dirtyWidgets.isEmpty() && dirty.isEmpty() && dirtyRenderToTextureWidgets.isEmpty()); } // ### Qt 4.6: Merge into a template function (after MSVC isn't supported anymore). diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index 675d54f6b4..2a4f31babf 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -883,14 +883,8 @@ void QWidgetWindow::handleExposeEvent(QExposeEvent *event) { if (isExposed()) { m_widget->setAttribute(Qt::WA_Mapped); - if (!event->region().isNull()) { - // Exposed native widgets need to be marked dirty to get them repainted correctly. - if (m_widget->internalWinId() && !m_widget->isWindow() && m_widget->isVisible() && m_widget->updatesEnabled()) { - if (QWidgetBackingStore *bs = m_widget->d_func()->maybeBackingStore()) - bs->markDirty(event->region(), m_widget); - } + if (!event->region().isNull()) m_widget->d_func()->syncBackingStore(event->region()); - } } else { m_widget->setAttribute(Qt::WA_Mapped, false); } diff --git a/src/widgets/styles/qfusionstyle.cpp b/src/widgets/styles/qfusionstyle.cpp index 1ac28f548b..06c3101643 100644 --- a/src/widgets/styles/qfusionstyle.cpp +++ b/src/widgets/styles/qfusionstyle.cpp @@ -2389,8 +2389,7 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption if (!titleBar->icon.isNull()) { titleBar->icon.paint(painter, iconRect); } else { - QStyleOption tool(0); - tool.palette = titleBar->palette; + QStyleOption tool = *titleBar; QPixmap pm = proxy()->standardIcon(SP_TitleBarMenuButton, &tool, widget).pixmap(16, 16); tool.rect = iconRect; painter->save(); diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm index deb2fb4da0..56531b10de 100644 --- a/src/widgets/styles/qmacstyle_mac.mm +++ b/src/widgets/styles/qmacstyle_mac.mm @@ -5951,12 +5951,10 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex #ifndef QT_NO_ACCESSIBILITY if (QStyleHelper::hasAncestor(opt->styleObject, QAccessible::ToolBar)) { if (tb->subControls & SC_ToolButtonMenu) { - QStyleOption arrowOpt(0); + QStyleOption arrowOpt = *tb; arrowOpt.rect = proxy()->subControlRect(cc, tb, SC_ToolButtonMenu, widget); arrowOpt.rect.setY(arrowOpt.rect.y() + arrowOpt.rect.height() / 2); arrowOpt.rect.setHeight(arrowOpt.rect.height() / 2); - arrowOpt.state = tb->state; - arrowOpt.palette = tb->palette; proxy()->drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, p, widget); } else if ((tb->features & QStyleOptionToolButton::HasMenu) && (tb->toolButtonStyle != Qt::ToolButtonTextOnly && !tb->icon.isNull())) { diff --git a/src/widgets/styles/qwindowsstyle.cpp b/src/widgets/styles/qwindowsstyle.cpp index 7ce9bbc273..b41ad4249e 100644 --- a/src/widgets/styles/qwindowsstyle.cpp +++ b/src/widgets/styles/qwindowsstyle.cpp @@ -2131,9 +2131,8 @@ void QWindowsStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComp if (sunkenArrow) flags |= State_Sunken; - QStyleOption arrowOpt(0); + QStyleOption arrowOpt = *cmb; arrowOpt.rect = ar.adjusted(1, 1, -1, -1); - arrowOpt.palette = cmb->palette; arrowOpt.state = flags; proxy()->drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, p, widget); } diff --git a/src/widgets/styles/qwindowsvistastyle.cpp b/src/widgets/styles/qwindowsvistastyle.cpp index 83820016aa..6009b5d1f8 100644 --- a/src/widgets/styles/qwindowsvistastyle.cpp +++ b/src/widgets/styles/qwindowsvistastyle.cpp @@ -1059,7 +1059,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption QPainter imagePainter(&image); theme.painter = &imagePainter; theme.partId = vertical ? PP_FILLVERT : PP_FILL; - theme.rect = QRect(QPoint(0,0), theme.rect.size()); + theme.rect = QRect(QPoint(0,0), animRect.size()); QLinearGradient alphaGradient(0, 0, vertical ? 0 : image.width(), vertical ? image.height() : 0); alphaGradient.setColorAt(0, QColor(0, 0, 0, 0)); diff --git a/src/widgets/styles/qwindowsxpstyle.cpp b/src/widgets/styles/qwindowsxpstyle.cpp index 916210ad09..2fbc40dc11 100644 --- a/src/widgets/styles/qwindowsxpstyle.cpp +++ b/src/widgets/styles/qwindowsxpstyle.cpp @@ -2866,8 +2866,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo } } - QStyleOption tool(0); - tool.palette = toolbutton->palette; + QStyleOption tool = *toolbutton; if (toolbutton->subControls & SC_ToolButton) { if (flags & (State_Sunken | State_On | State_Raised) || !autoRaise) { if (toolbutton->features & QStyleOptionToolButton::MenuButtonPopup && autoRaise) { diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp index c03c96333a..cb99b58d97 100644 --- a/src/widgets/widgets/qmenu.cpp +++ b/src/widgets/widgets/qmenu.cpp @@ -2744,10 +2744,15 @@ QMenu::event(QEvent *e) return true; } } break; - case QEvent::ContextMenu: - if (d->delayState.timer.isActive()) { - d->delayState.stop(); - internalDelayedPopup(); + case QEvent::MouseButtonPress: + case QEvent::ContextMenu: { + bool canPopup = true; + if (e->type() == QEvent::MouseButtonPress) + canPopup = (static_cast<QMouseEvent*>(e)->button() == Qt::LeftButton); + if (canPopup && d->delayState.timer.isActive()) { + d->delayState.stop(); + internalDelayedPopup(); + } } break; case QEvent::Resize: { diff --git a/src/widgets/widgets/qwidgetlinecontrol.cpp b/src/widgets/widgets/qwidgetlinecontrol.cpp index 23d52b278d..66f17dbe33 100644 --- a/src/widgets/widgets/qwidgetlinecontrol.cpp +++ b/src/widgets/widgets/qwidgetlinecontrol.cpp @@ -717,7 +717,7 @@ bool QWidgetLineControl::finishChange(int validateFromState, bool update, bool e if (m_transactions.count()) return false; internalUndo(validateFromState); - m_history.resize(m_undoState); + m_history.erase(m_history.begin() + m_undoState, m_history.end()); if (m_modifiedState > m_undoState) m_modifiedState = -1; m_validInput = true; @@ -796,14 +796,14 @@ void QWidgetLineControl::internalSetText(const QString &txt, int pos, bool edite */ void QWidgetLineControl::addCommand(const Command &cmd) { - if (m_separator && m_undoState && m_history[m_undoState - 1].type != Separator) { - m_history.resize(m_undoState + 2); - m_history[m_undoState++] = Command(Separator, m_cursor, 0, m_selstart, m_selend); - } else { - m_history.resize(m_undoState + 1); - } + m_history.erase(m_history.begin() + m_undoState, m_history.end()); + + if (m_separator && m_undoState && m_history[m_undoState - 1].type != Separator) + m_history.push_back(Command(Separator, m_cursor, 0, m_selstart, m_selend)); + m_separator = false; - m_history[m_undoState++] = cmd; + m_history.push_back(cmd); + m_undoState = int(m_history.size()); } /*! @@ -1563,6 +1563,7 @@ void QWidgetLineControl::processShortcutOverrideEvent(QKeyEvent *ke) if (ke == QKeySequence::Copy || ke == QKeySequence::MoveToNextWord || ke == QKeySequence::MoveToPreviousWord + || ke == QKeySequence::MoveToStartOfLine || ke == QKeySequence::MoveToEndOfLine || ke == QKeySequence::MoveToStartOfDocument || ke == QKeySequence::MoveToEndOfDocument @@ -1957,7 +1958,7 @@ bool QWidgetLineControl::isRedoAvailable() const // Same as with undo. Disabled for password modes. return !m_readOnly && m_echoMode == QLineEdit::Normal - && m_undoState < m_history.size(); + && m_undoState < int(m_history.size()); } QT_END_NAMESPACE diff --git a/src/widgets/widgets/qwidgetlinecontrol_p.h b/src/widgets/widgets/qwidgetlinecontrol_p.h index 34d19d1e77..5e52e29a51 100644 --- a/src/widgets/widgets/qwidgetlinecontrol_p.h +++ b/src/widgets/widgets/qwidgetlinecontrol_p.h @@ -67,6 +67,8 @@ #include "qplatformdefs.h" +#include <vector> + #ifdef DrawText # undef DrawText #endif @@ -469,7 +471,6 @@ private: // undo/redo handling enum CommandType { Separator, Insert, Remove, Delete, RemoveSelection, DeleteSelection, SetSelection }; struct Command { - inline Command() {} inline Command(CommandType t, int p, QChar c, int ss, int se) : type(t),uc(c),pos(p),selStart(ss),selEnd(se) {} uint type : 4; QChar uc; @@ -477,7 +478,7 @@ private: }; int m_modifiedState; int m_undoState; - QVector<Command> m_history; + std::vector<Command> m_history; void addCommand(const Command& cmd); inline void separate() { m_separator = true; } |