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>
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
WXUNUSED(inMoreMastersCalls
),
53 bool WXUNUSED(isEmbedded
) )
57 if ( Gestalt(gestaltSystemVersion
, &sUMASystemVersion
) != noErr
)
58 sUMASystemVersion
= 0x0000 ;
67 GetThemeFont(kThemeSmallSystemFont
, GetApplicationScript() , fontName
, &fontSize
, &fontStyle
) ;
68 GetFNum( fontName
, &fontId
);
70 TXNMacOSPreferredFontDescription fontDescriptions
[] =
72 { fontId
, (fontSize
<< 16) , kTXNDefaultFontStyle
, kTXNSystemDefaultEncoding
}
74 int noOfFontDescriptions
= sizeof( fontDescriptions
) / sizeof(TXNMacOSPreferredFontDescription
) ;
76 OptionBits options
= 0 ;
78 if ( UMAGetSystemVersion() < 0x1000 )
79 options
|= kTXNAlwaysUseQuickDrawTextMask
;
81 TXNInitTextension( fontDescriptions
, noOfFontDescriptions
, options
);
85 UMASetSystemIsInitialized( true );
89 long UMAGetProcessMode()
92 ProcessInfoRec processinfo
;
93 ProcessSerialNumber procno
;
95 procno
.highLongOfPSN
= 0 ;
96 procno
.lowLongOfPSN
= kCurrentProcess
;
97 processinfo
.processInfoLength
= sizeof(ProcessInfoRec
);
98 processinfo
.processName
= NULL
;
100 processinfo
.processAppSpec
= NULL
;
103 err
= ::GetProcessInformation( &procno
, &processinfo
) ;
104 wxASSERT( err
== noErr
) ;
106 return processinfo
.processMode
;
109 bool UMAGetProcessModeDoesActivateOnFGSwitch()
111 return UMAGetProcessMode() & modeDoesActivateOnFGSwitch
;
116 MenuRef
UMANewMenu( SInt16 id
, const wxString
& title
, wxFontEncoding encoding
)
118 wxString str
= wxStripMenuCodes( title
) ;
122 CreateNewMenu( id
, 0 , &menu
) ;
123 SetMenuTitleWithCFString( menu
, wxMacCFStringHolder(str
, encoding
) ) ;
126 wxMacStringToPascal( str
, ptitle
) ;
127 menu
= ::NewMenu( id
, ptitle
) ;
133 void UMASetMenuTitle( MenuRef menu
, const wxString
& title
, wxFontEncoding encoding
)
135 wxString str
= wxStripMenuCodes( title
) ;
138 SetMenuTitleWithCFString( menu
, wxMacCFStringHolder(str
, encoding
) ) ;
142 wxMacStringToPascal( str
, ptitle
) ;
143 SetMenuTitle( menu
, ptitle
) ;
147 void UMASetMenuItemText( MenuRef menu
, MenuItemIndex item
, const wxString
& title
, wxFontEncoding encoding
)
149 // we don't strip the accels here anymore, must be done before
150 wxString str
= title
;
153 SetMenuItemTextWithCFString( menu
, item
, wxMacCFStringHolder(str
, encoding
) ) ;
157 wxMacStringToPascal( str
, ptitle
) ;
158 SetMenuItemText( menu
, item
, ptitle
) ;
162 UInt32
UMAMenuEvent( EventRecord
*inEvent
)
164 return MenuEvent( inEvent
) ;
167 void UMAEnableMenuItem( MenuRef inMenu
, MenuItemIndex inItem
, bool enable
)
170 EnableMenuItem( inMenu
, inItem
) ;
172 DisableMenuItem( inMenu
, inItem
) ;
175 void UMAAppendSubMenuItem( MenuRef menu
, const wxString
& title
, wxFontEncoding encoding
, SInt16 id
)
177 AppendMenuItemTextWithCFString( menu
,
178 CFSTR("A"), 0, 0,NULL
);
179 UMASetMenuItemText( menu
, (SInt16
) ::CountMenuItems(menu
), title
, encoding
);
180 SetMenuItemHierarchicalID( menu
, CountMenuItems( menu
) , id
) ;
183 void UMAInsertSubMenuItem( MenuRef menu
, const wxString
& title
, wxFontEncoding encoding
, MenuItemIndex item
, SInt16 id
)
185 InsertMenuItemTextWithCFString( menu
,
186 CFSTR("A"), item
, 0, 0);
188 UMASetMenuItemText( menu
, item
+1, title
, encoding
);
189 SetMenuItemHierarchicalID( menu
, item
+1 , id
) ;
192 void UMASetMenuItemShortcut( MenuRef menu
, MenuItemIndex item
, wxAcceleratorEntry
*entry
)
197 UInt8 modifiers
= 0 ;
198 SInt16 key
= entry
->GetKeyCode() ;
201 bool explicitCommandKey
= (entry
->GetFlags() & wxACCEL_CTRL
);
203 if (entry
->GetFlags() & wxACCEL_ALT
)
204 modifiers
|= kMenuOptionModifier
;
206 if (entry
->GetFlags() & wxACCEL_SHIFT
)
207 modifiers
|= kMenuShiftModifier
;
210 SInt16 macKey
= key
;
211 if ( key
>= WXK_F1
&& key
<= WXK_F15
)
213 if ( !explicitCommandKey
)
214 modifiers
|= kMenuNoCommandModifier
;
216 // for some reasons this must be 0 right now
217 // everything else leads to just the first function key item
218 // to be selected. Thanks to Ryan Wilcox for finding out.
220 glyph
= kMenuF1Glyph
+ ( key
- WXK_F1
) ;
221 if ( key
>= WXK_F13
)
229 macKey
= kBackspaceCharCode
;
230 glyph
= kMenuDeleteLeftGlyph
;
234 macKey
= kTabCharCode
;
235 glyph
= kMenuTabRightGlyph
;
238 case kEnterCharCode
:
239 macKey
= kEnterCharCode
;
240 glyph
= kMenuEnterGlyph
;
244 macKey
= kReturnCharCode
;
245 glyph
= kMenuReturnGlyph
;
249 macKey
= kEscapeCharCode
;
250 glyph
= kMenuEscapeGlyph
;
255 glyph
= kMenuSpaceGlyph
;
259 macKey
= kDeleteCharCode
;
260 glyph
= kMenuDeleteRightGlyph
;
264 macKey
= kClearCharCode
;
265 glyph
= kMenuClearGlyph
;
269 macKey
= kPageUpCharCode
;
270 glyph
= kMenuPageUpGlyph
;
274 macKey
= kPageDownCharCode
;
275 glyph
= kMenuPageDownGlyph
;
279 macKey
= kLeftArrowCharCode
;
280 glyph
= kMenuLeftArrowGlyph
;
284 macKey
= kUpArrowCharCode
;
285 glyph
= kMenuUpArrowGlyph
;
289 macKey
= kRightArrowCharCode
;
290 glyph
= kMenuRightArrowGlyph
;
294 macKey
= kDownArrowCharCode
;
295 glyph
= kMenuDownArrowGlyph
;
299 macKey
= kHomeCharCode
;
300 glyph
= kMenuNorthwestArrowGlyph
;
304 macKey
= kEndCharCode
;
305 glyph
= kMenuSoutheastArrowGlyph
;
308 macKey
= toupper( key
) ;
312 // we now allow non command key shortcuts
313 // remove in case this gives problems
314 if ( !explicitCommandKey
)
315 modifiers
|= kMenuNoCommandModifier
;
318 // 1d and 1e have special meaning to SetItemCmd, so
319 // do not use for these character codes.
320 if (key
!= WXK_UP
&& key
!= WXK_RIGHT
&& key
!= WXK_DOWN
&& key
!= WXK_LEFT
)
321 SetItemCmd( menu
, item
, macKey
);
323 SetMenuItemModifiers( menu
, item
, modifiers
) ;
326 SetMenuItemKeyGlyph( menu
, item
, glyph
) ;
330 void UMAAppendMenuItem( MenuRef menu
, const wxString
& title
, wxFontEncoding encoding
, wxAcceleratorEntry
*entry
)
332 AppendMenuItemTextWithCFString( menu
,
333 CFSTR("A"), 0, 0,NULL
);
334 // don't attempt to interpret metacharacters like a '-' at the beginning (would become a separator otherwise)
335 ChangeMenuItemAttributes( menu
, ::CountMenuItems(menu
), kMenuItemAttrIgnoreMeta
, 0 ) ;
336 UMASetMenuItemText(menu
, (SInt16
) ::CountMenuItems(menu
), title
, encoding
);
337 UMASetMenuItemShortcut( menu
, (SInt16
) ::CountMenuItems(menu
), entry
) ;
340 void UMAInsertMenuItem( MenuRef menu
, const wxString
& title
, wxFontEncoding encoding
, MenuItemIndex item
, wxAcceleratorEntry
*entry
)
342 InsertMenuItemTextWithCFString( menu
,
343 CFSTR("A"), item
, 0, 0);
345 // don't attempt to interpret metacharacters like a '-' at the beginning (would become a separator otherwise)
346 ChangeMenuItemAttributes( menu
, item
+1, kMenuItemAttrIgnoreMeta
, 0 ) ;
347 UMASetMenuItemText(menu
, item
+1 , title
, encoding
);
348 UMASetMenuItemShortcut( menu
, item
+1 , entry
) ;
355 int gPrOpenCounter
= 0 ;
363 if ( gPrOpenCounter
== 1 )
367 wxASSERT( err
== noErr
) ;
373 OSStatus
UMAPrClose()
377 wxASSERT( gPrOpenCounter
>= 1 ) ;
379 if ( gPrOpenCounter
== 1 )
383 wxASSERT( err
== noErr
) ;
391 pascal QDGlobalsPtr
GetQDGlobalsPtr() ;
392 pascal QDGlobalsPtr
GetQDGlobalsPtr()
394 return QDGlobalsPtr (* (Ptr
*) LMGetCurrentA5 ( ) - 0xCA);
399 void UMAShowWatchCursor()
401 SetThemeCursor(kThemeWatchCursor
);
404 void UMAShowArrowCursor()
406 SetThemeCursor(kThemeArrowCursor
);
411 GrafPtr
UMAGetWindowPort( WindowRef inWindowRef
)
413 wxASSERT( inWindowRef
!= NULL
) ;
416 return (GrafPtr
) GetWindowPort( inWindowRef
) ;
418 return (GrafPtr
) inWindowRef
;
422 void UMADisposeWindow( WindowRef inWindowRef
)
424 wxASSERT( inWindowRef
!= NULL
) ;
426 DisposeWindow( inWindowRef
) ;
429 void UMASetWTitle( WindowRef inWindowRef
, const wxString
& title
, wxFontEncoding encoding
)
432 SetWindowTitleWithCFString( inWindowRef
, wxMacCFStringHolder(title
, encoding
) ) ;
436 wxMacStringToPascal( title
, ptitle
) ;
437 SetWTitle( inWindowRef
, ptitle
) ;
441 // appearance additions
443 void UMASetControlTitle( ControlRef inControl
, const wxString
& title
, wxFontEncoding encoding
)
446 SetControlTitleWithCFString( inControl
, wxMacCFStringHolder(title
, encoding
) ) ;
450 wxMacStringToPascal( title
, ptitle
) ;
451 SetControlTitle( inControl
, ptitle
) ;
455 void UMAActivateControl( ControlRef inControl
)
457 #if TARGET_API_MAC_OSX
458 ::ActivateControl( inControl
) ;
461 // we have to add the control after again to the update rgn
462 // otherwise updates get lost
463 if ( !IsControlActive( inControl
) )
465 bool visible
= IsControlVisible( inControl
) ;
467 SetControlVisibility( inControl
, false , false ) ;
469 ::ActivateControl( inControl
) ;
473 SetControlVisibility( inControl
, true , false ) ;
476 InvalWindowRect( GetControlOwner(inControl
), UMAGetControlBoundsInWindowCoords(inControl
, &ctrlBounds
) ) ;
482 void UMAMoveControl( ControlRef inControl
, short x
, short y
)
484 #if TARGET_API_MAC_OSX
485 ::MoveControl( inControl
, x
, y
) ;
488 bool visible
= IsControlVisible( inControl
) ;
491 SetControlVisibility( inControl
, false , false ) ;
493 InvalWindowRect( GetControlOwner(inControl
), GetControlBounds(inControl
, &ctrlBounds
) ) ;
496 ::MoveControl( inControl
, x
, y
) ;
500 SetControlVisibility( inControl
, true , false ) ;
502 InvalWindowRect( GetControlOwner(inControl
), GetControlBounds(inControl
, &ctrlBounds
) ) ;
507 void UMASizeControl( ControlRef inControl
, short x
, short y
)
509 #if TARGET_API_MAC_OSX
510 ::SizeControl( inControl
, x
, y
) ;
513 bool visible
= IsControlVisible( inControl
) ;
516 SetControlVisibility( inControl
, false , false ) ;
518 InvalWindowRect( GetControlOwner(inControl
), GetControlBounds(inControl
, &ctrlBounds
) ) ;
521 ::SizeControl( inControl
, x
, y
) ;
525 SetControlVisibility( inControl
, true , false ) ;
527 InvalWindowRect( GetControlOwner(inControl
), GetControlBounds(inControl
, &ctrlBounds
) ) ;
532 void UMADeactivateControl( ControlRef inControl
)
534 #if TARGET_API_MAC_OSX
535 ::DeactivateControl( inControl
) ;
538 // we have to add the control after again to the update rgn
539 // otherwise updates get lost
540 bool visible
= IsControlVisible( inControl
) ;
542 SetControlVisibility( inControl
, false , false ) ;
544 ::DeactivateControl( inControl
) ;
548 SetControlVisibility( inControl
, true , false ) ;
550 InvalWindowRect( GetControlOwner(inControl
), UMAGetControlBoundsInWindowCoords(inControl
, &ctrlBounds
) ) ;
555 // shows the control and adds the region to the update region
556 void UMAShowControl( ControlRef inControl
)
558 SetControlVisibility( inControl
, true , false ) ;
559 HIViewSetNeedsDisplay( inControl
, true );
562 // hides the control and adds the region to the update region
563 void UMAHideControl( ControlRef inControl
)
565 SetControlVisibility( inControl
, false , false ) ;
566 HIViewSetNeedsDisplay( inControl
, true );
570 OSErr
UMASetKeyboardFocus( WindowPtr inWindow
,
571 ControlRef inControl
,
572 ControlFocusPart inPart
)
579 SetPortWindowPort( inWindow
) ;
582 err
= SetKeyboardFocus( inWindow
, inControl
, inPart
) ;
590 bool UMAIsWindowFloating( WindowRef inWindow
)
594 GetWindowClass( inWindow
, &cl
) ;
595 return cl
== kFloatingWindowClass
;
598 bool UMAIsWindowModal( WindowRef inWindow
)
602 GetWindowClass( inWindow
, &cl
) ;
603 return cl
< kFloatingWindowClass
;
608 void UMAHighlightAndActivateWindow( WindowRef inWindowRef
, bool inActivate
)
612 // bool isHighlighted = IsWindowHighlited( inWindowRef ) ;
613 // if ( inActivate != isHighlighted )
617 SetPortWindowPort( inWindowRef
) ;
619 HiliteWindow( inWindowRef
, inActivate
) ;
620 ControlRef control
= NULL
;
621 ::GetRootControl( inWindowRef
, &control
) ;
625 UMAActivateControl( control
) ;
627 UMADeactivateControl( control
) ;
635 OSStatus
UMADrawThemePlacard( const Rect
*inRect
, ThemeDrawState inState
)
638 return ::DrawThemePlacard( inRect
, inState
) ;
645 static OSStatus helpMenuStatus
= noErr
;
646 static MenuItemIndex firstCustomItemIndex
= 0 ;
649 static OSStatus
UMAGetHelpMenu(
650 MenuRef
* outHelpMenu
,
651 MenuItemIndex
* outFirstCustomItemIndex
,
652 bool allowHelpMenuCreation
);
654 static OSStatus
UMAGetHelpMenu(
655 MenuRef
* outHelpMenu
,
656 MenuItemIndex
* outFirstCustomItemIndex
,
657 bool allowHelpMenuCreation
)
660 static bool s_createdHelpMenu
= false ;
662 if ( !s_createdHelpMenu
&& !allowHelpMenuCreation
)
667 OSStatus status
= HMGetHelpMenu( outHelpMenu
, outFirstCustomItemIndex
) ;
668 s_createdHelpMenu
= ( status
== noErr
) ;
671 wxUnusedVar( allowHelpMenuCreation
) ;
672 MenuRef helpMenuHandle
;
674 helpMenuStatus
= HMGetHelpMenuHandle( &helpMenuHandle
) ;
675 if ( firstCustomItemIndex
== 0 && helpMenuStatus
== noErr
)
676 firstCustomItemIndex
= CountMenuItems( helpMenuHandle
) + 1 ;
678 if ( outFirstCustomItemIndex
)
679 *outFirstCustomItemIndex
= firstCustomItemIndex
;
681 *outHelpMenu
= helpMenuHandle
;
683 return helpMenuStatus
;
687 OSStatus
UMAGetHelpMenu(
688 MenuRef
* outHelpMenu
,
689 MenuItemIndex
* outFirstCustomItemIndex
)
691 return UMAGetHelpMenu( outHelpMenu
, outFirstCustomItemIndex
, true );
694 OSStatus
UMAGetHelpMenuDontCreate(
695 MenuRef
* outHelpMenu
,
696 MenuItemIndex
* outFirstCustomItemIndex
)
698 return UMAGetHelpMenu( outHelpMenu
, outFirstCustomItemIndex
, false );
703 wxMacPortStateHelper::wxMacPortStateHelper( GrafPtr newport
)
709 wxMacPortStateHelper::wxMacPortStateHelper()
714 void wxMacPortStateHelper::Setup( GrafPtr newport
)
716 GetPort( &m_oldPort
) ;
720 wxASSERT_MSG( m_clip
== NULL
, wxT("Cannot call setup twice") ) ;
723 m_textFont
= GetPortTextFont( (CGrafPtr
) newport
);
724 m_textSize
= GetPortTextSize( (CGrafPtr
) newport
);
725 m_textStyle
= GetPortTextFace( (CGrafPtr
) newport
);
726 m_textMode
= GetPortTextMode( (CGrafPtr
) newport
);
727 GetThemeDrawingState( &m_drawingState
) ;
728 m_currentPort
= newport
;
731 void wxMacPortStateHelper::Clear()
735 DisposeRgn( m_clip
) ;
736 DisposeThemeDrawingState( m_drawingState
) ;
741 wxMacPortStateHelper::~wxMacPortStateHelper()
745 SetPort( m_currentPort
) ;
747 DisposeRgn( m_clip
) ;
748 TextFont( m_textFont
);
749 TextSize( m_textSize
);
750 TextFace( m_textStyle
);
751 TextMode( m_textMode
);
752 SetThemeDrawingState( m_drawingState
, true ) ;
753 SetPort( m_oldPort
) ;
759 OSStatus
UMAPutScrap( Size size
, OSType type
, void *data
)
761 OSStatus err
= noErr
;
764 err
= PutScrap( size
, type
, data
) ;
767 err
= GetCurrentScrap( &scrap
);
769 err
= PutScrapFlavor( scrap
, type
, 0, size
, data
);
775 Rect
* UMAGetControlBoundsInWindowCoords( ControlRef theControl
, Rect
*bounds
)
777 GetControlBounds( theControl
, bounds
) ;
779 #if TARGET_API_MAC_OSX
780 WindowRef tlwref
= GetControlOwner( theControl
) ;
782 wxTopLevelWindowMac
* tlwwx
= wxFindWinFromMacWindow( tlwref
) ;
785 ControlRef rootControl
= tlwwx
->GetPeer()->GetControlRef() ;
786 HIPoint hiPoint
= CGPointMake( 0 , 0 ) ;
787 HIViewConvertPoint( &hiPoint
, HIViewGetSuperview(theControl
) , rootControl
) ;
788 OffsetRect( bounds
, (short) hiPoint
.x
, (short) hiPoint
.y
) ;
799 static bool sUMASystemInitialized
= false ;
801 bool UMASystemIsInitialized()
803 return sUMASystemInitialized
;
806 void UMASetSystemIsInitialized(bool val
)
808 sUMASystemInitialized
= val
;