summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGabriel de Dietrich <gabriel.dedietrich@digia.com>2014-09-04 19:11:23 +0200
committerGabriel de Dietrich <gabriel.dedietrich@digia.com>2014-09-11 11:53:53 +0200
commit982b9b7ec2441103b100c09cfcca4755d67fe839 (patch)
tree9b1a11f3b5feca720a448b5654fe7c2423406a98 /src
parentc1b46b98edc2f12fb7c596660777debed9191f52 (diff)
QMacStyle: Use NSView rendering for some inactive widgets on 10.10
Right now, we use them for inactive non-editable combo box, check box, and radio button only on Yosemite. We keep as much as possible the previous behavior on older versions. In addition, we add a way for QQuickStyleItem to specify the window the item is on. This is currently without effect, since we don't seem to take the inactive window state into account. Task-number: QTBUG-40833 Change-Id: I2fb2a99e6adf1972f881195b79b07ce85a960273 Reviewed-by: Morten Johan Sørvig <morten.sorvig@digia.com>
Diffstat (limited to 'src')
-rw-r--r--src/widgets/styles/qmacstyle_mac.mm125
-rw-r--r--src/widgets/styles/qmacstyle_mac_p_p.h8
-rw-r--r--src/widgets/styles/qstylehelper.cpp10
-rw-r--r--src/widgets/styles/qstylehelper_p.h2
4 files changed, 142 insertions, 3 deletions
diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm
index 1f6940f063..d74e032412 100644
--- a/src/widgets/styles/qmacstyle_mac.mm
+++ b/src/widgets/styles/qmacstyle_mac.mm
@@ -1702,7 +1702,7 @@ void QMacStylePrivate::setAutoDefaultButton(QObject *button) const
}
QMacStylePrivate::QMacStylePrivate()
- : mouseDown(false)
+ : mouseDown(false), backingStoreNSView(nil)
{
defaultButtonStart = CFAbsoluteTimeGetCurrent();
memset(&buttonState, 0, sizeof(ButtonState));
@@ -1715,6 +1715,12 @@ QMacStylePrivate::QMacStylePrivate()
}
+QMacStylePrivate::~QMacStylePrivate()
+{
+ Q_FOREACH (NSView *b, buttons)
+ [b release];
+}
+
ThemeDrawState QMacStylePrivate::getDrawState(QStyle::State flags)
{
ThemeDrawState tds = kThemeStateActive;
@@ -1732,6 +1738,97 @@ ThemeDrawState QMacStylePrivate::getDrawState(QStyle::State flags)
return tds;
}
+NSView *QMacStylePrivate::buttonOfKind(ThemeButtonKind kind) const
+{
+ NSView *bv = buttons[kind];
+ if (!bv) {
+ if (kind == kThemePopupButton)
+ bv = [[NSPopUpButton alloc] init];
+ else if (kind == kThemeComboBox)
+ bv = [[NSComboBox alloc] init];
+ else
+ bv = [[NSButton alloc] init];
+
+ switch (kind) {
+ case kThemeArrowButton: {
+ NSButton *bc = (NSButton *)bv;
+ bc.buttonType = NSOnOffButton;
+ bc.bezelStyle = NSDisclosureBezelStyle;
+ break;
+ }
+ case kThemeCheckBox:
+ case kThemeCheckBoxSmall:
+ case kThemeCheckBoxMini: {
+ NSButton *bc = (NSButton *)bv;
+ bc.buttonType = NSSwitchButton;
+ break;
+ }
+ case kThemeRadioButton:
+ case kThemeRadioButtonSmall:
+ case kThemeRadioButtonMini: {
+ NSButton *bc = (NSButton *)bv;
+ bc.buttonType = NSRadioButton;
+ break;
+ }
+ case kThemePushButton:
+ case kThemePushButtonSmall:
+ case kThemePushButtonMini: {
+ NSButton *bc = (NSButton *)bv;
+ bc.buttonType = NSMomentaryPushButton;
+ bc.bezelStyle = NSRoundedBezelStyle;
+ break;
+ }
+ default:
+ break;
+ }
+
+// if (kind == kThemePushButtonSmall
+// || kind == kThemePopupButtonSmall
+// || kind == kThemeCheckBoxSmall
+// || kind == kThemeRadioButtonSmall)
+// bc.controlSize = NSSmallControlSize;
+// else if (kind == kThemePushButtonMini
+// || kind == kThemePopupButtonMini
+// || kind == kThemeCheckBoxMini
+// || kind == kThemeRadioButtonMini)
+// bc.controlSize = NSMiniControlSize;
+
+ if ([bv isKindOfClass:[NSButton class]]) {
+ NSButton *bc = (NSButton *)bv;
+ bc.title = nil;
+ }
+
+ const_cast<QMacStylePrivate *>(this)->buttons.insert(kind, bv);
+ }
+
+ return bv;
+}
+
+void QMacStylePrivate::drawNSViewInRect(NSView *view, const QRect &qtRect, QPainter *p) const
+{
+ QMacCGContext ctx(p);
+ CGContextSaveGState(ctx);
+
+ [NSGraphicsContext saveGraphicsState];
+ [NSGraphicsContext setCurrentContext:[NSGraphicsContext
+ graphicsContextWithGraphicsPort:ctx flipped:YES]];
+
+ CGRect rect = CGRectMake(qtRect.x() + 1, qtRect.y(), qtRect.width(), qtRect.height());
+
+ [backingStoreNSView addSubview:view];
+ view.frame = rect;
+ [view drawRect:rect];
+ [view removeFromSuperviewWithoutNeedingDisplay];
+
+ [NSGraphicsContext restoreGraphicsState];
+ CGContextRestoreGState(ctx);
+}
+
+void QMacStylePrivate::resolveCurrentNSView(QWindow *window)
+{
+ backingStoreNSView = window ? (NSView *)window->winId() : nil;
+}
+
void QMacStylePrivate::drawColorlessButton(const HIRect &macRect, HIThemeButtonDrawInfo *bdi,
QPainter *p, const QStyleOption *opt) const
{
@@ -1742,6 +1839,9 @@ void QMacStylePrivate::drawColorlessButton(const HIRect &macRect, HIThemeButtonD
finalyoff = 0;
const bool combo = opt->type == QStyleOption::SO_ComboBox;
+ const bool editableCombo = bdi->kind == kThemeComboBox
+ || bdi->kind == kThemeComboBoxSmall
+ || bdi->kind == kThemeComboBoxMini;
const bool button = opt->type == QStyleOption::SO_Button;
const bool pressed = bdi->state == kThemeStatePressed;
const bool usingYosemiteOrLater = QSysInfo::MacintoshVersion > QSysInfo::MV_10_9;
@@ -1789,7 +1889,7 @@ void QMacStylePrivate::drawColorlessButton(const HIRect &macRect, HIThemeButtonD
if (!combo && !button && bdi->value == kThemeButtonOff) {
pm = activePixmap;
- } else if ((combo && !usingYosemiteOrLater) || button) {
+ } else if (!usingYosemiteOrLater && (combo || button)) {
QImage image = activePixmap.toImage();
for (int y = 0; y < height; ++y) {
@@ -1816,7 +1916,17 @@ void QMacStylePrivate::drawColorlessButton(const HIRect &macRect, HIThemeButtonD
}
}
pm = QPixmap::fromImage(image);
- } else if (combo && usingYosemiteOrLater) {
+ } else if ((usingYosemiteOrLater && combo && !editableCombo) || button) {
+ NSButton *bc = (NSButton *)buttonOfKind(bdi->kind);
+ [bc highlight:pressed];
+ bc.enabled = bdi->state != kThemeStateUnavailable && bdi->state != kThemeStateUnavailableInactive;
+ bc.state = bdi->value == kThemeButtonOn ? NSOnState :
+ bdi->value == kThemeButtonMixed ? NSMixedState : NSOffState;
+ p->translate(0, 1);
+ drawNSViewInRect(bc, opt->rect, p);
+ p->translate(0, -1);
+ return;
+ } else if (usingYosemiteOrLater && editableCombo) {
QImage image = activePixmap.toImage();
for (int y = 0; y < height; ++y) {
@@ -2944,6 +3054,9 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
Q_D(const QMacStyle);
ThemeDrawState tds = d->getDrawState(opt->state);
QMacCGContext cg(p);
+ QWindow *window = w && w->window() ? w->window()->windowHandle() :
+ QStyleHelper::styleObjectWindow(opt->styleObject);
+ const_cast<QMacStylePrivate *>(d)->resolveCurrentNSView(window);
switch (pe) {
case PE_IndicatorArrowUp:
case PE_IndicatorArrowDown:
@@ -3358,6 +3471,9 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
Q_D(const QMacStyle);
ThemeDrawState tds = d->getDrawState(opt->state);
QMacCGContext cg(p);
+ QWindow *window = w && w->window() ? w->window()->windowHandle() :
+ QStyleHelper::styleObjectWindow(opt->styleObject);
+ const_cast<QMacStylePrivate *>(d)->resolveCurrentNSView(window);
switch (ce) {
case CE_HeaderSection:
if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(opt)) {
@@ -5075,6 +5191,9 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
Q_D(const QMacStyle);
ThemeDrawState tds = d->getDrawState(opt->state);
QMacCGContext cg(p);
+ QWindow *window = widget && widget->window() ? widget->window()->windowHandle() :
+ QStyleHelper::styleObjectWindow(opt->styleObject);
+ const_cast<QMacStylePrivate *>(d)->resolveCurrentNSView(window);
switch (cc) {
case CC_Slider:
case CC_ScrollBar:
diff --git a/src/widgets/styles/qmacstyle_mac_p_p.h b/src/widgets/styles/qmacstyle_mac_p_p.h
index 6f42f0ea79..3bbff61340 100644
--- a/src/widgets/styles/qmacstyle_mac_p_p.h
+++ b/src/widgets/styles/qmacstyle_mac_p_p.h
@@ -145,6 +145,7 @@ class QMacStylePrivate : public QCommonStylePrivate
Q_DECLARE_PUBLIC(QMacStyle)
public:
QMacStylePrivate();
+ ~QMacStylePrivate();
// Ideally these wouldn't exist, but since they already exist we need some accessors.
static const int PushButtonLeftOffset;
@@ -194,6 +195,11 @@ public:
void setAutoDefaultButton(QObject *button) const;
+ NSView *buttonOfKind(ThemeButtonKind kind) const;
+
+ void drawNSViewInRect(NSView *view, const QRect &rect, QPainter *p) const;
+ void resolveCurrentNSView(QWindow *window);
+
public:
mutable QPointer<QObject> pressedButton;
mutable QPointer<QObject> defaultButton;
@@ -212,6 +218,8 @@ public:
void *nsscroller;
#endif
void *indicatorBranchButtonCell;
+ NSView *backingStoreNSView;
+ QHash<ThemeButtonKind , NSView *> buttons;
};
QT_END_NAMESPACE
diff --git a/src/widgets/styles/qstylehelper.cpp b/src/widgets/styles/qstylehelper.cpp
index 6be07a3f45..49e406a8b7 100644
--- a/src/widgets/styles/qstylehelper.cpp
+++ b/src/widgets/styles/qstylehelper.cpp
@@ -47,6 +47,7 @@
#include <qmath.h>
#include <qscrollbar.h>
#include <qabstractscrollarea.h>
+#include <qwindow.h>
#include "qstylehelper_p.h"
#include <qstringbuilder.h>
@@ -397,5 +398,14 @@ QColor backgroundColor(const QPalette &pal, const QWidget* widget)
return widget->parentWidget()->parentWidget()->palette().color(QPalette::Base);
return pal.color(QPalette::Base);
}
+
+QWindow *styleObjectWindow(QObject *so)
+{
+ if (so)
+ return so->property("_q_styleObjectWindow").value<QWindow *>();
+
+ return 0;
+}
+
}
QT_END_NAMESPACE
diff --git a/src/widgets/styles/qstylehelper_p.h b/src/widgets/styles/qstylehelper_p.h
index 73e5c94dcd..1229af7497 100644
--- a/src/widgets/styles/qstylehelper_p.h
+++ b/src/widgets/styles/qstylehelper_p.h
@@ -68,6 +68,7 @@ class QPainter;
class QPixmap;
class QStyleOptionSlider;
class QStyleOption;
+class QWindow;
namespace QStyleHelper
{
@@ -87,6 +88,7 @@ namespace QStyleHelper
bool hasAncestor(QObject *obj, QAccessible::Role role);
#endif
QColor backgroundColor(const QPalette &pal, const QWidget* widget = 0);
+ QWindow *styleObjectWindow(QObject *so);
}