diff options
author | Liang Qi <liang.qi@qt.io> | 2019-06-25 11:17:32 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2019-06-25 13:04:27 +0200 |
commit | ef37ab9970ffb9347bc95a3e6006de956c0155c9 (patch) | |
tree | 4c6afb6d232c6ed8aab732763ef895e8bd85ec55 /src/widgets | |
parent | 79bdc7cf1daec75df59de9236599a9f24077511a (diff) | |
parent | 5b5e8f78fecbe2bd9279bfa9ef10015cef8b1bc7 (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.cpp | 59 | ||||
-rw-r--r-- | src/widgets/kernel/qwidget.cpp | 81 | ||||
-rw-r--r-- | src/widgets/kernel/qwidget_p.h | 2 | ||||
-rw-r--r-- | src/widgets/styles/qstylesheetstyle.cpp | 54 | ||||
-rw-r--r-- | src/widgets/widgets/qmdisubwindow.cpp | 16 | ||||
-rw-r--r-- | src/widgets/widgets/qmenu.cpp | 12 | ||||
-rw-r--r-- | src/widgets/widgets/qmenu_p.h | 2 | ||||
-rw-r--r-- | src/widgets/widgets/qmenubar.cpp | 15 |
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(); |