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