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 SInt32 sUMASystemVersion 
= 0 ; 
  46 long UMAGetSystemVersion() { return sUMASystemVersion 
; } 
  48 void UMACleanupToolbox() 
  52 void UMAInitToolbox( UInt16 inMoreMastersCalls
, bool isEmbedded 
) 
  56     if ( Gestalt(gestaltSystemVersion
, &sUMASystemVersion
) != noErr
) 
  57         sUMASystemVersion 
= 0x0000 ; 
  66         GetThemeFont(kThemeSmallSystemFont 
, GetApplicationScript() , fontName 
, &fontSize 
, &fontStyle 
) ; 
  67         GetFNum( fontName
, &fontId 
); 
  69         TXNMacOSPreferredFontDescription fontDescriptions
[] = 
  71             { fontId 
, (fontSize 
<< 16) , kTXNDefaultFontStyle
, kTXNSystemDefaultEncoding 
} 
  73         int noOfFontDescriptions 
= sizeof( fontDescriptions 
) / sizeof(TXNMacOSPreferredFontDescription
) ; 
  75         OptionBits options 
= 0 ; 
  77         if ( UMAGetSystemVersion() < 0x1000 ) 
  78             options 
|= kTXNAlwaysUseQuickDrawTextMask 
; 
  80         TXNInitTextension( fontDescriptions
,  noOfFontDescriptions
, options 
); 
  84     UMASetSystemIsInitialized( true ); 
  88 long UMAGetProcessMode() 
  91     ProcessInfoRec processinfo
; 
  92     ProcessSerialNumber procno 
; 
  94     procno
.highLongOfPSN 
= 0 ; 
  95     procno
.lowLongOfPSN 
= kCurrentProcess 
; 
  96     processinfo
.processInfoLength 
= sizeof(ProcessInfoRec
); 
  97     processinfo
.processName 
= NULL
; 
  99     processinfo
.processAppSpec 
= NULL
; 
 102     err 
= ::GetProcessInformation( &procno 
, &processinfo 
) ; 
 103     wxASSERT( err 
== noErr 
) ; 
 105     return processinfo
.processMode 
; 
 108 bool UMAGetProcessModeDoesActivateOnFGSwitch() 
 110     return UMAGetProcessMode() & modeDoesActivateOnFGSwitch 
; 
 115 MenuRef 
UMANewMenu( SInt16 id 
, const wxString
& title 
, wxFontEncoding encoding 
) 
 117     wxString str 
= wxStripMenuCodes( title 
) ; 
 121     CreateNewMenu( id 
, 0 , &menu 
) ; 
 122     SetMenuTitleWithCFString( menu 
, wxMacCFStringHolder(str 
, encoding 
) ) ; 
 125     wxMacStringToPascal( str 
, ptitle 
) ; 
 126     menu 
= ::NewMenu( id 
, ptitle 
) ; 
 132 void UMASetMenuTitle( MenuRef menu 
, const wxString
& title 
, wxFontEncoding encoding 
) 
 134     wxString str 
= wxStripMenuCodes( title 
) ; 
 137     SetMenuTitleWithCFString( menu 
, wxMacCFStringHolder(str 
, encoding
) ) ; 
 141     wxMacStringToPascal( str 
, ptitle 
) ; 
 142     SetMenuTitle( menu 
, ptitle 
) ; 
 146 void UMASetMenuItemText( MenuRef menu
,  MenuItemIndex item
, const wxString
& title
, wxFontEncoding encoding 
) 
 148     // we don't strip the accels here anymore, must be done before 
 149     wxString str 
= title 
; 
 152     SetMenuItemTextWithCFString( menu 
, item 
, wxMacCFStringHolder(str 
, encoding
) ) ; 
 156     wxMacStringToPascal( str 
, ptitle 
) ; 
 157     SetMenuItemText( menu 
, item 
, ptitle 
) ; 
 161 UInt32 
