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"
16 #include "wx/toplevel.h"
20 # include <MacTextEditor.h>
21 # include <Navigation.h>
22 # if defined(TARGET_CARBON)
23 # if PM_USE_SESSION_APIS
26 # include <PMApplication.h>
28 # include <Printing.h>
36 #include "wx/mac/uma.h"
38 // since we have decided that we only support 8.6 upwards we are
39 // checking for these minimum requirements in the startup code of
40 // the application so all wxWidgets code can safely assume that appearance 1.1
41 // windows manager, control manager, navigation services etc. are
44 static bool sUMAHasAppearance
= false ;
45 static long sUMAAppearanceVersion
= 0 ;
46 static long sUMASystemVersion
= 0 ;
47 static bool sUMAHasAquaLayout
= false ;
49 static bool sUMAHasInittedAppearance
= false;
51 bool UMAHasAppearance() { return sUMAHasAppearance
; }
52 long UMAGetAppearanceVersion() { return sUMAAppearanceVersion
; }
53 long UMAGetSystemVersion() { return sUMASystemVersion
; }
55 static bool sUMAHasWindowManager
= false ;
56 static long sUMAWindowManagerAttr
= 0 ;
58 bool UMAHasWindowManager() { return sUMAHasWindowManager
; }
59 long UMAGetWindowManagerAttr() { return sUMAWindowManagerAttr
; }
60 bool UMAHasAquaLayout() { return sUMAHasAquaLayout
; }
63 void UMACleanupToolbox()
65 if (sUMAHasInittedAppearance
)
66 UnregisterAppearanceClient() ;
68 if ( NavServicesAvailable() )
71 if ( TXNTerminateTextension
!= (void*) kUnresolvedCFragSymbolAddress
)
72 TXNTerminateTextension( ) ;
75 void UMAInitToolbox( UInt16 inMoreMastersCalls
, bool isEmbedded
)
79 for (long i
= 1; i
<= inMoreMastersCalls
; i
++)
84 ::InitGraf(&qd
.thePort
);
89 ::FlushEvents(everyEvent
, 0);
93 PurgeSpace(&total
, &contig
);
98 if ( Gestalt(gestaltSystemVersion
, &sUMASystemVersion
) != noErr
)
99 sUMASystemVersion
= 0x0000 ;
102 if ( Gestalt( gestaltAppearanceAttr
, &theAppearance
) == noErr
)
104 // If status equals appearanceProcessRegisteredErr it means the
105 // appearance client already was registered (For example if we run
106 // embedded, the host might have registered it). In such a case
107 // we don't unregister it later on.
109 sUMAHasAppearance
= true ;
110 OSStatus status
= RegisterAppearanceClient();
111 if (status
!= appearanceProcessRegisteredErr
)
113 // Appearance client wasn't registered yet.
114 sUMAHasInittedAppearance
= true;
117 if ( Gestalt( gestaltAppearanceVersion
, &theAppearance
) == noErr
)
118 sUMAAppearanceVersion
= theAppearance
;
120 sUMAAppearanceVersion
= 0x0100 ;
123 if ( Gestalt( gestaltWindowMgrAttr
, &sUMAWindowManagerAttr
) == noErr
)
124 sUMAHasWindowManager
= sUMAWindowManagerAttr
& gestaltWindowMgrPresent
;
127 // Call currently implicitely done : InitFloatingWindows() ;
131 if ( sUMAHasWindowManager
)
132 InitFloatingWindows() ;
138 if ( NavServicesAvailable() )
142 Gestalt( gestaltMenuMgrAttr
, &menuMgrAttr
) ;
143 if ( menuMgrAttr
& gestaltMenuMgrAquaLayoutMask
)
144 sUMAHasAquaLayout
= true ;
146 if ( TXNInitTextension
!= (void*) kUnresolvedCFragSymbolAddress
)
148 FontFamilyID fontId
;
153 GetThemeFont(kThemeSmallSystemFont
, GetApplicationScript() , fontName
, &fontSize
, &fontStyle
) ;
154 GetFNum( fontName
, &fontId
);
156 TXNMacOSPreferredFontDescription fontDescriptions
[] =
158 { fontId
, (fontSize
<< 16) , kTXNDefaultFontStyle
, kTXNSystemDefaultEncoding
}
160 int noOfFontDescriptions
= sizeof( fontDescriptions
) / sizeof(TXNMacOSPreferredFontDescription
) ;
162 OptionBits options
= 0 ;
164 if ( UMAGetSystemVersion() < 0x1000 )
165 options
|= kTXNAlwaysUseQuickDrawTextMask
;
167 TXNInitTextension( fontDescriptions
, noOfFontDescriptions
, options
);
170 UMASetSystemIsInitialized( true );
174 Boolean
CanUseATSUI()
177 OSErr err
= Gestalt(gestaltATSUVersion
, &result
);
178 return (err
== noErr
);
183 long UMAGetProcessMode()
186 ProcessInfoRec processinfo
;
187 ProcessSerialNumber procno
;
189 procno
.highLongOfPSN
= 0 ;
190 procno
.lowLongOfPSN
= kCurrentProcess
;
191 processinfo
.processInfoLength
= sizeof(ProcessInfoRec
);
192 processinfo
.processName
= NULL
;
193 processinfo
.processAppSpec
= NULL
;
195 err
= ::GetProcessInformation( &procno
, &processinfo
) ;
196 wxASSERT( err
== noErr
) ;
198 return processinfo
.processMode
;
201 bool UMAGetProcessModeDoesActivateOnFGSwitch()
203 return UMAGetProcessMode() & modeDoesActivateOnFGSwitch
;
208 MenuRef
UMANewMenu( SInt16 id
, const wxString
& title
, wxFontEncoding encoding
)
210 wxString str
= wxStripMenuCodes( title
) ;
214 CreateNewMenu( id
, 0 , &menu
) ;
215 SetMenuTitleWithCFString( menu
, wxMacCFStringHolder(str
, encoding
) ) ;
218 wxMacStringToPascal( str
, ptitle
) ;
219 menu
= ::NewMenu( id
, ptitle
) ;
225 void UMASetMenuTitle( MenuRef menu
, const wxString
& title
, wxFontEncoding encoding
)
227 wxString str
= wxStripMenuCodes( title
) ;
230 SetMenuTitleWithCFString( menu
, wxMacCFStringHolder(str
, encoding
) ) ;
234 wxMacStringToPascal( str
, ptitle
) ;
235 SetMenuTitle( menu
, ptitle
) ;
239 void UMASetMenuItemText( MenuRef menu
, MenuItemIndex item
, const wxString
& title
, wxFontEncoding encoding
)
241 // we don't strip the accels here anymore, must be done before
242 wxString str
= title
;
245 SetMenuItemTextWithCFString( menu
, item
, wxMacCFStringHolder(str
, encoding
) ) ;
249 wxMacStringToPascal( str
, ptitle
) ;
250 SetMenuItemText( menu
, item
, ptitle
) ;
254 UInt32
UMAMenuEvent( EventRecord
*inEvent
)
256 return MenuEvent( inEvent
) ;
259 void UMAEnableMenuItem( MenuRef inMenu
, MenuItemIndex inItem
, bool enable
)
262 EnableMenuItem( inMenu
, inItem
) ;
264 DisableMenuItem( inMenu
, inItem
) ;
267 void UMAAppendSubMenuItem( MenuRef menu
, const wxString
& title
, wxFontEncoding encoding
, SInt16 id
)
269 MacAppendMenu( menu
, "\pA" );
270 UMASetMenuItemText( menu
, (SInt16
) ::CountMenuItems(menu
), title
, encoding
);
271 SetMenuItemHierarchicalID( menu
, CountMenuItems( menu
) , id
) ;
274 void UMAInsertSubMenuItem( MenuRef menu
, const wxString
& title
, wxFontEncoding encoding
, MenuItemIndex item
, SInt16 id
)
276 MacInsertMenuItem( menu
, "\pA" , item
);
277 UMASetMenuItemText( menu
, item
+1, title
, encoding
);
278 SetMenuItemHierarchicalID( menu
, item
+1 , id
) ;
281 void UMASetMenuItemShortcut( MenuRef menu
, MenuItemIndex item
, wxAcceleratorEntry
*entry
)
286 UInt8 modifiers
= 0 ;
287 SInt16 key
= entry
->GetKeyCode() ;
290 bool explicitCommandKey
= (entry
->GetFlags() & wxACCEL_CTRL
);
292 if (entry
->GetFlags() & wxACCEL_ALT
)
293 modifiers
|= kMenuOptionModifier
;
295 if (entry
->GetFlags() & wxACCEL_SHIFT
)
296 modifiers
|= kMenuShiftModifier
;
299 SInt16 macKey
= key
;
300 if ( key
>= WXK_F1
&& key
<= WXK_F15
)
302 if ( !explicitCommandKey
)
303 modifiers
|= kMenuNoCommandModifier
;
305 // for some reasons this must be 0 right now
306 // everything else leads to just the first function key item
307 // to be selected. Thanks to Ryan Wilcox for finding out.
309 glyph
= kMenuF1Glyph
+ ( key
- WXK_F1
) ;
310 if ( key
>= WXK_F13
)
318 macKey
= kBackspaceCharCode
;
319 glyph
= kMenuDeleteLeftGlyph
;
323 macKey
= kTabCharCode
;
324 glyph
= kMenuTabRightGlyph
;
327 case kEnterCharCode
:
328 macKey
= kEnterCharCode
;
329 glyph
= kMenuEnterGlyph
;
333 macKey
= kReturnCharCode
;
334 glyph
= kMenuReturnGlyph
;
338 macKey
= kEscapeCharCode
;
339 glyph
= kMenuEscapeGlyph
;
344 glyph
= kMenuSpaceGlyph
;
348 macKey
= kDeleteCharCode
;
349 glyph
= kMenuDeleteRightGlyph
;
353 macKey
= kClearCharCode
;
354 glyph
= kMenuClearGlyph
;
358 macKey
= kPageUpCharCode
;
359 glyph
= kMenuPageUpGlyph
;
363 macKey
= kPageDownCharCode
;
364 glyph
= kMenuPageDownGlyph
;
368 macKey
= kLeftArrowCharCode
;
369 glyph
= kMenuLeftArrowGlyph
;
373 macKey
= kUpArrowCharCode
;
374 glyph
= kMenuUpArrowGlyph
;
378 macKey
= kRightArrowCharCode
;
379 glyph
= kMenuRightArrowGlyph
;
383 macKey
= kDownArrowCharCode
;
384 glyph
= kMenuDownArrowGlyph
;
388 macKey
= kHomeCharCode
;
389 glyph
= kMenuNorthwestArrowGlyph
;
393 macKey
= kEndCharCode
;
394 glyph
= kMenuSoutheastArrowGlyph
;
397 macKey
= toupper( key
) ;
401 // we now allow non command key shortcuts
402 // remove in case this gives problems
403 if ( !explicitCommandKey
)
404 modifiers
|= kMenuNoCommandModifier
;
407 // 1d and 1e have special meaning to SetItemCmd, so
408 // do not use for these character codes.
409 if (key
!= WXK_UP
&& key
!= WXK_RIGHT
&& key
!= WXK_DOWN
&& key
!= WXK_LEFT
)
410 SetItemCmd( menu
, item
, macKey
);
412 SetMenuItemModifiers( menu
, item
, modifiers
) ;
415 SetMenuItemKeyGlyph( menu
, item
, glyph
) ;
419 void UMAAppendMenuItem( MenuRef menu
, const wxString
& title
, wxFontEncoding encoding
, wxAcceleratorEntry
*entry
)
421 MacAppendMenu(menu
, "\pA");
423 // don't attempt to interpret metacharacters like a '-' at the beginning (would become a separator otherwise)
424 ChangeMenuItemAttributes( menu
, ::CountMenuItems(menu
), kMenuItemAttrIgnoreMeta
, 0 ) ;
425 UMASetMenuItemText(menu
, (SInt16
) ::CountMenuItems(menu
), title
, encoding
);
426 UMASetMenuItemShortcut( menu
, (SInt16
) ::CountMenuItems(menu
), entry
) ;
429 void UMAInsertMenuItem( MenuRef menu
, const wxString
& title
, wxFontEncoding encoding
, MenuItemIndex item
, wxAcceleratorEntry
*entry
)
431 MacInsertMenuItem( menu
, "\pA" , item
) ;
433 // don't attempt to interpret metacharacters like a '-' at the beginning (would become a separator otherwise)
434 ChangeMenuItemAttributes( menu
, item
+1, kMenuItemAttrIgnoreMeta
, 0 ) ;
435 UMASetMenuItemText(menu
, item
+1 , title
, encoding
);
436 UMASetMenuItemShortcut( menu
, item
+1 , entry
) ;
443 int gPrOpenCounter
= 0 ;
451 if ( gPrOpenCounter
== 1 )
455 wxASSERT( err
== noErr
) ;
461 OSStatus
UMAPrClose()
465 wxASSERT( gPrOpenCounter
>= 1 ) ;
467 if ( gPrOpenCounter
== 1 )
471 wxASSERT( err
== noErr
) ;
479 pascal QDGlobalsPtr
GetQDGlobalsPtr() ;
480 pascal QDGlobalsPtr
GetQDGlobalsPtr()
482 return QDGlobalsPtr (* (Ptr
*) LMGetCurrentA5 ( ) - 0xCA);
487 void UMAShowWatchCursor()
491 CursHandle watchFob
= GetCursor(watchCursor
);
493 if (watchFob
== NULL
)
500 // Cursor preservedArrow;
501 // GetQDGlobalsArrow(&preservedArrow);
502 // SetQDGlobalsArrow(*watchFob);
504 // SetQDGlobalsArrow(&preservedArrow);
505 SetCursor(*watchFob
);
507 SetCursor(*watchFob
);
512 void UMAShowArrowCursor()
516 SetCursor( GetQDGlobalsArrow(&arrow
) );
518 SetCursor (&(qd
.arrow
));
524 GrafPtr
UMAGetWindowPort( WindowRef inWindowRef
)
526 wxASSERT( inWindowRef
!= NULL
) ;
529 return (GrafPtr
) GetWindowPort( inWindowRef
) ;
531 return (GrafPtr
) inWindowRef
;
535 void UMADisposeWindow( WindowRef inWindowRef
)
537 wxASSERT( inWindowRef
!= NULL
) ;
539 DisposeWindow( inWindowRef
) ;
542 void UMASetWTitle( WindowRef inWindowRef
, const wxString
& title
, wxFontEncoding encoding
)
545 SetWindowTitleWithCFString( inWindowRef
, wxMacCFStringHolder(title
, encoding
) ) ;
549 wxMacStringToPascal( title
, ptitle
) ;
550 SetWTitle( inWindowRef
, ptitle
) ;
554 // appearance additions
556 void UMASetControlTitle( ControlRef inControl
, const wxString
& title
, wxFontEncoding encoding
)
559 SetControlTitleWithCFString( inControl
, wxMacCFStringHolder(title
, encoding
) ) ;
563 wxMacStringToPascal( title
, ptitle
) ;
564 SetControlTitle( inControl
, ptitle
) ;
568 void UMAActivateControl( ControlRef inControl
)
570 #if TARGET_API_MAC_OSX
571 ::ActivateControl( inControl
) ;
574 // we have to add the control after again to the update rgn
575 // otherwise updates get lost
576 if ( !IsControlActive( inControl
) )
578 bool visible
= IsControlVisible( inControl
) ;
580 SetControlVisibility( inControl
, false , false ) ;
582 ::ActivateControl( inControl
) ;
586 SetControlVisibility( inControl
, true , false ) ;
589 InvalWindowRect( GetControlOwner(inControl
), UMAGetControlBoundsInWindowCoords(inControl
, &ctrlBounds
) ) ;
595 void UMAMoveControl( ControlRef inControl
, short x
, short y
)
597 #if TARGET_API_MAC_OSX
598 ::MoveControl( inControl
, x
, y
) ;
601 bool visible
= IsControlVisible( inControl
) ;
604 SetControlVisibility( inControl
, false , false ) ;
606 InvalWindowRect( GetControlOwner(inControl
), GetControlBounds(inControl
, &ctrlBounds
) ) ;
609 ::MoveControl( inControl
, x
, y
) ;
613 SetControlVisibility( inControl
, true , false ) ;
615 InvalWindowRect( GetControlOwner(inControl
), GetControlBounds(inControl
, &ctrlBounds
) ) ;
620 void UMASizeControl( ControlRef inControl
, short x
, short y
)
622 #if TARGET_API_MAC_OSX
623 ::SizeControl( inControl
, x
, y
) ;
626 bool visible
= IsControlVisible( inControl
) ;
629 SetControlVisibility( inControl
, false , false ) ;
631 InvalWindowRect( GetControlOwner(inControl
), GetControlBounds(inControl
, &ctrlBounds
) ) ;
634 ::SizeControl( inControl
, x
, y
) ;
638 SetControlVisibility( inControl
, true , false ) ;
640 InvalWindowRect( GetControlOwner(inControl
), GetControlBounds(inControl
, &ctrlBounds
) ) ;
645 void UMADeactivateControl( ControlRef inControl
)
647 #if TARGET_API_MAC_OSX
648 ::DeactivateControl( inControl
) ;
651 // we have to add the control after again to the update rgn
652 // otherwise updates get lost
653 bool visible
= IsControlVisible( inControl
) ;
655 SetControlVisibility( inControl
, false , false ) ;
657 ::DeactivateControl( inControl
) ;
661 SetControlVisibility( inControl
, true , false ) ;
663 InvalWindowRect( GetControlOwner(inControl
), UMAGetControlBoundsInWindowCoords(inControl
, &ctrlBounds
) ) ;
668 // shows the control and adds the region to the update region
669 void UMAShowControl( ControlRef inControl
)
671 SetControlVisibility( inControl
, true , false ) ;
673 InvalWindowRect( GetControlOwner(inControl
), UMAGetControlBoundsInWindowCoords(inControl
, &ctrlBounds
) ) ;
676 // hides the control and adds the region to the update region
677 void UMAHideControl( ControlRef inControl
)
679 SetControlVisibility( inControl
, false , false ) ;
681 InvalWindowRect( GetControlOwner(inControl
), UMAGetControlBoundsInWindowCoords(inControl
, &ctrlBounds
) ) ;
685 OSErr
UMASetKeyboardFocus( WindowPtr inWindow
,
686 ControlRef inControl
,
687 ControlFocusPart inPart
)
693 SetPortWindowPort( inWindow
) ;
695 err
= SetKeyboardFocus( inWindow
, inControl
, inPart
) ;
701 bool UMAIsWindowFloating( WindowRef inWindow
)
705 GetWindowClass( inWindow
, &cl
) ;
706 return cl
== kFloatingWindowClass
;
709 bool UMAIsWindowModal( WindowRef inWindow
)
713 GetWindowClass( inWindow
, &cl
) ;
714 return cl
< kFloatingWindowClass
;
719 void UMAHighlightAndActivateWindow( WindowRef inWindowRef
, bool inActivate
)
723 // bool isHighlighted = IsWindowHighlited( inWindowRef ) ;
724 // if ( inActivate != isHighlighted )
728 SetPortWindowPort( inWindowRef
) ;
729 HiliteWindow( inWindowRef
, inActivate
) ;
730 ControlRef control
= NULL
;
731 ::GetRootControl( inWindowRef
, &control
) ;
735 UMAActivateControl( control
) ;
737 UMADeactivateControl( control
) ;
744 OSStatus
UMADrawThemePlacard( const Rect
*inRect
, ThemeDrawState inState
)
746 return ::DrawThemePlacard( inRect
, inState
) ;
750 static OSStatus helpMenuStatus
= noErr
;
751 static MenuItemIndex firstCustomItemIndex
= 0 ;
754 OSStatus
UMAGetHelpMenu(
755 MenuRef
* outHelpMenu
,
756 MenuItemIndex
* outFirstCustomItemIndex
)
759 return HMGetHelpMenu( outHelpMenu
, outFirstCustomItemIndex
) ;
762 MenuRef helpMenuHandle
;
764 helpMenuStatus
= HMGetHelpMenuHandle( &helpMenuHandle
) ;
765 if ( firstCustomItemIndex
== 0 && helpMenuStatus
== noErr
)
766 firstCustomItemIndex
= CountMenuItems( helpMenuHandle
) + 1 ;
768 if ( outFirstCustomItemIndex
)
769 *outFirstCustomItemIndex
= firstCustomItemIndex
;
771 *outHelpMenu
= helpMenuHandle
;
773 return helpMenuStatus
;
777 wxMacPortStateHelper::wxMacPortStateHelper( GrafPtr newport
)
783 wxMacPortStateHelper::wxMacPortStateHelper()
788 void wxMacPortStateHelper::Setup( GrafPtr newport
)
790 GetPort( &m_oldPort
) ;
794 wxASSERT_MSG( m_clip
== NULL
, wxT("Cannot call setup twice") ) ;
797 m_textFont
= GetPortTextFont( (CGrafPtr
) newport
);
798 m_textSize
= GetPortTextSize( (CGrafPtr
) newport
);
799 m_textStyle
= GetPortTextFace( (CGrafPtr
) newport
);
800 m_textMode
= GetPortTextMode( (CGrafPtr
) newport
);
801 GetThemeDrawingState( &m_drawingState
) ;
802 m_currentPort
= newport
;
805 void wxMacPortStateHelper::Clear()
809 DisposeRgn( m_clip
) ;
810 DisposeThemeDrawingState( m_drawingState
) ;
815 wxMacPortStateHelper::~wxMacPortStateHelper()
819 SetPort( m_currentPort
) ;
821 DisposeRgn( m_clip
) ;
822 TextFont( m_textFont
);
823 TextSize( m_textSize
);
824 TextFace( m_textStyle
);
825 TextMode( m_textMode
);
826 SetThemeDrawingState( m_drawingState
, true ) ;
827 SetPort( m_oldPort
) ;
831 OSStatus
UMAPutScrap( Size size
, OSType type
, void *data
)
833 OSStatus err
= noErr
;
836 err
= PutScrap( size
, type
, data
) ;
839 err
= GetCurrentScrap( &scrap
);
841 err
= PutScrapFlavor( scrap
, type
, 0, size
, data
);
847 Rect
* UMAGetControlBoundsInWindowCoords( ControlRef theControl
, Rect
*bounds
)
849 GetControlBounds( theControl
, bounds
) ;
851 #if TARGET_API_MAC_OSX
852 WindowRef tlwref
= GetControlOwner( theControl
) ;
854 wxTopLevelWindowMac
* tlwwx
= wxFindWinFromMacWindow( tlwref
) ;
857 ControlRef rootControl
= tlwwx
->GetPeer()->GetControlRef() ;
858 HIPoint hiPoint
= CGPointMake( 0 , 0 ) ;
859 HIViewConvertPoint( &hiPoint
, HIViewGetSuperview(theControl
) , rootControl
) ;
860 OffsetRect( bounds
, (short) hiPoint
.x
, (short) hiPoint
.y
) ;
871 static bool sUMASystemInitialized
= false ;
873 bool UMASystemIsInitialized()
875 return sUMASystemInitialized
;
878 void UMASetSystemIsInitialized(bool val
)
880 sUMASystemInitialized
= val
;