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"
19 # include <MacTextEditor.h>
20 # include <Navigation.h>
21 # if defined(TARGET_CARBON)
22 # if PM_USE_SESSION_APIS
25 # include <PMApplication.h>
27 # include <Printing.h>
34 #include "wx/mac/uma.h"
36 #if TARGET_API_MAC_OSX
37 #include "wx/toplevel.h"
40 // since we have decided that we only support 8.6 upwards we are
41 // checking for these minimum requirements in the startup code of
42 // the application so all wxWidgets code can safely assume that appearance 1.1
43 // windows manager, control manager, navigation services etc. are
46 static bool sUMAHasAppearance
= false ;
47 static long sUMAAppearanceVersion
= 0 ;
48 static long sUMASystemVersion
= 0 ;
49 static bool sUMAHasAquaLayout
= false ;
51 static bool sUMAHasInittedAppearance
= false;
53 extern int gAGABackgroundColor
;
55 bool UMAHasAppearance() { return sUMAHasAppearance
; }
56 long UMAGetAppearanceVersion() { return sUMAAppearanceVersion
; }
57 long UMAGetSystemVersion() { return sUMASystemVersion
; }
59 static bool sUMAHasWindowManager
= false ;
60 static long sUMAWindowManagerAttr
= 0 ;
62 bool UMAHasWindowManager() { return sUMAHasWindowManager
; }
63 long UMAGetWindowManagerAttr() { return sUMAWindowManagerAttr
; }
64 bool UMAHasAquaLayout() { return sUMAHasAquaLayout
; }
67 void UMACleanupToolbox()
69 if (sUMAHasInittedAppearance
)
70 UnregisterAppearanceClient() ;
72 if ( NavServicesAvailable() )
75 if ( TXNTerminateTextension
!= (void*) kUnresolvedCFragSymbolAddress
)
76 TXNTerminateTextension( ) ;
79 void UMAInitToolbox( UInt16 inMoreMastersCalls
, bool isEmbedded
)
83 for (long i
= 1; i
<= inMoreMastersCalls
; i
++)
88 ::InitGraf(&qd
.thePort
);
93 ::FlushEvents(everyEvent
, 0);
97 PurgeSpace(&total
, &contig
);
102 if ( Gestalt(gestaltSystemVersion
, &sUMASystemVersion
) != noErr
)
103 sUMASystemVersion
= 0x0000 ;
106 if ( Gestalt( gestaltAppearanceAttr
, &theAppearance
) == noErr
)
108 // If status equals appearanceProcessRegisteredErr it means the
109 // appearance client already was registered (For example if we run
110 // embedded, the host might have registered it). In such a case
111 // we don't unregister it later on.
113 sUMAHasAppearance
= true ;
114 OSStatus status
= RegisterAppearanceClient();
115 if (status
!= appearanceProcessRegisteredErr
)
117 // Appearance client wasn't registered yet.
118 sUMAHasInittedAppearance
= true;
121 if ( Gestalt( gestaltAppearanceVersion
, &theAppearance
) == noErr
)
122 sUMAAppearanceVersion
= theAppearance
;
124 sUMAAppearanceVersion
= 0x0100 ;
127 if ( Gestalt( gestaltWindowMgrAttr
, &sUMAWindowManagerAttr
) == noErr
)
128 sUMAHasWindowManager
= sUMAWindowManagerAttr
& gestaltWindowMgrPresent
;
131 // Call currently implicitely done : InitFloatingWindows() ;
135 if ( sUMAHasWindowManager
)
136 InitFloatingWindows() ;
142 if ( NavServicesAvailable() )
146 Gestalt( gestaltMenuMgrAttr
, &menuMgrAttr
) ;
147 if ( menuMgrAttr
& gestaltMenuMgrAquaLayoutMask
)
148 sUMAHasAquaLayout
= true ;
150 if ( TXNInitTextension
!= (void*) kUnresolvedCFragSymbolAddress
)
152 FontFamilyID fontId
;
157 GetThemeFont(kThemeSmallSystemFont
, GetApplicationScript() , fontName
, &fontSize
, &fontStyle
) ;
158 GetFNum( fontName
, &fontId
);
160 TXNMacOSPreferredFontDescription fontDescriptions
[] =
162 { fontId
, (fontSize
<< 16) , kTXNDefaultFontStyle
, kTXNSystemDefaultEncoding
}
164 int noOfFontDescriptions
= sizeof( fontDescriptions
) / sizeof(TXNMacOSPreferredFontDescription
) ;
166 OptionBits options
= 0 ;
168 if ( UMAGetSystemVersion() < 0x1000 )
169 options
|= kTXNAlwaysUseQuickDrawTextMask
;
171 TXNInitTextension( fontDescriptions
, noOfFontDescriptions
, options
);
174 UMASetSystemIsInitialized( true );
178 Boolean
CanUseATSUI()
181 OSErr err
= Gestalt(gestaltATSUVersion
, &result
);
182 return (err
== noErr
);
187 long UMAGetProcessMode()
190 ProcessInfoRec processinfo
;
191 ProcessSerialNumber procno
;
193 procno
.highLongOfPSN
= 0 ;
194 procno
.lowLongOfPSN
= kCurrentProcess
;
195 processinfo
.processInfoLength
= sizeof(ProcessInfoRec
);
196 processinfo
.processName
= NULL
;
197 processinfo
.processAppSpec
= NULL
;
199 err
= ::GetProcessInformation( &procno
, &processinfo
) ;
200 wxASSERT( err
== noErr
) ;
202 return processinfo
.processMode
;
205 bool UMAGetProcessModeDoesActivateOnFGSwitch()
207 return UMAGetProcessMode() & modeDoesActivateOnFGSwitch
;
212 MenuRef
UMANewMenu( SInt16 id
, const wxString
& title
, wxFontEncoding encoding
)
214 wxString str
= wxStripMenuCodes( title
) ;
218 CreateNewMenu( id
, 0 , &menu
) ;
219 SetMenuTitleWithCFString( menu
, wxMacCFStringHolder(str
, encoding
) ) ;
222 wxMacStringToPascal( str
, ptitle
) ;
223 menu
= ::NewMenu( id
, ptitle
) ;
229 void UMASetMenuTitle( MenuRef menu
, const wxString
& title
, wxFontEncoding encoding
)
231 wxString str
= wxStripMenuCodes( title
) ;
234 SetMenuTitleWithCFString( menu
, wxMacCFStringHolder(str
, encoding
) ) ;
238 wxMacStringToPascal( str
, ptitle
) ;
239 SetMenuTitle( menu
, ptitle
) ;
243 void UMASetMenuItemText( MenuRef menu
, MenuItemIndex item
, const wxString
& title
, wxFontEncoding encoding
)
245 // we don't strip the accels here anymore, must be done before
246 wxString str
= title
;
249 SetMenuItemTextWithCFString( menu
, item
, wxMacCFStringHolder(str
, encoding
) ) ;
253 wxMacStringToPascal( str
, ptitle
) ;
254 SetMenuItemText( menu
, item
, ptitle
) ;
258 UInt32
UMAMenuEvent( EventRecord
*inEvent
)
260 return MenuEvent( inEvent
) ;
263 void UMAEnableMenuItem( MenuRef inMenu
, MenuItemIndex inItem
, bool enable
)
266 EnableMenuItem( inMenu
, inItem
) ;
268 DisableMenuItem( inMenu
, inItem
) ;
271 void UMAAppendSubMenuItem( MenuRef menu
, const wxString
& title
, wxFontEncoding encoding
, SInt16 id
)
273 MacAppendMenu( menu
, "\pA" );
274 UMASetMenuItemText( menu
, (SInt16
) ::CountMenuItems(menu
), title
, encoding
);
275 SetMenuItemHierarchicalID( menu
, CountMenuItems( menu
) , id
) ;
278 void UMAInsertSubMenuItem( MenuRef menu
, const wxString
& title
, wxFontEncoding encoding
, MenuItemIndex item
, SInt16 id
)
280 MacInsertMenuItem( menu
, "\pA" , item
);
281 UMASetMenuItemText( menu
, item
+1, title
, encoding
);
282 SetMenuItemHierarchicalID( menu
, item
+1 , id
) ;
285 void UMASetMenuItemShortcut( MenuRef menu
, MenuItemIndex item
, wxAcceleratorEntry
*entry
)
290 UInt8 modifiers
= 0 ;
291 SInt16 key
= entry
->GetKeyCode() ;
294 bool explicitCommandKey
= (entry
->GetFlags() & wxACCEL_CTRL
);
296 if (entry
->GetFlags() & wxACCEL_ALT
)
297 modifiers
|= kMenuOptionModifier
;
299 if (entry
->GetFlags() & wxACCEL_SHIFT
)
300 modifiers
|= kMenuShiftModifier
;
303 SInt16 macKey
= key
;
304 if ( key
>= WXK_F1
&& key
<= WXK_F15
)
306 if ( !explicitCommandKey
)
307 modifiers
|= kMenuNoCommandModifier
;
309 // for some reasons this must be 0 right now
310 // everything else leads to just the first function key item
311 // to be selected. Thanks to Ryan Wilcox for finding out.
313 glyph
= kMenuF1Glyph
+ ( key
- WXK_F1
) ;
314 if ( key
>= WXK_F13
)
322 macKey
= kBackspaceCharCode
;
323 glyph
= kMenuDeleteLeftGlyph
;
327 macKey
= kTabCharCode
;
328 glyph
= kMenuTabRightGlyph
;
331 case kEnterCharCode
:
332 macKey
= kEnterCharCode
;
333 glyph
= kMenuEnterGlyph
;
337 macKey
= kReturnCharCode
;
338 glyph
= kMenuReturnGlyph
;
342 macKey
= kEscapeCharCode
;
343 glyph
= kMenuEscapeGlyph
;
348 glyph
= kMenuSpaceGlyph
;
352 macKey
= kDeleteCharCode
;
353 glyph
= kMenuDeleteRightGlyph
;
357 macKey
= kClearCharCode
;
358 glyph
= kMenuClearGlyph
;
362 macKey
= kPageUpCharCode
;
363 glyph
= kMenuPageUpGlyph
;
367 macKey
= kPageDownCharCode
;
368 glyph
= kMenuPageDownGlyph
;
372 macKey
= kLeftArrowCharCode
;
373 glyph
= kMenuLeftArrowGlyph
;
377 macKey
= kUpArrowCharCode
;
378 glyph
= kMenuUpArrowGlyph
;
382 macKey
= kRightArrowCharCode
;
383 glyph
= kMenuRightArrowGlyph
;
387 macKey
= kDownArrowCharCode
;
388 glyph
= kMenuDownArrowGlyph
;
392 macKey
= kHomeCharCode
;
393 glyph
= kMenuNorthwestArrowGlyph
;
397 macKey
= kEndCharCode
;
398 glyph
= kMenuSoutheastArrowGlyph
;
401 macKey
= toupper( key
) ;
405 // we now allow non command key shortcuts
406 // remove in case this gives problems
407 if ( !explicitCommandKey
)
408 modifiers
|= kMenuNoCommandModifier
;
411 // 1d and 1e have special meaning to SetItemCmd, so
412 // do not use for these character codes.
413 if (key
!= WXK_UP
&& key
!= WXK_RIGHT
&& key
!= WXK_DOWN
&& key
!= WXK_LEFT
)
414 SetItemCmd( menu
, item
, macKey
);
416 SetMenuItemModifiers( menu
, item
, modifiers
) ;
419 SetMenuItemKeyGlyph( menu
, item
, glyph
) ;
423 void UMAAppendMenuItem( MenuRef menu
, const wxString
& title
, wxFontEncoding encoding
, wxAcceleratorEntry
*entry
)
425 MacAppendMenu(menu
, "\pA");
427 // don't attempt to interpret metacharacters like a '-' at the beginning (would become a separator otherwise)
428 ChangeMenuItemAttributes( menu
, ::CountMenuItems(menu
), kMenuItemAttrIgnoreMeta
, 0 ) ;
429 UMASetMenuItemText(menu
, (SInt16
) ::CountMenuItems(menu
), title
, encoding
);
430 UMASetMenuItemShortcut( menu
, (SInt16
) ::CountMenuItems(menu
), entry
) ;
433 void UMAInsertMenuItem( MenuRef menu
, const wxString
& title
, wxFontEncoding encoding
, MenuItemIndex item
, wxAcceleratorEntry
*entry
)
435 MacInsertMenuItem( menu
, "\pA" , item
) ;
437 // don't attempt to interpret metacharacters like a '-' at the beginning (would become a separator otherwise)
438 ChangeMenuItemAttributes( menu
, item
+1, kMenuItemAttrIgnoreMeta
, 0 ) ;
439 UMASetMenuItemText(menu
, item
+1 , title
, encoding
);
440 UMASetMenuItemShortcut( menu
, item
+1 , entry
) ;
447 int gPrOpenCounter
= 0 ;
455 if ( gPrOpenCounter
== 1 )
459 wxASSERT( err
== noErr
) ;
465 OSStatus
UMAPrClose()
469 wxASSERT( gPrOpenCounter
>= 1 ) ;
471 if ( gPrOpenCounter
== 1 )
475 wxASSERT( err
== noErr
) ;
483 pascal QDGlobalsPtr
GetQDGlobalsPtr() ;
484 pascal QDGlobalsPtr
GetQDGlobalsPtr()
486 return QDGlobalsPtr (* (Ptr
*) LMGetCurrentA5 ( ) - 0xCA);
491 void UMAShowWatchCursor()
495 CursHandle watchFob
= GetCursor(watchCursor
);
497 if (watchFob
== NULL
)
504 // Cursor preservedArrow;
505 // GetQDGlobalsArrow(&preservedArrow);
506 // SetQDGlobalsArrow(*watchFob);
508 // SetQDGlobalsArrow(&preservedArrow);
509 SetCursor(*watchFob
);
511 SetCursor(*watchFob
);
516 void UMAShowArrowCursor()
520 SetCursor( GetQDGlobalsArrow(&arrow
) );
522 SetCursor (&(qd
.arrow
));
528 GrafPtr
UMAGetWindowPort( WindowRef inWindowRef
)
530 wxASSERT( inWindowRef
!= NULL
) ;
533 return (GrafPtr
) GetWindowPort( inWindowRef
) ;
535 return (GrafPtr
) inWindowRef
;
539 void UMADisposeWindow( WindowRef inWindowRef
)
541 wxASSERT( inWindowRef
!= NULL
) ;
543 DisposeWindow( inWindowRef
) ;
546 void UMASetWTitle( WindowRef inWindowRef
, const wxString
& title
, wxFontEncoding encoding
)
549 SetWindowTitleWithCFString( inWindowRef
, wxMacCFStringHolder(title
, encoding
) ) ;
553 wxMacStringToPascal( title
, ptitle
) ;
554 SetWTitle( inWindowRef
, ptitle
) ;
558 // appearance additions
560 void UMASetControlTitle( ControlRef inControl
, const wxString
& title
, wxFontEncoding encoding
)
563 SetControlTitleWithCFString( inControl
, wxMacCFStringHolder(title
, encoding
) ) ;
567 wxMacStringToPascal( title
, ptitle
) ;
568 SetControlTitle( inControl
, ptitle
) ;
572 void UMAActivateControl( ControlRef inControl
)
574 #if TARGET_API_MAC_OSX
575 ::ActivateControl( inControl
) ;
578 // we have to add the control after again to the update rgn
579 // otherwise updates get lost
580 if ( !IsControlActive( inControl
) )
582 bool visible
= IsControlVisible( inControl
) ;
584 SetControlVisibility( inControl
, false , false ) ;
586 ::ActivateControl( inControl
) ;
590 SetControlVisibility( inControl
, true , false ) ;
593 InvalWindowRect( GetControlOwner(inControl
), UMAGetControlBoundsInWindowCoords(inControl
, &ctrlBounds
) ) ;
599 void UMAMoveControl( ControlRef inControl
, short x
, short y
)
601 #if TARGET_API_MAC_OSX
602 ::MoveControl( inControl
, x
, y
) ;
605 bool visible
= IsControlVisible( inControl
) ;
608 SetControlVisibility( inControl
, false , false ) ;
610 InvalWindowRect( GetControlOwner(inControl
), GetControlBounds(inControl
, &ctrlBounds
) ) ;
613 ::MoveControl( inControl
, x
, y
) ;
617 SetControlVisibility( inControl
, true , false ) ;
619 InvalWindowRect( GetControlOwner(inControl
), GetControlBounds(inControl
, &ctrlBounds
) ) ;
624 void UMASizeControl( ControlRef inControl
, short x
, short y
)
626 #if TARGET_API_MAC_OSX
627 ::SizeControl( inControl
, x
, y
) ;
630 bool visible
= IsControlVisible( inControl
) ;
633 SetControlVisibility( inControl
, false , false ) ;
635 InvalWindowRect( GetControlOwner(inControl
), GetControlBounds(inControl
, &ctrlBounds
) ) ;
638 ::SizeControl( inControl
, x
, y
) ;
642 SetControlVisibility( inControl
, true , false ) ;
644 InvalWindowRect( GetControlOwner(inControl
), GetControlBounds(inControl
, &ctrlBounds
) ) ;
649 void UMADeactivateControl( ControlRef inControl
)
651 #if TARGET_API_MAC_OSX
652 ::DeactivateControl( inControl
) ;
655 // we have to add the control after again to the update rgn
656 // otherwise updates get lost
657 bool visible
= IsControlVisible( inControl
) ;
659 SetControlVisibility( inControl
, false , false ) ;
661 ::DeactivateControl( inControl
) ;
665 SetControlVisibility( inControl
, true , false ) ;
667 InvalWindowRect( GetControlOwner(inControl
), UMAGetControlBoundsInWindowCoords(inControl
, &ctrlBounds
) ) ;
672 // shows the control and adds the region to the update region
673 void UMAShowControl( ControlRef inControl
)
675 SetControlVisibility( inControl
, true , false ) ;
677 InvalWindowRect( GetControlOwner(inControl
), UMAGetControlBoundsInWindowCoords(inControl
, &ctrlBounds
) ) ;
680 // hides the control and adds the region to the update region
681 void UMAHideControl( ControlRef inControl
)
683 SetControlVisibility( inControl
, false , false ) ;
685 InvalWindowRect( GetControlOwner(inControl
), UMAGetControlBoundsInWindowCoords(inControl
, &ctrlBounds
) ) ;
689 OSErr
UMASetKeyboardFocus( WindowPtr inWindow
,
690 ControlRef inControl
,
691 ControlFocusPart inPart
)
697 SetPortWindowPort( inWindow
) ;
699 err
= SetKeyboardFocus( inWindow
, inControl
, inPart
) ;
705 bool UMAIsWindowFloating( WindowRef inWindow
)
709 GetWindowClass( inWindow
, &cl
) ;
710 return cl
== kFloatingWindowClass
;
713 bool UMAIsWindowModal( WindowRef inWindow
)
717 GetWindowClass( inWindow
, &cl
) ;
718 return cl
< kFloatingWindowClass
;
723 void UMAHighlightAndActivateWindow( WindowRef inWindowRef
, bool inActivate
)
727 // bool isHighlighted = IsWindowHighlited( inWindowRef ) ;
728 // if ( inActivate != isHighlighted )
732 SetPortWindowPort( inWindowRef
) ;
733 HiliteWindow( inWindowRef
, inActivate
) ;
734 ControlRef control
= NULL
;
735 ::GetRootControl( inWindowRef
, &control
) ;
739 UMAActivateControl( control
) ;
741 UMADeactivateControl( control
) ;
748 OSStatus
UMADrawThemePlacard( const Rect
*inRect
, ThemeDrawState inState
)
750 return ::DrawThemePlacard( inRect
, inState
) ;
754 static OSStatus helpMenuStatus
= noErr
;
755 static MenuItemIndex firstCustomItemIndex
= 0 ;
758 OSStatus
UMAGetHelpMenu(
759 MenuRef
* outHelpMenu
,
760 MenuItemIndex
* outFirstCustomItemIndex
)
763 return HMGetHelpMenu( outHelpMenu
, outFirstCustomItemIndex
) ;
766 MenuRef helpMenuHandle
;
768 helpMenuStatus
= HMGetHelpMenuHandle( &helpMenuHandle
) ;
769 if ( firstCustomItemIndex
== 0 && helpMenuStatus
== noErr
)
770 firstCustomItemIndex
= CountMenuItems( helpMenuHandle
) + 1 ;
772 if ( outFirstCustomItemIndex
)
773 *outFirstCustomItemIndex
= firstCustomItemIndex
;
775 *outHelpMenu
= helpMenuHandle
;
777 return helpMenuStatus
;
781 wxMacPortStateHelper::wxMacPortStateHelper( GrafPtr newport
)
787 wxMacPortStateHelper::wxMacPortStateHelper()
792 void wxMacPortStateHelper::Setup( GrafPtr newport
)
794 GetPort( &m_oldPort
) ;
798 wxASSERT_MSG( m_clip
== NULL
, wxT("Cannot call setup twice") ) ;
801 m_textFont
= GetPortTextFont( (CGrafPtr
) newport
);
802 m_textSize
= GetPortTextSize( (CGrafPtr
) newport
);
803 m_textStyle
= GetPortTextFace( (CGrafPtr
) newport
);
804 m_textMode
= GetPortTextMode( (CGrafPtr
) newport
);
805 GetThemeDrawingState( &m_drawingState
) ;
806 m_currentPort
= newport
;
809 void wxMacPortStateHelper::Clear()
813 DisposeRgn( m_clip
) ;
814 DisposeThemeDrawingState( m_drawingState
) ;
819 wxMacPortStateHelper::~wxMacPortStateHelper()
823 SetPort( m_currentPort
) ;
825 DisposeRgn( m_clip
) ;
826 TextFont( m_textFont
);
827 TextSize( m_textSize
);
828 TextFace( m_textStyle
);
829 TextMode( m_textMode
);
830 SetThemeDrawingState( m_drawingState
, true ) ;
831 SetPort( m_oldPort
) ;
835 OSStatus
UMAPutScrap( Size size
, OSType type
, void *data
)
837 OSStatus err
= noErr
;
840 err
= PutScrap( size
, type
, data
) ;
843 err
= GetCurrentScrap( &scrap
);
845 err
= PutScrapFlavor( scrap
, type
, 0, size
, data
);
851 Rect
* UMAGetControlBoundsInWindowCoords( ControlRef theControl
, Rect
*bounds
)
853 GetControlBounds( theControl
, bounds
) ;
855 #if TARGET_API_MAC_OSX
856 WindowRef tlwref
= GetControlOwner( theControl
) ;
858 wxTopLevelWindowMac
* tlwwx
= wxFindWinFromMacWindow( tlwref
) ;
859 if ( tlwwx
!= NULL
&& tlwwx
->MacUsesCompositing() )
861 ControlRef rootControl
= tlwwx
->GetPeer()->GetControlRef() ;
862 HIPoint hiPoint
= CGPointMake( 0 , 0 ) ;
863 HIViewConvertPoint( &hiPoint
, HIViewGetSuperview(theControl
) , rootControl
) ;
864 OffsetRect( bounds
, (short) hiPoint
.x
, (short) hiPoint
.y
) ;
875 static bool sUMASystemInitialized
= false ;
877 bool UMASystemIsInitialized()
879 return sUMASystemInitialized
;
882 void UMASetSystemIsInitialized(bool val
)
884 sUMASystemInitialized
= val
;