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