Mac OS X Porting - Native Controls

From Apache OpenOffice Wiki
Jump to: navigation, search

Native Controls



The purpose of this article is to present our current knowledge and progress of the implementation of native controls in the native Mac OS X version of Our goal by implementing native controls is to remove the win32 look as much as possible and replace it by the Aqua look and feel using the Carbon API.

Apple Documentation and References

The Appearance Manager and HITheme

Apple provides an easy way to change a custom user interface to an aqua interface by using the Appearance Manager(AM). This API was first developed for Mac OS 8 and is centered around QuickDraw. The AM is less and less supported by Apple since 10.2 and any implementation needs to be replaced with the HIToolbox version: HITheme. The problem with HITheme is that its implementation started on Mac OS X 10.2 (Jaguar) and has since gone under many revisions and new functions have been progressively added with each new version of OS X. Therefore some functions in the 10.4 version might not be in 10.3 or 10.2. This is one of the reason why the native version of will run on Mac OS X 10.4 and higher only.

Using HITheme

Unfortunately there is not much documentation provided by Apple about HITheme. Thus we have to look at the HITheme.h header file directly and read the extensive comments to understand how to use this API. All the constants used to describe the type of controls that we want to implement is still the same as in the AM. This is the reason why the AM reference document is still useful and should always be opened when implementing native controls. The AM and HITheme are very similar in the way they approach the implementation of native controls, most of the time the functions have similar names and the arguments different types so you can always use the AM reference to give you an idea about the procedure to follow.

  • Location of HITheme.h: /Developer/SDKs/MacOSX10.4u.sdk/System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/Headers/HITheme.h

Native controls in VCL

Native Controls Files in VCL


This file was copied directly from the Windows implementation of native controls. All the useless functions were removed and we are left with 6 functions:

  • isNativeControlSupported: function called to see if a control should be implemented natively or not. A big switch statement that goes through all the controls and part of controls possible. Returns true when a control is supported. Each time a new control is implemented this function should be modified so the new native code is used at compile time.
  • hitTestNativeControl: Boolean function. If the return value is TRUE, bIsInside contains information whether aPos was or not inside the native widget specified by the nType/nPart combination. This function will be used to redefine left/top buttons controls areas for e.g. the scrollbar.
  • getState: a translation from the VCL constants to the Carbon constants of the state of controls.
  • drawNativeControl: the most important function. This is where the code for new native controls is written. Again it is a big switch statment that lists each control with the corresponding implementation. Needs to be modified each time a new control is implemented.
  • drawNativeControlText: [TO DO]
  • getNativeControlRegion: [TO DO]


Uses AquaSalGraphics class, defined in vcl/aqua/inc/salgdi.h. AquaSalGraphics itself inherits of SalGraphics virtual class (defined in vcl/inc/salgdi.hxx).

This header file describes all the structures, classes and constants used to get the state and properties of the VCL controls. It is necessary to be familiar with this file since its content will be used to translate the state and properties to their Carbon equivalent.

Most of the stuff used in salnativewidgets.hxx are from HITheme.h (or Appearance.h for previous test)

The native controls and the implementation

Here is a list of all the controls that need to be native. Since some of them do not have the same name in VCL and Carbon, they are listed in this format: <VCL name> - <Carbon name> when they are different.

Push Button

  • Complemeted : Eric Bachard / Pavel Janik

This is the regular OK, Cancel buttons.

Aqua pushbuttons01.jpg

[FIXME] width is still not correct (work in progress)

nType is CONTROL_PUSHBUTTON   (value 1)
nPart is PART_ENTIRE_CONTROL (value 1)

[FIXME] How implement Heart Beat effect ? ( should be something default)

Radio Button

nType is CTRL_RADIOBUTTON (value is 2)

nPart is PART_ENTIRE_CONTROL (value is 1)
  • Completed : Eric Bachard / Pavel Janik

This is the regular radio button.

Aqua radiobuttons01.jpg

Check Box

This is the regular check box.

Remaining issues : the checkmark is ok, but is only refreshed when the mouse goes out of the control area.

getNativeControlRegion() saved us.

[UPDATE] : with correct refresh, the checkmarks disappears as expected

Aqua checkboxes01.jpg
nType is CTRL_CHECKBOX (value is 2)

nPart is PART_ENTIRE_CONTROL (value is 1)

Toolbars and Aqua Theme

  • Implemented : Eric Bachard
  • Todo : verify if repaint is necessary and it buttons can or not be drawn

Aqua toolbars 01.jpg

Popups Menus

  • Implemented : Eric Bachard


Aqua popup menus01.jpg

