Merge remote-tracking branch 'origin/5.11' into dev

Change-Id: I0bea38585382b5d9c8d7a013bf6bcb3a6008d159
This commit is contained in:
Qt Forward Merge Bot 2018-04-20 21:22:53 +02:00
commit 6f45fda50b
26 changed files with 392 additions and 435 deletions

View File

@ -292,6 +292,7 @@ Gui, printing, widget options:
(-qt-xcb still uses system version of libxcb itself) (-qt-xcb still uses system version of libxcb itself)
Input backends: Input backends:
-libudev............ Enable udev support [auto]
-evdev ............. Enable evdev support [auto] -evdev ............. Enable evdev support [auto]
-imf ............... Enable IMF support [auto] (QNX only) -imf ............... Enable IMF support [auto] (QNX only)
-libinput .......... Enable libinput support [auto] -libinput .......... Enable libinput support [auto]

View File

@ -8,21 +8,21 @@ contains(QMAKE_MAC_SDK, .*/.*): \
defineReplace(xcodeSDKInfo) { defineReplace(xcodeSDKInfo) {
info = $$1 info = $$1
equals(info, "Path"): \ equals(info, "Path"): \
info = --show-sdk-path infoarg = --show-sdk-path
equals(info, "PlatformPath"): \ equals(info, "PlatformPath"): \
info = --show-sdk-platform-path infoarg = --show-sdk-platform-path
equals(info, "SDKVersion"): \ equals(info, "SDKVersion"): \
info = --show-sdk-version infoarg = --show-sdk-version
sdk = $$2 sdk = $$2
isEmpty(sdk): \ isEmpty(sdk): \
sdk = $$QMAKE_MAC_SDK sdk = $$QMAKE_MAC_SDK
isEmpty(QMAKE_MAC_SDK.$${sdk}.$${info}) { isEmpty(QMAKE_MAC_SDK.$${sdk}.$${info}) {
QMAKE_MAC_SDK.$${sdk}.$${info} = $$system("/usr/bin/xcrun --sdk $$sdk $$info 2>/dev/null") QMAKE_MAC_SDK.$${sdk}.$${info} = $$system("/usr/bin/xcrun --sdk $$sdk $$infoarg 2>/dev/null")
# --show-sdk-platform-path won't work for Command Line Tools; this is fine # --show-sdk-platform-path won't work for Command Line Tools; this is fine
# only used by the XCTest backend to testlib # only used by the XCTest backend to testlib
isEmpty(QMAKE_MAC_SDK.$${sdk}.$${info}):if(!isEmpty(QMAKE_XCODEBUILD_PATH)|!equals(info, "--show-sdk-platform-path")): \ isEmpty(QMAKE_MAC_SDK.$${sdk}.$${info}):if(!isEmpty(QMAKE_XCODEBUILD_PATH)|!equals(infoarg, "--show-sdk-platform-path")): \
error("Could not resolve SDK $$info for \'$$sdk\'") error("Could not resolve SDK $$info for \'$$sdk\' using $$infoarg")
cache(QMAKE_MAC_SDK.$${sdk}.$${info}, set stash, QMAKE_MAC_SDK.$${sdk}.$${info}) cache(QMAKE_MAC_SDK.$${sdk}.$${info}, set stash, QMAKE_MAC_SDK.$${sdk}.$${info})
} }

View File

@ -1,7 +1,6 @@
!isEmpty(SOURCES) { !isEmpty(SOURCES) {
QT += qml qmltest QT += qml qmltest
load(testcase) load(testcase)
CONFIG -= app_bundle
DEFINES += QUICK_TEST_SOURCE_DIR=\"\\\"$$_PRO_FILE_PWD_\\\"\" DEFINES += QUICK_TEST_SOURCE_DIR=\"\\\"$$_PRO_FILE_PWD_\\\"\"
} else { } else {
# Allow a project to run tests without a CPP stub # Allow a project to run tests without a CPP stub

View File

@ -172,9 +172,10 @@ QFuture<QImage> thumbNails =
//! [13] //! [13]
QList<QImage> images = ...; QList<QImage> images = ...;
QFuture<QImage> thumbnails = QtConcurrent::mapped(images, [](const QImage &img) { std::function<QImage(const QImage &)> scale = [](const QImage &img) {
return img.scaledToWidth(100, Qt::SmoothTransformation); return img.scaledToWidth(100, Qt::SmoothTransformation);
}); };
QFuture<QImage> thumbnails = QtConcurrent::mapped(images, scale);
//! [13] //! [13]
//! [14] //! [14]

View File

@ -347,15 +347,15 @@ Qt::Key qt_mac_cocoaKey2QtKey(QChar keyCode)
void qt_apple_check_os_version() void qt_apple_check_os_version()
{ {
#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) #if defined(__WATCH_OS_VERSION_MIN_REQUIRED)
const char *os = "iOS"; const char *os = "watchOS";
const int version = __IPHONE_OS_VERSION_MIN_REQUIRED; const int version = __WATCH_OS_VERSION_MIN_REQUIRED;
#elif defined(__TV_OS_VERSION_MIN_REQUIRED) #elif defined(__TV_OS_VERSION_MIN_REQUIRED)
const char *os = "tvOS"; const char *os = "tvOS";
const int version = __TV_OS_VERSION_MIN_REQUIRED; const int version = __TV_OS_VERSION_MIN_REQUIRED;
#elif defined(__WATCH_OS_VERSION_MIN_REQUIRED) #elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
const char *os = "watchOS"; const char *os = "iOS";
const int version = __WATCH_OS_VERSION_MIN_REQUIRED; const int version = __IPHONE_OS_VERSION_MIN_REQUIRED;
#elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED) #elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
const char *os = "macOS"; const char *os = "macOS";
const int version = __MAC_OS_X_VERSION_MIN_REQUIRED; const int version = __MAC_OS_X_VERSION_MIN_REQUIRED;

View File

@ -309,7 +309,7 @@
\endomit \endomit
\sa QSharedDataPointer, QWeakPointer, QScopedPointer \sa QSharedDataPointer, QWeakPointer, QScopedPointer, QEnableSharedFromThis
*/ */
/*! /*!

View File

@ -41,6 +41,8 @@
#include "qnetworkinterface_p.h" #include "qnetworkinterface_p.h"
#include "qnetworkinterface_unix_p.h" #include "qnetworkinterface_unix_p.h"
#ifndef QT_NO_NETWORKINTERFACE
#include <qendian.h> #include <qendian.h>
#include <qobjectdefs.h> #include <qobjectdefs.h>
#include <qvarlengtharray.h> #include <qvarlengtharray.h>
@ -448,3 +450,5 @@ QList<QNetworkInterfacePrivate *> QNetworkInterfaceManager::scan()
} }
QT_END_NAMESPACE QT_END_NAMESPACE
#endif // QT_NO_NETWORKINTERFACE

View File

@ -226,7 +226,6 @@ bool shouldBeIgnored(QAccessibleInterface *interface)
const QAccessible::Role role = interface->role(); const QAccessible::Role role = interface->role();
if (role == QAccessible::Border || // QFrame if (role == QAccessible::Border || // QFrame
role == QAccessible::Application || // We use the system-provided application element. role == QAccessible::Application || // We use the system-provided application element.
role == QAccessible::MenuItem || // The system also provides the menu items.
role == QAccessible::ToolBar || // Access the tool buttons directly. role == QAccessible::ToolBar || // Access the tool buttons directly.
role == QAccessible::Pane || // Scroll areas. role == QAccessible::Pane || // Scroll areas.
role == QAccessible::Client) // The default for QWidget. role == QAccessible::Client) // The default for QWidget.

View File

@ -90,7 +90,9 @@ QPalette * qt_mac_createSystemPalette()
palette->setColor(QPalette::Disabled, QPalette::Text, qc); palette->setColor(QPalette::Disabled, QPalette::Text, qc);
palette->setColor(QPalette::Disabled, QPalette::WindowText, qc); palette->setColor(QPalette::Disabled, QPalette::WindowText, qc);
palette->setColor(QPalette::Disabled, QPalette::HighlightedText, qc); palette->setColor(QPalette::Disabled, QPalette::HighlightedText, qc);
palette->setBrush(QPalette::ToolTipBase, QColor(255, 255, 199));
palette->setBrush(QPalette::ToolTipBase, qt_mac_toQBrush([NSColor controlColor]));
return palette; return palette;
} }

View File

@ -50,11 +50,10 @@
@implementation QIOSApplicationDelegate @implementation QIOSApplicationDelegate
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options
{ {
Q_UNUSED(application); Q_UNUSED(application);
Q_UNUSED(sourceApplication); Q_UNUSED(options);
Q_UNUSED(annotation);
if (!QGuiApplication::instance()) if (!QGuiApplication::instance())
return NO; return NO;

View File

@ -56,8 +56,8 @@ public:
static Qt::ApplicationState toQtApplicationState(UIApplicationState state); static Qt::ApplicationState toQtApplicationState(UIApplicationState state);
Q_SIGNALS: Q_SIGNALS:
void applicationStateWillChange(Qt::ApplicationState); void applicationStateWillChange(Qt::ApplicationState oldState, Qt::ApplicationState newState);
void applicationStateDidChange(Qt::ApplicationState); void applicationStateDidChange(Qt::ApplicationState oldState, Qt::ApplicationState newState);
}; };
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -87,18 +87,18 @@ QIOSApplicationState::QIOSApplicationState()
void QIOSApplicationState::handleApplicationStateChanged(UIApplicationState uiState, const QString &reason) void QIOSApplicationState::handleApplicationStateChanged(UIApplicationState uiState, const QString &reason)
{ {
Qt::ApplicationState state = toQtApplicationState(uiState); Qt::ApplicationState oldState = QGuiApplication::applicationState();
qCDebug(lcQpaApplication) << qPrintable(reason) Qt::ApplicationState newState = toQtApplicationState(uiState);
<< "- moving from" << QGuiApplication::applicationState() << "to" << state; qCDebug(lcQpaApplication) << qPrintable(reason) << "- moving from" << oldState << "to" << newState;
if (QIOSIntegration *integration = QIOSIntegration::instance()) { if (QIOSIntegration *integration = QIOSIntegration::instance()) {
emit integration->applicationState.applicationStateWillChange(state); emit integration->applicationState.applicationStateWillChange(oldState, newState);
QWindowSystemInterface::handleApplicationStateChanged(state); QWindowSystemInterface::handleApplicationStateChanged(newState);
emit integration->applicationState.applicationStateDidChange(state); emit integration->applicationState.applicationStateDidChange(oldState, newState);
qCDebug(lcQpaApplication) << "done moving to" << state; qCDebug(lcQpaApplication) << "done moving to" << newState;
} else { } else {
qCDebug(lcQpaApplication) << "no platform integration yet, setting state directly"; qCDebug(lcQpaApplication) << "no platform integration yet, setting state directly";
QGuiApplicationPrivate::applicationState = state; QGuiApplicationPrivate::applicationState = newState;
} }
} }

View File

@ -301,29 +301,34 @@ bool QIOSContext::verifyGraphicsHardwareAvailability()
static dispatch_once_t onceToken = 0; static dispatch_once_t onceToken = 0;
dispatch_once(&onceToken, ^{ dispatch_once(&onceToken, ^{
QIOSApplicationState *applicationState = &QIOSIntegration::instance()->applicationState; QIOSApplicationState *applicationState = &QIOSIntegration::instance()->applicationState;
connect(applicationState, &QIOSApplicationState::applicationStateWillChange, [](Qt::ApplicationState state) { connect(applicationState, &QIOSApplicationState::applicationStateWillChange,
if (applicationBackgrounded && state != Qt::ApplicationSuspended) { [](Qt::ApplicationState oldState, Qt::ApplicationState newState) {
qCDebug(lcQpaGLContext) << "app no longer backgrounded, rendering enabled"; Q_UNUSED(oldState);
applicationBackgrounded = false; if (applicationBackgrounded && newState != Qt::ApplicationSuspended) {
qCDebug(lcQpaGLContext) << "app no longer backgrounded, rendering enabled";
applicationBackgrounded = true;
}
} }
}); );
connect(applicationState, &QIOSApplicationState::applicationStateDidChange, [](Qt::ApplicationState state) { connect(applicationState, &QIOSApplicationState::applicationStateDidChange,
if (state != Qt::ApplicationSuspended) [](Qt::ApplicationState oldState, Qt::ApplicationState newState) {
return; Q_UNUSED(oldState);
if (newState != Qt::ApplicationSuspended)
return;
qCDebug(lcQpaGLContext) << "app backgrounded, rendering disabled"; qCDebug(lcQpaGLContext) << "app backgrounded, rendering disabled";
applicationBackgrounded = true;
// By the time we receive this signal the application has moved into // By the time we receive this signal the application has moved into
// Qt::ApplactionStateSuspended, and all windows have been obscured, // Qt::ApplactionStateSuspended, and all windows have been obscured,
// which should stop all rendering. If there's still an active GL context, // which should stop all rendering. If there's still an active GL context,
// we follow Apple's advice and call glFinish before making it inactive. // we follow Apple's advice and call glFinish before making it inactive.
if (QOpenGLContext *currentContext = QOpenGLContext::currentContext()) { if (QOpenGLContext *currentContext = QOpenGLContext::currentContext()) {
qCWarning(lcQpaGLContext) << "explicitly glFinishing and deactivating" << currentContext; qCWarning(lcQpaGLContext) << "explicitly glFinishing and deactivating" << currentContext;
glFinish(); glFinish();
currentContext->doneCurrent(); currentContext->doneCurrent();
}
} }
}); );
}); });
if (applicationBackgrounded) { if (applicationBackgrounded) {

View File

@ -62,6 +62,8 @@ public:
QIOSIntegration(); QIOSIntegration();
~QIOSIntegration(); ~QIOSIntegration();
void initialize() override;
bool hasCapability(Capability cap) const override; bool hasCapability(Capability cap) const override;
QPlatformWindow *createPlatformWindow(QWindow *window) const override; QPlatformWindow *createPlatformWindow(QWindow *window) const override;

View File

@ -95,7 +95,10 @@ QIOSIntegration::QIOSIntegration()
// Set current directory to app bundle folder // Set current directory to app bundle folder
QDir::setCurrent(QString::fromUtf8([[[NSBundle mainBundle] bundlePath] UTF8String])); QDir::setCurrent(QString::fromUtf8([[[NSBundle mainBundle] bundlePath] UTF8String]));
}
void QIOSIntegration::initialize()
{
UIScreen *mainScreen = [UIScreen mainScreen]; UIScreen *mainScreen = [UIScreen mainScreen];
NSMutableArray<UIScreen *> *screens = [[[UIScreen screens] mutableCopy] autorelease]; NSMutableArray<UIScreen *> *screens = [[[UIScreen screens] mutableCopy] autorelease];
if (![screens containsObject:mainScreen]) { if (![screens containsObject:mainScreen]) {

View File

@ -271,6 +271,20 @@
m_focusWindowChangeConnection = QObject::connect(qApp, &QGuiApplication::focusWindowChanged, [self]() { m_focusWindowChangeConnection = QObject::connect(qApp, &QGuiApplication::focusWindowChanged, [self]() {
[self updateProperties]; [self updateProperties];
}); });
QIOSApplicationState *applicationState = &QIOSIntegration::instance()->applicationState;
QObject::connect(applicationState, &QIOSApplicationState::applicationStateDidChange,
[self](Qt::ApplicationState oldState, Qt::ApplicationState newState) {
if (oldState == Qt::ApplicationSuspended && newState != Qt::ApplicationSuspended) {
// We may have ignored an earlier layout because the application was suspended,
// and we didn't want to render anything at that moment in fear of being killed
// due to rendering in the background, so we trigger an explicit layout when
// coming out of the suspended state.
qCDebug(lcQpaWindow) << "triggering root VC layout when coming out of suspended state";
[self.view setNeedsLayout];
}
}
);
} }
return self; return self;

View File

@ -43,7 +43,6 @@
*/ */
#include <AppKit/AppKit.h> #include <AppKit/AppKit.h>
#include <ApplicationServices/ApplicationServices.h>
#include "qmacstyle_mac_p.h" #include "qmacstyle_mac_p.h"
#include "qmacstyle_mac_p_p.h" #include "qmacstyle_mac_p_p.h"
@ -263,13 +262,7 @@ QT_BEGIN_NAMESPACE
// The following constants are used for adjusting the size // The following constants are used for adjusting the size
// of push buttons so that they are drawn inside their bounds. // of push buttons so that they are drawn inside their bounds.
const int QMacStylePrivate::PushButtonLeftOffset = 6; const int QMacStylePrivate::PushButtonLeftOffset = 6;
const int QMacStylePrivate::PushButtonTopOffset = 4;
const int QMacStylePrivate::PushButtonRightOffset = 12; const int QMacStylePrivate::PushButtonRightOffset = 12;
const int QMacStylePrivate::PushButtonBottomOffset = 12;
const int QMacStylePrivate::MiniButtonH = 26;
const int QMacStylePrivate::SmallButtonH = 30;
const int QMacStylePrivate::BevelButtonW = 50;
const int QMacStylePrivate::BevelButtonH = 22;
const int QMacStylePrivate::PushButtonContentPadding = 6; const int QMacStylePrivate::PushButtonContentPadding = 6;
QVector<QPointer<QObject> > QMacStylePrivate::scrollBars; QVector<QPointer<QObject> > QMacStylePrivate::scrollBars;
@ -379,15 +372,6 @@ static const int toolButtonArrowMargin = 2;
static const qreal focusRingWidth = 3.5; static const qreal focusRingWidth = 3.5;
#if QT_CONFIG(tabbar)
static bool isVerticalTabs(const QTabBar::Shape shape) {
return (shape == QTabBar::RoundedEast
|| shape == QTabBar::TriangularEast
|| shape == QTabBar::RoundedWest
|| shape == QTabBar::TriangularWest);
}
#endif
static bool setupScroller(NSScroller *scroller, const QStyleOptionSlider *sb) static bool setupScroller(NSScroller *scroller, const QStyleOptionSlider *sb)
{ {
const qreal length = sb->maximum - sb->minimum + sb->pageStep; const qreal length = sb->maximum - sb->minimum + sb->pageStep;
@ -492,10 +476,10 @@ static void drawTabCloseButton(QPainter *p, bool hover, bool selected, bool pres
#if QT_CONFIG(tabbar) #if QT_CONFIG(tabbar)
QRect rotateTabPainter(QPainter *p, QTabBar::Shape shape, QRect tabRect) QRect rotateTabPainter(QPainter *p, QTabBar::Shape shape, QRect tabRect)
{ {
if (isVerticalTabs(shape)) { const auto tabDirection = QMacStylePrivate::tabDirection(shape);
if (QMacStylePrivate::verticalTabs(tabDirection)) {
int newX, newY, newRot; int newX, newY, newRot;
if (shape == QTabBar::RoundedEast if (tabDirection == QMacStylePrivate::East) {
|| shape == QTabBar::TriangularEast) {
newX = tabRect.width(); newX = tabRect.width();
newY = tabRect.y(); newY = tabRect.y();
newRot = 90; newRot = 90;
@ -516,23 +500,10 @@ QRect rotateTabPainter(QPainter *p, QTabBar::Shape shape, QRect tabRect)
void drawTabShape(QPainter *p, const QStyleOptionTab *tabOpt, bool isUnified, int tabOverlap) void drawTabShape(QPainter *p, const QStyleOptionTab *tabOpt, bool isUnified, int tabOverlap)
{ {
QRect rect = tabOpt->rect; QRect rect = tabOpt->rect;
if (QMacStylePrivate::verticalTabs(QMacStylePrivate::tabDirection(tabOpt->shape)))
switch (tabOpt->shape) { rect = rect.adjusted(-tabOverlap, 0, 0, 0);
case QTabBar::RoundedNorth: else
case QTabBar::TriangularNorth: rect = rect.adjusted(0, -tabOverlap, 0, 0);
case QTabBar::RoundedSouth:
case QTabBar::TriangularSouth:
rect.adjust(-tabOverlap, 0, 0, 0);
break;
case QTabBar::RoundedEast:
case QTabBar::TriangularEast:
case QTabBar::RoundedWest:
case QTabBar::TriangularWest:
rect.adjust(0, -tabOverlap, 0, 0);
break;
default:
break;
}
p->translate(rect.x(), rect.y()); p->translate(rect.x(), rect.y());
rect.moveLeft(0); rect.moveLeft(0);
@ -583,11 +554,11 @@ void drawTabShape(QPainter *p, const QStyleOptionTab *tabOpt, bool isUnified, in
void drawTabBase(QPainter *p, const QStyleOptionTabBarBase *tbb, const QWidget *w) void drawTabBase(QPainter *p, const QStyleOptionTabBarBase *tbb, const QWidget *w)
{ {
QRect r = tbb->rect; QRect r = tbb->rect;
if (isVerticalTabs(tbb->shape)) { if (QMacStylePrivate::verticalTabs(QMacStylePrivate::tabDirection(tbb->shape)))
r.setWidth(w->width()); r.setWidth(w->width());
} else { else
r.setHeight(w->height()); r.setHeight(w->height());
}
const QRect tabRect = rotateTabPainter(p, tbb->shape, r); const QRect tabRect = rotateTabPainter(p, tbb->shape, r);
const int width = tabRect.width(); const int width = tabRect.width();
const int height = tabRect.height(); const int height = tabRect.height();
@ -623,8 +594,7 @@ static QStyleHelper::WidgetSizePolicy getControlSize(const QStyleOption *option,
static inline bool isTreeView(const QWidget *widget) static inline bool isTreeView(const QWidget *widget)
{ {
return (widget && widget->parentWidget() && return (widget && widget->parentWidget() &&
(qobject_cast<const QTreeView *>(widget->parentWidget()) qobject_cast<const QTreeView *>(widget->parentWidget()));
));
} }
#endif #endif
@ -662,15 +632,6 @@ static QString qt_mac_removeMnemonics(const QString &original)
return returnText; return returnText;
} }
bool qt_macWindowIsTextured(const QWidget *window)
{
if (QWindow *w = window->windowHandle())
if (w->handle())
if (NSWindow *nswindow = static_cast<NSWindow*>(QGuiApplication::platformNativeInterface()->nativeResourceForWindow(QByteArrayLiteral("NSWindow"), w)))
return ([nswindow styleMask] & NSTexturedBackgroundWindowMask) ? true : false;
return false;
}
static bool qt_macWindowMainWindow(const QWidget *window) static bool qt_macWindowMainWindow(const QWidget *window)
{ {
if (QWindow *w = window->windowHandle()) { if (QWindow *w = window->windowHandle()) {
@ -1108,51 +1069,11 @@ static QStyleHelper::WidgetSizePolicy qt_aqua_guess_size(const QWidget *widg, QS
return QStyleHelper::SizeLarge; return QStyleHelper::SizeLarge;
} }
#if QT_CONFIG(mainwindow) if (qEnvironmentVariableIsSet("QWIDGET_ALL_SMALL"))
if (qEnvironmentVariableIsSet("QWIDGET_ALL_SMALL")) {
//if (small.width() != -1 || small.height() != -1)
return QStyleHelper::SizeSmall; return QStyleHelper::SizeSmall;
} else if (qEnvironmentVariableIsSet("QWIDGET_ALL_MINI")) { else if (qEnvironmentVariableIsSet("QWIDGET_ALL_MINI"))
return QStyleHelper::SizeMini; return QStyleHelper::SizeMini;
}
#endif
#if 0
/* Figure out which size we're closer to, I just hacked this in, I haven't
tested it as it would probably look pretty strange to have some widgets
big and some widgets small in the same window?? -Sam */
int large_delta=0;
if (large.width() != -1) {
int delta = large.width() - widg->width();
large_delta += delta * delta;
}
if (large.height() != -1) {
int delta = large.height() - widg->height();
large_delta += delta * delta;
}
int small_delta=0;
if (small.width() != -1) {
int delta = small.width() - widg->width();
small_delta += delta * delta;
}
if (small.height() != -1) {
int delta = small.height() - widg->height();
small_delta += delta * delta;
}
int mini_delta=0;
if (mini.width() != -1) {
int delta = mini.width() - widg->width();
mini_delta += delta * delta;
}
if (mini.height() != -1) {
int delta = mini.height() - widg->height();
mini_delta += delta * delta;
}
if (mini_delta < small_delta && mini_delta < large_delta)
return QStyleHelper::SizeMini;
else if (small_delta < large_delta)
return QStyleHelper::SizeSmall;
#endif
return QStyleHelper::SizeLarge; return QStyleHelper::SizeLarge;
} }
#endif #endif
@ -1172,10 +1093,10 @@ void QMacStylePrivate::drawFocusRing(QPainter *p, const QRectF &targetRect, int
auto innerRect = targetRect; auto innerRect = targetRect;
if (cw.type == TextField) if (cw.type == TextField)
innerRect = innerRect.adjusted(hMargin, vMargin, -hMargin, -vMargin).adjusted(0.5, 0.5, -0.5, -0.5); innerRect = innerRect.adjusted(hMargin, vMargin, -hMargin, -vMargin).adjusted(0.5, 0.5, -0.5, -0.5);
const auto outterRect = innerRect.adjusted(-focusRingWidth, -focusRingWidth, focusRingWidth, focusRingWidth); const auto outerRect = innerRect.adjusted(-focusRingWidth, -focusRingWidth, focusRingWidth, focusRingWidth);
const auto outterRadius = focusRingWidth; const auto outerRadius = focusRingWidth;
focusRingPath.addRect(innerRect); focusRingPath.addRect(innerRect);
focusRingPath.addRoundedRect(outterRect, outterRadius, outterRadius); focusRingPath.addRoundedRect(outerRect, outerRadius, outerRadius);
break; break;
} }
case Button_CheckBox: { case Button_CheckBox: {
@ -1186,9 +1107,9 @@ void QMacStylePrivate::drawFocusRing(QPainter *p, const QRectF &targetRect, int
cw.size == QStyleHelper::SizeSmall ? 2.0 : 1.0); // As measured cw.size == QStyleHelper::SizeSmall ? 2.0 : 1.0); // As measured
vOffset = 0.5 * qreal(targetRect.height() - cbSize); vOffset = 0.5 * qreal(targetRect.height() - cbSize);
const auto cbInnerRect = QRectF(0, 0, cbSize, cbSize); const auto cbInnerRect = QRectF(0, 0, cbSize, cbSize);
const auto cbOutterRadius = cbInnerRadius + focusRingWidth; const auto cbOuterRadius = cbInnerRadius + focusRingWidth;
const auto cbOutterRect = cbInnerRect.adjusted(-focusRingWidth, -focusRingWidth, focusRingWidth, focusRingWidth); const auto cbOuterRect = cbInnerRect.adjusted(-focusRingWidth, -focusRingWidth, focusRingWidth, focusRingWidth);
focusRingPath.addRoundedRect(cbOutterRect, cbOutterRadius, cbOutterRadius); focusRingPath.addRoundedRect(cbOuterRect, cbOuterRadius, cbOuterRadius);
focusRingPath.addRoundedRect(cbInnerRect, cbInnerRadius, cbInnerRadius); focusRingPath.addRoundedRect(cbInnerRect, cbInnerRadius, cbInnerRadius);
break; break;
} }
@ -1199,9 +1120,9 @@ void QMacStylePrivate::drawFocusRing(QPainter *p, const QRectF &targetRect, int
cw.size == QStyleHelper::SizeSmall ? 1.0 : 1.0); // As measured cw.size == QStyleHelper::SizeSmall ? 1.0 : 1.0); // As measured
vOffset = 0.5 * qreal(targetRect.height() - rbSize); vOffset = 0.5 * qreal(targetRect.height() - rbSize);
const auto rbInnerRect = QRectF(0, 0, rbSize, rbSize); const auto rbInnerRect = QRectF(0, 0, rbSize, rbSize);
const auto rbOutterRect = rbInnerRect.adjusted(-focusRingWidth, -focusRingWidth, focusRingWidth, focusRingWidth); const auto rbOuterRect = rbInnerRect.adjusted(-focusRingWidth, -focusRingWidth, focusRingWidth, focusRingWidth);
focusRingPath.addEllipse(rbInnerRect); focusRingPath.addEllipse(rbInnerRect);
focusRingPath.addEllipse(rbOutterRect); focusRingPath.addEllipse(rbOuterRect);
break; break;
} }
case Button_PopupButton: case Button_PopupButton:
@ -1209,13 +1130,13 @@ void QMacStylePrivate::drawFocusRing(QPainter *p, const QRectF &targetRect, int
case Button_PushButton: case Button_PushButton:
case SegmentedControl_Single: { case SegmentedControl_Single: {
const qreal innerRadius = cw.type == Button_PushButton ? 3 : 4; const qreal innerRadius = cw.type == Button_PushButton ? 3 : 4;
const qreal outterRadius = innerRadius + focusRingWidth; const qreal outerRadius = innerRadius + focusRingWidth;
hOffset = targetRect.left(); hOffset = targetRect.left();
vOffset = targetRect.top(); vOffset = targetRect.top();
const auto innerRect = targetRect.translated(-targetRect.topLeft()); const auto innerRect = targetRect.translated(-targetRect.topLeft());
const auto outterRect = innerRect.adjusted(-hMargin, -vMargin, hMargin, vMargin); const auto outerRect = innerRect.adjusted(-hMargin, -vMargin, hMargin, vMargin);
focusRingPath.addRoundedRect(innerRect, innerRadius, innerRadius); focusRingPath.addRoundedRect(innerRect, innerRadius, innerRadius);
focusRingPath.addRoundedRect(outterRect, outterRadius, outterRadius); focusRingPath.addRoundedRect(outerRect, outerRadius, outerRadius);
break; break;
} }
case ComboBox: case ComboBox:
@ -1224,9 +1145,9 @@ void QMacStylePrivate::drawFocusRing(QPainter *p, const QRectF &targetRect, int
hOffset = targetRect.left(); hOffset = targetRect.left();
vOffset = targetRect.top(); vOffset = targetRect.top();
const qreal innerRadius = 8; const qreal innerRadius = 8;
const qreal outterRadius = innerRadius + focusRingWidth; const qreal outerRadius = innerRadius + focusRingWidth;
const auto innerRect = targetRect.translated(-targetRect.topLeft()); const auto innerRect = targetRect.translated(-targetRect.topLeft());
const auto outterRect = innerRect.adjusted(-hMargin, -vMargin, hMargin, vMargin); const auto outerRect = innerRect.adjusted(-hMargin, -vMargin, hMargin, vMargin);
const auto cbFocusFramePath = [](const QRectF &rect, qreal tRadius, qreal bRadius) { const auto cbFocusFramePath = [](const QRectF &rect, qreal tRadius, qreal bRadius) {
QPainterPath path; QPainterPath path;
@ -1252,8 +1173,8 @@ void QMacStylePrivate::drawFocusRing(QPainter *p, const QRectF &targetRect, int
const auto innerPath = cbFocusFramePath(innerRect, 0, innerRadius); const auto innerPath = cbFocusFramePath(innerRect, 0, innerRadius);
focusRingPath.addPath(innerPath); focusRingPath.addPath(innerPath);
const auto outterPath = cbFocusFramePath(outterRect, 2 * focusRingWidth, outterRadius); const auto outerPath = cbFocusFramePath(outerRect, 2 * focusRingWidth, outerRadius);
focusRingPath.addPath(outterPath); focusRingPath.addPath(outerPath);
break; break;
} }
default: default:
@ -1412,6 +1333,12 @@ QMacStylePrivate::Direction QMacStylePrivate::tabDirection(QTabBar::Shape shape)
} }
} }
bool QMacStylePrivate::verticalTabs(QMacStylePrivate::Direction direction)
{
return (direction == QMacStylePrivate::East
|| direction == QMacStylePrivate::West);
}
#endif // QT_CONFIG(tabbar) #endif // QT_CONFIG(tabbar)
QStyleHelper::WidgetSizePolicy QMacStylePrivate::effectiveAquaSizeConstrain(const QStyleOption *option, QStyleHelper::WidgetSizePolicy QMacStylePrivate::effectiveAquaSizeConstrain(const QStyleOption *option,
@ -1599,7 +1526,6 @@ QMarginsF QMacStylePrivate::CocoaControl::titleMargins() const
return QMarginsF(); return QMarginsF();
} }
bool QMacStylePrivate::CocoaControl::getCocoaButtonTypeAndBezelStyle(NSButtonType *buttonType, NSBezelStyle *bezelStyle) const bool QMacStylePrivate::CocoaControl::getCocoaButtonTypeAndBezelStyle(NSButtonType *buttonType, NSBezelStyle *bezelStyle) const
{ {
switch (type) { switch (type) {
@ -1660,9 +1586,9 @@ QMacStylePrivate::CocoaControlType cocoaControlType(const QStyleOption *opt, con
Carbon draws comboboxes (and other views) outside the rect given as argument. Use this function to obtain Carbon draws comboboxes (and other views) outside the rect given as argument. Use this function to obtain
the corresponding inner rect for drawing the same combobox so that it stays inside the given outerBounds. the corresponding inner rect for drawing the same combobox so that it stays inside the given outerBounds.
*/ */
CGRect QMacStylePrivate::comboboxInnerBounds(const CGRect &outterBounds, const CocoaControl &cocoaWidget) CGRect QMacStylePrivate::comboboxInnerBounds(const CGRect &outerBounds, const CocoaControl &cocoaWidget)
{ {
CGRect innerBounds = outterBounds; CGRect innerBounds = outerBounds;
// Carbon draw parts of the view outside the rect. // Carbon draw parts of the view outside the rect.
// So make the rect a bit smaller to compensate // So make the rect a bit smaller to compensate
// (I wish HIThemeGetButtonBackgroundBounds worked) // (I wish HIThemeGetButtonBackgroundBounds worked)
@ -1717,9 +1643,9 @@ CGRect QMacStylePrivate::comboboxInnerBounds(const CGRect &outterBounds, const C
Inside a combobox Qt places a line edit widget. The size of this widget should depend on the kind Inside a combobox Qt places a line edit widget. The size of this widget should depend on the kind
of combobox we choose to draw. This function calculates and returns this size. of combobox we choose to draw. This function calculates and returns this size.
*/ */
QRectF QMacStylePrivate::comboboxEditBounds(const QRectF &outterBounds, const CocoaControl &cw) QRectF QMacStylePrivate::comboboxEditBounds(const QRectF &outerBounds, const CocoaControl &cw)
{ {
QRectF ret = outterBounds; QRectF ret = outerBounds;
if (cw.type == ComboBox) { if (cw.type == ComboBox) {
switch (cw.size) { switch (cw.size) {
case QStyleHelper::SizeLarge: case QStyleHelper::SizeLarge:
@ -1746,8 +1672,7 @@ QRectF QMacStylePrivate::comboboxEditBounds(const QRectF &outterBounds, const Co
ret.adjust(13, 4, -20, -3); ret.adjust(13, 4, -20, -3);
break; break;
case QStyleHelper::SizeMini: case QStyleHelper::SizeMini:
// FIXME Wrong ret.adjust(12, 0, -19, 0);
ret.adjust(16, 5, -19, 0);
ret.setHeight(13); ret.setHeight(13);
break; break;
default: default:
@ -1775,27 +1700,12 @@ QMacStylePrivate::~QMacStylePrivate()
[cell release]; [cell release];
} }
#if 0
ThemeDrawState QMacStylePrivate::getDrawState(QStyle::State flags)
{
ThemeDrawState tds = kThemeStateActive;
if (flags & QStyle::State_Sunken) {
tds = kThemeStatePressed;
} else if (flags & QStyle::State_Active) {
if (!(flags & QStyle::State_Enabled))
tds = kThemeStateUnavailable;
} else {
if (flags & QStyle::State_Enabled)
tds = kThemeStateInactive;
else
tds = kThemeStateUnavailableInactive;
}
return tds;
}
#endif
NSView *QMacStylePrivate::cocoaControl(CocoaControl widget) const NSView *QMacStylePrivate::cocoaControl(CocoaControl widget) const
{ {
if (widget.type == QMacStylePrivate::NoControl
|| widget.size == QStyleHelper::SizeDefault)
return nil;
NSView *bv = cocoaControls.value(widget, nil); NSView *bv = cocoaControls.value(widget, nil);
if (!bv) { if (!bv) {
switch (widget.type) { switch (widget.type) {
@ -1977,15 +1887,13 @@ NSCell *QMacStylePrivate::cocoaCell(CocoaControl widget) const
return cell; return cell;
} }
void QMacStylePrivate::drawNSViewInRect(CocoaControl widget, NSView *view, const QRectF &qtRect, QPainter *p, bool isQWidget, __attribute__((noescape)) DrawRectBlock drawRectBlock) const void QMacStylePrivate::drawNSViewInRect(NSView *view, const QRectF &qtRect, QPainter *p,
__attribute__((noescape)) DrawRectBlock drawRectBlock) const
{ {
Q_UNUSED(isQWidget);
Q_UNUSED(widget);
QMacCGContext ctx(p); QMacCGContext ctx(p);
setupNSGraphicsContext(ctx, YES); setupNSGraphicsContext(ctx, YES);
const CGRect rect = CGRectMake(qtRect.x(), qtRect.y(), qtRect.width(), qtRect.height()); const CGRect rect = qtRect.toCGRect();
[backingStoreNSView addSubview:view]; [backingStoreNSView addSubview:view];
view.frame = rect; view.frame = rect;
@ -2993,9 +2901,9 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
case PE_FrameTabWidget: case PE_FrameTabWidget:
#endif #endif
{ {
const auto cw = QMacStylePrivate::CocoaControl(QMacStylePrivate::Box, QStyleHelper::SizeDefault); const auto cw = QMacStylePrivate::CocoaControl(QMacStylePrivate::Box, QStyleHelper::SizeLarge);
auto *box = static_cast<NSBox *>(d->cocoaControl(cw)); auto *box = static_cast<NSBox *>(d->cocoaControl(cw));
d->drawNSViewInRect(cw, box, opt->rect, p, w != nullptr, ^(CGContextRef ctx, const CGRect &rect) { d->drawNSViewInRect(box, opt->rect, p, ^(CGContextRef ctx, const CGRect &rect) {
CGContextTranslateCTM(ctx, 0, rect.origin.y + rect.size.height); CGContextTranslateCTM(ctx, 0, rect.origin.y + rect.size.height);
CGContextScaleCTM(ctx, 1, -1); CGContextScaleCTM(ctx, 1, -1);
[box drawRect:rect]; [box drawRect:rect];
@ -3155,7 +3063,7 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
return cs == QStyleHelper::SizeSmall ? 0.5 : 0.0; return cs == QStyleHelper::SizeSmall ? 0.5 : 0.0;
} (); } ();
d->drawNSViewInRect(cw, tb, opt->rect, p, w != nullptr, ^(CGContextRef ctx, const CGRect &rect) { d->drawNSViewInRect(tb, opt->rect, p, ^(CGContextRef ctx, const CGRect &rect) {
CGContextTranslateCTM(ctx, 0, vOffset); CGContextTranslateCTM(ctx, 0, vOffset);
[tb.cell drawInteriorWithFrame:rect inView:tb]; [tb.cell drawInteriorWithFrame:rect inView:tb];
}); });
@ -3166,7 +3074,7 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
case PE_IndicatorBranch: { case PE_IndicatorBranch: {
if (!(opt->state & State_Children)) if (!(opt->state & State_Children))
break; break;
const auto cw = QMacStylePrivate::CocoaControl(QMacStylePrivate::Button_Disclosure, QStyleHelper::SizeLarge); const auto cw = QMacStylePrivate::CocoaControl(QMacStylePrivate::Button_Disclosure, QStyleHelper::SizeLarge);
NSButtonCell *triangleCell = static_cast<NSButtonCell *>(d->cocoaCell(cw)); NSButtonCell *triangleCell = static_cast<NSButtonCell *>(d->cocoaCell(cw));
[triangleCell setState:(opt->state & State_Open) ? NSOnState : NSOffState]; [triangleCell setState:(opt->state & State_Open) ? NSOnState : NSOffState];
bool viewHasFocus = (w && w->hasFocus()) || (opt->state & State_HasFocus); bool viewHasFocus = (w && w->hasFocus()) || (opt->state & State_HasFocus);
@ -3208,7 +3116,7 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
tf.bezeled = YES; tf.bezeled = YES;
static_cast<NSTextFieldCell *>(tf.cell).bezelStyle = isRounded ? NSTextFieldRoundedBezel : NSTextFieldSquareBezel; static_cast<NSTextFieldCell *>(tf.cell).bezelStyle = isRounded ? NSTextFieldRoundedBezel : NSTextFieldSquareBezel;
tf.frame = opt->rect.toCGRect(); tf.frame = opt->rect.toCGRect();
d->drawNSViewInRect(cw, tf, opt->rect, p, w != nullptr, ^(CGContextRef ctx, const CGRect &rect) { d->drawNSViewInRect(tf, opt->rect, p, ^(CGContextRef ctx, const CGRect &rect) {
Q_UNUSED(ctx); Q_UNUSED(ctx);
[tf.cell drawWithFrame:rect inView:tf]; [tf.cell drawWithFrame:rect inView:tf];
}); });
@ -3298,7 +3206,7 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
} }
} }
static inline QPixmap darkenPixmap(const QPixmap &pixmap) static QPixmap darkenPixmap(const QPixmap &pixmap)
{ {
QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32); QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32);
int imgh = img.height(); int imgh = img.height();
@ -3321,8 +3229,6 @@ static inline QPixmap darkenPixmap(const QPixmap &pixmap)
return QPixmap::fromImage(img); return QPixmap::fromImage(img);
} }
void QMacStylePrivate::setupVerticalInvertedXform(CGContextRef cg, bool reverse, bool vertical, const CGRect &rect) const void QMacStylePrivate::setupVerticalInvertedXform(CGContextRef cg, bool reverse, bool vertical, const CGRect &rect) const
{ {
if (vertical) { if (vertical) {
@ -3542,7 +3448,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
pb.enabled = isEnabled; pb.enabled = isEnabled;
[pb highlight:isPressed]; [pb highlight:isPressed];
pb.state = isHighlighted && !isPressed ? NSOnState : NSOffState; pb.state = isHighlighted && !isPressed ? NSOnState : NSOffState;
d->drawNSViewInRect(cw, pb, frameRect, p, true, ^(CGContextRef __unused ctx, const CGRect &r) { d->drawNSViewInRect(pb, frameRect, p, ^(CGContextRef __unused ctx, const CGRect &r) {
[pb.cell drawBezelWithFrame:r inView:pb.superview]; [pb.cell drawBezelWithFrame:r inView:pb.superview];
}); });
[pb highlight:NO]; [pb highlight:NO];
@ -3685,6 +3591,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
return; return;
} }
const bool isActive = tabOpt->state & State_Active;
const bool isEnabled = tabOpt->state & State_Enabled; const bool isEnabled = tabOpt->state & State_Enabled;
const bool isPressed = tabOpt->state & State_Sunken; const bool isPressed = tabOpt->state & State_Sunken;
const bool isSelected = tabOpt->state & State_Selected; const bool isSelected = tabOpt->state & State_Selected;
@ -3713,17 +3620,20 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
// a push NSButton instead and clip the CGContext. // a push NSButton instead and clip the CGContext.
const auto cs = d->effectiveAquaSizeConstrain(opt, w); const auto cs = d->effectiveAquaSizeConstrain(opt, w);
// Extra hack to get the proper pressed appreance when not selected // Extra hacks to get the proper pressed appreance when not selected or selected and inactive
const auto ct = isSelected || tp == QStyleOptionTab::OnlyOneTab ? const bool needsInactiveHack = (!isActive && isSelected);
const auto ct = !needsInactiveHack && (isSelected || tp == QStyleOptionTab::OnlyOneTab) ?
QMacStylePrivate::Button_PushButton : QMacStylePrivate::Button_PushButton :
QMacStylePrivate::Button_PopupButton; QMacStylePrivate::Button_PopupButton;
const bool isPopupButton = ct == QMacStylePrivate::Button_PopupButton;
const auto cw = QMacStylePrivate::CocoaControl(ct, cs); const auto cw = QMacStylePrivate::CocoaControl(ct, cs);
auto *pb = static_cast<NSButton *>(d->cocoaControl(cw)); auto *pb = static_cast<NSButton *>(d->cocoaControl(cw));
auto vOffset = isSelected ? 2 : 1;
auto vOffset = isPopupButton ? 1 : 2;
if (tabDirection == QMacStylePrivate::East) if (tabDirection == QMacStylePrivate::East)
vOffset -= 1; vOffset -= 1;
const auto outterAdjust = isSelected ? 4 : 1; const auto outerAdjust = isPopupButton ? 1 : 4;
const auto innerAdjust = isSelected ? 10 : 20; const auto innerAdjust = isPopupButton ? 20 : 10;
QRectF frameRect = tabOpt->rect; QRectF frameRect = tabOpt->rect;
if (verticalTabs) if (verticalTabs)
frameRect = QRectF(frameRect.y(), frameRect.x(), frameRect.height(), frameRect.width()); frameRect = QRectF(frameRect.y(), frameRect.x(), frameRect.height(), frameRect.width());
@ -3733,9 +3643,9 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
case QStyleOptionTab::Beginning: case QStyleOptionTab::Beginning:
// Pressed state hack: tweak adjustments in preparation for flip below // Pressed state hack: tweak adjustments in preparation for flip below
if (!isSelected && tabDirection == QMacStylePrivate::West) if (!isSelected && tabDirection == QMacStylePrivate::West)
frameRect = frameRect.adjusted(-innerAdjust, 0, outterAdjust, 0); frameRect = frameRect.adjusted(-innerAdjust, 0, outerAdjust, 0);
else else
frameRect = frameRect.adjusted(-outterAdjust, 0, innerAdjust, 0); frameRect = frameRect.adjusted(-outerAdjust, 0, innerAdjust, 0);
break; break;
case QStyleOptionTab::Middle: case QStyleOptionTab::Middle:
frameRect = frameRect.adjusted(-innerAdjust, 0, innerAdjust, 0); frameRect = frameRect.adjusted(-innerAdjust, 0, innerAdjust, 0);
@ -3743,22 +3653,24 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
case QStyleOptionTab::End: case QStyleOptionTab::End:
// Pressed state hack: tweak adjustments in preparation for flip below // Pressed state hack: tweak adjustments in preparation for flip below
if (isSelected || tabDirection == QMacStylePrivate::West) if (isSelected || tabDirection == QMacStylePrivate::West)
frameRect = frameRect.adjusted(-innerAdjust, 0, outterAdjust, 0); frameRect = frameRect.adjusted(-innerAdjust, 0, outerAdjust, 0);
else else
frameRect = frameRect.adjusted(-outterAdjust, 0, innerAdjust, 0); frameRect = frameRect.adjusted(-outerAdjust, 0, innerAdjust, 0);
break; break;
case QStyleOptionTab::OnlyOneTab: case QStyleOptionTab::OnlyOneTab:
frameRect = frameRect.adjusted(-outterAdjust, 0, outterAdjust, 0); frameRect = frameRect.adjusted(-outerAdjust, 0, outerAdjust, 0);
break; break;
} }
pb.frame = frameRect.toCGRect(); pb.frame = frameRect.toCGRect();
pb.enabled = isEnabled; pb.enabled = isEnabled;
[pb highlight:isPressed]; [pb highlight:isPressed];
pb.state = isSelected && !isPressed ? NSOnState : NSOffState; // Set off state when inactive. See needsInactiveHack for when it's selected
d->drawNSViewInRect(cw, pb, frameRect, p, true, ^(CGContextRef ctx, const CGRect &r) { pb.state = (isActive && isSelected && !isPressed) ? NSOnState : NSOffState;
const auto drawBezelBlock = ^(CGContextRef ctx, const CGRect &r) {
CGContextClipToRect(ctx, opt->rect.toCGRect()); CGContextClipToRect(ctx, opt->rect.toCGRect());
if (!isSelected) { if (!isSelected || needsInactiveHack) {
// Final stage of the pressed state hack: flip NSPopupButton rendering // Final stage of the pressed state hack: flip NSPopupButton rendering
if (!verticalTabs && tp == QStyleOptionTab::End) { if (!verticalTabs && tp == QStyleOptionTab::End) {
CGContextTranslateCTM(ctx, opt->rect.right(), 0); CGContextTranslateCTM(ctx, opt->rect.right(), 0);
@ -3786,7 +3698,42 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
} }
[pb.cell drawBezelWithFrame:r inView:pb.superview]; [pb.cell drawBezelWithFrame:r inView:pb.superview];
}); };
if (needsInactiveHack) {
// First, render tab as non-selected tab on a pixamp
const qreal pixelRatio = p->device()->devicePixelRatioF();
QImage tabPixmap(opt->rect.size() * pixelRatio, QImage::Format_ARGB32_Premultiplied);
tabPixmap.setDevicePixelRatio(pixelRatio);
tabPixmap.fill(Qt::transparent);
QPainter tabPainter(&tabPixmap);
d->drawNSViewInRect(pb, frameRect, &tabPainter, ^(CGContextRef ctx, const CGRect &r) {
CGContextTranslateCTM(ctx, -opt->rect.left(), -opt->rect.top());
drawBezelBlock(ctx, r);
});
tabPainter.end();
// Then, darken it with the proper shade of gray
const qreal inactiveGray = 0.898; // As measured
const int inactiveGray8 = qRound(inactiveGray * 255.0);
const QRgb inactiveGrayRGB = qRgb(inactiveGray8, inactiveGray8, inactiveGray8);
for (int l = 0; l < tabPixmap.height(); ++l) {
auto *line = reinterpret_cast<QRgb*>(tabPixmap.scanLine(l));
for (int i = 0; i < tabPixmap.width(); ++i) {
if (qAlpha(line[i]) == 255) {
line[i] = inactiveGrayRGB;
} else if (qAlpha(line[i]) > 128) {
const int g = qRound(inactiveGray * qRed(line[i]));
line[i] = qRgba(g, g, g, qAlpha(line[i]));
}
}
}
// Finally, draw the tab pixmap on the current painter
p->drawImage(opt->rect, tabPixmap);
} else {
d->drawNSViewInRect(pb, frameRect, p, drawBezelBlock);
}
if (!isSelected && sp != QStyleOptionTab::NextIsSelected if (!isSelected && sp != QStyleOptionTab::NextIsSelected
&& tp != QStyleOptionTab::End && tp != QStyleOptionTab::End
@ -4193,7 +4140,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
const auto cw = QMacStylePrivate::CocoaControl(QMacStylePrivate::ProgressIndicator_Determinate, aquaSize); const auto cw = QMacStylePrivate::CocoaControl(QMacStylePrivate::ProgressIndicator_Determinate, aquaSize);
auto *pi = static_cast<NSProgressIndicator *>(d->cocoaControl(cw)); auto *pi = static_cast<NSProgressIndicator *>(d->cocoaControl(cw));
d->drawNSViewInRect(cw, pi, rect, p, w != nullptr, ^(CGContextRef ctx, const CGRect &rect) { d->drawNSViewInRect(pi, rect, p, ^(CGContextRef ctx, const CGRect &rect) {
d->setupVerticalInvertedXform(ctx, reverse, vertical, rect); d->setupVerticalInvertedXform(ctx, reverse, vertical, rect);
pi.minValue = pb->minimum; pi.minValue = pb->minimum;
pi.maxValue = pb->maximum; pi.maxValue = pb->maximum;
@ -4243,7 +4190,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
const auto cw = QMacStylePrivate::CocoaControl(ct, QStyleHelper::SizeLarge); const auto cw = QMacStylePrivate::CocoaControl(ct, QStyleHelper::SizeLarge);
auto *sv = static_cast<NSSplitView *>(d->cocoaControl(cw)); auto *sv = static_cast<NSSplitView *>(d->cocoaControl(cw));
sv.frame = opt->rect.toCGRect(); sv.frame = opt->rect.toCGRect();
d->drawNSViewInRect(cw, sv, opt->rect, p, w != nullptr, ^(CGContextRef __unused ctx, const CGRect &rect) { d->drawNSViewInRect(sv, opt->rect, p, ^(CGContextRef __unused ctx, const CGRect &rect) {
[sv drawDividerInRect:rect]; [sv drawDividerInRect:rect];
}); });
} else { } else {
@ -5088,7 +5035,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
[slider.cell startTrackingAt:pressPoint inView:slider]; [slider.cell startTrackingAt:pressPoint inView:slider];
} }
d->drawNSViewInRect(cw, slider, opt->rect, p, widget != 0, ^(CGContextRef ctx, const CGRect &rect) { d->drawNSViewInRect(slider, opt->rect, p, ^(CGContextRef ctx, const CGRect &rect) {
if (isHorizontal && sl->upsideDown) { if (isHorizontal && sl->upsideDown) {
CGContextTranslateCTM(ctx, rect.size.width, 0); CGContextTranslateCTM(ctx, rect.size.width, 0);
CGContextScaleCTM(ctx, -1, 1); CGContextScaleCTM(ctx, -1, 1);
@ -5250,7 +5197,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
} }
pb.frame = frameRect.toCGRect(); pb.frame = frameRect.toCGRect();
[pb highlight:isPressed]; [pb highlight:isPressed];
d->drawNSViewInRect(cw, pb, frameRect, p, widget != 0, ^(CGContextRef __unused ctx, const CGRect &r) { d->drawNSViewInRect(pb, frameRect, p, ^(CGContextRef __unused ctx, const CGRect &r) {
[pb.cell drawBezelWithFrame:r inView:pb.superview]; [pb.cell drawBezelWithFrame:r inView:pb.superview];
}); });
} else if (cw.type == QMacStylePrivate::ComboBox) { } else if (cw.type == QMacStylePrivate::ComboBox) {
@ -5263,7 +5210,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
#else #else
// TODO Render to pixmap and darken the button manually // TODO Render to pixmap and darken the button manually
#endif #endif
d->drawNSViewInRect(cw, cb, frameRect, p, widget != 0, ^(CGContextRef __unused ctx, const CGRect &r) { d->drawNSViewInRect(cb, frameRect, p, ^(CGContextRef __unused ctx, const CGRect &r) {
// FIXME This is usually drawn in the control's superview, but we wouldn't get inactive look in this case // FIXME This is usually drawn in the control's superview, but we wouldn't get inactive look in this case
[cb.cell drawWithFrame:r inView:cb]; [cb.cell drawWithFrame:r inView:cb];
}); });
@ -5300,12 +5247,12 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
// FIXME A single drawPath() with 0-sized pen // FIXME A single drawPath() with 0-sized pen
// doesn't look as good as this double fillPath(). // doesn't look as good as this double fillPath().
const auto outterFrameRect = QRectF(opt->rect.adjusted(0, 0, 0, opt->rect.height())); const auto outerFrameRect = QRectF(opt->rect.adjusted(0, 0, 0, opt->rect.height()));
QPainterPath outterFramePath = d->windowPanelPath(outterFrameRect); QPainterPath outerFramePath = d->windowPanelPath(outerFrameRect);
p->fillPath(outterFramePath, opt->palette.dark()); p->fillPath(outerFramePath, opt->palette.dark());
const auto frameAdjust = 1.0 / p->device()->devicePixelRatioF(); const auto frameAdjust = 1.0 / p->device()->devicePixelRatioF();
const auto innerFrameRect = outterFrameRect.adjusted(frameAdjust, frameAdjust, -frameAdjust, 0); const auto innerFrameRect = outerFrameRect.adjusted(frameAdjust, frameAdjust, -frameAdjust, 0);
QPainterPath innerFramePath = d->windowPanelPath(innerFrameRect); QPainterPath innerFramePath = d->windowPanelPath(innerFrameRect);
if (isActive) { if (isActive) {
QLinearGradient g; QLinearGradient g;
@ -5341,7 +5288,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
auto *wbCell = static_cast<NSButtonCell *>(wb.cell); auto *wbCell = static_cast<NSButtonCell *>(wb.cell);
[wbCell drawWithFrame:rect inView:wb]; [wbCell drawWithFrame:rect inView:wb];
}; };
d->drawNSViewInRect(cw, wb, buttonRect, p, widget != nullptr, drawBlock); d->drawNSViewInRect(wb, buttonRect, p, drawBlock);
} }
} }
@ -5451,7 +5398,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
[pb highlight:isPressed]; [pb highlight:isPressed];
pb.state = isHighlighted && !isPressed ? NSOnState : NSOffState; pb.state = isHighlighted && !isPressed ? NSOnState : NSOffState;
const auto buttonRect = proxy()->subControlRect(cc, tb, SC_ToolButton, widget); const auto buttonRect = proxy()->subControlRect(cc, tb, SC_ToolButton, widget);
d->drawNSViewInRect(cw, pb, buttonRect, p, ^(CGContextRef __unused ctx, const CGRect &rect) { d->drawNSViewInRect(pb, buttonRect, p, ^(CGContextRef __unused ctx, const CGRect &rect) {
[pb.cell drawBezelWithFrame:rect inView:pb]; [pb.cell drawBezelWithFrame:rect inView:pb];
}); });
} }

View File

@ -236,13 +236,7 @@ public:
// Ideally these wouldn't exist, but since they already exist we need some accessors. // Ideally these wouldn't exist, but since they already exist we need some accessors.
static const int PushButtonLeftOffset; static const int PushButtonLeftOffset;
static const int PushButtonTopOffset;
static const int PushButtonRightOffset; static const int PushButtonRightOffset;
static const int PushButtonBottomOffset;
static const int MiniButtonH;
static const int SmallButtonH;
static const int BevelButtonW;
static const int BevelButtonH;
static const int PushButtonContentPadding; static const int PushButtonContentPadding;
enum Animates { AquaPushButton, AquaProgressBar, AquaListViewItemOpen, AquaScrollBar }; enum Animates { AquaPushButton, AquaProgressBar, AquaListViewItemOpen, AquaScrollBar };
@ -269,7 +263,7 @@ public:
void setupVerticalInvertedXform(CGContextRef cg, bool reverse, bool vertical, const CGRect &rect) const; void setupVerticalInvertedXform(CGContextRef cg, bool reverse, bool vertical, const CGRect &rect) const;
void drawNSViewInRect(CocoaControl widget, NSView *view, const QRectF &rect, QPainter *p, bool isQWidget = true, __attribute__((noescape)) DrawRectBlock drawRectBlock = nil) const; void drawNSViewInRect(NSView *view, const QRectF &rect, QPainter *p, __attribute__((noescape)) DrawRectBlock drawRectBlock = nil) const;
void resolveCurrentNSView(QWindow *window) const; void resolveCurrentNSView(QWindow *window) const;
void drawFocusRing(QPainter *p, const QRectF &targetRect, int hMargin, int vMargin, const CocoaControl &cw) const; void drawFocusRing(QPainter *p, const QRectF &targetRect, int hMargin, int vMargin, const CocoaControl &cw) const;
@ -283,6 +277,7 @@ public:
#if QT_CONFIG(tabbar) #if QT_CONFIG(tabbar)
void tabLayout(const QStyleOptionTab *opt, const QWidget *widget, QRect *textRect, QRect *iconRect) const; void tabLayout(const QStyleOptionTab *opt, const QWidget *widget, QRect *textRect, QRect *iconRect) const;
static Direction tabDirection(QTabBar::Shape shape); static Direction tabDirection(QTabBar::Shape shape);
static bool verticalTabs(QMacStylePrivate::Direction tabDirection);
#endif #endif
public: public:

View File

@ -130,6 +130,7 @@ QT_BEGIN_NAMESPACE
} }
Q_CORE_EXPORT void qt_call_post_routines(); Q_CORE_EXPORT void qt_call_post_routines();
Q_GUI_EXPORT bool qt_sendShortcutOverrideEvent(QObject *o, ulong timestamp, int k, Qt::KeyboardModifiers mods, const QString &text = QString(), bool autorep = false, ushort count = 1);
QApplicationPrivate *QApplicationPrivate::self = 0; QApplicationPrivate *QApplicationPrivate::self = 0;
@ -3075,8 +3076,19 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
switch (e->type()) { switch (e->type()) {
case QEvent::KeyPress: { case QEvent::KeyPress: {
int key = static_cast<QKeyEvent*>(e)->key(); QKeyEvent* keyEvent = static_cast<QKeyEvent*>(e);
qt_in_tab_key_event = (key == Qt::Key_Backtab const int key = keyEvent->key();
// When a key press is received which is not spontaneous then it needs to
// be manually sent as a shortcut override event to ensure that any
// matching shortcut is triggered first. This enables emulation/playback
// of recorded events to still have the same effect.
if (!e->spontaneous() && receiver->isWidgetType()) {
if (qt_sendShortcutOverrideEvent(qobject_cast<QWidget *>(receiver), keyEvent->timestamp(),
key, keyEvent->modifiers(), keyEvent->text(),
keyEvent->isAutoRepeat(), keyEvent->count()))
return true;
}
qt_in_tab_key_event = (key == Qt::Key_Backtab
|| key == Qt::Key_Tab || key == Qt::Key_Tab
|| key == Qt::Key_Left || key == Qt::Key_Left
|| key == Qt::Key_Up || key == Qt::Key_Up

View File

@ -187,8 +187,15 @@ static bool correctWidgetContext(Qt::ShortcutContext context, QWidget *w, QWidge
active_window = active_window->parentWidget()->window(); active_window = active_window->parentWidget()->window();
} }
if (active_window != tlw) if (active_window != tlw) {
#if QT_CONFIG(menubar)
// If the tlw is a QMenuBar then we allow it to proceed as this indicates that
// the QMenuBar is a parentless one and is therefore used for multiple top level
// windows in the application. This is common on macOS platforms for example.
if (!qobject_cast<QMenuBar *>(tlw))
#endif
return false; return false;
}
/* if we live in a MDI subwindow, ignore the event if we are /* if we live in a MDI subwindow, ignore the event if we are
not the active document window */ not the active document window */

View File

@ -327,15 +327,13 @@ void QTipLabel::timerEvent(QTimerEvent *e)
bool QTipLabel::eventFilter(QObject *o, QEvent *e) bool QTipLabel::eventFilter(QObject *o, QEvent *e)
{ {
switch (e->type()) { switch (e->type()) {
#if 0 // Used to be included in Qt4 for Q_WS_MAC #ifdef Q_OS_MACOS
case QEvent::KeyPress: case QEvent::KeyPress:
case QEvent::KeyRelease: { case QEvent::KeyRelease: {
int key = static_cast<QKeyEvent *>(e)->key(); const int key = static_cast<QKeyEvent *>(e)->key();
Qt::KeyboardModifiers mody = static_cast<QKeyEvent *>(e)->modifiers(); // Anything except key modifiers or caps-lock, etc.
if (!(mody & Qt::KeyboardModifierMask) if (key < Qt::Key_Shift || key > Qt::Key_ScrollLock)
&& key != Qt::Key_Shift && key != Qt::Key_Control hideTipImmediately();
&& key != Qt::Key_Alt && key != Qt::Key_Meta)
hideTip();
break; break;
} }
#endif #endif

View File

@ -1231,9 +1231,9 @@ QSplitterHandle *QSplitter::createHandle()
} }
/*! /*!
Returns the handle to the left (or above) for the item in the Returns the handle to the left of (or above) the item in the
splitter's layout at the given \a index. The handle at index 0 is splitter's layout at the given \a index, or \c nullptr if there is no such item.
always hidden. The handle at index 0 is always hidden.
For right-to-left languages such as Arabic and Hebrew, the layout For right-to-left languages such as Arabic and Hebrew, the layout
of horizontal splitters is reversed. The handle will be to the of horizontal splitters is reversed. The handle will be to the
@ -1250,7 +1250,8 @@ QSplitterHandle *QSplitter::handle(int index) const
} }
/*! /*!
Returns the widget at the given \a index in the splitter's layout. Returns the widget at the given \a index in the splitter's layout,
or \c nullptr if there is no such widget.
\sa count(), handle(), indexOf(), insertWidget() \sa count(), handle(), indexOf(), insertWidget()
*/ */

View File

@ -376,7 +376,8 @@ QTabWidget::~QTabWidget()
\fn int QTabWidget::addTab(QWidget *page, const QString &label) \fn int QTabWidget::addTab(QWidget *page, const QString &label)
Adds a tab with the given \a page and \a label to the tab widget, Adds a tab with the given \a page and \a label to the tab widget,
and returns the index of the tab in the tab bar. and returns the index of the tab in the tab bar. Ownership of \a page
is passed on to the QTabWidget.
If the tab's \a label contains an ampersand, the letter following If the tab's \a label contains an ampersand, the letter following
the ampersand is used as a shortcut for the tab, e.g. if the the ampersand is used as a shortcut for the tab, e.g. if the
@ -403,7 +404,8 @@ int QTabWidget::addTab(QWidget *child, const QString &label)
\overload \overload
Adds a tab with the given \a page, \a icon, and \a label to the tab Adds a tab with the given \a page, \a icon, and \a label to the tab
widget, and returns the index of the tab in the tab bar. widget, and returns the index of the tab in the tab bar. Ownership
of \a page is passed on to the QTabWidget.
This function is the same as addTab(), but with an additional \a This function is the same as addTab(), but with an additional \a
icon. icon.
@ -419,7 +421,8 @@ int QTabWidget::addTab(QWidget *child, const QIcon& icon, const QString &label)
Inserts a tab with the given \a label and \a page into the tab Inserts a tab with the given \a label and \a page into the tab
widget at the specified \a index, and returns the index of the widget at the specified \a index, and returns the index of the
inserted tab in the tab bar. inserted tab in the tab bar. Ownership of \a page is passed on to the
QTabWidget.
The label is displayed in the tab and may vary in appearance depending The label is displayed in the tab and may vary in appearance depending
on the configuration of the tab widget. on the configuration of the tab widget.
@ -458,7 +461,8 @@ int QTabWidget::insertTab(int index, QWidget *w, const QString &label)
Inserts a tab with the given \a label, \a page, and \a icon into Inserts a tab with the given \a label, \a page, and \a icon into
the tab widget at the specified \a index, and returns the index of the the tab widget at the specified \a index, and returns the index of the
inserted tab in the tab bar. inserted tab in the tab bar. Ownership of \a page is passed on to the
QTabWidget.
This function is the same as insertTab(), but with an additional This function is the same as insertTab(), but with an additional
\a icon. \a icon.

View File

@ -23,3 +23,6 @@ osx-10.12 ci
[testInputEvents] [testInputEvents]
rhel-7.4 rhel-7.4
[isActive]
# QTBUG-67768
ubuntu

View File

@ -67,6 +67,7 @@ private slots:
void keysequence(); // QTBUG-53381 void keysequence(); // QTBUG-53381
void disableShortcutsWithBlockedWidgets_data(); void disableShortcutsWithBlockedWidgets_data();
void disableShortcutsWithBlockedWidgets(); void disableShortcutsWithBlockedWidgets();
void shortcutFromKeyEvent(); // QTBUG-48325
private: private:
int m_lastEventType; int m_lastEventType;
@ -509,5 +510,41 @@ void tst_QAction::disableShortcutsWithBlockedWidgets()
QCOMPARE(spy.count(), 0); QCOMPARE(spy.count(), 0);
} }
class ShortcutOverrideWidget : public QWidget
{
public:
ShortcutOverrideWidget(QWidget *parent = 0) : QWidget(parent), shortcutOverrideCount(0) {}
int shortcutOverrideCount;
protected:
bool event(QEvent *e)
{
if (e->type() == QEvent::ShortcutOverride)
++shortcutOverrideCount;
return QWidget::event(e);
}
};
// Test that a key press event sent with sendEvent() still gets handled as a possible
// ShortcutOverride event first before passing it on as a normal KeyEvent.
void tst_QAction::shortcutFromKeyEvent()
{
ShortcutOverrideWidget testWidget;
QAction action;
action.setShortcut(Qt::Key_1);
testWidget.addAction(&action);
testWidget.show();
QSignalSpy spy(&action, &QAction::triggered);
QVERIFY(spy.isValid());
QVERIFY(QTest::qWaitForWindowActive(&testWidget));
QCOMPARE(testWidget.shortcutOverrideCount, 0);
// Don't use the QTest::keyPress approach as this will take the
// shortcut route for us
QKeyEvent e(QEvent::KeyPress, Qt::Key_1, Qt::NoModifier);
QApplication::sendEvent(&testWidget, &e);
QCOMPARE(spy.count(), 1);
QCOMPARE(testWidget.shortcutOverrideCount, 1);
}
QTEST_MAIN(tst_QAction) QTEST_MAIN(tst_QAction)
#include "tst_qaction.moc" #include "tst_qaction.moc"

View File

@ -28,6 +28,7 @@
#include <QApplication> #include <QApplication>
#include <QVBoxLayout> #include <QVBoxLayout>
#include <QGridLayout>
#include <QWidget> #include <QWidget>
#include <QLabel> #include <QLabel>
#include <QPushButton> #include <QPushButton>
@ -36,200 +37,123 @@
class ShortcutTester : public QWidget class ShortcutTester : public QWidget
{ {
public: public:
ShortcutTester() { ShortcutTester()
{
const QString title = QLatin1String(QT_VERSION_STR) + QLatin1Char(' ')
+ qApp->platformName();
setWindowTitle(title);
setupLayout(); setupLayout();
} }
protected:
void setupLayout()
{
QVBoxLayout *layout = new QVBoxLayout(this);
setLayout(layout);
QLabel *testPurpose = new QLabel(); private:
testPurpose->setWordWrap(true); void setupLayout();
testPurpose->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Expanding); void addToGrid(QWidget *w, int &row, int col);
testPurpose->setText("This test come in handy to verify shortcuts under different " void addShortcutToGrid(const QKeySequence &k, int &row, int col);
"keyboard layouts - qwerty, dvorak, non-latin (russian, arabic), etc."); void addShortcutToGrid(int key, int &row, int col)
layout->addWidget(testPurpose); { addShortcutToGrid(QKeySequence(key), row, col); }
QKeySequence altShiftG(Qt::AltModifier + Qt::ShiftModifier + Qt::Key_G); QGridLayout *m_gridLayout = new QGridLayout;
QPushButton *_altShiftG = new QPushButton(altShiftG.toString());
_altShiftG->setShortcut(altShiftG);
layout->addWidget(_altShiftG);
QKeySequence altG(Qt::AltModifier + Qt::Key_G);
QPushButton *_altG = new QPushButton(altG.toString());
_altG->setShortcut(altG);
layout->addWidget(_altG);
QKeySequence ctrlShiftR(Qt::ControlModifier + Qt::ShiftModifier + Qt::Key_R);
QPushButton *_ctrlShiftR = new QPushButton(ctrlShiftR.toString());
_ctrlShiftR->setShortcut(ctrlShiftR);
layout->addWidget(_ctrlShiftR);
QKeySequence ctrlR(Qt::ControlModifier + Qt::Key_R);
QPushButton *_ctrlR = new QPushButton(ctrlR.toString());
_ctrlR->setShortcut(ctrlR);
layout->addWidget(_ctrlR);
QKeySequence ctrlReturn(Qt::ControlModifier + Qt::Key_Return);
QPushButton *_ctrlReturn = new QPushButton(ctrlReturn.toString());
_ctrlReturn->setShortcut(ctrlReturn);
layout->addWidget(_ctrlReturn);
QKeySequence ctrlEnter(Qt::ControlModifier + Qt::Key_Enter);
QPushButton *_ctrlEnter = new QPushButton(ctrlEnter.toString());
_ctrlEnter->setShortcut(ctrlEnter);
layout->addWidget(_ctrlEnter);
QKeySequence ctrlShiftAltR(Qt::ControlModifier + Qt::ShiftModifier + Qt::AltModifier + Qt::Key_R);
QPushButton *_ctrlShiftAltR = new QPushButton(ctrlShiftAltR.toString());
_ctrlShiftAltR->setShortcut(ctrlShiftAltR);
layout->addWidget(_ctrlShiftAltR);
QKeySequence shift5(Qt::ShiftModifier + Qt::Key_5);
QPushButton *_shift5 = new QPushButton(shift5.toString());
_shift5->setShortcut(shift5);
layout->addWidget(_shift5);
QKeySequence shiftPercent(Qt::ShiftModifier + Qt::Key_Percent);
QPushButton *_shiftPercent = new QPushButton(shiftPercent.toString());
_shiftPercent->setShortcut(shiftPercent);
layout->addWidget(_shiftPercent);
QKeySequence percent(Qt::Key_Percent);
QPushButton *_percent = new QPushButton(percent.toString());
_percent->setShortcut(percent);
layout->addWidget(_percent);
QKeySequence key5(Qt::Key_5);
QPushButton *_key5 = new QPushButton(key5.toString());
_key5->setShortcut(key5);
layout->addWidget(_key5);
QKeySequence keyQ(Qt::Key_Q);
QPushButton *_keyQ = new QPushButton(keyQ.toString());
_keyQ->setShortcut(keyQ);
layout->addWidget(_keyQ);
QKeySequence ctrlPercent(Qt::ControlModifier + Qt::Key_Percent);
QPushButton *_ctrlPercent = new QPushButton(ctrlPercent.toString());
_ctrlPercent->setShortcut(ctrlPercent);
layout->addWidget(_ctrlPercent);
QKeySequence ctrlShift5(Qt::ControlModifier + Qt::ShiftModifier + Qt::Key_5);
QPushButton *_ctrlShift5 = new QPushButton(ctrlShift5.toString());
_ctrlShift5->setShortcut(ctrlShift5);
layout->addWidget(_ctrlShift5);
QKeySequence ctrl5(Qt::ControlModifier + Qt::Key_5);
QPushButton *_ctrl5 = new QPushButton(ctrl5.toString());
_ctrl5->setShortcut(ctrl5);
layout->addWidget(_ctrl5);
QKeySequence alt5(Qt::AltModifier + Qt::Key_5);
QPushButton *_alt5 = new QPushButton(alt5.toString());
_alt5->setShortcut(alt5);
layout->addWidget(_alt5);
QKeySequence ctrlPlus(Qt::ControlModifier + Qt::Key_Plus);
QPushButton *_ctrlPlus = new QPushButton(ctrlPlus.toString());
_ctrlPlus->setShortcut(ctrlPlus);
layout->addWidget(_ctrlPlus);
QKeySequence ctrlShiftPlus(Qt::ControlModifier + Qt::ShiftModifier + Qt::Key_Plus);
QPushButton *_ctrlShiftPlus = new QPushButton(ctrlShiftPlus.toString());
_ctrlShiftPlus->setShortcut(ctrlShiftPlus);
layout->addWidget(_ctrlShiftPlus);
QKeySequence ctrlY(Qt::ControlModifier + Qt::Key_Y);
QPushButton *_ctrlY = new QPushButton(ctrlY.toString());
_ctrlY->setShortcut(ctrlY);
layout->addWidget(_ctrlY);
QKeySequence shiftComma(Qt::ShiftModifier + Qt::Key_Comma);
QPushButton *_shiftComma = new QPushButton(shiftComma.toString());
_shiftComma->setShortcut(shiftComma);
layout->addWidget(_shiftComma);
QKeySequence ctrlComma(Qt::ControlModifier + Qt::Key_Comma);
QPushButton *_ctrlComma = new QPushButton(ctrlComma.toString());
_ctrlComma->setShortcut(ctrlComma);
layout->addWidget(_ctrlComma);
QKeySequence ctrlSlash(Qt::ControlModifier + Qt::Key_Slash);
QPushButton *_ctrlSlash = new QPushButton(ctrlSlash.toString());
_ctrlSlash->setShortcut(ctrlSlash);
layout->addWidget(_ctrlSlash);
QKeySequence ctrlBackslash(Qt::ControlModifier + Qt::Key_Backslash);
QPushButton *_ctrlBackslash = new QPushButton(ctrlBackslash.toString());
_ctrlBackslash->setShortcut(ctrlBackslash);
layout->addWidget(_ctrlBackslash);
QKeySequence metaShiftA(Qt::MetaModifier + Qt::ShiftModifier + Qt::Key_A);
QPushButton *_metaShiftA = new QPushButton(metaShiftA.toString());
_metaShiftA->setShortcut(metaShiftA);
layout->addWidget(_metaShiftA);
QKeySequence metaShift5(Qt::MetaModifier + Qt::ShiftModifier + Qt::Key_5);
QPushButton *_metaShift5 = new QPushButton(metaShift5.toString());
_metaShift5->setShortcut(metaShift5);
layout->addWidget(_metaShift5);
QKeySequence ctrlBracketRigth(Qt::ControlModifier + Qt::Key_BracketRight);
QPushButton *_ctrlBracketRigth = new QPushButton(ctrlBracketRigth.toString());
_ctrlBracketRigth->setShortcut(ctrlBracketRigth);
layout->addWidget(_ctrlBracketRigth);
QKeySequence shiftF3(Qt::ShiftModifier + Qt::Key_F3);
QPushButton *_shiftF3 = new QPushButton(shiftF3.toString());
_shiftF3->setShortcut(shiftF3);
layout->addWidget(_shiftF3);
QKeySequence ctrlF3(Qt::ControlModifier + Qt::Key_F3);
QPushButton *_ctrlF3 = new QPushButton(ctrlF3.toString());
_ctrlF3->setShortcut(ctrlF3);
layout->addWidget(_ctrlF3);
QKeySequence euro(0x20AC); // EURO SIGN e.g. US (with euro on 5) on 3rd keyboard level
QPushButton *_euro = new QPushButton(euro.toString());
_euro->setShortcut(euro);
layout->addWidget(_euro);
QKeySequence ctrlEuro(Qt::ControlModifier + 0x20AC);
QPushButton *_ctrlEuro = new QPushButton(ctrlEuro.toString());
_ctrlEuro->setShortcut(ctrlEuro);
layout->addWidget(_ctrlEuro);
// with german (neo 2) layout on linux under ISO_Level3_Shift + ISO_Level5_Shift + I
QKeySequence greekPsi(QString(QStringLiteral("\u03A8")));
QPushButton *_greekPsi = new QPushButton(greekPsi.toString());
_greekPsi->setShortcut(greekPsi);
layout->addWidget(_greekPsi);
layout->addWidget(new QLabel("Norwegian layout"));
// LATIN SMALL LETTER O WITH STROKE
QKeySequence norwegianO(QString(QStringLiteral("\u00F8")));
QPushButton *_norwegianO = new QPushButton(norwegianO.toString());
_norwegianO->setShortcut(norwegianO);
layout->addWidget(_norwegianO);
layout->addWidget(new QLabel("Russian layout"));
// CYRILLIC SMALL LETTER ZHE
QKeySequence zhe(QString(QStringLiteral("\u0436")));
QPushButton *_zhe = new QPushButton(zhe.toString());
_zhe->setShortcut(zhe);
layout->addWidget(_zhe);
// for sequence definitons see qplatformtheme.cpp
layout->addWidget(new QLabel("QKeySequence::StandardKey(s)"));
QPushButton *_open = new QPushButton("Open");
_open->setShortcut(QKeySequence::Open); // Qt::CTRL | Qt::Key_O
layout->addWidget(_open);
}
}; };
inline void ShortcutTester::addToGrid(QWidget *w, int &row, int col)
{
m_gridLayout->addWidget(w, row++, col);
}
void ShortcutTester::addShortcutToGrid(const QKeySequence &k, int &row, int col)
{
QPushButton *button = new QPushButton(k.toString());
button->setShortcut(k);
addToGrid(button, row, col);
}
void addShortcutToGrid(int key, int &row, int col);
void ShortcutTester::setupLayout()
{
QVBoxLayout *layout = new QVBoxLayout(this);
QLabel *testPurpose = new QLabel();
testPurpose->setWordWrap(true);
testPurpose->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Expanding);
testPurpose->setText("This test come in handy to verify shortcuts under different "
"keyboard layouts - qwerty, dvorak, non-latin (russian, arabic), etc.");
layout->addWidget(testPurpose);
layout->addLayout(m_gridLayout);
int row = 0;
int col = 0;
const int keys1[] = {
Qt::AltModifier + Qt::ShiftModifier + Qt::Key_G,
Qt::AltModifier + Qt::Key_G,
Qt::ControlModifier + Qt::ShiftModifier + Qt::Key_R,
Qt::ControlModifier + Qt::Key_R,
Qt::ControlModifier + Qt::Key_Return, Qt::ControlModifier + Qt::Key_Enter,
Qt::ControlModifier + Qt::ShiftModifier + Qt::AltModifier + Qt::Key_R,
Qt::ShiftModifier + Qt::Key_5, Qt::ShiftModifier + Qt::Key_Percent,
Qt::Key_Percent, Qt::Key_5, Qt::Key_Q
};
for (int k : keys1)
addShortcutToGrid(k, row, col);
row = 0;
col++;
const int keys2[] = {
Qt::ControlModifier + Qt::Key_Percent,
Qt::ControlModifier + Qt::ShiftModifier + Qt::Key_5,
Qt::ControlModifier + Qt::Key_5, Qt::AltModifier + Qt::Key_5,
Qt::ControlModifier + Qt::Key_Plus,
Qt::ControlModifier + Qt::ShiftModifier + Qt::Key_Plus,
Qt::ControlModifier + Qt::Key_Y, Qt::ShiftModifier + Qt::Key_Comma,
Qt::ControlModifier + Qt::Key_Comma, Qt::ControlModifier + Qt::Key_Slash,
Qt::ControlModifier + Qt::Key_Backslash
};
for (int k : keys2)
addShortcutToGrid(k, row, col);
row = 0;
col++;
const int keys3[] = {
Qt::MetaModifier + Qt::ShiftModifier + Qt::Key_A,
Qt::MetaModifier + Qt::ShiftModifier + Qt::Key_5,
Qt::ControlModifier + Qt::Key_BracketRight,
Qt::ShiftModifier + Qt::Key_F3,
Qt::ControlModifier + Qt::Key_F3,
0x20AC, // EURO SIGN e.g. US (with euro on 5) on 3rd keyboard level
Qt::ControlModifier + 0x20AC
};
for (int k : keys3)
addShortcutToGrid(k, row, col);
// with german (neo 2) layout on linux under ISO_Level3_Shift + ISO_Level5_Shift + I
const QKeySequence greekPsi(QString(QStringLiteral("\u03A8")));
addShortcutToGrid(greekPsi, row, col);
row = 0;
col++;
addToGrid(new QLabel("Norwegian layout"), row, col);
// LATIN SMALL LETTER O WITH STROKE
QKeySequence norwegianO(QString(QStringLiteral("\u00F8")));
addShortcutToGrid(norwegianO, row, col);
addToGrid(new QLabel("Russian layout"), row, col);
// CYRILLIC SMALL LETTER ZHE
QKeySequence zhe(QString(QStringLiteral("\u0436")));
addShortcutToGrid(zhe, row, col);
// for sequence definitons see qplatformtheme.cpp
addToGrid(new QLabel("QKeySequence::StandardKey(s)"), row, col);
addShortcutToGrid(QKeySequence(QKeySequence::Open), row, col); // Qt::CTRL | Qt::Key_O
}
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
QApplication a(argc, argv); QApplication a(argc, argv);