UMAMenuEvent( EventRecord 
*inEvent 
) 
 163     return MenuEvent( inEvent 
) ; 
 166 void UMAEnableMenuItem( MenuRef inMenu 
, MenuItemIndex inItem 
, bool enable
) 
 169         EnableMenuItem( inMenu 
, inItem 
) ; 
 171         DisableMenuItem( inMenu 
, inItem 
) ; 
 174 void UMAAppendSubMenuItem( MenuRef menu 
, const wxString
& title
, wxFontEncoding encoding 
, SInt16 id 
) 
 176     AppendMenuItemTextWithCFString( menu
, 
 177                                 CFSTR("A"), 0, 0,NULL
);  
 178     UMASetMenuItemText( menu
, (SInt16
) ::CountMenuItems(menu
), title 
, encoding 
); 
 179     SetMenuItemHierarchicalID( menu 
, CountMenuItems( menu 
) , id 
) ; 
 182 void UMAInsertSubMenuItem( MenuRef menu 
, const wxString
& title
, wxFontEncoding encoding 
, MenuItemIndex item 
, SInt16 id  
) 
 184     InsertMenuItemTextWithCFString( menu
, 
 185                 CFSTR("A"), item
, 0, 0);  
 187     UMASetMenuItemText( menu
, item
+1, title 
, encoding 
); 
 188     SetMenuItemHierarchicalID( menu 
, item
+1 , id 
) ; 
 191 void UMASetMenuItemShortcut( MenuRef menu 
, MenuItemIndex item 
, wxAcceleratorEntry 
*entry 
) 
 196     UInt8 modifiers 
= 0 ; 
 197     SInt16 key 
= entry
->GetKeyCode() ; 
 200         bool explicitCommandKey 
= (entry
->GetFlags() & wxACCEL_CTRL
); 
 202         if (entry
->GetFlags() & wxACCEL_ALT
) 
 203             modifiers 
|= kMenuOptionModifier 
; 
 205         if (entry
->GetFlags() & wxACCEL_SHIFT
) 
 206             modifiers 
|= kMenuShiftModifier 
; 
 209         SInt16 macKey 
= key 
; 
 210         if ( key 
>= WXK_F1 
&& key 
<= WXK_F15 
) 
 212             if ( !explicitCommandKey 
) 
 213                 modifiers 
|= kMenuNoCommandModifier 
; 
 215             // for some reasons this must be 0 right now 
 216             // everything else leads to just the first function key item 
 217             // to be selected. Thanks to Ryan Wilcox for finding out. 
 219             glyph 
= kMenuF1Glyph 
+ ( key 
- WXK_F1 
) ; 
 220             if ( key 
>= WXK_F13 
) 
 228                     macKey 
= kBackspaceCharCode 
; 
 229                     glyph 
= kMenuDeleteLeftGlyph 
; 
 233                     macKey 
= kTabCharCode 
; 
 234                     glyph 
= kMenuTabRightGlyph 
; 
 237                 case kEnterCharCode 
: 
 238                     macKey 
= kEnterCharCode 
; 
 239                     glyph 
= kMenuEnterGlyph 
; 
 243                     macKey 
= kReturnCharCode 
; 
 244                     glyph 
= kMenuReturnGlyph 
; 
 248                     macKey 
= kEscapeCharCode 
; 
 249                     glyph 
= kMenuEscapeGlyph 
; 
 254                     glyph 
= kMenuSpaceGlyph 
; 
 258                     macKey 
= kDeleteCharCode 
; 
 259                     glyph 
= kMenuDeleteRightGlyph 
; 
 263                     macKey 
= kClearCharCode 
; 
 264                     glyph 
= kMenuClearGlyph 
; 
 268                     macKey 
= kPageUpCharCode 
; 
 269                     glyph 
= kMenuPageUpGlyph 
; 
 273                     macKey 
= kPageDownCharCode 
; 
 274                     glyph 
= kMenuPageDownGlyph 
; 
 278                     macKey 
= kLeftArrowCharCode 
; 
 279                     glyph 
= kMenuLeftArrowGlyph 
; 
 283                     macKey 
