]> git.saurik.com Git - wxWidgets.git/blob - src/mac/uma.cpp
native window disposal is moved to deferred delete, size of parent taken into account...
[wxWidgets.git] / src / mac / 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 TXNMacOSPreferredFontDescription defaults;
110 defaults.fontID = kFontIDGeneva ;
111 defaults.pointSize = (10 << 16) ;
112 defaults.fontStyle = kTXNDefaultFontStyle;
113 defaults.encoding = kTXNSystemDefaultEncoding;
114 TXNInitTextension(&defaults, 1, (kTXNAlwaysUseQuickDrawTextMask | kTXNWantMoviesMask | kTXNWantSoundMask | kTXNWantGraphicsMask));
115 }
116
117 long menuMgrAttr ;
118 Gestalt( gestaltMenuMgrAttr , &menuMgrAttr ) ;
119 if ( menuMgrAttr & gestaltMenuMgrAquaLayoutMask )
120 sUMAHasAquaLayout = true ;
121 sUMASystemInitialized = true ;
122
123 }
124
125 /*
126 Boolean CanUseATSUI()
127 {
128 long result;
129 OSErr err = Gestalt(gestaltATSUVersion, &result);
130 return (err == noErr);
131 }
132 */
133 // process manager
134 long UMAGetProcessMode()
135 {
136 OSErr err ;
137 ProcessInfoRec processinfo;
138 ProcessSerialNumber procno ;
139
140 procno.highLongOfPSN = NULL ;
141 procno.lowLongOfPSN = kCurrentProcess ;
142 processinfo.processInfoLength = sizeof(ProcessInfoRec);
143 processinfo.processName = NULL;
144 processinfo.processAppSpec = NULL;
145
146 err = ::GetProcessInformation( &procno , &processinfo ) ;
147 wxASSERT( err == noErr ) ;
148 return processinfo.processMode ;
149 }
150
151 bool UMAGetProcessModeDoesActivateOnFGSwitch()
152 {
153 return UMAGetProcessMode() & modeDoesActivateOnFGSwitch ;
154 }
155
156 // menu manager
157
158 void UMASetMenuTitle( MenuRef menu , StringPtr title )
159 {
160 /*
161 #if !TARGET_CARBON
162 long size = GetHandleSize( (Handle) menu ) ;
163 const long headersize = 14 ;
164 int oldlen = (**menu).menuData[0] + 1;
165 int newlen = title[0] + 1 ;
166
167 if ( oldlen < newlen )
168 {
169 // enlarge before adjusting
170 SetHandleSize( (Handle) menu , size + (newlen - oldlen ) );
171 }
172
173 if ( oldlen != newlen )
174 memmove( (char*) (**menu).menuData + newlen , (char*) (**menu).menuData + oldlen , size - headersize - oldlen ) ;
175
176 memcpy( (char*) (**menu).menuData , title , newlen ) ;
177 if ( oldlen > newlen )
178 {
179 // shrink after
180 SetHandleSize( (Handle) menu , size + (newlen - oldlen ) ) ;
181 }
182 #else
183 */
184 SetMenuTitle( menu , title ) ;
185 //#endif
186 }
187
188 UInt32 UMAMenuEvent( EventRecord *inEvent )
189 {
190 return MenuEvent( inEvent ) ;
191 }
192
193 void UMAEnableMenuItem( MenuRef inMenu , MenuItemIndex inItem )
194 {
195 EnableMenuItem( inMenu , inItem ) ;
196 }
197
198 void UMADisableMenuItem( MenuRef inMenu , MenuItemIndex inItem )
199 {
200 DisableMenuItem( inMenu , inItem ) ;
201 }
202
203 void UMAAppendSubMenuItem( MenuRef menu , StringPtr l , SInt16 id )
204 {
205 Str255 label ;
206 memcpy( label , l , l[0]+1 ) ;
207 // hardcoded adding of the submenu combination for mac
208
209 int theEnd = label[0] + 1;
210 if (theEnd > 251)
211 theEnd = 251; // mac allows only 255 characters
212 label[theEnd++] = '/';
213 label[theEnd++] = hMenuCmd;
214 label[theEnd++] = '!';
215 label[theEnd++] = id ;
216 label[theEnd] = 0x00;
217 label[0] = theEnd;
218 MacAppendMenu(menu, label);
219 }
220
221 void UMAInsertSubMenuItem( MenuRef menu , StringPtr l , MenuItemIndex item , 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 MacInsertMenuItem(menu, label , item);
237 }
238
239 void UMAAppendMenuItem( MenuRef menu , StringPtr l , SInt16 key, UInt8 modifiers )
240 {
241 Str255 label ;
242 memcpy( label , l , l[0]+1 ) ;
243 if ( key )
244 {
245 int pos = label[0] ;
246 label[++pos] = '/';
247 label[++pos] = toupper( key );
248 label[0] = pos ;
249 }
250 MacAppendMenu( menu , label ) ;
251 }
252
253 void UMAInsertMenuItem( MenuRef menu , StringPtr l , MenuItemIndex item , SInt16 key, UInt8 modifiers )
254 {
255 Str255 label ;
256 memcpy( label , l , l[0]+1 ) ;
257 if ( key )
258 {
259 int pos = label[0] ;
260 label[++pos] = '/';
261 label[++pos] = toupper( key );
262 label[0] = pos ;
263 }
264 MacInsertMenuItem( menu , label , item) ;
265 }
266
267 // quickdraw
268
269 int gPrOpenCounter = 0 ;
270
271 OSStatus UMAPrOpen(void *macPrintSession)
272 {
273 #if !TARGET_CARBON
274 OSErr err = noErr ;
275 ++gPrOpenCounter ;
276 if ( gPrOpenCounter == 1 )
277 {
278 PrOpen() ;
279 err = PrError() ;
280 wxASSERT( err == noErr ) ;
281 }
282 return err ;
283 #else
284 OSStatus err = noErr ;
285 ++gPrOpenCounter ;
286 if ( gPrOpenCounter == 1 )
287 {
288 #if PM_USE_SESSION_APIS
289 err = PMCreateSession((PMPrintSession *)macPrintSession) ;
290 #else
291 err = PMBegin() ;
292 #endif
293 wxASSERT( err == noErr ) ;
294 }
295 return err ;
296 #endif
297 }
298
299 OSStatus UMAPrClose(void *macPrintSession)
300 {
301 #if !TARGET_CARBON
302 OSErr err = noErr ;
303 wxASSERT( gPrOpenCounter >= 1 ) ;
304 if ( gPrOpenCounter == 1 )
305 {
306 PrClose() ;
307 err = PrError() ;
308 wxASSERT( err == noErr ) ;
309 }
310 --gPrOpenCounter ;
311 return err ;
312 #else
313 OSStatus err = noErr ;
314 wxASSERT( gPrOpenCounter >= 1 ) ;
315 if ( gPrOpenCounter == 1 )
316 {
317 #if PM_USE_SESSION_APIS
318 err = PMRelease(*(PMPrintSession *)macPrintSession) ;
319 *(PMPrintSession *)macPrintSession = kPMNoReference;
320 #else
321 err = PMEnd() ;
322 #endif
323 }
324 --gPrOpenCounter ;
325 return err ;
326 #endif
327 }
328
329 #if !TARGET_CARBON
330
331 pascal QDGlobalsPtr GetQDGlobalsPtr (void) ;
332 pascal QDGlobalsPtr GetQDGlobalsPtr (void)
333 {
334 return QDGlobalsPtr (* (Ptr*) LMGetCurrentA5 ( ) - 0xCA);
335 }
336
337 #endif
338
339 void UMAShowWatchCursor()
340 {
341 OSErr err = noErr;
342
343 CursHandle watchFob = GetCursor (watchCursor);
344
345 if (!watchFob)
346 err = nilHandleErr;
347 else
348 {
349 #if TARGET_CARBON
350 // Cursor preservedArrow;
351 // GetQDGlobalsArrow (&preservedArrow);
352 // SetQDGlobalsArrow (*watchFob);
353 // InitCursor ( );
354 // SetQDGlobalsArrow (&preservedArrow);
355 SetCursor (*watchFob);
356 #else
357 SetCursor (*watchFob);
358 #endif
359 }
360 }
361
362 void UMAShowArrowCursor()
363 {
364 #if TARGET_CARBON
365 Cursor arrow;
366 SetCursor (GetQDGlobalsArrow (&arrow));
367 #else
368 SetCursor (&(qd.arrow));
369 #endif
370 }
371
372 // window manager
373
374 GrafPtr UMAGetWindowPort( WindowRef inWindowRef )
375 {
376 wxASSERT( inWindowRef != NULL ) ;
377 #if TARGET_CARBON
378 return (GrafPtr) GetWindowPort( inWindowRef ) ;
379 #else
380 return (GrafPtr) inWindowRef ;
381 #endif
382 }
383
384 void UMADisposeWindow( WindowRef inWindowRef )
385 {
386 wxASSERT( inWindowRef != NULL ) ;
387 DisposeWindow( inWindowRef ) ;
388 }
389
390 void UMASetWTitleC( WindowRef inWindowRef , const char *title )
391 {
392 Str255 ptitle ;
393 strncpy( (char*)ptitle , title , 96 ) ;
394 ptitle[96] = 0 ;
395 #if TARGET_CARBON
396 c2pstrcpy( ptitle, (char *)ptitle ) ;
397 #else
398 c2pstr( (char*)ptitle ) ;
399 #endif
400 SetWTitle( inWindowRef , ptitle ) ;
401 }
402
403 void UMAGetWTitleC( WindowRef inWindowRef , char *title )
404 {
405 GetWTitle( inWindowRef , (unsigned char*)title ) ;
406 #if TARGET_CARBON
407 p2cstrcpy( title, (unsigned char *)title ) ;
408 #else
409 p2cstr( (unsigned char*)title ) ;
410 #endif
411 }
412
413 // appearance additions
414
415 void UMAActivateControl( ControlHandle inControl )
416 {
417 // we have to add the control after again to the update rgn
418 // otherwise updates get lost
419 if ( !IsControlActive( inControl ) )
420 {
421 bool visible = IsControlVisible( inControl ) ;
422 if ( visible )
423 SetControlVisibility( inControl , false , false ) ;
424 ::ActivateControl( inControl ) ;
425 if ( visible ) {
426 SetControlVisibility( inControl , true , false ) ;
427 Rect ctrlBounds ;
428 InvalWindowRect(GetControlOwner(inControl),GetControlBounds(inControl,&ctrlBounds) ) ;
429 }
430 }
431 }
432
433 void UMADrawControl( ControlHandle inControl )
434 {
435 WindowRef theWindow = GetControlOwner(inControl) ;
436 RgnHandle updateRgn = NewRgn() ;
437 GetWindowUpdateRgn( theWindow , updateRgn ) ;
438 Point zero = { 0 , 0 } ;
439 LocalToGlobal( &zero ) ;
440 OffsetRgn( updateRgn , -zero.h , -zero.v ) ;
441 ::DrawControlInCurrentPort( inControl ) ;
442 InvalWindowRgn( theWindow, updateRgn) ;
443 DisposeRgn( updateRgn ) ;
444 }
445
446 void UMAMoveControl( ControlHandle inControl , short x , short y )
447 {
448 bool visible = IsControlVisible( inControl ) ;
449 if ( visible ) {
450 SetControlVisibility( inControl , false , false ) ;
451 Rect ctrlBounds ;
452 InvalWindowRect(GetControlOwner(inControl),GetControlBounds(inControl,&ctrlBounds) ) ;
453 }
454 ::MoveControl( inControl , x , y ) ;
455 if ( visible ) {
456 SetControlVisibility( inControl , true , false ) ;
457 Rect ctrlBounds ;
458 InvalWindowRect(GetControlOwner(inControl),GetControlBounds(inControl,&ctrlBounds) ) ;
459 }
460 }
461
462 void UMASizeControl( ControlHandle inControl , short x , short y )
463 {
464 bool visible = IsControlVisible( inControl ) ;
465 if ( visible ) {
466 SetControlVisibility( inControl , false , false ) ;
467 Rect ctrlBounds ;
468 InvalWindowRect(GetControlOwner(inControl),GetControlBounds(inControl,&ctrlBounds) ) ;
469 }
470 ::SizeControl( inControl , x , y ) ;
471 if ( visible ) {
472 SetControlVisibility( inControl , true , false ) ;
473 Rect ctrlBounds ;
474 InvalWindowRect(GetControlOwner(inControl),GetControlBounds(inControl,&ctrlBounds) ) ;
475 }
476 }
477
478 void UMADeactivateControl( ControlHandle inControl )
479 {
480 // we have to add the control after again to the update rgn
481 // otherwise updates get lost
482 bool visible = IsControlVisible( inControl ) ;
483 if ( visible )
484 SetControlVisibility( inControl , false , false ) ;
485 ::DeactivateControl( inControl ) ;
486 if ( visible ) {
487 SetControlVisibility( inControl , true , false ) ;
488 Rect ctrlBounds ;
489 InvalWindowRect(GetControlOwner(inControl),GetControlBounds(inControl,&ctrlBounds) ) ;
490 }
491 }
492 // shows the control and adds the region to the update region
493 void UMAShowControl (ControlHandle inControl)
494 {
495 SetControlVisibility( inControl , true , false ) ;
496 Rect ctrlBounds ;
497 InvalWindowRect(GetControlOwner(inControl),GetControlBounds(inControl,&ctrlBounds) ) ;
498 }
499
500 // shows the control and adds the region to the update region
501 void UMAHideControl (ControlHandle inControl)
502 {
503 SetControlVisibility( inControl , false , false ) ;
504 Rect ctrlBounds ;
505 InvalWindowRect(GetControlOwner(inControl),GetControlBounds(inControl,&ctrlBounds) ) ;
506 }
507 // keyboard focus
508 OSErr UMASetKeyboardFocus (WindowPtr inWindow,
509 ControlHandle inControl,
510 ControlFocusPart inPart)
511 {
512 OSErr err = noErr;
513 GrafPtr port ;
514 GetPort( &port ) ;
515
516 SetPortWindowPort( inWindow ) ;
517
518 err = SetKeyboardFocus( inWindow , inControl , inPart ) ;
519 SetPort( port ) ;
520 return err ;
521 }
522
523
524
525
526 // events
527 void UMAUpdateControls( WindowPtr inWindow , RgnHandle inRgn )
528 {
529 RgnHandle updateRgn = NewRgn() ;
530 GetWindowUpdateRgn( inWindow , updateRgn ) ;
531
532 Point zero = { 0 , 0 } ;
533 LocalToGlobal( &zero ) ;
534 OffsetRgn( updateRgn , -zero.h , -zero.v ) ;
535
536 UpdateControls( inWindow , inRgn ) ;
537 InvalWindowRgn( inWindow, updateRgn) ;
538 DisposeRgn( updateRgn ) ;
539
540 }
541
542 bool UMAIsWindowFloating( WindowRef inWindow )
543 {
544 WindowClass cl ;
545
546 GetWindowClass( inWindow , &cl ) ;
547 return cl == kFloatingWindowClass ;
548 }
549
550 bool UMAIsWindowModal( WindowRef inWindow )
551 {
552 WindowClass cl ;
553
554 GetWindowClass( inWindow , &cl ) ;
555 return cl < kFloatingWindowClass ;
556 }
557
558 // others
559
560 void UMAHighlightAndActivateWindow( WindowRef inWindowRef , bool inActivate )
561 {
562 if ( inWindowRef )
563 {
564 // bool isHighlighted = IsWindowHighlited( inWindowRef ) ;
565 // if ( inActivate != isHightlited )
566 GrafPtr port ;
567 GetPort( &port ) ;
568 SetPortWindowPort( inWindowRef ) ;
569 HiliteWindow( inWindowRef , inActivate ) ;
570 ControlHandle control = NULL ;
571 ::GetRootControl( inWindowRef , & control ) ;
572 if ( control )
573 {
574 if ( inActivate )
575 UMAActivateControl( control ) ;
576 else
577 UMADeactivateControl( control ) ;
578 }
579 SetPort( port ) ;
580 }
581 }
582 OSStatus UMADrawThemePlacard( const Rect *inRect , ThemeDrawState inState )
583 {
584 return ::DrawThemePlacard( inRect , inState ) ;
585 }
586
587 #if !TARGET_CARBON
588 static OSStatus helpMenuStatus = noErr ;
589 static MenuItemIndex firstCustomItemIndex = 0 ;
590 #endif
591
592 OSStatus UMAGetHelpMenu(
593 MenuRef * outHelpMenu,
594 MenuItemIndex * outFirstCustomItemIndex)
595 {
596 #if TARGET_CARBON
597 return HMGetHelpMenu( outHelpMenu , outFirstCustomItemIndex ) ;
598 #else
599 MenuRef helpMenuHandle ;
600 helpMenuStatus = HMGetHelpMenuHandle( &helpMenuHandle ) ;
601 if ( firstCustomItemIndex == 0 && helpMenuStatus == noErr )
602 {
603 firstCustomItemIndex = CountMenuItems( helpMenuHandle ) + 1 ;
604 }
605 if ( outFirstCustomItemIndex )
606 {
607 *outFirstCustomItemIndex = firstCustomItemIndex ;
608 }
609 *outHelpMenu = helpMenuHandle ;
610 return helpMenuStatus ;
611 #endif
612 }
613
614 wxMacPortStateHelper::wxMacPortStateHelper( GrafPtr newport)
615 {
616 m_clip = NULL ;
617 Setup( newport ) ;
618 }
619
620 wxMacPortStateHelper::wxMacPortStateHelper()
621 {
622 m_clip = NULL ;
623 }
624
625 void wxMacPortStateHelper::Setup( GrafPtr newport )
626 {
627 GetPort( &m_oldPort ) ;
628 SetPort( newport ) ;
629 wxASSERT_MSG( m_clip == NULL , "Cannot call setup twice" ) ;
630 m_clip = NewRgn() ;
631 GetClip( m_clip );
632 m_textFont = GetPortTextFont( (CGrafPtr) newport);
633 m_textSize = GetPortTextSize( (CGrafPtr) newport);
634 m_textStyle = GetPortTextFace( (CGrafPtr) newport);
635 m_textMode = GetPortTextMode( (CGrafPtr) newport);
636 GetThemeDrawingState( &m_drawingState ) ;
637 m_currentPort = newport ;
638 }
639 void wxMacPortStateHelper::Clear()
640 {
641 if ( m_clip )
642 {
643 DisposeRgn( m_clip ) ;
644 DisposeThemeDrawingState( m_drawingState ) ;
645 m_clip = NULL ;
646 }
647 }
648
649 wxMacPortStateHelper::~wxMacPortStateHelper()
650 {
651 if ( m_clip )
652 {
653 SetPort( m_currentPort ) ;
654 SetClip( m_clip ) ;
655 DisposeRgn( m_clip ) ;
656 TextFont( m_textFont );
657 TextSize( m_textSize );
658 TextFace( m_textStyle );
659 TextMode( m_textMode );
660 SetThemeDrawingState( m_drawingState , true ) ;
661 SetPort( m_oldPort ) ;
662 }
663 }
664