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"
37 // since we have decided that we only support 8.6 upwards we are
38 // checking for these minimum requirements in the startup code of
39 // the application so all wxWidgets code can safely assume that appearance 1.1
40 // windows manager, control manager, navigation services etc. are
43 static bool sUMAHasAppearance
= false ;
44 static long sUMAAppearanceVersion
= 0 ;
45 static long sUMASystemVersion
= 0 ;
46 static bool sUMAHasAquaLayout
= false ;
48 static bool sUMAHasInittedAppearance
= false;
50 extern int gAGABackgroundColor
;
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
)
67 UnregisterAppearanceClient() ;
69 if ( NavServicesAvailable() )
73 if ( TXNTerminateTextension
!= (void*) kUnresolvedCFragSymbolAddress
)
74 TXNTerminateTextension( ) ;
76 void UMAInitToolbox( UInt16 inMoreMastersCalls
, bool isEmbedded
)
80 for (long i
= 1; i
<= inMoreMastersCalls
; i
++)
85 ::InitGraf(&qd
.thePort
);
90 ::FlushEvents(everyEvent
, 0);
94 PurgeSpace(&total
, &contig
);
99 if ( Gestalt(gestaltSystemVersion
, &sUMASystemVersion
) != noErr
)
100 sUMASystemVersion
= 0x0000 ;
103 if ( Gestalt( gestaltAppearanceAttr
, &theAppearance
) == noErr
)
105 sUMAHasAppearance
= true ;
106 OSStatus status
= RegisterAppearanceClient();
107 // If status equals appearanceProcessRegisteredErr it means the
108 // appearance client already was registered (For example if we run
109 // embedded, the host might have registered it). In such a case
110 // we don't unregister it later on.
111 if (status
!= appearanceProcessRegisteredErr
)
113 // Appearance client wasn't registered yet.
114 sUMAHasInittedAppearance
= true;
117 if ( Gestalt( gestaltAppearanceVersion
, &theAppearance
) == noErr
)
119 sUMAAppearanceVersion
= theAppearance
;
123 sUMAAppearanceVersion
= 0x0100 ;
126 if ( Gestalt( gestaltWindowMgrAttr
, &sUMAWindowManagerAttr
) == noErr
)
128 sUMAHasWindowManager
= sUMAWindowManagerAttr
& gestaltWindowMgrPresent
;
132 // Call currently implicitely done : InitFloatingWindows() ;
136 if ( sUMAHasWindowManager
)
137 InitFloatingWindows() ;
143 if ( NavServicesAvailable() )
149 Gestalt( gestaltMenuMgrAttr
, &menuMgrAttr
) ;
150 if ( menuMgrAttr
& gestaltMenuMgrAquaLayoutMask
)
151 sUMAHasAquaLayout
= true ;
153 if ( TXNInitTextension
!= (void*) kUnresolvedCFragSymbolAddress
)
155 FontFamilyID fontId
;
159 GetThemeFont(kThemeSmallSystemFont
, GetApplicationScript() , fontName
, &fontSize
, &fontStyle
) ;
160 GetFNum( fontName
, &fontId
);
162 TXNMacOSPreferredFontDescription fontDescriptions
[] =
164 { fontId
, (fontSize
<< 16) ,kTXNDefaultFontStyle
, kTXNSystemDefaultEncoding
}
166 int noOfFontDescriptions
= sizeof( fontDescriptions
) / sizeof(TXNMacOSPreferredFontDescription
) ;
168 OptionBits options
= 0 ;
170 if ( UMAGetSystemVersion() < 0x1000 )
172 options
|= kTXNAlwaysUseQuickDrawTextMask
;
174 TXNInitTextension(fontDescriptions
, noOfFontDescriptions
, options
);
178 UMASetSystemIsInitialized(true);
183 Boolean CanUseATSUI()
186 OSErr err = Gestalt(gestaltATSUVersion, &result);
187 return (err == noErr);
191 long UMAGetProcessMode()
194 ProcessInfoRec processinfo
;
195 ProcessSerialNumber procno
;
197 procno
.highLongOfPSN
= 0 ;
198 procno
.lowLongOfPSN
= kCurrentProcess
;
199 processinfo
.processInfoLength
= sizeof(ProcessInfoRec
);
200 processinfo
.processName
= NULL
;
201 processinfo
.processAppSpec
= NULL
;
203 err
= ::GetProcessInformation( &procno
, &processinfo
) ;
204 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
) ;
220 CreateNewMenu( id
, 0 , &menu
) ;
221 SetMenuTitleWithCFString( menu
, wxMacCFStringHolder(str
, encoding
) ) ;
224 wxMacStringToPascal( str
, ptitle
) ;
225 menu
= ::NewMenu( id
, ptitle
) ;
230 void UMASetMenuTitle( MenuRef menu
, const wxString
& title
, wxFontEncoding encoding
)
232 wxString str
= wxStripMenuCodes( title
) ;
234 SetMenuTitleWithCFString( menu
, wxMacCFStringHolder(str
, encoding
) ) ;
237 wxMacStringToPascal( str
, ptitle
) ;
238 SetMenuTitle( menu
, ptitle
) ;
242 void UMASetMenuItemText( MenuRef menu
, MenuItemIndex item
, const wxString
& title
, wxFontEncoding encoding
)
244 wxString str
= wxStripMenuCodes( title
) ;
246 SetMenuItemTextWithCFString( menu
, item
, wxMacCFStringHolder(str
, encoding
) ) ;
249 wxMacStringToPascal( str
, ptitle
) ;
250 SetMenuItemText( menu
, item
, ptitle
) ;
255 UInt32
UMAMenuEvent( EventRecord
*inEvent
)
257 return MenuEvent( inEvent
) ;
260 void UMAEnableMenuItem( MenuRef inMenu
, MenuItemIndex inItem
, bool enable
)
263 EnableMenuItem( inMenu
, inItem
) ;
265 DisableMenuItem( inMenu
, inItem
) ;
268 void UMAAppendSubMenuItem( MenuRef menu
, const wxString
& title
, wxFontEncoding encoding
, SInt16 id
)
270 MacAppendMenu(menu
, "\pA");
271 UMASetMenuItemText(menu
, (SInt16
) ::CountMenuItems(menu
), title
, encoding
);
272 SetMenuItemHierarchicalID( menu
, CountMenuItems( menu
) , id
) ;
275 void UMAInsertSubMenuItem( MenuRef menu
, const wxString
& title
, wxFontEncoding encoding
, MenuItemIndex item
, SInt16 id
)
277 MacInsertMenuItem(menu
, "\pA" , item
);
278 UMASetMenuItemText(menu
, item
+1, title
, encoding
);
279 SetMenuItemHierarchicalID( menu
, item
+1 , id
) ;
282 void UMASetMenuItemShortcut( MenuRef menu
, MenuItemIndex item
, wxAcceleratorEntry
*entry
)
287 UInt8 modifiers
= 0 ;
288 SInt16 key
= entry
->GetKeyCode() ;
291 bool explicitCommandKey
= false ;
293 if ( entry
->GetFlags() & wxACCEL_CTRL
)
295 explicitCommandKey
= true ;
298 if (entry
->GetFlags() & wxACCEL_ALT
)
300 modifiers
|= kMenuOptionModifier
;
303 if (entry
->GetFlags() & wxACCEL_SHIFT
)
305 modifiers
|= kMenuShiftModifier
;
309 SInt16 macKey
= key
;
310 if ( key
>= WXK_F1
&& key
<= WXK_F15
)
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
)
319 if ( !explicitCommandKey
)
320 modifiers
|= kMenuNoCommandModifier
;
327 macKey
= kBackspaceCharCode
;
328 glyph
= kMenuDeleteLeftGlyph
;
331 macKey
= kTabCharCode
;
332 glyph
= kMenuTabRightGlyph
;
334 case kEnterCharCode
:
335 macKey
= kEnterCharCode
;
336 glyph
= kMenuEnterGlyph
;
339 macKey
= kReturnCharCode
;
340 glyph
= kMenuReturnGlyph
;
343 macKey
= kEscapeCharCode
;
344 glyph
= kMenuEscapeGlyph
;
348 glyph
= kMenuSpaceGlyph
;
351 macKey
= kDeleteCharCode
;
352 glyph
= kMenuDeleteRightGlyph
;
355 macKey
= kClearCharCode
;
356 glyph
= kMenuClearGlyph
;
358 case WXK_PRIOR
: // PAGE UP
359 macKey
= kPageUpCharCode
;
360 glyph
= kMenuPageUpGlyph
;
363 macKey
= kPageDownCharCode
;
364 glyph
= kMenuPageDownGlyph
;
367 macKey
= kLeftArrowCharCode
;
368 glyph
= kMenuLeftArrowGlyph
;
371 macKey
= kUpArrowCharCode
;
372 glyph
= kMenuUpArrowGlyph
;
375 macKey
= kRightArrowCharCode
;
376 glyph
= kMenuRightArrowGlyph
;
379 macKey
= kDownArrowCharCode
;
380 glyph
= kMenuDownArrowGlyph
;
383 macKey
= toupper( key
) ;
386 // we now allow non command key shortcuts
387 // remove in case this gives problems
388 if ( !explicitCommandKey
)
389 modifiers
|= kMenuNoCommandModifier
;
392 // 1d and 1e have special meaning to SetItemCmd, so
393 // do not use for these character codes.
394 if (key
!= WXK_UP
&& key
!= WXK_RIGHT
)
395 SetItemCmd( menu
, item
, macKey
);
397 SetMenuItemModifiers(menu
, item
, modifiers
) ;
400 SetMenuItemKeyGlyph(menu
, item
, glyph
) ;
404 void UMAAppendMenuItem( MenuRef menu
, const wxString
& title
, wxFontEncoding encoding
, wxAcceleratorEntry
*entry
)
406 MacAppendMenu(menu
, "\pA");
407 // don't attempt to interpret metacharacters like a '-' at the beginning (would become a separator otherwise)
408 ChangeMenuItemAttributes( menu
, ::CountMenuItems(menu
), kMenuItemAttrIgnoreMeta
, 0 ) ;
409 UMASetMenuItemText(menu
, (SInt16
) ::CountMenuItems(menu
), title
, encoding
);
410 UMASetMenuItemShortcut( menu
, (SInt16
) ::CountMenuItems(menu
), entry
) ;
413 void UMAInsertMenuItem( MenuRef menu
, const wxString
& title
, wxFontEncoding encoding
, MenuItemIndex item
, wxAcceleratorEntry
*entry
)
415 MacInsertMenuItem( menu
, "\pA" , item
) ;
416 // don't attempt to interpret metacharacters like a '-' at the beginning (would become a separator otherwise)
417 ChangeMenuItemAttributes( menu
, item
+1, kMenuItemAttrIgnoreMeta
, 0 ) ;
418 UMASetMenuItemText(menu
, item
+1 , title
, encoding
);
419 UMASetMenuItemShortcut( menu
, item
+1 , entry
) ;
426 int gPrOpenCounter
= 0 ;
432 if ( gPrOpenCounter
== 1 )
436 wxASSERT( err
== noErr
) ;
441 OSStatus
UMAPrClose()
444 wxASSERT( gPrOpenCounter
>= 1 ) ;
445 if ( gPrOpenCounter
== 1 )
449 wxASSERT( err
== noErr
) ;
455 pascal QDGlobalsPtr
GetQDGlobalsPtr (void) ;
456 pascal QDGlobalsPtr
GetQDGlobalsPtr (void)
458 return QDGlobalsPtr (* (Ptr
*) LMGetCurrentA5 ( ) - 0xCA);
463 void UMAShowWatchCursor()
467 CursHandle watchFob
= GetCursor (watchCursor
);
474 // Cursor preservedArrow;
475 // GetQDGlobalsArrow (&preservedArrow);
476 // SetQDGlobalsArrow (*watchFob);
478 // SetQDGlobalsArrow (&preservedArrow);
479 SetCursor (*watchFob
);
481 SetCursor (*watchFob
);
486 void UMAShowArrowCursor()
490 SetCursor (GetQDGlobalsArrow (&arrow
));
492 SetCursor (&(qd
.arrow
));
498 GrafPtr
UMAGetWindowPort( WindowRef inWindowRef
)
500 wxASSERT( inWindowRef
!= NULL
) ;
502 return (GrafPtr
) GetWindowPort( inWindowRef
) ;
504 return (GrafPtr
) inWindowRef
;
508 void UMADisposeWindow( WindowRef inWindowRef
)
510 wxASSERT( inWindowRef
!= NULL
) ;
511 DisposeWindow( inWindowRef
) ;
514 void UMASetWTitle( WindowRef inWindowRef
, const wxString
& title
, wxFontEncoding encoding
)
517 SetWindowTitleWithCFString( inWindowRef
, wxMacCFStringHolder(title
, encoding
) ) ;
520 wxMacStringToPascal( title
, ptitle
) ;
521 SetWTitle( inWindowRef
, ptitle
) ;
525 // appearance additions
527 void UMASetControlTitle( ControlRef inControl
, const wxString
& title
, wxFontEncoding encoding
)
530 SetControlTitleWithCFString( inControl
, wxMacCFStringHolder(title
, encoding
) ) ;
533 wxMacStringToPascal( title
, ptitle
) ;
534 SetControlTitle( inControl
, ptitle
) ;
538 void UMAActivateControl( ControlRef inControl
)
540 #if !TARGET_API_MAC_OSX
541 // we have to add the control after again to the update rgn
542 // otherwise updates get lost
543 if ( !IsControlActive( inControl
) )
545 bool visible
= IsControlVisible( inControl
) ;
547 SetControlVisibility( inControl
, false , false ) ;
549 ::ActivateControl( inControl
) ;
550 #if !TARGET_API_MAC_OSX
552 SetControlVisibility( inControl
, true , false ) ;
555 InvalWindowRect(GetControlOwner(inControl
),UMAGetControlBoundsInWindowCoords(inControl
,&ctrlBounds
) ) ;
561 void UMAMoveControl( ControlRef inControl
, short x
, short y
)
563 #if !TARGET_API_MAC_OSX
564 bool visible
= IsControlVisible( inControl
) ;
566 SetControlVisibility( inControl
, false , false ) ;
568 InvalWindowRect(GetControlOwner(inControl
),GetControlBounds(inControl
,&ctrlBounds
) ) ;
571 ::MoveControl( inControl
, x
, y
) ;
572 #if !TARGET_API_MAC_OSX
574 SetControlVisibility( inControl
, true , false ) ;
576 InvalWindowRect(GetControlOwner(inControl
),GetControlBounds(inControl
,&ctrlBounds
) ) ;
581 void UMASizeControl( ControlRef inControl
, short x
, short y
)
583 #if !TARGET_API_MAC_OSX
584 bool visible
= IsControlVisible( inControl
) ;
586 SetControlVisibility( inControl
, false , false ) ;
588 InvalWindowRect(GetControlOwner(inControl
),GetControlBounds(inControl
,&ctrlBounds
) ) ;
591 ::SizeControl( inControl
, x
, y
) ;
592 #if !TARGET_API_MAC_OSX
594 SetControlVisibility( inControl
, true , false ) ;
596 InvalWindowRect(GetControlOwner(inControl
),GetControlBounds(inControl
,&ctrlBounds
) ) ;
601 void UMADeactivateControl( ControlRef inControl
)
603 #if !TARGET_API_MAC_OSX
604 // we have to add the control after again to the update rgn
605 // otherwise updates get lost
606 bool visible
= IsControlVisible( inControl
) ;
608 SetControlVisibility( inControl
, false , false ) ;
610 ::DeactivateControl( inControl
) ;
611 #if !TARGET_API_MAC_OSX
613 SetControlVisibility( inControl
, true , false ) ;
615 InvalWindowRect(GetControlOwner(inControl
),UMAGetControlBoundsInWindowCoords(inControl
,&ctrlBounds
) ) ;
619 // shows the control and adds the region to the update region
620 void UMAShowControl (ControlRef inControl
)
622 SetControlVisibility( inControl
, true , false ) ;
624 InvalWindowRect(GetControlOwner(inControl
),UMAGetControlBoundsInWindowCoords(inControl
,&ctrlBounds
) ) ;
627 // hides the control and adds the region to the update region
628 void UMAHideControl (ControlRef inControl
)
630 SetControlVisibility( inControl
, false , false ) ;
632 InvalWindowRect(GetControlOwner(inControl
),UMAGetControlBoundsInWindowCoords(inControl
,&ctrlBounds
) ) ;
635 OSErr
UMASetKeyboardFocus (WindowPtr inWindow
,
636 ControlRef inControl
,
637 ControlFocusPart inPart
)
643 SetPortWindowPort( inWindow
) ;
645 err
= SetKeyboardFocus( inWindow
, inControl
, inPart
) ;
650 bool UMAIsWindowFloating( WindowRef inWindow
)
654 GetWindowClass( inWindow
, &cl
) ;
655 return cl
== kFloatingWindowClass
;
658 bool UMAIsWindowModal( WindowRef inWindow
)
662 GetWindowClass( inWindow
, &cl
) ;
663 return cl
< kFloatingWindowClass
;
668 void UMAHighlightAndActivateWindow( WindowRef inWindowRef
, bool inActivate
)
672 // bool isHighlighted = IsWindowHighlited( inWindowRef ) ;
673 // if ( inActivate != isHightlited )
676 SetPortWindowPort( inWindowRef
) ;
677 HiliteWindow( inWindowRef
, inActivate
) ;
678 ControlRef control
= NULL
;
679 ::GetRootControl( inWindowRef
, & control
) ;
683 UMAActivateControl( control
) ;
685 UMADeactivateControl( control
) ;
691 OSStatus
UMADrawThemePlacard( const Rect
*inRect
, ThemeDrawState inState
)
693 return ::DrawThemePlacard( inRect
, inState
) ;
697 static OSStatus helpMenuStatus
= noErr
;
698 static MenuItemIndex firstCustomItemIndex
= 0 ;
701 OSStatus
UMAGetHelpMenu(
702 MenuRef
* outHelpMenu
,
703 MenuItemIndex
* outFirstCustomItemIndex
)
706 return HMGetHelpMenu( outHelpMenu
, outFirstCustomItemIndex
) ;
708 MenuRef helpMenuHandle
;
709 helpMenuStatus
= HMGetHelpMenuHandle( &helpMenuHandle
) ;
710 if ( firstCustomItemIndex
== 0 && helpMenuStatus
== noErr
)
712 firstCustomItemIndex
= CountMenuItems( helpMenuHandle
) + 1 ;
714 if ( outFirstCustomItemIndex
)
716 *outFirstCustomItemIndex
= firstCustomItemIndex
;
718 *outHelpMenu
= helpMenuHandle
;
719 return helpMenuStatus
;
723 wxMacPortStateHelper::wxMacPortStateHelper( GrafPtr newport
)
729 wxMacPortStateHelper::wxMacPortStateHelper()
734 void wxMacPortStateHelper::Setup( GrafPtr newport
)
736 GetPort( &m_oldPort
) ;
739 wxASSERT_MSG( m_clip
== NULL
, wxT("Cannot call setup twice") ) ;
742 m_textFont
= GetPortTextFont( (CGrafPtr
) newport
);
743 m_textSize
= GetPortTextSize( (CGrafPtr
) newport
);
744 m_textStyle
= GetPortTextFace( (CGrafPtr
) newport
);
745 m_textMode
= GetPortTextMode( (CGrafPtr
) newport
);
746 GetThemeDrawingState( &m_drawingState
) ;
747 m_currentPort
= newport
;
749 void wxMacPortStateHelper::Clear()
753 DisposeRgn( m_clip
) ;
754 DisposeThemeDrawingState( m_drawingState
) ;
759 wxMacPortStateHelper::~wxMacPortStateHelper()
763 SetPort( m_currentPort
) ;
765 DisposeRgn( m_clip
) ;
766 TextFont( m_textFont
);
767 TextSize( m_textSize
);
768 TextFace( m_textStyle
);
769 TextMode( m_textMode
);
770 SetThemeDrawingState( m_drawingState
, true ) ;
771 SetPort( m_oldPort
) ;
775 OSStatus
UMAPutScrap( Size size
, OSType type
, void *data
)
777 OSStatus err
= noErr
;
779 err
= PutScrap( size
, type
, data
) ;
782 err
= GetCurrentScrap (&scrap
);
785 err
= PutScrapFlavor (scrap
, type
, 0, size
, data
);
791 Rect
* UMAGetControlBoundsInWindowCoords(ControlRef theControl
, Rect
*bounds
)
793 GetControlBounds( theControl
, bounds
) ;
794 #if TARGET_API_MAC_OSX
795 WindowRef tlwref
= GetControlOwner( theControl
) ;
797 wxTopLevelWindowMac
* tlwwx
= wxFindWinFromMacWindow( tlwref
) ;
798 if ( tlwwx
->MacUsesCompositing() )
800 ControlRef rootControl
= tlwwx
->GetPeer()->GetControlRef() ;
801 HIPoint hiPoint
= CGPointMake( 0 , 0 ) ;
802 HIViewConvertPoint( &hiPoint
, HIViewGetSuperview(theControl
) , rootControl
) ;
803 OffsetRect( bounds
, (short) hiPoint
.x
, (short) hiPoint
.y
) ;
814 static bool sUMASystemInitialized
= false ;
816 bool UMASystemIsInitialized()
818 return sUMASystemInitialized
;
821 void UMASetSystemIsInitialized(bool val
)
823 sUMASystemInitialized
= val
;