1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/mac/carbon/uma.cpp
3 // Purpose: UMA support
4 // Author: Stefan Csomor
8 // Copyright: (c) Stefan Csomor
9 // Licence: The wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 #include "wx/wxprec.h"
17 #if TARGET_API_MAC_OSX
18 #include "wx/toplevel.h"
25 # include <MacTextEditor.h>
26 # include <Navigation.h>
27 # if defined(TARGET_CARBON)
28 # if PM_USE_SESSION_APIS
31 # include <PMApplication.h>
33 # include <Printing.h>
41 #include "wx/mac/uma.h"
43 // since we have decided that we only support 8.6 upwards we are
44 // checking for these minimum requirements in the startup code of
45 // the application so all wxWidgets code can safely assume that appearance 1.1
46 // windows manager, control manager, navigation services etc. are
49 static bool sUMAHasAppearance
= false ;
50 static long sUMAAppearanceVersion
= 0 ;
51 static long sUMASystemVersion
= 0 ;
52 static bool sUMAHasAquaLayout
= false ;
54 static bool sUMAHasInittedAppearance
= false;
56 extern int gAGABackgroundColor
;
58 bool UMAHasAppearance() { return sUMAHasAppearance
; }
59 long UMAGetAppearanceVersion() { return sUMAAppearanceVersion
; }
60 long UMAGetSystemVersion() { return sUMASystemVersion
; }
62 static bool sUMAHasWindowManager
= false ;
63 static long sUMAWindowManagerAttr
= 0 ;
65 bool UMAHasWindowManager() { return sUMAHasWindowManager
; }
66 long UMAGetWindowManagerAttr() { return sUMAWindowManagerAttr
; }
67 bool UMAHasAquaLayout() { return sUMAHasAquaLayout
; }
70 void UMACleanupToolbox()
72 if (sUMAHasInittedAppearance
)
73 UnregisterAppearanceClient() ;
75 if ( NavServicesAvailable() )
78 if ( TXNTerminateTextension
!= (void*) kUnresolvedCFragSymbolAddress
)
79 TXNTerminateTextension( ) ;
82 void UMAInitToolbox( UInt16 inMoreMastersCalls
, bool isEmbedded
)
86 for (long i
= 1; i
<= inMoreMastersCalls
; i
++)
91 ::InitGraf(&qd
.thePort
);
96 ::FlushEvents(everyEvent
, 0);
100 PurgeSpace(&total
, &contig
);
105 if ( Gestalt(gestaltSystemVersion
, &sUMASystemVersion
) != noErr
)
106 sUMASystemVersion
= 0x0000 ;
109 if ( Gestalt( gestaltAppearanceAttr
, &theAppearance
) == noErr
)
111 // If status equals appearanceProcessRegisteredErr it means the
112 // appearance client already was registered (For example if we run
113 // embedded, the host might have registered it). In such a case
114 // we don't unregister it later on.
116 sUMAHasAppearance
= true ;
117 OSStatus status
= RegisterAppearanceClient();
118 if (status
!= appearanceProcessRegisteredErr
)
120 // Appearance client wasn't registered yet.
121 sUMAHasInittedAppearance
= true;
124 if ( Gestalt( gestaltAppearanceVersion
, &theAppearance
) == noErr
)
125 sUMAAppearanceVersion
= theAppearance
;
127 sUMAAppearanceVersion
= 0x0100 ;
130 if ( Gestalt( gestaltWindowMgrAttr
, &sUMAWindowManagerAttr
) == noErr
)
131 sUMAHasWindowManager
= sUMAWindowManagerAttr
& gestaltWindowMgrPresent
;
134 // Call currently implicitely done : InitFloatingWindows() ;
138 if ( sUMAHasWindowManager
)
139 InitFloatingWindows() ;
145 if ( NavServicesAvailable() )
149 Gestalt( gestaltMenuMgrAttr
, &menuMgrAttr
) ;
150 if ( menuMgrAttr
& gestaltMenuMgrAquaLayoutMask
)
151 sUMAHasAquaLayout
= true ;
153 if ( TXNInitTextension
!= (void*) kUnresolvedCFragSymbolAddress
)
155 FontFamilyID fontId
;
160 GetThemeFont(kThemeSmallSystemFont
, GetApplicationScript() , fontName
, &fontSize
, &fontStyle
) ;
161 GetFNum( fontName
, &fontId
);
163 TXNMacOSPreferredFontDescription fontDescriptions
[] =
165 { fontId
, (fontSize
<< 16) , kTXNDefaultFontStyle
, kTXNSystemDefaultEncoding
}
167 int noOfFontDescriptions
= sizeof( fontDescriptions
) / sizeof(TXNMacOSPreferredFontDescription
) ;
169 OptionBits options
= 0 ;
171 if ( UMAGetSystemVersion() < 0x1000 )
172 options
|= kTXNAlwaysUseQuickDrawTextMask
;
174 TXNInitTextension( fontDescriptions
, noOfFontDescriptions
, options
);
177 UMASetSystemIsInitialized( true );
181 Boolean
CanUseATSUI()
184 OSErr err
= Gestalt(gestaltATSUVersion
, &result
);
185 return (err
== noErr
);
190 long UMAGetProcessMode()
193 ProcessInfoRec processinfo
;
194 ProcessSerialNumber procno
;
196 procno
.highLongOfPSN
= 0 ;
197 procno
.lowLongOfPSN
= kCurrentProcess
;
198 processinfo
.processInfoLength
= sizeof(ProcessInfoRec
);
199 processinfo
.processName
= NULL
;
200 processinfo
.processAppSpec
= NULL
;
202 err
= ::GetProcessInformation( &procno
, &processinfo
) ;
203 wxASSERT( err
== noErr
) ;
205 return processinfo
.processMode
;
208 bool UMAGetProcessModeDoesActivateOnFGSwitch()
210 return UMAGetProcessMode() & modeDoesActivateOnFGSwitch
;
215 MenuRef
UMANewMenu( SInt16 id
, const wxString
& title
, wxFontEncoding encoding
)
217 wxString str
= wxStripMenuCodes( title
) ;
221 CreateNewMenu( id
, 0 , &menu
) ;
222 SetMenuTitleWithCFString( menu
, wxMacCFStringHolder(str
, encoding
) ) ;
225 wxMacStringToPascal( str
, ptitle
) ;
226 menu
= ::NewMenu( id
, ptitle
) ;
232 void UMASetMenuTitle( MenuRef menu
, const wxString
& title
, wxFontEncoding encoding
)
234 wxString str
= wxStripMenuCodes( title
) ;
237 SetMenuTitleWithCFString( menu
, wxMacCFStringHolder(str
, encoding
) ) ;
241 wxMacStringToPascal( str
, ptitle
) ;
242 SetMenuTitle( menu
, ptitle
) ;
246 void UMASetMenuItemText( MenuRef menu
, MenuItemIndex item
, const wxString
& title
, wxFontEncoding encoding
)
248 // we don't strip the accels here anymore, must be done before
249 wxString str
= title
;
252 SetMenuItemTextWithCFString( menu
, item
, wxMacCFStringHolder(str
, encoding
) ) ;
256 wxMacStringToPascal( str
, ptitle
) ;
257 SetMenuItemText( menu
, item
, ptitle
) ;
261 UInt32
UMAMenuEvent( EventRecord
*inEvent
)
263 return MenuEvent( inEvent
) ;
266 void UMAEnableMenuItem( MenuRef inMenu
, MenuItemIndex inItem
, bool enable
)
269 EnableMenuItem( inMenu
, inItem
) ;
271 DisableMenuItem( inMenu
, inItem
) ;
274 void UMAAppendSubMenuItem( MenuRef menu
, const wxString
& title
, wxFontEncoding encoding
, SInt16 id
)
276 MacAppendMenu( menu
, "\pA" );
277 UMASetMenuItemText( menu
, (SInt16
) ::CountMenuItems(menu
), title
, encoding
);
278 SetMenuItemHierarchicalID( menu
, CountMenuItems( menu
) , id
) ;
281 void UMAInsertSubMenuItem( MenuRef menu
, const wxString
& title
, wxFontEncoding encoding
, MenuItemIndex item
, SInt16 id
)
283 MacInsertMenuItem( menu
, "\pA" , item
);
284 UMASetMenuItemText( menu
, item
+1, title
, encoding
);
285 SetMenuItemHierarchicalID( menu
, item
+1 , id
) ;
288 void UMASetMenuItemShortcut( MenuRef menu
, MenuItemIndex item
, wxAcceleratorEntry
*entry
)
293 UInt8 modifiers
= 0 ;
294 SInt16 key
= entry
->GetKeyCode() ;
297 bool explicitCommandKey
= (entry
->GetFlags() & wxACCEL_CTRL
);
299 if (entry
->GetFlags() & wxACCEL_ALT
)
300 modifiers
|= kMenuOptionModifier
;
302 if (entry
->GetFlags() & wxACCEL_SHIFT
)
303 modifiers
|= kMenuShiftModifier
;
306 SInt16 macKey
= key
;
307 if ( key
>= WXK_F1
&& key
<= WXK_F15
)
309 if ( !explicitCommandKey
)
310 modifiers
|= kMenuNoCommandModifier
;
312 // for some reasons this must be 0 right now
313 // everything else leads to just the first function key item
314 // to be selected. Thanks to Ryan Wilcox for finding out.
316 glyph
= kMenuF1Glyph
+ ( key
- WXK_F1
) ;
317 if ( key
>= WXK_F13
)
325 macKey
= kBackspaceCharCode
;
326 glyph
= kMenuDeleteLeftGlyph
;
330 macKey
= kTabCharCode
;
331 glyph
= kMenuTabRightGlyph
;
334 case kEnterCharCode
:
335 macKey
= kEnterCharCode
;
336 glyph
= kMenuEnterGlyph
;
340 macKey
= kReturnCharCode
;
341 glyph
= kMenuReturnGlyph
;
345 macKey
= kEscapeCharCode
;
346 glyph
= kMenuEscapeGlyph
;
351 glyph
= kMenuSpaceGlyph
;
355 macKey
= kDeleteCharCode
;
356 glyph
= kMenuDeleteRightGlyph
;
360 macKey
= kClearCharCode
;
361 glyph
= kMenuClearGlyph
;
365 macKey
= kPageUpCharCode
;
366 glyph
= kMenuPageUpGlyph
;
370 macKey
= kPageDownCharCode
;
371 glyph
= kMenuPageDownGlyph
;
375 macKey
= kLeftArrowCharCode
;
376 glyph
= kMenuLeftArrowGlyph
;
380 macKey
= kUpArrowCharCode
;
381 glyph
= kMenuUpArrowGlyph
;
385 macKey
= kRightArrowCharCode
;
386 glyph
= kMenuRightArrowGlyph
;
390 macKey
= kDownArrowCharCode
;
391 glyph
= kMenuDownArrowGlyph
;
395 macKey
= kHomeCharCode
;
396 glyph
= kMenuNorthwestArrowGlyph
;
400 macKey
= kEndCharCode
;
401 glyph
= kMenuSoutheastArrowGlyph
;
404 macKey
= toupper( key
) ;
408 // we now allow non command key shortcuts
409 // remove in case this gives problems
410 if ( !explicitCommandKey
)
411 modifiers
|= kMenuNoCommandModifier
;
414 // 1d and 1e have special meaning to SetItemCmd, so
415 // do not use for these character codes.
416 if (key
!= WXK_UP
&& key
!= WXK_RIGHT
&& key
!= WXK_DOWN
&& key
!= WXK_LEFT
)
417 SetItemCmd( menu
, item
, macKey
);
419 SetMenuItemModifiers( menu
, item
, modifiers
) ;
422 SetMenuItemKeyGlyph( menu
, item
, glyph
) ;
426 void UMAAppendMenuItem( MenuRef menu
, const wxString
& title
, wxFontEncoding encoding
, wxAcceleratorEntry
*entry
)
428 MacAppendMenu(menu
, "\pA");
430 // don't attempt to interpret metacharacters like a '-' at the beginning (would become a separator otherwise)
431 ChangeMenuItemAttributes( menu
, ::CountMenuItems(menu
), kMenuItemAttrIgnoreMeta
, 0 ) ;
432 UMASetMenuItemText(menu
, (SInt16
) ::CountMenuItems(menu
), title
, encoding
);
433 UMASetMenuItemShortcut( menu
, (SInt16
) ::CountMenuItems(menu
), entry
) ;
436 void UMAInsertMenuItem( MenuRef menu
, const wxString
& title
, wxFontEncoding encoding
, MenuItemIndex item
, wxAcceleratorEntry
*entry
)
438 MacInsertMenuItem( menu
, "\pA" , item
) ;
440 // don't attempt to interpret metacharacters like a '-' at the beginning (would become a separator otherwise)
441 ChangeMenuItemAttributes( menu
, item
+1, kMenuItemAttrIgnoreMeta
, 0 ) ;
442 UMASetMenuItemText(menu
, item
+1 , title
, encoding
);
443 UMASetMenuItemShortcut( menu
, item
+1 , entry
) ;
450 int gPrOpenCounter
= 0 ;
458 if ( gPrOpenCounter
== 1 )
462 wxASSERT( err
== noErr
) ;
468 OSStatus
UMAPrClose()
472 wxASSERT( gPrOpenCounter
>= 1 ) ;
474 if ( gPrOpenCounter
== 1 )
478 wxASSERT( err
== noErr
) ;
486 pascal QDGlobalsPtr
GetQDGlobalsPtr() ;
487 pascal QDGlobalsPtr
GetQDGlobalsPtr()
489 return QDGlobalsPtr (* (Ptr
*) LMGetCurrentA5 ( ) - 0xCA);
494 void UMAShowWatchCursor()
498 CursHandle watchFob
= GetCursor(watchCursor
);
500 if (watchFob
== NULL
)
507 // Cursor preservedArrow;
508 // GetQDGlobalsArrow(&preservedArrow);
509 // SetQDGlobalsArrow(*watchFob);
511 // SetQDGlobalsArrow(&preservedArrow);
512 SetCursor(*watchFob
);
514 SetCursor(*watchFob
);
519 void UMAShowArrowCursor()
523 SetCursor( GetQDGlobalsArrow(&arrow
) );
525 SetCursor (&(qd
.arrow
));
531 GrafPtr
UMAGetWindowPort( WindowRef inWindowRef
)
533 wxASSERT( inWindowRef
!= NULL
) ;
536 return (GrafPtr
) GetWindowPort( inWindowRef
) ;
538 return (GrafPtr
) inWindowRef
;
542 void UMADisposeWindow( WindowRef inWindowRef
)
544 wxASSERT( inWindowRef
!= NULL
) ;
546 DisposeWindow( inWindowRef
) ;
549 void UMASetWTitle( WindowRef inWindowRef
, const wxString
& title
, wxFontEncoding encoding
)
552 SetWindowTitleWithCFString( inWindowRef
, wxMacCFStringHolder(title
, encoding
) ) ;
556 wxMacStringToPascal( title
, ptitle
) ;
557 SetWTitle( inWindowRef
, ptitle
) ;
561 // appearance additions
563 void UMASetControlTitle( ControlRef inControl
, const wxString
& title
, wxFontEncoding encoding
)
566 SetControlTitleWithCFString( inControl
, wxMacCFStringHolder(title
, encoding
) ) ;
570 wxMacStringToPascal( title
, ptitle
) ;
571 SetControlTitle( inControl
, ptitle
) ;
575 void UMAActivateControl( ControlRef inControl
)
577 #if TARGET_API_MAC_OSX
578 ::ActivateControl( inControl
) ;
581 // we have to add the control after again to the update rgn
582 // otherwise updates get lost
583 if ( !IsControlActive( inControl
) )
585 bool visible
= IsControlVisible( inControl
) ;
587 SetControlVisibility( inControl
, false , false ) ;
589 ::ActivateControl( inControl
) ;
593 SetControlVisibility( inControl
, true , false ) ;
596 InvalWindowRect( GetControlOwner(inControl
), UMAGetControlBoundsInWindowCoords(inControl
, &ctrlBounds
) ) ;
602 void UMAMoveControl( ControlRef inControl
, short x
, short y
)
604 #if TARGET_API_MAC_OSX
605 ::MoveControl( inControl
, x
, y
) ;
608 bool visible
= IsControlVisible( inControl
) ;
611 SetControlVisibility( inControl
, false , false ) ;
613 InvalWindowRect( GetControlOwner(inControl
), GetControlBounds(inControl
, &ctrlBounds
) ) ;
616 ::MoveControl( inControl
, x
, y
) ;
620 SetControlVisibility( inControl
, true , false ) ;
622 InvalWindowRect( GetControlOwner(inControl
), GetControlBounds(inControl
, &ctrlBounds
) ) ;
627 void UMASizeControl( ControlRef inControl
, short x
, short y
)
629 #if TARGET_API_MAC_OSX
630 ::SizeControl( inControl
, x
, y
) ;
633 bool visible
= IsControlVisible( inControl
) ;
636 SetControlVisibility( inControl
, false , false ) ;
638 InvalWindowRect( GetControlOwner(inControl
), GetControlBounds(inControl
, &ctrlBounds
) ) ;
641 ::SizeControl( inControl
, x
, y
) ;
645 SetControlVisibility( inControl
, true , false ) ;
647 InvalWindowRect( GetControlOwner(inControl
), GetControlBounds(inControl
, &ctrlBounds
) ) ;
652 void UMADeactivateControl( ControlRef inControl
)
654 #if TARGET_API_MAC_OSX
655 ::DeactivateControl( inControl
) ;
658 // we have to add the control after again to the update rgn
659 // otherwise updates get lost
660 bool visible
= IsControlVisible( inControl
) ;
662 SetControlVisibility( inControl
, false , false ) ;
664 ::DeactivateControl( inControl
) ;
668 SetControlVisibility( inControl
, true , false ) ;
670 InvalWindowRect( GetControlOwner(inControl
), UMAGetControlBoundsInWindowCoords(inControl
, &ctrlBounds
) ) ;
675 // shows the control and adds the region to the update region
676 void UMAShowControl( ControlRef inControl
)
678 SetControlVisibility( inControl
, true , false ) ;
680 InvalWindowRect( GetControlOwner(inControl
), UMAGetControlBoundsInWindowCoords(inControl
, &ctrlBounds
) ) ;
683 // hides the control and adds the region to the update region
684 void UMAHideControl( ControlRef inControl
)
686 SetControlVisibility( inControl
, false , false ) ;
688 InvalWindowRect( GetControlOwner(inControl
), UMAGetControlBoundsInWindowCoords(inControl
, &ctrlBounds
) ) ;
692 OSErr
UMASetKeyboardFocus( WindowPtr inWindow
,
693 ControlRef inControl
,
694 ControlFocusPart inPart
)
700 SetPortWindowPort( inWindow
) ;
702 err
= SetKeyboardFocus( inWindow
, inControl
, inPart
) ;
708 bool UMAIsWindowFloating( WindowRef inWindow
)
712 GetWindowClass( inWindow
, &cl
) ;
713 return cl
== kFloatingWindowClass
;
716 bool UMAIsWindowModal( WindowRef inWindow
)
720 GetWindowClass( inWindow
, &cl
) ;
721 return cl
< kFloatingWindowClass
;
726 void UMAHighlightAndActivateWindow( WindowRef inWindowRef
, bool inActivate
)
730 // bool isHighlighted = IsWindowHighlited( inWindowRef ) ;
731 // if ( inActivate != isHighlighted )
735 SetPortWindowPort( inWindowRef
) ;
736 HiliteWindow( inWindowRef
, inActivate
) ;
737 ControlRef control
= NULL
;
738 ::GetRootControl( inWindowRef
, &control
) ;
742 UMAActivateControl( control
) ;
744 UMADeactivateControl( control
) ;
751 OSStatus
UMADrawThemePlacard( const Rect
*inRect
, ThemeDrawState inState
)
753 return ::DrawThemePlacard( inRect
, inState
) ;
757 static OSStatus helpMenuStatus
= noErr
;
758 static MenuItemIndex firstCustomItemIndex
= 0 ;
761 OSStatus
UMAGetHelpMenu(
762 MenuRef
* outHelpMenu
,
763 MenuItemIndex
* outFirstCustomItemIndex
)
766 return HMGetHelpMenu( outHelpMenu
, outFirstCustomItemIndex
) ;
769 MenuRef helpMenuHandle
;
771 helpMenuStatus
= HMGetHelpMenuHandle( &helpMenuHandle
) ;
772 if ( firstCustomItemIndex
== 0 && helpMenuStatus
== noErr
)
773 firstCustomItemIndex
= CountMenuItems( helpMenuHandle
) + 1 ;
775 if ( outFirstCustomItemIndex
)
776 *outFirstCustomItemIndex
= firstCustomItemIndex
;
778 *outHelpMenu
= helpMenuHandle
;
780 return helpMenuStatus
;
784 wxMacPortStateHelper::wxMacPortStateHelper( GrafPtr newport
)
790 wxMacPortStateHelper::wxMacPortStateHelper()
795 void wxMacPortStateHelper::Setup( GrafPtr newport
)
797 GetPort( &m_oldPort
) ;
801 wxASSERT_MSG( m_clip
== NULL
, wxT("Cannot call setup twice") ) ;
804 m_textFont
= GetPortTextFont( (CGrafPtr
) newport
);
805 m_textSize
= GetPortTextSize( (CGrafPtr
) newport
);
806 m_textStyle
= GetPortTextFace( (CGrafPtr
) newport
);
807 m_textMode
= GetPortTextMode( (CGrafPtr
) newport
);
808 GetThemeDrawingState( &m_drawingState
) ;
809 m_currentPort
= newport
;
812 void wxMacPortStateHelper::Clear()
816 DisposeRgn( m_clip
) ;
817 DisposeThemeDrawingState( m_drawingState
) ;
822 wxMacPortStateHelper::~wxMacPortStateHelper()
826 SetPort( m_currentPort
) ;
828 DisposeRgn( m_clip
) ;
829 TextFont( m_textFont
);
830 TextSize( m_textSize
);
831 TextFace( m_textStyle
);
832 TextMode( m_textMode
);
833 SetThemeDrawingState( m_drawingState
, true ) ;
834 SetPort( m_oldPort
) ;
838 OSStatus
UMAPutScrap( Size size
, OSType type
, void *data
)
840 OSStatus err
= noErr
;
843 err
= PutScrap( size
, type
, data
) ;
846 err
= GetCurrentScrap( &scrap
);
848 err
= PutScrapFlavor( scrap
, type
, 0, size
, data
);
854 Rect
* UMAGetControlBoundsInWindowCoords( ControlRef theControl
, Rect
*bounds
)
856 GetControlBounds( theControl
, bounds
) ;
858 #if TARGET_API_MAC_OSX
859 WindowRef tlwref
= GetControlOwner( theControl
) ;
861 wxTopLevelWindowMac
* tlwwx
= wxFindWinFromMacWindow( tlwref
) ;
862 if ( tlwwx
!= NULL
&& tlwwx
->MacUsesCompositing() )
864 ControlRef rootControl
= tlwwx
->GetPeer()->GetControlRef() ;
865 HIPoint hiPoint
= CGPointMake( 0 , 0 ) ;
866 HIViewConvertPoint( &hiPoint
, HIViewGetSuperview(theControl
) , rootControl
) ;
867 OffsetRect( bounds
, (short) hiPoint
.x
, (short) hiPoint
.y
) ;
878 static bool sUMASystemInitialized
= false ;
880 bool UMASystemIsInitialized()
882 return sUMASystemInitialized
;
885 void UMASetSystemIsInitialized(bool val
)
887 sUMASystemInitialized
= val
;