summaryrefslogtreecommitdiffstats
path: root/src/widgets
diff options
context:
space:
mode:
Diffstat (limited to 'src/widgets')
-rw-r--r--src/widgets/dialogs/qdialog.cpp6
-rw-r--r--src/widgets/itemviews/qabstractitemview.cpp3
-rw-r--r--src/widgets/kernel/qdesktopwidget.cpp99
-rw-r--r--src/widgets/kernel/qdesktopwidget_p.h16
-rw-r--r--src/widgets/kernel/qopenglwidget.cpp4
-rw-r--r--src/widgets/kernel/qwidgetbackingstore.cpp22
-rw-r--r--src/widgets/kernel/qwidgetbackingstore_p.h2
-rw-r--r--src/widgets/kernel/qwidgetwindow.cpp8
-rw-r--r--src/widgets/styles/qfusionstyle.cpp3
-rw-r--r--src/widgets/styles/qmacstyle_mac.mm4
-rw-r--r--src/widgets/styles/qwindowsstyle.cpp3
-rw-r--r--src/widgets/styles/qwindowsvistastyle.cpp2
-rw-r--r--src/widgets/styles/qwindowsxpstyle.cpp3
-rw-r--r--src/widgets/widgets/qmenu.cpp13
-rw-r--r--src/widgets/widgets/qwidgetlinecontrol.cpp19
-rw-r--r--src/widgets/widgets/qwidgetlinecontrol_p.h5
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; }