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"
14 #include "wx/mac/uma.h"
18 #include "wx/toplevel.h"
22 # include <MacTextEditor.h>
23 # include <Navigation.h>
24 # if defined(TARGET_CARBON)
25 # if PM_USE_SESSION_APIS
28 # include <PMApplication.h>
30 # include <Printing.h>
34 #include "wx/mac/uma.h"
36 // since we have decided that we only support 8.6 upwards we are
37 // checking for these minimum requirements in the startup code of
38 // the application so all wxWidgets code can safely assume that appearance 1.1
39 // windows manager, control manager, navigation services etc. are
42 static SInt32 sUMASystemVersion
= 0 ;
44 long UMAGetSystemVersion() { return sUMASystemVersion
; }
46 void UMACleanupToolbox()
50 void UMAInitToolbox( UInt16
WXUNUSED(inMoreMastersCalls
),
51 bool WXUNUSED(isEmbedded
) )
55 if ( Gestalt(gestaltSystemVersion
, &sUMASystemVersion
) != noErr
)
56 sUMASystemVersion
= 0x0000 ;
65 GetThemeFont(kThemeSmallSystemFont
, GetApplicationScript() , fontName
, &fontSize
, &fontStyle
) ;
66 GetFNum( fontName
, &fontId
);
68 TXNMacOSPreferredFontDescription fontDescriptions
[] =
70 { fontId
, (fontSize
<< 16) , kTXNDefaultFontStyle
, kTXNSystemDefaultEncoding
}
72 int noOfFontDescriptions
= sizeof( fontDescriptions
) / sizeof(TXNMacOSPreferredFontDescription
) ;
74 OptionBits options
= 0 ;
76 if ( UMAGetSystemVersion() < 0x1000 )
77 options
|= kTXNAlwaysUseQuickDrawTextMask
;
79 TXNInitTextension( fontDescriptions
, noOfFontDescriptions
, options
);
83 UMASetSystemIsInitialized( true );
87 long UMAGetProcessMode()
90 ProcessInfoRec processinfo
;
91 ProcessSerialNumber procno
;
93 procno
.highLongOfPSN
= 0 ;
94 procno
.lowLongOfPSN
= kCurrentProcess
;
95 processinfo
.processInfoLength
= sizeof(ProcessInfoRec
);
96 processinfo
.processName
= NULL
;
98 processinfo
.processAppSpec
= NULL
;
101 err
= ::GetProcessInformation( &procno
, &processinfo
) ;
102 wxASSERT( err
== noErr
) ;
104 return processinfo
.processMode
;
107 bool UMAGetProcessModeDoesActivateOnFGSwitch()
109 return UMAGetProcessMode() & modeDoesActivateOnFGSwitch
;
114 MenuRef
UMANewMenu( SInt16 id
, const wxString
& title
, wxFontEncoding encoding
)
116 wxString str
= wxStripMenuCodes( title
) ;
120 CreateNewMenu( id
, 0 , &menu
) ;
121 SetMenuTitleWithCFString( menu
, wxMacCFStringHolder(str
, encoding
) ) ;
124 wxMacStringToPascal( str
, ptitle
) ;
125 menu
= ::NewMenu( id
, ptitle
) ;
131 void UMASetMenuTitle( MenuRef menu
, const wxString
& title
, wxFontEncoding encoding
)
133 wxString str
= wxStripMenuCodes( title
) ;
136 SetMenuTitleWithCFString( menu
, wxMacCFStringHolder(str
, encoding
) ) ;
140 wxMacStringToPascal( str
, ptitle
) ;
141 SetMenuTitle( menu
, ptitle
) ;
145 void UMASetMenuItemText( MenuRef menu
, MenuItemIndex item
, const wxString
& title
, wxFontEncoding encoding
)
147 // we don't strip the accels here anymore, must be done before
148 wxString str
= title
;
151 SetMenuItemTextWithCFString( menu
, item
, wxMacCFStringHolder(str
, encoding
) ) ;
155 wxMacStringToPascal( str
, ptitle
) ;
156 SetMenuItemText( menu
, item
, ptitle
) ;
160 UInt32
UMAMenuEvent( EventRecord
*inEvent
)
162 return MenuEvent( inEvent
) ;
165 void UMAEnableMenuItem( MenuRef inMenu
, MenuItemIndex inItem
, bool enable
)
168 EnableMenuItem( inMenu
, inItem
) ;
170 DisableMenuItem( inMenu
, inItem
) ;
173 void UMAAppendSubMenuItem( MenuRef menu
, const wxString
& title
, wxFontEncoding encoding
, SInt16 id
)
175 AppendMenuItemTextWithCFString( menu
,
176 CFSTR("A"), 0, 0,NULL
);
177 UMASetMenuItemText( menu
, (SInt16
) ::CountMenuItems(menu
), title
, encoding
);
178 SetMenuItemHierarchicalID( menu
, CountMenuItems( menu
) , id
) ;
181 void UMAInsertSubMenuItem( MenuRef menu
, const wxString
& title
, wxFontEncoding encoding
, MenuItemIndex item
, SInt16 id
)
183 InsertMenuItemTextWithCFString( menu
,
184 CFSTR("A"), item
, 0, 0);
186 UMASetMenuItemText( menu
, item
+1, title
, encoding
);
187 SetMenuItemHierarchicalID( menu
, item
+1 , id
) ;
190 void UMASetMenuItemShortcut( MenuRef menu
, MenuItemIndex item
, wxAcceleratorEntry
*entry
)
195 UInt8 modifiers
= 0 ;
196 SInt16 key
= entry
->GetKeyCode() ;
199 bool explicitCommandKey
= (entry
->GetFlags() & wxACCEL_CTRL
);
201 if (entry
->GetFlags() & wxACCEL_ALT
)
202 modifiers
|= kMenuOptionModifier
;
204 if (entry
->GetFlags() & wxACCEL_SHIFT
)
205 modifiers
|= kMenuShiftModifier
;
208 SInt16 macKey
= key
;
209 if ( key
>= WXK_F1
&& key
<= WXK_F15
)
211 if ( !explicitCommandKey
)
212 modifiers
|= kMenuNoCommandModifier
;
214 // for some reasons this must be 0 right now
215 // everything else leads to just the first function key item
216 // to be selected. Thanks to Ryan Wilcox for finding out.
218 glyph
= kMenuF1Glyph
+ ( key
- WXK_F1
) ;
219 if ( key
>= WXK_F13
)
227 macKey
= kBackspaceCharCode
;
228 glyph
= kMenuDeleteLeftGlyph
;
232 macKey
= kTabCharCode
;
233 glyph
= kMenuTabRightGlyph
;
236 case kEnterCharCode
:
237 macKey
= kEnterCharCode
;
238 glyph
= kMenuEnterGlyph
;
242 macKey
= kReturnCharCode
;
243 glyph
= kMenuReturnGlyph
;
247 macKey
= kEscapeCharCode
;
248 glyph
= kMenuEscapeGlyph
;
253 glyph
= kMenuSpaceGlyph
;
257 macKey
= kDeleteCharCode
;
258 glyph
= kMenuDeleteRightGlyph
;
262 macKey
= kClearCharCode
;
263 glyph
= kMenuClearGlyph
;
267 macKey
= kPageUpCharCode
;
268 glyph
= kMenuPageUpGlyph
;
272 macKey
= kPageDownCharCode
;
273 glyph
= kMenuPageDownGlyph
;
277 macKey
= kLeftArrowCharCode
;
278 glyph
= kMenuLeftArrowGlyph
;
282 macKey
= kUpArrowCharCode
;
283 glyph
= kMenuUpArrowGlyph
;
287 macKey
= kRightArrowCharCode
;
288 glyph
= kMenuRightArrowGlyph
;
292 macKey
= kDownArrowCharCode
;
293 glyph
= kMenuDownArrowGlyph
;
297 macKey
= kHomeCharCode
;
298 glyph
= kMenuNorthwestArrowGlyph
;
302 macKey
= kEndCharCode
;
303 glyph
= kMenuSoutheastArrowGlyph
;
306 macKey
= toupper( key
) ;
310 // we now allow non command key shortcuts
311 // remove in case this gives problems
312 if ( !explicitCommandKey
)
313 modifiers
|= kMenuNoCommandModifier
;
316 // 1d and 1e have special meaning to SetItemCmd, so
317 // do not use for these character codes.
318 if (key
!= WXK_UP
&& key
!= WXK_RIGHT
&& key
!= WXK_DOWN
&& key
!= WXK_LEFT
)
319 SetItemCmd( menu
, item
, macKey
);
321 SetMenuItemModifiers( menu
, item
, modifiers
) ;
324 SetMenuItemKeyGlyph( menu
, item
, glyph
) ;
328 void UMAAppendMenuItem( MenuRef menu
, const wxString
& title
, wxFontEncoding encoding
, wxAcceleratorEntry
*entry
)
330 AppendMenuItemTextWithCFString( menu
,
331 CFSTR("A"), 0, 0,NULL
);
332 // don't attempt to interpret metacharacters like a '-' at the beginning (would become a separator otherwise)
333 ChangeMenuItemAttributes( menu
, ::CountMenuItems(menu
), kMenuItemAttrIgnoreMeta
, 0 ) ;
334 UMASetMenuItemText(menu
, (SInt16
) ::CountMenuItems(menu
), title
, encoding
);
335 UMASetMenuItemShortcut( menu
, (SInt16
) ::CountMenuItems(menu
), entry
) ;
338 void UMAInsertMenuItem( MenuRef menu
, const wxString
& title
, wxFontEncoding encoding
, MenuItemIndex item
, wxAcceleratorEntry
*entry
)
340 InsertMenuItemTextWithCFString( menu
,
341 CFSTR("A"), item
, 0, 0);
343 // don't attempt to interpret metacharacters like a '-' at the beginning (would become a separator otherwise)
344 ChangeMenuItemAttributes( menu
, item
+1, kMenuItemAttrIgnoreMeta
, 0 ) ;
345 UMASetMenuItemText(menu
, item
+1 , title
, encoding
);
346 UMASetMenuItemShortcut( menu
, item
+1 , entry
) ;
353 int gPrOpenCounter
= 0 ;
361 if ( gPrOpenCounter
== 1 )
365 wxASSERT( err
== noErr
) ;
371 OSStatus
UMAPrClose()
375 wxASSERT( gPrOpenCounter
>= 1 ) ;
377 if ( gPrOpenCounter
== 1 )
381 wxASSERT( err
== noErr
) ;
389 pascal QDGlobalsPtr
GetQDGlobalsPtr() ;
390 pascal QDGlobalsPtr
GetQDGlobalsPtr()
392 return QDGlobalsPtr (* (Ptr
*) LMGetCurrentA5 ( ) - 0xCA);
397 void UMAShowWatchCursor()
399 SetThemeCursor(kThemeWatchCursor
);
402 void UMAShowArrowCursor()
404 SetThemeCursor(kThemeArrowCursor
);
409 GrafPtr
UMAGetWindowPort( WindowRef inWindowRef
)
411 wxASSERT( inWindowRef
!= NULL
) ;
414 return (GrafPtr
) GetWindowPort( inWindowRef
) ;
416 return (GrafPtr
) inWindowRef
;
420 void UMADisposeWindow( WindowRef inWindowRef
)
422 wxASSERT( inWindowRef
!= NULL
) ;
424 DisposeWindow( inWindowRef
) ;
427 void UMASetWTitle( WindowRef inWindowRef
, const wxString
& title
, wxFontEncoding encoding
)
430 SetWindowTitleWithCFString( inWindowRef
, wxMacCFStringHolder(title
, encoding
) ) ;
434 wxMacStringToPascal( title
, ptitle
) ;
435 SetWTitle( inWindowRef
, ptitle
) ;
439 // appearance additions
441 void UMASetControlTitle( ControlRef inControl
, const wxString
& title
, wxFontEncoding encoding
)
444 SetControlTitleWithCFString( inControl
, wxMacCFStringHolder(title
, encoding
) ) ;
448 wxMacStringToPascal( title
, ptitle
) ;
449 SetControlTitle( inControl
, ptitle
) ;
453 void UMAActivateControl( ControlRef inControl
)
455 #if TARGET_API_MAC_OSX
456 ::ActivateControl( inControl
) ;
459 // we have to add the control after again to the update rgn
460 // otherwise updates get lost
461 if ( !IsControlActive( inControl
) )
463 bool visible
= IsControlVisible( inControl
) ;
465 SetControlVisibility( inControl
, false , false ) ;
467 ::ActivateControl( inControl
) ;
471 SetControlVisibility( inControl
, true , false ) ;
474 InvalWindowRect( GetControlOwner(inControl
), UMAGetControlBoundsInWindowCoords(inControl
, &ctrlBounds
) ) ;
480 void UMAMoveControl( ControlRef inControl
, short x
, short y
)
482 #if TARGET_API_MAC_OSX
483 ::MoveControl( inControl
, x
, y
) ;
486 bool visible
= IsControlVisible( inControl
) ;
489 SetControlVisibility( inControl
, false , false ) ;
491 InvalWindowRect( GetControlOwner(inControl
), GetControlBounds(inControl
, &ctrlBounds
) ) ;
494 ::MoveControl( inControl
, x
, y
) ;
498 SetControlVisibility( inControl
, true , false ) ;
500 InvalWindowRect( GetControlOwner(inControl
), GetControlBounds(inControl
, &ctrlBounds
) ) ;
505 void UMASizeControl( ControlRef inControl
, short x
, short y
)
507 #if TARGET_API_MAC_OSX
508 ::SizeControl( inControl
, x
, y
) ;
511 bool visible
= IsControlVisible( inControl
) ;
514 SetControlVisibility( inControl
, false , false ) ;
516 InvalWindowRect( GetControlOwner(inControl
), GetControlBounds(inControl
, &ctrlBounds
) ) ;
519 ::SizeControl( inControl
, x
, y
) ;
523 SetControlVisibility( inControl
, true , false ) ;
525 InvalWindowRect( GetControlOwner(inControl
), GetControlBounds(inControl
, &ctrlBounds
) ) ;
530 void UMADeactivateControl( ControlRef inControl
)
532 #if TARGET_API_MAC_OSX
533 ::DeactivateControl( inControl
) ;
536 // we have to add the control after again to the update rgn
537 // otherwise updates get lost
538 bool visible
= IsControlVisible( inControl
) ;
540 SetControlVisibility( inControl
, false , false ) ;
542 ::DeactivateControl( inControl
) ;
546 SetControlVisibility( inControl
, true , false ) ;
548 InvalWindowRect( GetControlOwner(inControl
), UMAGetControlBoundsInWindowCoords(inControl
, &ctrlBounds
) ) ;
553 // shows the control and adds the region to the update region
554 void UMAShowControl( ControlRef inControl
)
556 SetControlVisibility( inControl
, true , false ) ;
557 HIViewSetNeedsDisplay( inControl
, true );
560 // hides the control and adds the region to the update region
561 void UMAHideControl( ControlRef inControl
)
563 SetControlVisibility( inControl
, false , false ) ;
564 HIViewSetNeedsDisplay( inControl
, true );
568 OSErr
UMASetKeyboardFocus( WindowPtr inWindow
,
569 ControlRef inControl
,
570 ControlFocusPart inPart
)
577 SetPortWindowPort( inWindow
) ;
580 err
= SetKeyboardFocus( inWindow
, inControl
, inPart
) ;
588 bool UMAIsWindowFloating( WindowRef inWindow
)
592 GetWindowClass( inWindow
, &cl
) ;
593 return cl
== kFloatingWindowClass
;
596 bool UMAIsWindowModal( WindowRef inWindow
)
600 GetWindowClass( inWindow
, &cl
) ;
601 return cl
< kFloatingWindowClass
;
606 void UMAHighlightAndActivateWindow( WindowRef inWindowRef
, bool inActivate
)
610 // bool isHighlighted = IsWindowHighlited( inWindowRef ) ;
611 // if ( inActivate != isHighlighted )
615 SetPortWindowPort( inWindowRef
) ;
617 HiliteWindow( inWindowRef
, inActivate
) ;
618 ControlRef control
= NULL
;
619 ::GetRootControl( inWindowRef
, &control
) ;
623 UMAActivateControl( control
) ;
625 UMADeactivateControl( control
) ;
633 OSStatus
UMADrawThemePlacard( const Rect
*inRect
, ThemeDrawState inState
)
636 return ::DrawThemePlacard( inRect
, inState
) ;
643 static OSStatus helpMenuStatus
= noErr
;
644 static MenuItemIndex firstCustomItemIndex
= 0 ;
647 static OSStatus
UMAGetHelpMenu(
648 MenuRef
* outHelpMenu
,
649 MenuItemIndex
* outFirstCustomItemIndex
,
650 bool allowHelpMenuCreation
);
652 static OSStatus
UMAGetHelpMenu(
653 MenuRef
* outHelpMenu
,
654 MenuItemIndex
* outFirstCustomItemIndex
,
655 bool allowHelpMenuCreation
)
658 static bool s_createdHelpMenu
= false ;
660 if ( !s_createdHelpMenu
&& !allowHelpMenuCreation
)
665 OSStatus status
= HMGetHelpMenu( outHelpMenu
, outFirstCustomItemIndex
) ;
666 s_createdHelpMenu
= ( status
== noErr
) ;
669 wxUnusedVar( allowHelpMenuCreation
) ;
670 MenuRef helpMenuHandle
;
672 helpMenuStatus
= HMGetHelpMenuHandle( &helpMenuHandle
) ;
673 if ( firstCustomItemIndex
== 0 && helpMenuStatus
== noErr
)
674 firstCustomItemIndex
= CountMenuItems( helpMenuHandle
) + 1 ;
676 if ( outFirstCustomItemIndex
)
677 *outFirstCustomItemIndex
= firstCustomItemIndex
;
679 *outHelpMenu
= helpMenuHandle
;
681 return helpMenuStatus
;
685 OSStatus
UMAGetHelpMenu(
686 MenuRef
* outHelpMenu
,
687 MenuItemIndex
* outFirstCustomItemIndex
)
689 return UMAGetHelpMenu( outHelpMenu
, outFirstCustomItemIndex
, true );
692 OSStatus
UMAGetHelpMenuDontCreate(
693 MenuRef
* outHelpMenu
,
694 MenuItemIndex
* outFirstCustomItemIndex
)
696 return UMAGetHelpMenu( outHelpMenu
, outFirstCustomItemIndex
, false );
701 wxMacPortStateHelper::wxMacPortStateHelper( GrafPtr newport
)
707 wxMacPortStateHelper::wxMacPortStateHelper()
712 void wxMacPortStateHelper::Setup( GrafPtr newport
)
714 GetPort( &m_oldPort
) ;
718 wxASSERT_MSG( m_clip
== NULL
, wxT("Cannot call setup twice") ) ;
721 m_textFont
= GetPortTextFont( (CGrafPtr
) newport
);
722 m_textSize
= GetPortTextSize( (CGrafPtr
) newport
);
723 m_textStyle
= GetPortTextFace( (CGrafPtr
) newport
);
724 m_textMode
= GetPortTextMode( (CGrafPtr
) newport
);
725 GetThemeDrawingState( &m_drawingState
) ;
726 m_currentPort
= newport
;
729 void wxMacPortStateHelper::Clear()
733 DisposeRgn( m_clip
) ;
734 DisposeThemeDrawingState( m_drawingState
) ;
739 wxMacPortStateHelper::~wxMacPortStateHelper()
743 SetPort( m_currentPort
) ;
745 DisposeRgn( m_clip
) ;
746 TextFont( m_textFont
);
747 TextSize( m_textSize
);
748 TextFace( m_textStyle
);
749 TextMode( m_textMode
);
750 SetThemeDrawingState( m_drawingState
, true ) ;
751 SetPort( m_oldPort
) ;
757 Rect
* UMAGetControlBoundsInWindowCoords( ControlRef theControl
, Rect
*bounds
)
759 GetControlBounds( theControl
, bounds
) ;
761 #if TARGET_API_MAC_OSX
762 WindowRef tlwref
= GetControlOwner( theControl
) ;
764 wxTopLevelWindowMac
* tlwwx
= wxFindWinFromMacWindow( tlwref
) ;
767 ControlRef rootControl
= tlwwx
->GetPeer()->GetControlRef() ;
768 HIPoint hiPoint
= CGPointMake( 0 , 0 ) ;
769 HIViewConvertPoint( &hiPoint
, HIViewGetSuperview(theControl
) , rootControl
) ;
770 OffsetRect( bounds
, (short) hiPoint
.x
, (short) hiPoint
.y
) ;
777 size_t UMAPutBytesCFRefCallback( void *info
, const void *bytes
, size_t count
)
779 CFMutableDataRef data
= (CFMutableDataRef
) info
;
782 CFDataAppendBytes( data
, (const UInt8
*) bytes
, count
);
787 void UMAReleaseCFDataProviderCallback( void *info
, const void *data
, size_t count
)
790 CFRelease( (CFDataRef
) info
);
793 void UMAReleaseCFDataConsumerCallback( void *info
)
796 CFRelease( (CFDataRef
) info
);
799 CGDataProviderRef
UMACGDataProviderCreateWithCFData( CFDataRef data
)
804 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
805 if( &CGDataProviderCreateWithCFData
!= NULL
)
807 return CGDataProviderCreateWithCFData( data
);
811 // make sure we keep it until done
813 CGDataProviderRef provider
= CGDataProviderCreateWithData( (void*) data
, CFDataGetBytePtr( data
) ,
814 CFDataGetLength( data
), UMAReleaseCFDataProviderCallback
);
815 // if provider couldn't be created, release the data again
816 if ( provider
== NULL
)
821 CGDataConsumerRef
UMACGDataConsumerCreateWithCFData( CFMutableDataRef data
)
826 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
827 if( &CGDataConsumerCreateWithCFData
!= NULL
)
829 return CGDataConsumerCreateWithCFData( data
);
832 // make sure we keep it until done
834 CGDataConsumerCallbacks callbacks
;
835 callbacks
.putBytes
= UMAPutBytesCFRefCallback
;
836 callbacks
.releaseConsumer
= UMAReleaseCFDataConsumerCallback
;
837 CGDataConsumerRef consumer
= CGDataConsumerCreate( data
, &callbacks
);
838 // if consumer couldn't be created, release the data again
839 if ( consumer
== NULL
)
847 static bool sUMASystemInitialized
= false ;
849 bool UMASystemIsInitialized()
851 return sUMASystemInitialized
;
854 void UMASetSystemIsInitialized(bool val
)
856 sUMASystemInitialized
= val
;