= kUpArrowCharCode 
; 
 284                     glyph 
= kMenuUpArrowGlyph 
; 
 288                     macKey 
= kRightArrowCharCode 
; 
 289                     glyph 
= kMenuRightArrowGlyph 
; 
 293                     macKey 
= kDownArrowCharCode 
; 
 294                     glyph 
= kMenuDownArrowGlyph 
; 
 298                     macKey 
= kHomeCharCode 
; 
 299                     glyph 
= kMenuNorthwestArrowGlyph 
; 
 303                     macKey 
= kEndCharCode 
; 
 304                     glyph 
= kMenuSoutheastArrowGlyph 
; 
 307                     macKey 
= toupper( key 
) ; 
 311             // we now allow non command key shortcuts 
 312             // remove in case this gives problems 
 313             if ( !explicitCommandKey 
) 
 314                 modifiers 
|= kMenuNoCommandModifier 
; 
 317         // 1d and 1e have special meaning to SetItemCmd, so 
 318         // do not use for these character codes. 
 319         if (key 
!= WXK_UP 
&& key 
!= WXK_RIGHT 
&& key 
!= WXK_DOWN 
&& key 
!= WXK_LEFT
) 
 320             SetItemCmd( menu
, item 
, macKey 
); 
 322         SetMenuItemModifiers( menu
, item 
, modifiers 
) ; 
 325             SetMenuItemKeyGlyph( menu
, item 
, glyph 
) ; 
 329 void UMAAppendMenuItem( MenuRef menu 
, const wxString
& title
, wxFontEncoding encoding 
, wxAcceleratorEntry 
*entry 
) 
 331     AppendMenuItemTextWithCFString( menu
, 
 332                                 CFSTR("A"), 0, 0,NULL
);  
 333     // don't attempt to interpret metacharacters like a '-' at the beginning (would become a separator otherwise) 
 334     ChangeMenuItemAttributes( menu 
, ::CountMenuItems(menu
), kMenuItemAttrIgnoreMeta 
, 0 ) ; 
 335     UMASetMenuItemText(menu
, (SInt16
) ::CountMenuItems(menu
), title 
, encoding 
); 
 336     UMASetMenuItemShortcut( menu 
, (SInt16
) ::CountMenuItems(menu
), entry 
) ; 
 339 void UMAInsertMenuItem( MenuRef menu 
, const wxString
& title
, wxFontEncoding encoding 
, MenuItemIndex item 
, wxAcceleratorEntry 
*entry 
) 
 341     InsertMenuItemTextWithCFString( menu
, 
 342                 CFSTR("A"), item
, 0, 0);  
 344     // don't attempt to interpret metacharacters like a '-' at the beginning (would become a separator otherwise) 
 345     ChangeMenuItemAttributes( menu 
, item
+1, kMenuItemAttrIgnoreMeta 
, 0 ) ; 
 346     UMASetMenuItemText(menu
, item
+1 , title 
, encoding 
); 
 347     UMASetMenuItemShortcut( menu 
, item
+1 , entry 
) ; 
 354 int gPrOpenCounter 
= 0 ; 
 362     if ( gPrOpenCounter 
== 1 ) 
 366         wxASSERT( err 
== noErr 
) ; 
 372 OSStatus 
UMAPrClose() 
 376     wxASSERT( gPrOpenCounter 
>= 1 ) ; 
 378     if ( gPrOpenCounter 
== 1 ) 
 382         wxASSERT( err 
== noErr 
) ; 
 390 pascal QDGlobalsPtr 
GetQDGlobalsPtr() ; 
 391 pascal QDGlobalsPtr 
GetQDGlobalsPtr() 
 393     return QDGlobalsPtr (* (Ptr
*) LMGetCurrentA5 ( ) - 0xCA); 
 398 void UMAShowWatchCursor() 
 400     SetThemeCursor(kThemeWatchCursor
); 
 403 void UMAShowArrowCursor() 
 405     SetThemeCursor(kThemeArrowCursor
); 
 410 GrafPtr 
