summaryrefslogtreecommitdiffstats
path: root/src/widgets
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2019-06-25 11:17:32 +0200
committerLiang Qi <liang.qi@qt.io>2019-06-25 13:04:27 +0200
commitef37ab9970ffb9347bc95a3e6006de956c0155c9 (patch)
tree4c6afb6d232c6ed8aab732763ef895e8bd85ec55 /src/widgets
parent79bdc7cf1daec75df59de9236599a9f24077511a (diff)
parent5b5e8f78fecbe2bd9279bfa9ef10015cef8b1bc7 (diff)
Merge remote-tracking branch 'origin/5.12' into dev
Conflicts: .qmake.conf src/gui/painting/qdrawhelper.cpp src/gui/text/qdistancefield.cpp src/gui/text/qdistancefield_p.h src/network/ssl/qsslsocket_openssl.cpp src/plugins/platforms/android/qandroidinputcontext.cpp src/widgets/styles/qstylesheetstyle.cpp Done-With: Timur Pocheptsov <timur.pocheptsov@qt.io> Change-Id: Ia7daad21f077ea889898f17734ec46303e71fe6b
Diffstat (limited to 'src/widgets')
-rw-r--r--src/widgets/kernel/qapplication.cpp59
-rw-r--r--src/widgets/kernel/qwidget.cpp81
-rw-r--r--src/widgets/kernel/qwidget_p.h2
-rw-r--r--src/widgets/styles/qstylesheetstyle.cpp54
-rw-r--r--src/widgets/widgets/qmdisubwindow.cpp16
-rw-r--r--src/widgets/widgets/qmenu.cpp12
-rw-r--r--src/widgets/widgets/qmenu_p.h2
-rw-r--r--src/widgets/widgets/qmenubar.cpp15
8 files changed, 118 insertions, 123 deletions
diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp
index ba8878be57..526bf0a0ff 100644
--- a/src/widgets/kernel/qapplication.cpp
+++ b/src/widgets/kernel/qapplication.cpp
@@ -381,8 +381,6 @@ QWidget *QApplication::topLevelAt(const QPoint &pos)
0 if there is no such widget.
*/
-void qt_init(QApplicationPrivate *priv, int type
- );
void qt_init_tooltip_palette();
void qt_cleanup();
@@ -428,16 +426,10 @@ bool Q_WIDGETS_EXPORT qt_tab_all_widgets()
// ######## move to QApplicationPrivate
// Default application palettes and fonts (per widget type)
Q_GLOBAL_STATIC(PaletteHash, app_palettes)
-PaletteHash *qt_app_palettes_hash()
-{
- return app_palettes();
-}
-
Q_GLOBAL_STATIC(FontHash, app_fonts)
-FontHash *qt_app_fonts_hash()
-{
- return app_fonts();
-}
+// Exported accessors for use outside of this file
+PaletteHash *qt_app_palettes_hash() { return app_palettes(); }
+FontHash *qt_app_fonts_hash() { return app_fonts(); }
QWidgetList *QApplicationPrivate::popupWidgets = 0; // has keyboard input focus
@@ -571,7 +563,10 @@ void QApplicationPrivate::init()
process_cmdline();
// Must be called before initialize()
- qt_init(this, application_type);
+ QColormap::initialize();
+ qt_init_tooltip_palette();
+ QApplicationPrivate::initializeWidgetFontHash();
+
initialize();
eventDispatcher->startingUp();
@@ -582,18 +577,6 @@ void QApplicationPrivate::init()
}
-void qt_init(QApplicationPrivate *priv, int type)
-{
- Q_UNUSED(priv);
- Q_UNUSED(type);
-
- QColormap::initialize();
-
- qt_init_tooltip_palette();
-
- QApplicationPrivate::initializeWidgetFontHash();
-}
-
void qt_init_tooltip_palette()
{
#ifndef QT_NO_TOOLTIP
@@ -659,7 +642,7 @@ void QApplicationPrivate::initializeWidgetPaletteHash()
QPlatformTheme *platformTheme = QGuiApplicationPrivate::platformTheme();
if (!platformTheme)
return;
- qt_app_palettes_hash()->clear();
+ app_palettes()->clear();
setPossiblePalette(platformTheme->palette(QPlatformTheme::ToolButtonPalette), "QToolButton");
setPossiblePalette(platformTheme->palette(QPlatformTheme::ButtonPalette), "QAbstractButton");
@@ -683,7 +666,7 @@ void QApplicationPrivate::initializeWidgetFontHash()
const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme();
if (!theme)
return;
- FontHash *fontHash = qt_app_fonts_hash();
+ FontHash *fontHash = app_fonts();
fontHash->clear();
if (const QFont *font = theme->font(QPlatformTheme::MenuFont))
@@ -1162,9 +1145,7 @@ void QApplication::setStyle(QStyle *style)
} else if (QApplicationPrivate::sys_pal) {
clearSystemPalette();
initSystemPalette();
- QApplicationPrivate::initializeWidgetPaletteHash();
QApplicationPrivate::initializeWidgetFontHash();
- QApplicationPrivate::setPalette_helper(*QApplicationPrivate::sys_pal, /*className=*/0, /*clearWidgetPaletteHash=*/false);
} else if (!QApplicationPrivate::sys_pal) {
// Initialize the sys_pal if it hasn't happened yet...
QApplicationPrivate::setSystemPalette(QApplicationPrivate::app_style->standardPalette());
@@ -1462,28 +1443,10 @@ void QApplication::setPalette(const QPalette &palette, const char* className)
void QApplicationPrivate::setSystemPalette(const QPalette &pal)
{
- QPalette adjusted;
-
-#if 0
- // adjust the system palette to avoid dithering
- QColormap cmap = QColormap::instance();
- if (cmap.depths() > 4 && cmap.depths() < 24) {
- for (int g = 0; g < QPalette::NColorGroups; g++)
- for (int i = 0; i < QPalette::NColorRoles; i++) {
- QColor color = pal.color((QPalette::ColorGroup)g, (QPalette::ColorRole)i);
- color = cmap.colorAt(cmap.pixel(color));
- adjusted.setColor((QPalette::ColorGroup)g, (QPalette::ColorRole) i, color);
- }
- }
-#else
- adjusted = pal;
-#endif
-
if (!sys_pal)
- sys_pal = new QPalette(adjusted);
+ sys_pal = new QPalette(pal);
else
- *sys_pal = adjusted;
-
+ *sys_pal = pal;
if (!QApplicationPrivate::set_pal)
QApplication::setPalette(*sys_pal);
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index be2906a743..2176c612d0 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -1,4 +1,4 @@
-/****************************************************************************
+/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Copyright (C) 2016 Intel Corporation.
@@ -2617,14 +2617,27 @@ bool QWidgetPrivate::setScreenForPoint(const QPoint &pos)
Q_Q(QWidget);
if (!q->isWindow())
return false;
- // Find the screen for pos and make the widget undertand it is on that screen.
+ // Find the screen for pos and make the widget understand it is on that screen.
+ return setScreen(QGuiApplication::screenAt(pos));
+}
+
+/*!
+\internal
+Ensures that the widget's QWindow is set to be on the given \a screen.
+Returns true if the screen was changed.
+*/
+
+bool QWidgetPrivate::setScreen(QScreen *screen)
+{
+ Q_Q(QWidget);
+ if (!screen || !q->isWindow())
+ return false;
const QScreen *currentScreen = windowHandle() ? windowHandle()->screen() : nullptr;
- QScreen *actualScreen = QGuiApplication::screenAt(pos);
- if (actualScreen && currentScreen != actualScreen) {
+ if (currentScreen != screen) {
if (!windowHandle()) // Try to create a window handle if not created.
createWinId();
if (windowHandle())
- windowHandle()->setScreen(actualScreen);
+ windowHandle()->setScreen(screen);
return true;
}
return false;
@@ -7025,37 +7038,41 @@ void QWidget::setTabOrder(QWidget* first, QWidget *second)
lastFocusChild = focusNext;
}
};
+ auto setPrev = [](QWidget *w, QWidget *prev)
+ {
+ w->d_func()->focus_prev = prev;
+ };
+ auto setNext = [](QWidget *w, QWidget *next)
+ {
+ w->d_func()->focus_next = next;
+ };
- QWidget *lastFocusChildOfFirst, *lastFocusChildOfSecond;
- determineLastFocusChild(first, lastFocusChildOfFirst);
+ // remove the second widget from the chain
+ QWidget *lastFocusChildOfSecond;
determineLastFocusChild(second, lastFocusChildOfSecond);
-
- // If the tab order is already correct, exit early
- if (lastFocusChildOfFirst == second ||
- lastFocusChildOfFirst->d_func()->focus_next == second) {
- return;
+ {
+ QWidget *oldPrev = second->d_func()->focus_prev;
+ QWidget *prevWithFocus = oldPrev;
+ while (prevWithFocus->focusPolicy() == Qt::NoFocus)
+ prevWithFocus = prevWithFocus->d_func()->focus_prev;
+ // only widgets between first and second -> all is fine
+ if (prevWithFocus == first)
+ return;
+ QWidget *oldNext = lastFocusChildOfSecond->d_func()->focus_next;
+ setPrev(oldNext, oldPrev);
+ setNext(oldPrev, oldNext);
}
- // Note that we need to handle two different sections in the tab chain; The section
- // that 'first' belongs to (firstSection), where we are about to insert 'second', and
- // the section that 'second' used be a part of (secondSection). When we pull 'second'
- // out of the second section and insert it into the first, we also need to ensure
- // that we leave the second section in a connected state.
- QWidget *firstChainOldSecond = lastFocusChildOfFirst->d_func()->focus_next;
- QWidget *secondChainNewFirst = second->d_func()->focus_prev;
- QWidget *secondChainNewSecond = lastFocusChildOfSecond->d_func()->focus_next;
-
- // Insert 'second' after 'first'
- lastFocusChildOfFirst->d_func()->focus_next = second;
- second->d_func()->focus_prev = lastFocusChildOfFirst;
-
- // The widget that used to be 'second' in the first section, should now become 'third'
- lastFocusChildOfSecond->d_func()->focus_next = firstChainOldSecond;
- firstChainOldSecond->d_func()->focus_prev = lastFocusChildOfSecond;
-
- // Repair the second section after we pulled 'second' out of it
- secondChainNewFirst->d_func()->focus_next = secondChainNewSecond;
- secondChainNewSecond->d_func()->focus_prev = secondChainNewFirst;
+ // insert the second widget into the chain
+ QWidget *lastFocusChildOfFirst;
+ determineLastFocusChild(first, lastFocusChildOfFirst);
+ {
+ QWidget *oldNext = lastFocusChildOfFirst->d_func()->focus_next;
+ setPrev(second, lastFocusChildOfFirst);
+ setNext(lastFocusChildOfFirst, second);
+ setPrev(oldNext, lastFocusChildOfSecond);
+ setNext(lastFocusChildOfSecond, oldNext);
+ }
}
/*!\internal
diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h
index 1f36c192f5..99ec38e050 100644
--- a/src/widgets/kernel/qwidget_p.h
+++ b/src/widgets/kernel/qwidget_p.h
@@ -181,6 +181,7 @@ struct QTLWExtra {
QRect frameStrut;
QRect normalGeometry; // used by showMin/maximized/FullScreen
Qt::WindowFlags savedFlags; // Save widget flags while showing fullscreen
+ // ### TODO replace initialScreenIndex with QScreen *, in case the screens change at runtime
int initialScreenIndex; // Screen number when passing a QDesktop[Screen]Widget as parent.
QVector<QPlatformTextureList *> widgetTextures;
@@ -364,6 +365,7 @@ public:
void createWinId();
bool setScreenForPoint(const QPoint &pos);
+ bool setScreen(QScreen *screen);
void createTLExtra();
void createExtra();
diff --git a/src/widgets/styles/qstylesheetstyle.cpp b/src/widgets/styles/qstylesheetstyle.cpp
index 025e1e0044..c1f498cd0c 100644
--- a/src/widgets/styles/qstylesheetstyle.cpp
+++ b/src/widgets/styles/qstylesheetstyle.cpp
@@ -3706,17 +3706,6 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
bool dis = !(opt->state & QStyle::State_Enabled),
act = opt->state & QStyle::State_Selected;
- int checkableOffset = 0;
- if (checkable) {
- QRenderRule subSubRule = renderRule(w, opt, PseudoElement_MenuCheckMark);
- QStyleOptionMenuItem newMi = mi;
- newMi.rect = positionRect(w, subRule, subSubRule, PseudoElement_MenuCheckMark, opt->rect, opt->direction);
- // align with icons if there are some
- checkableOffset = std::max(m->maxIconWidth, newMi.rect.width());
- if (subSubRule.hasDrawable() || checked)
- drawPrimitive(PE_IndicatorMenuCheckMark, &newMi, p, w);
- }
-
if (!mi.icon.isNull()) {
QIcon::Mode mode = dis ? QIcon::Disabled : QIcon::Normal;
if (act && !dis)
@@ -3733,24 +3722,28 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
}
QRect iconRect = positionRect(w, subRule, iconRule, PseudoElement_MenuIcon, opt->rect, opt->direction);
if (opt->direction == Qt::LeftToRight)
- iconRect.moveLeft(iconRect.left() + checkableOffset);
+ iconRect.moveLeft(iconRect.left());
else
- iconRect.moveRight(iconRect.right() - checkableOffset);
+ iconRect.moveRight(iconRect.right());
iconRule.drawRule(p, iconRect);
QRect pmr(0, 0, pixw, pixh);
pmr.moveCenter(iconRect.center());
p->drawPixmap(pmr.topLeft(), pixmap);
+ } else if (checkable) {
+ QRenderRule subSubRule = renderRule(w, opt, PseudoElement_MenuCheckMark);
+ if (subSubRule.hasDrawable() || checked) {
+ QStyleOptionMenuItem newMi = mi;
+ if (!dis)
+ newMi.state |= State_Enabled;
+ if (act)
+ newMi.state |= State_On;
+ newMi.rect = positionRect(w, subRule, subSubRule, PseudoElement_MenuCheckMark, opt->rect, opt->direction);
+ drawPrimitive(PE_IndicatorMenuCheckMark, &newMi, p, w);
+ }
}
- int textOffset = 0;
- // padding overrules it all
- if (!subRule.hasBox() || subRule.box()->paddings[LeftEdge] == 0) {
- textOffset = checkableOffset;
- if (!m->icon.isNull() || !checkable)
- textOffset += m->maxIconWidth;
- }
QRect textRect = subRule.contentsRect(opt->rect);
- textRect.setLeft(textRect.left() + textOffset);
+ textRect.setLeft(textRect.left() + m->maxIconWidth);
textRect.setWidth(textRect.width() - mi.tabWidth);
const QRect vTextRect = visualRect(opt->direction, m->rect, textRect);
@@ -5106,27 +5099,20 @@ QSize QStyleSheetStyle::sizeFromContents(ContentsType ct, const QStyleOption *op
if (mi->text.contains(QLatin1Char('\t')))
sz.rwidth() += 12; //as in QCommonStyle
bool checkable = mi->checkType != QStyleOptionMenuItem::NotCheckable;
- int checkableWidth = 0;
- if (checkable) {
+ if (!mi->icon.isNull()) {
+ const int pmSmall = pixelMetric(PM_SmallIconSize);
+ const QSize pmSize = mi->icon.actualSize(QSize(pmSmall, pmSmall));
+ sz.rwidth() += pmSize.width() + 4;
+ } else if (checkable) {
QRenderRule subSubRule = renderRule(w, opt, PseudoElement_MenuCheckMark);
QRect checkmarkRect = positionRect(w, subRule, subSubRule, PseudoElement_MenuCheckMark, opt->rect, opt->direction);
- checkableWidth = std::max(mi->maxIconWidth, checkmarkRect.width());
- }
- if (!mi->icon.isNull()) {
- QPixmap pixmap = mi->icon.pixmap(pixelMetric(PM_SmallIconSize));
- sz.rwidth() += pixmap.width();
+ sz.rwidth() += std::max(mi->maxIconWidth, checkmarkRect.width()) + 4;
}
if (subRule.hasFont) {
QFontMetrics fm(subRule.font);
const QRect r = fm.boundingRect(QRect(), Qt::TextSingleLine | Qt::TextShowMnemonic, mi->text);
sz = sz.expandedTo(r.size());
}
- // padding overrules it all
- if (!subRule.hasBox() || subRule.box()->paddings[LeftEdge] == 0) {
- sz.rwidth() += checkableWidth;
- if (!mi->icon.isNull() || !checkable)
- sz.rwidth() += mi->maxIconWidth;
- }
return subRule.boxSize(subRule.adjustSize(sz));
}
}
diff --git a/src/widgets/widgets/qmdisubwindow.cpp b/src/widgets/widgets/qmdisubwindow.cpp
index e25bc6de7a..685c5e159e 100644
--- a/src/widgets/widgets/qmdisubwindow.cpp
+++ b/src/widgets/widgets/qmdisubwindow.cpp
@@ -3141,8 +3141,6 @@ void QMdiSubWindow::paintEvent(QPaintEvent *paintEvent)
}
Q_D(QMdiSubWindow);
- if (isMaximized() && !d->drawTitleBarWhenMaximized())
- return;
if (d->resizeTimerId != -1) {
// Only update the style option rect and the window title.
@@ -3162,6 +3160,17 @@ void QMdiSubWindow::paintEvent(QPaintEvent *paintEvent)
}
QStylePainter painter(this);
+ QStyleOptionFrame frameOptions;
+ frameOptions.initFrom(this);
+ frameOptions.state.setFlag(QStyle::State_Active, d->isActive);
+ if (isMaximized() && !d->drawTitleBarWhenMaximized()) {
+ if (!autoFillBackground() && (!widget() || !qt_widget_private(widget())->isOpaque)) {
+ // make sure we paint all pixels of a maximized QMdiSubWindow if no-one else does
+ painter.drawPrimitive(QStyle::PE_FrameWindow, frameOptions);
+ }
+ return;
+ }
+
if (!d->windowTitle.isEmpty())
painter.setFont(d->font);
painter.drawComplexControl(QStyle::CC_TitleBar, d->cachedStyleOptions);
@@ -3169,10 +3178,7 @@ void QMdiSubWindow::paintEvent(QPaintEvent *paintEvent)
if (isMinimized() && !d->hasBorder(d->cachedStyleOptions))
return;
- QStyleOptionFrame frameOptions;
- frameOptions.initFrom(this);
frameOptions.lineWidth = style()->pixelMetric(QStyle::PM_MdiSubWindowFrameWidth, 0, this);
- frameOptions.state.setFlag(QStyle::State_Active, d->isActive);
// ### Ensure that we do not require setting the cliprect for 4.4
if (!isMinimized() && !d->hasBorder(d->cachedStyleOptions))
diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp
index 287be3e272..7b6a1b6da8 100644
--- a/src/widgets/widgets/qmenu.cpp
+++ b/src/widgets/widgets/qmenu.cpp
@@ -2331,8 +2331,18 @@ void QMenu::popup(const QPoint &p, QAction *atAction)
d->updateLayoutDirection();
// Ensure that we get correct sizeHints by placing this window on the correct screen.
- if (d->setScreenForPoint(p))
+ // However if the QMenu was constructed with a QDesktopScreenWidget as its parent,
+ // then initialScreenIndex was set, so we should respect that for the lifetime of this menu.
+ // Use d->popupScreen to remember, because initialScreenIndex will be reset after the first showing.
+ const int screenIndex = d->topData()->initialScreenIndex;
+ if (screenIndex >= 0)
+ d->popupScreen = screenIndex;
+ if (auto s = QGuiApplication::screens().value(d->popupScreen)) {
+ if (d->setScreen(s))
+ d->itemsDirty = true;
+ } else if (d->setScreenForPoint(p)) {
d->itemsDirty = true;
+ }
const bool contextMenu = d->isContextMenu();
if (d->lastContextMenu != contextMenu) {
diff --git a/src/widgets/widgets/qmenu_p.h b/src/widgets/widgets/qmenu_p.h
index ef152cd71b..efbbc099a1 100644
--- a/src/widgets/widgets/qmenu_p.h
+++ b/src/widgets/widgets/qmenu_p.h
@@ -515,6 +515,8 @@ public:
bool tearoffHighlighted : 1;
//menu fading/scrolling effects
bool doChildEffects : 1;
+
+ int popupScreen = -1;
};
QT_END_NAMESPACE
diff --git a/src/widgets/widgets/qmenubar.cpp b/src/widgets/widgets/qmenubar.cpp
index a53d7841f4..9a60f1477d 100644
--- a/src/widgets/widgets/qmenubar.cpp
+++ b/src/widgets/widgets/qmenubar.cpp
@@ -68,6 +68,7 @@
#include "qmenu_p.h"
#include "qmenubar_p.h"
+#include <private/qscreen_p.h>
#include "qdebug.h"
QT_BEGIN_NAMESPACE
@@ -322,11 +323,18 @@ void QMenuBarPrivate::popupAction(QAction *action, bool activateFirst)
QRect adjustedActionRect = actionRect(action);
QPoint pos(q->mapToGlobal(QPoint(adjustedActionRect.left(), adjustedActionRect.bottom() + 1)));
QSize popup_size = activeMenu->sizeHint();
-
//we put the popup menu on the screen containing the bottom-center of the action rect
- QRect screenRect = QDesktopWidgetPrivate::screenGeometry(pos + QPoint(adjustedActionRect.width() / 2, 0));
+ QScreen *popupScreen = q->window()->windowHandle()->screen();
+ QPoint bottomMiddlePos = pos + QPoint(adjustedActionRect.width() / 2, 0);
+ const auto &siblings = popupScreen->virtualSiblings();
+ for (QScreen *sibling : siblings) {
+ if (sibling->geometry().contains(bottomMiddlePos)) {
+ popupScreen = sibling;
+ break;
+ }
+ }
+ QRect screenRect = popupScreen->geometry();
pos = QPoint(qMax(pos.x(), screenRect.x()), qMax(pos.y(), screenRect.y()));
-
const bool fitUp = (pos.y() - popup_size.height() >= screenRect.top());
const bool fitDown = (pos.y() + popup_size.height() <= screenRect.bottom());
const bool rtl = q->isRightToLeft();
@@ -352,6 +360,7 @@ void QMenuBarPrivate::popupAction(QAction *action, bool activateFirst)
if(!defaultPopDown || (fitUp && !fitDown))
pos.setY(qMax(screenRect.y(), q->mapToGlobal(QPoint(0, adjustedActionRect.top()-popup_size.height())).y()));
+ QMenuPrivate::get(activeMenu)->topData()->initialScreenIndex = QGuiApplication::screens().indexOf(popupScreen);
activeMenu->popup(pos);
if(activateFirst)
activeMenu->d_func()->setFirstActionActive();