Difference between revisions of "Mac OS X Implementing HIView"
m |
|||
(60 intermediate revisions by 2 users not shown) | |||
Line 5: | Line 5: | ||
Sébastien Plisson [[http://wiki.services.openoffice.org/wiki/User:Plipli plipli]] | Sébastien Plisson [[http://wiki.services.openoffice.org/wiki/User:Plipli plipli]] | ||
− | == | + | == Introduction == |
− | + | '''[DRAFT] : means, not yet working, work in progress ... ''' | |
+ | HIObject is a common base class for all user interface objects and all menus, windows, controls, toolbars, and so on, are subclasses of HIObject. | ||
+ | |||
+ | HIView is an object-oriented view system subclassed from HIObject. All controls are implemented as HIView objects ("views"). You can easily subclass HIView classes, making it easy to implement custom controls. Over time the HIView API will replace the current Control Manager. See [[http://developer.apple.com/documentation/Carbon/Conceptual/HandlingWindowsControls/hitb-wind_cont_tasks/chapter_3_section_9.html HIView intro]] | ||
+ | |||
+ | The main idea behind HIView is to superpose plans, to create any view, using compositing possibilities of Quartz Graphical Engine. | ||
+ | |||
+ | The final result is the superposition of all plans, following simple rules like : | ||
+ | |||
+ | - The last plan is always drawn on the previous one ; | ||
+ | - Some plans can be declared visible, or not, very easily. | ||
+ | |||
+ | This page is part of [[http://wiki.services.openoffice.org/wiki/Mac_OS_X_Porting_-_Native_Controls Native Controls Implementation]] and the objective is to use HIView for HIComboboxes or other HI* controls. | ||
+ | |||
+ | Our objective is to bind vcl controls with HI* controls, from Carbon API. | ||
+ | |||
+ | e.g. : implement HICombobox as one control only. | ||
+ | |||
+ | The generic implementation, under tests (and not fully working), uses : | ||
+ | |||
+ | '''In progress :'''<br> | ||
+ | - plipli : '''HIFramework''' integration : compiled, to be cleaned up before testing delivery to mac@porting ; | ||
+ | - ericb/ismael : salnativewidget - create and bind '''native controls''' (HIViews) (ericb) and '''HIWindow''' (ismael); | ||
+ | |||
+ | |||
+ | |||
+ | Note : we "or"- ed kWindowCompositingAttribute in nWindowAttributes, to see compositing effects. | ||
+ | [FIXME] : investigate, because use this attribute causes refresh issues | ||
+ | |||
+ | == HIFramework integration and benefits == | ||
+ | --[[User:Plipli|Plipli]] 15:00, 25 April 2007 (CEST) | ||
+ | |||
+ | * '''''Origin''''' : Issued from Apple samples | ||
+ | |||
+ | * '''''Pros''''' : | ||
+ | - use recent API code, <br> | ||
+ | - given with many helpers and set/getters to manage data and events<br> | ||
+ | - easily adaptable to use new services coming with Leopard (MacOSX 0.5)<br> | ||
+ | - up/down compatibility with different MacOSX versions<br> | ||
+ | - hiobject registering system : low couplage with the utility classes of HIFramework<br> | ||
+ | |||
+ | * '''''Cons''''' : | ||
+ | - ?? too nice to be true :-) | ||
+ | |||
+ | * '''''Step by step''''' : | ||
+ | '''1''' - When any HIObject is created in salframe/salnativewidget (AquaSalFrame / AquaSalGraphics) it will be | ||
+ | registered to HIFramework base classes ;<br> | ||
+ | '''2a''' - Being registered gives this instance of HIView/HIWindow access to helpers/setters/getters methods ;<br> | ||
+ | '''2b''' - Event handling is highly centralized/factored : create, initialize, draw... ;<br> | ||
+ | '''3''' - Almost all possible data / events is covered by HIFramework and will be easily used, as new controls are implemented in salnativewidget ;<br> | ||
+ | |||
+ | * '''''Conclusion''''' : | ||
+ | - Let's clean it, test it and enjoy fastest implementation of Aqua native controls !! (GsoC fun ;-) | ||
+ | |||
+ | == Technical principles == | ||
+ | |||
+ | 1) OO ask to VCL / native implementation code to draw controls (ie DrawNativeControl) or images or text | ||
+ | |||
+ | 2) For controls, native implementation code create objects but do not draw them | ||
+ | For images and text, native code draw objects to context (from QDBegin) or context from HiView event | ||
+ | |||
+ | 3) When HIView events are received by event handler, especially kEventControlDraw, native code should draw controls to context given by the event | ||
+ | |||
+ | 4) Native code call needsDisplay functions to tell Quartz which zone to update | ||
== Current code implementation== | == Current code implementation== | ||
− | ===Events === | + | ===Events for HIView === |
Two sorts of events are needed: | Two sorts of events are needed: | ||
Line 18: | Line 81: | ||
*for objects (ClasskEventClassHIObject ) : | *for objects (ClasskEventClassHIObject ) : | ||
− | kEventHIObjectConstruct | + | <pre>kEventHIObjectConstruct |
kEventHIObjectInitialize | kEventHIObjectInitialize | ||
− | kEventHIObjectDestruct | + | kEventHIObjectDestruct</pre> |
*for controls themselves ( Class kEventClassControl ) : | *for controls themselves ( Class kEventClassControl ) : | ||
− | kEventControlDraw | + | <pre>kEventControlDraw |
kEventControlInitialize | kEventControlInitialize | ||
Line 34: | Line 97: | ||
kEventControlGetPartRegion | kEventControlGetPartRegion | ||
− | + | </pre> | |
+ | |||
+ | |||
Current implementation : see vcl/aqua/aquavclevents.hxx for more informations about the syntax. | Current implementation : see vcl/aqua/aquavclevents.hxx for more informations about the syntax. | ||
− | === | + | ===Install Event Handler === |
+ | |||
+ | Now we have to install event Handler, inside AquaSalFrame::CreateNewSystemWindow() : | ||
+ | <pre> | ||
+ | |||
+ | InstallEventHandler ( | ||
+ | GetControlEventTarget (mhView), | ||
+ | NewEventHandlerUPP (HandleHIViewEvent), | ||
+ | GetEventTypeCount (cHIViewEvent), | ||
+ | cHIViewEvent, | ||
+ | (void*)mhView, // note the use of the pointer | ||
+ | NULL | ||
+ | ); | ||
+ | |||
+ | </pre> | ||
+ | |||
+ | === The HI* Event Handler === | ||
+ | |||
+ | The Handler is OSStatus type, and is used when events are detected. | ||
+ | |||
+ | e.g. : we created HandleHIViewEvent() | ||
+ | |||
+ | using GetEventParameter, itself using the parameters described in Apple documentation. | ||
+ | |||
+ | Code sample : | ||
+ | <pre> | ||
+ | OSStatus HandleHIViewEvent(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void* inUserData) | ||
+ | { | ||
+ | //lock | ||
+ | ImplSalYieldMutexAcquire(); | ||
+ | |||
+ | |||
+ | OSStatus status = noErr; | ||
+ | |||
+ | // we use mrContext, global and seen from everywhere | ||
+ | CGContextRef mrContext; | ||
+ | |||
+ | // create HIRect, containing the control bounds ( in local coordinates) | ||
+ | HIRect bounds; | ||
+ | |||
+ | status = GetEventParameter (inEvent, | ||
+ | kEventParamCGContextRef, | ||
+ | typeCGContextRef, | ||
+ | NULL, | ||
+ | sizeof (CGContextRef), | ||
+ | NULL, | ||
+ | &mrContext); | ||
+ | |||
+ | // not used, but useful | ||
+ | //require_noerr(status, CantGetGraphicsContext); // 2 | ||
+ | |||
+ | |||
+ | // We need to know the bounds containing the current control | ||
+ | HIViewGetBounds ((HIViewRef) inUserData, &bounds); | ||
+ | |||
+ | // not used, but useful | ||
+ | //require_noerr(status, CantGetBoundingRectangle); | ||
+ | |||
+ | // unlock | ||
+ | ImplSalYieldMutexRelease(); | ||
+ | |||
+ | return status; | ||
+ | } | ||
+ | </pre> | ||
+ | |||
+ | ===HIView use in AquaSalFrame::CreateNewSystemWindow() === | ||
+ | |||
+ | Code sample : | ||
+ | |||
+ | <pre> | ||
+ | |||
+ | // TEST HIVIew part | ||
+ | // Set mrContentView with HIView Content ViewRef | ||
+ | |||
+ | HIRect myViewRect; | ||
+ | myViewRect.origin.x = aContentRect.left; | ||
+ | myViewRect.origin.y = aContentRect.right; | ||
+ | myViewRect.size.width = aContentRect.right-aContentRect.left; | ||
+ | myViewRect.size.height = aContentRect.bottom-aContentRect.top; | ||
+ | OSStatus errval; | ||
+ | errval = HIViewFindByID(HIViewGetRoot(mrWindow), kHIViewWindowContentID, &mrContentView); | ||
+ | |||
+ | // make the view visible | ||
+ | HIViewSetVisible (mrContentView, true); | ||
+ | |||
+ | // set the frame | ||
+ | HIViewSetFrame (mrContentView, &myViewRect); | ||
+ | |||
+ | // Activate content view and children | ||
+ | HIViewSetActivated (mrContentView,true); | ||
+ | |||
+ | </pre> | ||
+ | |||
+ | === Controls === | ||
[FIXME] | [FIXME] | ||
− | === | + | Example : HICombobox |
+ | |||
+ | -> code located in vcl/aqua/source/gdi/salnativewidgets.cxx , where all NWF are defined | ||
+ | |||
+ | 1) declare CTRL_COMBOBOX control as "true" in isNativeControlSupported() | ||
+ | |||
+ | 2) get the control region in getNativeControlRegion() | ||
+ | |||
+ | 3) add CTRL_COMBOBOX case in drawNativeControl() | ||
+ | |||
+ | Code sample for the last part (Warning : not yet working !! ) : | ||
+ | |||
+ | <pre> | ||
+ | switch( nType ) | ||
+ | { | ||
+ | |||
+ | case CTRL_COMBOBOX: | ||
+ | if ( ( nPart==PART_BUTTON_DOWN) || (nPart==PART_SUB_EDIT) || (nPart==PART_ENTIRE_CONTROL) || (nPart==HAS_BACKGROUND_TEXTURE)) | ||
+ | |||
+ | .... (other code ) | ||
+ | HIViewRef myCombo; | ||
+ | |||
+ | HIRect rc2; | ||
+ | |||
+ | rc2.origin.x = rControlRegion.GetBoundRect().Left(); | ||
+ | rc2.origin.y = rControlRegion.GetBoundRect().Top(); | ||
+ | rc2.size.width = rControlRegion.GetBoundRect().GetWidth(); | ||
+ | rc2.size.height = rControlRegion.GetBoundRect().GetHeight(); | ||
+ | |||
+ | HIComboBoxCreate ( &rc2 , NULL, NULL, NULL, kHIComboBoxStandardAttributes, &myCombo); | ||
+ | |||
+ | HIViewSetVisible ( myCombo, true); | ||
+ | HIViewAddSubview (mrView, myCombo); | ||
+ | |||
+ | HIViewSetNeedsDisplay (myCombo, true); | ||
+ | |||
+ | printf ("rc2.origin.x %.0f \n rc2.origin.y %.0f \n rc2.size.width %.0f \n rc2.size.height %.0f \n", | ||
+ | rc2.origin.x, rc2.origin.y, rc2.size.width , rc2.size.height ); | ||
+ | |||
+ | //HIViewSetActivated (myCombo,true); | ||
− | + | ..... (other code ) | |
+ | </pre> | ||
== Usefull Links == | == Usefull Links == | ||
− | === | + | === References === |
− | |||
− | + | [[http://developer.apple.com/documentation/Carbon/Conceptual/HandlingWindowsControls/hitb-wind_cont_tasks/chapter_3_section_9.html Introducing HIView]] | |
+ | |||
+ | OverView : [[http://developer.apple.com/carbon/HIToolbox_feature.html HIToolbox]] | ||
+ | |||
+ | HIVIew : [[http://developer.apple.com/documentation/Carbon/Reference/HIViewReference/Reference/reference.html reference]] [[http://developer.apple.com/documentation/Carbon/Reference/HIViewReference/HIViewReference.pdf or .pdf format]] | ||
+ | |||
+ | [[http://developer.apple.com/documentation/Carbon/Conceptual/Upgrading_HIToolbox/index.html Upgrading to HIToolbox]] | ||
===Code sample === | ===Code sample === | ||
+ | Build a big toy with all controls included : [http://developer.apple.com/samplecode/AppearanceSampleUpdated/listing575.html All controls + code around] | ||
+ | |||
+ | High Level Toolbox, HIServices Release Notes : [http://developer.apple.com/releasenotes/Carbon/RN-HIToolbox/ HIToolbox] | ||
Latest revision as of 00:07, 28 May 2010
Contributors
Eric Bachard[ericb]
Sébastien Plisson [plipli]
Introduction
[DRAFT] : means, not yet working, work in progress ...
HIObject is a common base class for all user interface objects and all menus, windows, controls, toolbars, and so on, are subclasses of HIObject.
HIView is an object-oriented view system subclassed from HIObject. All controls are implemented as HIView objects ("views"). You can easily subclass HIView classes, making it easy to implement custom controls. Over time the HIView API will replace the current Control Manager. See [HIView intro]
The main idea behind HIView is to superpose plans, to create any view, using compositing possibilities of Quartz Graphical Engine.
The final result is the superposition of all plans, following simple rules like :
- The last plan is always drawn on the previous one ; - Some plans can be declared visible, or not, very easily.
This page is part of [Native Controls Implementation] and the objective is to use HIView for HIComboboxes or other HI* controls.
Our objective is to bind vcl controls with HI* controls, from Carbon API.
e.g. : implement HICombobox as one control only.
The generic implementation, under tests (and not fully working), uses :
In progress :
- plipli : HIFramework integration : compiled, to be cleaned up before testing delivery to mac@porting ;
- ericb/ismael : salnativewidget - create and bind native controls (HIViews) (ericb) and HIWindow (ismael);
Note : we "or"- ed kWindowCompositingAttribute in nWindowAttributes, to see compositing effects. [FIXME] : investigate, because use this attribute causes refresh issues
HIFramework integration and benefits
--Plipli 15:00, 25 April 2007 (CEST)
- Origin : Issued from Apple samples
- Pros :
- use recent API code,
- given with many helpers and set/getters to manage data and events
- easily adaptable to use new services coming with Leopard (MacOSX 0.5)
- up/down compatibility with different MacOSX versions
- hiobject registering system : low couplage with the utility classes of HIFramework
- Cons :
- ?? too nice to be true :-)
- Step by step :
1 - When any HIObject is created in salframe/salnativewidget (AquaSalFrame / AquaSalGraphics) it will be
registered to HIFramework base classes ;
2a - Being registered gives this instance of HIView/HIWindow access to helpers/setters/getters methods ;
2b - Event handling is highly centralized/factored : create, initialize, draw... ;
3 - Almost all possible data / events is covered by HIFramework and will be easily used, as new controls are implemented in salnativewidget ;
- Conclusion :
- Let's clean it, test it and enjoy fastest implementation of Aqua native controls !! (GsoC fun ;-)
Technical principles
1) OO ask to VCL / native implementation code to draw controls (ie DrawNativeControl) or images or text
2) For controls, native implementation code create objects but do not draw them For images and text, native code draw objects to context (from QDBegin) or context from HiView event
3) When HIView events are received by event handler, especially kEventControlDraw, native code should draw controls to context given by the event
4) Native code call needsDisplay functions to tell Quartz which zone to update
Current code implementation
Events for HIView
Two sorts of events are needed:
- for objects (ClasskEventClassHIObject ) :
kEventHIObjectConstruct kEventHIObjectInitialize kEventHIObjectDestruct
- for controls themselves ( Class kEventClassControl ) :
kEventControlDraw kEventControlInitialize kEventControlHitTest kEventControlGetPartRegion
Current implementation : see vcl/aqua/aquavclevents.hxx for more informations about the syntax.
Install Event Handler
Now we have to install event Handler, inside AquaSalFrame::CreateNewSystemWindow() :
InstallEventHandler ( GetControlEventTarget (mhView), NewEventHandlerUPP (HandleHIViewEvent), GetEventTypeCount (cHIViewEvent), cHIViewEvent, (void*)mhView, // note the use of the pointer NULL );
The HI* Event Handler
The Handler is OSStatus type, and is used when events are detected.
e.g. : we created HandleHIViewEvent()
using GetEventParameter, itself using the parameters described in Apple documentation.
Code sample :
OSStatus HandleHIViewEvent(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void* inUserData) { //lock ImplSalYieldMutexAcquire(); OSStatus status = noErr; // we use mrContext, global and seen from everywhere CGContextRef mrContext; // create HIRect, containing the control bounds ( in local coordinates) HIRect bounds; status = GetEventParameter (inEvent, kEventParamCGContextRef, typeCGContextRef, NULL, sizeof (CGContextRef), NULL, &mrContext); // not used, but useful //require_noerr(status, CantGetGraphicsContext); // 2 // We need to know the bounds containing the current control HIViewGetBounds ((HIViewRef) inUserData, &bounds); // not used, but useful //require_noerr(status, CantGetBoundingRectangle); // unlock ImplSalYieldMutexRelease(); return status; }
HIView use in AquaSalFrame::CreateNewSystemWindow()
Code sample :
// TEST HIVIew part // Set mrContentView with HIView Content ViewRef HIRect myViewRect; myViewRect.origin.x = aContentRect.left; myViewRect.origin.y = aContentRect.right; myViewRect.size.width = aContentRect.right-aContentRect.left; myViewRect.size.height = aContentRect.bottom-aContentRect.top; OSStatus errval; errval = HIViewFindByID(HIViewGetRoot(mrWindow), kHIViewWindowContentID, &mrContentView); // make the view visible HIViewSetVisible (mrContentView, true); // set the frame HIViewSetFrame (mrContentView, &myViewRect); // Activate content view and children HIViewSetActivated (mrContentView,true);
Controls
[FIXME]
Example : HICombobox
-> code located in vcl/aqua/source/gdi/salnativewidgets.cxx , where all NWF are defined
1) declare CTRL_COMBOBOX control as "true" in isNativeControlSupported()
2) get the control region in getNativeControlRegion()
3) add CTRL_COMBOBOX case in drawNativeControl()
Code sample for the last part (Warning : not yet working !! ) :
switch( nType ) { case CTRL_COMBOBOX: if ( ( nPart==PART_BUTTON_DOWN) || (nPart==PART_SUB_EDIT) || (nPart==PART_ENTIRE_CONTROL) || (nPart==HAS_BACKGROUND_TEXTURE)) .... (other code ) HIViewRef myCombo; HIRect rc2; rc2.origin.x = rControlRegion.GetBoundRect().Left(); rc2.origin.y = rControlRegion.GetBoundRect().Top(); rc2.size.width = rControlRegion.GetBoundRect().GetWidth(); rc2.size.height = rControlRegion.GetBoundRect().GetHeight(); HIComboBoxCreate ( &rc2 , NULL, NULL, NULL, kHIComboBoxStandardAttributes, &myCombo); HIViewSetVisible ( myCombo, true); HIViewAddSubview (mrView, myCombo); HIViewSetNeedsDisplay (myCombo, true); printf ("rc2.origin.x %.0f \n rc2.origin.y %.0f \n rc2.size.width %.0f \n rc2.size.height %.0f \n", rc2.origin.x, rc2.origin.y, rc2.size.width , rc2.size.height ); //HIViewSetActivated (myCombo,true); ..... (other code )
Usefull Links
References
OverView : [HIToolbox]
HIVIew : [reference] [or .pdf format]
Code sample
Build a big toy with all controls included : All controls + code around
High Level Toolbox, HIServices Release Notes : HIToolbox