]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/uma.cpp
conditionalized theme box drawing
[wxWidgets.git] / src / mac / carbon / uma.cpp
1 #include "wx/defs.h"
2 #include "wx/dc.h"
3 #include "wx/mac/uma.h"
4 #include <MacTextEditor.h>
5
6 #ifndef __DARWIN__
7 # include <Navigation.h>
8 # if defined(TARGET_CARBON)
9 # if PM_USE_SESSION_APIS
10 # include <PMCore.h>
11 # endif
12 # include <PMApplication.h>
13 # else
14 # include <Printing.h>
15 # endif
16 #endif
17
18 // since we have decided that we only support 8.6 upwards we are
19 // checking for these minimum requirements in the startup code of
20 // the application so all wxWindows code can safely assume that appearance 1.1
21 // windows manager, control manager, navigation services etc. are
22 // present
23
24 static bool sUMAHasAppearance = false ;
25 static long sUMAAppearanceVersion = 0 ;
26 static bool sUMAHasAquaLayout = false ;
27 static bool sUMASystemInitialized = false ;
28
29 extern int gAGABackgroundColor ;
30 bool UMAHasAppearance() { return sUMAHasAppearance ; }
31 long UMAGetAppearanceVersion() { return sUMAAppearanceVersion ; }
32
33 static bool sUMAHasWindowManager = false ;
34 static long sUMAWindowManagerAttr = 0 ;
35
36 bool UMAHasWindowManager() { return sUMAHasWindowManager ; }
37 long UMAGetWindowManagerAttr() { return sUMAWindowManagerAttr ; }
38 bool UMAHasAquaLayout() { return sUMAHasAquaLayout ; }
39 bool UMASystemIsInitialized() { return sUMASystemInitialized ; }
40
41 void UMACleanupToolbox()
42 {
43 if ( sUMAHasAppearance )
44 {
45 UnregisterAppearanceClient() ;
46 }
47 if ( NavServicesAvailable() )
48 {
49 NavUnload() ;
50 }
51 if ( TXNTerminateTextension != (void*) kUnresolvedCFragSymbolAddress )
52 TXNTerminateTextension( ) ;
53 }
54 void UMAInitToolbox( UInt16 inMoreMastersCalls )
55 {
56 #if !TARGET_CARBON
57 ::MaxApplZone();
58 for (long i = 1; i <= inMoreMastersCalls; i++)
59 ::MoreMasters();
60
61 ::InitGraf(&qd.thePort);
62 ::InitFonts();
63 ::InitMenus();
64 ::TEInit();
65 ::InitDialogs(0L);
66 ::FlushEvents(everyEvent, 0);
67 ::InitCursor();
68 long total,contig;
69 PurgeSpace(&total, &contig);
70 #else
71 InitCursor();
72 #endif
73
74 long theAppearance ;
75 if ( Gestalt( gestaltAppearanceAttr, &theAppearance ) == noErr )
76 {
77 sUMAHasAppearance = true ;
78 RegisterAppearanceClient();
79 if ( Gestalt( gestaltAppearanceVersion, &theAppearance ) == noErr )
80 {
81 sUMAAppearanceVersion = theAppearance ;
82 }
83 else
84 {
85 sUMAAppearanceVersion = 0x0100 ;
86 }
87 }
88 if ( Gestalt( gestaltWindowMgrAttr, &sUMAWindowManagerAttr ) == noErr )
89 {
90 sUMAHasWindowManager = sUMAWindowManagerAttr & gestaltWindowMgrPresent ;
91 }
92
93 #if TARGET_CARBON
94 // Call currently implicitely done : InitFloatingWindows() ;
95 #else
96 if ( sUMAHasWindowManager )
97 InitFloatingWindows() ;
98 else
99 InitWindows();
100 #endif
101
102 if ( NavServicesAvailable() )
103 {
104 NavLoad() ;
105 }
106
107 if ( TXNInitTextension != (void*) kUnresolvedCFragSymbolAddress )
108 {
109 FontFamilyID fontId ;
110 Str255 fontName ;
111 SInt16 fontSize ;
112 Style fontStyle ;
113 GetThemeFont(kThemeSmallSystemFont , GetApplicationScript() , fontName , &fontSize , &fontStyle ) ;
114 GetFNum( fontName, &fontId );
115
116 TXNMacOSPreferredFontDescription fontDescriptions[] =
117 {
118 { fontId , (fontSize << 16) ,kTXNDefaultFontStyle, kTXNSystemDefaultEncoding } ,
119 } ;
120 int noOfFontDescriptions = sizeof( fontDescriptions ) / sizeof(TXNMacOSPreferredFontDescription) ;
121 #if 0 // TARGET_CARBON
122 --noOfFontDescriptions ;
123 #endif
124 // kTXNAlwaysUseQuickDrawTextMask might be desirable because of speed increases but it crashes the app under OS X upon key stroke
125 OptionBits options = kTXNWantMoviesMask | kTXNWantSoundMask | kTXNWantGraphicsMask ;
126 #if TARGET_CARBON
127 if ( !UMAHasAquaLayout() )
128 #endif
129 {
130 options |= kTXNAlwaysUseQuickDrawTextMask ;
131 }
132 TXNInitTextension(fontDescriptions, noOfFontDescriptions, options );
133 }
134
135 long menuMgrAttr ;
136 Gestalt( gestaltMenuMgrAttr , &menuMgrAttr ) ;
137 if ( menuMgrAttr & gestaltMenuMgrAquaLayoutMask )
138 sUMAHasAquaLayout = true ;
139 sUMASystemInitialized = true ;
140
141 }
142
143 /*
144 Boolean CanUseATSUI()
145 {
146 long result;
147 OSErr err = Gestalt(gestaltATSUVersion, &result);
148 return (err == noErr);
149 }
150 */
151 // process manager
152 long UMAGetProcessMode()
153 {
154 OSErr err ;
155 ProcessInfoRec processinfo;
156 ProcessSerialNumber procno ;
157
158 procno.highLongOfPSN = NULL ;
159 procno.lowLongOfPSN = kCurrentProcess ;
160 processinfo.processInfoLength = sizeof(ProcessInfoRec);
161 processinfo.processName = NULL;
162 processinfo.processAppSpec = NULL;
163
164 err = ::GetProcessInformation( &procno , &processinfo ) ;
165 wxASSERT( err == noErr ) ;
166 return processinfo.processMode ;
167 }
168
169 bool UMAGetProcessModeDoesActivateOnFGSwitch()
170 {
171 return UMAGetProcessMode() & modeDoesActivateOnFGSwitch ;
172 }
173
174 // menu manager
175
176 void UMASetMenuTitle( MenuRef menu , StringPtr title )
177 {
178 /*
179 #if !TARGET_CARBON
180 long size = GetHandleSize( (Handle) menu ) ;
181 const long headersize = 14 ;
182 int oldlen = (**menu).menuData[0] + 1;
183 int newlen = title[0] + 1 ;
184
185 if ( oldlen < newlen )
186 {
187 // enlarge before adjusting
188 SetHandleSize( (Handle) menu , size + (newlen - oldlen ) );
189 }
190
191 if ( oldlen != newlen )
192 memmove( (char*) (**menu).menuData + newlen , (char*) (**menu).menuData + oldlen , size - headersize - oldlen ) ;
193
194 memcpy( (char*) (**menu).menuData , title , newlen ) ;
195 if ( oldlen > newlen )
196 {
197 // shrink after
198 SetHandleSize( (Handle) menu , size + (newlen - oldlen ) ) ;
199 }
200 #else
201 */
202 SetMenuTitle( menu , title ) ;
203 //#endif
204 }
205
206 UInt32 UMAMenuEvent( EventRecord *inEvent )
207 {
208 return MenuEvent( inEvent ) ;
209 }
210
211 void UMAEnableMenuItem( MenuRef inMenu , MenuItemIndex inItem )
212 {
213 EnableMenuItem( inMenu , inItem ) ;
214 }
215
216 void UMADisableMenuItem( MenuRef inMenu , MenuItemIndex inItem )
217 {
218 DisableMenuItem( inMenu , inItem ) ;
219 }
220
221 void UMAAppendSubMenuItem( MenuRef menu , StringPtr l , SInt16 id )
222 {
223 Str255 label ;
224 memcpy( label , l , l[0]+1 ) ;
225 // hardcoded adding of the submenu combination for mac
226
227 int theEnd = label[0] + 1;
228 if (theEnd > 251)
229 theEnd = 251; // mac allows only 255 characters
230 label[theEnd++] = '/';
231 label[theEnd++] = hMenuCmd;
232 label[theEnd++] = '!';
233 label[theEnd++] = id ;
234 label[theEnd] = 0x00;
235 label[0] = theEnd;
236 MacAppendMenu(menu, label);
237 }
238
239 void UMAInsertSubMenuItem( MenuRef menu , StringPtr l , MenuItemIndex item , SInt16 id )
240 {
241 Str255 label ;
242 memcpy( label , l , l[0]+1 ) ;
243 // hardcoded adding of the submenu combination for mac
244
245 int theEnd = label[0] + 1;
246 if (theEnd > 251)
247 theEnd = 251; // mac allows only 255 characters
248 label[theEnd++] = '/';
249 label[theEnd++] = hMenuCmd;
250 label[theEnd++] = '!';
251 label[theEnd++] = id;
252 label[theEnd] = 0x00;
253 label[0] = theEnd;
254 MacInsertMenuItem(menu, label , item);
255 }
256
257 void UMAAppendMenuItem( MenuRef menu , StringPtr l , SInt16 key, UInt8 modifiers )
258 {
259 Str255 label ;
260 memcpy( label , l , l[0]+1 ) ;
261 if ( key )
262 {
263 int pos = label[0] ;
264 label[++pos] = '/';
265 label[++pos] = toupper( key );
266 label[0] = pos ;
267 }
268 MacAppendMenu( menu , label ) ;
269 }
270
271 void UMAInsertMenuItem( MenuRef menu , StringPtr l , MenuItemIndex item , SInt16 key, UInt8 modifiers )
272 {
273 Str255 label ;
274 memcpy( label , l , l[0]+1 ) ;
275 if ( key )
276 {
277 int pos = label[0] ;
278 label[++pos] = '/';
279 label[++pos] = toupper( key );
280 label[0] = pos ;
281 }
282 MacInsertMenuItem( menu , label , item) ;
283 }
284
285 // quickdraw
286
287 int gPrOpenCounter = 0 ;
288
289 OSStatus UMAPrOpen(void *macPrintSession)
290 {
291 #if !TARGET_CARBON
292 OSErr err = noErr ;
293 ++gPrOpenCounter ;
294 if ( gPrOpenCounter == 1 )
295 {
296 PrOpen() ;
297 err = PrError() ;
298 wxASSERT( err == noErr ) ;
299 }
300 return err ;
301 #else
302 OSStatus err = noErr ;
303 ++gPrOpenCounter ;
304 if ( gPrOpenCounter == 1 )
305 {
306 #if PM_USE_SESSION_APIS
307 err = PMCreateSession((PMPrintSession *)macPrintSession) ;
308 #else
309 err = PMBegin() ;
310 #endif
311 wxASSERT( err == noErr ) ;
312 }
313 return err ;
314 #endif
315 }
316
317 OSStatus UMAPrClose(void *macPrintSession)
318 {
319 #if !TARGET_CARBON
320 OSErr err = noErr ;
321 wxASSERT( gPrOpenCounter >= 1 ) ;
322 if ( gPrOpenCounter == 1 )
323 {
324 PrClose() ;
325 err = PrError() ;
326 wxASSERT( err == noErr ) ;
327 }
328 --gPrOpenCounter ;
329 return err ;
330 #else
331 OSStatus err = noErr ;
332 wxASSERT( gPrOpenCounter >= 1 ) ;
333 if ( gPrOpenCounter == 1 )
334 {
335 #if PM_USE_SESSION_APIS
336 err = PMRelease(*(PMPrintSession *)macPrintSession) ;
337 *(PMPrintSession *)macPrintSession = kPMNoReference;
338 #else
339 err = PMEnd() ;
340 #endif
341 }
342 --gPrOpenCounter ;
343 return err ;
344 #endif
345 }
346
347 #if !TARGET_CARBON
348
349 pascal QDGlobalsPtr GetQDGlobalsPtr (void) ;
350 pascal QDGlobalsPtr GetQDGlobalsPtr (void)
351 {
352 return QDGlobalsPtr (* (Ptr*) LMGetCurrentA5 ( ) - 0xCA);
353 }
354
355 #endif
356
357 void UMAShowWatchCursor()
358 {
359 OSErr err = noErr;
360
361 CursHandle watchFob = GetCursor (watchCursor);
362
363 if (!watchFob)
364 err = nilHandleErr;
365 else
366 {
367 #if TARGET_CARBON
368 // Cursor preservedArrow;
369 // GetQDGlobalsArrow (&preservedArrow);
370 // SetQDGlobalsArrow (*watchFob);
371 // InitCursor ( );
372 // SetQDGlobalsArrow (&preservedArrow);
373 SetCursor (*watchFob);
374 #else
375 SetCursor (*watchFob);
376 #endif
377 }
378 }
379
380 void UMAShowArrowCursor()
381 {
382 #if TARGET_CARBON
383 Cursor arrow;
384 SetCursor (GetQDGlobalsArrow (&arrow));
385 #else
386 SetCursor (&(qd.arrow));
387 #endif
388 }
389
390 // window manager
391
392 GrafPtr UMAGetWindowPort( WindowRef inWindowRef )
393 {
394 wxASSERT( inWindowRef != NULL ) ;
395 #if TARGET_CARBON
396 return (GrafPtr) GetWindowPort( inWindowRef ) ;
397 #else
398 return (GrafPtr) inWindowRef ;
399 #endif
400 }
401
402 void UMADisposeWindow( WindowRef inWindowRef )
403 {
404 wxASSERT( inWindowRef != NULL ) ;
405 DisposeWindow( inWindowRef ) ;
406 }
407
408 void UMASetWTitleC( WindowRef inWindowRef , const char *title )
409 {
410 Str255 ptitle ;
411 strncpy( (char*)ptitle , title , 96 ) ;
412 ptitle[96] = 0 ;
413 #if TARGET_CARBON
414 c2pstrcpy( ptitle, (char *)ptitle ) ;
415 #else
416 c2pstr( (char*)ptitle ) ;
417 #endif
418 SetWTitle( inWindowRef , ptitle ) ;
419 }
420
421 void UMAGetWTitleC( WindowRef inWindowRef , char *title )
422 {
423 GetWTitle( inWindowRef , (unsigned char*)title ) ;
424 #if TARGET_CARBON
425 p2cstrcpy( title, (unsigned char *)title ) ;
426 #else
427 p2cstr( (unsigned char*)title ) ;
428 #endif
429 }
430
431 // appearance additions
432
433 void UMAActivateControl( ControlHandle inControl )
434 {
435 // we have to add the control after again to the update rgn
436 // otherwise updates get lost
437 if ( !IsControlActive( inControl ) )
438 {
439 bool visible = IsControlVisible( inControl ) ;
440 if ( visible )
441 SetControlVisibility( inControl , false , false ) ;
442 ::ActivateControl( inControl ) ;
443 if ( visible ) {
444 SetControlVisibility( inControl , true , false ) ;
445 Rect ctrlBounds ;
446 InvalWindowRect(GetControlOwner(inControl),GetControlBounds(inControl,&ctrlBounds) ) ;
447 }
448 }
449 }
450
451 void UMADrawControl( ControlHandle inControl )
452 {
453 WindowRef theWindow = GetControlOwner(inControl) ;
454 RgnHandle updateRgn = NewRgn() ;
455 GetWindowUpdateRgn( theWindow , updateRgn ) ;
456 Point zero = { 0 , 0 } ;
457 LocalToGlobal( &zero ) ;
458 OffsetRgn( updateRgn , -zero.h , -zero.v ) ;
459 ::DrawControlInCurrentPort( inControl ) ;
460 InvalWindowRgn( theWindow, updateRgn) ;
461 DisposeRgn( updateRgn ) ;
462 }
463
464 void UMAMoveControl( ControlHandle inControl , short x , short y )
465 {
466 bool visible = IsControlVisible( inControl ) ;
467 if ( visible ) {
468 SetControlVisibility( inControl , false , false ) ;
469 Rect ctrlBounds ;
470 InvalWindowRect(GetControlOwner(inControl),GetControlBounds(inControl,&ctrlBounds) ) ;
471 }
472 ::MoveControl( inControl , x , y ) ;
473 if ( visible ) {
474 SetControlVisibility( inControl , true , false ) ;
475 Rect ctrlBounds ;
476 InvalWindowRect(GetControlOwner(inControl),GetControlBounds(inControl,&ctrlBounds) ) ;
477 }
478 }
479
480 void UMASizeControl( ControlHandle inControl , short x , short y )
481 {
482 bool visible = IsControlVisible( inControl ) ;
483 if ( visible ) {
484 SetControlVisibility( inControl , false , false ) ;
485 Rect ctrlBounds ;
486 InvalWindowRect(GetControlOwner(inControl),GetControlBounds(inControl,&ctrlBounds) ) ;
487 }
488 ::SizeControl( inControl , x , y ) ;
489 if ( visible ) {
490 SetControlVisibility( inControl , true , false ) ;
491 Rect ctrlBounds ;
492 InvalWindowRect(GetControlOwner(inControl),GetControlBounds(inControl,&ctrlBounds) ) ;
493 }
494 }
495
496 void UMADeactivateControl( ControlHandle inControl )
497 {
498 // we have to add the control after again to the update rgn
499 // otherwise updates get lost
500 bool visible = IsControlVisible( inControl ) ;
501 if ( visible )
502 SetControlVisibility( inControl , false , false ) ;
503 ::DeactivateControl( inControl ) ;
504 if ( visible ) {
505 SetControlVisibility( inControl , true , false ) ;
506 Rect ctrlBounds ;
507 InvalWindowRect(GetControlOwner(inControl),GetControlBounds(inControl,&ctrlBounds) ) ;
508 }
509 }
510 // shows the control and adds the region to the update region
511 void UMAShowControl (ControlHandle inControl)
512 {
513 SetControlVisibility( inControl , true , false ) ;
514 Rect ctrlBounds ;
515 InvalWindowRect(GetControlOwner(inControl),GetControlBounds(inControl,&ctrlBounds) ) ;
516 }
517
518 // shows the control and adds the region to the update region
519 void UMAHideControl (ControlHandle inControl)
520 {
521 SetControlVisibility( inControl , false , false ) ;
522 Rect ctrlBounds ;
523 InvalWindowRect(GetControlOwner(inControl),GetControlBounds(inControl,&ctrlBounds) ) ;
524 }
525 // keyboard focus
526 OSErr UMASetKeyboardFocus (WindowPtr inWindow,
527 ControlHandle inControl,
528 ControlFocusPart inPart)
529 {
530 OSErr err = noErr;
531 GrafPtr port ;
532 GetPort( &port ) ;
533
534 SetPortWindowPort( inWindow ) ;
535
536 err = SetKeyboardFocus( inWindow , inControl , inPart ) ;
537 SetPort( port ) ;
538 return err ;
539 }
540
541
542
543
544 // events
545 void UMAUpdateControls( WindowPtr inWindow , RgnHandle inRgn )
546 {
547 RgnHandle updateRgn = NewRgn() ;
548 GetWindowUpdateRgn( inWindow , updateRgn ) ;
549
550 Point zero = { 0 , 0 } ;
551 LocalToGlobal( &zero ) ;
552 OffsetRgn( updateRgn , -zero.h , -zero.v ) ;
553
554 UpdateControls( inWindow , inRgn ) ;
555 InvalWindowRgn( inWindow, updateRgn) ;
556 DisposeRgn( updateRgn ) ;
557
558 }
559
560 bool UMAIsWindowFloating( WindowRef inWindow )
561 {
562 WindowClass cl ;
563
564 GetWindowClass( inWindow , &cl ) ;
565 return cl == kFloatingWindowClass ;
566 }
567
568 bool UMAIsWindowModal( WindowRef inWindow )
569 {
570 WindowClass cl ;
571
572 GetWindowClass( inWindow , &cl ) ;
573 return cl < kFloatingWindowClass ;
574 }
575
576 // others
577
578 void UMAHighlightAndActivateWindow( WindowRef inWindowRef , bool inActivate )
579 {
580 if ( inWindowRef )
581 {
582 // bool isHighlighted = IsWindowHighlited( inWindowRef ) ;
583 // if ( inActivate != isHightlited )
584 GrafPtr port ;
585 GetPort( &port ) ;
586 SetPortWindowPort( inWindowRef ) ;
587 HiliteWindow( inWindowRef , inActivate ) ;
588 ControlHandle control = NULL ;
589 ::GetRootControl( inWindowRef , & control ) ;
590 if ( control )
591 {
592 if ( inActivate )
593 UMAActivateControl( control ) ;
594 else
595 UMADeactivateControl( control ) ;
596 }
597 SetPort( port ) ;
598 }
599 }
600 OSStatus UMADrawThemePlacard( const Rect *inRect , ThemeDrawState inState )
601 {
602 return ::DrawThemePlacard( inRect , inState ) ;
603 }
604
605 #if !TARGET_CARBON
606 static OSStatus helpMenuStatus = noErr ;
607 static MenuItemIndex firstCustomItemIndex = 0 ;
608 #endif
609
610 OSStatus UMAGetHelpMenu(
611 MenuRef * outHelpMenu,
612 MenuItemIndex * outFirstCustomItemIndex)
613 {
614 #if TARGET_CARBON
615 return HMGetHelpMenu( outHelpMenu , outFirstCustomItemIndex ) ;
616 #else
617 MenuRef helpMenuHandle ;
618 helpMenuStatus = HMGetHelpMenuHandle( &helpMenuHandle ) ;
619 if ( firstCustomItemIndex == 0 && helpMenuStatus == noErr )
620 {
621 firstCustomItemIndex = CountMenuItems( helpMenuHandle ) + 1 ;
622 }
623 if ( outFirstCustomItemIndex )
624 {
625 *outFirstCustomItemIndex = firstCustomItemIndex ;
626 }
627 *outHelpMenu = helpMenuHandle ;
628 return helpMenuStatus ;
629 #endif
630 }
631
632 wxMacPortStateHelper::wxMacPortStateHelper( GrafPtr newport)
633 {
634 m_clip = NULL ;
635 Setup( newport ) ;
636 }
637
638 wxMacPortStateHelper::wxMacPortStateHelper()
639 {
640 m_clip = NULL ;
641 }
642
643 void wxMacPortStateHelper::Setup( GrafPtr newport )
644 {
645 GetPort( &m_oldPort ) ;
646 SetPort( newport ) ;
647 wxASSERT_MSG( m_clip == NULL , "Cannot call setup twice" ) ;
648 m_clip = NewRgn() ;
649 GetClip( m_clip );
650 m_textFont = GetPortTextFont( (CGrafPtr) newport);
651 m_textSize = GetPortTextSize( (CGrafPtr) newport);
652 m_textStyle = GetPortTextFace( (CGrafPtr) newport);
653 m_textMode = GetPortTextMode( (CGrafPtr) newport);
654 GetThemeDrawingState( &m_drawingState ) ;
655 m_currentPort = newport ;
656 }
657 void wxMacPortStateHelper::Clear()
658 {
659 if ( m_clip )
660 {
661 DisposeRgn( m_clip ) ;
662 DisposeThemeDrawingState( m_drawingState ) ;
663 m_clip = NULL ;
664 }
665 }
666
667 wxMacPortStateHelper::~wxMacPortStateHelper()
668 {
669 if ( m_clip )
670 {
671 SetPort( m_currentPort ) ;
672 SetClip( m_clip ) ;
673 DisposeRgn( m_clip ) ;
674 TextFont( m_textFont );
675 TextSize( m_textSize );
676 TextFace( m_textStyle );
677 TextMode( m_textMode );
678 SetThemeDrawingState( m_drawingState , true ) ;
679 SetPort( m_oldPort ) ;
680 }
681 }
682