1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtWidgets module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 
41 #ifndef QMACSTYLE_MAC_P_P_H
42 #define QMACSTYLE_MAC_P_P_H
43 
44 #include "qmacstyle_mac_p.h"
45 
46 #include <QtCore/qdebug.h>
47 #include <QtCore/qhash.h>
48 #include <QtCore/qmap.h>
49 #include <QtCore/qmath.h>
50 #include <QtCore/qpair.h>
51 #include <QtCore/qpointer.h>
52 #include <QtCore/qtextstream.h>
53 #include <QtCore/qvector.h>
54 
55 #include <QtGui/private/qpainter_p.h>
56 
57 #include <QtGui/qbitmap.h>
58 #include <QtGui/qevent.h>
59 #include <QtGui/qpaintdevice.h>
60 #include <QtGui/qpainter.h>
61 #include <QtGui/qpixmapcache.h>
62 
63 #include <QtWidgets/private/qapplication_p.h>
64 #include <QtWidgets/private/qcommonstyle_p.h>
65 #include <QtWidgets/private/qstylehelper_p.h>
66 
67 #include <QtWidgets/qapplication.h>
68 #include <QtWidgets/qfocusframe.h>
69 #include <QtWidgets/qformlayout.h>
70 #include <QtWidgets/qlayout.h>
71 #include <QtWidgets/qstyleoption.h>
72 #include <QtWidgets/qtextedit.h>
73 
74 #if QT_CONFIG(checkbox)
75 #include <QtWidgets/qcheckbox.h>
76 #endif
77 #if QT_CONFIG(combobox)
78 #include <QtWidgets/private/qcombobox_p.h>
79 #include <QtWidgets/qcombobox.h>
80 #endif
81 #if QT_CONFIG(datetimeedit)
82 #include <QtWidgets/qdatetimeedit.h>
83 #endif
84 #if QT_CONFIG(dialogbuttonbox)
85 #include <QtWidgets/qdialogbuttonbox.h>
86 #endif
87 #if QT_CONFIG(dockwidget)
88 #include <QtWidgets/qdockwidget.h>
89 #endif
90 #if QT_CONFIG(graphicsview)
91 #include <QtWidgets/qgraphicsproxywidget.h>
92 #include <QtWidgets/qgraphicsview.h>
93 #endif
94 #if QT_CONFIG(groupbox)
95 #include <QtWidgets/qgroupbox.h>
96 #endif
97 #if QT_CONFIG(itemviews)
98 #include <QtWidgets/qheaderview.h>
99 #endif
100 #if QT_CONFIG(lineedit)
101 #include <QtWidgets/qlineedit.h>
102 #endif
103 #if QT_CONFIG(listview)
104 #include <QtWidgets/qlistview.h>
105 #endif
106 #if QT_CONFIG(mainwindow)
107 #include <QtWidgets/qmainwindow.h>
108 #endif
109 #if QT_CONFIG(menubar)
110 #include <QtWidgets/qmenubar.h>
111 #endif
112 #if QT_CONFIG(progressbar)
113 #include <QtWidgets/qprogressbar.h>
114 #endif
115 #if QT_CONFIG(pushbutton)
116 #include <QtWidgets/qpushbutton.h>
117 #endif
118 #include <QtWidgets/qradiobutton.h>
119 #if QT_CONFIG(rubberband)
120 #include <QtWidgets/qrubberband.h>
121 #endif
122 #if QT_CONFIG(sizegrip)
123 #include <QtWidgets/qsizegrip.h>
124 #endif
125 #if QT_CONFIG(spinbox)
126 #include <QtWidgets/qspinbox.h>
127 #endif
128 #if QT_CONFIG(splitter)
129 #include <QtWidgets/qsplitter.h>
130 #endif
131 #if QT_CONFIG(tableview)
132 #include <QtWidgets/qtableview.h>
133 #endif
134 #if QT_CONFIG(toolbar)
135 #include <QtWidgets/qtoolbar.h>
136 #endif
137 #if QT_CONFIG(toolbutton)
138 #include <QtWidgets/qtoolbutton.h>
139 #endif
140 #if QT_CONFIG(treeview)
141 #include <QtWidgets/qtreeview.h>
142 #endif
143 
144 //
145 //  W A R N I N G
146 //  -------------
147 //
148 // This file is not part of the Qt API.  It exists purely as an
149 // implementation detail.  This header file may change from version to
150 // version without notice, or even be removed.
151 //
152 // We mean it.
153 //
154 
155 Q_FORWARD_DECLARE_MUTABLE_CG_TYPE(CGContext);
156 
157 Q_FORWARD_DECLARE_OBJC_CLASS(NSView);
158 Q_FORWARD_DECLARE_OBJC_CLASS(NSCell);
159 
160 QT_BEGIN_NAMESPACE
161 
162 /*
163     AHIG:
164         macOS Human Interface Guidelines
165         https://developer.apple.com/macos/human-interface-guidelines/overview/themes/
166 
167     Builder:
168         Interface Builder in Xcode 8 or later
169 */
170 
171 // this works as long as we have at most 16 different control types
172 #define CT1(c) CT2(c, c)
173 #define CT2(c1, c2) ((uint(c1) << 16) | uint(c2))
174 
175 #define SIZE(large, small, mini) \
176     (controlSize == QStyleHelper::SizeLarge ? (large) : controlSize == QStyleHelper::SizeSmall ? (small) : (mini))
177 
178 // same as return SIZE(...) but optimized
179 #define return_SIZE(large, small, mini) \
180     do { \
181         static const int sizes[] = { (large), (small), (mini) }; \
182         return sizes[controlSize]; \
183     } while (false)
184 
185 class QMacStylePrivate : public QCommonStylePrivate
186 {
187     Q_DECLARE_PUBLIC(QMacStyle)
188 public:
189     enum Direction {
190         North, South, East, West
191     };
192 
193     enum CocoaControlType {
194         NoControl,    // For when there's no such a control in Cocoa
195         Box,          // QGroupBox
196         Box_Dark,     // FIXME See render code in drawPrimitive(PE_FrameTabWidget)
197         Button_CheckBox,
198         Button_Disclosure,  // Disclosure triangle, like in QTreeView
199         Button_PopupButton,  // Non-editable QComboBox
200         Button_PullDown, // QPushButton with menu
201         Button_PushButton, // Plain QPushButton and QTabBar buttons
202         Button_RadioButton,
203         Button_SquareButton, // Oversized QPushButton
204         Button_WindowClose,
205         Button_WindowMiniaturize,
206         Button_WindowZoom,
207         ComboBox,     // Editable QComboBox
208         ProgressIndicator_Determinate,
209         ProgressIndicator_Indeterminate,
210         Scroller_Horizontal,
211         Scroller_Vertical,
212         SegmentedControl_First, // QTabBar buttons focus ring
213         SegmentedControl_Middle,
214         SegmentedControl_Last,
215         SegmentedControl_Single,
216         Slider_Horizontal,
217         Slider_Vertical,
218         SplitView_Horizontal,
219         SplitView_Vertical,
220         Stepper,      // QSpinBox buttons
221         TextField
222     };
223 
224     struct CocoaControl {
225         CocoaControl();
226         CocoaControl(CocoaControlType t, QStyleHelper::WidgetSizePolicy s);
227 
228         CocoaControlType type;
229         QStyleHelper::WidgetSizePolicy size;
230 
231         bool operator==(const CocoaControl &other) const;
232 
233         QSizeF defaultFrameSize() const;
234         QRectF adjustedControlFrame(const QRectF &rect) const;
235         QMarginsF titleMargins() const;
236 
237         bool getCocoaButtonTypeAndBezelStyle(NSButtonType *buttonType, NSBezelStyle *bezelStyle) const;
238     };
239 
240 
241     typedef void (^DrawRectBlock)(CGContextRef, const CGRect &);
242 
243     QMacStylePrivate();
244     ~QMacStylePrivate();
245 
246     // Ideally these wouldn't exist, but since they already exist we need some accessors.
247     static const int PushButtonLeftOffset;
248     static const int PushButtonRightOffset;
249     static const int PushButtonContentPadding;
250 
251     enum Animates { AquaPushButton, AquaProgressBar, AquaListViewItemOpen, AquaScrollBar };
252     QStyleHelper::WidgetSizePolicy aquaSizeConstrain(const QStyleOption *option, const QWidget *widg,
253                              QStyle::ContentsType ct = QStyle::CT_CustomBase,
254                              QSize szHint=QSize(-1, -1), QSize *insz = 0) const;
255     QStyleHelper::WidgetSizePolicy effectiveAquaSizeConstrain(const QStyleOption *option, const QWidget *widg,
256                              QStyle::ContentsType ct = QStyle::CT_CustomBase,
257                              QSize szHint=QSize(-1, -1), QSize *insz = 0) const;
animateSpeed(Animates)258     inline int animateSpeed(Animates) const { return 33; }
259 
260     // Utility functions
261     static CGRect comboboxInnerBounds(const CGRect &outterBounds, const CocoaControl &cocoaWidget);
262 
263     static QRectF comboboxEditBounds(const QRectF &outterBounds, const CocoaControl &cw);
264 
265     void setAutoDefaultButton(QObject *button) const;
266 
267     NSView *cocoaControl(CocoaControl widget) const;
268     NSCell *cocoaCell(CocoaControl widget) const;
269 
270     void setupNSGraphicsContext(CGContextRef cg, bool flipped) const;
271     void restoreNSGraphicsContext(CGContextRef cg) const;
272 
273     void setupVerticalInvertedXform(CGContextRef cg, bool reverse, bool vertical, const CGRect &rect) const;
274 
275     void drawNSViewInRect(NSView *view, const QRectF &rect, QPainter *p, __attribute__((noescape)) DrawRectBlock drawRectBlock = nil) const;
276     void resolveCurrentNSView(QWindow *window) const;
277 
278     void drawFocusRing(QPainter *p, const QRectF &targetRect, int hMargin, int vMargin, const CocoaControl &cw) const;
279 
280     void drawToolbarButtonArrow(const QStyleOption *opt, QPainter *p) const;
281 
282     QPainterPath windowPanelPath(const QRectF &r) const;
283 
284     CocoaControlType windowButtonCocoaControl(QStyle::SubControl sc) const;
285 
286 #if QT_CONFIG(tabbar)
287     void tabLayout(const QStyleOptionTab *opt, const QWidget *widget, QRect *textRect, QRect *iconRect) const override;
288     static Direction tabDirection(QTabBar::Shape shape);
289     static bool verticalTabs(QMacStylePrivate::Direction tabDirection);
290 #endif
291 
292 public:
293     mutable QPointer<QObject> autoDefaultButton;
294     static  QVector<QPointer<QObject> > scrollBars;
295 
296     mutable QPointer<QFocusFrame> focusWidget;
297     mutable NSView *backingStoreNSView;
298     mutable QHash<CocoaControl, NSView *> cocoaControls;
299     mutable QHash<CocoaControl, NSCell *> cocoaCells;
300 
301     QFont smallSystemFont;
302     QFont miniSystemFont;
303 
304     QMacKeyValueObserver appearanceObserver;
305 };
306 
307 QT_END_NAMESPACE
308 
309 #endif // QMACSTYLE_MAC_P_P_H
310