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
;