UMAGetWindowPort( WindowRef inWindowRef 
) 
 412     wxASSERT( inWindowRef 
!= NULL 
) ; 
 415     return (GrafPtr
) GetWindowPort( inWindowRef 
) ; 
 417     return (GrafPtr
) inWindowRef 
; 
 421 void UMADisposeWindow( WindowRef inWindowRef 
) 
 423     wxASSERT( inWindowRef 
!= NULL 
) ; 
 425     DisposeWindow( inWindowRef 
) ; 
 428 void UMASetWTitle( WindowRef inWindowRef 
, const wxString
& title 
, wxFontEncoding encoding 
) 
 431     SetWindowTitleWithCFString( inWindowRef 
, wxMacCFStringHolder(title 
, encoding
) ) ; 
 435     wxMacStringToPascal( title 
, ptitle 
) ; 
 436     SetWTitle( inWindowRef 
, ptitle 
) ; 
 440 // appearance additions 
 442 void UMASetControlTitle( ControlRef inControl 
, const wxString
& title 
, wxFontEncoding encoding 
) 
 445     SetControlTitleWithCFString( inControl 
, wxMacCFStringHolder(title 
, encoding
) ) ; 
 449     wxMacStringToPascal( title 
, ptitle 
) ; 
 450     SetControlTitle( inControl 
, ptitle 
) ; 
 454 void UMAActivateControl( ControlRef inControl 
) 
 456 #if TARGET_API_MAC_OSX 
 457     ::ActivateControl( inControl 
) ; 
 460     // we have to add the control after again to the update rgn 
 461     // otherwise updates get lost 
 462     if ( !IsControlActive( inControl 
) ) 
 464         bool visible 
= IsControlVisible( inControl 
) ; 
 466             SetControlVisibility( inControl 
, false , false ) ; 
 468         ::ActivateControl( inControl 
) ; 
 472             SetControlVisibility( inControl 
, true , false ) ; 
 475             InvalWindowRect( GetControlOwner(inControl
), UMAGetControlBoundsInWindowCoords(inControl
, &ctrlBounds
) ) ; 
 481 void UMAMoveControl( ControlRef inControl 
, short x 
, short y 
) 
 483 #if TARGET_API_MAC_OSX 
 484     ::MoveControl( inControl 
, x 
, y 
) ; 
 487     bool visible 
= IsControlVisible( inControl 
) ; 
 490         SetControlVisibility( inControl 
, false , false ) ; 
 492         InvalWindowRect( GetControlOwner(inControl
), GetControlBounds(inControl
, &ctrlBounds
) ) ; 
 495     ::MoveControl( inControl 
, x 
, y 
) ; 
 499         SetControlVisibility( inControl 
, true , false ) ; 
 501         InvalWindowRect( GetControlOwner(inControl
), GetControlBounds(inControl
, &ctrlBounds
) ) ; 
 506 void UMASizeControl( ControlRef inControl 
, short x 
, short y 
) 
 508 #if TARGET_API_MAC_OSX 
 509     ::SizeControl( inControl 
, x 
, y 
) ; 
 512     bool visible 
= IsControlVisible( inControl 
) ; 
 515         SetControlVisibility( inControl 
, false , false ) ; 
 517         InvalWindowRect( GetControlOwner(inControl
), GetControlBounds(inControl
, &ctrlBounds
) ) ; 
 520     ::SizeControl( inControl 
, x 
, y 
) ; 
 524         SetControlVisibility( inControl 
, true , false ) ; 
 526         InvalWindowRect( GetControlOwner(inControl
), GetControlBounds(inControl
, &ctrlBounds
) ) ; 
 531 void UMADeactivateControl( ControlRef inControl 
) 
 533 #if TARGET_API_MAC_OSX 
 534     ::DeactivateControl( inControl 
) ; 
 537     // we have to add the control after again to the update rgn 
 538     // otherwise updates get lost 
 539     bool visible 