Check marks and radio mark (popup menus)

  • Implemented by: Ismael Merzaq







Status : begining of the implementation ( HIView now works )

Todo : add text entry, fix some refresh issues

nType is CTRL_COMBOBOX (value is 20)

nPart is PART_ENTIRE_CONTROL (value is 1)

Sébastien and me finally found a way to use HIView and draw comboboxes. Please have a look at Mac_OS_X_Implementing_HIView for the documentation and the work in progress

1) Combobox inactive

As you can see, the final control is greyed. [FIXME] : change for status active when not clicked

Combobox inactive01.jpg

2) Combobox active

The controls displays ok.

[FIXME] : implement the native popup area

Combobox active01.jpg

Our previous try was plain wrong, because we where confused with listboxes.

As you can see, we are in facvt using lisboxes (no data entry possible ) :

Native controls popup8.jpg

From OSXHIGuidelines.pdf, page 253:

For Carbon, ComboBoxes are available in Interface Builder. To create them programmatically
use the HIComboBoxCreate function or DrawThemeButton with the appropriate constant.

Mechanism seems similar to other controls : in vcl/source/control/combobox.cxx, GetNativeControlRegion is used, so we'll proceed like for scrollbar.


  • Implemented by: Pierre de Filippis, Eric Bachard and Pavel Janik

This is the regular scrollbar.

  • Improvement : the user can select either Arrows together or séparated arrows ( using System Preferences )
  • Todo : vcl and native thumb area are not exactly superposed (offset in % ) between them. To be fixed asap.

Horizontal scrollbar, with left button active :

Native scrollbar left button.jpg

With arrows separated ( using System Preferences) :

Aqua scrollbar arrows separated01.jpg

nType is CONTROL_SCROLLBAR   (value 60)
nPart is PART_ENTIRE_CONTROL (value 1)

Other screenshot, showing vertical scrollbar and top button active : Native scrollbar top button.jpg

Native FilePicker

  • Implemented : Florian Heckl / Pavel Janik
  • Todo : X11 backport ?
  • Status : aquafilpicker01 cws, not yet integrated

Aqua native filepicker01.jpg

Current status

[WORK IN PROGRESS] Aqua scrollbar works now as expected (see vcl/aqua/source/gdi/salnatigewidgets.cxx in aquavcl01 cws ), but some issues are remaining:

the main one is replace value for areas, with pointers on correct areas 
 (vcl and aqua controls are not exactly superposed )
when we click on top of slider, it moves up from hlaf of slider size 
( sort of "slide" :-) effect ? )
Translation of the Control Area

AquaSalGraphics::IsNativeControlSupported() returns true -> nType is ok , getstate() works , DrawNativeControl() works fine two, and several controls are drawn.

Everything seems to work excepted the button control area, because left/top control button is not located the same way for vcl and for aqua control : same behaviour, but different places.

Vertical scrollbar vcl : top (Button1) / bottom (Button2) aqua: both at bottom

Horizontal scrollbar: vcl : left (Button1) /right ( Button2) aqua: both on right

-> our problem is simple : translate the coordinates of the control area of left/top button under aqua control, else, clicking on the left of the scrollbar ... the button on right is active :-)

(same bug for vertical bar).

Solution proposed by Philipp Lohmann and Jan Holesovsky :

"...The actual hit testing is done in the overloaded SalGraphics::hitTestNativeControl method, so you can implement your own sensitive areas there. The getNativeControlRegion is used for drawing purposes (so the buttons are drawn at the positions you tell there)..."

[done] implement AquaSalGraphics::hitTestNativeControl() for scrollbar, to translate left/top control areas, and manage rIsInside Boolean variable.

How a ScrollBar is drawn

After printing out the part numbers passed to draw a ScrollBar, I found out how it is actually drawn out:

  • 1. Part 101 - PART_BUTTON_UP
  • 2. Part 102 - PART_BUTTON_DOWN
  • 3. Part 211 - PART_THUMB_VERT
  • 4. Part 201 - PART_TRACK_VERT_UPPER
  • 5. Part 203 - PART_TRACK_VERT_LOWER

The first two parts are self-explanatory. The last 3 are a little more confusing at first especially since some heights and widths can be negative. But here is what they are.

Part 211

This part is the slider. As described by its value, it is vertical. The horizontal equivalent is part 210 - PART_THUMB_HORZ.

Part 201 - Part 203

These are the parts that are between the slider and the arrows. Part 201 is between the slider and the upper arrow. Part 203 is between the slider and the lower arrow. Each one of them can actually have a negative size in the case where the slider touches one or both of the arrows. The equivalents for a horizontal scrollbar are part 200 - PART_TRACK_HORZ_LEFT and part 202 - PART_TRACK_HORZ_RIGHT.

