1 /////////////////////////////////////////////////////////////////////////////
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 #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
;
54 bool UMAHasAppearance() { return sUMAHasAppearance
; }
55 long UMAGetAppearanceVersion() { return sUMAAppearanceVersion
; }
56 long UMAGetSystemVersion() { return sUMASystemVersion
; }
58 static bool sUMAHasWindowManager
= false ;
59 static long sUMAWindowManagerAttr
= 0 ;
61 bool UMAHasWindowManager() { return sUMAHasWindowManager
; }
62 long UMAGetWindowManagerAttr() { return sUMAWindowManagerAttr
; }
63 bool UMAHasAquaLayout() { return sUMAHasAquaLayout
; }
66 void UMACleanupToolbox()
68 if (sUMAHasInittedAppearance
)
70 UnregisterAppearanceClient() ;
72 if ( NavServicesAvailable() )
76 if ( TXNTerminateTextension
!= (void*) kUnresolvedCFragSymbolAddress
)
77 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 sUMAHasAppearance
= true ;
109 OSStatus status
= RegisterAppearanceClient();
110 // If status equals appearanceProcessRegisteredErr it means the
111 // appearance client already was registered (For example if we run
112 // embedded, the host might have registered it). In such a case
113 // we don't unregister it later on.
114 if (status
!= appearanceProcessRegisteredErr
)
116 // Appearance client wasn't registered yet.
117 sUMAHasInittedAppearance
= true;
120 if ( Gestalt( gestaltAppearanceVersion
, &theAppearance
) == noErr
)
122 sUMAAppearanceVersion
= theAppearance
;
126 sUMAAppearanceVersion
= 0x0100 ;
129 if ( Gestalt( gestaltWindowMgrAttr
, &sUMAWindowManagerAttr
) == noErr
)
131 sUMAHasWindowManager
= sUMAWindowManagerAttr
& gestaltWindowMgrPresent
;
135 // Call currently implicitely done : InitFloatingWindows() ;
139 if ( sUMAHasWindowManager
)
140 InitFloatingWindows() ;
146 if ( NavServicesAvailable() )
152 Gestalt( gestaltMenuMgrAttr
, &menuMgrAttr
) ;
153 if ( menuMgrAttr
& gestaltMenuMgrAquaLayoutMask
)
154 sUMAHasAquaLayout
= true ;
156 if ( TXNInitTextension
!= (void*) kUnresolvedCFragSymbolAddress
)
158 FontFamilyID fontId
;
162 GetThemeFont(kThemeSmallSystemFont
, GetApplicationScript() , fontName
, &fontSize
, &fontStyle
) ;
163 GetFNum( fontName
, &fontId
);
165 TXNMacOSPreferredFontDescription fontDescriptions
[] =
167 { fontId
, (fontSize
<< 16) ,kTXNDefaultFontStyle
, kTXNSystemDefaultEncoding
}
169 int noOfFontDescriptions
= sizeof( fontDescriptions
) / sizeof(TXNMacOSPreferredFontDescription
) ;
171 OptionBits options
= 0 ;
173 if ( UMAGetSystemVersion() < 0x1000 )
175 options
|= kTXNAlwaysUseQuickDrawTextMask
;
177 TXNInitTextension(fontDescriptions
, noOfFontDescriptions
, options
);
181 UMASetSystemIsInitialized(true);
186 Boolean CanUseATSUI()
189 OSErr err = Gestalt(gestaltATSUVersion, &result);
190 return (err == noErr);
194 long UMAGetProcessMode()
197 ProcessInfoRec processinfo
;
198 ProcessSerialNumber procno
;
200 procno
.highLongOfPSN
= 0 ;
201 procno
.lowLongOfPSN
= kCurrentProcess
;
202 processinfo
.processInfoLength
= sizeof(ProcessInfoRec
);
203 processinfo
.processName
= NULL
;
204 processinfo
.processAppSpec
= NULL
;
206 err
= ::GetProcessInformation( &procno
, &processinfo
) ;
207 wxASSERT( err
== noErr
) ;
208 return processinfo
.processMode
;
211 bool UMAGetProcessModeDoesActivateOnFGSwitch()
213 return UMAGetProcessMode() & modeDoesActivateOnFGSwitch
;
218 MenuRef
UMANewMenu( SInt16 id
, const wxString
& title
, wxFontEncoding encoding
)
220 wxString str
= wxStripMenuCodes( title
) ;
223 CreateNewMenu( id
, 0 , &menu
) ;
224 SetMenuTitleWithCFString( menu
, wxMacCFStringHolder(str
, encoding
) ) ;
227 wxMacStringToPascal( str
, ptitle
) ;
228 menu
= ::NewMenu( id
, ptitle
) ;
233 void UMASetMenuTitle( MenuRef menu
, const wxString
& title
, wxFontEncoding encoding
)
235 wxString str
= wxStripMenuCodes( title
) ;
237 SetMenuTitleWithCFString( menu
, wxMacCFStringHolder(str
, encoding
) ) ;
240 wxMacStringToPascal( str
, ptitle
) ;
241 SetMenuTitle( menu
, ptitle
) ;
245 void UMASetMenuItemText( MenuRef menu
, MenuItemIndex item
, const wxString
& title
, wxFontEncoding encoding
)
247 wxString str
= wxStripMenuCodes( title
) ;
249 SetMenuItemTextWithCFString( menu
, item
, wxMacCFStringHolder(str
, encoding
) ) ;
252 wxMacStringToPascal( str
, ptitle
) ;
253 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
= false ;
296 if ( entry
->GetFlags() & wxACCEL_CTRL
)
298 explicitCommandKey
= true ;
301 if (entry
->GetFlags() & wxACCEL_ALT
)
303 modifiers
|= kMenuOptionModifier
;
306 if (entry
->GetFlags() & wxACCEL_SHIFT
)
308 modifiers
|= kMenuShiftModifier
;
312 SInt16 macKey
= key
;
313 if ( key
>= WXK_F1
&& key
<= WXK_F15
)
315 // for some reasons this must be 0 right now
316 // everything else leads to just the first function key item
317 // to be selected. Thanks to Ryan Wilcox for finding out.
319 glyph
= kMenuF1Glyph
+ ( key
- WXK_F1
) ;
320 if ( key
>= WXK_F13
)
322 if ( !explicitCommandKey
)
323 modifiers
|= kMenuNoCommandModifier
;
330 macKey
= kBackspaceCharCode
;
331 glyph
= kMenuDeleteLeftGlyph
;
334 macKey
= kTabCharCode
;
335 glyph
= kMenuTabRightGlyph
;
337 case kEnterCharCode
:
338 macKey
= kEnterCharCode
;
339 glyph
= kMenuEnterGlyph
;
342 macKey
= kReturnCharCode
;
343 glyph
= kMenuReturnGlyph
;
346 macKey
= kEscapeCharCode
;
347 glyph
= kMenuEscapeGlyph
;
351 glyph
= kMenuSpaceGlyph
;
354 macKey
= kDeleteCharCode
;
355 glyph
= kMenuDeleteRightGlyph
;
358 macKey
= kClearCharCode
;
359 glyph
= kMenuClearGlyph
;
361 case WXK_PRIOR
: // PAGE UP
362 macKey
= kPageUpCharCode
;
363 glyph
= kMenuPageUpGlyph
;
366 macKey
= kPageDownCharCode
;
367 glyph
= kMenuPageDownGlyph
;
370 macKey
= kLeftArrowCharCode
;
371 glyph
= kMenuLeftArrowGlyph
;
374 macKey
= kUpArrowCharCode
;
375 glyph
= kMenuUpArrowGlyph
;
378 macKey
= kRightArrowCharCode
;
379 glyph
= kMenuRightArrowGlyph
;
382 macKey
= kDownArrowCharCode
;
383 glyph
= kMenuDownArrowGlyph
;
386 macKey
= toupper( key
) ;
389 // we now allow non command key shortcuts
390 // remove in case this gives problems
391 if ( !explicitCommandKey
)
392 modifiers
|= kMenuNoCommandModifier
;
395 // 1d and 1e have special meaning to SetItemCmd, so
396 // do not use for these character codes.
397 if (key
!= WXK_UP
&& key
!= WXK_RIGHT
)
398 SetItemCmd( menu
, item
, macKey
);
400 SetMenuItemModifiers(menu
, item
, modifiers
) ;
403 SetMenuItemKeyGlyph(menu
, item
, glyph
) ;
407 void UMAAppendMenuItem( MenuRef menu
, const wxString
& title
, wxFontEncoding encoding
, wxAcceleratorEntry
*entry
)
409 MacAppendMenu(menu
, "\pA");
410 // don't attempt to interpret metacharacters like a '-' at the beginning (would become a separator otherwise)
411 ChangeMenuItemAttributes( menu
, ::CountMenuItems(menu
), kMenuItemAttrIgnoreMeta
, 0 ) ;
412 UMASetMenuItemText(menu
, (SInt16
) ::CountMenuItems(menu
), title
, encoding
);
413 UMASetMenuItemShortcut( menu
, (SInt16
) ::CountMenuItems(menu
), entry
) ;
416 void UMAInsertMenuItem( MenuRef menu
, const wxString
& title
, wxFontEncoding encoding
, MenuItemIndex item
, wxAcceleratorEntry
*entry
)
418 MacInsertMenuItem( menu
, "\pA" , item
) ;
419 // don't attempt to interpret metacharacters like a '-' at the beginning (would become a separator otherwise)
420 ChangeMenuItemAttributes( menu
, item
+1, kMenuItemAttrIgnoreMeta
, 0 ) ;
421 UMASetMenuItemText(menu
, item
+1 , title
, encoding
);
422 UMASetMenuItemShortcut( menu
, item
+1 , entry
) ;
429 int gPrOpenCounter
= 0 ;
435 if ( gPrOpenCounter
== 1 )
439 wxASSERT( err
== noErr
) ;
444 OSStatus
UMAPrClose()
447 wxASSERT( gPrOpenCounter
>= 1 ) ;
448 if ( gPrOpenCounter
== 1 )
452 wxASSERT( err
== noErr
) ;
458 pascal QDGlobalsPtr
GetQDGlobalsPtr (void) ;
459 pascal QDGlobalsPtr
GetQDGlobalsPtr (void)
461 return QDGlobalsPtr (* (Ptr
*) LMGetCurrentA5 ( ) - 0xCA);
466 void UMAShowWatchCursor()
470 CursHandle watchFob
= GetCursor (watchCursor
);
477 // Cursor preservedArrow;
478 // GetQDGlobalsArrow (&preservedArrow);
479 // SetQDGlobalsArrow (*watchFob);
481 // SetQDGlobalsArrow (&preservedArrow);
482 SetCursor (*watchFob
);
484 SetCursor (*watchFob
);
489 void UMAShowArrowCursor()
493 SetCursor (GetQDGlobalsArrow (&arrow
));
495 SetCursor (&(qd
.arrow
));
501 GrafPtr
UMAGetWindowPort( WindowRef inWindowRef
)
503 wxASSERT( inWindowRef
!= NULL
) ;
505 return (GrafPtr
) GetWindowPort( inWindowRef
) ;
507 return (GrafPtr
) inWindowRef
;
511 void UMADisposeWindow( WindowRef inWindowRef
)
513 wxASSERT( inWindowRef
!= NULL
) ;
514 DisposeWindow( inWindowRef
) ;
517 void UMASetWTitle( WindowRef inWindowRef
, const wxString
& title
, wxFontEncoding encoding
)
520 SetWindowTitleWithCFString( inWindowRef
, wxMacCFStringHolder(title
, encoding
) ) ;
523 wxMacStringToPascal( title
, ptitle
) ;
524 SetWTitle( inWindowRef
, ptitle
) ;
528 // appearance additions
530 void UMASetControlTitle( ControlRef inControl
, const wxString
& title
, wxFontEncoding encoding
)
533 SetControlTitleWithCFString( inControl
, wxMacCFStringHolder(title
, encoding
) ) ;
536 wxMacStringToPascal( title
, ptitle
) ;
537 SetControlTitle( inControl
, ptitle
) ;
541 void UMAActivateControl( ControlRef inControl
)
543 #if !TARGET_API_MAC_OSX
544 // we have to add the control after again to the update rgn
545 // otherwise updates get lost
546 if ( !IsControlActive( inControl
) )
548 bool visible
= IsControlVisible( inControl
) ;
550 SetControlVisibility( inControl
, false , false ) ;
552 ::ActivateControl( inControl
) ;
553 #if !TARGET_API_MAC_OSX
555 SetControlVisibility( inControl
, true , false ) ;
558 InvalWindowRect(GetControlOwner(inControl
),UMAGetControlBoundsInWindowCoords(inControl
,&ctrlBounds
) ) ;
564 void UMAMoveControl( ControlRef inControl
, short x
, short y
)
566 #if !TARGET_API_MAC_OSX
567 bool visible
= IsControlVisible( inControl
) ;
569 SetControlVisibility( inControl
, false , false ) ;
571 InvalWindowRect(GetControlOwner(inControl
),GetControlBounds(inControl
,&ctrlBounds
) ) ;
574 ::MoveControl( inControl
, x
, y
) ;
575 #if !TARGET_API_MAC_OSX
577 SetControlVisibility( inControl
, true , false ) ;
579 InvalWindowRect(GetControlOwner(inControl
),GetControlBounds(inControl
,&ctrlBounds
) ) ;
584 void UMASizeControl( ControlRef inControl
, short x
, short y
)
586 #if !TARGET_API_MAC_OSX
587 bool visible
= IsControlVisible( inControl
) ;
589 SetControlVisibility( inControl
, false , false ) ;
591 InvalWindowRect(GetControlOwner(inControl
),GetControlBounds(inControl
,&ctrlBounds
) ) ;
594 ::SizeControl( inControl
, x
, y
) ;
595 #if !TARGET_API_MAC_OSX
597 SetControlVisibility( inControl
, true , false ) ;
599 InvalWindowRect(GetControlOwner(inControl
),GetControlBounds(inControl
,&ctrlBounds
) ) ;
604 void UMADeactivateControl( ControlRef inControl
)
606 #if !TARGET_API_MAC_OSX
607 // we have to add the control after again to the update rgn
608 // otherwise updates get lost
609 bool visible
= IsControlVisible( inControl
) ;
611 SetControlVisibility( inControl
, false , false ) ;
613 ::DeactivateControl( inControl
) ;
614 #if !TARGET_API_MAC_OSX
616 SetControlVisibility( inControl
, true , false ) ;
618 InvalWindowRect(GetControlOwner(inControl
),UMAGetControlBoundsInWindowCoords(inControl
,&ctrlBounds
) ) ;
622 // shows the control and adds the region to the update region
623 void UMAShowControl (ControlRef inControl
)
625 SetControlVisibility( inControl
, true , false ) ;
627 InvalWindowRect(GetControlOwner(inControl
),UMAGetControlBoundsInWindowCoords(inControl
,&ctrlBounds
) ) ;
630 // hides the control and adds the region to the update region
631 void UMAHideControl (ControlRef inControl
)
633 SetControlVisibility( inControl
, false , false ) ;
635 InvalWindowRect(GetControlOwner(inControl
),UMAGetControlBoundsInWindowCoords(inControl
,&ctrlBounds
) ) ;
638 OSErr
UMASetKeyboardFocus (WindowPtr inWindow
,
639 ControlRef inControl
,
640 ControlFocusPart inPart
)
646 SetPortWindowPort( inWindow
) ;
648 err
= SetKeyboardFocus( inWindow
, inControl
, inPart
) ;
653 bool UMAIsWindowFloating( WindowRef inWindow
)
657 GetWindowClass( inWindow
, &cl
) ;
658 return cl
== kFloatingWindowClass
;
661 bool UMAIsWindowModal( WindowRef inWindow
)
665 GetWindowClass( inWindow
, &cl
) ;
666 return cl
< kFloatingWindowClass
;
671 void UMAHighlightAndActivateWindow( WindowRef inWindowRef
, bool inActivate
)
675 // bool isHighlighted = IsWindowHighlited( inWindowRef ) ;
676 // if ( inActivate != isHighlighted )
679 SetPortWindowPort( inWindowRef
) ;
680 HiliteWindow( inWindowRef
, inActivate
) ;
681 ControlRef control
= NULL
;
682 ::GetRootControl( inWindowRef
, & control
) ;
686 UMAActivateControl( control
) ;
688 UMADeactivateControl( control
) ;
694 OSStatus
UMADrawThemePlacard( const Rect
*inRect
, ThemeDrawState inState
)
696 return ::DrawThemePlacard( inRect
, inState
) ;
700 static OSStatus helpMenuStatus
= noErr
;
701 static MenuItemIndex firstCustomItemIndex
= 0 ;
704 OSStatus
UMAGetHelpMenu(
705 MenuRef
* outHelpMenu
,
706 MenuItemIndex
* outFirstCustomItemIndex
)
709 return HMGetHelpMenu( outHelpMenu
, outFirstCustomItemIndex
) ;
711 MenuRef helpMenuHandle
;
712 helpMenuStatus
= HMGetHelpMenuHandle( &helpMenuHandle
) ;
713 if ( firstCustomItemIndex
== 0 && helpMenuStatus
== noErr
)
715 firstCustomItemIndex
= CountMenuItems( helpMenuHandle
) + 1 ;
717 if ( outFirstCustomItemIndex
)
719 *outFirstCustomItemIndex
= firstCustomItemIndex
;
721 *outHelpMenu
= helpMenuHandle
;
722 return helpMenuStatus
;
726 wxMacPortStateHelper::wxMacPortStateHelper( GrafPtr newport
)
732 wxMacPortStateHelper::wxMacPortStateHelper()
737 void wxMacPortStateHelper::Setup( GrafPtr newport
)
739 GetPort( &m_oldPort
) ;
742 wxASSERT_MSG( m_clip
== NULL
, wxT("Cannot call setup twice") ) ;
745 m_textFont
= GetPortTextFont( (CGrafPtr
) newport
);
746 m_textSize
= GetPortTextSize( (CGrafPtr
) newport
);
747 m_textStyle
= GetPortTextFace( (CGrafPtr
) newport
);
748 m_textMode
= GetPortTextMode( (CGrafPtr
) newport
);
749 GetThemeDrawingState( &m_drawingState
) ;
750 m_currentPort
= newport
;
752 void wxMacPortStateHelper::Clear()
756 DisposeRgn( m_clip
) ;
757 DisposeThemeDrawingState( m_drawingState
) ;
762 wxMacPortStateHelper::~wxMacPortStateHelper()
766 SetPort( m_currentPort
) ;
768 DisposeRgn( m_clip
) ;
769 TextFont( m_textFont
);
770 TextSize( m_textSize
);
771 TextFace( m_textStyle
);
772 TextMode( m_textMode
);
773 SetThemeDrawingState( m_drawingState
, true ) ;
774 SetPort( m_oldPort
) ;
778 OSStatus
UMAPutScrap( Size size
, OSType type
, void *data
)
780 OSStatus err
= noErr
;
782 err
= PutScrap( size
, type
, data
) ;
785 err
= GetCurrentScrap (&scrap
);
788 err
= PutScrapFlavor (scrap
, type
, 0, size
, data
);
794 Rect
* UMAGetControlBoundsInWindowCoords(ControlRef theControl
, Rect
*bounds
)
796 GetControlBounds( theControl
, bounds
) ;
797 #if TARGET_API_MAC_OSX
798 WindowRef tlwref
= GetControlOwner( theControl
) ;
800 wxTopLevelWindowMac
* tlwwx
= wxFindWinFromMacWindow( tlwref
) ;
801 if ( tlwwx
!= NULL
&& tlwwx
->MacUsesCompositing() )
803 ControlRef rootControl
= tlwwx
->GetPeer()->GetControlRef() ;
804 HIPoint hiPoint
= CGPointMake( 0 , 0 ) ;
805 HIViewConvertPoint( &hiPoint
, HIViewGetSuperview(theControl
) , rootControl
) ;
806 OffsetRect( bounds
, (short) hiPoint
.x
, (short) hiPoint
.y
) ;
817 static bool sUMASystemInitialized
= false ;
819 bool UMASystemIsInitialized()
821 return sUMASystemInitialized
;
824 void UMASetSystemIsInitialized(bool val
)
826 sUMASystemInitialized
= val
;