= IsControlVisible( inControl 
) ; 
 541         SetControlVisibility( inControl 
, false , false ) ; 
 543     ::DeactivateControl( inControl 
) ; 
 547         SetControlVisibility( inControl 
, true , false ) ; 
 549         InvalWindowRect( GetControlOwner(inControl
), UMAGetControlBoundsInWindowCoords(inControl
, &ctrlBounds
) ) ; 
 554 // shows the control and adds the region to the update region 
 555 void UMAShowControl( ControlRef inControl 
) 
 557     SetControlVisibility( inControl 
, true , false ) ; 
 558     HIViewSetNeedsDisplay( inControl
, true ); 
 561 // hides the control and adds the region to the update region 
 562 void UMAHideControl( ControlRef inControl 
) 
 564     SetControlVisibility( inControl 
, false , false ) ; 
 565     HIViewSetNeedsDisplay( inControl
, true ); 
 569 OSErr 
UMASetKeyboardFocus( WindowPtr inWindow
, 
 570                                  ControlRef inControl
, 
 571                                  ControlFocusPart inPart 
) 
 578     SetPortWindowPort( inWindow 
) ; 
 581     err 
= SetKeyboardFocus( inWindow 
, inControl 
, inPart 
) ; 
 589 bool UMAIsWindowFloating( WindowRef inWindow 
) 
 593     GetWindowClass( inWindow 
, &cl 
) ; 
 594     return cl 
== kFloatingWindowClass 
; 
 597 bool UMAIsWindowModal( WindowRef inWindow 
) 
 601     GetWindowClass( inWindow 
, &cl 
) ; 
 602     return cl 
< kFloatingWindowClass 
; 
 607 void UMAHighlightAndActivateWindow( WindowRef inWindowRef 
, bool inActivate 
) 
 611 //        bool isHighlighted = IsWindowHighlited( inWindowRef ) ; 
 612 //        if ( inActivate != isHighlighted ) 
 616         SetPortWindowPort( inWindowRef 
) ; 
 618         HiliteWindow( inWindowRef 
, inActivate 
) ; 
 619         ControlRef control 
= NULL 
; 
 620         ::GetRootControl( inWindowRef 
, &control 
) ; 
 624                 UMAActivateControl( control 
) ; 
 626                 UMADeactivateControl( control 
) ; 
 634 OSStatus 
UMADrawThemePlacard( const Rect 
*inRect 
, ThemeDrawState inState 
) 
 637     return ::DrawThemePlacard( inRect 
, inState 
) ; 
 644 static OSStatus helpMenuStatus 
= noErr 
; 
 645 static MenuItemIndex firstCustomItemIndex 
= 0 ; 
 648 static OSStatus 
UMAGetHelpMenu( 
 649     MenuRef 
*        outHelpMenu
, 
 650     MenuItemIndex 
*  outFirstCustomItemIndex
, 
 651     bool             allowHelpMenuCreation
); 
 653 static OSStatus 
UMAGetHelpMenu( 
 654     MenuRef 
*        outHelpMenu
, 
 655     MenuItemIndex 
*  outFirstCustomItemIndex
, 
 656     bool             allowHelpMenuCreation
) 
 659     static bool s_createdHelpMenu 
= false ; 
 661     if ( !s_createdHelpMenu 
&& !allowHelpMenuCreation 
) 
 666     OSStatus status 
= HMGetHelpMenu( outHelpMenu 
, outFirstCustomItemIndex 
) ; 
 667     s_createdHelpMenu 
= ( status 
== noErr 
) ; 
 670     wxUnusedVar( allowHelpMenuCreation 
) ; 
 671     MenuRef helpMenuHandle 
; 
 673     helpMenuStatus 
= HMGetHelpMenuHandle( &helpMenuHandle 
) ; 
 674     if ( firstCustomItemIndex 
== 0 && helpMenuStatus 
== noErr 
) 
 675         firstCustomItemIndex 
= CountMenuItems( helpMenuHandle 
) + 1 ; 
 677     if ( outFirstCustomItemIndex 
) 
 678         *outFirstCustomItemIndex 
