Fixed crash in GL 2 paint engine on Intel Atom.
[profile/ivi/qtbase.git] / src / widgets / styles / qmacstyle_mac.mm
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the QtGui module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 /*
43   Note: The qdoc comments for QMacStyle are contained in
44   .../doc/src/qstyles.qdoc. 
45 */
46
47 #include "qmacstyle_mac.h"
48 #include "qmacstyle_mac_p.h"
49 #include "qmacstylepixmaps_mac_p.h"
50
51 #define QMAC_QAQUASTYLE_SIZE_CONSTRAIN
52 //#define DEBUG_SIZE_CONSTRAINT
53
54 #include <private/qcore_mac_p.h>
55 #include <private/qcombobox_p.h>
56 #include <private/qpainter_p.h>
57 #include <qapplication.h>
58 #include <qbitmap.h>
59 #include <qcheckbox.h>
60 #include <qcombobox.h>
61 #include <qdialogbuttonbox.h>
62 #include <qdockwidget.h>
63 #include <qevent.h>
64 #include <qfocusframe.h>
65 #include <qformlayout.h>
66 #include <qgroupbox.h>
67 #include <qhash.h>
68 #include <qheaderview.h>
69 #include <qlayout.h>
70 #include <qlineedit.h>
71 #include <qlistview.h>
72 #include <qmainwindow.h>
73 #include <qmap.h>
74 #include <qmenubar.h>
75 #include <qpaintdevice.h>
76 #include <qpainter.h>
77 #include <qpixmapcache.h>
78 #include <qpointer.h>
79 #include <qprogressbar.h>
80 #include <qpushbutton.h>
81 #include <qradiobutton.h>
82 #include <qrubberband.h>
83 #include <qsizegrip.h>
84 #include <qspinbox.h>
85 #include <qsplitter.h>
86 #include <qstyleoption.h>
87 #include <qtextedit.h>
88 #include <qtextstream.h>
89 #include <qtoolbar.h>
90 #include <qtoolbutton.h>
91 #include <qtreeview.h>
92 #include <qtableview.h>
93 #include <qwizard.h>
94 #include <qdebug.h>
95 #include <qlibrary.h>
96 #include <qdatetimeedit.h>
97 #include <qmath.h>
98 #include <QtWidgets/qgraphicsproxywidget.h>
99 #include <QtWidgets/qgraphicsview.h>
100 #include <private/qstylehelper_p.h>
101 #include <QtGui/QPlatformFontDatabase>
102
103 QT_BEGIN_NAMESPACE
104
105 // The following constants are used for adjusting the size
106 // of push buttons so that they are drawn inside their bounds.
107 const int QMacStylePrivate::PushButtonLeftOffset = 6;
108 const int QMacStylePrivate::PushButtonTopOffset = 4;
109 const int QMacStylePrivate::PushButtonRightOffset = 12;
110 const int QMacStylePrivate::PushButtonBottomOffset = 12;
111 const int QMacStylePrivate::MiniButtonH = 26;
112 const int QMacStylePrivate::SmallButtonH = 30;
113 const int QMacStylePrivate::BevelButtonW = 50;
114 const int QMacStylePrivate::BevelButtonH = 22;
115 const int QMacStylePrivate::PushButtonContentPadding = 6;
116
117 // These colors specify the titlebar gradient colors on
118 // Leopard. Ideally we should get them from the system.
119 static const QColor titlebarGradientActiveBegin(220, 220, 220);
120 static const QColor titlebarGradientActiveEnd(151, 151, 151);
121 static const QColor titlebarSeparatorLineActive(111, 111, 111);
122 static const QColor titlebarGradientInactiveBegin(241, 241, 241);
123 static const QColor titlebarGradientInactiveEnd(207, 207, 207);
124 static const QColor titlebarSeparatorLineInactive(131, 131, 131);
125
126 // Gradient colors used for the dock widget title bar and
127 // non-unifed tool bar bacground.
128 static const QColor mainWindowGradientBegin(240, 240, 240);
129 static const QColor mainWindowGradientEnd(200, 200, 200);
130
131 static const int DisclosureOffset = 4;
132
133 // Resolve these at run-time, since the functions was moved in Leopard.
134 typedef HIRect * (*PtrHIShapeGetBounds)(HIShapeRef, HIRect *);
135 static PtrHIShapeGetBounds ptrHIShapeGetBounds = 0;
136
137 static int closeButtonSize = 12;
138 static bool isVerticalTabs(const QTabBar::Shape shape) {
139     return (shape == QTabBar::RoundedEast
140                 || shape == QTabBar::TriangularEast
141                 || shape == QTabBar::RoundedWest
142                 || shape == QTabBar::TriangularWest);
143 }
144
145 void drawTabCloseButton(QPainter *p, bool hover, bool active, bool selected)
146 {
147     // draw background circle
148     p->setRenderHints(QPainter::Antialiasing);
149     QRect rect(0, 0, closeButtonSize, closeButtonSize);
150     QColor background;
151     if (hover) {
152         background = QColor(124, 124, 124);
153     } else {
154         if (active) {
155             if (selected)
156                 background = QColor(104, 104, 104);
157             else
158                 background = QColor(83, 83, 83);
159         } else {
160             if (selected)
161                 background = QColor(144, 144, 144);
162             else
163                 background = QColor(114, 114, 114);
164         }
165     }
166     p->setPen(Qt::transparent);
167     p->setBrush(background);
168     p->drawEllipse(rect);
169
170     // draw cross
171     int min = 3;
172     int max = 9;
173     QPen crossPen;
174     crossPen.setColor(QColor(194, 194, 194));
175     crossPen.setWidthF(1.3);
176     crossPen.setCapStyle(Qt::FlatCap);
177     p->setPen(crossPen);
178     p->drawLine(min, min, max, max);
179     p->drawLine(min, max, max, min);
180 }
181
182 QRect rotateTabPainter(QPainter *p, QTabBar::Shape shape, QRect tabRect)
183 {
184     if (isVerticalTabs(shape)) {
185         int newX, newY, newRot;
186         if (shape == QTabBar::RoundedEast
187             || shape == QTabBar::TriangularEast) {
188             newX = tabRect.width();
189             newY = tabRect.y();
190             newRot = 90;
191         } else {
192             newX = 0;
193             newY = tabRect.y() + tabRect.height();
194             newRot = -90;
195         }
196         tabRect.setRect(0, 0, tabRect.height(), tabRect.width());
197         QMatrix m;
198         m.translate(newX, newY);
199         m.rotate(newRot);
200         p->setMatrix(m, true);
201     }
202     return tabRect;
203 }
204
205 void drawTabShape(QPainter *p, const QStyleOptionTabV3 *tabOpt)
206 {
207     QRect r = tabOpt->rect;
208     p->translate(tabOpt->rect.x(), tabOpt->rect.y());
209     r.moveLeft(0);
210     r.moveTop(0);
211     QRect tabRect = rotateTabPainter(p, tabOpt->shape, r);
212
213     int width = tabRect.width();
214     int height = 20;
215     bool active = (tabOpt->state & QStyle::State_Active);
216     bool selected = (tabOpt->state & QStyle::State_Selected);
217
218     if (selected) {
219         QRect rect(1, 0, width - 2, height);
220
221         // fill body
222         if (active) {
223             int d = (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_6) ? 16 : 0;
224             p->fillRect(rect, QColor(151 + d, 151 + d, 151 + d));
225         } else {
226             int d = (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_6) ? 9 : 0;
227             QLinearGradient gradient(rect.topLeft(), rect.bottomLeft());
228             gradient.setColorAt(0, QColor(207 + d, 207 + d, 207 + d));
229             gradient.setColorAt(0.5, QColor(206 + d, 206 + d, 206 + d));
230             gradient.setColorAt(1, QColor(201 + d, 201 + d, 201 + d));
231             p->fillRect(rect, gradient);
232         }
233
234         // draw border
235         QColor borderSides;
236         QColor borderBottom;
237         if (active) {
238             borderSides = QColor(88, 88, 88);
239             borderBottom = QColor(88, 88, 88);
240         } else {
241             borderSides = QColor(121, 121, 121);
242             borderBottom = QColor(116, 116, 116);
243         }
244
245         p->setPen(borderSides);
246
247         int bottom = height;
248         // left line
249         p->drawLine(0, 1, 0, bottom-2);
250         // right line
251         p->drawLine(width-1, 1, width-1, bottom-2);
252
253         // bottom line
254         if (active) {
255             p->setPen(QColor(168, 168, 168));
256             p->drawLine(3, bottom-1, width-3, bottom-1);
257         }
258         p->setPen(borderBottom);
259         p->drawLine(2, bottom, width-2, bottom);
260
261         int w = 3;
262         QRectF rectangleLeft(1, height - w, w, w);
263         QRectF rectangleRight(width - 2, height - 1, w, w);
264         int startAngle = 180 * 16;
265         int spanAngle = 90 * 16;
266         p->setRenderHint(QPainter::Antialiasing);
267         p->drawArc(rectangleLeft, startAngle, spanAngle);
268         p->drawArc(rectangleRight, startAngle, -spanAngle);
269     } else {
270         // when the mouse is over non selected tabs they get a new color
271         bool hover = (tabOpt->state & QStyle::State_MouseOver);
272         if (hover) {
273             QRect rect(1, 2, width - 1, height - 1);
274             p->fillRect(rect, QColor(110, 110, 110));
275         }
276
277         // seperator lines between tabs
278         bool west = (tabOpt->shape == QTabBar::RoundedWest || tabOpt->shape == QTabBar::TriangularWest);
279         bool drawOnRight = !west;
280         if ((!drawOnRight && tabOpt->selectedPosition != QStyleOptionTab::NextIsSelected)
281             || (drawOnRight && tabOpt->selectedPosition != QStyleOptionTab::NextIsSelected)) {
282             QColor borderColor;
283             QColor borderHighlightColor;
284             if (active) {
285                 borderColor = QColor(64, 64, 64);
286                 borderHighlightColor = QColor(140, 140, 140);
287             } else {
288                 borderColor = QColor(135, 135, 135);
289                 borderHighlightColor = QColor(178, 178, 178);
290             }
291
292             int x = drawOnRight ? width : 0;
293
294             // tab seperator line
295             p->setPen(borderColor);
296             p->drawLine(x, 2, x, height + 1);
297
298             // tab seperator highlight
299             p->setPen(borderHighlightColor);
300             p->drawLine(x-1, 2, x-1, height + 1);
301             p->drawLine(x+1, 2, x+1, height + 1);
302         }
303     }
304 }
305
306 void drawTabBase(QPainter *p, const QStyleOptionTabBarBaseV2 *tbb, const QWidget *w)
307 {
308     QRect r = tbb->rect;
309     if (isVerticalTabs(tbb->shape)) {
310         r.setWidth(w->width());
311     } else {
312         r.setHeight(w->height());
313     }
314     QRect tabRect = rotateTabPainter(p, tbb->shape, r);
315     int width = tabRect.width();
316     int height = tabRect.height();
317     bool active = (tbb->state & QStyle::State_Active);
318
319     // top border lines
320     QColor borderHighlightTop;
321     QColor borderTop;
322     if (active) {
323         borderTop = QColor(64, 64, 64);
324         borderHighlightTop = QColor(174, 174, 174);
325     } else {
326         borderTop = QColor(135, 135, 135);
327         borderHighlightTop = QColor(207, 207, 207);
328     }
329     p->setPen(borderHighlightTop);
330     p->drawLine(tabRect.x(), 0, width, 0);
331     p->setPen(borderTop);
332     p->drawLine(tabRect.x(), 1, width, 1);
333
334     // center block
335     QRect centralRect(tabRect.x(), 2, width, height - 2);
336     if (active) {
337         QColor mainColor = QColor(120, 120, 120);
338         p->fillRect(centralRect, mainColor);
339     } else {
340         QLinearGradient gradient(centralRect.topLeft(), centralRect.bottomLeft());
341         gradient.setColorAt(0, QColor(165, 165, 165));
342         gradient.setColorAt(0.5, QColor(164, 164, 164));
343         gradient.setColorAt(1, QColor(158, 158, 158));
344         p->fillRect(centralRect, gradient);
345     }
346
347     // bottom border lines
348     QColor borderHighlightBottom;
349     QColor borderBottom;
350     if (active) {
351         borderHighlightBottom = QColor(153, 153, 153);
352         borderBottom = QColor(64, 64, 64);
353     } else {
354         borderHighlightBottom = QColor(177, 177, 177);
355         borderBottom = QColor(127, 127, 127);
356     }
357     p->setPen(borderHighlightBottom);
358     p->drawLine(tabRect.x(), height - 2, width, height - 2);
359     p->setPen(borderBottom);
360     p->drawLine(tabRect.x(), height - 1, width, height - 1);
361 }
362
363 static int getControlSize(const QStyleOption *option, const QWidget *widget)
364 {
365     if (option) {
366         if (option->state & (QStyle::State_Small | QStyle::State_Mini))
367             return (option->state & QStyle::State_Mini) ? QAquaSizeMini : QAquaSizeSmall;
368     } else if (widget) {
369         switch (QMacStyle::widgetSizePolicy(widget)) {
370         case QMacStyle::SizeSmall:
371             return QAquaSizeSmall;
372         case QMacStyle::SizeMini:
373             return QAquaSizeMini;
374         default:
375             break;
376         }
377     }
378     return QAquaSizeLarge;
379 }
380
381
382 static inline bool isTreeView(const QWidget *widget)
383 {
384     return (widget && widget->parentWidget() &&
385             (qobject_cast<const QTreeView *>(widget->parentWidget())
386              ));
387 }
388
389 static inline ThemeTabDirection getTabDirection(QTabBar::Shape shape)
390 {
391     ThemeTabDirection ttd;
392     switch (shape) {
393     case QTabBar::RoundedSouth:
394     case QTabBar::TriangularSouth:
395         ttd = kThemeTabSouth;
396         break;
397     default:  // Added to remove the warning, since all values are taken care of, really!
398     case QTabBar::RoundedNorth:
399     case QTabBar::TriangularNorth:
400         ttd = kThemeTabNorth;
401         break;
402     case QTabBar::RoundedWest:
403     case QTabBar::TriangularWest:
404         ttd = kThemeTabWest;
405         break;
406     case QTabBar::RoundedEast:
407     case QTabBar::TriangularEast:
408         ttd = kThemeTabEast;
409         break;
410     }
411     return ttd;
412 }
413
414 static QString qt_mac_removeMnemonics(const QString &original)
415 {
416     QString returnText(original.size(), 0);
417     int finalDest = 0;
418     int currPos = 0;
419     int l = original.length();
420     while (l) {
421         if (original.at(currPos) == QLatin1Char('&')
422             && (l == 1 || original.at(currPos + 1) != QLatin1Char('&'))) {
423             ++currPos;
424             --l;
425             if (l == 0)
426                 break;
427         }
428         returnText[finalDest] = original.at(currPos);
429         ++currPos;
430         ++finalDest;
431         --l;
432     }
433     returnText.truncate(finalDest);
434     return returnText;
435 }
436
437 class QMacCGContext
438 {
439     CGContextRef context;
440 public:
441     QMacCGContext(QPainter *p); //qpaintengine_mac.cpp
442     inline QMacCGContext() { context = 0; }
443     inline QMacCGContext(const QPaintDevice *pdev) {
444         extern CGContextRef qt_mac_cg_context(const QPaintDevice *);
445         context = qt_mac_cg_context(pdev);
446     }
447     inline QMacCGContext(CGContextRef cg, bool takeOwnership=false) {
448         context = cg;
449         if (!takeOwnership)
450             CGContextRetain(context);
451     }
452     inline QMacCGContext(const QMacCGContext &copy) : context(0) { *this = copy; }
453     inline ~QMacCGContext() {
454         if (context)
455             CGContextRelease(context);
456     }
457     inline bool isNull() const { return context; }
458     inline operator CGContextRef() { return context; }
459     inline QMacCGContext &operator=(const QMacCGContext &copy) {
460         if (context)
461             CGContextRelease(context);
462         context = copy.context;
463         CGContextRetain(context);
464         return *this;
465     }
466     inline QMacCGContext &operator=(CGContextRef cg) {
467         if (context)
468             CGContextRelease(context);
469         context = cg;
470         CGContextRetain(context); //we do not take ownership
471         return *this;
472     }
473 };
474
475 static QColor qcolorFromCGColor(CGColorRef cgcolor)
476 {
477     QColor pc;
478     CGColorSpaceModel model = CGColorSpaceGetModel(CGColorGetColorSpace(cgcolor));
479     const CGFloat *components = CGColorGetComponents(cgcolor);
480     if (model == kCGColorSpaceModelRGB) {
481         pc.setRgbF(components[0], components[1], components[2], components[3]);
482     } else if (model == kCGColorSpaceModelCMYK) {
483         pc.setCmykF(components[0], components[1], components[2], components[3]);
484     } else if (model == kCGColorSpaceModelMonochrome) {
485         pc.setRgbF(components[0], components[0], components[0], components[1]);
486     } else {
487         // Colorspace we can't deal with.
488         qWarning("Qt: qcolorFromCGColor: cannot convert from colorspace model: %d", model);
489         Q_ASSERT(false);
490     }
491     return pc;
492 }
493
494 static inline QColor leopardBrush(ThemeBrush brush)
495 {
496     QCFType<CGColorRef> cgClr = 0;
497     HIThemeBrushCreateCGColor(brush, &cgClr);
498     return qcolorFromCGColor(cgClr);
499 }
500
501 QColor qcolorForTheme(ThemeBrush brush)
502 {
503     return leopardBrush(brush);
504 }
505
506 OSStatus qt_mac_shape2QRegionHelper(int inMessage, HIShapeRef, const CGRect *inRect, void *inRefcon)
507 {
508     QRegion *region = static_cast<QRegion *>(inRefcon);
509     if (!region)
510         return paramErr;
511
512     switch (inMessage) {
513     case kHIShapeEnumerateRect:
514         *region += QRect(inRect->origin.x, inRect->origin.y,
515                          inRect->size.width, inRect->size.height);
516         break;
517     case kHIShapeEnumerateInit:
518         // Assume the region is already setup correctly
519     case kHIShapeEnumerateTerminate:
520     default:
521         break;
522     }
523     return noErr;
524 }
525
526
527 /*!
528     \internal
529      Create's a mutable shape, it's the caller's responsibility to release.
530      WARNING: this function clamps the coordinates to SHRT_MIN/MAX on 10.4 and below.
531 */
532 HIMutableShapeRef qt_mac_toHIMutableShape(const QRegion &region)
533 {
534     HIMutableShapeRef shape = HIShapeCreateMutable();
535     if (region.rectCount() < 2 ) {
536         QRect qtRect = region.boundingRect();
537         CGRect cgRect = CGRectMake(qtRect.x(), qtRect.y(), qtRect.width(), qtRect.height());
538         HIShapeUnionWithRect(shape, &cgRect);
539     } else {
540         foreach (const QRect &qtRect, region.rects()) {
541             CGRect cgRect = CGRectMake(qtRect.x(), qtRect.y(), qtRect.width(), qtRect.height());
542             HIShapeUnionWithRect(shape, &cgRect);
543         }
544     }
545     return shape;
546 }
547
548 QRegion qt_mac_fromHIShapeRef(HIShapeRef shape)
549 {
550     QRegion returnRegion;
551     //returnRegion.detach();
552     HIShapeEnumerate(shape, kHIShapeParseFromTopLeft, qt_mac_shape2QRegionHelper, &returnRegion);
553     return returnRegion;
554 }
555
556 CGColorSpaceRef m_genericColorSpace = 0;
557 QHash<CGDirectDisplayID, CGColorSpaceRef> m_displayColorSpaceHash;
558 bool m_postRoutineRegistered = false;
559
560 CGColorSpaceRef qt_mac_displayColorSpace(const QWidget *widget);
561 CGColorSpaceRef qt_mac_genericColorSpace()
562 {
563 #if 0
564     if (!m_genericColorSpace) {
565 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
566         if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) {
567             m_genericColorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
568         } else
569 #endif
570         {
571             m_genericColorSpace = CGColorSpaceCreateDeviceRGB();
572         }
573         if (!m_postRoutineRegistered) {
574             m_postRoutineRegistered = true;
575             qAddPostRoutine(QCoreGraphicsPaintEngine::cleanUpMacColorSpaces);
576         }
577     }
578     return m_genericColorSpace;
579 #else
580     // Just return the main display colorspace for the moment.
581     return qt_mac_displayColorSpace(0);
582 #endif
583 }
584
585 /*
586     Ideally, we should pass the widget in here, and use CGGetDisplaysWithRect() etc.
587     to support multiple displays correctly.
588 */
589 CGColorSpaceRef qt_mac_displayColorSpace(const QWidget *widget)
590 {
591     CGColorSpaceRef colorSpace;
592
593     CGDirectDisplayID displayID;
594     CMProfileRef displayProfile = 0;
595     if (widget == 0) {
596         displayID = CGMainDisplayID();
597     } else {
598         displayID = CGMainDisplayID();
599         /*
600         ### get correct display
601         const QRect &qrect = widget->window()->geometry();
602         CGRect rect = CGRectMake(qrect.x(), qrect.y(), qrect.width(), qrect.height());
603         CGDisplayCount throwAway;
604         CGDisplayErr dErr = CGGetDisplaysWithRect(rect, 1, &displayID, &throwAway);
605         if (dErr != kCGErrorSuccess)
606             return macDisplayColorSpace(0); // fall back on main display
607         */
608     }
609     if ((colorSpace = m_displayColorSpaceHash.value(displayID)))
610         return colorSpace;
611
612     CMError err = CMGetProfileByAVID((CMDisplayIDType)displayID, &displayProfile);
613     if (err == noErr) {
614         colorSpace = CGColorSpaceCreateWithPlatformColorSpace(displayProfile);
615     } else if (widget) {
616         return qt_mac_displayColorSpace(0); // fall back on main display
617     }
618
619     if (colorSpace == 0)
620         colorSpace = CGColorSpaceCreateDeviceRGB();
621
622     m_displayColorSpaceHash.insert(displayID, colorSpace);
623     CMCloseProfile(displayProfile);
624     if (!m_postRoutineRegistered) {
625         m_postRoutineRegistered = true;
626         void qt_mac_cleanUpMacColorSpaces();
627         qAddPostRoutine(qt_mac_cleanUpMacColorSpaces);
628     }
629     return colorSpace;
630 }
631
632 void qt_mac_cleanUpMacColorSpaces()
633 {
634     if (m_genericColorSpace) {
635         CFRelease(m_genericColorSpace);
636         m_genericColorSpace = 0;
637     }
638     QHash<CGDirectDisplayID, CGColorSpaceRef>::const_iterator it = m_displayColorSpaceHash.constBegin();
639     while (it != m_displayColorSpaceHash.constEnd()) {
640         if (it.value())
641             CFRelease(it.value());
642         ++it;
643     }
644     m_displayColorSpaceHash.clear();
645 }
646
647 bool qt_macWindowIsTextured(const QWidget *window)
648 {
649     NSWindow *nswindow = static_cast<NSWindow*>(
650         QApplication::platformNativeInterface()->nativeResourceForWindow("NSWindow", window->windowHandle()));
651     if (!nswindow)
652         return false;
653     return ([nswindow styleMask] & NSTexturedBackgroundWindowMask) ? true : false;
654 }
655
656 /*****************************************************************************
657   QMacCGStyle globals
658  *****************************************************************************/
659 const int qt_mac_hitheme_version = 0; //the HITheme version we speak
660 const int macItemFrame         = 2;    // menu item frame width
661 const int macItemHMargin       = 3;    // menu item hor text margin
662 const int macItemVMargin       = 2;    // menu item ver text margin
663 const int macRightBorder       = 12;   // right border on mac
664 const ThemeWindowType QtWinType = kThemeDocumentWindow; // Window type we use for QTitleBar.
665 QPixmap *qt_mac_backgroundPattern = 0; // stores the standard widget background.
666
667 /*****************************************************************************
668   QMacCGStyle utility functions
669  *****************************************************************************/
670 static inline int qt_mac_hitheme_tab_version()
671 {
672     return 1;
673 }
674
675 static inline HIRect qt_hirectForQRect(const QRect &convertRect, const QRect &rect = QRect())
676 {
677     return CGRectMake(convertRect.x() + rect.x(), convertRect.y() + rect.y(),
678                       convertRect.width() - rect.width(), convertRect.height() - rect.height());
679 }
680
681 static inline const QRect qt_qrectForHIRect(const HIRect &hirect)
682 {
683     return QRect(QPoint(int(hirect.origin.x), int(hirect.origin.y)),
684                  QSize(int(hirect.size.width), int(hirect.size.height)));
685 }
686
687 inline bool qt_mac_is_metal(const QWidget *w)
688 {
689     for (; w; w = w->parentWidget()) {
690         if (w->testAttribute(Qt::WA_MacBrushedMetal))
691             return true;
692         if (w->isWindow() && w->testAttribute(Qt::WA_WState_Created)) {  // If not created will fall through to the opaque check and be fine anyway.
693             return qt_macWindowIsTextured(w);
694         }
695         if (w->d_func()->isOpaque)
696             break;
697     }
698     return false;
699 }
700
701 static int qt_mac_aqua_get_metric(ThemeMetric met)
702 {
703     SInt32 ret;
704     GetThemeMetric(met, &ret);
705     return ret;
706 }
707
708 static QSize qt_aqua_get_known_size(QStyle::ContentsType ct, const QWidget *widg, QSize szHint,
709                                     QAquaWidgetSize sz)
710 {
711     QSize ret(-1, -1);
712     if (sz != QAquaSizeSmall && sz != QAquaSizeLarge && sz != QAquaSizeMini) {
713         qDebug("Not sure how to return this...");
714         return ret;
715     }
716     if ((widg && widg->testAttribute(Qt::WA_SetFont)) || !QApplication::desktopSettingsAware()) {
717         // If you're using a custom font and it's bigger than the default font,
718         // then no constraints for you. If you are smaller, we can try to help you out
719         QFont font = qt_app_fonts_hash()->value(widg->metaObject()->className(), QFont());
720         if (widg->font().pointSize() > font.pointSize())
721             return ret;
722     }
723
724     if (ct == QStyle::CT_CustomBase && widg) {
725         if (qobject_cast<const QPushButton *>(widg))
726             ct = QStyle::CT_PushButton;
727         else if (qobject_cast<const QRadioButton *>(widg))
728             ct = QStyle::CT_RadioButton;
729         else if (qobject_cast<const QCheckBox *>(widg))
730             ct = QStyle::CT_CheckBox;
731         else if (qobject_cast<const QComboBox *>(widg))
732             ct = QStyle::CT_ComboBox;
733         else if (qobject_cast<const QToolButton *>(widg))
734             ct = QStyle::CT_ToolButton;
735         else if (qobject_cast<const QSlider *>(widg))
736             ct = QStyle::CT_Slider;
737         else if (qobject_cast<const QProgressBar *>(widg))
738             ct = QStyle::CT_ProgressBar;
739         else if (qobject_cast<const QLineEdit *>(widg))
740             ct = QStyle::CT_LineEdit;
741         else if (qobject_cast<const QHeaderView *>(widg))
742             ct = QStyle::CT_HeaderSection;
743         else if (qobject_cast<const QMenuBar *>(widg))
744             ct = QStyle::CT_MenuBar;
745         else if (qobject_cast<const QSizeGrip *>(widg))
746             ct = QStyle::CT_SizeGrip;
747         else
748             return ret;
749     }
750
751     switch (ct) {
752     case QStyle::CT_PushButton: {
753         const QPushButton *psh = qobject_cast<const QPushButton *>(widg);
754         // If this comparison is false, then the widget was not a push button.
755         // This is bad and there's very little we can do since we were requested to find a
756         // sensible size for a widget that pretends to be a QPushButton but is not.
757         if(psh) {
758             QString buttonText = qt_mac_removeMnemonics(psh->text());
759             if (buttonText.contains(QLatin1Char('\n')))
760                 ret = QSize(-1, -1);
761             else if (sz == QAquaSizeLarge)
762                 ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricPushButtonHeight));
763             else if (sz == QAquaSizeSmall)
764                 ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricSmallPushButtonHeight));
765             else if (sz == QAquaSizeMini)
766                 ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricMiniPushButtonHeight));
767
768             if (!psh->icon().isNull()){
769                 // If the button got an icon, and the icon is larger than the
770                 // button, we can't decide on a default size
771                 ret.setWidth(-1);
772                 if (ret.height() < psh->iconSize().height())
773                     ret.setHeight(-1);
774             }
775             else if (buttonText == QLatin1String("OK") || buttonText == QLatin1String("Cancel")){
776                 // Aqua Style guidelines restrict the size of OK and Cancel buttons to 68 pixels.
777                 // However, this doesn't work for German, therefore only do it for English,
778                 // I suppose it would be better to do some sort of lookups for languages
779                 // that like to have really long words.
780                 ret.setWidth(77 - 8);
781             }
782         } else {
783             // The only sensible thing to do is to return whatever the style suggests...
784             if (sz == QAquaSizeLarge)
785                 ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricPushButtonHeight));
786             else if (sz == QAquaSizeSmall)
787                 ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricSmallPushButtonHeight));
788             else if (sz == QAquaSizeMini)
789                 ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricMiniPushButtonHeight));
790             else
791                 // Since there's no default size we return the large size...
792                 ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricPushButtonHeight));
793          }
794 #if 0 //Not sure we are applying the rules correctly for RadioButtons/CheckBoxes --Sam
795     } else if (ct == QStyle::CT_RadioButton) {
796         QRadioButton *rdo = static_cast<QRadioButton *>(widg);
797         // Exception for case where multiline radio button text requires no size constrainment
798         if (rdo->text().find('\n') != -1)
799             return ret;
800         if (sz == QAquaSizeLarge)
801             ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricRadioButtonHeight));
802         else if (sz == QAquaSizeSmall)
803             ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricSmallRadioButtonHeight));
804         else if (sz == QAquaSizeMini)
805             ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricMiniRadioButtonHeight));
806     } else if (ct == QStyle::CT_CheckBox) {
807         if (sz == QAquaSizeLarge)
808             ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricCheckBoxHeight));
809         else if (sz == QAquaSizeSmall)
810             ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricSmallCheckBoxHeight));
811         else if (sz == QAquaSizeMini)
812             ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricMiniCheckBoxHeight));
813 #endif
814         break;
815     }
816     case QStyle::CT_SizeGrip:
817         if (sz == QAquaSizeLarge || sz == QAquaSizeSmall) {
818             HIRect r;
819             HIPoint p = { 0, 0 };
820             HIThemeGrowBoxDrawInfo gbi;
821             gbi.version = 0;
822             gbi.state = kThemeStateActive;
823             gbi.kind = kHIThemeGrowBoxKindNormal;
824             gbi.direction = QApplication::isRightToLeft() ? kThemeGrowLeft | kThemeGrowDown
825                                                           : kThemeGrowRight | kThemeGrowDown;
826             gbi.size = sz == QAquaSizeSmall ? kHIThemeGrowBoxSizeSmall : kHIThemeGrowBoxSizeNormal;
827             if (HIThemeGetGrowBoxBounds(&p, &gbi, &r) == noErr)
828                 ret = QSize(r.size.width, r.size.height);
829         }
830         break;
831     case QStyle::CT_ComboBox:
832         switch (sz) {
833         case QAquaSizeLarge:
834             ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricPopupButtonHeight));
835             break;
836         case QAquaSizeSmall:
837             ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricSmallPopupButtonHeight));
838             break;
839         case QAquaSizeMini:
840             ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricMiniPopupButtonHeight));
841             break;
842         default:
843             break;
844         }
845         break;
846     case QStyle::CT_ToolButton:
847         if (sz == QAquaSizeSmall) {
848             int width = 0, height = 0;
849             if (szHint == QSize(-1, -1)) { //just 'guess'..
850                 const QToolButton *bt = qobject_cast<const QToolButton *>(widg);
851                 // If this conversion fails then the widget was not what it claimed to be.
852                 if(bt) {
853                     if (!bt->icon().isNull()) {
854                         QSize iconSize = bt->iconSize();
855                         QSize pmSize = bt->icon().actualSize(QSize(32, 32), QIcon::Normal);
856                         width = qMax(width, qMax(iconSize.width(), pmSize.width()));
857                         height = qMax(height, qMax(iconSize.height(), pmSize.height()));
858                     }
859                     if (!bt->text().isNull() && bt->toolButtonStyle() != Qt::ToolButtonIconOnly) {
860                         int text_width = bt->fontMetrics().width(bt->text()),
861                            text_height = bt->fontMetrics().height();
862                         if (bt->toolButtonStyle() == Qt::ToolButtonTextUnderIcon) {
863                             width = qMax(width, text_width);
864                             height += text_height;
865                         } else {
866                             width += text_width;
867                             width = qMax(height, text_height);
868                         }
869                     }
870                 } else {
871                     // Let's return the size hint...
872                     width = szHint.width();
873                     height = szHint.height();
874                 }
875             } else {
876                 width = szHint.width();
877                 height = szHint.height();
878             }
879             width =  qMax(20, width +  5); //border
880             height = qMax(20, height + 5); //border
881             ret = QSize(width, height);
882         }
883         break;
884     case QStyle::CT_Slider: {
885         int w = -1;
886         const QSlider *sld = qobject_cast<const QSlider *>(widg);
887         // If this conversion fails then the widget was not what it claimed to be.
888         if(sld) {
889             if (sz == QAquaSizeLarge) {
890                 if (sld->orientation() == Qt::Horizontal) {
891                     w = qt_mac_aqua_get_metric(kThemeMetricHSliderHeight);
892                     if (sld->tickPosition() != QSlider::NoTicks)
893                         w += qt_mac_aqua_get_metric(kThemeMetricHSliderTickHeight);
894                 } else {
895                     w = qt_mac_aqua_get_metric(kThemeMetricVSliderWidth);
896                     if (sld->tickPosition() != QSlider::NoTicks)
897                         w += qt_mac_aqua_get_metric(kThemeMetricVSliderTickWidth);
898                 }
899             } else if (sz == QAquaSizeSmall) {
900                 if (sld->orientation() == Qt::Horizontal) {
901                     w = qt_mac_aqua_get_metric(kThemeMetricSmallHSliderHeight);
902                     if (sld->tickPosition() != QSlider::NoTicks)
903                         w += qt_mac_aqua_get_metric(kThemeMetricSmallHSliderTickHeight);
904                 } else {
905                     w = qt_mac_aqua_get_metric(kThemeMetricSmallVSliderWidth);
906                     if (sld->tickPosition() != QSlider::NoTicks)
907                         w += qt_mac_aqua_get_metric(kThemeMetricSmallVSliderTickWidth);
908                 }
909             } else if (sz == QAquaSizeMini) {
910                 if (sld->orientation() == Qt::Horizontal) {
911                     w = qt_mac_aqua_get_metric(kThemeMetricMiniHSliderHeight);
912                     if (sld->tickPosition() != QSlider::NoTicks)
913                         w += qt_mac_aqua_get_metric(kThemeMetricMiniHSliderTickHeight);
914                 } else {
915                     w = qt_mac_aqua_get_metric(kThemeMetricMiniVSliderWidth);
916                     if (sld->tickPosition() != QSlider::NoTicks)
917                         w += qt_mac_aqua_get_metric(kThemeMetricMiniVSliderTickWidth);
918                 }
919             }
920         } else {
921             // This is tricky, we were requested to find a size for a slider which is not
922             // a slider. We don't know if this is vertical or horizontal or if we need to
923             // have tick marks or not.
924             // For this case we will return an horizontal slider without tick marks.
925             w = qt_mac_aqua_get_metric(kThemeMetricHSliderHeight);
926             w += qt_mac_aqua_get_metric(kThemeMetricHSliderTickHeight);
927         }
928         if (sld->orientation() == Qt::Horizontal)
929             ret.setHeight(w);
930         else
931             ret.setWidth(w);
932         break;
933     }
934     case QStyle::CT_ProgressBar: {
935         int finalValue = -1;
936         Qt::Orientation orient = Qt::Horizontal;
937         if (const QProgressBar *pb = qobject_cast<const QProgressBar *>(widg))
938             orient = pb->orientation();
939
940         if (sz == QAquaSizeLarge)
941             finalValue = qt_mac_aqua_get_metric(kThemeMetricLargeProgressBarThickness)
942                             + qt_mac_aqua_get_metric(kThemeMetricProgressBarShadowOutset);
943         else
944             finalValue = qt_mac_aqua_get_metric(kThemeMetricNormalProgressBarThickness)
945                             + qt_mac_aqua_get_metric(kThemeMetricSmallProgressBarShadowOutset);
946         if (orient == Qt::Horizontal)
947             ret.setHeight(finalValue);
948         else
949             ret.setWidth(finalValue);
950         break;
951     }
952     case QStyle::CT_LineEdit:
953         if (!widg || !qobject_cast<QComboBox *>(widg->parentWidget())) {
954             //should I take into account the font dimentions of the lineedit? -Sam
955             if (sz == QAquaSizeLarge)
956                 ret = QSize(-1, 22);
957             else
958                 ret = QSize(-1, 19);
959         }
960         break;
961     case QStyle::CT_HeaderSection:
962         if (isTreeView(widg))
963            ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricListHeaderHeight));
964         break;
965     case QStyle::CT_MenuBar:
966         if (sz == QAquaSizeLarge) {
967             ret = QSize(-1, [[NSApp mainMenu] menuBarHeight]);
968             // In the qt_mac_set_native_menubar(false) case,
969             // we come it here with a zero-height main menu,
970             // preventing the in-window menu from displaying.
971             // Use 22 pixels for the height, by observation.
972             if (ret.height() <= 0)
973                 ret.setHeight(22);
974         }
975         break;
976     default:
977         break;
978     }
979     return ret;
980 }
981
982
983 #if defined(QMAC_QAQUASTYLE_SIZE_CONSTRAIN) || defined(DEBUG_SIZE_CONSTRAINT)
984 static QAquaWidgetSize qt_aqua_guess_size(const QWidget *widg, QSize large, QSize small, QSize mini)
985 {
986     if (large == QSize(-1, -1)) {
987         if (small != QSize(-1, -1))
988             return QAquaSizeSmall;
989         if (mini != QSize(-1, -1))
990             return QAquaSizeMini;
991         return QAquaSizeUnknown;
992     } else if (small == QSize(-1, -1)) {
993         if (mini != QSize(-1, -1))
994             return QAquaSizeMini;
995         return QAquaSizeLarge;
996     } else if (mini == QSize(-1, -1)) {
997         return QAquaSizeLarge;
998     }
999
1000 #ifndef QT_NO_MAINWINDOW
1001     if (qobject_cast<QDockWidget *>(widg->window()) || !qgetenv("QWIDGET_ALL_SMALL").isNull()) {
1002         //if (small.width() != -1 || small.height() != -1)
1003         return QAquaSizeSmall;
1004     } else if (!qgetenv("QWIDGET_ALL_MINI").isNull()) {
1005         return QAquaSizeMini;
1006     }
1007 #endif
1008
1009 #if 0
1010     /* Figure out which size we're closer to, I just hacked this in, I haven't
1011        tested it as it would probably look pretty strange to have some widgets
1012        big and some widgets small in the same window?? -Sam */
1013     int large_delta=0;
1014     if (large.width() != -1) {
1015         int delta = large.width() - widg->width();
1016         large_delta += delta * delta;
1017     }
1018     if (large.height() != -1) {
1019         int delta = large.height() - widg->height();
1020         large_delta += delta * delta;
1021     }
1022     int small_delta=0;
1023     if (small.width() != -1) {
1024         int delta = small.width() - widg->width();
1025         small_delta += delta * delta;
1026     }
1027     if (small.height() != -1) {
1028         int delta = small.height() - widg->height();
1029         small_delta += delta * delta;
1030     }
1031     int mini_delta=0;
1032     if (mini.width() != -1) {
1033         int delta = mini.width() - widg->width();
1034         mini_delta += delta * delta;
1035     }
1036     if (mini.height() != -1) {
1037         int delta = mini.height() - widg->height();
1038         mini_delta += delta * delta;
1039     }
1040     if (mini_delta < small_delta && mini_delta < large_delta)
1041         return QAquaSizeMini;
1042     else if (small_delta < large_delta)
1043         return QAquaSizeSmall;
1044 #endif
1045     return QAquaSizeLarge;
1046 }
1047 #endif
1048
1049 QAquaWidgetSize QMacStylePrivate::aquaSizeConstrain(const QStyleOption *option, const QWidget *widg,
1050                                        QStyle::ContentsType ct, QSize szHint, QSize *insz) const
1051 {
1052 #if defined(QMAC_QAQUASTYLE_SIZE_CONSTRAIN) || defined(DEBUG_SIZE_CONSTRAINT)
1053     if (option) {
1054         if (option->state & QStyle::State_Small)
1055             return QAquaSizeSmall;
1056         if (option->state & QStyle::State_Mini)
1057             return QAquaSizeMini;
1058     }
1059
1060     if (!widg) {
1061         if (insz)
1062             *insz = QSize();
1063         if (!qgetenv("QWIDGET_ALL_SMALL").isNull())
1064             return QAquaSizeSmall;
1065         if (!qgetenv("QWIDGET_ALL_MINI").isNull())
1066             return QAquaSizeMini;
1067         return QAquaSizeUnknown;
1068     }
1069     QSize large = qt_aqua_get_known_size(ct, widg, szHint, QAquaSizeLarge),
1070           small = qt_aqua_get_known_size(ct, widg, szHint, QAquaSizeSmall),
1071           mini  = qt_aqua_get_known_size(ct, widg, szHint, QAquaSizeMini);
1072     bool guess_size = false;
1073     QAquaWidgetSize ret = QAquaSizeUnknown;
1074     QMacStyle::WidgetSizePolicy wsp = q->widgetSizePolicy(widg);
1075     if (wsp == QMacStyle::SizeDefault)
1076         guess_size = true;
1077     else if (wsp == QMacStyle::SizeMini)
1078         ret = QAquaSizeMini;
1079     else if (wsp == QMacStyle::SizeSmall)
1080         ret = QAquaSizeSmall;
1081     else if (wsp == QMacStyle::SizeLarge)
1082         ret = QAquaSizeLarge;
1083     if (guess_size)
1084         ret = qt_aqua_guess_size(widg, large, small, mini);
1085
1086     QSize *sz = 0;
1087     if (ret == QAquaSizeSmall)
1088         sz = &small;
1089     else if (ret == QAquaSizeLarge)
1090         sz = &large;
1091     else if (ret == QAquaSizeMini)
1092         sz = &mini;
1093     if (insz)
1094         *insz = sz ? *sz : QSize(-1, -1);
1095 #ifdef DEBUG_SIZE_CONSTRAINT
1096     if (sz) {
1097         const char *size_desc = "Unknown";
1098         if (sz == &small)
1099             size_desc = "Small";
1100         else if (sz == &large)
1101             size_desc = "Large";
1102         else if (sz == &mini)
1103             size_desc = "Mini";
1104         qDebug("%s - %s: %s taken (%d, %d) [%d, %d]",
1105                widg ? widg->objectName().toLatin1().constData() : "*Unknown*",
1106                widg ? widg->metaObject()->className() : "*Unknown*", size_desc, widg->width(), widg->height(),
1107                sz->width(), sz->height());
1108     }
1109 #endif
1110     return ret;
1111 #else
1112     if (insz)
1113         *insz = QSize();
1114     Q_UNUSED(widg);
1115     Q_UNUSED(ct);
1116     Q_UNUSED(szHint);
1117     return QAquaSizeUnknown;
1118 #endif
1119 }
1120
1121 /**
1122     Returns the free space awailable for contents inside the
1123     button (and not the size of the contents itself)
1124 */
1125 HIRect QMacStylePrivate::pushButtonContentBounds(const QStyleOptionButton *btn,
1126                                                  const HIThemeButtonDrawInfo *bdi) const
1127 {
1128     HIRect outerBounds = qt_hirectForQRect(btn->rect);
1129     // Adjust the bounds to correct for
1130     // carbon not calculating the content bounds fully correct
1131     if (bdi->kind == kThemePushButton || bdi->kind == kThemePushButtonSmall){
1132         outerBounds.origin.y += QMacStylePrivate::PushButtonTopOffset;
1133         outerBounds.size.height -= QMacStylePrivate::PushButtonBottomOffset;
1134     } else if (bdi->kind == kThemePushButtonMini) {
1135         outerBounds.origin.y += QMacStylePrivate::PushButtonTopOffset;
1136     }
1137
1138     HIRect contentBounds;
1139     HIThemeGetButtonContentBounds(&outerBounds, bdi, &contentBounds);
1140     return contentBounds;
1141 }
1142
1143 /**
1144     Calculates the size of the button contents.
1145     This includes both the text and the icon.
1146 */
1147 QSize QMacStylePrivate::pushButtonSizeFromContents(const QStyleOptionButton *btn) const
1148 {
1149     QSize csz(0, 0);
1150     QSize iconSize = btn->icon.isNull() ? QSize(0, 0)
1151                 : (btn->iconSize + QSize(QMacStylePrivate::PushButtonContentPadding, 0));
1152     QRect textRect = btn->text.isEmpty() ? QRect(0, 0, 1, 1)
1153                 : btn->fontMetrics.boundingRect(QRect(), Qt::AlignCenter, btn->text);
1154     csz.setWidth(iconSize.width() + textRect.width()
1155              + ((btn->features & QStyleOptionButton::HasMenu)
1156                             ? q->proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator, btn, 0) : 0));
1157     csz.setHeight(qMax(iconSize.height(), textRect.height()));
1158     return csz;
1159 }
1160
1161 /**
1162     Checks if the actual contents of btn fits inside the free content bounds of
1163     'buttonKindToCheck'. Meant as a helper function for 'initHIThemePushButton'
1164     for determining which button kind to use for drawing.
1165 */
1166 bool QMacStylePrivate::contentFitsInPushButton(const QStyleOptionButton *btn,
1167                                                HIThemeButtonDrawInfo *bdi,
1168                                                ThemeButtonKind buttonKindToCheck) const
1169 {
1170     ThemeButtonKind tmp = bdi->kind;
1171     bdi->kind = buttonKindToCheck;
1172     QSize contentSize = pushButtonSizeFromContents(btn);
1173     QRect freeContentRect = qt_qrectForHIRect(pushButtonContentBounds(btn, bdi));
1174     bdi->kind = tmp;
1175     return freeContentRect.contains(QRect(freeContentRect.x(), freeContentRect.y(),
1176                                     contentSize.width(), contentSize.height()));
1177 }
1178
1179 /**
1180     Creates a HIThemeButtonDrawInfo structure that specifies the correct button
1181     kind and other details to use for drawing the given push button. Which
1182     button kind depends on the size of the button, the size of the contents,
1183     explicit user style settings, etc.
1184 */
1185 void QMacStylePrivate::initHIThemePushButton(const QStyleOptionButton *btn,
1186                                              const QWidget *widget,
1187                                              const ThemeDrawState tds,
1188                                              HIThemeButtonDrawInfo *bdi) const
1189 {
1190     bool drawColorless = btn->palette.currentColorGroup() == QPalette::Active;
1191     ThemeDrawState tdsModified = tds;
1192     if (btn->state & QStyle::State_On)
1193         tdsModified = kThemeStatePressed;
1194     bdi->version = qt_mac_hitheme_version;
1195     bdi->state = tdsModified;
1196     bdi->value = kThemeButtonOff;
1197
1198     if (drawColorless && tdsModified == kThemeStateInactive)
1199         bdi->state = kThemeStateActive;
1200     if (btn->state & QStyle::State_HasFocus)
1201         bdi->adornment = kThemeAdornmentFocus;
1202     else
1203         bdi->adornment = kThemeAdornmentNone;
1204
1205
1206     if (btn->features & (QStyleOptionButton::Flat)) {
1207         bdi->kind = kThemeBevelButton;
1208     } else {
1209         switch (aquaSizeConstrain(btn, widget)) {
1210         case QAquaSizeSmall:
1211             bdi->kind = kThemePushButtonSmall;
1212             break;
1213         case QAquaSizeMini:
1214             bdi->kind = kThemePushButtonMini;
1215             break;
1216         case QAquaSizeLarge:
1217             // ... We should honor if the user is explicit about using the
1218             // large button. But right now Qt will specify the large button
1219             // as default rather than QAquaSizeUnknown.
1220             // So we treat it like QAquaSizeUnknown
1221             // to get the dynamic choosing of button kind.
1222         case QAquaSizeUnknown:
1223             // Choose the button kind that closest match the button rect, but at the
1224             // same time displays the button contents without clipping.
1225             bdi->kind = kThemeBevelButton;
1226             if (btn->rect.width() >= QMacStylePrivate::BevelButtonW && btn->rect.height() >= QMacStylePrivate::BevelButtonH){
1227                 if (widget && widget->testAttribute(Qt::WA_MacVariableSize)) {
1228                     if (btn->rect.height() <= QMacStylePrivate::MiniButtonH){
1229                         if (contentFitsInPushButton(btn, bdi, kThemePushButtonMini))
1230                             bdi->kind = kThemePushButtonMini;
1231                     } else if (btn->rect.height() <= QMacStylePrivate::SmallButtonH){
1232                         if (contentFitsInPushButton(btn, bdi, kThemePushButtonSmall))
1233                             bdi->kind = kThemePushButtonSmall;
1234                     } else if (contentFitsInPushButton(btn, bdi, kThemePushButton)) {
1235                         bdi->kind = kThemePushButton;
1236                     }
1237                 } else {
1238                     bdi->kind = kThemePushButton;
1239                 }
1240             }
1241         }
1242     }
1243 }
1244
1245 bool qt_mac_buttonIsRenderedFlat(const QPushButton *pushButton, const QStyleOptionButton *option)
1246 {
1247     QMacStyle *macStyle = qobject_cast<QMacStyle *>(pushButton->style());
1248     if (!macStyle)
1249         return false;
1250     HIThemeButtonDrawInfo bdi;
1251     macStyle->d->initHIThemePushButton(option, pushButton, kThemeStateActive, &bdi);
1252     return bdi.kind == kThemeBevelButton;
1253 }
1254
1255 /**
1256     Creates a HIThemeButtonDrawInfo structure that specifies the correct button
1257     kind and other details to use for drawing the given combobox. Which button
1258     kind depends on the size of the combo, wether or not it is editable,
1259     explicit user style settings, etc.
1260 */
1261 void QMacStylePrivate::initComboboxBdi(const QStyleOptionComboBox *combo, HIThemeButtonDrawInfo *bdi,
1262                                     const QWidget *widget, const ThemeDrawState &tds)
1263 {
1264     bdi->version = qt_mac_hitheme_version;
1265     bdi->adornment = kThemeAdornmentArrowLeftArrow;
1266     bdi->value = kThemeButtonOff;
1267     if (combo->state & QStyle::State_HasFocus)
1268         bdi->adornment = kThemeAdornmentFocus;
1269     bool drawColorless = combo->palette.currentColorGroup() == QPalette::Active && tds == kThemeStateInactive;
1270     if (combo->activeSubControls & QStyle::SC_ComboBoxArrow)
1271         bdi->state = kThemeStatePressed;
1272     else if (drawColorless)
1273         bdi->state = kThemeStateActive;
1274     else
1275         bdi->state = tds;
1276
1277     QAquaWidgetSize aSize = aquaSizeConstrain(combo, widget);
1278     switch (aSize) {
1279     case QAquaSizeMini:
1280         bdi->kind = combo->editable ? ThemeButtonKind(kThemeComboBoxMini)
1281             : ThemeButtonKind(kThemePopupButtonMini);
1282         break;
1283     case QAquaSizeSmall:
1284         bdi->kind = combo->editable ? ThemeButtonKind(kThemeComboBoxSmall)
1285             : ThemeButtonKind(kThemePopupButtonSmall);
1286         break;
1287     case QAquaSizeUnknown:
1288     case QAquaSizeLarge:
1289         // Unless the user explicitly specified large buttons, determine the
1290         // kind by looking at the combox size.
1291         // ... specifying small and mini-buttons it not a current feature of
1292         // Qt (e.g. QWidget::getAttribute(WA_ButtonSize)). But when it is, add
1293         // an extra check here before using the mini and small buttons.
1294         int h = combo->rect.size().height();
1295         if (combo->editable){
1296             if (h < 21)
1297                 bdi->kind = kThemeComboBoxMini;
1298             else if (h < 26)
1299                 bdi->kind = kThemeComboBoxSmall;
1300             else
1301                 bdi->kind = kThemeComboBox;
1302         } else {
1303             // Even if we specify that we want the kThemePopupButton, Carbon
1304             // will use the kThemePopupButtonSmall if the size matches. So we
1305             // do the same size check explicit to have the size of the inner
1306             // text field be correct. Therefore, do this even if the user specifies
1307             // the use of LargeButtons explicit.
1308             if (h < 21)
1309                 bdi->kind = kThemePopupButtonMini;
1310             else if (h < 26)
1311                 bdi->kind = kThemePopupButtonSmall;
1312             else
1313                 bdi->kind = kThemePopupButton;
1314         }
1315         break;
1316     }
1317 }
1318
1319 /**
1320     Carbon draws comboboxes (and other views) outside the rect given as argument. Use this function to obtain
1321     the corresponding inner rect for drawing the same combobox so that it stays inside the given outerBounds.
1322 */
1323 HIRect QMacStylePrivate::comboboxInnerBounds(const HIRect &outerBounds, int buttonKind)
1324 {
1325     HIRect innerBounds = outerBounds;
1326     // Carbon draw parts of the view outside the rect.
1327     // So make the rect a bit smaller to compensate
1328     // (I wish HIThemeGetButtonBackgroundBounds worked)
1329     switch (buttonKind){
1330     case kThemePopupButton:
1331         innerBounds.origin.x += 2;
1332         innerBounds.origin.y += 3;
1333         innerBounds.size.width -= 5;
1334         innerBounds.size.height -= 6;
1335         break;
1336     case kThemePopupButtonSmall:
1337         innerBounds.origin.x += 3;
1338         innerBounds.origin.y += 3;
1339         innerBounds.size.width -= 6;
1340         innerBounds.size.height -= 7;
1341         break;
1342     case kThemePopupButtonMini:
1343         innerBounds.origin.x += 2;
1344         innerBounds.origin.y += 2;
1345         innerBounds.size.width -= 5;
1346         innerBounds.size.height -= 6;
1347         break;
1348     case kThemeComboBox:
1349         innerBounds.origin.x += 3;
1350         innerBounds.origin.y += 3;
1351         innerBounds.size.width -= 6;
1352         innerBounds.size.height -= 6;
1353         break;
1354     case kThemeComboBoxSmall:
1355         innerBounds.origin.x += 3;
1356         innerBounds.origin.y += 3;
1357         innerBounds.size.width -= 7;
1358         innerBounds.size.height -= 8;
1359         break;
1360     case kThemeComboBoxMini:
1361         innerBounds.origin.x += 3;
1362         innerBounds.origin.y += 3;
1363         innerBounds.size.width -= 4;
1364         innerBounds.size.height -= 8;
1365         break;
1366     default:
1367         break;
1368     }
1369     return innerBounds;
1370 }
1371
1372 /**
1373     Inside a combobox Qt places a line edit widget. The size of this widget should depend on the kind
1374     of combobox we choose to draw. This function calculates and returns this size.
1375 */
1376 QRect QMacStylePrivate::comboboxEditBounds(const QRect &outerBounds, const HIThemeButtonDrawInfo &bdi)
1377 {
1378     QRect ret = outerBounds;
1379     switch (bdi.kind){
1380     case kThemeComboBox:
1381         ret.adjust(5, 8, -21, -4);
1382         break;
1383     case kThemeComboBoxSmall:
1384         ret.adjust(4, 5, -18, 0);
1385         ret.setHeight(16);
1386         break;
1387     case kThemeComboBoxMini:
1388         ret.adjust(4, 5, -16, 0);
1389         ret.setHeight(13);
1390         break;
1391     case kThemePopupButton:
1392         ret.adjust(10, 3, -23, -3);
1393         break;
1394     case kThemePopupButtonSmall:
1395         ret.adjust(9, 3, -20, -3);
1396         break;
1397     case kThemePopupButtonMini:
1398         ret.adjust(8, 3, -19, 0);
1399         ret.setHeight(13);
1400         break;
1401     }
1402     return ret;
1403 }
1404
1405 /**
1406     Carbon comboboxes don't scale (sight). If the size of the combo suggest a scaled version,
1407     create it manually by drawing a small Carbon combo onto a pixmap (use pixmap cache), chop
1408     it up, and copy it back onto the widget. Othervise, draw the combobox supplied by Carbon directly.
1409 */
1410 void QMacStylePrivate::drawCombobox(const HIRect &outerBounds, const HIThemeButtonDrawInfo &bdi, QPainter *p)
1411 {
1412     if (!(bdi.kind == kThemeComboBox && outerBounds.size.height > 28)){
1413         // We have an unscaled combobox, or popup-button; use Carbon directly.
1414         HIRect innerBounds = QMacStylePrivate::comboboxInnerBounds(outerBounds, bdi.kind);
1415         HIThemeDrawButton(&innerBounds, &bdi, QMacCGContext(p), kHIThemeOrientationNormal, 0);
1416     } else {
1417         QPixmap buffer;
1418         QString key = QString(QLatin1String("$qt_cbox%1-%2")).arg(int(bdi.state)).arg(int(bdi.adornment));
1419         if (!QPixmapCache::find(key, buffer)) {
1420             HIRect innerBoundsSmallCombo = {{3, 3}, {29, 25}};
1421             buffer = QPixmap(35, 28);
1422             buffer.fill(Qt::transparent);
1423             QPainter buffPainter(&buffer);
1424             HIThemeDrawButton(&innerBoundsSmallCombo, &bdi, QMacCGContext(&buffPainter), kHIThemeOrientationNormal, 0);
1425             buffPainter.end();
1426             QPixmapCache::insert(key, buffer);
1427         }
1428
1429         const int bwidth = 20;
1430         const int fwidth = 10;
1431         const int fheight = 10;
1432         int w = qRound(outerBounds.size.width);
1433         int h = qRound(outerBounds.size.height);
1434         int bstart = w - bwidth;
1435         int blower = fheight + 1;
1436         int flower = h - fheight;
1437         int sheight = flower - fheight;
1438         int center = qRound(outerBounds.size.height + outerBounds.origin.y) / 2;
1439
1440         // Draw upper and lower gap
1441         p->drawPixmap(fwidth, 0, bstart - fwidth, fheight, buffer, fwidth, 0, 1, fheight);
1442         p->drawPixmap(fwidth, flower, bstart - fwidth, fheight, buffer, fwidth, buffer.height() - fheight, 1, fheight);
1443         // Draw left and right gap. Right gap is drawn top and bottom separatly
1444         p->drawPixmap(0, fheight, fwidth, sheight, buffer, 0, fheight, fwidth, 1);
1445         p->drawPixmap(bstart, fheight, bwidth, center - fheight, buffer, buffer.width() - bwidth, fheight - 1, bwidth, 1);
1446         p->drawPixmap(bstart, center, bwidth, sheight / 2, buffer, buffer.width() - bwidth, fheight + 6, bwidth, 1);
1447         // Draw arrow
1448         p->drawPixmap(bstart, center - 4, bwidth - 3, 6, buffer, buffer.width() - bwidth, fheight, bwidth - 3, 6);
1449         // Draw corners
1450         p->drawPixmap(0, 0, fwidth, fheight, buffer, 0, 0, fwidth, fheight);
1451         p->drawPixmap(bstart, 0, bwidth, fheight, buffer, buffer.width() - bwidth, 0, bwidth, fheight);
1452         p->drawPixmap(0, flower, fwidth, fheight, buffer, 0, buffer.height() - fheight, fwidth, fheight);
1453         p->drawPixmap(bstart, h - blower, bwidth, blower, buffer, buffer.width() - bwidth, buffer.height() - blower, bwidth, blower);
1454     }
1455 }
1456
1457 /**
1458     Carbon tableheaders don't scale (sight). So create it manually by drawing a small Carbon header
1459     onto a pixmap (use pixmap cache), chop it up, and copy it back onto the widget.
1460 */
1461 void QMacStylePrivate::drawTableHeader(const HIRect &outerBounds,
1462     bool drawTopBorder, bool drawLeftBorder, const HIThemeButtonDrawInfo &bdi, QPainter *p)
1463 {
1464     static SInt32 headerHeight = 0;
1465     static OSStatus err = GetThemeMetric(kThemeMetricListHeaderHeight, &headerHeight);
1466     Q_UNUSED(err);
1467
1468     QPixmap buffer;
1469     QString key = QString(QLatin1String("$qt_tableh%1-%2-%3")).arg(int(bdi.state)).arg(int(bdi.adornment)).arg(int(bdi.value));
1470     if (!QPixmapCache::find(key, buffer)) {
1471         HIRect headerNormalRect = {{0., 0.}, {16., CGFloat(headerHeight)}};
1472         buffer = QPixmap(headerNormalRect.size.width, headerNormalRect.size.height);
1473         buffer.fill(Qt::transparent);
1474         QPainter buffPainter(&buffer);
1475         HIThemeDrawButton(&headerNormalRect, &bdi, QMacCGContext(&buffPainter), kHIThemeOrientationNormal, 0);
1476         buffPainter.end();
1477         QPixmapCache::insert(key, buffer);
1478     }
1479     const int buttonw = qRound(outerBounds.size.width);
1480     const int buttonh = qRound(outerBounds.size.height);
1481     const int framew = 1;
1482     const int frameh_n = 4;
1483     const int frameh_s = 3;
1484     const int transh = buffer.height() - frameh_n - frameh_s;
1485     int center = buttonh - frameh_s - int(transh / 2.0f) + 1; // Align bottom;
1486
1487     int skipTopBorder = 0;
1488     if (!drawTopBorder)
1489         skipTopBorder = 1;
1490
1491     p->translate(outerBounds.origin.x, outerBounds.origin.y);
1492
1493     p->drawPixmap(QRect(QRect(0, -skipTopBorder, buttonw - framew , frameh_n)), buffer, QRect(framew, 0, 1, frameh_n));
1494     p->drawPixmap(QRect(0, buttonh - frameh_s, buttonw - framew, frameh_s), buffer, QRect(framew, buffer.height() - frameh_s, 1, frameh_s));
1495     // Draw upper and lower center blocks
1496     p->drawPixmap(QRect(0, frameh_n - skipTopBorder, buttonw - framew, center - frameh_n + skipTopBorder), buffer, QRect(framew, frameh_n, 1, 1));
1497     p->drawPixmap(QRect(0, center, buttonw - framew, buttonh - center - frameh_s), buffer, QRect(framew, buffer.height() - frameh_s, 1, 1));
1498     // Draw right center block borders
1499     p->drawPixmap(QRect(buttonw - framew, frameh_n - skipTopBorder, framew, center - frameh_n), buffer, QRect(buffer.width() - framew, frameh_n, framew, 1));
1500     p->drawPixmap(QRect(buttonw - framew, center, framew, buttonh - center - 1), buffer, QRect(buffer.width() - framew, buffer.height() - frameh_s, framew, 1));
1501     // Draw right corners
1502     p->drawPixmap(QRect(buttonw - framew, -skipTopBorder, framew, frameh_n), buffer, QRect(buffer.width() - framew, 0, framew, frameh_n));
1503     p->drawPixmap(QRect(buttonw - framew, buttonh - frameh_s, framew, frameh_s), buffer, QRect(buffer.width() - framew, buffer.height() - frameh_s, framew, frameh_s));
1504     // Draw center transition block
1505     p->drawPixmap(QRect(0, center - qRound(transh / 2.0f), buttonw - framew, buffer.height() - frameh_n - frameh_s), buffer, QRect(framew, frameh_n + 1, 1, transh));
1506     // Draw right center transition block border
1507     p->drawPixmap(QRect(buttonw - framew, center - qRound(transh / 2.0f), framew, buffer.height() - frameh_n - frameh_s), buffer, QRect(buffer.width() - framew, frameh_n + 1, framew, transh));
1508     if (drawLeftBorder){
1509         // Draw left center block borders
1510         p->drawPixmap(QRect(0, frameh_n - skipTopBorder, framew, center - frameh_n + skipTopBorder), buffer, QRect(0, frameh_n, framew, 1));
1511         p->drawPixmap(QRect(0, center, framew, buttonh - center - 1), buffer, QRect(0, buffer.height() - frameh_s, framew, 1));
1512         // Draw left corners
1513         p->drawPixmap(QRect(0, -skipTopBorder, framew, frameh_n), buffer, QRect(0, 0, framew, frameh_n));
1514         p->drawPixmap(QRect(0, buttonh - frameh_s, framew, frameh_s), buffer, QRect(0, buffer.height() - frameh_s, framew, frameh_s));
1515         // Draw left center transition block border
1516         p->drawPixmap(QRect(0, center - qRound(transh / 2.0f), framew, buffer.height() - frameh_n - frameh_s), buffer, QRect(0, frameh_n + 1, framew, transh));
1517     }
1518
1519     p->translate(-outerBounds.origin.x, -outerBounds.origin.y);
1520 }
1521
1522 /*
1523     Returns cutoff sizes for scroll bars.
1524     thumbIndicatorCutoff is the smallest size where the thumb indicator is drawn.
1525     scrollButtonsCutoff is the smallest size where the up/down buttons is drawn.
1526 */
1527 enum ScrollBarCutoffType { thumbIndicatorCutoff = 0, scrollButtonsCutoff = 1 };
1528 static int scrollButtonsCutoffSize(ScrollBarCutoffType cutoffType, QMacStyle::WidgetSizePolicy widgetSize)
1529 {
1530     // Mini scroll bars do not exist as of version 10.4.
1531     if (widgetSize ==  QMacStyle::SizeMini)
1532         return 0;
1533
1534     const int sizeIndex = (widgetSize == QMacStyle::SizeSmall) ? 1 : 0;
1535     static const int sizeTable[2][2] = { { 61, 56 }, { 49, 44 } };
1536     return sizeTable[sizeIndex][cutoffType];
1537 }
1538
1539 void QMacStylePrivate::getSliderInfo(QStyle::ComplexControl cc, const QStyleOptionSlider *slider,
1540                           HIThemeTrackDrawInfo *tdi, const QWidget *needToRemoveMe)
1541 {
1542     memset(tdi, 0, sizeof(HIThemeTrackDrawInfo)); // We don't get it all for some reason or another...
1543     tdi->version = qt_mac_hitheme_version;
1544     tdi->reserved = 0;
1545     tdi->filler1 = 0;
1546     bool isScrollbar = (cc == QStyle::CC_ScrollBar);
1547     switch (aquaSizeConstrain(0, needToRemoveMe)) {
1548     case QAquaSizeUnknown:
1549     case QAquaSizeLarge:
1550         if (isScrollbar)
1551             tdi->kind = kThemeMediumScrollBar;
1552         else
1553             tdi->kind = kThemeMediumSlider;
1554         break;
1555     case QAquaSizeMini:
1556         if (isScrollbar)
1557             tdi->kind = kThemeSmallScrollBar; // should be kThemeMiniScrollBar, but not implemented
1558         else
1559             tdi->kind = kThemeMiniSlider;
1560         break;
1561     case QAquaSizeSmall:
1562         if (isScrollbar)
1563             tdi->kind = kThemeSmallScrollBar;
1564         else
1565             tdi->kind = kThemeSmallSlider;
1566         break;
1567     }
1568     tdi->bounds = qt_hirectForQRect(slider->rect);
1569     tdi->min = slider->minimum;
1570     tdi->max = slider->maximum;
1571     tdi->value = slider->sliderPosition;
1572     tdi->attributes = kThemeTrackShowThumb;
1573     if (slider->upsideDown)
1574         tdi->attributes |= kThemeTrackRightToLeft;
1575     if (slider->orientation == Qt::Horizontal) {
1576         tdi->attributes |= kThemeTrackHorizontal;
1577         if (isScrollbar && slider->direction == Qt::RightToLeft) {
1578             if (!slider->upsideDown)
1579                 tdi->attributes |= kThemeTrackRightToLeft;
1580             else
1581                 tdi->attributes &= ~kThemeTrackRightToLeft;
1582         }
1583     }
1584
1585     // Tiger broke reverse scroll bars so put them back and "fake it"
1586     if (isScrollbar && (tdi->attributes & kThemeTrackRightToLeft)) {
1587         tdi->attributes &= ~kThemeTrackRightToLeft;
1588         tdi->value = tdi->max - slider->sliderPosition;
1589     }
1590
1591     tdi->enableState = (slider->state & QStyle::State_Enabled) ? kThemeTrackActive
1592                                                              : kThemeTrackDisabled;
1593     if (!(slider->state & QStyle::State_Active))
1594         tdi->enableState = kThemeTrackInactive;
1595     if (!isScrollbar) {
1596         if (slider->state & QStyle::QStyle::State_HasFocus)
1597             tdi->attributes |= kThemeTrackHasFocus;
1598         if (slider->tickPosition == QSlider::NoTicks || slider->tickPosition == QSlider::TicksBothSides)
1599             tdi->trackInfo.slider.thumbDir = kThemeThumbPlain;
1600         else if (slider->tickPosition == QSlider::TicksAbove)
1601             tdi->trackInfo.slider.thumbDir = kThemeThumbUpward;
1602         else
1603             tdi->trackInfo.slider.thumbDir = kThemeThumbDownward;
1604     } else {
1605         tdi->trackInfo.scrollbar.viewsize = slider->pageStep;
1606     }
1607 }
1608
1609 QMacStylePrivate::QMacStylePrivate(QMacStyle *style)
1610     : timerID(-1), progressFrame(0), q(style), mouseDown(false)
1611 {
1612     defaultButtonStart = CFAbsoluteTimeGetCurrent();
1613     memset(&buttonState, 0, sizeof(ButtonState));
1614
1615     if (ptrHIShapeGetBounds == 0) {
1616         QLibrary library(QLatin1String("/System/Library/Frameworks/Carbon.framework/Carbon"));
1617         library.setLoadHints(QLibrary::ExportExternalSymbolsHint);
1618                 ptrHIShapeGetBounds = reinterpret_cast<PtrHIShapeGetBounds>(library.resolve("HIShapeGetBounds"));
1619     }
1620
1621 }
1622
1623 bool QMacStylePrivate::animatable(QMacStylePrivate::Animates as, const QWidget *w) const
1624 {
1625     if (!w)
1626         return false;
1627
1628     if (as == AquaPushButton) {
1629         QPushButton *pb = const_cast<QPushButton *>(static_cast<const QPushButton *>(w));
1630         if (w->window()->isActiveWindow() && pb && !mouseDown) {
1631             if (static_cast<const QPushButton *>(w) != defaultButton) {
1632                 // Changed on its own, update the value.
1633                 const_cast<QMacStylePrivate *>(this)->stopAnimate(as, defaultButton);
1634                 const_cast<QMacStylePrivate *>(this)->startAnimate(as, pb);
1635             }
1636             return true;
1637         }
1638     } else if (as == AquaProgressBar) {
1639         if (progressBars.contains((const_cast<QWidget *>(w))))
1640             return true;
1641     }
1642     return false;
1643 }
1644
1645 void QMacStylePrivate::stopAnimate(QMacStylePrivate::Animates as, QWidget *w)
1646 {
1647     if (as == AquaPushButton && defaultButton) {
1648         QPushButton *tmp = defaultButton;
1649         defaultButton = 0;
1650         tmp->update();
1651     } else if (as == AquaProgressBar) {
1652         progressBars.removeAll(w);
1653     }
1654 }
1655
1656 void QMacStylePrivate::startAnimate(QMacStylePrivate::Animates as, QWidget *w)
1657 {
1658     if (as == AquaPushButton)
1659         defaultButton = static_cast<QPushButton *>(w);
1660     else if (as == AquaProgressBar)
1661         progressBars.append(w);
1662     startAnimationTimer();
1663 }
1664
1665 void QMacStylePrivate::startAnimationTimer()
1666 {
1667     if ((defaultButton || !progressBars.isEmpty()) && timerID <= -1)
1668         timerID = startTimer(animateSpeed(AquaListViewItemOpen));
1669 }
1670
1671 bool QMacStylePrivate::addWidget(QWidget *w)
1672 {
1673     //already knew of it
1674     if (static_cast<QPushButton*>(w) == defaultButton
1675             || progressBars.contains(static_cast<QProgressBar*>(w)))
1676         return false;
1677
1678     if (QPushButton *btn = qobject_cast<QPushButton *>(w)) {
1679         btn->installEventFilter(this);
1680         if (btn->isDefault() || (btn->autoDefault() && btn->hasFocus()))
1681             startAnimate(AquaPushButton, btn);
1682         return true;
1683     } else {
1684         bool isProgressBar = (qobject_cast<QProgressBar *>(w));
1685         if (isProgressBar) {
1686             w->installEventFilter(this);
1687             startAnimate(AquaProgressBar, w);
1688             return true;
1689         }
1690     }
1691     if (w->isWindow()) {
1692         w->installEventFilter(this);
1693         return true;
1694     }
1695     return false;
1696 }
1697
1698 void QMacStylePrivate::removeWidget(QWidget *w)
1699 {
1700     QPushButton *btn = qobject_cast<QPushButton *>(w);
1701     if (btn && btn == defaultButton) {
1702         stopAnimate(AquaPushButton, btn);
1703     } else if (qobject_cast<QProgressBar *>(w)) {
1704         stopAnimate(AquaProgressBar, w);
1705     }
1706 }
1707
1708 ThemeDrawState QMacStylePrivate::getDrawState(QStyle::State flags)
1709 {
1710     ThemeDrawState tds = kThemeStateActive;
1711     if (flags & QStyle::State_Sunken) {
1712         tds = kThemeStatePressed;
1713     } else if (flags & QStyle::State_Active) {
1714         if (!(flags & QStyle::State_Enabled))
1715             tds = kThemeStateUnavailable;
1716     } else {
1717         if (flags & QStyle::State_Enabled)
1718             tds = kThemeStateInactive;
1719         else
1720             tds = kThemeStateUnavailableInactive;
1721     }
1722     return tds;
1723 }
1724
1725 void QMacStylePrivate::timerEvent(QTimerEvent *)
1726 {
1727     int animated = 0;
1728     if (defaultButton && defaultButton->isEnabled() && defaultButton->window()->isActiveWindow()
1729         && defaultButton->isVisibleTo(0) && (defaultButton->isDefault()
1730         || (defaultButton->autoDefault() && defaultButton->hasFocus()))
1731         && doAnimate(AquaPushButton)) {
1732         ++animated;
1733         defaultButton->update();
1734     }
1735     if (!progressBars.isEmpty()) {
1736         int i = 0;
1737         while (i < progressBars.size()) {
1738             QWidget *maybeProgress = progressBars.at(i);
1739             if (!maybeProgress) {
1740                 progressBars.removeAt(i);
1741             } else {
1742                 if (QProgressBar *pb = qobject_cast<QProgressBar *>(maybeProgress)) {
1743                     if (pb->maximum() == 0 || (pb->value() > 0 && pb->value() < pb->maximum())) {
1744                         if (doAnimate(AquaProgressBar))
1745                             pb->update();
1746                     }
1747                 }
1748                 ++i;
1749             }
1750         }
1751         if (i > 0) {
1752             ++progressFrame;
1753             animated += i;
1754         }
1755     }
1756     if (animated <= 0) {
1757         killTimer(timerID);
1758         timerID = -1;
1759     }
1760 }
1761
1762 bool QMacStylePrivate::eventFilter(QObject *o, QEvent *e)
1763 {
1764     //animate
1765     if (QProgressBar *pb = qobject_cast<QProgressBar *>(o)) {
1766         switch (e->type()) {
1767         default:
1768             break;
1769         case QEvent::Show:
1770             if (!progressBars.contains(pb))
1771                 startAnimate(AquaProgressBar, pb);
1772             break;
1773         case QEvent::Destroy:
1774         case QEvent::Hide:
1775             progressBars.removeAll(pb);
1776         }
1777     } else if (QPushButton *btn = qobject_cast<QPushButton *>(o)) {
1778         switch (e->type()) {
1779         default:
1780             break;
1781         case QEvent::FocusIn:
1782             if (btn->autoDefault())
1783                 startAnimate(AquaPushButton, btn);
1784             break;
1785         case QEvent::Destroy:
1786         case QEvent::Hide:
1787             if (btn == defaultButton)
1788                 stopAnimate(AquaPushButton, btn);
1789             break;
1790         case QEvent::MouseButtonPress:
1791             // It is very confusing to keep the button pulsing, so just stop the animation.
1792             if (static_cast<QMouseEvent *>(e)->button() == Qt::LeftButton)
1793                 mouseDown = true;
1794             stopAnimate(AquaPushButton, btn);
1795             break;
1796         case QEvent::MouseButtonRelease:
1797             if (static_cast<QMouseEvent *>(e)->button() == Qt::LeftButton)
1798                 mouseDown = false;
1799             // fall through
1800         case QEvent::FocusOut:
1801         case QEvent::Show:
1802         case QEvent::WindowActivate: {
1803             QList<QPushButton *> list = btn->window()->findChildren<QPushButton *>();
1804             for (int i = 0; i < list.size(); ++i) {
1805                 QPushButton *pBtn = list.at(i);
1806                 if ((e->type() == QEvent::FocusOut
1807                      && (pBtn->isDefault() || (pBtn->autoDefault() && pBtn->hasFocus()))
1808                      && pBtn != btn)
1809                     || ((e->type() == QEvent::Show || e->type() == QEvent::MouseButtonRelease
1810                          || e->type() == QEvent::WindowActivate)
1811                         && pBtn->isDefault())) {
1812                     if (pBtn->window()->isActiveWindow()) {
1813                         startAnimate(AquaPushButton, pBtn);
1814                     }
1815                     break;
1816                 }
1817             }
1818             break; }
1819         }
1820     }
1821     return false;
1822 }
1823
1824 bool QMacStylePrivate::doAnimate(QMacStylePrivate::Animates as)
1825 {
1826     if (as == AquaPushButton) {
1827     } else if (as == AquaProgressBar) {
1828         // something for later...
1829     } else if (as == AquaListViewItemOpen) {
1830         // To be revived later...
1831     }
1832     return true;
1833 }
1834
1835 void QMacStylePrivate::drawColorlessButton(const HIRect &macRect, HIThemeButtonDrawInfo *bdi,
1836                                            QPainter *p, const QStyleOption *opt) const
1837 {
1838     int xoff = 0,
1839         yoff = 0,
1840         extraWidth = 0,
1841         extraHeight = 0,
1842         finalyoff = 0;
1843
1844     const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox *>(opt);
1845     int width = int(macRect.size.width) + extraWidth;
1846     int height = int(macRect.size.height) + extraHeight;
1847
1848     if (width <= 0 || height <= 0)
1849         return;   // nothing to draw
1850
1851     QString key = QLatin1String("$qt_mac_style_ctb_") + QString::number(bdi->kind) + QLatin1Char('_')
1852                   + QString::number(bdi->value) + QLatin1Char('_') + QString::number(width)
1853                   + QLatin1Char('_') + QString::number(height);
1854     QPixmap pm;
1855     if (!QPixmapCache::find(key, pm)) {
1856         QPixmap activePixmap(width, height);
1857         activePixmap.fill(Qt::transparent);
1858         {
1859             if (combo){
1860                 // Carbon combos don't scale. Therefore we draw it
1861                 // ourselves, if a scaled version is needed.
1862                 QPainter tmpPainter(&activePixmap);
1863                 QMacStylePrivate::drawCombobox(macRect, *bdi, &tmpPainter);
1864             }
1865             else {
1866                 QMacCGContext cg(&activePixmap);
1867                 HIRect newRect = CGRectMake(xoff, yoff, macRect.size.width, macRect.size.height);
1868                 HIThemeDrawButton(&newRect, bdi, cg, kHIThemeOrientationNormal, 0);
1869             }
1870         }
1871
1872         if (!combo && bdi->value == kThemeButtonOff) {
1873             pm = activePixmap;
1874         } else if (combo) {
1875             QImage image = activePixmap.toImage();
1876
1877             for (int y = 0; y < height; ++y) {
1878                 QRgb *scanLine = reinterpret_cast<QRgb *>(image.scanLine(y));
1879
1880                 for (int x = 0; x < width; ++x) {
1881                     QRgb &pixel = scanLine[x];
1882
1883                     int darkest = qRed(pixel);
1884                     int mid = qGreen(pixel);
1885                     int lightest = qBlue(pixel);
1886
1887                     if (darkest > mid)
1888                         qSwap(darkest, mid);
1889                     if (mid > lightest)
1890                         qSwap(mid, lightest);
1891                     if (darkest > mid)
1892                         qSwap(darkest, mid);
1893
1894                     int gray = (mid + 2 * lightest) / 3;
1895                     pixel = qRgba(gray, gray, gray, qAlpha(pixel));
1896                 }
1897             }
1898             pm = QPixmap::fromImage(image);
1899         } else {
1900             QImage activeImage = activePixmap.toImage();
1901             QImage colorlessImage;
1902             {
1903                 QPixmap colorlessPixmap(width, height);
1904                 colorlessPixmap.fill(Qt::transparent);
1905
1906                 QMacCGContext cg(&colorlessPixmap);
1907                 HIRect newRect = CGRectMake(xoff, yoff, macRect.size.width, macRect.size.height);
1908                 int oldValue = bdi->value;
1909                 bdi->value = kThemeButtonOff;
1910                 HIThemeDrawButton(&newRect, bdi, cg, kHIThemeOrientationNormal, 0);
1911                 bdi->value = oldValue;
1912                 colorlessImage = colorlessPixmap.toImage();
1913             }
1914
1915             for (int y = 0; y < height; ++y) {
1916                 QRgb *colorlessScanLine = reinterpret_cast<QRgb *>(colorlessImage.scanLine(y));
1917                 const QRgb *activeScanLine = reinterpret_cast<const QRgb *>(activeImage.scanLine(y));
1918
1919                 for (int x = 0; x < width; ++x) {
1920                     QRgb &colorlessPixel = colorlessScanLine[x];
1921                     QRgb activePixel = activeScanLine[x];
1922
1923                     if (activePixel != colorlessPixel) {
1924                         int max = qMax(qMax(qRed(activePixel), qGreen(activePixel)),
1925                                        qBlue(activePixel));
1926                         QRgb newPixel = qRgba(max, max, max, qAlpha(activePixel));
1927                         if (qGray(newPixel) < qGray(colorlessPixel)
1928                                 || qAlpha(newPixel) > qAlpha(colorlessPixel))
1929                             colorlessPixel = newPixel;
1930                     }
1931                 }
1932             }
1933             pm = QPixmap::fromImage(colorlessImage);
1934         }
1935         QPixmapCache::insert(key, pm);
1936     }
1937     p->drawPixmap(int(macRect.origin.x), int(macRect.origin.y) + finalyoff, width, height, pm);
1938 }
1939
1940 QMacStyle::QMacStyle()
1941     : QWindowsStyle()
1942 {
1943     d = new QMacStylePrivate(this);
1944 }
1945
1946 QMacStyle::~QMacStyle()
1947 {
1948     delete qt_mac_backgroundPattern;
1949     qt_mac_backgroundPattern = 0;
1950     delete d;
1951 }
1952
1953 /*! \internal
1954     Generates the standard widget background pattern.
1955 */
1956 QPixmap QMacStylePrivate::generateBackgroundPattern() const
1957 {
1958     QPixmap px(4, 4);
1959     QMacCGContext cg(&px);
1960     HIThemeSetFill(kThemeBrushDialogBackgroundActive, 0, cg, kHIThemeOrientationNormal);
1961     const CGRect cgRect = CGRectMake(0, 0, px.width(), px.height());
1962     CGContextFillRect(cg, cgRect);
1963     return px;
1964 }
1965
1966 /*! \internal
1967     Fills the given \a rect with the pattern stored in \a brush. As an optimization,
1968     HIThemeSetFill us used directly if we are filling with the standard background.
1969 */
1970 void qt_mac_fill_background(QPainter *painter, const QRegion &rgn, const QBrush &brush)
1971 {
1972     QPoint dummy;
1973     const QPaintDevice *target = painter->device();
1974     const QPaintDevice *redirected = QPainter::redirected(target, &dummy);
1975     //const bool usePainter = redirected && redirected != target;
1976
1977 #if 0
1978     if (!usePainter && qt_mac_backgroundPattern
1979         && qt_mac_backgroundPattern->cacheKey() == brush.texture().cacheKey()) {
1980
1981         painter->setClipRegion(rgn);
1982
1983         QCFType<CGContextRef> cg = qt_mac_cg_context(target);
1984         CGContextSaveGState(cg);
1985         HIThemeSetFill(kThemeBrushDialogBackgroundActive, 0, cg, kHIThemeOrientationInverted);
1986
1987         const QVector<QRect> &rects = rgn.rects();
1988         for (int i = 0; i < rects.size(); ++i) {
1989             const QRect rect(rects.at(i));
1990             // Anchor the pattern to the top so it stays put when the window is resized.
1991             CGContextSetPatternPhase(cg, CGSizeMake(rect.width(), rect.height()));
1992             CGRect mac_rect = CGRectMake(rect.x(), rect.y(), rect.width(), rect.height());
1993             CGContextFillRect(cg, mac_rect);
1994         }
1995
1996         CGContextRestoreGState(cg);
1997     } else {
1998 #endif
1999         const QRect rect(rgn.boundingRect());
2000         painter->setClipRegion(rgn);
2001         painter->drawTiledPixmap(rect, brush.texture(), rect.topLeft());
2002 //    }
2003 }
2004
2005 void QMacStyle::polish(QPalette &pal)
2006 {
2007     if (!qt_mac_backgroundPattern) {
2008         if (!qApp)
2009             return;
2010         qt_mac_backgroundPattern = new QPixmap(d->generateBackgroundPattern());
2011     }
2012
2013     QColor pc(Qt::black);
2014     pc = qcolorForTheme(kThemeBrushDialogBackgroundActive);
2015     QBrush background(pc, *qt_mac_backgroundPattern);
2016     pal.setBrush(QPalette::All, QPalette::Window, background);
2017     pal.setBrush(QPalette::All, QPalette::Button, background);
2018
2019     QCFString theme;
2020     const OSErr err = CopyThemeIdentifier(&theme);
2021     if (err == noErr && CFStringCompare(theme, kThemeAppearanceAquaGraphite, 0) == kCFCompareEqualTo) {
2022         pal.setBrush(QPalette::All, QPalette::AlternateBase, QColor(240, 240, 240));
2023     } else {
2024         pal.setBrush(QPalette::All, QPalette::AlternateBase, QColor(237, 243, 254));
2025     }
2026 }
2027
2028 void QMacStyle::polish(QApplication *)
2029 {
2030 }
2031
2032 void QMacStyle::unpolish(QApplication *)
2033 {
2034 }
2035
2036 void QMacStyle::polish(QWidget* w)
2037 {
2038     d->addWidget(w);
2039     if (qt_mac_is_metal(w) && !w->testAttribute(Qt::WA_SetPalette)) {
2040         // Set a clear brush so that the metal shines through.
2041         QPalette pal = w->palette();
2042         QBrush background(Qt::transparent);
2043         pal.setBrush(QPalette::All, QPalette::Window, background);
2044         pal.setBrush(QPalette::All, QPalette::Button, background);
2045         w->setPalette(pal);
2046         w->setAttribute(Qt::WA_SetPalette, false);
2047     }
2048
2049     if (qobject_cast<QMenu*>(w) || qobject_cast<QComboBoxPrivateContainer *>(w)) {
2050         w->setWindowOpacity(QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5 ? 0.985 : 0.94);
2051         if (!w->testAttribute(Qt::WA_SetPalette)) {
2052             QPixmap px(64, 64);
2053             px.fill(Qt::white);
2054             HIThemeMenuDrawInfo mtinfo;
2055             mtinfo.version = qt_mac_hitheme_version;
2056             mtinfo.menuType = kThemeMenuTypePopUp;
2057             HIRect rect = CGRectMake(0, 0, px.width(), px.height());
2058             // ###
2059             //HIThemeDrawMenuBackground(&rect, &mtinfo, QCFType<CGContextRef>(qt_mac_cg_context(&px)),
2060             //                          kHIThemeOrientationNormal);
2061             QPalette pal = w->palette();
2062             QBrush background(px);
2063             pal.setBrush(QPalette::All, QPalette::Window, background);
2064             pal.setBrush(QPalette::All, QPalette::Button, background);
2065             w->setPalette(pal);
2066             w->setAttribute(Qt::WA_SetPalette, false);
2067         }
2068     }
2069
2070     if (QTabBar *tb = qobject_cast<QTabBar*>(w)) {
2071         if (tb->documentMode()) {
2072             w->setAttribute(Qt::WA_Hover);
2073             w->setFont(qt_app_fonts_hash()->value("QSmallFont", QFont()));
2074             QPalette p = w->palette();
2075             p.setColor(QPalette::WindowText, QColor(17, 17, 17));
2076             w->setPalette(p);
2077         }
2078     }
2079
2080     QWindowsStyle::polish(w);
2081
2082     if (QRubberBand *rubber = qobject_cast<QRubberBand*>(w)) {
2083         rubber->setWindowOpacity(0.25);
2084         rubber->setAttribute(Qt::WA_PaintOnScreen, false);
2085         rubber->setAttribute(Qt::WA_NoSystemBackground, false);
2086     }
2087 }
2088
2089 void QMacStyle::unpolish(QWidget* w)
2090 {
2091     d->removeWidget(w);
2092     if ((qobject_cast<QMenu*>(w) || qt_mac_is_metal(w)) && !w->testAttribute(Qt::WA_SetPalette)) {
2093         QPalette pal = qApp->palette(w);
2094         w->setPalette(pal);
2095         w->setAttribute(Qt::WA_SetPalette, false);
2096         w->setWindowOpacity(1.0);
2097     }
2098
2099     if (QComboBox *combo = qobject_cast<QComboBox *>(w)) {
2100         if (!combo->isEditable()) {
2101             if (QWidget *widget = combo->findChild<QComboBoxPrivateContainer *>())
2102                 widget->setWindowOpacity(1.0);
2103         }
2104     }
2105
2106     if (QRubberBand *rubber = ::qobject_cast<QRubberBand*>(w)) {
2107         rubber->setWindowOpacity(1.0);
2108         rubber->setAttribute(Qt::WA_PaintOnScreen, true);
2109         rubber->setAttribute(Qt::WA_NoSystemBackground, true);
2110     }
2111
2112     if (QFocusFrame *frame = qobject_cast<QFocusFrame *>(w))
2113         frame->setAttribute(Qt::WA_NoSystemBackground, true);
2114
2115     QWindowsStyle::unpolish(w);
2116 }
2117
2118 int QMacStyle::pixelMetric(PixelMetric metric, const QStyleOption *opt, const QWidget *widget) const
2119 {
2120     int controlSize = getControlSize(opt, widget);
2121     SInt32 ret = 0;
2122
2123     switch (metric) {
2124     case PM_TabCloseIndicatorWidth:
2125     case PM_TabCloseIndicatorHeight:
2126         ret = closeButtonSize;
2127         break;
2128     case PM_ToolBarIconSize:
2129         ret = proxy()->pixelMetric(PM_LargeIconSize);
2130         break;
2131     case PM_FocusFrameVMargin:
2132     case PM_FocusFrameHMargin:
2133         GetThemeMetric(kThemeMetricFocusRectOutset, &ret);
2134         break;
2135     case PM_DialogButtonsSeparator:
2136         ret = -5;
2137         break;
2138     case PM_DialogButtonsButtonHeight: {
2139         QSize sz;
2140         ret = d->aquaSizeConstrain(opt, 0, QStyle::CT_PushButton, QSize(-1, -1), &sz);
2141         if (sz == QSize(-1, -1))
2142             ret = 32;
2143         else
2144             ret = sz.height();
2145         break; }
2146     case PM_CheckListButtonSize: {
2147         switch (d->aquaSizeConstrain(opt, widget)) {
2148         case QAquaSizeUnknown:
2149         case QAquaSizeLarge:
2150             GetThemeMetric(kThemeMetricCheckBoxWidth, &ret);
2151             break;
2152         case QAquaSizeMini:
2153             GetThemeMetric(kThemeMetricMiniCheckBoxWidth, &ret);
2154             break;
2155         case QAquaSizeSmall:
2156             GetThemeMetric(kThemeMetricSmallCheckBoxWidth, &ret);
2157             break;
2158         }
2159         break; }
2160     case PM_DialogButtonsButtonWidth: {
2161         QSize sz;
2162         ret = d->aquaSizeConstrain(opt, 0, QStyle::CT_PushButton, QSize(-1, -1), &sz);
2163         if (sz == QSize(-1, -1))
2164             ret = 70;
2165         else
2166             ret = sz.width();
2167         break; }
2168
2169     case PM_MenuBarHMargin:
2170         ret = 8;
2171         break;
2172
2173     case PM_MenuBarVMargin:
2174         ret = 0;
2175         break;
2176
2177     case QStyle::PM_MenuDesktopFrameWidth:
2178         ret = 5;
2179         break;
2180
2181     case PM_CheckBoxLabelSpacing:
2182     case PM_RadioButtonLabelSpacing:
2183         ret = 2;
2184         break;
2185     case PM_MenuScrollerHeight:
2186 #if 0
2187         SInt16 ash, asw;
2188         GetThemeMenuItemExtra(kThemeMenuItemScrollUpArrow, &ash, &asw);
2189         ret = ash;
2190 #else
2191         ret = 15; // I hate having magic numbers in here...
2192 #endif
2193         break;
2194     case PM_DefaultFrameWidth:
2195 #ifndef QT_NO_MAINWINDOW
2196         if (widget && (widget->isWindow() || !widget->parentWidget()
2197                 || (qobject_cast<const QMainWindow*>(widget->parentWidget())
2198                    && static_cast<QMainWindow *>(widget->parentWidget())->centralWidget() == widget))
2199                 && (qobject_cast<const QAbstractScrollArea *>(widget)
2200                     || widget->inherits("QWorkspaceChild")))
2201             ret = 0;
2202         else
2203 #endif
2204         // The combo box popup has no frame.
2205         if (qstyleoption_cast<const QStyleOptionComboBox *>(opt) != 0)
2206             ret = 0;
2207         // Frame of mac style line edits is two pixels on top and one on the bottom
2208         else if (qobject_cast<const QLineEdit *>(widget) != 0)
2209             ret = 2;
2210         else
2211             ret = 1;
2212         break;
2213     case PM_MaximumDragDistance:
2214         ret = -1;
2215         break;
2216     case PM_ScrollBarSliderMin:
2217         ret = 24;
2218         break;
2219     case PM_SpinBoxFrameWidth:
2220         GetThemeMetric(kThemeMetricEditTextFrameOutset, &ret);
2221         switch (d->aquaSizeConstrain(opt, widget)) {
2222         default:
2223             ret += 2;
2224             break;
2225         case QAquaSizeMini:
2226             ret += 1;
2227             break;
2228         }
2229         break;
2230     case PM_ButtonShiftHorizontal:
2231     case PM_ButtonShiftVertical:
2232         ret = 0;
2233         break;
2234     case PM_SliderLength:
2235         ret = 17;
2236         break;
2237     case PM_ButtonDefaultIndicator:
2238         ret = 0;
2239         break;
2240     case PM_TitleBarHeight:
2241         if (const QStyleOptionTitleBar *tb = qstyleoption_cast<const QStyleOptionTitleBar *>(opt)) {
2242             HIThemeWindowDrawInfo wdi;
2243             wdi.version = qt_mac_hitheme_version;
2244             wdi.state = kThemeStateActive;
2245             wdi.windowType = QtWinType;
2246             if (tb->titleBarState)
2247                 wdi.attributes = kThemeWindowHasFullZoom | kThemeWindowHasCloseBox
2248                                   | kThemeWindowHasCollapseBox;
2249             else if (tb->titleBarFlags & Qt::WindowSystemMenuHint)
2250                 wdi.attributes = kThemeWindowHasCloseBox;
2251             else
2252                 wdi.attributes = 0;
2253             wdi.titleHeight = tb->rect.height();
2254             wdi.titleWidth = tb->rect.width();
2255             QCFType<HIShapeRef> region;
2256             HIRect hirect = qt_hirectForQRect(tb->rect);
2257             if (hirect.size.width <= 0)
2258                 hirect.size.width = 100;
2259             if (hirect.size.height <= 0)
2260                 hirect.size.height = 30;
2261
2262             HIThemeGetWindowShape(&hirect, &wdi, kWindowTitleBarRgn, &region);
2263             HIRect rect;
2264             ptrHIShapeGetBounds(region, &rect);
2265             ret = int(rect.size.height);
2266             ret += 4;
2267         }
2268         break;
2269     case PM_TabBarTabVSpace:
2270         ret = 4;
2271         break;
2272     case PM_TabBarTabShiftHorizontal:
2273     case PM_TabBarTabShiftVertical:
2274         ret = 0;
2275         break;
2276     case PM_TabBarBaseHeight:
2277         ret = 0;
2278         break;
2279     case PM_TabBarTabOverlap:
2280         ret = 0;
2281         break;
2282     case PM_TabBarBaseOverlap:
2283         switch (d->aquaSizeConstrain(opt, widget)) {
2284         case QAquaSizeUnknown:
2285         case QAquaSizeLarge:
2286             ret = 11;
2287             break;
2288         case QAquaSizeSmall:
2289             ret = 8;
2290             break;
2291         case QAquaSizeMini:
2292             ret = 7;
2293             break;
2294         }
2295         break;
2296     case PM_ScrollBarExtent: {
2297         switch (d->aquaSizeConstrain(opt, widget)) {
2298         case QAquaSizeUnknown:
2299         case QAquaSizeLarge:
2300             GetThemeMetric(kThemeMetricScrollBarWidth, &ret);
2301             break;
2302         case QAquaSizeMini:
2303         case QAquaSizeSmall:
2304             GetThemeMetric(kThemeMetricSmallScrollBarWidth, &ret);
2305             break;
2306         }
2307         break; }
2308     case PM_IndicatorHeight: {
2309         switch (d->aquaSizeConstrain(opt, widget)) {
2310         case QAquaSizeUnknown:
2311         case QAquaSizeLarge:
2312             GetThemeMetric(kThemeMetricCheckBoxHeight, &ret);
2313             break;
2314         case QAquaSizeMini:
2315             GetThemeMetric(kThemeMetricMiniCheckBoxHeight, &ret);
2316             break;
2317         case QAquaSizeSmall:
2318             GetThemeMetric(kThemeMetricSmallCheckBoxHeight, &ret);
2319             break;
2320         }
2321         break; }
2322     case PM_IndicatorWidth: {
2323         switch (d->aquaSizeConstrain(opt, widget)) {
2324         case QAquaSizeUnknown:
2325         case QAquaSizeLarge:
2326             GetThemeMetric(kThemeMetricCheckBoxWidth, &ret);
2327             break;
2328         case QAquaSizeMini:
2329             GetThemeMetric(kThemeMetricMiniCheckBoxWidth, &ret);
2330             break;
2331         case QAquaSizeSmall:
2332             GetThemeMetric(kThemeMetricSmallCheckBoxWidth, &ret);
2333             break;
2334         }
2335         ++ret;
2336         break; }
2337     case PM_ExclusiveIndicatorHeight: {
2338         switch (d->aquaSizeConstrain(opt, widget)) {
2339         case QAquaSizeUnknown:
2340         case QAquaSizeLarge:
2341             GetThemeMetric(kThemeMetricRadioButtonHeight, &ret);
2342             break;
2343         case QAquaSizeMini:
2344             GetThemeMetric(kThemeMetricMiniRadioButtonHeight, &ret);
2345             break;
2346         case QAquaSizeSmall:
2347             GetThemeMetric(kThemeMetricSmallRadioButtonHeight, &ret);
2348             break;
2349         }
2350         break; }
2351     case PM_ExclusiveIndicatorWidth: {
2352         switch (d->aquaSizeConstrain(opt, widget)) {
2353         case QAquaSizeUnknown:
2354         case QAquaSizeLarge:
2355             GetThemeMetric(kThemeMetricRadioButtonWidth, &ret);
2356             break;
2357         case QAquaSizeMini:
2358             GetThemeMetric(kThemeMetricMiniRadioButtonWidth, &ret);
2359             break;
2360         case QAquaSizeSmall:
2361             GetThemeMetric(kThemeMetricSmallRadioButtonWidth, &ret);
2362             break;
2363         }
2364         ++ret;
2365         break; }
2366     case PM_MenuVMargin:
2367         ret = 4;
2368         break;
2369     case PM_MenuPanelWidth:
2370         ret = 0;
2371         break;
2372     case PM_ToolTipLabelFrameWidth:
2373         ret = 0;
2374         break;
2375     case PM_SizeGripSize: {
2376         QAquaWidgetSize aSize;
2377         if (widget && widget->window()->windowType() == Qt::Tool)
2378             aSize = QAquaSizeSmall;
2379         else
2380             aSize = QAquaSizeLarge;
2381         const QSize size = qt_aqua_get_known_size(CT_SizeGrip, widget, QSize(), aSize);
2382         ret = size.width();
2383         break; }
2384     case PM_MdiSubWindowFrameWidth:
2385         ret = 1;
2386         break;
2387     case PM_DockWidgetFrameWidth:
2388         ret = 2;
2389         break;
2390     case PM_DockWidgetTitleMargin:
2391         ret = 0;
2392         break;
2393     case PM_DockWidgetSeparatorExtent:
2394         ret = 1;
2395         break;
2396     case PM_ToolBarHandleExtent:
2397         ret = 11;
2398         break;
2399     case PM_ToolBarItemMargin:
2400         ret = 0;
2401         break;
2402     case PM_ToolBarItemSpacing:
2403         ret = 4;
2404         break;
2405     case PM_SplitterWidth:
2406         ret = qMax(7, QApplication::globalStrut().width());
2407         break;
2408     case PM_LayoutLeftMargin:
2409     case PM_LayoutTopMargin:
2410     case PM_LayoutRightMargin:
2411     case PM_LayoutBottomMargin:
2412         {
2413             bool isWindow = false;
2414             if (opt) {
2415                 isWindow = (opt->state & State_Window);
2416             } else if (widget) {
2417                 isWindow = widget->isWindow();
2418             }
2419
2420             if (isWindow) {
2421                 bool isMetal = widget && widget->testAttribute(Qt::WA_MacBrushedMetal);
2422                 if (isMetal) {
2423                     if (metric == PM_LayoutTopMargin) {
2424                         return_SIZE(9 /* AHIG */, 6 /* guess */, 6 /* guess */);
2425                     } else if (metric == PM_LayoutBottomMargin) {
2426                         return_SIZE(18 /* AHIG */, 15 /* guess */, 13 /* guess */);
2427                     } else {
2428                         return_SIZE(14 /* AHIG */, 11 /* guess */, 9 /* guess */);
2429                     }
2430                 } else {
2431                     /*
2432                         AHIG would have (20, 8, 10) here but that makes
2433                         no sense. It would also have 14 for the top margin
2434                         but this contradicts both Builder and most
2435                         applications.
2436                     */
2437                     return_SIZE(20, 10, 10);    // AHIG
2438                 }
2439             } else {
2440                 // hack to detect QTabWidget
2441                 if (widget && widget->parentWidget()
2442                         && widget->parentWidget()->sizePolicy().controlType() == QSizePolicy::TabWidget) {
2443                     if (metric == PM_LayoutTopMargin) {
2444                         /*
2445                             Builder would have 14 (= 20 - 6) instead of 12,
2446                             but that makes the tab look disproportionate.
2447                         */
2448                         return_SIZE(12, 6, 6);  // guess
2449                     } else {
2450                         return_SIZE(20 /* Builder */, 8 /* guess */, 8 /* guess */);
2451                     }
2452                 } else {
2453                     /*
2454                         Child margins are highly inconsistent in AHIG and Builder.
2455                     */
2456                     return_SIZE(12, 8, 6);    // guess
2457                 }
2458             }
2459         }
2460     case PM_LayoutHorizontalSpacing:
2461     case PM_LayoutVerticalSpacing:
2462         return -1;
2463     case QStyle::PM_TabBarTabHSpace:
2464         switch (d->aquaSizeConstrain(opt, widget)) {
2465         case QAquaSizeLarge:
2466         case QAquaSizeUnknown:
2467             ret = QWindowsStyle::pixelMetric(metric, opt, widget);
2468             break;
2469         case QAquaSizeSmall:
2470             ret = 20;
2471             break;
2472         case QAquaSizeMini:
2473             ret = 16;
2474             break;
2475         }
2476         break;
2477     case PM_MenuHMargin:
2478         ret = 0;
2479         break;
2480     case PM_ToolBarFrameWidth:
2481         ret = 1;
2482         if (widget) {
2483             if (QMainWindow * mainWindow = qobject_cast<QMainWindow *>(widget->parent()))
2484                 if (mainWindow->unifiedTitleAndToolBarOnMac())
2485                     ret = 0;
2486         }
2487         break;
2488     default:
2489         ret = QWindowsStyle::pixelMetric(metric, opt, widget);
2490         break;
2491     }
2492     return ret;
2493 }
2494
2495 QPalette QMacStyle::standardPalette() const
2496 {
2497     QPalette pal = QWindowsStyle::standardPalette();
2498     pal.setColor(QPalette::Disabled, QPalette::Dark, QColor(191, 191, 191));
2499     pal.setColor(QPalette::Active, QPalette::Dark, QColor(191, 191, 191));
2500     pal.setColor(QPalette::Inactive, QPalette::Dark, QColor(191, 191, 191));
2501     return pal;
2502 }
2503
2504 int QMacStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *w,
2505                          QStyleHintReturn *hret) const
2506 {
2507     SInt32 ret = 0;
2508     switch (sh) {
2509     case SH_Menu_SelectionWrap:
2510         ret = false;
2511         break;
2512     case SH_Menu_KeyboardSearch:
2513         ret = true;
2514         break;
2515     case SH_Menu_SpaceActivatesItem:
2516         ret = true;
2517         break;
2518     case SH_Slider_AbsoluteSetButtons:
2519         ret = Qt::LeftButton|Qt::MidButton;
2520         break;
2521     case SH_Slider_PageSetButtons:
2522         ret = 0;
2523         break;
2524     case SH_ScrollBar_ContextMenu:
2525         ret = false;
2526         break;
2527     case SH_TitleBar_AutoRaise:
2528         ret = true;
2529         break;
2530     case SH_Menu_AllowActiveAndDisabled:
2531         ret = false;
2532         break;
2533     case SH_Menu_SubMenuPopupDelay:
2534         ret = 100;
2535         break;
2536     case SH_ScrollBar_LeftClickAbsolutePosition: {
2537         if(QApplication::keyboardModifiers() & Qt::AltModifier)
2538             ret = false;
2539             //ret = !qt_scrollbar_jump_to_pos;
2540         else
2541             ret = true;
2542             //ret = qt_scrollbar_jump_to_pos;
2543         break; }
2544     case SH_TabBar_PreferNoArrows:
2545         ret = true;
2546         break;
2547     case SH_LineEdit_PasswordCharacter:
2548         ret = kBulletUnicode;
2549         break;
2550         /*
2551     case SH_DialogButtons_DefaultButton:
2552         ret = QDialogButtons::Reject;
2553         break;
2554         */
2555     case SH_Menu_SloppySubMenus:
2556         ret = true;
2557         break;
2558     case SH_GroupBox_TextLabelVerticalAlignment:
2559         ret = Qt::AlignTop;
2560         break;
2561     case SH_ScrollView_FrameOnlyAroundContents:
2562         if (w && (w->isWindow() || !w->parentWidget() || w->parentWidget()->isWindow())
2563                 && (w->inherits("QWorkspaceChild")
2564                 ))
2565             ret = true;
2566         else
2567             ret = QWindowsStyle::styleHint(sh, opt, w, hret);
2568         break;
2569     case SH_Menu_FillScreenWithScroll:
2570         ret = false;
2571         break;
2572     case SH_Menu_Scrollable:
2573         ret = true;
2574         break;
2575     case SH_RichText_FullWidthSelection:
2576         ret = true;
2577         break;
2578     case SH_BlinkCursorWhenTextSelected:
2579         ret = false;
2580         break;
2581     case SH_ScrollBar_StopMouseOverSlider:
2582         ret = true;
2583         break;
2584     case SH_Q3ListViewExpand_SelectMouseType:
2585         ret = QEvent::MouseButtonRelease;
2586         break;
2587     case SH_TabBar_SelectMouseType:
2588         if (const QStyleOptionTabBarBaseV2 *opt2 = qstyleoption_cast<const QStyleOptionTabBarBaseV2 *>(opt)) {
2589             ret = opt2->documentMode ? QEvent::MouseButtonPress : QEvent::MouseButtonRelease;
2590         } else {
2591             ret = QEvent::MouseButtonRelease;
2592         }
2593         break;
2594     case SH_ComboBox_Popup:
2595         if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(opt))
2596             ret = !cmb->editable;
2597         else
2598             ret = 0;
2599         break;
2600     case SH_Workspace_FillSpaceOnMaximize:
2601         ret = true;
2602         break;
2603     case SH_Widget_ShareActivation:
2604         ret = true;
2605         break;
2606     case SH_Header_ArrowAlignment:
2607         ret = Qt::AlignRight;
2608         break;
2609     case SH_TabBar_Alignment: {
2610         if (const QTabWidget *tab = qobject_cast<const QTabWidget*>(w)) {
2611             if (tab->documentMode()) {
2612                 ret = Qt::AlignLeft;
2613                 break;
2614             }
2615         }
2616         if (const QTabBar *tab = qobject_cast<const QTabBar*>(w)) {
2617             if (tab->documentMode()) {
2618                 ret = Qt::AlignLeft;
2619                 break;
2620             }
2621         }
2622         ret = Qt::AlignCenter;
2623         } break;
2624     case SH_UnderlineShortcut:
2625         ret = false;
2626         break;
2627     case SH_ToolTipLabel_Opacity:
2628         ret = 242; // About 95%
2629         break;
2630     case SH_Button_FocusPolicy:
2631         ret = Qt::TabFocus;
2632         break;
2633     case SH_EtchDisabledText:
2634         ret = false;
2635         break;
2636     case SH_FocusFrame_Mask: {
2637         ret = true;
2638         if(QStyleHintReturnMask *mask = qstyleoption_cast<QStyleHintReturnMask*>(hret)) {
2639             const uchar fillR = 192, fillG = 191, fillB = 190;
2640             QImage img;
2641
2642             QSize pixmapSize = opt->rect.size();
2643             if (pixmapSize.isValid()) {
2644                 QPixmap pix(pixmapSize);
2645                 pix.fill(QColor(fillR, fillG, fillB));
2646                 QPainter pix_paint(&pix);
2647                 proxy()->drawControl(CE_FocusFrame, opt, &pix_paint, w);
2648                 pix_paint.end();
2649                 img = pix.toImage();
2650             }
2651
2652             const QRgb *sptr = (QRgb*)img.bits(), *srow;
2653             const int sbpl = img.bytesPerLine();
2654             const int w = sbpl/4, h = img.height();
2655
2656             QImage img_mask(img.width(), img.height(), QImage::Format_ARGB32);
2657             QRgb *dptr = (QRgb*)img_mask.bits(), *drow;
2658             const int dbpl = img_mask.bytesPerLine();
2659
2660             for (int y = 0; y < h; ++y) {
2661                 srow = sptr+((y*sbpl)/4);
2662                 drow = dptr+((y*dbpl)/4);
2663                 for (int x = 0; x < w; ++x) {
2664                     const int diff = (((qRed(*srow)-fillR)*(qRed(*srow)-fillR)) +
2665                                       ((qGreen(*srow)-fillG)*((qGreen(*srow)-fillG))) +
2666                                       ((qBlue(*srow)-fillB)*((qBlue(*srow)-fillB))));
2667                     (*drow++) = (diff < 100) ? 0xffffffff : 0xff000000;
2668                     ++srow;
2669                 }
2670             }
2671             QBitmap qmask = QBitmap::fromImage(img_mask);
2672             mask->region = QRegion(qmask);
2673         }
2674         break; }
2675     case SH_TitleBar_NoBorder:
2676         ret = 1;
2677         break;
2678     case SH_RubberBand_Mask:
2679         ret = 0;
2680         break;
2681     case SH_ComboBox_LayoutDirection:
2682         ret = Qt::LeftToRight;
2683         break;
2684     case SH_ItemView_EllipsisLocation:
2685         ret = Qt::AlignHCenter;
2686         break;
2687     case SH_ItemView_ShowDecorationSelected:
2688         ret = true;
2689         break;
2690     case SH_TitleBar_ModifyNotification:
2691         ret = false;
2692         break;
2693     case SH_ScrollBar_RollBetweenButtons:
2694         ret = true;
2695         break;
2696     case SH_WindowFrame_Mask:
2697         ret = 1;
2698         if (QStyleHintReturnMask *mask = qstyleoption_cast<QStyleHintReturnMask *>(hret)) {
2699             mask->region = opt->rect;
2700             mask->region -= QRect(opt->rect.left(), opt->rect.top(), 5, 1);
2701             mask->region -= QRect(opt->rect.left(), opt->rect.top() + 1, 3, 1);
2702             mask->region -= QRect(opt->rect.left(), opt->rect.top() + 2, 2, 1);
2703             mask->region -= QRect(opt->rect.left(), opt->rect.top() + 3, 1, 2);
2704
2705             mask->region -= QRect(opt->rect.right() - 4, opt->rect.top(), 5, 1);
2706             mask->region -= QRect(opt->rect.right() - 2, opt->rect.top() + 1, 3, 1);
2707             mask->region -= QRect(opt->rect.right() - 1, opt->rect.top() + 2, 2, 1);
2708             mask->region -= QRect(opt->rect.right() , opt->rect.top() + 3, 1, 2);
2709         }
2710         break;
2711     case SH_TabBar_ElideMode:
2712         ret = Qt::ElideRight;
2713         break;
2714     case SH_DialogButtonLayout:
2715         ret = QDialogButtonBox::MacLayout;
2716         break;
2717     case SH_FormLayoutWrapPolicy:
2718         ret = QFormLayout::DontWrapRows;
2719         break;
2720     case SH_FormLayoutFieldGrowthPolicy:
2721         ret = QFormLayout::FieldsStayAtSizeHint;
2722         break;
2723     case SH_FormLayoutFormAlignment:
2724         ret = Qt::AlignHCenter | Qt::AlignTop;
2725         break;
2726     case SH_FormLayoutLabelAlignment:
2727         ret = Qt::AlignRight;
2728         break;
2729     case SH_ComboBox_PopupFrameStyle:
2730         ret = QFrame::NoFrame | QFrame::Plain;
2731         break;
2732     case SH_MessageBox_TextInteractionFlags:
2733         ret = Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse | Qt::TextSelectableByKeyboard;
2734         break;
2735     case SH_SpellCheckUnderlineStyle:
2736         ret = QTextCharFormat::DashUnderline;
2737         break;
2738     case SH_MessageBox_CenterButtons:
2739         ret = false;
2740         break;
2741     case SH_MenuBar_AltKeyNavigation:
2742         ret = false;
2743         break;
2744     case SH_ItemView_MovementWithoutUpdatingSelection:
2745         ret = false;
2746         break;
2747     case SH_FocusFrame_AboveWidget:
2748         ret = true;
2749         break;
2750     case SH_WizardStyle:
2751         ret = QWizard::MacStyle;
2752         break;
2753     case SH_ItemView_ArrowKeysNavigateIntoChildren:
2754         ret = false;
2755         break;
2756     case SH_Menu_FlashTriggeredItem:
2757         ret = true;
2758         break;
2759     case SH_Menu_FadeOutOnHide:
2760         ret = true;
2761         break;
2762     case SH_Menu_Mask:
2763         if (opt) {
2764             if (QStyleHintReturnMask *mask = qstyleoption_cast<QStyleHintReturnMask*>(hret)) {
2765                 ret = true;
2766                 HIRect menuRect = CGRectMake(opt->rect.x(), opt->rect.y() + 4,
2767                                              opt->rect.width(), opt->rect.height() - 8);
2768                 HIThemeMenuDrawInfo mdi;
2769                 mdi.version = 0;
2770                 if (w && qobject_cast<QMenu *>(w->parentWidget()))
2771                     mdi.menuType = kThemeMenuTypeHierarchical;
2772                 else
2773                     mdi.menuType = kThemeMenuTypePopUp;
2774                 QCFType<HIShapeRef> shape;
2775                 HIThemeGetMenuBackgroundShape(&menuRect, &mdi, &shape);
2776
2777                 mask->region = qt_mac_fromHIShapeRef(shape);
2778             }
2779         }
2780         break;
2781     case SH_ItemView_PaintAlternatingRowColorsForEmptyArea:
2782         ret = true;
2783         break;
2784     case SH_TabBar_CloseButtonPosition:
2785         ret = QTabBar::LeftSide;
2786         break;
2787     case SH_DockWidget_ButtonsHaveFrame:
2788         ret = false;
2789         break;
2790     default:
2791         ret = QWindowsStyle::styleHint(sh, opt, w, hret);
2792         break;
2793     }
2794     return ret;
2795 }
2796
2797 QPixmap QMacStyle::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap,
2798                                        const QStyleOption *opt) const
2799 {
2800     switch (iconMode) {
2801     case QIcon::Disabled: {
2802         QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32);
2803         int imgh = img.height();
2804         int imgw = img.width();
2805         QRgb pixel;
2806         for (int y = 0; y < imgh; ++y) {
2807             for (int x = 0; x < imgw; ++x) {
2808                 pixel = img.pixel(x, y);
2809                 img.setPixel(x, y, qRgba(qRed(pixel), qGreen(pixel), qBlue(pixel),
2810                                          qAlpha(pixel) / 2));
2811             }
2812         }
2813         return QPixmap::fromImage(img);
2814     }
2815     default:
2816         ;
2817     }
2818     return QWindowsStyle::generatedIconPixmap(iconMode, pixmap, opt);
2819 }
2820
2821
2822 QPixmap QMacStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt,
2823                                   const QWidget *widget) const
2824 {
2825     // The default implementation of QStyle::standardIconImplementation() is to call standardPixmap()
2826     // I don't want infinite recursion so if we do get in that situation, just return the Window's
2827     // standard pixmap instead (since there is no mac-specific icon then). This should be fine until
2828     // someone changes how Windows standard
2829     // pixmap works.
2830     static bool recursionGuard = false;
2831
2832     if (recursionGuard)
2833         return QWindowsStyle::standardPixmap(standardPixmap, opt, widget);
2834
2835     recursionGuard = true;
2836     QIcon icon = standardIconImplementation(standardPixmap, opt, widget);
2837     recursionGuard = false;
2838     int size;
2839     switch (standardPixmap) {
2840         default:
2841             size = 32;
2842             break;
2843         case SP_MessageBoxCritical:
2844         case SP_MessageBoxQuestion:
2845         case SP_MessageBoxInformation:
2846         case SP_MessageBoxWarning:
2847             size = 64;
2848             break;
2849     }
2850     return icon.pixmap(size, size);
2851 }
2852
2853 void QMacStyle::setFocusRectPolicy(QWidget *w, FocusRectPolicy policy)
2854 {
2855     switch (policy) {
2856     case FocusDefault:
2857         break;
2858     case FocusEnabled:
2859     case FocusDisabled:
2860         w->setAttribute(Qt::WA_MacShowFocusRect, policy == FocusEnabled);
2861         break;
2862     }
2863 }
2864
2865 QMacStyle::FocusRectPolicy QMacStyle::focusRectPolicy(const QWidget *w)
2866 {
2867     return w->testAttribute(Qt::WA_MacShowFocusRect) ? FocusEnabled : FocusDisabled;
2868 }
2869
2870 void QMacStyle::setWidgetSizePolicy(const QWidget *widget, WidgetSizePolicy policy)
2871 {
2872     QWidget *wadget = const_cast<QWidget *>(widget);
2873     wadget->setAttribute(Qt::WA_MacNormalSize, policy == SizeLarge);
2874     wadget->setAttribute(Qt::WA_MacSmallSize, policy == SizeSmall);
2875     wadget->setAttribute(Qt::WA_MacMiniSize, policy == SizeMini);
2876 }
2877
2878 QMacStyle::WidgetSizePolicy QMacStyle::widgetSizePolicy(const QWidget *widget)
2879 {
2880     while (widget) {
2881         if (widget->testAttribute(Qt::WA_MacMiniSize)) {
2882             return SizeMini;
2883         } else if (widget->testAttribute(Qt::WA_MacSmallSize)) {
2884             return SizeSmall;
2885         } else if (widget->testAttribute(Qt::WA_MacNormalSize)) {
2886             return SizeLarge;
2887         }
2888         widget = widget->parentWidget();
2889     }
2890     return SizeDefault;
2891 }
2892
2893 void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *p,
2894                               const QWidget *w) const
2895 {
2896     ThemeDrawState tds = d->getDrawState(opt->state);
2897     QMacCGContext cg(p);
2898     switch (pe) {
2899     case PE_IndicatorArrowUp:
2900     case PE_IndicatorArrowDown:
2901     case PE_IndicatorArrowRight:
2902     case PE_IndicatorArrowLeft: {
2903         p->save();
2904         p->setRenderHint(QPainter::Antialiasing);
2905         int xOffset = opt->direction == Qt::LeftToRight ? 2 : -1;
2906         QMatrix matrix;
2907         matrix.translate(opt->rect.center().x() + xOffset, opt->rect.center().y() + 2);
2908         QPainterPath path;
2909         switch(pe) {
2910         default:
2911         case PE_IndicatorArrowDown:
2912             break;
2913         case PE_IndicatorArrowUp:
2914             matrix.rotate(180);
2915             break;
2916         case PE_IndicatorArrowLeft:
2917             matrix.rotate(90);
2918             break;
2919         case PE_IndicatorArrowRight:
2920             matrix.rotate(-90);
2921             break;
2922         }
2923         path.moveTo(0, 5);
2924         path.lineTo(-4, -3);
2925         path.lineTo(4, -3);
2926         p->setMatrix(matrix);
2927         p->setPen(Qt::NoPen);
2928         p->setBrush(QColor(0, 0, 0, 135));
2929         p->drawPath(path);
2930         p->restore();
2931         break; }
2932     case PE_FrameTabBarBase:
2933         if (const QStyleOptionTabBarBaseV2 *tbb
2934                 = qstyleoption_cast<const QStyleOptionTabBarBaseV2 *>(opt)) {
2935             if (tbb->documentMode) {
2936                 p->save();
2937                 drawTabBase(p, tbb, w);
2938                 p->restore();
2939                 return;
2940             }
2941
2942             QRegion region(tbb->rect);
2943             region -= tbb->tabBarRect;
2944             p->save();
2945             p->setClipRegion(region);
2946             QStyleOptionTabWidgetFrame twf;
2947             twf.QStyleOption::operator=(*tbb);
2948             twf.shape  = tbb->shape;
2949             switch (getTabDirection(twf.shape)) {
2950             case kThemeTabNorth:
2951                 twf.rect = twf.rect.adjusted(0, 0, 0, 10);
2952                 break;
2953             case kThemeTabSouth:
2954                 twf.rect = twf.rect.adjusted(0, -10, 0, 0);
2955                 break;
2956             case kThemeTabWest:
2957                 twf.rect = twf.rect.adjusted(0, 0, 10, 0);
2958                 break;
2959             case kThemeTabEast:
2960                 twf.rect = twf.rect.adjusted(0, -10, 0, 0);
2961                 break;
2962             }
2963             proxy()->drawPrimitive(PE_FrameTabWidget, &twf, p, w);
2964             p->restore();
2965         }
2966         break;
2967     case PE_PanelTipLabel:
2968         p->fillRect(opt->rect, opt->palette.brush(QPalette::ToolTipBase));
2969         break;
2970     case PE_FrameGroupBox:
2971         if (const QStyleOptionFrame *groupBox = qstyleoption_cast<const QStyleOptionFrame *>(opt)) {
2972             const QStyleOptionFrameV2 *frame2 = qstyleoption_cast<const QStyleOptionFrameV2 *>(opt);
2973             if (frame2 && frame2->features & QStyleOptionFrameV2::Flat) {
2974                 QWindowsStyle::drawPrimitive(pe, groupBox, p, w);
2975             } else {
2976                 HIThemeGroupBoxDrawInfo gdi;
2977                 gdi.version = qt_mac_hitheme_version;
2978                 gdi.state = tds;
2979                 if (w && qobject_cast<QGroupBox *>(w->parentWidget()))
2980                     gdi.kind = kHIThemeGroupBoxKindSecondary;
2981                 else
2982                     gdi.kind = kHIThemeGroupBoxKindPrimary;
2983                 HIRect hirect = qt_hirectForQRect(opt->rect);
2984                 HIThemeDrawGroupBox(&hirect, &gdi, cg, kHIThemeOrientationNormal);
2985             }
2986         }
2987         break;
2988     case PE_IndicatorToolBarSeparator: {
2989             QPainterPath path;
2990             if (opt->state & State_Horizontal) {
2991                 int xpoint = opt->rect.center().x();
2992                 path.moveTo(xpoint + 0.5, opt->rect.top() + 1);
2993                 path.lineTo(xpoint + 0.5, opt->rect.bottom());
2994             } else {
2995                 int ypoint = opt->rect.center().y();
2996                 path.moveTo(opt->rect.left() + 2 , ypoint + 0.5);
2997                 path.lineTo(opt->rect.right() + 1, ypoint + 0.5);
2998             }
2999             QPainterPathStroker theStroker;
3000             theStroker.setCapStyle(Qt::FlatCap);
3001             theStroker.setDashPattern(QVector<qreal>() << 1 << 2);
3002             path = theStroker.createStroke(path);
3003             p->fillPath(path, QColor(0, 0, 0, 119));
3004         }
3005         break;
3006     case PE_FrameWindow:
3007         break;
3008     case PE_IndicatorDockWidgetResizeHandle: {
3009             // The docwidget resize handle is drawn as a one-pixel wide line.
3010             p->save();
3011             if (opt->state & State_Horizontal) {
3012                 p->setPen(QColor(160, 160, 160));
3013                 p->drawLine(opt->rect.topLeft(), opt->rect.topRight());
3014             } else {
3015                 p->setPen(QColor(145, 145, 145));
3016                 p->drawLine(opt->rect.topRight(), opt->rect.bottomRight());
3017             }
3018             p->restore();
3019         } break;
3020     case PE_IndicatorToolBarHandle: {
3021             p->save();
3022             QPainterPath path;
3023             int x = opt->rect.x() + 6;
3024             int y = opt->rect.y() + 5;
3025             static const int RectHeight = 2;
3026             if (opt->state & State_Horizontal) {
3027                 while (y < opt->rect.height() - RectHeight - 6) {
3028                     path.moveTo(x, y);
3029                     path.addRect(x, y, RectHeight, RectHeight);
3030                     y += 6;
3031                 }
3032             } else {
3033                 while (x < opt->rect.width() - RectHeight - 6) {
3034                     path.moveTo(x, y);
3035                     path.addRect(x, y, RectHeight, RectHeight);
3036                     x += 6;
3037                 }
3038             }
3039             p->setPen(Qt::NoPen);
3040             QColor dark = opt->palette.dark().color();
3041             dark.setAlphaF(0.75);
3042             QColor light = opt->palette.light().color();
3043             light.setAlphaF(0.6);
3044             p->fillPath(path, light);
3045             p->save();
3046             p->translate(1, 1);
3047             p->fillPath(path, dark);
3048             p->restore();
3049             p->translate(3, 3);
3050             p->fillPath(path, light);
3051             p->translate(1, 1);
3052             p->fillPath(path, dark);
3053             p->restore();
3054
3055             break;
3056         }
3057     case PE_IndicatorHeaderArrow:
3058         if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(opt)) {
3059             // In HITheme, up is down, down is up and hamburgers eat people.
3060             if (header->sortIndicator != QStyleOptionHeader::None)
3061                 proxy()->drawPrimitive(
3062                     (header->sortIndicator == QStyleOptionHeader::SortDown) ?
3063                     PE_IndicatorArrowUp : PE_IndicatorArrowDown, header, p, w);
3064         }
3065         break;
3066     case PE_IndicatorMenuCheckMark: {
3067         const int checkw = 8;
3068         const int checkh = 8;
3069         const int xoff = qMax(0, (opt->rect.width() - checkw) / 2);
3070         const int yoff = qMax(0, (opt->rect.width() - checkh) / 2);
3071         const int x1 = xoff + opt->rect.x();
3072         const int y1 = yoff + opt->rect.y() + checkw/2;
3073         const int x2 = xoff + opt->rect.x() + checkw/4;
3074         const int y2 = yoff + opt->rect.y() + checkh;
3075         const int x3 = xoff + opt->rect.x() + checkw;
3076         const int y3 = yoff + opt->rect.y();
3077
3078         QVector<QLineF> a(2);
3079         a << QLineF(x1, y1, x2, y2);
3080         a << QLineF(x2, y2, x3, y3);
3081         if (opt->palette.currentColorGroup() == QPalette::Active) {
3082             if (opt->state & State_On)
3083                 p->setPen(QPen(opt->palette.highlightedText().color(), 3));
3084             else
3085                 p->setPen(QPen(opt->palette.text().color(), 3));
3086         } else {
3087             p->setPen(QPen(QColor(100, 100, 100), 3));
3088         }
3089         p->save();
3090         p->setRenderHint(QPainter::Antialiasing);
3091         p->drawLines(a);
3092         p->restore();
3093         break; }
3094     case PE_IndicatorViewItemCheck:
3095     case PE_Q3CheckListExclusiveIndicator:
3096     case PE_Q3CheckListIndicator:
3097     case PE_IndicatorRadioButton:
3098     case PE_IndicatorCheckBox: {
3099         bool drawColorless = (!(opt->state & State_Active))
3100                               && opt->palette.currentColorGroup() == QPalette::Active;
3101         HIThemeButtonDrawInfo bdi;
3102         bdi.version = qt_mac_hitheme_version;
3103         bdi.state = tds;
3104         if (drawColorless && tds == kThemeStateInactive)
3105             bdi.state = kThemeStateActive;
3106         bdi.adornment = kThemeDrawIndicatorOnly;
3107         if (opt->state & State_HasFocus)
3108             bdi.adornment |= kThemeAdornmentFocus;
3109         bool isRadioButton = (pe == PE_Q3CheckListExclusiveIndicator
3110                               || pe == PE_IndicatorRadioButton);
3111         switch (d->aquaSizeConstrain(opt, w)) {
3112         case QAquaSizeUnknown:
3113         case QAquaSizeLarge:
3114             if (isRadioButton)
3115                 bdi.kind = kThemeRadioButton;
3116             else
3117                 bdi.kind = kThemeCheckBox;
3118             break;
3119         case QAquaSizeMini:
3120             if (isRadioButton)
3121                 bdi.kind = kThemeMiniRadioButton;
3122             else
3123                 bdi.kind = kThemeMiniCheckBox;
3124             break;
3125         case QAquaSizeSmall:
3126             if (isRadioButton)
3127                 bdi.kind = kThemeSmallRadioButton;
3128             else
3129                 bdi.kind = kThemeSmallCheckBox;
3130             break;
3131         }
3132         if (opt->state & State_NoChange)
3133             bdi.value = kThemeButtonMixed;
3134         else if (opt->state & State_On)
3135             bdi.value = kThemeButtonOn;
3136         else
3137             bdi.value = kThemeButtonOff;
3138         HIRect macRect;
3139         if (pe == PE_Q3CheckListExclusiveIndicator || pe == PE_Q3CheckListIndicator)
3140             macRect = qt_hirectForQRect(opt->rect);
3141         else
3142             macRect = qt_hirectForQRect(opt->rect);
3143         if (!drawColorless)
3144             HIThemeDrawButton(&macRect, &bdi, cg, kHIThemeOrientationNormal, 0);
3145         else
3146             d->drawColorlessButton(macRect, &bdi, p, opt);
3147         break; }
3148     case PE_FrameFocusRect:
3149         // Use the our own focus widget stuff.
3150         break;
3151     case PE_IndicatorBranch: {
3152         if (!(opt->state & State_Children))
3153             break;
3154         HIThemeButtonDrawInfo bi;
3155         bi.version = qt_mac_hitheme_version;
3156         bi.state = tds;
3157         if (tds == kThemeStateInactive && opt->palette.currentColorGroup() == QPalette::Active)
3158             bi.state = kThemeStateActive;
3159         if (opt->state & State_Sunken)
3160             bi.state |= kThemeStatePressed;
3161         bi.kind = kThemeDisclosureButton;
3162         if (opt->state & State_Open)
3163             bi.value = kThemeDisclosureDown;
3164         else
3165             bi.value = opt->direction == Qt::LeftToRight ? kThemeDisclosureRight : kThemeDisclosureLeft;
3166         bi.adornment = kThemeAdornmentNone;
3167         HIRect hirect = qt_hirectForQRect(opt->rect.adjusted(DisclosureOffset,0,-DisclosureOffset,0));
3168         HIThemeDrawButton(&hirect, &bi, cg, kHIThemeOrientationNormal, 0);
3169         break; }
3170
3171     case PE_Frame: {
3172         QPen oldPen = p->pen();
3173         p->setPen(opt->palette.base().color().darker(140));
3174         p->drawRect(opt->rect.adjusted(0, 0, -1, -1));
3175         p->setPen(opt->palette.base().color().darker(180));
3176         p->drawLine(opt->rect.topLeft(), opt->rect.topRight());
3177         p->setPen(oldPen);
3178         break; }
3179
3180     case PE_FrameLineEdit:
3181         if (const QStyleOptionFrame *frame = qstyleoption_cast<const QStyleOptionFrame *>(opt)) {
3182             if (frame->state & State_Sunken) {
3183                 QColor baseColor(frame->palette.background().color());
3184                 HIThemeFrameDrawInfo fdi;
3185                 fdi.version = qt_mac_hitheme_version;
3186                 fdi.state = tds;
3187                 SInt32 frame_size;
3188                 if (pe == PE_FrameLineEdit) {
3189                     fdi.kind = kHIThemeFrameTextFieldSquare;
3190                     GetThemeMetric(kThemeMetricEditTextFrameOutset, &frame_size);
3191                     if ((frame->state & State_ReadOnly) || !(frame->state & State_Enabled))
3192                         fdi.state = kThemeStateInactive;
3193                 } else {
3194                     baseColor = QColor(150, 150, 150); //hardcoded since no query function --Sam
3195                     fdi.kind = kHIThemeFrameListBox;
3196                     GetThemeMetric(kThemeMetricListBoxFrameOutset, &frame_size);
3197                 }
3198                 fdi.isFocused = (frame->state & State_HasFocus);
3199                 int lw = frame->lineWidth;
3200                 if (lw <= 0)
3201                     lw = proxy()->pixelMetric(PM_DefaultFrameWidth, frame, w);
3202                 { //clear to base color
3203                     p->save();
3204                     p->setPen(QPen(baseColor, lw));
3205                     p->setBrush(Qt::NoBrush);
3206                     p->drawRect(frame->rect);
3207                     p->restore();
3208                 }
3209                 HIRect hirect = qt_hirectForQRect(frame->rect,
3210                                                   QRect(frame_size, frame_size,
3211                                                         frame_size * 2, frame_size * 2));
3212
3213                 HIThemeDrawFrame(&hirect, &fdi, cg, kHIThemeOrientationNormal);
3214             } else {
3215                 QWindowsStyle::drawPrimitive(pe, opt, p, w);
3216             }
3217         }
3218         break;
3219     case PE_PanelLineEdit:
3220         QWindowsStyle::drawPrimitive(pe, opt, p, w);
3221         // Draw the focus frame for widgets other than QLineEdit (e.g. for line edits in Webkit).
3222         // Focus frame is drawn outside the rectangle passed in the option-rect.
3223         if (const QStyleOptionFrame *panel = qstyleoption_cast<const QStyleOptionFrame *>(opt)) {
3224             if ((opt->state & State_HasFocus) && !qobject_cast<const QLineEdit*>(w)) {
3225                 int vmargin = pixelMetric(QStyle::PM_FocusFrameVMargin);
3226                 int hmargin = pixelMetric(QStyle::PM_FocusFrameHMargin);
3227                 QStyleOptionFrame focusFrame = *panel;
3228                 focusFrame.rect = panel->rect.adjusted(-hmargin, -vmargin, hmargin, vmargin);
3229                 drawControl(CE_FocusFrame, &focusFrame, p, w);
3230             }
3231         }
3232
3233         break;
3234     case PE_FrameTabWidget:
3235         if (const QStyleOptionTabWidgetFrame *twf
3236                 = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) {
3237             HIRect hirect = qt_hirectForQRect(twf->rect);
3238             HIThemeTabPaneDrawInfo tpdi;
3239             tpdi.version = qt_mac_hitheme_tab_version();
3240             tpdi.state = tds;
3241             tpdi.direction = getTabDirection(twf->shape);
3242             tpdi.size = kHIThemeTabSizeNormal;
3243             tpdi.kind = kHIThemeTabKindNormal;
3244             tpdi.adornment = kHIThemeTabPaneAdornmentNormal;
3245             HIThemeDrawTabPane(&hirect, &tpdi, cg, kHIThemeOrientationNormal);
3246         }
3247         break;
3248     case PE_PanelScrollAreaCorner: {
3249         const QBrush brush(opt->palette.brush(QPalette::Base));
3250         p->fillRect(opt->rect, brush);
3251         p->setPen(QPen(QColor(217, 217, 217)));
3252         p->drawLine(opt->rect.topLeft(), opt->rect.topRight());
3253         p->drawLine(opt->rect.topLeft(), opt->rect.bottomLeft());
3254         } break;
3255     case PE_FrameStatusBarItem:
3256         break;
3257     case PE_IndicatorTabClose: {
3258         bool hover = (opt->state & State_MouseOver);
3259         bool selected = (opt->state & State_Selected);
3260         bool active = (opt->state & State_Active);
3261         drawTabCloseButton(p, hover, active, selected);
3262         } break;
3263     case PE_PanelStatusBar: {
3264         if (QSysInfo::MacintoshVersion <= QSysInfo::MV_10_4) {
3265             QWindowsStyle::drawPrimitive(pe, opt, p, w);
3266             break;
3267         }
3268         // Use the Leopard style only if the status bar is the status bar for a
3269         // QMainWindow with a unifed toolbar.
3270         if (w == 0 || w->parent() == 0 || qobject_cast<QMainWindow *>(w->parent()) == 0 ||
3271             qobject_cast<QMainWindow *>(w->parent())->unifiedTitleAndToolBarOnMac() == false ) {
3272             QWindowsStyle::drawPrimitive(pe, opt, p, w);
3273             break;
3274         }
3275
3276         // Fill the status bar with the titlebar gradient.
3277         QLinearGradient linearGrad(0, opt->rect.top(), 0, opt->rect.bottom());
3278         if (opt->state & QStyle::State_Active) {
3279             linearGrad.setColorAt(0, titlebarGradientActiveBegin);
3280             linearGrad.setColorAt(1, titlebarGradientActiveEnd);
3281         } else {
3282             linearGrad.setColorAt(0, titlebarGradientInactiveBegin);
3283             linearGrad.setColorAt(1, titlebarGradientInactiveEnd);
3284         }
3285         p->fillRect(opt->rect, linearGrad);
3286
3287         // Draw the black separator line at the top of the status bar.
3288         if (opt->state & QStyle::State_Active)
3289             p->setPen(titlebarSeparatorLineActive);
3290         else
3291             p->setPen(titlebarSeparatorLineInactive);
3292         p->drawLine(opt->rect.left(), opt->rect.top(), opt->rect.right(), opt->rect.top());
3293
3294         break;
3295     }
3296
3297     default:
3298         QWindowsStyle::drawPrimitive(pe, opt, p, w);
3299         break;
3300     }
3301 }
3302
3303 static inline QPixmap darkenPixmap(const QPixmap &pixmap)
3304 {
3305     QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32);
3306     int imgh = img.height();
3307     int imgw = img.width();
3308     int h, s, v, a;
3309     QRgb pixel;
3310     for (int y = 0; y < imgh; ++y) {
3311         for (int x = 0; x < imgw; ++x) {
3312             pixel = img.pixel(x, y);
3313             a = qAlpha(pixel);
3314             QColor hsvColor(pixel);
3315             hsvColor.getHsv(&h, &s, &v);
3316             s = qMin(100, s * 2);
3317             v = v / 2;
3318             hsvColor.setHsv(h, s, v);
3319             pixel = hsvColor.rgb();
3320             img.setPixel(x, y, qRgba(qRed(pixel), qGreen(pixel), qBlue(pixel), a));
3321         }
3322     }
3323     return QPixmap::fromImage(img);
3324 }
3325
3326
3327
3328 void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter *p,
3329                             const QWidget *w) const
3330 {
3331     ThemeDrawState tds = d->getDrawState(opt->state);
3332     QMacCGContext cg(p);
3333     switch (ce) {
3334     case CE_HeaderSection:
3335         if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(opt)) {
3336             HIThemeButtonDrawInfo bdi;
3337             bdi.version = qt_mac_hitheme_version;
3338             State flags = header->state;
3339             QRect ir = header->rect;
3340             bdi.kind = kThemeListHeaderButton;
3341             bdi.adornment = kThemeAdornmentNone;
3342             bdi.state = kThemeStateActive;
3343
3344             if (flags & State_On)
3345                 bdi.value = kThemeButtonOn;
3346             else
3347                 bdi.value = kThemeButtonOff;
3348
3349             if (header->orientation == Qt::Horizontal){
3350                 switch (header->position) {
3351                 case QStyleOptionHeader::Beginning:
3352                     ir.adjust(-1, -1, 0, 0);
3353                     break;
3354                 case QStyleOptionHeader::Middle:
3355                     ir.adjust(-1, -1, 0, 0);
3356                     break;
3357                 case QStyleOptionHeader::OnlyOneSection:
3358                 case QStyleOptionHeader::End:
3359                     ir.adjust(-1, -1, 1, 0);
3360                     break;
3361                 default:
3362                     break;
3363                 }
3364
3365                 if (header->position != QStyleOptionHeader::Beginning
3366                     && header->position != QStyleOptionHeader::OnlyOneSection) {
3367                     bdi.adornment = header->direction == Qt::LeftToRight
3368                         ? kThemeAdornmentHeaderButtonLeftNeighborSelected
3369                         : kThemeAdornmentHeaderButtonRightNeighborSelected;
3370                 }
3371             }
3372
3373             if (flags & State_Active) {
3374                 if (!(flags & State_Enabled))
3375                     bdi.state = kThemeStateUnavailable;
3376                 else if (flags & State_Sunken)
3377                     bdi.state = kThemeStatePressed;
3378             } else {
3379                 if (flags & State_Enabled)
3380                     bdi.state = kThemeStateInactive;
3381                 else
3382                     bdi.state = kThemeStateUnavailableInactive;
3383             }
3384
3385             if (header->sortIndicator != QStyleOptionHeader::None) {
3386                 bdi.value = kThemeButtonOn;
3387                 if (header->sortIndicator == QStyleOptionHeader::SortDown)
3388                     bdi.adornment = kThemeAdornmentHeaderButtonSortUp;
3389             }
3390             if (flags & State_HasFocus)
3391                 bdi.adornment = kThemeAdornmentFocus;
3392
3393             ir = visualRect(header->direction, header->rect, ir);
3394             HIRect bounds = qt_hirectForQRect(ir);
3395
3396             bool noVerticalHeader = true;
3397             if (w)
3398                 if (const QTableView *table = qobject_cast<const QTableView *>(w->parentWidget()))
3399                     noVerticalHeader = !table->verticalHeader()->isVisible();
3400
3401             bool drawTopBorder = header->orientation == Qt::Horizontal;
3402             bool drawLeftBorder = header->orientation == Qt::Vertical
3403                 || header->position == QStyleOptionHeader::OnlyOneSection
3404                 || (header->position == QStyleOptionHeader::Beginning && noVerticalHeader);
3405             d->drawTableHeader(bounds, drawTopBorder, drawLeftBorder, bdi, p);
3406         }
3407         break;
3408     case CE_HeaderLabel:
3409         if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(opt)) {
3410             QRect textr = header->rect;
3411             if (!header->icon.isNull()) {
3412                 QIcon::Mode mode = QIcon::Disabled;
3413                 if (opt->state & State_Enabled)
3414                     mode = QIcon::Normal;
3415                 QPixmap pixmap = header->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize), mode);
3416
3417                 QRect pixr = header->rect;
3418                 pixr.setY(header->rect.center().y() - (pixmap.height() - 1) / 2);
3419                 proxy()->drawItemPixmap(p, pixr, Qt::AlignVCenter, pixmap);
3420                 textr.translate(pixmap.width() + 2, 0);
3421             }
3422
3423             proxy()->drawItemText(p, textr, header->textAlignment | Qt::AlignVCenter, header->palette,
3424                                        header->state & State_Enabled, header->text, QPalette::ButtonText);
3425         }
3426         break;
3427     case CE_ToolButtonLabel:
3428         if (const QStyleOptionToolButton *tb = qstyleoption_cast<const QStyleOptionToolButton *>(opt)) {
3429             QStyleOptionToolButton myTb = *tb;
3430             myTb.state &= ~State_AutoRaise;
3431             if (w && qobject_cast<QToolBar *>(w->parentWidget())) {
3432                 QRect cr = tb->rect;
3433                 int shiftX = 0;
3434                 int shiftY = 0;
3435                 bool needText = false;
3436                 int alignment = 0;
3437                 bool down = tb->state & (State_Sunken | State_On);
3438                 if (down) {
3439                     shiftX = proxy()->pixelMetric(PM_ButtonShiftHorizontal, tb, w);
3440                     shiftY = proxy()->pixelMetric(PM_ButtonShiftVertical, tb, w);
3441                 }
3442                 // The down state is special for QToolButtons in a toolbar on the Mac
3443                 // The text is a bit bolder and gets a drop shadow and the icons are also darkened.
3444                 // This doesn't really fit into any particular case in QIcon, so we
3445                 // do the majority of the work ourselves.
3446                 if (!(tb->features & QStyleOptionToolButton::Arrow)) {
3447                     Qt::ToolButtonStyle tbstyle = tb->toolButtonStyle;
3448                     if (tb->icon.isNull() && !tb->text.isEmpty())
3449                         tbstyle = Qt::ToolButtonTextOnly;
3450
3451                     switch (tbstyle) {
3452                     case Qt::ToolButtonTextOnly: {
3453                         needText = true;
3454                         alignment = Qt::AlignCenter;
3455                         break; }
3456                     case Qt::ToolButtonIconOnly:
3457                     case Qt::ToolButtonTextBesideIcon:
3458                     case Qt::ToolButtonTextUnderIcon: {
3459                         QRect pr = cr;
3460                         QIcon::Mode iconMode = (tb->state & State_Enabled) ? QIcon::Normal
3461                                                                             : QIcon::Disabled;
3462                         QIcon::State iconState = (tb->state & State_On) ? QIcon::On
3463                                                                          : QIcon::Off;
3464                         QPixmap pixmap = tb->icon.pixmap(tb->rect.size().boundedTo(tb->iconSize), iconMode, iconState);
3465
3466                         // Draw the text if it's needed.
3467                         if (tb->toolButtonStyle != Qt::ToolButtonIconOnly) {
3468                             needText = true;
3469                             if (tb->toolButtonStyle == Qt::ToolButtonTextUnderIcon) {
3470                                 QMainWindow *mw = qobject_cast<QMainWindow *>(w->window());
3471                                 if (mw && mw->unifiedTitleAndToolBarOnMac()) {
3472                                     pr.setHeight(pixmap.size().height());
3473                                     cr.adjust(0, pr.bottom() + 1, 0, 1);
3474                                 } else {
3475                                     pr.setHeight(pixmap.size().height() + 6);
3476                                     cr.adjust(0, pr.bottom(), 0, -3);
3477                                 }       
3478                                 alignment |= Qt::AlignCenter;
3479                             } else {
3480                                 pr.setWidth(pixmap.width() + 8);
3481                                 cr.adjust(pr.right(), 0, 0, 0);
3482                                 alignment |= Qt::AlignLeft | Qt::AlignVCenter;
3483                             }
3484                         }
3485                         if (opt->state & State_Sunken) {
3486                             pr.translate(shiftX, shiftY);
3487                             pixmap = darkenPixmap(pixmap);
3488                         }
3489                         proxy()->drawItemPixmap(p, pr, Qt::AlignCenter, pixmap);
3490                         break; }
3491                     default:
3492                         Q_ASSERT(false);
3493                         break;
3494                     }
3495
3496                     if (needText) {
3497                         QPalette pal = tb->palette;
3498                         QPalette::ColorRole role = QPalette::NoRole;
3499                         if (!proxy()->styleHint(SH_UnderlineShortcut, tb, w))
3500                             alignment |= Qt::TextHideMnemonic;
3501                         if (down)
3502                             cr.translate(shiftX, shiftY);
3503                         if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5
3504                             && (tbstyle == Qt::ToolButtonTextOnly
3505                                 || (tbstyle != Qt::ToolButtonTextOnly && !down))) {
3506                             QPen pen = p->pen();
3507                             QColor light = down ? Qt::black : Qt::white;
3508                             light.setAlphaF(0.375f);
3509                             p->setPen(light);
3510                             p->drawText(cr.adjusted(0, 1, 0, 1), alignment, tb->text);
3511                             p->setPen(pen);
3512                             if (down && tbstyle == Qt::ToolButtonTextOnly) {
3513                                 pal = QApplication::palette("QMenu");
3514                                 pal.setCurrentColorGroup(tb->palette.currentColorGroup());
3515                                 role = QPalette::HighlightedText;
3516                             }
3517                         }
3518                         proxy()->drawItemText(p, cr, alignment, pal,
3519                                               tb->state & State_Enabled, tb->text, role);
3520                         if (QSysInfo::MacintoshVersion < QSysInfo::MV_10_5 &&
3521                             (tb->state & State_Sunken)) {
3522                             // Draw a "drop shadow" in earlier versions.
3523                             proxy()->drawItemText(p, cr.adjusted(0, 1, 0, 1), alignment,
3524                                                   tb->palette, tb->state & State_Enabled, tb->text);
3525                         }
3526                     }
3527                 } else {
3528                     QWindowsStyle::drawControl(ce, &myTb, p, w);
3529                 }
3530             } else {
3531                 QWindowsStyle::drawControl(ce, &myTb, p, w);
3532             }
3533         }
3534         break;
3535     case CE_ToolBoxTabShape:
3536         QCommonStyle::drawControl(ce, opt, p, w);
3537         break;
3538     case CE_PushButtonBevel:
3539         if (const QStyleOptionButton *btn = ::qstyleoption_cast<const QStyleOptionButton *>(opt)) {
3540             if (!(btn->state & (State_Raised | State_Sunken | State_On)))
3541                 break;
3542
3543             if (btn->features & QStyleOptionButton::CommandLinkButton) {
3544                 QWindowsStyle::drawControl(ce, opt, p, w);
3545                 break;
3546             }
3547
3548             HIThemeButtonDrawInfo bdi;
3549             d->initHIThemePushButton(btn, w, tds, &bdi);
3550             if (btn->features & QStyleOptionButton::DefaultButton
3551                     && d->animatable(QMacStylePrivate::AquaPushButton, w)) {
3552                 bdi.adornment |= kThemeAdornmentDefault;
3553                 bdi.animation.time.start = d->defaultButtonStart;
3554                 bdi.animation.time.current = CFAbsoluteTimeGetCurrent();
3555                 if (d->timerID <= -1)
3556                     QMetaObject::invokeMethod(d, "startAnimationTimer", Qt::QueuedConnection);
3557             }
3558             // Unlike Carbon, we want the button to always be drawn inside its bounds.
3559             // Therefore, make the button a bit smaller, so that even if it got focus,
3560             // the focus 'shadow' will be inside.
3561             HIRect newRect = qt_hirectForQRect(btn->rect);
3562             if (bdi.kind == kThemePushButton || bdi.kind == kThemePushButtonSmall) {
3563                 newRect.origin.x += QMacStylePrivate::PushButtonLeftOffset;
3564                 newRect.origin.y += QMacStylePrivate::PushButtonTopOffset;
3565                 newRect.size.width -= QMacStylePrivate::PushButtonRightOffset;
3566                 newRect.size.height -= QMacStylePrivate::PushButtonBottomOffset;
3567             } else if (bdi.kind == kThemePushButtonMini) {
3568                 newRect.origin.x += QMacStylePrivate::PushButtonLeftOffset - 2;
3569                 newRect.origin.y += QMacStylePrivate::PushButtonTopOffset;
3570                 newRect.size.width -= QMacStylePrivate::PushButtonRightOffset - 4;
3571             }
3572             HIThemeDrawButton(&newRect, &bdi, cg, kHIThemeOrientationNormal, 0);
3573
3574             if (btn->features & QStyleOptionButton::HasMenu) {
3575                 int mbi = proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator, btn, w);
3576                 QRect ir = btn->rect;
3577                 HIRect arrowRect = CGRectMake(ir.right() - mbi - QMacStylePrivate::PushButtonRightOffset,
3578                                               ir.height() / 2 - 4, mbi, ir.height() / 2);
3579                 bool drawColorless = btn->palette.currentColorGroup() == QPalette::Active;
3580                 if (drawColorless && tds == kThemeStateInactive)
3581                     tds = kThemeStateActive;
3582
3583                 HIThemePopupArrowDrawInfo pdi;
3584                 pdi.version = qt_mac_hitheme_version;
3585                 pdi.state = tds;
3586                 pdi.orientation = kThemeArrowDown;
3587                 if (arrowRect.size.width < 8.)
3588                     pdi.size = kThemeArrow5pt;
3589                 else
3590                     pdi.size = kThemeArrow9pt;
3591                 HIThemeDrawPopupArrow(&arrowRect, &pdi, cg, kHIThemeOrientationNormal);
3592             }
3593         }
3594         break;
3595     case CE_PushButtonLabel:
3596         if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
3597             // We really don't want the label to be drawn the same as on
3598             // windows style if it has an icon and text, then it should be more like a
3599             // tab. So, cheat a little here. However, if it *is* only an icon
3600             // the windows style works great, so just use that implementation.
3601             bool hasMenu = btn->features & QStyleOptionButton::HasMenu;
3602             bool hasIcon = !btn->icon.isNull();
3603             bool hasText = !btn->text.isEmpty();
3604             if (!hasIcon && !hasMenu) {
3605                 // ### this is really overly difficult, simplify.
3606                 // It basically tries to get the right font for "small" and "mini" icons.
3607                 QFont oldFont = p->font();
3608                 QFont newFont = qt_app_fonts_hash()->value("QPushButton", QFont());
3609                 ThemeFontID themeId = kThemePushButtonFont;
3610                 if (oldFont == newFont) {  // Yes, use HITheme to draw the text for small sizes.
3611                     switch (d->aquaSizeConstrain(opt, w)) {
3612                     default:
3613                         break;
3614                     case QAquaSizeSmall:
3615                         themeId = kThemeSmallSystemFont;
3616                         break;
3617                     case QAquaSizeMini:
3618                         themeId = kThemeMiniSystemFont;
3619                         break;
3620                     }
3621                 }
3622                 if (themeId == kThemePushButtonFont) {
3623                     QWindowsStyle::drawControl(ce, btn, p, w);
3624                 } else {
3625                     p->save();
3626                     CGContextSetShouldAntialias(cg, true);
3627                     CGContextSetShouldSmoothFonts(cg, true);
3628                     HIThemeTextInfo tti;
3629                     tti.version = qt_mac_hitheme_version;
3630                     tti.state = tds;
3631                     QColor textColor = btn->palette.buttonText().color();
3632                     CGFloat colorComp[] = { textColor.redF(), textColor.greenF(),
3633                                           textColor.blueF(), textColor.alphaF() };
3634                     CGContextSetFillColorSpace(cg, qt_mac_genericColorSpace());
3635                     CGContextSetFillColor(cg, colorComp);
3636                     tti.fontID = themeId;
3637                     tti.horizontalFlushness = kHIThemeTextHorizontalFlushCenter;
3638                     tti.verticalFlushness = kHIThemeTextVerticalFlushCenter;
3639                     tti.options = kHIThemeTextBoxOptionNone;
3640                     tti.truncationPosition = kHIThemeTextTruncationNone;
3641                     tti.truncationMaxLines = 1 + btn->text.count(QLatin1Char('\n'));
3642                     QCFString buttonText = qt_mac_removeMnemonics(btn->text);
3643                     QRect r = btn->rect;
3644                     HIRect bounds = qt_hirectForQRect(r);
3645                     HIThemeDrawTextBox(buttonText, &bounds, &tti,
3646                                        cg, kHIThemeOrientationNormal);
3647                     p->restore();
3648                 }
3649             } else {
3650                 if (hasIcon && !hasText) {
3651                     QWindowsStyle::drawControl(ce, btn, p, w);
3652                 } else {
3653                     QRect freeContentRect = btn->rect;
3654                     QRect textRect = itemTextRect(
3655                         btn->fontMetrics, freeContentRect, Qt::AlignCenter, btn->state & State_Enabled, btn->text);
3656                     if (hasMenu)
3657                         textRect.adjust(-1, 0, -1, 0);
3658                     // Draw the icon:
3659                     if (hasIcon) {
3660                         int contentW = textRect.width();
3661                         if (hasMenu)
3662                             contentW += proxy()->pixelMetric(PM_MenuButtonIndicator) + 4;
3663                         QIcon::Mode mode = btn->state & State_Enabled ? QIcon::Normal : QIcon::Disabled;
3664                         if (mode == QIcon::Normal && btn->state & State_HasFocus)
3665                             mode = QIcon::Active;
3666                         // Decide if the icon is should be on or off:
3667                         QIcon::State state = QIcon::Off;
3668                         if (btn->state & State_On)
3669                             state = QIcon::On;
3670                         QPixmap pixmap = btn->icon.pixmap(btn->iconSize, mode, state);
3671                         contentW += pixmap.width() + QMacStylePrivate::PushButtonContentPadding;
3672                         int iconLeftOffset = freeContentRect.x() + (freeContentRect.width() - contentW) / 2;
3673                         int iconTopOffset = freeContentRect.y() + (freeContentRect.height() - pixmap.height()) / 2;
3674                         QRect iconDestRect(iconLeftOffset, iconTopOffset, pixmap.width(), pixmap.height());
3675                         QRect visualIconDestRect = visualRect(btn->direction, freeContentRect, iconDestRect);
3676                         proxy()->drawItemPixmap(p, visualIconDestRect, Qt::AlignLeft | Qt::AlignVCenter, pixmap);
3677                         int newOffset = iconDestRect.x() + iconDestRect.width()
3678                                         + QMacStylePrivate::PushButtonContentPadding - textRect.x();
3679                         textRect.adjust(newOffset, 0, newOffset, 0);
3680                     }
3681                     // Draw the text:
3682                     if (hasText) {
3683                         textRect = visualRect(btn->direction, freeContentRect, textRect);
3684                         proxy()->drawItemText(p, textRect, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, btn->palette,
3685                                                    (btn->state & State_Enabled), btn->text, QPalette::ButtonText);
3686                     }
3687                 }
3688             }
3689         }
3690         break;
3691     case CE_ComboBoxLabel:
3692         if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) {
3693             QStyleOptionComboBox comboCopy = *cb;
3694             comboCopy.direction = Qt::LeftToRight;
3695             QWindowsStyle::drawControl(CE_ComboBoxLabel, &comboCopy, p, w);
3696         }
3697         break;
3698     case CE_TabBarTabShape:
3699         if (const QStyleOptionTab *tabOpt = qstyleoption_cast<const QStyleOptionTab *>(opt)) {
3700
3701             if (const QStyleOptionTabV3 *tabOptV3 = qstyleoption_cast<const QStyleOptionTabV3 *>(opt)) {
3702                 if (tabOptV3->documentMode) {
3703                     p->save();
3704                     QRect tabRect = tabOptV3->rect;
3705                     drawTabShape(p, tabOptV3);
3706                     p->restore();
3707                     return;
3708                 }
3709             }
3710             HIThemeTabDrawInfo tdi;
3711             tdi.version = 1;
3712             tdi.style = kThemeTabNonFront;
3713             tdi.direction = getTabDirection(tabOpt->shape);
3714             switch (d->aquaSizeConstrain(opt, w)) {
3715             default:
3716             case QAquaSizeUnknown:
3717             case QAquaSizeLarge:
3718                 tdi.size = kHIThemeTabSizeNormal;
3719                 break;
3720             case QAquaSizeSmall:
3721                 tdi.size = kHIThemeTabSizeSmall;
3722                 break;
3723             case QAquaSizeMini:
3724                 tdi.size = kHIThemeTabSizeMini;
3725                 break;
3726             }
3727             bool verticalTabs = tdi.direction == kThemeTabWest || tdi.direction == kThemeTabEast;
3728             QRect tabRect = tabOpt->rect;
3729
3730             bool selected = tabOpt->state & State_Selected;
3731             if (selected) {
3732                 if (!(tabOpt->state & State_Active))
3733                     tdi.style = kThemeTabFrontUnavailable;
3734                 else if (!(tabOpt->state & State_Enabled))
3735                     tdi.style = kThemeTabFrontInactive;
3736                 else
3737                     tdi.style = kThemeTabFront;
3738             } else if (!(tabOpt->state & State_Active)) {
3739                 tdi.style = kThemeTabNonFrontUnavailable;
3740             } else if (!(tabOpt->state & State_Enabled)) {
3741                 tdi.style = kThemeTabNonFrontInactive;
3742             } else if (tabOpt->state & State_Sunken) {
3743                 tdi.style = kThemeTabFrontInactive; // (should be kThemeTabNonFrontPressed)
3744             }
3745             if (tabOpt->state & State_HasFocus)
3746                 tdi.adornment = kHIThemeTabAdornmentFocus;
3747             else
3748                 tdi.adornment = kHIThemeTabAdornmentNone;
3749             tdi.kind = kHIThemeTabKindNormal;
3750             if (!verticalTabs)
3751                 tabRect.setY(tabRect.y() - 1);
3752             else
3753                 tabRect.setX(tabRect.x() - 1);
3754             QStyleOptionTab::TabPosition tp = tabOpt->position;
3755             QStyleOptionTab::SelectedPosition sp = tabOpt->selectedPosition;
3756             if (tabOpt->direction == Qt::RightToLeft && !verticalTabs) {
3757                 if (sp == QStyleOptionTab::NextIsSelected)
3758                     sp = QStyleOptionTab::PreviousIsSelected;
3759                 else if (sp == QStyleOptionTab::PreviousIsSelected)
3760                     sp = QStyleOptionTab::NextIsSelected;
3761                 switch (tp) {
3762                 case QStyleOptionTab::Beginning:
3763                     tp = QStyleOptionTab::End;
3764                     break;
3765                 case QStyleOptionTab::End:
3766                     tp = QStyleOptionTab::Beginning;
3767                     break;
3768                 default:
3769                     break;
3770                 }
3771             }
3772             bool stretchTabs = (!verticalTabs && tabRect.height() > 22) || (verticalTabs && tabRect.width() > 22);
3773
3774             switch (tp) {
3775             case QStyleOptionTab::Beginning:
3776                 tdi.position = kHIThemeTabPositionFirst;
3777                 if (sp != QStyleOptionTab::NextIsSelected || stretchTabs)
3778                     tdi.adornment |= kHIThemeTabAdornmentTrailingSeparator;
3779                 break;
3780             case QStyleOptionTab::Middle:
3781                 tdi.position = kHIThemeTabPositionMiddle;
3782                 if (selected)
3783                     tdi.adornment |= kHIThemeTabAdornmentLeadingSeparator;
3784                 if (sp != QStyleOptionTab::NextIsSelected || stretchTabs)  // Also when we're selected.
3785                     tdi.adornment |= kHIThemeTabAdornmentTrailingSeparator;
3786                 break;
3787             case QStyleOptionTab::End:
3788                 tdi.position = kHIThemeTabPositionLast;
3789                 if (selected)
3790                     tdi.adornment |= kHIThemeTabAdornmentLeadingSeparator;
3791                 break;
3792             case QStyleOptionTab::OnlyOneTab:
3793                 tdi.position = kHIThemeTabPositionOnly;
3794                 break;
3795             }
3796             // HITheme doesn't stretch its tabs. Therefore we have to cheat and do the job ourselves.
3797             if (stretchTabs) {
3798                 HIRect hirect = CGRectMake(0, 0, 23, 23);
3799                 QPixmap pm(23, 23);
3800                 pm.fill(Qt::transparent);
3801                 {
3802                     QMacCGContext pmcg(&pm);
3803                     HIThemeDrawTab(&hirect, &tdi, pmcg, kHIThemeOrientationNormal, 0);
3804                 }
3805                 QStyleHelper::drawBorderPixmap(pm, p, tabRect, 7, 7, 7, 7);
3806             } else {
3807                 HIRect hirect = qt_hirectForQRect(tabRect);
3808                 HIThemeDrawTab(&hirect, &tdi, cg, kHIThemeOrientationNormal, 0);
3809             }
3810         }
3811         break;
3812     case CE_TabBarTabLabel:
3813         if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) {
3814             QStyleOptionTabV3 myTab = *tab;
3815             ThemeTabDirection ttd = getTabDirection(myTab.shape);
3816             bool verticalTabs = ttd == kThemeTabWest || ttd == kThemeTabEast;
3817
3818             // Check to see if we use have the same as the system font
3819             // (QComboMenuItem is internal and should never be seen by the
3820             // outside world, unless they read the source, in which case, it's
3821             // their own fault).
3822             bool nonDefaultFont = p->font() != qt_app_fonts_hash()->value("QComboMenuItem");
3823             if (verticalTabs || nonDefaultFont || !tab->icon.isNull()
3824                 || !myTab.leftButtonSize.isNull() || !myTab.rightButtonSize.isNull()) {
3825                 int heightOffset = 0;
3826                 if (verticalTabs) {
3827                     heightOffset = -1;
3828                 } else if (nonDefaultFont) {
3829                     if (p->fontMetrics().height() == myTab.rect.height())
3830                         heightOffset = 2;
3831                 }
3832                 myTab.rect.setHeight(myTab.rect.height() + heightOffset);
3833
3834                 if (myTab.documentMode) {
3835                     p->save();
3836                     rotateTabPainter(p, myTab.shape, myTab.rect);
3837
3838                     QPalette np = tab->palette;
3839                     np.setColor(QPalette::WindowText, QColor(255, 255, 255, 75));
3840                     QRect nr = subElementRect(SE_TabBarTabText, opt, w);
3841                     nr.moveTop(-1);
3842                     int alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextHideMnemonic;
3843                     proxy()->drawItemText(p, nr, alignment, np, tab->state & State_Enabled,
3844                                                tab->text, QPalette::WindowText);
3845                     p->restore();
3846                 }
3847
3848                 QCommonStyle::drawControl(ce, &myTab, p, w);
3849             } else {
3850                 p->save();
3851                 CGContextSetShouldAntialias(cg, true);
3852                 CGContextSetShouldSmoothFonts(cg, true);
3853                 HIThemeTextInfo tti;
3854                 tti.version = qt_mac_hitheme_version;
3855                 tti.state = tds;
3856                 QColor textColor = myTab.palette.windowText().color();
3857                 CGFloat colorComp[] = { textColor.redF(), textColor.greenF(),
3858                                         textColor.blueF(), textColor.alphaF() };
3859                 CGContextSetFillColorSpace(cg, qt_mac_genericColorSpace());
3860                 CGContextSetFillColor(cg, colorComp);
3861                 switch (d->aquaSizeConstrain(opt, w)) {
3862                 default:
3863                 case QAquaSizeUnknown:
3864                 case QAquaSizeLarge:
3865                     tti.fontID = kThemeSystemFont;
3866                     break;
3867                 case QAquaSizeSmall:
3868                     tti.fontID = kThemeSmallSystemFont;
3869                     break;
3870                 case QAquaSizeMini:
3871                     tti.fontID = kThemeMiniSystemFont;
3872                     break;
3873                 }
3874                 tti.horizontalFlushness = kHIThemeTextHorizontalFlushCenter;
3875                 tti.verticalFlushness = kHIThemeTextVerticalFlushCenter;
3876                 tti.options = verticalTabs ? kHIThemeTextBoxOptionStronglyVertical : kHIThemeTextBoxOptionNone;
3877                 tti.truncationPosition = kHIThemeTextTruncationNone;
3878                 tti.truncationMaxLines = 1 + myTab.text.count(QLatin1Char('\n'));
3879                 QCFString tabText = qt_mac_removeMnemonics(myTab.text);
3880                 QRect r = myTab.rect.adjusted(0, 0, 0, -1);
3881                 HIRect bounds = qt_hirectForQRect(r);
3882                 HIThemeDrawTextBox(tabText, &bounds, &tti, cg, kHIThemeOrientationNormal);
3883                 p->restore();
3884             }
3885         }
3886         break;
3887     case CE_DockWidgetTitle:
3888         if (const QDockWidget *dockWidget = qobject_cast<const QDockWidget *>(w)) {
3889             bool floating = dockWidget->isFloating();
3890             if (floating) {
3891                 ThemeDrawState tds = d->getDrawState(opt->state);
3892                 HIThemeWindowDrawInfo wdi;
3893                 wdi.version = qt_mac_hitheme_version;
3894                 wdi.state = tds;
3895                 wdi.windowType = kThemeMovableDialogWindow;
3896                 wdi.titleHeight = opt->rect.height();
3897                 wdi.titleWidth = opt->rect.width();
3898                 wdi.attributes = 0;
3899
3900                 HIRect titleBarRect;
3901                 HIRect tmpRect = qt_hirectForQRect(opt->rect);
3902                 {
3903                     QCFType<HIShapeRef> titleRegion;
3904                     QRect newr = opt->rect.adjusted(0, 0, 2, 0);
3905                     HIThemeGetWindowShape(&tmpRect, &wdi, kWindowTitleBarRgn, &titleRegion);
3906                     ptrHIShapeGetBounds(titleRegion, &tmpRect);
3907                     newr.translate(newr.x() - int(tmpRect.origin.x), newr.y() - int(tmpRect.origin.y));
3908                     titleBarRect = qt_hirectForQRect(newr);
3909                 }
3910                 QMacCGContext cg(p);
3911                 HIThemeDrawWindowFrame(&titleBarRect, &wdi, cg, kHIThemeOrientationNormal, 0);
3912             } else {
3913                 // fill title bar background
3914                 QLinearGradient linearGrad(0, opt->rect.top(), 0, opt->rect.bottom());
3915                 linearGrad.setColorAt(0, mainWindowGradientBegin);
3916                 linearGrad.setColorAt(1, mainWindowGradientEnd);
3917                 p->fillRect(opt->rect, linearGrad);
3918
3919                 // draw horizontal lines at top and bottom
3920                 p->save();
3921                 p->setPen(mainWindowGradientBegin.lighter(114));
3922                 p->drawLine(opt->rect.topLeft(), opt->rect.topRight());
3923                 p->setPen(mainWindowGradientEnd.darker(114));
3924                 p->drawLine(opt->rect.bottomLeft(), opt->rect.bottomRight());
3925                 p->restore();
3926             }
3927         }
3928
3929         // Draw the text...
3930         if (const QStyleOptionDockWidget *dwOpt = qstyleoption_cast<const QStyleOptionDockWidget *>(opt)) {
3931             if (!dwOpt->title.isEmpty()) {
3932                 const QStyleOptionDockWidgetV2 *v2
3933                     = qstyleoption_cast<const QStyleOptionDockWidgetV2*>(dwOpt);
3934                 bool verticalTitleBar = v2 == 0 ? false : v2->verticalTitleBar;
3935
3936                 QRect titleRect = subElementRect(SE_DockWidgetTitleBarText, opt, w);
3937                 if (verticalTitleBar) {
3938                     QRect rect = dwOpt->rect;
3939                     QRect r = rect;
3940                     QSize s = r.size();
3941                     s.transpose();
3942                     r.setSize(s);
3943
3944                     titleRect = QRect(r.left() + rect.bottom()
3945                                         - titleRect.bottom(),
3946                                     r.top() + titleRect.left() - rect.left(),
3947                                     titleRect.height(), titleRect.width());
3948
3949                     p->translate(r.left(), r.top() + r.width());
3950                     p->rotate(-90);
3951                     p->translate(-r.left(), -r.top());
3952                 }
3953
3954                 QFont oldFont = p->font();
3955                 p->setFont(qt_app_fonts_hash()->value("QToolButton", p->font()));
3956                 QString text = p->fontMetrics().elidedText(dwOpt->title, Qt::ElideRight,
3957                     titleRect.width());
3958                 drawItemText(p, titleRect,
3959                               Qt::AlignCenter | Qt::TextShowMnemonic, dwOpt->palette,
3960                               dwOpt->state & State_Enabled, text,
3961                               QPalette::WindowText);
3962                 p->setFont(oldFont);
3963             }
3964         }
3965         break;
3966     case CE_FocusFrame: {
3967         int xOff = proxy()->pixelMetric(PM_FocusFrameHMargin, opt, w) + 1;
3968         int yOff = proxy()->pixelMetric(PM_FocusFrameVMargin, opt, w) + 1;
3969         HIRect hirect = CGRectMake(xOff+opt->rect.x(), yOff+opt->rect.y(), opt->rect.width() - 2 * xOff,
3970                                    opt->rect.height() - 2 * yOff);
3971         HIThemeDrawFocusRect(&hirect, true, QMacCGContext(p), kHIThemeOrientationNormal);
3972         break; }
3973     case CE_MenuItem:
3974     case CE_MenuEmptyArea:
3975         if (const QStyleOptionMenuItem *mi = qstyleoption_cast<const QStyleOptionMenuItem *>(opt)) {
3976             p->fillRect(mi->rect, opt->palette.background());
3977             QAquaWidgetSize widgetSize = d->aquaSizeConstrain(opt, w);
3978             int tabwidth = mi->tabWidth;
3979             int maxpmw = mi->maxIconWidth;
3980             bool active = mi->state & State_Selected;
3981             bool enabled = mi->state & State_Enabled;
3982             HIRect menuRect = qt_hirectForQRect(mi->menuRect);
3983             HIRect itemRect = qt_hirectForQRect(mi->rect);
3984             HIThemeMenuItemDrawInfo mdi;
3985             mdi.version = qt_mac_hitheme_version;
3986             mdi.itemType = kThemeMenuItemPlain;
3987             if (!mi->icon.isNull())
3988                 mdi.itemType |= kThemeMenuItemHasIcon;
3989             if (mi->menuItemType == QStyleOptionMenuItem::SubMenu)
3990                 mdi.itemType |= kThemeMenuItemHierarchical | kThemeMenuItemHierBackground;
3991             else
3992                 mdi.itemType |= kThemeMenuItemPopUpBackground;
3993             if (enabled)
3994                 mdi.state = kThemeMenuActive;
3995             else
3996                 mdi.state = kThemeMenuDisabled;
3997             if (active)
3998                 mdi.state |= kThemeMenuSelected;
3999             QRect contentRect;
4000             if (mi->menuItemType == QStyleOptionMenuItem::Separator) {
4001                 // First arg should be &menurect, but wacky stuff happens then.
4002                 HIThemeDrawMenuSeparator(&itemRect, &itemRect, &mdi,
4003                                          cg, kHIThemeOrientationNormal);
4004                 break;
4005             } else {
4006                 HIRect cr;
4007                 bool needAlpha = mi->palette.color(QPalette::Button) == Qt::transparent;
4008                 if (needAlpha) {
4009                     needAlpha = true;
4010                     CGContextSaveGState(cg);
4011                     CGContextSetAlpha(cg, 0.0);
4012                 }
4013                 HIThemeDrawMenuItem(&menuRect, &itemRect, &mdi,
4014                                     cg, kHIThemeOrientationNormal, &cr);
4015                 if (needAlpha)
4016                     CGContextRestoreGState(cg);
4017                 if (ce == CE_MenuEmptyArea)
4018                     break;
4019                 contentRect = qt_qrectForHIRect(cr);
4020             }
4021             int xpos = contentRect.x() + 18;
4022             int checkcol = maxpmw;
4023             if (!enabled)
4024                 p->setPen(mi->palette.text().color());
4025             else if (active)
4026                 p->setPen(mi->palette.highlightedText().color());
4027             else
4028                 p->setPen(mi->palette.buttonText().color());
4029
4030             if (mi->checked) {
4031                 // Use the HIThemeTextInfo foo to draw the check mark correctly, if we do it,
4032                 // we somehow need to use a special encoding as it doesn't look right with our
4033                 // drawText().
4034                 p->save();
4035                 CGContextSetShouldAntialias(cg, true);
4036                 CGContextSetShouldSmoothFonts(cg, true);
4037                 QColor textColor = p->pen().color();
4038                 CGFloat colorComp[] = { textColor.redF(), textColor.greenF(),
4039                                       textColor.blueF(), textColor.alphaF() };
4040                 CGContextSetFillColorSpace(cg, qt_mac_genericColorSpace());
4041                 CGContextSetFillColor(cg, colorComp);
4042                 HIThemeTextInfo tti;
4043                 tti.version = qt_mac_hitheme_version;
4044                 tti.state = tds;
4045                 if (active && enabled)
4046                     tti.state = kThemeStatePressed;
4047                 switch (widgetSize) {
4048                 case QAquaSizeUnknown:
4049                 case QAquaSizeLarge:
4050                     tti.fontID = kThemeMenuItemMarkFont;
4051                     break;
4052                 case QAquaSizeSmall:
4053                     tti.fontID = kThemeSmallSystemFont;
4054                     break;
4055                 case QAquaSizeMini:
4056                     tti.fontID = kThemeMiniSystemFont;
4057                     break;
4058                 }
4059                 tti.horizontalFlushness = kHIThemeTextHorizontalFlushLeft;
4060                 tti.verticalFlushness = kHIThemeTextVerticalFlushCenter;
4061                 tti.options = kHIThemeTextBoxOptionNone;
4062                 tti.truncationPosition = kHIThemeTextTruncationNone;
4063                 tti.truncationMaxLines = 1;
4064                 QCFString checkmark;
4065 #if 0
4066                 if (mi->checkType == QStyleOptionMenuItem::Exclusive)
4067                     checkmark = QString(QChar(kDiamondUnicode));
4068                 else
4069 #endif
4070                     checkmark = QString(QChar(kCheckUnicode));
4071                 int mw = checkcol + macItemFrame;
4072                 int mh = contentRect.height() - 2 * macItemFrame;
4073                 int xp = contentRect.x();
4074                 xp += macItemFrame;
4075                 CGFloat outWidth, outHeight, outBaseline;
4076                 HIThemeGetTextDimensions(checkmark, 0, &tti, &outWidth, &outHeight,
4077                                          &outBaseline);
4078                 if (widgetSize == QAquaSizeMini)
4079                     outBaseline += 1;
4080                 QRect r(xp, contentRect.y(), mw, mh);
4081                 r.translate(0, p->fontMetrics().ascent() - int(outBaseline) + 1);
4082                 HIRect bounds = qt_hirectForQRect(r);
4083                 HIThemeDrawTextBox(checkmark, &bounds, &tti,
4084                                    cg, kHIThemeOrientationNormal);
4085                 p->restore();
4086             }
4087             if (!mi->icon.isNull()) {
4088                 QIcon::Mode mode = (mi->state & State_Enabled) ? QIcon::Normal
4089                                                                : QIcon::Disabled;
4090                 // Always be normal or disabled to follow the Mac style.
4091                 int smallIconSize = proxy()->pixelMetric(PM_SmallIconSize);
4092                 QSize iconSize(smallIconSize, smallIconSize);
4093                 if (const QComboBox *comboBox = qobject_cast<const QComboBox *>(w)) {
4094                     iconSize = comboBox->iconSize();
4095                 }
4096                 QPixmap pixmap = mi->icon.pixmap(iconSize, mode);
4097                 int pixw = pixmap.width();
4098                 int pixh = pixmap.height();
4099                 QRect cr(xpos, contentRect.y(), checkcol, contentRect.height());
4100                 QRect pmr(0, 0, pixw, pixh);
4101                 pmr.moveCenter(cr.center());
4102                 p->drawPixmap(pmr.topLeft(), pixmap);
4103                 xpos += pixw + 6;
4104             }
4105
4106             QString s = mi->text;
4107             if (!s.isEmpty()) {
4108                 int t = s.indexOf(QLatin1Char('\t'));
4109                 int text_flags = Qt::AlignRight | Qt::AlignVCenter | Qt::TextHideMnemonic
4110                                  | Qt::TextSingleLine | Qt::AlignAbsolute;
4111                 int yPos = contentRect.y();
4112                 if (widgetSize == QAquaSizeMini)
4113                     yPos += 1;
4114                 p->save();
4115                 if (t >= 0) {
4116                     p->setFont(qt_app_fonts_hash()->value("QMenuItem", p->font()));
4117                     int xp = contentRect.right() - tabwidth - macRightBorder
4118                              - macItemHMargin - macItemFrame + 1;
4119                     p->drawText(xp, yPos, tabwidth, contentRect.height(), text_flags,
4120                                 s.mid(t + 1));
4121                     s = s.left(t);
4122                 }
4123
4124                 const int xm = macItemFrame + maxpmw + macItemHMargin;
4125                 QFont myFont = mi->font;
4126                 // myFont may not have any "hard" flags set. We override
4127                 // the point size so that when it is resolved against the device, this font will win.
4128                 // This is mainly to handle cases where someone sets the font on the window
4129                 // and then the combo inherits it and passes it onward. At that point the resolve mask
4130                 // is very, very weak. This makes it stonger.
4131                 myFont.setPointSizeF(QFontInfo(mi->font).pointSizeF());
4132                 p->setFont(myFont);
4133                 p->drawText(xpos, yPos, contentRect.width() - xm - tabwidth + 1,
4134                             contentRect.height(), text_flags ^ Qt::AlignRight, s);
4135                 p->restore();
4136             }
4137         }
4138         break;
4139     case CE_MenuHMargin:
4140     case CE_MenuVMargin:
4141     case CE_MenuTearoff:
4142     case CE_MenuScroller:
4143         if (const QStyleOptionMenuItem *mi = qstyleoption_cast<const QStyleOptionMenuItem *>(opt)) {
4144             p->fillRect(mi->rect, opt->palette.background());
4145
4146             HIRect menuRect = qt_hirectForQRect(mi->menuRect);
4147             HIRect itemRect = qt_hirectForQRect(mi->rect);
4148             HIThemeMenuItemDrawInfo mdi;
4149             mdi.version = qt_mac_hitheme_version;
4150             if (!(opt->state & State_Enabled))
4151                 mdi.state = kThemeMenuDisabled;
4152             else if (opt->state & State_Selected)
4153                 mdi.state = kThemeMenuSelected;
4154             else
4155                 mdi.state = kThemeMenuActive;
4156             if (ce == CE_MenuScroller) {
4157                 if (opt->state & State_DownArrow)
4158                     mdi.itemType = kThemeMenuItemScrollDownArrow;
4159                 else
4160                     mdi.itemType = kThemeMenuItemScrollUpArrow;
4161             } else {
4162                 mdi.itemType = kThemeMenuItemPlain;
4163             }
4164             HIThemeDrawMenuItem(&menuRect, &itemRect, &mdi,
4165                                 cg,
4166                                 kHIThemeOrientationNormal, 0);
4167             if (ce == CE_MenuTearoff) {
4168                 p->setPen(QPen(mi->palette.dark().color(), 1, Qt::DashLine));
4169                 p->drawLine(mi->rect.x() + 2, mi->rect.y() + mi->rect.height() / 2 - 1,
4170                             mi->rect.x() + mi->rect.width() - 4,
4171                             mi->rect.y() + mi->rect.height() / 2 - 1);
4172                 p->setPen(QPen(mi->palette.light().color(), 1, Qt::DashLine));
4173                 p->drawLine(mi->rect.x() + 2, mi->rect.y() + mi->rect.height() / 2,
4174                             mi->rect.x() + mi->rect.width() - 4,
4175                             mi->rect.y() + mi->rect.height() / 2);
4176             }
4177         }
4178         break;
4179     case CE_MenuBarItem:
4180         if (const QStyleOptionMenuItem *mi = qstyleoption_cast<const QStyleOptionMenuItem *>(opt)) {
4181             HIRect menuRect = qt_hirectForQRect(mi->menuRect);
4182             HIRect itemRect = qt_hirectForQRect(mi->rect);
4183
4184             if ((opt->state & State_Selected) && (opt->state & State_Enabled) && (opt->state & State_Sunken)){
4185                 // Draw a selected menu item background:
4186                 HIThemeMenuItemDrawInfo mdi;
4187                 mdi.version = qt_mac_hitheme_version;
4188                 mdi.state = kThemeMenuSelected;
4189                 mdi.itemType = kThemeMenuItemPlain;
4190                 HIThemeDrawMenuItem(&menuRect, &itemRect, &mdi, cg, kHIThemeOrientationNormal, 0);
4191             } else {
4192                 // Draw the toolbar background:
4193                 HIThemeMenuBarDrawInfo bdi;
4194                 bdi.version = qt_mac_hitheme_version;
4195                 bdi.state = kThemeMenuBarNormal;
4196                 bdi.attributes = 0;
4197                 HIThemeDrawMenuBarBackground(&menuRect, &bdi, cg, kHIThemeOrientationNormal);
4198             }
4199
4200             if (!mi->icon.isNull()) {
4201                 drawItemPixmap(p, mi->rect,
4202                                   Qt::AlignCenter | Qt::TextHideMnemonic | Qt::TextDontClip
4203                                   | Qt::TextSingleLine,
4204                                   mi->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize),
4205                           (mi->state & State_Enabled) ? QIcon::Normal : QIcon::Disabled));
4206             } else {
4207                 drawItemText(p, mi->rect,
4208                                 Qt::AlignCenter | Qt::TextHideMnemonic | Qt::TextDontClip
4209                                 | Qt::TextSingleLine,
4210                                 mi->palette, mi->state & State_Enabled,
4211                                 mi->text, QPalette::ButtonText);
4212             }
4213         }
4214         break;
4215     case CE_MenuBarEmptyArea:
4216         if (const QStyleOptionMenuItem *mi = qstyleoption_cast<const QStyleOptionMenuItem *>(opt)) {
4217             HIThemeMenuBarDrawInfo bdi;
4218             bdi.version = qt_mac_hitheme_version;
4219             bdi.state = kThemeMenuBarNormal;
4220             bdi.attributes = 0;
4221             HIRect hirect = qt_hirectForQRect(mi->rect);
4222             HIThemeDrawMenuBarBackground(&hirect, &bdi, cg,
4223                                          kHIThemeOrientationNormal);
4224             break;
4225         }
4226     case CE_ProgressBarContents:
4227         if (const QStyleOptionProgressBar *pb = qstyleoption_cast<const QStyleOptionProgressBar *>(opt)) {
4228             HIThemeTrackDrawInfo tdi;
4229             tdi.version = qt_mac_hitheme_version;
4230             tdi.reserved = 0;
4231             bool isIndeterminate = (pb->minimum == 0 && pb->maximum == 0);
4232             bool vertical = false;
4233             bool inverted = false;
4234             if (const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast<const QStyleOptionProgressBarV2 *>(opt)) {
4235                 vertical = (pb2->orientation == Qt::Vertical);
4236                 inverted = pb2->invertedAppearance;
4237             }
4238             bool reverse = (!vertical && (pb->direction == Qt::RightToLeft));
4239             if (inverted)
4240                 reverse = !reverse;
4241             switch (d->aquaSizeConstrain(opt, w)) {
4242             case QAquaSizeUnknown:
4243             case QAquaSizeLarge:
4244                 tdi.kind = !isIndeterminate ? kThemeLargeProgressBar
4245                                             : kThemeLargeIndeterminateBar;
4246                 break;
4247             case QAquaSizeMini:
4248             case QAquaSizeSmall:
4249                 tdi.kind = !isIndeterminate ? kThemeProgressBar : kThemeIndeterminateBar;
4250                 break;
4251             }
4252             tdi.bounds = qt_hirectForQRect(pb->rect);
4253             tdi.max = pb->maximum;
4254             tdi.min = pb->minimum;
4255             tdi.value = pb->progress;
4256             tdi.attributes = vertical ? 0 : kThemeTrackHorizontal;
4257             tdi.trackInfo.progress.phase = d->progressFrame;
4258             if (!(pb->state & State_Active))
4259                 tdi.enableState = kThemeTrackInactive;
4260             else if (!(pb->state & State_Enabled))
4261                 tdi.enableState = kThemeTrackDisabled;
4262             else
4263                 tdi.enableState = kThemeTrackActive;
4264             HIThemeOrientation drawOrientation = kHIThemeOrientationNormal;
4265             if (reverse) {
4266                 if (vertical) {
4267                     drawOrientation = kHIThemeOrientationInverted;
4268                 } else {
4269                     CGContextSaveGState(cg);
4270                     CGContextTranslateCTM(cg, pb->rect.width(), 0);
4271                     CGContextScaleCTM(cg, -1, 1);
4272                 }
4273             }
4274             HIThemeDrawTrack(&tdi, 0, cg, drawOrientation);
4275             if (reverse && !vertical)
4276                 CGContextRestoreGState(cg);
4277         }
4278         break;
4279     case CE_ProgressBarLabel:
4280     case CE_ProgressBarGroove:
4281         break;
4282     case CE_SizeGrip: {
4283         if (w && w->testAttribute(Qt::WA_MacOpaqueSizeGrip)) {
4284             HIThemeGrowBoxDrawInfo gdi;
4285             gdi.version = qt_mac_hitheme_version;
4286             gdi.state = tds;
4287             gdi.kind = kHIThemeGrowBoxKindNormal;
4288             gdi.direction = kThemeGrowRight | kThemeGrowDown;
4289             gdi.size = kHIThemeGrowBoxSizeNormal;
4290             HIPoint pt = CGPointMake(opt->rect.x(), opt->rect.y());
4291             HIThemeDrawGrowBox(&pt, &gdi, cg, kHIThemeOrientationNormal);
4292         } else {
4293             // It isn't possible to draw a transparent size grip with the
4294             // native API, so we do it ourselves here.
4295             const bool metal = qt_mac_is_metal(w);
4296             QPen lineColor = metal ? QColor(236, 236, 236) : QColor(82, 82, 82, 192);
4297             QPen metalHighlight = QColor(5, 5, 5, 192);
4298             lineColor.setWidth(1);
4299             p->save();
4300             p->setRenderHint(QPainter::Antialiasing);
4301             p->setPen(lineColor);
4302             const Qt::LayoutDirection layoutDirection = w ? w->layoutDirection() : qApp->layoutDirection();
4303             const int NumLines = metal ? 4 : 3;
4304             for (int l = 0; l < NumLines; ++l) {
4305                 const int offset = (l * 4 + (metal ? 2 : 3));
4306                 QPoint start, end;
4307                 if (layoutDirection == Qt::LeftToRight) {
4308                     start = QPoint(opt->rect.width() - offset, opt->rect.height() - 1);
4309                     end = QPoint(opt->rect.width() - 1, opt->rect.height() - offset);
4310                 } else {
4311                     start = QPoint(offset, opt->rect.height() - 1);
4312                     end = QPoint(1, opt->rect.height() - offset);
4313                 }
4314                 p->drawLine(start, end);
4315                 if (metal) {
4316                     p->setPen(metalHighlight);
4317                     p->setRenderHint(QPainter::Antialiasing, false);
4318                     p->drawLine(start + QPoint(0, -1), end + QPoint(0, -1));
4319                     p->setRenderHint(QPainter::Antialiasing, true);
4320                     p->setPen(lineColor);
4321                 }
4322             }
4323             p->restore();
4324         }
4325         break;
4326         }
4327     case CE_Splitter: {
4328         HIThemeSplitterDrawInfo sdi;
4329         sdi.version = qt_mac_hitheme_version;
4330         sdi.state = tds;
4331         sdi.adornment = qt_mac_is_metal(w) ? kHIThemeSplitterAdornmentMetal
4332                                            : kHIThemeSplitterAdornmentNone;
4333         HIRect hirect = qt_hirectForQRect(opt->rect);
4334         HIThemeDrawPaneSplitter(&hirect, &sdi, cg, kHIThemeOrientationNormal);
4335         break; }
4336     case CE_RubberBand:
4337         if (const QStyleOptionRubberBand *rubber = qstyleoption_cast<const QStyleOptionRubberBand *>(opt)) {
4338             QColor fillColor(opt->palette.color(QPalette::Disabled, QPalette::Highlight));
4339             if (!rubber->opaque) {
4340                 QColor strokeColor;
4341                 // I retrieved these colors from the Carbon-Dev mailing list
4342                 strokeColor.setHsvF(0, 0, 0.86, 1.0);
4343                 fillColor.setHsvF(0, 0, 0.53, 0.25);
4344                 if (opt->rect.width() * opt->rect.height() <= 3) {
4345                     p->fillRect(opt->rect, strokeColor);
4346                 } else {
4347                     QPen oldPen = p->pen();
4348                     QBrush oldBrush = p->brush();
4349                     QPen pen(strokeColor);
4350                     p->setPen(pen);
4351                     p->setBrush(fillColor);
4352                     p->drawRect(opt->rect.adjusted(0, 0, -1, -1));
4353                     p->setPen(oldPen);
4354                     p->setBrush(oldBrush);
4355                 }
4356             } else {
4357                 p->fillRect(opt->rect, fillColor);
4358             }
4359         }
4360         break;
4361     case CE_ToolBar: {
4362         // For unified tool bars, draw nothing.
4363         if (w) {
4364             if (QMainWindow * mainWindow = qobject_cast<QMainWindow *>(w->window())) {
4365                 if (mainWindow->unifiedTitleAndToolBarOnMac())
4366                     break;
4367                 }
4368         }
4369
4370         // draw background gradient
4371         QLinearGradient linearGrad;
4372         if (opt->state & State_Horizontal)
4373             linearGrad = QLinearGradient(0, opt->rect.top(), 0, opt->rect.bottom());
4374         else
4375             linearGrad = QLinearGradient(opt->rect.left(), 0,  opt->rect.right(), 0);
4376
4377         linearGrad.setColorAt(0, mainWindowGradientBegin);
4378         linearGrad.setColorAt(1, mainWindowGradientEnd);
4379         p->fillRect(opt->rect, linearGrad);
4380
4381         p->save();
4382         if (opt->state & State_Horizontal) {
4383             p->setPen(mainWindowGradientBegin.lighter(114));
4384             p->drawLine(opt->rect.topLeft(), opt->rect.topRight());
4385             p->setPen(mainWindowGradientEnd.darker(114));
4386             p->drawLine(opt->rect.bottomLeft(), opt->rect.bottomRight());
4387
4388         } else {
4389             p->setPen(mainWindowGradientBegin.lighter(114));
4390             p->drawLine(opt->rect.topLeft(), opt->rect.bottomLeft());
4391             p->setPen(mainWindowGradientEnd.darker(114));
4392             p->drawLine(opt->rect.topRight(), opt->rect.bottomRight());
4393         }
4394         p->restore();
4395
4396
4397         } break;
4398     default:
4399         QWindowsStyle::drawControl(ce, opt, p, w);
4400         break;
4401     }
4402 }
4403
4404 static void setLayoutItemMargins(int left, int top, int right, int bottom, QRect *rect, Qt::LayoutDirection dir)
4405 {
4406     if (dir == Qt::RightToLeft) {
4407         rect->adjust(-right, top, -left, bottom);
4408     } else {
4409         rect->adjust(left, top, right, bottom);
4410     }
4411 }
4412
4413 QRect QMacStyle::subElementRect(SubElement sr, const QStyleOption *opt,
4414                                 const QWidget *widget) const
4415 {
4416     QRect rect;
4417     int controlSize = getControlSize(opt, widget);
4418
4419     switch (sr) {
4420     case SE_ItemViewItemText:
4421         if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(opt)) {
4422             int fw = proxy()->pixelMetric(PM_FocusFrameHMargin, opt, widget);
4423             // We add the focusframeargin between icon and text in commonstyle
4424             rect = QCommonStyle::subElementRect(sr, opt, widget);
4425             if (vopt->features & QStyleOptionViewItemV2::HasDecoration)
4426                 rect.adjust(-fw, 0, 0, 0);
4427         }
4428         break;
4429     case SE_ToolBoxTabContents:
4430         rect = QCommonStyle::subElementRect(sr, opt, widget);
4431         break;
4432     case SE_PushButtonContents:
4433         if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
4434             // Unlike Carbon, we want the button to always be drawn inside its bounds.
4435             // Therefore, the button is a bit smaller, so that even if it got focus,
4436             // the focus 'shadow' will be inside. Adjust the content rect likewise.
4437             HIThemeButtonDrawInfo bdi;
4438             d->initHIThemePushButton(btn, widget, d->getDrawState(opt->state), &bdi);
4439             HIRect contentRect = d->pushButtonContentBounds(btn, &bdi);
4440             rect = qt_qrectForHIRect(contentRect);
4441         }
4442         break;
4443     case SE_HeaderLabel:
4444         if (qstyleoption_cast<const QStyleOptionHeader *>(opt)) {
4445             rect = QWindowsStyle::subElementRect(sr, opt, widget);
4446             if (widget && widget->height() <= 22){
4447                 // We need to allow the text a bit more space when the header is
4448                 // small, otherwise it gets clipped:
4449                 rect.setY(0);
4450                 rect.setHeight(widget->height());
4451             }
4452         }
4453         break;
4454     case SE_ProgressBarGroove:
4455     case SE_ProgressBarLabel:
4456         break;
4457     case SE_ProgressBarContents:
4458         rect = opt->rect;
4459         break;
4460     case SE_TreeViewDisclosureItem: {
4461         HIRect inRect = CGRectMake(opt->rect.x(), opt->rect.y(),
4462                                    opt->rect.width(), opt->rect.height());
4463         HIThemeButtonDrawInfo bdi;
4464         bdi.version = qt_mac_hitheme_version;
4465         bdi.state = kThemeStateActive;
4466         bdi.kind = kThemeDisclosureButton;
4467         bdi.value = kThemeDisclosureRight;
4468         bdi.adornment = kThemeAdornmentNone;
4469         HIRect contentRect;
4470         HIThemeGetButtonContentBounds(&inRect, &bdi, &contentRect);
4471         QCFType<HIShapeRef> shape;
4472         HIRect outRect;
4473         HIThemeGetButtonShape(&inRect, &bdi, &shape);
4474         ptrHIShapeGetBounds(shape, &outRect);
4475         rect = QRect(int(outRect.origin.x + DisclosureOffset), int(outRect.origin.y),
4476                   int(contentRect.origin.x - outRect.origin.x + DisclosureOffset),
4477                   int(outRect.size.height));
4478         break;
4479     }
4480     case SE_TabWidgetLeftCorner:
4481         if (const QStyleOptionTabWidgetFrame *twf
4482                 = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) {
4483             switch (twf->shape) {
4484             case QTabBar::RoundedNorth:
4485             case QTabBar::TriangularNorth:
4486                 rect = QRect(QPoint(0, 0), twf->leftCornerWidgetSize);
4487                 break;
4488             case QTabBar::RoundedSouth:
4489             case QTabBar::TriangularSouth:
4490                 rect = QRect(QPoint(0, twf->rect.height() - twf->leftCornerWidgetSize.height()),
4491                           twf->leftCornerWidgetSize);
4492                 break;
4493             default:
4494                 break;
4495             }
4496             rect = visualRect(twf->direction, twf->rect, rect);
4497         }
4498         break;
4499     case SE_TabWidgetRightCorner:
4500         if (const QStyleOptionTabWidgetFrame *twf
4501                 = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) {
4502             switch (twf->shape) {
4503             case QTabBar::RoundedNorth:
4504             case QTabBar::TriangularNorth:
4505                 rect = QRect(QPoint(twf->rect.width() - twf->rightCornerWidgetSize.width(), 0),
4506                           twf->rightCornerWidgetSize);
4507                 break;
4508             case QTabBar::RoundedSouth:
4509             case QTabBar::TriangularSouth:
4510                 rect = QRect(QPoint(twf->rect.width() - twf->rightCornerWidgetSize.width(),
4511                                  twf->rect.height() - twf->rightCornerWidgetSize.height()),
4512                           twf->rightCornerWidgetSize);
4513                 break;
4514             default:
4515                 break;
4516             }
4517             rect = visualRect(twf->direction, twf->rect, rect);
4518         }
4519         break;
4520     case SE_TabWidgetTabContents:
4521         rect = QWindowsStyle::subElementRect(sr, opt, widget);
4522         if (const QStyleOptionTabWidgetFrame *twf
4523                 = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) {
4524             if (twf->lineWidth != 0) {
4525                 switch (getTabDirection(twf->shape)) {
4526                 case kThemeTabNorth:
4527                     rect.adjust(+1, +14, -1, -1);
4528                     break;
4529                 case kThemeTabSouth:
4530                     rect.adjust(+1, +1, -1, -14);
4531                     break;
4532                 case kThemeTabWest:
4533                     rect.adjust(+14, +1, -1, -1);
4534                     break;
4535                 case kThemeTabEast:
4536                     rect.adjust(+1, +1, -14, -1);
4537                 }
4538             }
4539         }
4540         break;
4541     case SE_LineEditContents:
4542         rect = QWindowsStyle::subElementRect(sr, opt, widget);
4543         if(widget->parentWidget() && qobject_cast<const QComboBox*>(widget->parentWidget()))
4544             rect.adjust(-1, -2, 0, 0);
4545         else
4546             rect.adjust(-1, 0, 0, +1);
4547         break;
4548     case SE_CheckBoxLayoutItem:
4549         rect = opt->rect;
4550         if (controlSize == QAquaSizeLarge) {
4551             setLayoutItemMargins(+2, +3, -9, -4, &rect, opt->direction);
4552         } else if (controlSize == QAquaSizeSmall) {
4553             setLayoutItemMargins(+1, +5, 0 /* fix */, -6, &rect, opt->direction);
4554         } else {
4555             setLayoutItemMargins(0, +7, 0 /* fix */, -6, &rect, opt->direction);
4556         }
4557         break;
4558     case SE_ComboBoxLayoutItem:
4559         if (widget && qobject_cast<QToolBar *>(widget->parentWidget())) {
4560             // Do nothing, because QToolbar needs the entire widget rect.
4561             // Otherwise it will be clipped. Equivalent to
4562             // widget->setAttribute(Qt::WA_LayoutUsesWidgetRect), but without
4563             // all the hassle.
4564         } else {
4565             rect = opt->rect;
4566             if (controlSize == QAquaSizeLarge) {
4567                 rect.adjust(+3, +2, -3, -4);
4568             } else if (controlSize == QAquaSizeSmall) {
4569                 setLayoutItemMargins(+2, +1, -3, -4, &rect, opt->direction);
4570             } else {
4571                 setLayoutItemMargins(+1, 0, -2, 0, &rect, opt->direction);
4572             }
4573         }
4574         break;
4575     case SE_LabelLayoutItem:
4576         rect = opt->rect;
4577         setLayoutItemMargins(+1, 0 /* SHOULD be -1, done for alignment */, 0, 0 /* SHOULD be -1, done for alignment */, &rect, opt->direction);
4578         break;
4579     case SE_ProgressBarLayoutItem: {
4580         rect = opt->rect;
4581         int bottom = SIZE(3, 8, 8);
4582         if (opt->state & State_Horizontal) {
4583             rect.adjust(0, +1, 0, -bottom);
4584         } else {
4585             setLayoutItemMargins(+1, 0, -bottom, 0, &rect, opt->direction);
4586         }
4587         break;
4588     }
4589     case SE_PushButtonLayoutItem:
4590         if (const QStyleOptionButton *buttonOpt
4591                 = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
4592             if ((buttonOpt->features & QStyleOptionButton::Flat))
4593                 break;  // leave rect alone
4594         }
4595         rect = opt->rect;
4596         if (controlSize == QAquaSizeLarge) {
4597             rect.adjust(+6, +4, -6, -8);
4598         } else if (controlSize == QAquaSizeSmall) {
4599             rect.adjust(+5, +4, -5, -6);
4600         } else {
4601             rect.adjust(+1, 0, -1, -2);
4602         }
4603         break;
4604     case SE_RadioButtonLayoutItem:
4605         rect = opt->rect;
4606         if (controlSize == QAquaSizeLarge) {
4607             setLayoutItemMargins(+2, +2 /* SHOULD BE +3, done for alignment */,
4608                                  0, -4 /* SHOULD BE -3, done for alignment */, &rect, opt->direction);
4609         } else if (controlSize == QAquaSizeSmall) {
4610             rect.adjust(0, +6, 0 /* fix */, -5);
4611         } else {
4612             rect.adjust(0, +6, 0 /* fix */, -7);
4613         }
4614         break;
4615     case SE_SliderLayoutItem:
4616         if (const QStyleOptionSlider *sliderOpt
4617                 = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
4618             rect = opt->rect;
4619             if (sliderOpt->tickPosition == QSlider::NoTicks) {
4620                 int above = SIZE(3, 0, 2);
4621                 int below = SIZE(4, 3, 0);
4622                 if (sliderOpt->orientation == Qt::Horizontal) {
4623                     rect.adjust(0, +above, 0, -below);
4624                 } else {
4625                     rect.adjust(+above, 0, -below, 0);  //### Seems that QSlider flip the position of the ticks in reverse mode.
4626                 }
4627             } else if (sliderOpt->tickPosition == QSlider::TicksAbove) {
4628                 int below = SIZE(3, 2, 0);
4629                 if (sliderOpt->orientation == Qt::Horizontal) {
4630                     rect.setHeight(rect.height() - below);
4631                 } else {
4632                     rect.setWidth(rect.width() - below);
4633                 }
4634             } else if (sliderOpt->tickPosition == QSlider::TicksBelow) {
4635                 int above = SIZE(3, 2, 0);
4636                 if (sliderOpt->orientation == Qt::Horizontal) {
4637                     rect.setTop(rect.top() + above);
4638                 } else {
4639                     rect.setLeft(rect.left() + above);
4640                 }
4641             }
4642         }
4643         break;
4644     case SE_FrameLayoutItem:
4645         // hack because QStyleOptionFrameV2 doesn't have a frameStyle member
4646         if (const QFrame *frame = qobject_cast<const QFrame *>(widget)) {
4647             rect = opt->rect;
4648             switch (frame->frameStyle() & QFrame::Shape_Mask) {
4649             case QFrame::HLine:
4650                 rect.adjust(0, +1, 0, -1);
4651                 break;
4652             case QFrame::VLine:
4653                 rect.adjust(+1, 0, -1, 0);
4654                 break;
4655             default:
4656                 ;
4657             }
4658         }
4659         break;
4660     case SE_GroupBoxLayoutItem:
4661         rect = opt->rect;
4662         if (const QStyleOptionGroupBox *groupBoxOpt =
4663                 qstyleoption_cast<const QStyleOptionGroupBox *>(opt)) {
4664             /*
4665                 AHIG is very inconsistent when it comes to group boxes.
4666                 Basically, we make sure that (non-checkable) group boxes
4667                 and tab widgets look good when laid out side by side.
4668             */
4669             if (groupBoxOpt->subControls & (QStyle::SC_GroupBoxCheckBox
4670                                             | QStyle::SC_GroupBoxLabel)) {
4671                 int delta;
4672                 if (groupBoxOpt->subControls & QStyle::SC_GroupBoxCheckBox) {
4673                     delta = SIZE(8, 4, 4);       // guess
4674                 } else {
4675                     delta = SIZE(15, 12, 12);    // guess
4676                 }
4677                 rect.setTop(rect.top() + delta);
4678             }
4679         }
4680         rect.setBottom(rect.bottom() - 1);
4681         break;
4682     case SE_TabWidgetLayoutItem:
4683         if (const QStyleOptionTabWidgetFrame *tabWidgetOpt =
4684                 qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) {
4685             /*
4686                 AHIG specifies "12 or 14" as the distance from the window
4687                 edge. We choose 14 and since the default top margin is 20,
4688                 the overlap is 6.
4689             */
4690             rect = tabWidgetOpt->rect;
4691             if (tabWidgetOpt->shape == QTabBar::RoundedNorth)
4692                 rect.setTop(rect.top() + SIZE(6 /* AHIG */, 3 /* guess */, 2 /* AHIG */));
4693         }
4694         break;
4695 #ifndef QT_NO_DOCKWIDGET
4696         case SE_DockWidgetCloseButton:
4697         case SE_DockWidgetFloatButton:
4698         case SE_DockWidgetTitleBarText:
4699         case SE_DockWidgetIcon: {
4700             int iconSize = proxy()->pixelMetric(PM_SmallIconSize, opt, widget);
4701             int buttonMargin = proxy()->pixelMetric(PM_DockWidgetTitleBarButtonMargin, opt, widget);
4702             QRect srect = opt->rect;
4703
4704             const QStyleOptionDockWidget *dwOpt
4705                 = qstyleoption_cast<const QStyleOptionDockWidget*>(opt);
4706             bool canClose = dwOpt == 0 ? true : dwOpt->closable;
4707             bool canFloat = dwOpt == 0 ? false : dwOpt->floatable;
4708             const QStyleOptionDockWidgetV2 *v2
4709                 = qstyleoption_cast<const QStyleOptionDockWidgetV2*>(opt);
4710             bool verticalTitleBar = v2 == 0 ? false : v2->verticalTitleBar;
4711
4712             // If this is a vertical titlebar, we transpose and work as if it was
4713             // horizontal, then transpose again.
4714             if (verticalTitleBar) {
4715                 QSize size = srect.size();
4716                 size.transpose();
4717                 srect.setSize(size);
4718             }
4719
4720             do {
4721                 int right = srect.right();
4722                 int left = srect.left();
4723
4724                 QRect closeRect;
4725                 if (canClose) {
4726                     QSize sz = standardIcon(QStyle::SP_TitleBarCloseButton,
4727                                             opt, widget).actualSize(QSize(iconSize, iconSize));
4728                     sz += QSize(buttonMargin, buttonMargin);
4729                     if (verticalTitleBar)
4730                         sz.transpose();
4731                     closeRect = QRect(left,
4732                                       srect.center().y() - sz.height()/2,
4733                                       sz.width(), sz.height());
4734                     left = closeRect.right() + 1;
4735                 }
4736                 if (sr == SE_DockWidgetCloseButton) {
4737                     rect = closeRect;
4738                     break;
4739                 }
4740
4741                 QRect floatRect;
4742                 if (canFloat) {
4743                     QSize sz = standardIcon(QStyle::SP_TitleBarNormalButton,
4744                                             opt, widget).actualSize(QSize(iconSize, iconSize));
4745                     sz += QSize(buttonMargin, buttonMargin);
4746                     if (verticalTitleBar)
4747                         sz.transpose();
4748                     floatRect = QRect(left,
4749                                       srect.center().y() - sz.height()/2,
4750                                       sz.width(), sz.height());
4751                     left = floatRect.right() + 1;
4752                 }
4753                 if (sr == SE_DockWidgetFloatButton) {
4754                     rect = floatRect;
4755                     break;
4756                 }
4757
4758                 QRect iconRect;
4759                 if (const QDockWidget *dw = qobject_cast<const QDockWidget*>(widget)) {
4760                     QIcon icon;
4761                     if (dw->isFloating())
4762                         icon = dw->windowIcon();
4763                     if (!icon.isNull()
4764                         && icon.cacheKey() != QApplication::windowIcon().cacheKey()) {
4765                         QSize sz = icon.actualSize(QSize(rect.height(), rect.height()));
4766                         if (verticalTitleBar)
4767                             sz.transpose();
4768                         iconRect = QRect(right - sz.width(), srect.center().y() - sz.height()/2,
4769                                          sz.width(), sz.height());
4770                         right = iconRect.left() - 1;
4771                     }
4772                 }
4773                 if (sr == SE_DockWidgetIcon) {
4774                     rect = iconRect;
4775                     break;
4776                 }
4777
4778                 QRect textRect = QRect(left, srect.top(),
4779                                        right - left, srect.height());
4780                 if (sr == SE_DockWidgetTitleBarText) {
4781                     rect = textRect;
4782                     break;
4783                 }
4784             } while (false);
4785
4786             if (verticalTitleBar) {
4787                 rect = QRect(srect.left() + rect.top() - srect.top(),
4788                           srect.top() + srect.right() - rect.right(),
4789                           rect.height(), rect.width());
4790             } else {
4791                 rect = visualRect(opt->direction, srect, rect);
4792             }
4793             break;
4794         }
4795 #endif
4796     default:
4797         rect = QWindowsStyle::subElementRect(sr, opt, widget);
4798         break;
4799     }
4800     return rect;
4801 }
4802
4803 static inline void drawToolbarButtonArrow(const QRect &toolButtonRect, ThemeDrawState tds, CGContextRef cg)
4804 {
4805     QRect arrowRect = QRect(toolButtonRect.right() - 9, toolButtonRect.bottom() - 9, 7, 5);
4806     HIThemePopupArrowDrawInfo padi;
4807     padi.version = qt_mac_hitheme_version;
4808     padi.state = tds;
4809     padi.orientation = kThemeArrowDown;
4810     padi.size = kThemeArrow7pt;
4811     HIRect hirect = qt_hirectForQRect(arrowRect);
4812     HIThemeDrawPopupArrow(&hirect, &padi, cg, kHIThemeOrientationNormal);
4813 }
4814
4815 void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p,
4816                                    const QWidget *widget) const
4817 {
4818     ThemeDrawState tds = d->getDrawState(opt->state);
4819     QMacCGContext cg(p);
4820     switch (cc) {
4821     case CC_Slider:
4822     case CC_ScrollBar:
4823         if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
4824             HIThemeTrackDrawInfo tdi;
4825             d->getSliderInfo(cc, slider, &tdi, widget);
4826             if (slider->state & State_Sunken) {
4827                 if (cc == CC_Slider) {
4828                     if (slider->activeSubControls == SC_SliderHandle)
4829                         tdi.trackInfo.slider.pressState = kThemeThumbPressed;
4830                     else if (slider->activeSubControls == SC_SliderGroove)
4831                         tdi.trackInfo.slider.pressState = kThemeLeftTrackPressed;
4832                 } else {
4833                     if (slider->activeSubControls == SC_ScrollBarSubLine
4834                         || slider->activeSubControls == SC_ScrollBarAddLine) {
4835                         // This test looks complex but it basically boils down
4836                         // to the following: The "RTL look" on the mac also
4837                         // changed the directions of the controls, that's not
4838                         // what people expect (an arrow is an arrow), so we
4839                         // kind of fake and say the opposite button is hit.
4840                         // This works great, up until 10.4 which broke the
4841                         // scroll bars, so I also have actually do something
4842                         // similar when I have an upside down scroll bar
4843                         // because on Tiger I only "fake" the reverse stuff.
4844                         bool reverseHorizontal = (slider->direction == Qt::RightToLeft
4845                                                   && slider->orientation == Qt::Horizontal);
4846                         if ((reverseHorizontal
4847                              && slider->activeSubControls == SC_ScrollBarAddLine)
4848                             || (!reverseHorizontal
4849                                 && slider->activeSubControls == SC_ScrollBarSubLine)) {
4850                             tdi.trackInfo.scrollbar.pressState = kThemeRightInsideArrowPressed
4851                                                                  | kThemeLeftOutsideArrowPressed;
4852                         } else {
4853                             tdi.trackInfo.scrollbar.pressState = kThemeLeftInsideArrowPressed
4854                                                                  | kThemeRightOutsideArrowPressed;
4855                         }
4856                     } else if (slider->activeSubControls == SC_ScrollBarAddPage) {
4857                         tdi.trackInfo.scrollbar.pressState = kThemeRightTrackPressed;
4858                     } else if (slider->activeSubControls == SC_ScrollBarSubPage) {
4859                         tdi.trackInfo.scrollbar.pressState = kThemeLeftTrackPressed;
4860                     } else if (slider->activeSubControls == SC_ScrollBarSlider) {
4861                         tdi.trackInfo.scrollbar.pressState = kThemeThumbPressed;
4862                     }
4863                 }
4864             }
4865             HIRect macRect;
4866             bool tracking = slider->sliderPosition == slider->sliderValue;
4867             if (!tracking) {
4868                 // Small optimization, the same as q->subControlRect
4869                 QCFType<HIShapeRef> shape;
4870                 HIThemeGetTrackThumbShape(&tdi, &shape);
4871                 ptrHIShapeGetBounds(shape, &macRect);
4872                 tdi.value = slider->sliderValue;
4873             }
4874
4875             // Remove controls from the scroll bar if it is to short to draw them correctly.
4876             // This is done in two stages: first the thumb indicator is removed when it is
4877             // no longer possible to move it, second the up/down buttons are removed when
4878             // there is not enough space for them.
4879             if (cc == CC_ScrollBar) {
4880                 const int scrollBarLength = (slider->orientation == Qt::Horizontal)
4881                     ? slider->rect.width() : slider->rect.height();
4882                 const QMacStyle::WidgetSizePolicy sizePolicy = widgetSizePolicy(widget);
4883                 if (scrollBarLength < scrollButtonsCutoffSize(thumbIndicatorCutoff, sizePolicy))
4884                     tdi.attributes &= ~kThemeTrackShowThumb;
4885                 if (scrollBarLength < scrollButtonsCutoffSize(scrollButtonsCutoff, sizePolicy))
4886                     tdi.enableState = kThemeTrackNothingToScroll;
4887             } else {
4888                 if (!(slider->subControls & SC_SliderHandle))
4889                     tdi.attributes &= ~kThemeTrackShowThumb;
4890 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
4891                 if (!(slider->subControls & SC_SliderGroove))
4892                     tdi.attributes |= kThemeTrackHideTrack;
4893 #endif
4894             }
4895
4896             HIThemeDrawTrack(&tdi, tracking ? 0 : &macRect, cg,
4897                              kHIThemeOrientationNormal);
4898             if (cc == CC_Slider && slider->subControls & SC_SliderTickmarks) {
4899                 if (qt_mac_is_metal(widget)) {
4900                     if (tdi.enableState == kThemeTrackInactive)
4901                         tdi.enableState = kThemeTrackActive;  // Looks more Cocoa-like
4902                 }
4903                 int interval = slider->tickInterval;
4904                 if (interval == 0) {
4905                     interval = slider->pageStep;
4906                     if (interval == 0)
4907                         interval = slider->singleStep;
4908                     if (interval == 0)
4909                         interval = 1;
4910                 }
4911                 int numMarks = 1 + ((slider->maximum - slider->minimum) / interval);
4912
4913                 if (tdi.trackInfo.slider.thumbDir == kThemeThumbPlain) {
4914                     // They asked for both, so we'll give it to them.
4915                     tdi.trackInfo.slider.thumbDir = kThemeThumbDownward;
4916                     HIThemeDrawTrackTickMarks(&tdi, numMarks,
4917                                               cg,
4918                                               kHIThemeOrientationNormal);
4919                     tdi.trackInfo.slider.thumbDir = kThemeThumbUpward;
4920                     HIThemeDrawTrackTickMarks(&tdi, numMarks,
4921                                               cg,
4922                                                kHIThemeOrientationNormal);
4923                 } else {
4924                     HIThemeDrawTrackTickMarks(&tdi, numMarks,
4925                                               cg,
4926                                               kHIThemeOrientationNormal);
4927
4928                 }
4929             }
4930         }
4931         break;
4932     case CC_Q3ListView:
4933         if (const QStyleOptionQ3ListView *lv = qstyleoption_cast<const QStyleOptionQ3ListView *>(opt)) {
4934             if (lv->subControls & SC_Q3ListView)
4935                 QWindowsStyle::drawComplexControl(cc, lv, p, widget);
4936             if (lv->subControls & (SC_Q3ListViewBranch | SC_Q3ListViewExpand)) {
4937                 int y = lv->rect.y();
4938                 int h = lv->rect.height();
4939                 int x = lv->rect.right() - 10;
4940                 for (int i = 1; i < lv->items.size() && y < h; ++i) {
4941                     QStyleOptionQ3ListViewItem item = lv->items.at(i);
4942                     if (y + item.height > 0 && (item.childCount > 0
4943                         || (item.features & (QStyleOptionQ3ListViewItem::Expandable
4944                                             | QStyleOptionQ3ListViewItem::Visible))
4945                             == (QStyleOptionQ3ListViewItem::Expandable
4946                                 | QStyleOptionQ3ListViewItem::Visible))) {
4947                         QStyleOption treeOpt(0);
4948                         treeOpt.rect.setRect(x, y + item.height / 2 - 4, 9, 9);
4949                         treeOpt.palette = lv->palette;
4950                         treeOpt.state = lv->state;
4951                         treeOpt.state |= State_Children;
4952                         if (item.state & State_Open)
4953                             treeOpt.state |= State_Open;
4954                         proxy()->drawPrimitive(PE_IndicatorBranch, &treeOpt, p, widget);
4955                     }
4956                     y += item.totalHeight;
4957                 }
4958             }
4959         }
4960         break;
4961     case CC_SpinBox:
4962         if (const QStyleOptionSpinBox *sb = qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) {
4963             QStyleOptionSpinBox newSB = *sb;
4964             if (sb->frame && (sb->subControls & SC_SpinBoxFrame)) {
4965                 SInt32 frame_size;
4966                 GetThemeMetric(kThemeMetricEditTextFrameOutset, &frame_size);
4967
4968                 QRect lineeditRect = proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxEditField, widget);
4969                 lineeditRect.adjust(-frame_size, -frame_size, +frame_size, +frame_size);
4970
4971                 HIThemeFrameDrawInfo fdi;
4972                 fdi.version = qt_mac_hitheme_version;
4973                 fdi.state = tds;
4974                 fdi.kind = kHIThemeFrameTextFieldSquare;
4975                 fdi.isFocused = false;
4976                 HIRect hirect = qt_hirectForQRect(lineeditRect);
4977                 HIThemeDrawFrame(&hirect, &fdi, cg, kHIThemeOrientationNormal);
4978             }
4979             if (sb->subControls & (SC_SpinBoxUp | SC_SpinBoxDown)) {
4980                 HIThemeButtonDrawInfo bdi;
4981                 bdi.version = qt_mac_hitheme_version;
4982                 QAquaWidgetSize aquaSize = d->aquaSizeConstrain(opt, widget);
4983                 switch (aquaSize) {
4984                     case QAquaSizeUnknown:
4985                     case QAquaSizeLarge:
4986                         bdi.kind = kThemeIncDecButton;
4987                         break;
4988                     case QAquaSizeMini:
4989                         bdi.kind = kThemeIncDecButtonMini;
4990                         break;
4991                     case QAquaSizeSmall:
4992                         bdi.kind = kThemeIncDecButtonSmall;
4993                         break;
4994                 }
4995                 if (!(sb->stepEnabled & (QAbstractSpinBox::StepUpEnabled
4996                                         | QAbstractSpinBox::StepDownEnabled)))
4997                     tds = kThemeStateUnavailable;
4998                 if (sb->activeSubControls == SC_SpinBoxDown
4999                     && (sb->state & State_Sunken))
5000                     tds = kThemeStatePressedDown;
5001                 else if (sb->activeSubControls == SC_SpinBoxUp
5002                          && (sb->state & State_Sunken))
5003                     tds = kThemeStatePressedUp;
5004                 bdi.state = tds;
5005                 if (!(sb->state & State_Active)
5006                         && sb->palette.currentColorGroup() == QPalette::Active
5007                         && tds == kThemeStateInactive)
5008                     bdi.state = kThemeStateActive;
5009                 bdi.value = kThemeButtonOff;
5010                 bdi.adornment = kThemeAdornmentNone;
5011
5012                 QRect updown = proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxUp, widget);
5013
5014                 updown |= proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxDown, widget);
5015                 HIRect newRect = qt_hirectForQRect(updown);
5016                 QRect off_rct;
5017                 HIRect outRect;
5018                 HIThemeGetButtonBackgroundBounds(&newRect, &bdi, &outRect);
5019                 off_rct.setRect(int(newRect.origin.x - outRect.origin.x),
5020                                 int(newRect.origin.y - outRect.origin.y),
5021                                 int(outRect.size.width - newRect.size.width),
5022                                 int(outRect.size.height - newRect.size.height));
5023
5024                 newRect = qt_hirectForQRect(updown, off_rct);
5025                 HIThemeDrawButton(&newRect, &bdi, cg, kHIThemeOrientationNormal, 0);
5026             }
5027         }
5028         break;
5029     case CC_ComboBox:
5030         if (const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox *>(opt)){
5031             HIThemeButtonDrawInfo bdi;
5032             d->initComboboxBdi(combo, &bdi, widget, d->getDrawState(opt->state));
5033             bool drawColorless = combo->palette.currentColorGroup() == QPalette::Active && tds == kThemeStateInactive;
5034             if (!drawColorless)
5035                 QMacStylePrivate::drawCombobox(qt_hirectForQRect(combo->rect), bdi, p);
5036             else
5037                 d->drawColorlessButton(qt_hirectForQRect(combo->rect), &bdi, p, opt);
5038         }
5039         break;
5040     case CC_TitleBar:
5041         if (const QStyleOptionTitleBar *titlebar
5042                 = qstyleoption_cast<const QStyleOptionTitleBar *>(opt)) {
5043             if (titlebar->state & State_Active) {
5044                 if (titlebar->titleBarState & State_Active)
5045                     tds = kThemeStateActive;
5046                 else
5047                     tds = kThemeStateInactive;
5048             } else {
5049                 tds = kThemeStateInactive;
5050             }
5051
5052             HIThemeWindowDrawInfo wdi;
5053             wdi.version = qt_mac_hitheme_version;
5054             wdi.state = tds;
5055             wdi.windowType = QtWinType;
5056             wdi.titleHeight = titlebar->rect.height();
5057             wdi.titleWidth = titlebar->rect.width();
5058             wdi.attributes = kThemeWindowHasTitleText;
5059             // It seems HIThemeDrawTitleBarWidget is not able to draw a dirty
5060             // close button, so use HIThemeDrawWindowFrame instead.
5061             if (widget && widget->isWindowModified() && titlebar->subControls & SC_TitleBarCloseButton)
5062                 wdi.attributes |= kThemeWindowHasCloseBox | kThemeWindowHasDirty;
5063
5064             HIRect titleBarRect;
5065             HIRect tmpRect = qt_hirectForQRect(titlebar->rect);
5066             {
5067                 QCFType<HIShapeRef> titleRegion;
5068                 QRect newr = titlebar->rect.adjusted(0, 0, 2, 0);
5069                 HIThemeGetWindowShape(&tmpRect, &wdi, kWindowTitleBarRgn, &titleRegion);
5070                 ptrHIShapeGetBounds(titleRegion, &tmpRect);
5071                 newr.translate(newr.x() - int(tmpRect.origin.x), newr.y() - int(tmpRect.origin.y));
5072                 titleBarRect = qt_hirectForQRect(newr);
5073             }
5074             HIThemeDrawWindowFrame(&titleBarRect, &wdi, cg, kHIThemeOrientationNormal, 0);
5075             if (titlebar->subControls & (SC_TitleBarCloseButton
5076                                          | SC_TitleBarMaxButton
5077                                          | SC_TitleBarMinButton
5078                                          | SC_TitleBarNormalButton)) {
5079                 HIThemeWindowWidgetDrawInfo wwdi;
5080                 wwdi.version = qt_mac_hitheme_version;
5081                 wwdi.widgetState = tds;
5082                 if (titlebar->state & State_MouseOver)
5083                     wwdi.widgetState = kThemeStateRollover;
5084                 wwdi.windowType = QtWinType;
5085                 wwdi.attributes = wdi.attributes | kThemeWindowHasFullZoom | kThemeWindowHasCloseBox | kThemeWindowHasCollapseBox;
5086                 wwdi.windowState = wdi.state;
5087                 wwdi.titleHeight = wdi.titleHeight;
5088                 wwdi.titleWidth = wdi.titleWidth;
5089                 ThemeDrawState savedControlState = wwdi.widgetState;
5090                 uint sc = SC_TitleBarMinButton;
5091                 ThemeTitleBarWidget tbw = kThemeWidgetCollapseBox;
5092                 bool active = titlebar->state & State_Active;
5093                 if (qMacVersion() < QSysInfo::MV_10_6) {
5094                     int border = 2;
5095                     titleBarRect.origin.x += border;
5096                     titleBarRect.origin.y -= border;
5097                 }
5098
5099                 while (sc <= SC_TitleBarCloseButton) {
5100                     if (sc & titlebar->subControls) {
5101                         uint tmp = sc;
5102                         wwdi.widgetState = savedControlState;
5103                         wwdi.widgetType = tbw;
5104                         if (sc == SC_TitleBarMinButton)
5105                             tmp |= SC_TitleBarNormalButton;
5106                         if (active && (titlebar->activeSubControls & tmp)
5107                                 && (titlebar->state & State_Sunken))
5108                             wwdi.widgetState = kThemeStatePressed;
5109                         // Draw all sub controllers except the dirty close button
5110                         // (it is already handled by HIThemeDrawWindowFrame).
5111                         if (!(widget && widget->isWindowModified() && tbw == kThemeWidgetCloseBox)) {
5112                             HIThemeDrawTitleBarWidget(&titleBarRect, &wwdi, cg, kHIThemeOrientationNormal);
5113                             p->paintEngine()->syncState();
5114                         }
5115                     }
5116                     sc = sc << 1;
5117                     tbw = tbw >> 1;
5118                 }
5119             }
5120             p->paintEngine()->syncState();
5121             if (titlebar->subControls & SC_TitleBarLabel) {
5122                 int iw = 0;
5123                 if (!titlebar->icon.isNull()) {
5124                     QCFType<HIShapeRef> titleRegion2;
5125                     HIThemeGetWindowShape(&titleBarRect, &wdi, kWindowTitleProxyIconRgn,
5126                                           &titleRegion2);
5127                     ptrHIShapeGetBounds(titleRegion2, &tmpRect);
5128                     if (tmpRect.size.width != 1) {
5129                         int iconExtent = proxy()->pixelMetric(PM_SmallIconSize);
5130                         iw = titlebar->icon.actualSize(QSize(iconExtent, iconExtent)).width();
5131                     }
5132                 }
5133                 if (!titlebar->text.isEmpty()) {
5134                     p->save();
5135                     QCFType<HIShapeRef> titleRegion3;
5136                     HIThemeGetWindowShape(&titleBarRect, &wdi, kWindowTitleTextRgn, &titleRegion3);
5137                     ptrHIShapeGetBounds(titleRegion3, &tmpRect);
5138                     p->setClipRect(qt_qrectForHIRect(tmpRect));
5139                     QRect br = p->clipRegion().boundingRect();
5140                     int x = br.x(),
5141                     y = br.y() + (titlebar->rect.height() / 2 - p->fontMetrics().height() / 2);
5142                     if (br.width() <= (p->fontMetrics().width(titlebar->text) + iw * 2))
5143                         x += iw;
5144                     else
5145                         x += br.width() / 2 - p->fontMetrics().width(titlebar->text) / 2;
5146                     if (iw)
5147                         p->drawPixmap(x - iw, y, 
5148                                       titlebar->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize), QIcon::Normal));
5149                     drawItemText(p, br, Qt::AlignCenter, opt->palette, tds == kThemeStateActive,
5150                                     titlebar->text, QPalette::Text);
5151                     p->restore();
5152                 }
5153             }
5154         }
5155         break;
5156     case CC_GroupBox:
5157         if (const QStyleOptionGroupBox *groupBox
5158                 = qstyleoption_cast<const QStyleOptionGroupBox *>(opt)) {
5159
5160             QStyleOptionGroupBox groupBoxCopy(*groupBox);
5161             if ((widget && !widget->testAttribute(Qt::WA_SetFont))
5162                     && QApplication::desktopSettingsAware())
5163                 groupBoxCopy.subControls = groupBoxCopy.subControls & ~SC_GroupBoxLabel;
5164             QWindowsStyle::drawComplexControl(cc, &groupBoxCopy, p, widget);
5165             if (groupBoxCopy.subControls != groupBox->subControls) {
5166                 bool checkable = groupBox->subControls & SC_GroupBoxCheckBox;
5167                 p->save();
5168                 CGContextSetShouldAntialias(cg, true);
5169                 CGContextSetShouldSmoothFonts(cg, true);
5170                 HIThemeTextInfo tti;
5171                 tti.version = qt_mac_hitheme_version;
5172                 tti.state = tds;
5173                 QColor textColor = groupBox->palette.windowText().color();
5174                 CGFloat colorComp[] = { textColor.redF(), textColor.greenF(),
5175                                       textColor.blueF(), textColor.alphaF() };
5176                 CGContextSetFillColorSpace(cg, qt_mac_genericColorSpace());
5177                 CGContextSetFillColor(cg, colorComp);
5178                 tti.fontID = checkable ? kThemeSystemFont : kThemeSmallSystemFont;
5179                 tti.horizontalFlushness = kHIThemeTextHorizontalFlushCenter;
5180                 tti.verticalFlushness = kHIThemeTextVerticalFlushCenter;
5181                 tti.options = kHIThemeTextBoxOptionNone;
5182                 tti.truncationPosition = kHIThemeTextTruncationNone;
5183                 tti.truncationMaxLines = 1 + groupBox->text.count(QLatin1Char('\n'));
5184                 QCFString groupText = qt_mac_removeMnemonics(groupBox->text);
5185                 QRect r = proxy()->subControlRect(CC_GroupBox, groupBox, SC_GroupBoxLabel, widget);
5186                 HIRect bounds = qt_hirectForQRect(r);
5187                 HIThemeDrawTextBox(groupText, &bounds, &tti, cg, kHIThemeOrientationNormal);
5188                 p->restore();
5189             }
5190         }
5191         break;
5192     case CC_ToolButton:
5193         if (const QStyleOptionToolButton *tb
5194                 = qstyleoption_cast<const QStyleOptionToolButton *>(opt)) {
5195             if (widget && qobject_cast<QToolBar *>(widget->parentWidget())) {
5196                 if (tb->subControls & SC_ToolButtonMenu) {
5197                     QStyleOption arrowOpt(0);
5198                     arrowOpt.rect = proxy()->subControlRect(cc, tb, SC_ToolButtonMenu, widget);
5199                     arrowOpt.rect.setY(arrowOpt.rect.y() + arrowOpt.rect.height() / 2);
5200                     arrowOpt.rect.setHeight(arrowOpt.rect.height() / 2);
5201                     arrowOpt.state = tb->state;
5202                     arrowOpt.palette = tb->palette;
5203                     proxy()->drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, p, widget);
5204                 } else if ((tb->features & QStyleOptionToolButton::HasMenu)
5205                             && (tb->toolButtonStyle != Qt::ToolButtonTextOnly && !tb->icon.isNull())) {
5206                     drawToolbarButtonArrow(tb->rect, tds, cg);
5207                 }
5208                 if (tb->state & State_On) {
5209                     if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) {
5210                         static QPixmap pm(QLatin1String(":/trolltech/mac/style/images/leopard-unified-toolbar-on.png"));
5211                         p->setRenderHint(QPainter::SmoothPixmapTransform);
5212                         QStyleHelper::drawBorderPixmap(pm, p, tb->rect, 2, 2, 2, 2);
5213                     } else {
5214                         QPen oldPen = p->pen();
5215                         p->setPen(QColor(0, 0, 0, 0x3a));
5216                         p->fillRect(tb->rect.adjusted(1, 1, -1, -1), QColor(0, 0, 0, 0x12));
5217                         p->drawLine(tb->rect.left() + 1, tb->rect.top(),
5218                                     tb->rect.right() - 1, tb->rect.top());
5219                         p->drawLine(tb->rect.left() + 1, tb->rect.bottom(),
5220                                     tb->rect.right() - 1, tb->rect.bottom());
5221                         p->drawLine(tb->rect.topLeft(), tb->rect.bottomLeft());
5222                         p->drawLine(tb->rect.topRight(), tb->rect.bottomRight());
5223                         p->setPen(oldPen);
5224                     }
5225                 }
5226                 proxy()->drawControl(CE_ToolButtonLabel, opt, p, widget);
5227             } else {
5228                 ThemeButtonKind bkind = kThemeBevelButton;
5229                 switch (d->aquaSizeConstrain(opt, widget)) {
5230                 case QAquaSizeUnknown:
5231                 case QAquaSizeLarge:
5232                     bkind = kThemeBevelButton;
5233                     break;
5234                 case QAquaSizeMini:
5235                 case QAquaSizeSmall:
5236                     bkind = kThemeSmallBevelButton;
5237                     break;
5238                 }
5239
5240                 QRect button, menuarea;
5241                 button   = proxy()->subControlRect(cc, tb, SC_ToolButton, widget);
5242                 menuarea = proxy()->subControlRect(cc, tb, SC_ToolButtonMenu, widget);
5243                 State bflags = tb->state,
5244                 mflags = tb->state;
5245                 if (tb->subControls & SC_ToolButton)
5246                     bflags |= State_Sunken;
5247                 if (tb->subControls & SC_ToolButtonMenu)
5248                     mflags |= State_Sunken;
5249
5250                 if (tb->subControls & SC_ToolButton) {
5251                     if (bflags & (State_Sunken | State_On | State_Raised)) {
5252                         HIThemeButtonDrawInfo bdi;
5253                         bdi.version = qt_mac_hitheme_version;
5254                         bdi.state = tds;
5255                         bdi.adornment = kThemeAdornmentNone;
5256                         bdi.kind = bkind;
5257                         bdi.value = kThemeButtonOff;
5258                         if (tb->state & State_HasFocus)
5259                             bdi.adornment = kThemeAdornmentFocus;
5260                         if (tb->state & State_Sunken)
5261                             bdi.state = kThemeStatePressed;
5262                         if (tb->state & State_On)
5263                             bdi.value = kThemeButtonOn;
5264
5265                         QRect off_rct(0, 0, 0, 0);
5266                         HIRect myRect, macRect;
5267                         myRect = CGRectMake(tb->rect.x(), tb->rect.y(),
5268                                             tb->rect.width(), tb->rect.height());
5269                         HIThemeGetButtonBackgroundBounds(&myRect, &bdi, &macRect);
5270                         off_rct.setRect(int(myRect.origin.x - macRect.origin.x),
5271                                         int(myRect.origin.y - macRect.origin.y),
5272                                         int(macRect.size.width - myRect.size.width),
5273                                         int(macRect.size.height - myRect.size.height));
5274
5275                         myRect = qt_hirectForQRect(button, off_rct);
5276                         HIThemeDrawButton(&myRect, &bdi, cg, kHIThemeOrientationNormal, 0);
5277                     }
5278                 }
5279
5280                 if (tb->subControls & SC_ToolButtonMenu) {
5281                     HIThemeButtonDrawInfo bdi;
5282                     bdi.version = qt_mac_hitheme_version;
5283                     bdi.state = tds;
5284                     bdi.value = kThemeButtonOff;
5285                     bdi.adornment = kThemeAdornmentNone;
5286                     bdi.kind = bkind;
5287                     if (tb->state & State_HasFocus)
5288                         bdi.adornment = kThemeAdornmentFocus;
5289                     if (tb->state & (State_On | State_Sunken)
5290                                      || (tb->activeSubControls & SC_ToolButtonMenu))
5291                         bdi.state = kThemeStatePressed;
5292                     HIRect hirect = qt_hirectForQRect(menuarea);
5293                     HIThemeDrawButton(&hirect, &bdi, cg, kHIThemeOrientationNormal, 0);
5294                     QRect r(menuarea.x() + ((menuarea.width() / 2) - 3), menuarea.height() - 8, 8, 8);
5295                     HIThemePopupArrowDrawInfo padi;
5296                     padi.version = qt_mac_hitheme_version;
5297                     padi.state = tds;
5298                     padi.orientation = kThemeArrowDown;
5299                     padi.size = kThemeArrow7pt;
5300                     hirect = qt_hirectForQRect(r);
5301                     HIThemeDrawPopupArrow(&hirect, &padi, cg, kHIThemeOrientationNormal);
5302                 } else if (tb->features & QStyleOptionToolButton::HasMenu) {
5303                     drawToolbarButtonArrow(tb->rect, tds, cg);
5304                 }
5305                 QRect buttonRect = proxy()->subControlRect(CC_ToolButton, tb, SC_ToolButton, widget);
5306                 int fw = proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget);
5307                 QStyleOptionToolButton label = *tb;
5308                 label.rect = buttonRect.adjusted(fw, fw, -fw, -fw);
5309                 proxy()->drawControl(CE_ToolButtonLabel, &label, p, widget);
5310             }
5311         }
5312         break;
5313     case CC_Dial:
5314         if (const QStyleOptionSlider *dial = qstyleoption_cast<const QStyleOptionSlider *>(opt))
5315             QStyleHelper::drawDial(dial, p);
5316         break;
5317     default:
5318         QWindowsStyle::drawComplexControl(cc, opt, p, widget);
5319         break;
5320     }
5321 }
5322
5323 QStyle::SubControl QMacStyle::hitTestComplexControl(ComplexControl cc,
5324                                                     const QStyleOptionComplex *opt,
5325                                                     const QPoint &pt, const QWidget *widget) const
5326 {
5327     SubControl sc = QStyle::SC_None;
5328     switch (cc) {
5329     case CC_ComboBox:
5330         if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) {
5331             sc = QWindowsStyle::hitTestComplexControl(cc, cmb, pt, widget);
5332             if (!cmb->editable && sc != QStyle::SC_None)
5333                 sc = SC_ComboBoxArrow;  // A bit of a lie, but what we want
5334         }
5335         break;
5336     case CC_Slider:
5337         if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
5338             HIThemeTrackDrawInfo tdi;
5339             d->getSliderInfo(cc, slider, &tdi, widget);
5340             ControlPartCode part;
5341             HIPoint pos = CGPointMake(pt.x(), pt.y());
5342             if (HIThemeHitTestTrack(&tdi, &pos, &part)) {
5343                 if (part == kControlPageUpPart || part == kControlPageDownPart)
5344                     sc = SC_SliderGroove;
5345                 else
5346                     sc = SC_SliderHandle;
5347             }
5348         }
5349         break;
5350     case CC_ScrollBar:
5351         if (const QStyleOptionSlider *sb = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
5352             HIScrollBarTrackInfo sbi;
5353             sbi.version = qt_mac_hitheme_version;
5354             if (!(sb->state & State_Active))
5355                 sbi.enableState = kThemeTrackInactive;
5356             else if (sb->state & State_Enabled)
5357                 sbi.enableState = kThemeTrackActive;
5358             else
5359                 sbi.enableState = kThemeTrackDisabled;
5360
5361             // The arrow buttons are not drawn if the scroll bar is to short,
5362             // exclude them from the hit test.
5363             const int scrollBarLength = (sb->orientation == Qt::Horizontal)
5364                 ? sb->rect.width() : sb->rect.height();
5365             if (scrollBarLength < scrollButtonsCutoffSize(scrollButtonsCutoff, widgetSizePolicy(widget)))
5366                 sbi.enableState = kThemeTrackNothingToScroll;
5367
5368             sbi.viewsize = sb->pageStep;
5369             HIPoint pos = CGPointMake(pt.x(), pt.y());
5370
5371             HIRect macSBRect = qt_hirectForQRect(sb->rect);
5372             ControlPartCode part;
5373             bool reverseHorizontal = (sb->direction == Qt::RightToLeft
5374                                       && sb->orientation == Qt::Horizontal
5375                                       && (!sb->upsideDown ||
5376                                           (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4
5377                                                       && sb->upsideDown)));
5378             if (HIThemeHitTestScrollBarArrows(&macSBRect, &sbi, sb->orientation == Qt::Horizontal,
5379                         &pos, 0, &part)) {
5380                 if (part == kControlUpButtonPart)
5381                     sc = reverseHorizontal ? SC_ScrollBarAddLine : SC_ScrollBarSubLine;
5382                 else if (part == kControlDownButtonPart)
5383                     sc = reverseHorizontal ? SC_ScrollBarSubLine : SC_ScrollBarAddLine;
5384             } else {
5385                 HIThemeTrackDrawInfo tdi;
5386                 d->getSliderInfo(cc, sb, &tdi, widget);
5387                 if(tdi.enableState == kThemeTrackInactive)
5388                     tdi.enableState = kThemeTrackActive;
5389                 if (HIThemeHitTestTrack(&tdi, &pos, &part)) {
5390                     if (part == kControlPageUpPart)
5391                         sc = reverseHorizontal ? SC_ScrollBarAddPage
5392                                                : SC_ScrollBarSubPage;
5393                     else if (part == kControlPageDownPart)
5394                         sc = reverseHorizontal ? SC_ScrollBarSubPage
5395                                                : SC_ScrollBarAddPage;
5396                     else
5397                         sc = SC_ScrollBarSlider;
5398                 }
5399             }
5400         }
5401         break;
5402 /*
5403     I don't know why, but we only get kWindowContentRgn here, which isn't what we want at all.
5404     It would be very nice if this would work.
5405     case QStyle::CC_TitleBar:
5406         if (const QStyleOptionTitleBar *tbar = qstyleoption_cast<const QStyleOptionTitleBar *>(opt)) {
5407             HIThemeWindowDrawInfo wdi;
5408             memset(&wdi, 0, sizeof(wdi));
5409             wdi.version = qt_mac_hitheme_version;
5410             wdi.state = kThemeStateActive;
5411             wdi.windowType = QtWinType;
5412             wdi.titleWidth = tbar->rect.width();
5413             wdi.titleHeight = tbar->rect.height();
5414             if (tbar->titleBarState)
5415                 wdi.attributes |= kThemeWindowHasFullZoom | kThemeWindowHasCloseBox
5416                                   | kThemeWindowHasCollapseBox;
5417             else if (tbar->titleBarFlags & Qt::WindowSystemMenuHint)
5418                 wdi.attributes |= kThemeWindowHasCloseBox;
5419             QRect tmpRect = tbar->rect;
5420             tmpRect.setHeight(tmpRect.height() + 100);
5421             HIRect hirect = qt_hirectForQRect(tmpRect);
5422             WindowRegionCode hit;
5423             HIPoint hipt = CGPointMake(pt.x(), pt.y());
5424             if (HIThemeGetWindowRegionHit(&hirect, &wdi, &hipt, &hit)) {
5425                 switch (hit) {
5426                 case kWindowCloseBoxRgn:
5427                     sc = QStyle::SC_TitleBarCloseButton;
5428                     break;
5429                 case kWindowCollapseBoxRgn:
5430                     sc = QStyle::SC_TitleBarMinButton;
5431                     break;
5432                 case kWindowZoomBoxRgn:
5433                     sc = QStyle::SC_TitleBarMaxButton;
5434                     break;
5435                 case kWindowTitleTextRgn:
5436                     sc = QStyle::SC_TitleBarLabel;
5437                     break;
5438                 default:
5439                     qDebug("got something else %d", hit);
5440                     break;
5441                 }
5442             }
5443         }
5444         break;
5445 */
5446     default:
5447         sc = QWindowsStyle::hitTestComplexControl(cc, opt, pt, widget);
5448         break;
5449     }
5450     return sc;
5451 }
5452
5453 QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *opt, SubControl sc,
5454                                 const QWidget *widget) const
5455 {
5456     QRect ret;
5457     switch (cc) {
5458     case CC_Slider:
5459     case CC_ScrollBar:
5460         if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
5461             HIThemeTrackDrawInfo tdi;
5462             d->getSliderInfo(cc, slider, &tdi, widget);
5463             HIRect macRect;
5464             QCFType<HIShapeRef> shape;
5465             bool scrollBar = cc == CC_ScrollBar;
5466             if ((scrollBar && sc == SC_ScrollBarSlider)
5467                 || (!scrollBar && sc == SC_SliderHandle)) {
5468                 HIThemeGetTrackThumbShape(&tdi, &shape);
5469                 ptrHIShapeGetBounds(shape, &macRect);
5470             } else if (!scrollBar && sc == SC_SliderGroove) {
5471                 HIThemeGetTrackBounds(&tdi, &macRect);
5472             } else if (sc == SC_ScrollBarGroove) { // Only scroll bar parts available...
5473                 HIThemeGetTrackDragRect(&tdi, &macRect);
5474             } else {
5475                 ControlPartCode cpc;
5476                 if (sc == SC_ScrollBarSubPage || sc == SC_ScrollBarAddPage) {
5477                     cpc = sc == SC_ScrollBarSubPage ? kControlPageDownPart
5478                                                             : kControlPageUpPart;
5479                 } else {
5480                     cpc = sc == SC_ScrollBarSubLine ? kControlUpButtonPart
5481                                                             : kControlDownButtonPart;
5482                     if (slider->direction == Qt::RightToLeft
5483                         && slider->orientation == Qt::Horizontal) {
5484                         if (cpc == kControlDownButtonPart)
5485                             cpc = kControlUpButtonPart;
5486                         else if (cpc == kControlUpButtonPart)
5487                             cpc = kControlDownButtonPart;
5488                     }
5489                 }
5490                 HIThemeGetTrackPartBounds(&tdi, cpc, &macRect);
5491             }
5492             ret = qt_qrectForHIRect(macRect);
5493
5494             // Tweak: the dark line between the sub/add line buttons belong to only one of the buttons
5495             // when doing hit-testing, but both of them have to repaint it. Extend the rect to cover
5496             // the line in the cases where HIThemeGetTrackPartBounds returns a rect that doesn't.
5497             if (slider->orientation == Qt::Horizontal) {
5498                 if (slider->direction == Qt::LeftToRight && sc == SC_ScrollBarSubLine)
5499                     ret.adjust(0, 0, 1, 0);
5500                 else if (slider->direction == Qt::RightToLeft && sc == SC_ScrollBarAddLine)
5501                     ret.adjust(-1, 0, 1, 0);
5502             } else if (sc == SC_ScrollBarAddLine) {
5503                 ret.adjust(0, -1, 0, 1);
5504             }
5505         }
5506         break;
5507     case CC_TitleBar:
5508         if (const QStyleOptionTitleBar *titlebar
5509                 = qstyleoption_cast<const QStyleOptionTitleBar *>(opt)) {
5510             HIThemeWindowDrawInfo wdi;
5511             memset(&wdi, 0, sizeof(wdi));
5512             wdi.version = qt_mac_hitheme_version;
5513             wdi.state = kThemeStateActive;
5514             wdi.windowType = QtWinType;
5515             wdi.titleHeight = titlebar->rect.height();
5516             wdi.titleWidth = titlebar->rect.width();
5517             wdi.attributes = kThemeWindowHasTitleText;
5518             if (titlebar->subControls & SC_TitleBarCloseButton)
5519                 wdi.attributes |= kThemeWindowHasCloseBox;
5520             if (titlebar->subControls & SC_TitleBarMaxButton
5521                                         | SC_TitleBarNormalButton)
5522                 wdi.attributes |= kThemeWindowHasFullZoom;
5523             if (titlebar->subControls & SC_TitleBarMinButton)
5524                 wdi.attributes |= kThemeWindowHasCollapseBox;
5525             WindowRegionCode wrc = kWindowGlobalPortRgn;
5526
5527             if (sc == SC_TitleBarCloseButton)
5528                 wrc = kWindowCloseBoxRgn;
5529             else if (sc == SC_TitleBarMinButton)
5530                 wrc = kWindowCollapseBoxRgn;
5531             else if (sc == SC_TitleBarMaxButton)
5532                 wrc = kWindowZoomBoxRgn;
5533             else if (sc == SC_TitleBarLabel)
5534                 wrc = kWindowTitleTextRgn;
5535             else if (sc == SC_TitleBarSysMenu)
5536                 ret.setRect(-1024, -1024, 10, proxy()->pixelMetric(PM_TitleBarHeight,
5537                                                              titlebar, widget));
5538             if (wrc != kWindowGlobalPortRgn) {
5539                 QCFType<HIShapeRef> region;
5540                 QRect tmpRect = titlebar->rect;
5541                 HIRect titleRect = qt_hirectForQRect(tmpRect);
5542                 HIThemeGetWindowShape(&titleRect, &wdi, kWindowTitleBarRgn, &region);
5543                 ptrHIShapeGetBounds(region, &titleRect);
5544                 CFRelease(region);
5545                 tmpRect.translate(tmpRect.x() - int(titleRect.origin.x),
5546                                tmpRect.y() - int(titleRect.origin.y));
5547                 titleRect = qt_hirectForQRect(tmpRect);
5548                 HIThemeGetWindowShape(&titleRect, &wdi, wrc, &region);
5549                 ptrHIShapeGetBounds(region, &titleRect);
5550                 ret = qt_qrectForHIRect(titleRect);
5551             }
5552         }
5553         break;
5554     case CC_ComboBox:
5555         if (const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) {
5556             HIThemeButtonDrawInfo bdi;
5557             d->initComboboxBdi(combo, &bdi, widget, d->getDrawState(opt->state));
5558
5559             switch (sc) {
5560             case SC_ComboBoxEditField:{
5561                 ret = QMacStylePrivate::comboboxEditBounds(combo->rect, bdi);
5562                     // hack to posistion the edit feld correctly for QDateTimeEdits
5563                     // in calendarPopup mode.
5564                     if (qobject_cast<const QDateTimeEdit *>(widget)) {
5565                        ret.moveTop(ret.top() - 2);
5566                        ret.setHeight(ret.height() +1);
5567                     }
5568                 break; }
5569             case SC_ComboBoxArrow:{
5570                 ret = QMacStylePrivate::comboboxEditBounds(combo->rect, bdi);
5571                 ret.setX(ret.x() + ret.width());
5572                 ret.setWidth(combo->rect.right() - ret.right());
5573                 break; }
5574             case SC_ComboBoxListBoxPopup:{
5575                 if (combo->editable) {
5576                     HIRect inner = QMacStylePrivate::comboboxInnerBounds(qt_hirectForQRect(combo->rect), bdi.kind);
5577                     QRect editRect = QMacStylePrivate::comboboxEditBounds(combo->rect, bdi);
5578                     const int comboTop = combo->rect.top();
5579                     ret = QRect(qRound(inner.origin.x),
5580                                 comboTop,
5581                                 qRound(inner.origin.x - combo->rect.left() + inner.size.width),
5582                                 editRect.bottom() - comboTop + 2);
5583                 } else {
5584                     QRect editRect = QMacStylePrivate::comboboxEditBounds(combo->rect, bdi);
5585                     ret = QRect(combo->rect.x() + 4 - 11,
5586                                 combo->rect.y() + 1,
5587                                 editRect.width() + 10 + 11,
5588                                 1);
5589                  }
5590                 break; }
5591             default:
5592                 break;
5593             }
5594         }
5595         break;
5596     case CC_GroupBox:
5597         if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(opt)) {
5598             bool checkable = groupBox->subControls & SC_GroupBoxCheckBox;
5599             bool flat = (groupBox->features & QStyleOptionFrameV2::Flat);
5600             bool hasNoText = !checkable && groupBox->text.isEmpty();
5601             switch (sc) {
5602             case SC_GroupBoxLabel:
5603             case SC_GroupBoxCheckBox: {
5604                 // Cheat and use the smaller font if we need to
5605                 bool checkable = groupBox->subControls & SC_GroupBoxCheckBox;
5606                 bool fontIsSet = (widget && widget->testAttribute(Qt::WA_SetFont))
5607                                   || !QApplication::desktopSettingsAware();
5608                 int tw;
5609                 int h;
5610                 int margin =  flat || hasNoText ? 0 : 12;
5611                 ret = groupBox->rect.adjusted(margin, 0, -margin, 0);
5612
5613                 if (!fontIsSet) {
5614                     HIThemeTextInfo tti;
5615                     tti.version = qt_mac_hitheme_version;
5616                     tti.state = kThemeStateActive;
5617                     tti.fontID = checkable ? kThemeSystemFont : kThemeSmallSystemFont;
5618                     tti.horizontalFlushness = kHIThemeTextHorizontalFlushCenter;
5619                     tti.verticalFlushness = kHIThemeTextVerticalFlushCenter;
5620                     tti.options = kHIThemeTextBoxOptionNone;
5621                     tti.truncationPosition = kHIThemeTextTruncationNone;
5622                     tti.truncationMaxLines = 1 + groupBox->text.count(QLatin1Char('\n'));
5623                     CGFloat width;
5624                     CGFloat height;
5625                     QCFString groupText = qt_mac_removeMnemonics(groupBox->text);
5626                     HIThemeGetTextDimensions(groupText, 0, &tti, &width, &height, 0);
5627                     tw = qRound(width);
5628                     h = qCeil(height);
5629                 } else {
5630                     QFontMetricsF fm = QFontMetricsF(groupBox->fontMetrics);
5631                     h = qCeil(fm.height());
5632                     tw = qCeil(fm.size(Qt::TextShowMnemonic, groupBox->text).width());
5633                 }
5634                 ret.setHeight(h);
5635
5636                 QRect labelRect = alignedRect(groupBox->direction, groupBox->textAlignment,
5637                                               QSize(tw, h), ret);
5638                 int indicatorWidth = proxy()->pixelMetric(PM_IndicatorWidth, opt, widget);
5639                 bool rtl = groupBox->direction == Qt::RightToLeft;
5640                 if (sc == SC_GroupBoxLabel) {
5641                     if (checkable) {
5642                         int newSum = indicatorWidth + 1;
5643                         int newLeft = labelRect.left() + (rtl ? -newSum : newSum);
5644                         labelRect.moveLeft(newLeft);
5645                     } else if (flat) {
5646                         int newLeft = labelRect.left() - (rtl ? 3 : -3);
5647                         labelRect.moveLeft(newLeft);
5648                         labelRect.moveTop(labelRect.top() + 3);
5649                     } else {
5650                         int newLeft = labelRect.left() - (rtl ? 3 : 2);
5651                         labelRect.moveLeft(newLeft);
5652                         labelRect.moveTop(labelRect.top() + 5);
5653                     }
5654                     ret = labelRect;
5655                 }
5656
5657                 if (sc == SC_GroupBoxCheckBox) {
5658                     int left = rtl ? labelRect.right() - indicatorWidth : labelRect.left();
5659                     ret.setRect(left, ret.top(),
5660                                 indicatorWidth, proxy()->pixelMetric(PM_IndicatorHeight, opt, widget));
5661                 }
5662                 break;
5663             }
5664             case SC_GroupBoxContents:
5665             case SC_GroupBoxFrame: {
5666                 if (flat) {
5667                     ret = QWindowsStyle::subControlRect(cc, groupBox, sc, widget);
5668                     break;
5669                 }
5670                 QFontMetrics fm = groupBox->fontMetrics;
5671                 bool checkable = groupBox->subControls & SC_GroupBoxCheckBox;
5672                 int yOffset = 3;
5673                 if (!checkable) {
5674                     if (widget && !widget->testAttribute(Qt::WA_SetFont)
5675                             && QApplication::desktopSettingsAware())
5676                         fm = QFontMetrics(qt_app_fonts_hash()->value("QSmallFont", QFont()));
5677                     yOffset = 5;
5678                     if (hasNoText)
5679                         yOffset = -qCeil(QFontMetricsF(fm).height());
5680                 }
5681
5682                 ret = opt->rect.adjusted(0, qCeil(QFontMetricsF(fm).height()) + yOffset, 0, 0);
5683                 if (sc == SC_GroupBoxContents)
5684                     ret.adjust(3, 3, -3, -4);    // guess
5685             }
5686                 break;
5687             default:
5688                 ret = QWindowsStyle::subControlRect(cc, groupBox, sc, widget);
5689                 break;
5690             }
5691         }
5692         break;
5693     case CC_SpinBox:
5694         if (const QStyleOptionSpinBox *spin = qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) {
5695             QAquaWidgetSize aquaSize = d->aquaSizeConstrain(spin, widget);
5696             int spinner_w;
5697             int spinBoxSep;
5698             int fw = proxy()->pixelMetric(PM_SpinBoxFrameWidth, spin, widget);
5699             switch (aquaSize) {
5700             default:
5701             case QAquaSizeUnknown:
5702             case QAquaSizeLarge:
5703                 spinner_w = 14;
5704                 spinBoxSep = 2;
5705                 break;
5706             case QAquaSizeSmall:
5707                 spinner_w = 12;
5708                 spinBoxSep = 2;
5709                 break;
5710             case QAquaSizeMini:
5711                 spinner_w = 10;
5712                 spinBoxSep = 1;
5713                 break;
5714             }
5715
5716             switch (sc) {
5717             case SC_SpinBoxUp:
5718             case SC_SpinBoxDown: {
5719                 if (spin->buttonSymbols == QAbstractSpinBox::NoButtons)
5720                     break;
5721
5722                 const int y = fw;
5723                 const int x = spin->rect.width() - spinner_w;
5724                 ret.setRect(x + spin->rect.x(), y + spin->rect.y(), spinner_w, spin->rect.height() - y * 2);
5725                 HIThemeButtonDrawInfo bdi;
5726                 bdi.version = qt_mac_hitheme_version;
5727                 bdi.kind = kThemeIncDecButton;
5728                 int hackTranslateX;
5729                 switch (aquaSize) {
5730                 default:
5731                 case QAquaSizeUnknown:
5732                 case QAquaSizeLarge:
5733                     bdi.kind = kThemeIncDecButton;
5734                     hackTranslateX = 0;
5735                     break;
5736                 case QAquaSizeSmall:
5737                     bdi.kind = kThemeIncDecButtonSmall;
5738                     hackTranslateX = -2;
5739                     break;
5740                 case QAquaSizeMini:
5741                     bdi.kind = kThemeIncDecButtonMini;
5742                     hackTranslateX = -1;
5743                     break;
5744                 }
5745                 bdi.state = kThemeStateActive;
5746                 bdi.value = kThemeButtonOff;
5747                 bdi.adornment = kThemeAdornmentNone;
5748                 HIRect hirect = qt_hirectForQRect(ret);
5749
5750                 HIRect outRect;
5751                 HIThemeGetButtonBackgroundBounds(&hirect, &bdi, &outRect);
5752                 ret = qt_qrectForHIRect(outRect);
5753                 switch (sc) {
5754                 case SC_SpinBoxUp:
5755                     ret.setHeight(ret.height() / 2);
5756                     break;
5757                 case SC_SpinBoxDown:
5758                     ret.setY(ret.y() + ret.height() / 2);
5759                     break;
5760                 default:
5761                     Q_ASSERT(0);
5762                     break;
5763                 }
5764                 ret.translate(hackTranslateX, 0); // hack: position the buttons correctly (weird that we need this)
5765                 ret = visualRect(spin->direction, spin->rect, ret);
5766                 break;
5767             }
5768             case SC_SpinBoxEditField:
5769                 if (spin->buttonSymbols == QAbstractSpinBox::NoButtons) {
5770                     ret.setRect(fw, fw,
5771                                 spin->rect.width() - fw * 2,
5772                                 spin->rect.height() - fw * 2);
5773                 } else {
5774                     ret.setRect(fw, fw,
5775                                 spin->rect.width() - fw * 2 - spinBoxSep - spinner_w,
5776                                 spin->rect.height() - fw * 2);
5777                 }
5778                 ret = visualRect(spin->direction, spin->rect, ret);
5779                 break;
5780             default:
5781                 ret = QWindowsStyle::subControlRect(cc, spin, sc, widget);
5782                 break;
5783             }
5784         }
5785         break;
5786     case CC_ToolButton:
5787         ret = QWindowsStyle::subControlRect(cc, opt, sc, widget);
5788         if (sc == SC_ToolButtonMenu && widget && !qobject_cast<QToolBar*>(widget->parentWidget())) {
5789             ret.adjust(-1, 0, 0, 0);
5790         }
5791         break;
5792     default:
5793         ret = QWindowsStyle::subControlRect(cc, opt, sc, widget);
5794         break;
5795     }
5796     return ret;
5797 }
5798
5799 QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
5800                                   const QSize &csz, const QWidget *widget) const
5801 {
5802     QSize sz(csz);
5803     bool useAquaGuideline = true;
5804
5805     switch (ct) {
5806     case QStyle::CT_SpinBox:
5807          // hack to work around horrible sizeHint() code in QAbstractSpinBox
5808         sz.setHeight(sz.height() - 3);
5809         break;
5810         case QStyle::CT_TabWidget:
5811         // the size between the pane and the "contentsRect" (+4,+4)
5812         // (the "contentsRect" is on the inside of the pane)
5813         sz = QWindowsStyle::sizeFromContents(ct, opt, csz, widget);
5814         /**
5815             This is supposed to show the relationship between the tabBar and
5816             the stack widget of a QTabWidget.
5817             Unfortunately ascii is not a good way of representing graphics.....
5818             PS: The '=' line is the painted frame.
5819
5820                top    ---+
5821                          |
5822                          |
5823                          |
5824                          |                vvv just outside the painted frame is the "pane"
5825                       - -|- - - - - - - - - - <-+
5826             TAB BAR      +=====^============    | +2 pixels
5827                     - - -|- - -|- - - - - - - <-+
5828                          |     |      ^   ^^^ just inside the painted frame is the "contentsRect"
5829                          |     |      |
5830                          |   overlap  |
5831                          |     |      |
5832             bottom ------+   <-+     +14 pixels
5833                                       |
5834                                       v
5835                 ------------------------------  <- top of stack widget
5836
5837
5838         To summarize: 
5839              * 2 is the distance between the pane and the contentsRect 
5840              * The 14 and the 1's are the distance from the contentsRect to the stack widget.
5841                (same value as used in SE_TabWidgetTabContents)
5842              * overlap is how much the pane should overlap the tab bar
5843         */      
5844         // then add the size between the stackwidget and the "contentsRect"
5845
5846         if (const QStyleOptionTabWidgetFrame *twf
5847                 = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) {
5848             QSize extra(0,0);
5849             const int overlap = pixelMetric(PM_TabBarBaseOverlap, opt, widget);
5850             const int gapBetweenTabbarAndStackWidget = 2 + 14 - overlap;
5851
5852             if (getTabDirection(twf->shape) == kThemeTabNorth || getTabDirection(twf->shape) == kThemeTabSouth) {
5853                 extra = QSize(2, gapBetweenTabbarAndStackWidget + 1);
5854             } else {
5855                 extra = QSize(gapBetweenTabbarAndStackWidget + 1, 2);
5856             }
5857             sz+= extra;
5858         }
5859
5860         break;
5861     case QStyle::CT_TabBarTab:
5862         if (const QStyleOptionTabV3 *tab = qstyleoption_cast<const QStyleOptionTabV3 *>(opt)) {
5863             const QAquaWidgetSize AquaSize = d->aquaSizeConstrain(opt, widget);
5864             const bool differentFont = (widget && widget->testAttribute(Qt::WA_SetFont))
5865                                        || !QApplication::desktopSettingsAware();
5866             ThemeTabDirection ttd = getTabDirection(tab->shape);
5867             bool vertTabs = ttd == kThemeTabWest || ttd == kThemeTabEast;
5868             if (vertTabs)
5869                 sz.transpose();
5870             int defaultTabHeight;
5871             int defaultExtraSpace = proxy()->pixelMetric(PM_TabBarTabHSpace, tab, widget); // Remove spurious gcc warning (AFAIK)
5872             QFontMetrics fm = opt->fontMetrics;
5873             switch (AquaSize) {
5874             case QAquaSizeUnknown:
5875             case QAquaSizeLarge:
5876                 if (tab->documentMode)
5877                     defaultTabHeight = 23;
5878                 else
5879                     defaultTabHeight = 21;
5880                 break;
5881             case QAquaSizeSmall:
5882                 defaultTabHeight = 18;
5883                 break;
5884             case QAquaSizeMini:
5885                 defaultTabHeight = 16;
5886                 break;
5887             }
5888             bool setWidth = false;
5889             if (differentFont || !tab->icon.isNull()) {
5890                 sz.rheight() = qMax(defaultTabHeight, sz.height());
5891             } else {
5892                 QSize textSize = fm.size(Qt::TextShowMnemonic, tab->text);
5893                 sz.rheight() = qMax(defaultTabHeight, textSize.height());
5894                 sz.rwidth() = textSize.width() + defaultExtraSpace;
5895                 setWidth = true;
5896             }
5897
5898             if (vertTabs)
5899                 sz.transpose();
5900
5901             int maxWidgetHeight = qMax(tab->leftButtonSize.height(), tab->rightButtonSize.height());
5902             int maxWidgetWidth = qMax(tab->leftButtonSize.width(), tab->rightButtonSize.width());
5903
5904             int widgetWidth = 0;
5905             int widgetHeight = 0;
5906             int padding = 0;
5907             if (tab->leftButtonSize.isValid()) {
5908                 padding += 8;
5909                 widgetWidth += tab->leftButtonSize.width();
5910                 widgetHeight += tab->leftButtonSize.height();
5911             }
5912             if (tab->rightButtonSize.isValid()) {
5913                 padding += 8;
5914                 widgetWidth += tab->rightButtonSize.width();
5915                 widgetHeight += tab->rightButtonSize.height();
5916             }
5917
5918             if (vertTabs) {
5919                 sz.setHeight(sz.height() + widgetHeight + padding);
5920                 sz.setWidth(qMax(sz.width(), maxWidgetWidth));
5921             } else {
5922                 if (setWidth)
5923                     sz.setWidth(sz.width() + widgetWidth + padding);
5924                 sz.setHeight(qMax(sz.height(), maxWidgetHeight));
5925             }
5926         }
5927         break;
5928     case QStyle::CT_PushButton:
5929         // By default, we fit the contents inside a normal rounded push button.
5930         // Do this by add enough space around the contents so that rounded
5931         // borders (including highlighting when active) will show.
5932         sz.rwidth() += QMacStylePrivate::PushButtonLeftOffset + QMacStylePrivate::PushButtonRightOffset + 12;
5933         sz.rheight() += QMacStylePrivate::PushButtonTopOffset + QMacStylePrivate::PushButtonBottomOffset;
5934         break;
5935     case QStyle::CT_MenuItem:
5936         if (const QStyleOptionMenuItem *mi = qstyleoption_cast<const QStyleOptionMenuItem *>(opt)) {
5937             int maxpmw = mi->maxIconWidth;
5938             const QComboBox *comboBox = qobject_cast<const QComboBox *>(widget);
5939             int w = sz.width(),
5940                 h = sz.height();
5941             if (mi->menuItemType == QStyleOptionMenuItem::Separator) {
5942                 w = 10;
5943                 SInt16 ash;
5944                 GetThemeMenuSeparatorHeight(&ash);
5945                 h = ash;
5946             } else {
5947                 h = mi->fontMetrics.height() + 2;
5948                 if (!mi->icon.isNull()) {
5949                     if (comboBox) {
5950                         const QSize &iconSize = comboBox->iconSize();
5951                         h = qMax(h, iconSize.height() + 4);
5952                         maxpmw = qMax(maxpmw, iconSize.width());
5953                     } else {
5954                         int iconExtent = proxy()->pixelMetric(PM_SmallIconSize);
5955                         h = qMax(h, mi->icon.actualSize(QSize(iconExtent, iconExtent)).height() + 4);
5956                     }
5957                 }
5958             }
5959             if (mi->text.contains(QLatin1Char('\t')))
5960                 w += 12;
5961             if (mi->menuItemType == QStyleOptionMenuItem::SubMenu)
5962                 w += 20;
5963             if (maxpmw)
5964                 w += maxpmw + 6;
5965             // add space for a check. All items have place for a check too.
5966             w += 20;
5967             if (comboBox && comboBox->isVisible()) {
5968                 QStyleOptionComboBox cmb;
5969                 cmb.initFrom(comboBox);
5970                 cmb.editable = false;
5971                 cmb.subControls = QStyle::SC_ComboBoxEditField;
5972                 cmb.activeSubControls = QStyle::SC_None;
5973                 w = qMax(w, subControlRect(QStyle::CC_ComboBox, &cmb,
5974                                                    QStyle::SC_ComboBoxEditField,
5975                                                    comboBox).width());
5976             } else {
5977                 w += 12;
5978             }
5979             sz = QSize(w, h);
5980         }
5981         break;
5982     case CT_ToolButton:
5983         if (widget && qobject_cast<const QToolBar *>(widget->parentWidget())) {
5984             if (QMainWindow * mainWindow = qobject_cast<QMainWindow *>(widget->parent())) {
5985                 if (mainWindow->unifiedTitleAndToolBarOnMac()) {
5986                     sz.rwidth() += 4;
5987                     if (sz.height() <= 32) {
5988                         // Workaround strange HIToolBar bug when getting constraints.
5989                         sz.rheight() += 1;
5990                     }
5991                     return sz;
5992                 }
5993             }
5994         }
5995         sz.rwidth() += 10;
5996         sz.rheight() += 10;
5997         return sz;
5998     case CT_ComboBox:
5999         sz.rwidth() += 50;
6000         break;
6001     case CT_Menu: {
6002         QStyleHintReturnMask menuMask;
6003         QStyleOption myOption = *opt;
6004         myOption.rect.setSize(sz);
6005         if (proxy()->styleHint(SH_Menu_Mask, &myOption, widget, &menuMask)) {
6006             sz = menuMask.region.boundingRect().size();
6007         }
6008         break; }
6009     case CT_HeaderSection:{
6010         const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(opt);
6011         sz = QWindowsStyle::sizeFromContents(ct, opt, csz, widget);
6012         if (header->text.contains(QLatin1Char('\n')))
6013             useAquaGuideline = false;
6014         break; }
6015     case CT_ScrollBar :
6016         // Make sure that the scroll bar is large enough to display the thumb indicator.
6017         if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
6018             const int minimumSize = scrollButtonsCutoffSize(thumbIndicatorCutoff, widgetSizePolicy(widget));
6019             if (slider->orientation == Qt::Horizontal)
6020                 sz = sz.expandedTo(QSize(minimumSize, sz.height()));
6021             else
6022                 sz = sz.expandedTo(QSize(sz.width(), minimumSize));
6023         }
6024         break;
6025     case CT_ItemViewItem:
6026         if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(opt)) {
6027             sz = QCommonStyle::sizeFromContents(ct, vopt, csz, widget);
6028             sz.setHeight(sz.height() + 2);
6029         }
6030         break;
6031
6032     default:
6033         sz = QWindowsStyle::sizeFromContents(ct, opt, csz, widget);
6034     }
6035
6036     if (useAquaGuideline){
6037         QSize macsz;
6038         if (d->aquaSizeConstrain(opt, widget, ct, sz, &macsz) != QAquaSizeUnknown) {
6039             if (macsz.width() != -1)
6040                 sz.setWidth(macsz.width());
6041             if (macsz.height() != -1)
6042                 sz.setHeight(macsz.height());
6043         }
6044     }
6045
6046     // The sizes that Carbon and the guidelines gives us excludes the focus frame.
6047     // We compensate for this by adding some extra space here to make room for the frame when drawing:
6048     if (const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox *>(opt)){
6049         QAquaWidgetSize widgetSize = d->aquaSizeConstrain(opt, widget);
6050         int bkind = 0;
6051         switch (widgetSize) {
6052         default:
6053         case QAquaSizeLarge:
6054             bkind = combo->editable ? kThemeComboBox : kThemePopupButton;
6055             break;
6056         case QAquaSizeSmall:
6057             bkind = combo->editable ? int(kThemeComboBoxSmall) : int(kThemePopupButtonSmall);
6058             break;
6059         case QAquaSizeMini:
6060             bkind = combo->editable ? kThemeComboBoxMini : kThemePopupButtonMini;
6061             break;
6062         }
6063         HIRect tmpRect = {{0, 0}, {0, 0}};
6064         HIRect diffRect = QMacStylePrivate::comboboxInnerBounds(tmpRect, bkind);
6065         sz.rwidth() -= qRound(diffRect.size.width);
6066         sz.rheight() -= qRound(diffRect.size.height);
6067     } else if (ct == CT_PushButton || ct == CT_ToolButton){
6068         ThemeButtonKind bkind;
6069         QAquaWidgetSize widgetSize = d->aquaSizeConstrain(opt, widget);
6070         switch (ct) {
6071         default:
6072         case CT_PushButton:
6073             if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
6074                 if (btn->features & QStyleOptionButton::CommandLinkButton) {
6075                     return QWindowsStyle::sizeFromContents(ct, opt, sz, widget);
6076                 }
6077             }
6078
6079             switch (widgetSize) {
6080             default:
6081             case QAquaSizeLarge:
6082                 bkind = kThemePushButton;
6083                 break;
6084             case QAquaSizeSmall:
6085                 bkind = kThemePushButtonSmall;
6086                 break;
6087             case QAquaSizeMini:
6088                 bkind = kThemePushButtonMini;
6089                 break;
6090             }
6091             break;
6092         case CT_ToolButton:
6093             switch (widgetSize) {
6094             default:
6095             case QAquaSizeLarge:
6096                 bkind = kThemeLargeBevelButton;
6097                 break;
6098             case QAquaSizeMini:
6099             case QAquaSizeSmall:
6100                 bkind = kThemeSmallBevelButton;
6101             }
6102             break;
6103         }
6104
6105         HIThemeButtonDrawInfo bdi;
6106         bdi.version = qt_mac_hitheme_version;
6107         bdi.state = kThemeStateActive;
6108         bdi.kind = bkind;
6109         bdi.value = kThemeButtonOff;
6110         bdi.adornment = kThemeAdornmentNone;
6111         HIRect macRect, myRect;
6112         myRect = CGRectMake(0, 0, sz.width(), sz.height());
6113         HIThemeGetButtonBackgroundBounds(&myRect, &bdi, &macRect);
6114         // Mini buttons only return their actual size in HIThemeGetButtonBackgroundBounds, so help them out a bit (guess),
6115         if (bkind == kThemePushButtonMini)
6116             macRect.size.height += 8.;
6117         else if (bkind == kThemePushButtonSmall)
6118             macRect.size.height -= 10;
6119         sz.setWidth(sz.width() + int(macRect.size.width - myRect.size.width));
6120         sz.setHeight(sz.height() + int(macRect.size.height - myRect.size.height));
6121     }
6122     return sz;
6123 }
6124
6125 void QMacStyle::drawItemText(QPainter *p, const QRect &r, int flags, const QPalette &pal,
6126                              bool enabled, const QString &text, QPalette::ColorRole textRole) const
6127 {
6128     if(flags & Qt::TextShowMnemonic)
6129         flags |= Qt::TextHideMnemonic;
6130     QWindowsStyle::drawItemText(p, r, flags, pal, enabled, text, textRole);
6131 }
6132
6133 bool QMacStyle::event(QEvent *e)
6134 {
6135     if(e->type() == QEvent::FocusIn) {
6136         QWidget *f = 0;
6137         QWidget *focusWidget = QApplication::focusWidget();
6138 #ifndef QT_NO_GRAPHICSVIEW
6139         if (QGraphicsView *graphicsView = qobject_cast<QGraphicsView *>(focusWidget)) {
6140             QGraphicsItem *focusItem = graphicsView->scene() ? graphicsView->scene()->focusItem() : 0;
6141             if (focusItem && focusItem->type() == QGraphicsProxyWidget::Type) {
6142                 QGraphicsProxyWidget *proxy = static_cast<QGraphicsProxyWidget *>(focusItem);
6143                 if (proxy->widget())
6144                     focusWidget = proxy->widget()->focusWidget();
6145             }
6146         }
6147 #endif
6148         if (focusWidget && focusWidget->testAttribute(Qt::WA_MacShowFocusRect)) {
6149             f = focusWidget;
6150             QWidget *top = f->parentWidget();
6151             while (top && !top->isWindow() && !(top->windowType() == Qt::SubWindow))
6152                 top = top->parentWidget();
6153 #ifndef QT_NO_MAINWINDOW
6154             if (qobject_cast<QMainWindow *>(top)) {
6155                 QWidget *central = static_cast<QMainWindow *>(top)->centralWidget();
6156                 for (const QWidget *par = f; par; par = par->parentWidget()) {
6157                     if (par == central) {
6158                         top = central;
6159                         break;
6160                     }
6161                     if (par->isWindow())
6162                         break;
6163                 }
6164             }
6165 #endif
6166         }
6167         if (f) {
6168             if(!d->focusWidget)
6169                 d->focusWidget = new QFocusFrame(f);
6170             d->focusWidget->setWidget(f);
6171         } else if(d->focusWidget) {
6172             d->focusWidget->setWidget(0);
6173         }
6174     } else if(e->type() == QEvent::FocusOut) {
6175         if(d->focusWidget)
6176             d->focusWidget->setWidget(0);
6177     }
6178     return false;
6179 }
6180
6181 QIcon QMacStyle::standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *opt,
6182                                             const QWidget *widget) const
6183 {
6184     switch (standardIcon) {
6185     default:
6186         return QWindowsStyle::standardIconImplementation(standardIcon, opt, widget);
6187     case SP_ToolBarHorizontalExtensionButton:
6188     case SP_ToolBarVerticalExtensionButton: {
6189         QPixmap pixmap(qt_mac_toolbar_ext);
6190         if (standardIcon == SP_ToolBarVerticalExtensionButton) {
6191             QPixmap pix2(pixmap.height(), pixmap.width());
6192             pix2.fill(Qt::transparent);
6193             QPainter p(&pix2);
6194             p.translate(pix2.width(), 0);
6195             p.rotate(90);
6196             p.drawPixmap(0, 0, pixmap);
6197             return pix2;
6198         }
6199         return pixmap;
6200     }
6201     }
6202 }
6203
6204 int QMacStyle::layoutSpacingImplementation(QSizePolicy::ControlType control1,
6205                                            QSizePolicy::ControlType control2,
6206                                            Qt::Orientation orientation,
6207                                            const QStyleOption *option,
6208                                            const QWidget *widget) const
6209 {
6210     const int ButtonMask = QSizePolicy::ButtonBox | QSizePolicy::PushButton;
6211     bool isMetal = (widget && widget->testAttribute(Qt::WA_MacBrushedMetal));
6212     int controlSize = getControlSize(option, widget);
6213
6214     if (control2 == QSizePolicy::ButtonBox) {
6215         /*
6216             AHIG seems to prefer a 12-pixel margin between group
6217             boxes and the row of buttons. The 20 pixel comes from
6218             Builder.
6219         */
6220         if (isMetal                                         // (AHIG, guess, guess)
6221                 || (control1 & (QSizePolicy::Frame          // guess
6222                                 | QSizePolicy::GroupBox     // (AHIG, guess, guess)
6223                                 | QSizePolicy::TabWidget    // guess
6224                                 | ButtonMask)))    {        // AHIG
6225             return_SIZE(14, 8, 8);
6226         } else if (control1 == QSizePolicy::LineEdit) {
6227             return_SIZE(8, 8, 8); // Interface Builder
6228         } else {
6229             return_SIZE(20, 7, 7); // Interface Builder
6230         }
6231     }
6232
6233     if ((control1 | control2) & ButtonMask) {
6234         if (control1 == QSizePolicy::LineEdit)
6235             return_SIZE(8, 8, 8); // Interface Builder
6236         else if (control2 == QSizePolicy::LineEdit) {
6237             if (orientation == Qt::Vertical)
6238                 return_SIZE(20, 7, 7); // Interface Builder
6239             else
6240                 return_SIZE(20, 8, 8);
6241         }
6242         return_SIZE(14, 8, 8);     // Interface Builder
6243     }
6244
6245     switch (CT2(control1, control2)) {
6246     case CT1(QSizePolicy::Label):                             // guess
6247     case CT2(QSizePolicy::Label, QSizePolicy::DefaultType):   // guess
6248     case CT2(QSizePolicy::Label, QSizePolicy::CheckBox):      // AHIG
6249     case CT2(QSizePolicy::Label, QSizePolicy::ComboBox):      // AHIG
6250     case CT2(QSizePolicy::Label, QSizePolicy::LineEdit):      // guess
6251     case CT2(QSizePolicy::Label, QSizePolicy::RadioButton):   // AHIG
6252     case CT2(QSizePolicy::Label, QSizePolicy::Slider):        // guess
6253     case CT2(QSizePolicy::Label, QSizePolicy::SpinBox):       // guess
6254     case CT2(QSizePolicy::Label, QSizePolicy::ToolButton):    // guess
6255         return_SIZE(8, 6, 5);
6256     case CT1(QSizePolicy::ToolButton):
6257         return 8;   // AHIG
6258     case CT1(QSizePolicy::CheckBox):
6259     case CT2(QSizePolicy::CheckBox, QSizePolicy::RadioButton):
6260     case CT2(QSizePolicy::RadioButton, QSizePolicy::CheckBox):
6261         if (orientation == Qt::Vertical)
6262             return_SIZE(8, 8, 7);        // AHIG and Builder
6263         break;
6264     case CT1(QSizePolicy::RadioButton):
6265         if (orientation == Qt::Vertical)
6266             return 5;                   // (Builder, guess, AHIG)
6267     }
6268
6269     if (orientation == Qt::Horizontal
6270             && (control2 & (QSizePolicy::CheckBox | QSizePolicy::RadioButton)))
6271         return_SIZE(12, 10, 8);        // guess
6272
6273     if ((control1 | control2) & (QSizePolicy::Frame
6274                                  | QSizePolicy::GroupBox
6275                                  | QSizePolicy::TabWidget)) {
6276         /*
6277             These values were chosen so that nested container widgets
6278             look good side by side. Builder uses 8, which looks way
6279             too small, and AHIG doesn't say anything.
6280         */
6281         return_SIZE(16, 10, 10);    // guess
6282     }
6283
6284     if ((control1 | control2) & (QSizePolicy::Line | QSizePolicy::Slider))
6285         return_SIZE(12, 10, 8);     // AHIG
6286
6287     if ((control1 | control2) & QSizePolicy::LineEdit)
6288         return_SIZE(10, 8, 8);      // AHIG
6289
6290     /*
6291         AHIG and Builder differ by up to 4 pixels for stacked editable
6292         comboboxes. We use some values that work fairly well in all
6293         cases.
6294     */
6295     if ((control1 | control2) & QSizePolicy::ComboBox)
6296         return_SIZE(10, 8, 7);      // guess
6297
6298     /*
6299         Builder defaults to 8, 6, 5 in lots of cases, but most of the time the
6300         result looks too cramped.
6301     */
6302     return_SIZE(10, 8, 6);  // guess
6303 }
6304
6305 void qt_mac_clip_cg(CGContextRef hd, const QRegion &rgn, CGAffineTransform *orig_xform)
6306 {
6307     CGAffineTransform old_xform = CGAffineTransformIdentity;
6308     if (orig_xform) { //setup xforms
6309         old_xform = CGContextGetCTM(hd);
6310         CGContextConcatCTM(hd, CGAffineTransformInvert(old_xform));
6311         CGContextConcatCTM(hd, *orig_xform);
6312     }
6313
6314     //do the clipping
6315     CGContextBeginPath(hd);
6316     if (rgn.isEmpty()) {
6317         CGContextAddRect(hd, CGRectMake(0, 0, 0, 0));
6318     } else {
6319         QCFType<HIMutableShapeRef> shape = qt_mac_toHIMutableShape(rgn);
6320         Q_ASSERT(!HIShapeIsEmpty(shape));
6321         HIShapeReplacePathInCGContext(shape, hd);
6322     }
6323     CGContextClip(hd);
6324
6325     if (orig_xform) {//reset xforms
6326         CGContextConcatCTM(hd, CGAffineTransformInvert(CGContextGetCTM(hd)));
6327         CGContextConcatCTM(hd, old_xform);
6328     }
6329 }
6330
6331 QMacCGContext::QMacCGContext(QPainter *p)
6332 {
6333     QPaintEngine *pe = p->paintEngine();
6334     pe->syncState();
6335     context = 0;
6336
6337     int devType = p->device()->devType();
6338     if (pe->type() == QPaintEngine::Raster
6339             && (devType == QInternal::Widget ||
6340                 devType == QInternal::Pixmap ||
6341                 devType == QInternal::Image)) {
6342
6343         extern CGColorSpaceRef qt_mac_colorSpaceForDeviceType(const QPaintDevice *paintDevice);
6344         CGColorSpaceRef colorspace = qt_mac_colorSpaceForDeviceType(pe->paintDevice());
6345         uint flags = kCGImageAlphaPremultipliedFirst;
6346         flags |= kCGBitmapByteOrder32Host;
6347
6348         const QImage *image = (const QImage *) pe->paintDevice();
6349
6350         context = CGBitmapContextCreate((void *) image->bits(), image->width(), image->height(),
6351                                         8, image->bytesPerLine(), colorspace, flags);
6352
6353         CGContextTranslateCTM(context, 0, image->height());
6354         CGContextScaleCTM(context, 1, -1);
6355
6356         if (devType == QInternal::Widget) {
6357             QRegion clip = p->paintEngine()->systemClip();
6358             QTransform native = p->deviceTransform();
6359             QTransform logical = p->combinedTransform();
6360
6361             if (p->hasClipping()) {
6362                 QRegion r = p->clipRegion();
6363                 r.translate(native.dx(), native.dy());
6364                 if (clip.isEmpty())
6365                     clip = r;
6366                 else
6367                     clip &= r;
6368             }
6369             qt_mac_clip_cg(context, clip, 0);
6370
6371             CGContextTranslateCTM(context, native.dx(), native.dy());
6372         }
6373     } else {
6374         qDebug() << "QMacCGContext:: Unsupported painter devtype type" << devType;
6375     }
6376 }
6377
6378 CGColorSpaceRef qt_mac_colorSpaceForDeviceType(const QPaintDevice *paintDevice)
6379 {
6380     bool isWidget = (paintDevice->devType() == QInternal::Widget);
6381     return qt_mac_displayColorSpace(isWidget ? static_cast<const QWidget *>(paintDevice) : 0);
6382 }
6383
6384 /*! \internal
6385
6386     Returns the CoreGraphics CGContextRef of the paint device. 0 is
6387     returned if it can't be obtained. It is the caller's responsibility to
6388     CGContextRelease the context when finished using it.
6389
6390     \warning This function is only available on Mac OS X.
6391 */
6392
6393 CGContextRef qt_mac_cg_context(const QPaintDevice *pdev)
6394 {
6395     if (pdev->devType() == QInternal::Pixmap) {
6396         const QPixmap *pm = static_cast<const QPixmap*>(pdev);
6397         CGColorSpaceRef colorspace = qt_mac_colorSpaceForDeviceType(pdev);
6398         uint flags = kCGImageAlphaPremultipliedFirst;
6399         flags |= kCGBitmapByteOrder32Host;
6400         CGContextRef ret = 0;
6401
6402         QPlatformPixmap *data = const_cast<QPixmap *>(pm)->data_ptr().data();
6403         if (data->classId() == QPlatformPixmap::RasterClass) {
6404             QImage *image = data->buffer();
6405             ret = CGBitmapContextCreate(image->bits(), image->width(), image->height(),
6406                                         8, image->bytesPerLine(), colorspace, flags);
6407         } else {
6408             qDebug() << "qt_mac_cg_context: Unsupported pixmap class";
6409         }
6410
6411         CGContextTranslateCTM(ret, 0, pm->height());
6412         CGContextScaleCTM(ret, 1, -1);
6413         return ret;
6414     } else if (pdev->devType() == QInternal::Widget) {
6415         //CGContextRef ret = static_cast<CGContextRef>(static_cast<const QWidget *>(pdev)->macCGHandle());
6416         ///CGContextRetain(ret);
6417         //return ret;
6418         qDebug() << "qt_mac_cg_context: not implemented: Widget class";
6419         return 0;
6420     }
6421     return 0;
6422 }
6423
6424 /*
6425 FontHash::FontHash()
6426 {
6427     QHash<QByteArray, QFont>::operator=(QGuiApplicationPrivate::platformIntegration()->fontDatabase()->defaultFonts());
6428 }
6429
6430 Q_GLOBAL_STATIC(FontHash, app_fonts)
6431 FontHash *qt_app_fonts_hash()
6432 {
6433     return app_fonts();
6434 }
6435 */
6436 QT_END_NAMESPACE