(18 September)


Pierre fixed an important bug, and we now have vertical scrollbar working fine (last remaining problem is top arrow), but horizontal is still having problems.

todo : fix top arrow, and improve horizontal scrollbar.

(10th September) Now the scrollbar is correctly drawn. Missing: always full (needs some work). modify the top control coordinates, manage active/not active.

Patch available here :

Screenshots :


(03rd September) Does not work as expected, work in progress to fix arrows issue, and obtain correct redrawing (arrows are correctly drawn, but not at good place). See screenshot:

Current state of native scrollbar


  • Started by: Ericb (spin buttons)
  • Implemented by: Ismael Merzaq (fixed spin buttons and added text field)
CTRL_SPINBOX : two standalone spin buttons with an edit field


20th October : native spinbox can be drawn.

Todo :

solve the background issue
decrease the vcl control size
implement up/down parts in hitTestNativeControl()
replace hardcoded (currentlky 16) spinbutton width with system returned value

First try (using kThemeIncDecButton ) :

Native controls spinbuttons1.jpg Todo : implement hitTestNativeControl, to draw up and down parts.

Second test (using kThemeArrowButton) :

Native controls spinbuttons2.jpg

VCL spinbox button (work in progress to change for native spinbox button) Native control spinbox.jpg

nType is CTRL_SPINBOX (value is 40)
nPart is PART_ENTIRE_CONTROL (value is 1)

[FIXME]nPart HAS_BACKGROUND_TEXTURE (value is 4000 ) seems to be defined too

Tab Body

  • Implemented by:

CTRL_TAB_BODY : background of a Tab Pane

Native control ctrl tab body.jpg

nType is CTRL_TAB_BODY (value is 56)
nPart is PART_ENTIRE_CONTROL (value is 1)

[FIXME]nPart HAS_BACKGROUND_TEXTURE (value is 4000 ) seems to be defined too

Edit Box, Multiline Edit Box

  • Implemented by: Ismael Merzaq
  • Focus rect added by: Philipp Lohmann





The scrollbar is drawn separately.

nPart is PART_ENTIRE_CONTROL (value is 1)

List Box

  • Started by: Eric Bachard
  • Implemented by: Ismael Merzaq
  • Fixed by: Philipp Lohmann
CTRL_LISTBOX : Control that pops up a menu, but does NOT allow data entry

Native controls listbox2.jpg

nType is CTRL_LISTBOX (value is 35)
nPart is PART_ENTIRE_CONTROL (value is 1)

I (Ismael Merzaq) started to add a more native appearance for the floating frame of the listbox to replace the current one (image on the left) by a more aqua one (image on the right).

ListBoxOld.png listBoxNew.png


  • Implemented by: Ismael Merzaq
CTRL_TAB_ITEM : a single tab

With HIThemeTabDrawInfo with version=1


with version=0:


Tab Panes

  • Implemented by: Ismael Merzaq
CTRL_TAB_PANE : the border around a tab area, but without the tabs themselves.

For the version element of the HIThemeTabPaneDrawInfo structure, see tabs as the values are the same.

Progress bar

  • Implemented by: Philipp Lohmann



Intro progress bar

  • Implemented by: Ismael Merzaq (added support to native control in the code in desktop)
  • Native code by: Philipp Lohmann

CTRL_INTROPROGRESS: Progress bar of the splash screen. Its implementation is in the desktop module


Work in progress

Implement Aqua Theme inside windows and bounds, i.e. modify color panes and windows

First try : Aqua controls menu popup01.jpg

Preliminary : in AquaSalGraphics::IsNativeControlSupported(), tabs are present :

        case CTRL_TAB_PANE:
        case CTRL_TAB_BODY:
                if( nPart == PART_ENTIRE_CONTROL ||
                    nPart == PART_TABS_DRAW_RTL )
                    return false;

First try : use

HIThemeTabDrawInfo aTabDrawInfo

HIThemeTabPaneDrawInfo aTabPaneInfo

In AquaSalGraphics::drawNativeControl()

Starting point :

Controls not yet implemented

BOOL AquaSalGraphics::IsNativeControlSupported() returns true when control is one of the listed controls :

CTRL_FIXEDBORDER : a rectangular border, like a Tab Pane, but without the possible gap for a tab

Probably not needed : 
CTRL_TOOLBAR : a toolbar control with buttons and a grip
CTRL_MENUBAR : the menubar

Current state of native controls

Current state of native controls. Bigger Version


This work is part of

Personal tools