= firstCustomItemIndex 
; 
 680     *outHelpMenu 
= helpMenuHandle 
; 
 682     return helpMenuStatus 
; 
 686 OSStatus 
UMAGetHelpMenu( 
 687     MenuRef 
*        outHelpMenu
, 
 688     MenuItemIndex 
*  outFirstCustomItemIndex
) 
 690     return UMAGetHelpMenu( outHelpMenu 
, outFirstCustomItemIndex 
, true ); 
 693 OSStatus 
UMAGetHelpMenuDontCreate( 
 694     MenuRef 
*        outHelpMenu
, 
 695     MenuItemIndex 
*  outFirstCustomItemIndex
) 
 697     return UMAGetHelpMenu( outHelpMenu 
, outFirstCustomItemIndex 
, false ); 
 702 wxMacPortStateHelper::wxMacPortStateHelper( GrafPtr newport 
) 
 708 wxMacPortStateHelper::wxMacPortStateHelper() 
 713 void wxMacPortStateHelper::Setup( GrafPtr newport 
) 
 715     GetPort( &m_oldPort 
) ; 
 719     wxASSERT_MSG( m_clip 
== NULL 
, wxT("Cannot call setup twice") ) ; 
 722     m_textFont 
= GetPortTextFont( (CGrafPtr
) newport 
); 
 723     m_textSize 
= GetPortTextSize( (CGrafPtr
) newport 
); 
 724     m_textStyle 
= GetPortTextFace( (CGrafPtr
) newport 
); 
 725     m_textMode 
= GetPortTextMode( (CGrafPtr
) newport 
); 
 726     GetThemeDrawingState( &m_drawingState 
) ; 
 727     m_currentPort 
= newport 
; 
 730 void wxMacPortStateHelper::Clear() 
 734         DisposeRgn( m_clip 
) ; 
 735         DisposeThemeDrawingState( m_drawingState 
) ; 
 740 wxMacPortStateHelper::~wxMacPortStateHelper() 
 744         SetPort( m_currentPort 
) ; 
 746         DisposeRgn( m_clip 
) ; 
 747         TextFont( m_textFont 
); 
 748         TextSize( m_textSize 
); 
 749         TextFace( m_textStyle 
); 
 750         TextMode( m_textMode 
); 
 751         SetThemeDrawingState( m_drawingState 
, true ) ; 
 752         SetPort( m_oldPort 
) ; 
 758 OSStatus 
UMAPutScrap( Size size 
, OSType type 
, void *data 
) 
 760     OSStatus err 
= noErr 
; 
 763     err 
= PutScrap( size 
, type 
, data 
) ; 
 766     err 
= GetCurrentScrap( &scrap 
); 
 768         err 
= PutScrapFlavor( scrap
, type 
, 0, size
, data 
); 
 774 Rect 
* UMAGetControlBoundsInWindowCoords( ControlRef theControl
, Rect 
*bounds 
) 
 776     GetControlBounds( theControl 
, bounds 
) ; 
 778 #if TARGET_API_MAC_OSX 
 779     WindowRef tlwref 
= GetControlOwner( theControl 
) ; 
 781     wxTopLevelWindowMac
* tlwwx 
= wxFindWinFromMacWindow( tlwref 
) ; 
 784         ControlRef rootControl 
= tlwwx
->GetPeer()->GetControlRef() ; 
 785         HIPoint hiPoint 
= CGPointMake( 0 , 0 ) ; 
 786         HIViewConvertPoint( &hiPoint 
, HIViewGetSuperview(theControl
) , rootControl 
) ; 
 787         OffsetRect( bounds 
, (short) hiPoint
.x 
, (short) hiPoint
.y 
) ; 
 798 static bool sUMASystemInitialized 
= false ; 
 800 bool UMASystemIsInitialized() 
 802     return sUMASystemInitialized 
; 
 805 void UMASetSystemIsInitialized(bool val
) 
 807     sUMASystemInitialized 
= val
;