1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/mac/classic/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"
21 #include <MacTextEditor.h>
24 # include <Navigation.h>
25 # if defined(TARGET_CARBON)
26 # if PM_USE_SESSION_APIS
29 # include <PMApplication.h>
31 # include <Printing.h>
38 #include "wx/mac/uma.h"
41 // since we have decided that we only support 8.6 upwards we are
42 // checking for these minimum requirements in the startup code of
43 // the application so all wxWidgets code can safely assume that appearance 1.1
44 // windows manager, control manager, navigation services etc. are
47 static bool sUMAHasAppearance
= false ;
48 static long sUMAAppearanceVersion
= 0 ;
49 static long sUMASystemVersion
= 0 ;
50 static bool sUMAHasAquaLayout
= false ;
52 static bool sUMAHasInittedAppearance
= false;
54 extern int gAGABackgroundColor
;
55 bool UMAHasAppearance() { return sUMAHasAppearance
; }
56 long UMAGetAppearanceVersion() { return sUMAAppearanceVersion
; }
57 long UMAGetSystemVersion() { return sUMASystemVersion
; }
59 static bool sUMAHasWindowManager
= false ;
60 static long sUMAWindowManagerAttr
= 0 ;
62 bool UMAHasWindowManager() { return sUMAHasWindowManager
; }
63 long UMAGetWindowManagerAttr() { return sUMAWindowManagerAttr
; }
64 bool UMAHasAquaLayout() { return sUMAHasAquaLayout
; }
67 void UMACleanupToolbox()
69 if (sUMAHasInittedAppearance
)
71 UnregisterAppearanceClient() ;
73 if ( NavServicesAvailable() )
77 if ( TXNTerminateTextension
!= (void*) kUnresolvedCFragSymbolAddress
)
78 TXNTerminateTextension( ) ;
80 void UMAInitToolbox( UInt16 inMoreMastersCalls
, bool isEmbedded
)
84 for (long i
= 1; i
<= inMoreMastersCalls
; i
++)
89 ::InitGraf(&qd
.thePort
);
94 ::FlushEvents(everyEvent
, 0);
98 PurgeSpace(&total
, &contig
);
103 if ( Gestalt(gestaltSystemVersion
, &sUMASystemVersion
) != noErr
)
104 sUMASystemVersion
= 0x0000 ;
107 if ( Gestalt( gestaltAppearanceAttr
, &theAppearance
) == noErr
)
109 sUMAHasAppearance
= true ;
110 OSStatus status
= RegisterAppearanceClient();
111 // If status equals appearanceProcessRegisteredErr it means the
112 // appearance client already was registered (For example if we run
113 // embedded, the host might have registered it). In such a case
114 // we don't unregister it later on.
115 if (status
!= appearanceProcessRegisteredErr
)
117 // Appearance client wasn't registered yet.
118 sUMAHasInittedAppearance
= true;
121 if ( Gestalt( gestaltAppearanceVersion
, &theAppearance
) == noErr
)
123 sUMAAppearanceVersion
= theAppearance
;
127 sUMAAppearanceVersion
= 0x0100 ;
130 if ( Gestalt( gestaltWindowMgrAttr
, &sUMAWindowManagerAttr
) == noErr
)
132 sUMAHasWindowManager
= sUMAWindowManagerAttr
& gestaltWindowMgrPresent
;
136 // Call currently implicitely done : InitFloatingWindows() ;
140 if ( sUMAHasWindowManager
)
141 InitFloatingWindows() ;
147 if ( NavServicesAvailable() )
153 Gestalt( gestaltMenuMgrAttr
, &menuMgrAttr
) ;
154 if ( menuMgrAttr
& gestaltMenuMgrAquaLayoutMask
)
155 sUMAHasAquaLayout
= true ;
157 if ( TXNInitTextension
!= (void*) kUnresolvedCFragSymbolAddress
)
159 FontFamilyID fontId
;
163 GetThemeFont(kThemeSmallSystemFont
, GetApplicationScript() , fontName
, &fontSize
, &fontStyle
) ;
164 GetFNum( fontName
, &fontId
);
166 TXNMacOSPreferredFontDescription fontDescriptions
[] =
168 { fontId
, (fontSize
<< 16) ,kTXNDefaultFontStyle
, kTXNSystemDefaultEncoding
}
170 int noOfFontDescriptions
= sizeof( fontDescriptions
) / sizeof(TXNMacOSPreferredFontDescription
) ;
172 // kTXNAlwaysUseQuickDrawTextMask might be desirable because of speed increases but it crashes the app under OS X upon key stroke
174 // leads to unexpected content for clients, TODO configurable
175 OptionBits options
= kTXNWantMoviesMask
| kTXNWantSoundMask
| kTXNWantGraphicsMask
;
177 OptionBits options
= 0 ;
181 if ( !UMAHasAquaLayout() )
184 options
|= kTXNAlwaysUseQuickDrawTextMask
;
186 TXNInitTextension(fontDescriptions
, noOfFontDescriptions
, options
);
190 UMASetSystemIsInitialized(true);
195 Boolean CanUseATSUI()
198 OSErr err = Gestalt(gestaltATSUVersion, &result);
199 return (err == noErr);
203 long UMAGetProcessMode()
206 ProcessInfoRec processinfo
;
207 ProcessSerialNumber procno
;
209 procno
.highLongOfPSN
= NULL
;
210 procno
.lowLongOfPSN
= kCurrentProcess
;
211 processinfo
.processInfoLength
= sizeof(ProcessInfoRec
);
212 processinfo
.processName
= NULL
;
213 processinfo
.processAppSpec
= NULL
;
215 err
= ::GetProcessInformation( &procno
, &processinfo
) ;
216 wxASSERT( err
== noErr
) ;
217 return processinfo
.processMode
;
220 bool UMAGetProcessModeDoesActivateOnFGSwitch()
222 return UMAGetProcessMode() & modeDoesActivateOnFGSwitch
;
227 MenuRef
UMANewMenu( SInt16 id
, const wxString
& title
, wxFontEncoding encoding
)
229 wxString str
= wxStripMenuCodes( title
) ;
232 CreateNewMenu( id
, 0 , &menu
) ;
233 SetMenuTitleWithCFString( menu
, wxMacCFStringHolder(str
, encoding
) ) ;
236 wxMacStringToPascal( str
, ptitle
) ;
237 menu
= ::NewMenu( id
, ptitle
) ;
242 void UMASetMenuTitle( MenuRef menu
, const wxString
& title
, wxFontEncoding encoding
)
244 wxString str
= wxStripMenuCodes( title
) ;
246 SetMenuTitleWithCFString( menu
, wxMacCFStringHolder(str
, encoding
) ) ;
249 wxMacStringToPascal( str
, ptitle
) ;
250 SetMenuTitle( menu
, ptitle
) ;
254 void UMASetMenuItemText( MenuRef menu
, MenuItemIndex item
, const wxString
& title
, wxFontEncoding encoding
)
256 wxString str
= wxStripMenuCodes( title
) ;
258 SetMenuItemTextWithCFString( menu
, item
, wxMacCFStringHolder(str
, encoding
) ) ;
261 wxMacStringToPascal( str
, ptitle
) ;
262 SetMenuItemText( menu
, item
, ptitle
) ;
267 UInt32
UMAMenuEvent( EventRecord
*inEvent
)
269 return MenuEvent( inEvent
) ;
272 void UMAEnableMenuItem( MenuRef inMenu
, MenuItemIndex inItem
, bool enable
)
275 EnableMenuItem( inMenu
, inItem
) ;
277 DisableMenuItem( inMenu
, inItem
) ;
280 void UMAAppendSubMenuItem( MenuRef menu
, const wxString
& title
, wxFontEncoding encoding
, SInt16 id
)
282 MacAppendMenu(menu
, "\pA");
283 UMASetMenuItemText(menu
, (SInt16
) ::CountMenuItems(menu
), title
, encoding
);
284 SetMenuItemHierarchicalID( menu
, CountMenuItems( menu
) , id
) ;
287 void UMAInsertSubMenuItem( MenuRef menu
, const wxString
& title
, wxFontEncoding encoding
, MenuItemIndex item
, SInt16 id
)
289 MacInsertMenuItem(menu
, "\pA" , item
);
290 UMASetMenuItemText(menu
, item
, title
, encoding
);
291 SetMenuItemHierarchicalID( menu
, item
, id
) ;
294 void UMASetMenuItemShortcut( MenuRef menu
, MenuItemIndex item
, wxAcceleratorEntry
*entry
)
299 UInt8 modifiers
= 0 ;
300 SInt16 key
= entry
->GetKeyCode() ;
303 bool explicitCommandKey
= false ;
305 if ( entry
->GetFlags() & wxACCEL_CTRL
)
307 explicitCommandKey
= true ;
310 if (entry
->GetFlags() & wxACCEL_ALT
)
312 modifiers
|= kMenuOptionModifier
;
315 if (entry
->GetFlags() & wxACCEL_SHIFT
)
317 modifiers
|= kMenuShiftModifier
;
321 SInt16 macKey
= key
;
322 if ( key
>= WXK_F1
&& key
<= WXK_F15
)
324 // for some reasons this must be 0 right now
325 // everything else leads to just the first function key item
326 // to be selected. Thanks to Ryan Wilcox for finding out.
328 glyph
= kMenuF1Glyph
+ ( key
- WXK_F1
) ;
329 if ( key
>= WXK_F13
)
331 if ( !explicitCommandKey
)
332 modifiers
|= kMenuNoCommandModifier
;
339 macKey
= kBackspaceCharCode
;
340 glyph
= kMenuDeleteLeftGlyph
;
343 macKey
= kTabCharCode
;
344 glyph
= kMenuTabRightGlyph
;
346 case kEnterCharCode
:
347 macKey
= kEnterCharCode
;
348 glyph
= kMenuEnterGlyph
;
351 macKey
= kReturnCharCode
;
352 glyph
= kMenuReturnGlyph
;
355 macKey
= kEscapeCharCode
;
356 glyph
= kMenuEscapeGlyph
;
360 glyph
= kMenuSpaceGlyph
;
363 macKey
= kDeleteCharCode
;
364 glyph
= kMenuDeleteRightGlyph
;
367 macKey
= kClearCharCode
;
368 glyph
= kMenuClearGlyph
;
371 macKey
= kPageUpCharCode
;
372 glyph
= kMenuPageUpGlyph
;
375 macKey
= kPageDownCharCode
;
376 glyph
= kMenuPageDownGlyph
;
379 macKey
= kLeftArrowCharCode
;
380 glyph
= kMenuLeftArrowGlyph
;
383 macKey
= kUpArrowCharCode
;
384 glyph
= kMenuUpArrowGlyph
;
387 macKey
= kRightArrowCharCode
;
388 glyph
= kMenuRightArrowGlyph
;
391 macKey
= kDownArrowCharCode
;
392 glyph
= kMenuDownArrowGlyph
;
397 SetItemCmd( menu
, item
, macKey
);
398 SetMenuItemModifiers(menu
, item
, modifiers
) ;
401 SetMenuItemKeyGlyph(menu
, item
, glyph
) ;
405 void UMAAppendMenuItem( MenuRef menu
, const wxString
& title
, wxFontEncoding encoding
, wxAcceleratorEntry
*entry
)
407 MacAppendMenu(menu
, "\pA");
408 UMASetMenuItemText(menu
, (SInt16
) ::CountMenuItems(menu
), title
, encoding
);
409 UMASetMenuItemShortcut( menu
, (SInt16
) ::CountMenuItems(menu
), entry
) ;
412 void UMAInsertMenuItem( MenuRef menu
, const wxString
& title
, wxFontEncoding encoding
, MenuItemIndex item
, wxAcceleratorEntry
*entry
)
414 MacInsertMenuItem( menu
, "\pA" , item
) ;
415 UMASetMenuItemText(menu
, item
+1 , title
, encoding
);
416 UMASetMenuItemShortcut( menu
, item
+1 , entry
) ;
423 int gPrOpenCounter
= 0 ;
429 if ( gPrOpenCounter
== 1 )
433 wxASSERT( err
== noErr
) ;
438 OSStatus
UMAPrClose()
441 wxASSERT( gPrOpenCounter
>= 1 ) ;
442 if ( gPrOpenCounter
== 1 )
446 wxASSERT( err
== noErr
) ;
452 pascal QDGlobalsPtr
GetQDGlobalsPtr (void) ;
453 pascal QDGlobalsPtr
GetQDGlobalsPtr (void)
455 return QDGlobalsPtr (* (Ptr
*) LMGetCurrentA5 ( ) - 0xCA);
460 void UMAShowWatchCursor()
464 CursHandle watchFob
= GetCursor (watchCursor
);
471 // Cursor preservedArrow;
472 // GetQDGlobalsArrow (&preservedArrow);
473 // SetQDGlobalsArrow (*watchFob);
475 // SetQDGlobalsArrow (&preservedArrow);
476 SetCursor (*watchFob
);
478 SetCursor (*watchFob
);
483 void UMAShowArrowCursor()
487 SetCursor (GetQDGlobalsArrow (&arrow
));
489 SetCursor (&(qd
.arrow
));
495 GrafPtr
UMAGetWindowPort( WindowRef inWindowRef
)
497 wxASSERT( inWindowRef
!= NULL
) ;
499 return (GrafPtr
) GetWindowPort( inWindowRef
) ;
501 return (GrafPtr
) inWindowRef
;
505 void UMADisposeWindow( WindowRef inWindowRef
)
507 wxASSERT( inWindowRef
!= NULL
) ;
508 DisposeWindow( inWindowRef
) ;
511 void UMASetWTitle( WindowRef inWindowRef
, const wxString
& title
, wxFontEncoding encoding
)
514 SetWindowTitleWithCFString( inWindowRef
, wxMacCFStringHolder(title
, encoding
) ) ;
517 wxMacStringToPascal( title
, ptitle
) ;
518 SetWTitle( inWindowRef
, ptitle
) ;
522 // appearance additions
524 void UMASetControlTitle( ControlHandle inControl
, const wxString
& title
, wxFontEncoding encoding
)
527 SetControlTitleWithCFString( inControl
, wxMacCFStringHolder(title
, encoding
) ) ;
530 wxMacStringToPascal( title
, ptitle
) ;
531 SetControlTitle( inControl
, ptitle
) ;
535 void UMAActivateControl( ControlHandle inControl
)
537 // we have to add the control after again to the update rgn
538 // otherwise updates get lost
539 if ( !IsControlActive( inControl
) )
541 bool visible
= IsControlVisible( inControl
) ;
543 SetControlVisibility( inControl
, false , false ) ;
544 ::ActivateControl( inControl
) ;
546 SetControlVisibility( inControl
, true , false ) ;
548 InvalWindowRect(GetControlOwner(inControl
),GetControlBounds(inControl
,&ctrlBounds
) ) ;
553 void UMADrawControl( ControlHandle inControl
)
555 WindowRef theWindow
= GetControlOwner(inControl
) ;
556 wxMacPortStateHelper
help( (GrafPtr
) GetWindowPort(theWindow
) ) ;
557 RgnHandle updateRgn
= NewRgn() ;
558 GetWindowUpdateRgn( theWindow
, updateRgn
) ;
559 Point zero
= { 0 , 0 } ;
560 LocalToGlobal( &zero
) ;
561 OffsetRgn( updateRgn
, -zero
.h
, -zero
.v
) ;
562 ::DrawControlInCurrentPort( inControl
) ;
563 InvalWindowRgn( theWindow
, updateRgn
) ;
564 DisposeRgn( updateRgn
) ;
567 void UMAMoveControl( ControlHandle inControl
, short x
, short y
)
569 bool visible
= IsControlVisible( inControl
) ;
571 SetControlVisibility( inControl
, false , false ) ;
573 InvalWindowRect(GetControlOwner(inControl
),GetControlBounds(inControl
,&ctrlBounds
) ) ;
575 ::MoveControl( inControl
, x
, y
) ;
577 SetControlVisibility( inControl
, true , false ) ;
579 InvalWindowRect(GetControlOwner(inControl
),GetControlBounds(inControl
,&ctrlBounds
) ) ;
583 void UMASizeControl( ControlHandle inControl
, short x
, short y
)
585 bool visible
= IsControlVisible( inControl
) ;
587 SetControlVisibility( inControl
, false , false ) ;
589 InvalWindowRect(GetControlOwner(inControl
),GetControlBounds(inControl
,&ctrlBounds
) ) ;
591 ::SizeControl( inControl
, x
, y
) ;
593 SetControlVisibility( inControl
, true , false ) ;
595 InvalWindowRect(GetControlOwner(inControl
),GetControlBounds(inControl
,&ctrlBounds
) ) ;
599 void UMADeactivateControl( ControlHandle inControl
)
601 // we have to add the control after again to the update rgn
602 // otherwise updates get lost
603 bool visible
= IsControlVisible( inControl
) ;
605 SetControlVisibility( inControl
, false , false ) ;
606 ::DeactivateControl( inControl
) ;
608 SetControlVisibility( inControl
, true , false ) ;
610 InvalWindowRect(GetControlOwner(inControl
),GetControlBounds(inControl
,&ctrlBounds
) ) ;
613 // shows the control and adds the region to the update region
614 void UMAShowControl (ControlHandle inControl
)
616 SetControlVisibility( inControl
, true , false ) ;
618 InvalWindowRect(GetControlOwner(inControl
),GetControlBounds(inControl
,&ctrlBounds
) ) ;
621 // shows the control and adds the region to the update region
622 void UMAHideControl (ControlHandle inControl
)
624 SetControlVisibility( inControl
, false , false ) ;
626 InvalWindowRect(GetControlOwner(inControl
),GetControlBounds(inControl
,&ctrlBounds
) ) ;
629 OSErr
UMASetKeyboardFocus (WindowPtr inWindow
,
630 ControlHandle inControl
,
631 ControlFocusPart inPart
)
637 SetPortWindowPort( inWindow
) ;
639 err
= SetKeyboardFocus( inWindow
, inControl
, inPart
) ;
646 void UMAUpdateControls( WindowPtr inWindow
, RgnHandle inRgn
)
648 wxMacPortStateHelper
help( (GrafPtr
) GetWindowPort( (WindowRef
) inWindow
) ) ;
649 RgnHandle updateRgn
= NewRgn() ;
650 GetWindowUpdateRgn( inWindow
, updateRgn
) ;
652 Point zero
= { 0 , 0 } ;
653 LocalToGlobal( &zero
) ;
654 OffsetRgn( updateRgn
, -zero
.h
, -zero
.v
) ;
656 UpdateControls( inWindow
, inRgn
) ;
657 InvalWindowRgn( inWindow
, updateRgn
) ;
658 DisposeRgn( updateRgn
) ;
661 bool UMAIsWindowFloating( WindowRef inWindow
)
665 GetWindowClass( inWindow
, &cl
) ;
666 return cl
== kFloatingWindowClass
;
669 bool UMAIsWindowModal( WindowRef inWindow
)
673 GetWindowClass( inWindow
, &cl
) ;
674 return cl
< kFloatingWindowClass
;
679 void UMAHighlightAndActivateWindow( WindowRef inWindowRef
, bool inActivate
)
683 // bool isHighlighted = IsWindowHighlited( inWindowRef ) ;
684 // if ( inActivate != isHightlited )
687 SetPortWindowPort( inWindowRef
) ;
688 HiliteWindow( inWindowRef
, inActivate
) ;
689 ControlHandle control
= NULL
;
690 ::GetRootControl( inWindowRef
, & control
) ;
694 UMAActivateControl( control
) ;
696 UMADeactivateControl( control
) ;
702 OSStatus
UMADrawThemePlacard( const Rect
*inRect
, ThemeDrawState inState
)
704 return ::DrawThemePlacard( inRect
, inState
) ;
708 static OSStatus helpMenuStatus
= noErr
;
709 static MenuItemIndex firstCustomItemIndex
= 0 ;
712 OSStatus
UMAGetHelpMenu(
713 MenuRef
* outHelpMenu
,
714 MenuItemIndex
* outFirstCustomItemIndex
)
717 return HMGetHelpMenu( outHelpMenu
, outFirstCustomItemIndex
) ;
719 MenuRef helpMenuHandle
;
720 helpMenuStatus
= HMGetHelpMenuHandle( &helpMenuHandle
) ;
721 if ( firstCustomItemIndex
== 0 && helpMenuStatus
== noErr
)
723 firstCustomItemIndex
= CountMenuItems( helpMenuHandle
) + 1 ;
725 if ( outFirstCustomItemIndex
)
727 *outFirstCustomItemIndex
= firstCustomItemIndex
;
729 *outHelpMenu
= helpMenuHandle
;
730 return helpMenuStatus
;
734 wxMacPortStateHelper::wxMacPortStateHelper( GrafPtr newport
)
740 wxMacPortStateHelper::wxMacPortStateHelper()
745 void wxMacPortStateHelper::Setup( GrafPtr newport
)
747 GetPort( &m_oldPort
) ;
750 wxASSERT_MSG( m_clip
== NULL
, wxT("Cannot call setup twice") ) ;
753 m_textFont
= GetPortTextFont( (CGrafPtr
) newport
);
754 m_textSize
= GetPortTextSize( (CGrafPtr
) newport
);
755 m_textStyle
= GetPortTextFace( (CGrafPtr
) newport
);
756 m_textMode
= GetPortTextMode( (CGrafPtr
) newport
);
757 GetThemeDrawingState( &m_drawingState
) ;
758 m_currentPort
= newport
;
760 void wxMacPortStateHelper::Clear()
764 DisposeRgn( m_clip
) ;
765 DisposeThemeDrawingState( m_drawingState
) ;
770 wxMacPortStateHelper::~wxMacPortStateHelper()
774 SetPort( m_currentPort
) ;
776 DisposeRgn( m_clip
) ;
777 TextFont( m_textFont
);
778 TextSize( m_textSize
);
779 TextFace( m_textStyle
);
780 TextMode( m_textMode
);
781 SetThemeDrawingState( m_drawingState
, true ) ;
782 SetPort( m_oldPort
) ;
786 OSStatus
UMAPutScrap( Size size
, OSType type
, void *data
)
788 OSStatus err
= noErr
;
790 err
= PutScrap( size
, type
, data
) ;
793 err
= GetCurrentScrap (&scrap
);
796 err
= PutScrapFlavor (scrap
, type
, 0, size
, data
);
806 static bool sUMASystemInitialized
= false ;
808 bool UMASystemIsInitialized()
810 return sUMASystemInitialized
;
813 void UMASetSystemIsInitialized(bool val
)
815 sUMASystemInitialized
= val
;