]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/toplevel.cpp
bdcba53822524bd705874b87880580466a7b8a0b
[wxWidgets.git] / src / mac / carbon / toplevel.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/mac/carbon/toplevel.cpp
3 // Purpose: implements wxTopLevelWindow for Mac
4 // Author: Stefan Csomor
5 // Modified by:
6 // Created: 24.09.01
7 // RCS-ID: $Id$
8 // Copyright: (c) 2001-2004 Stefan Csomor
9 // License: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22
23 #ifdef __BORLANDC__
24 #pragma hdrstop
25 #endif
26
27 #ifndef WX_PRECOMP
28 #include "wx/app.h"
29 #include "wx/toplevel.h"
30 #include "wx/frame.h"
31 #include "wx/string.h"
32 #include "wx/log.h"
33 #include "wx/intl.h"
34 #include "wx/settings.h"
35 #include "wx/strconv.h"
36 #include "wx/control.h"
37 #endif //WX_PRECOMP
38
39 #include "wx/mac/uma.h"
40 #include "wx/mac/aga.h"
41 #include "wx/app.h"
42 #include "wx/tooltip.h"
43 #include "wx/dnd.h"
44
45 #if wxUSE_SYSTEM_OPTIONS
46 #include "wx/sysopt.h"
47 #endif
48
49 #ifndef __DARWIN__
50 #include <ToolUtils.h>
51 #endif
52
53 // for targeting OSX
54 #include "wx/mac/private.h"
55
56 // ----------------------------------------------------------------------------
57 // constants
58 // ----------------------------------------------------------------------------
59
60 // trace mask for activation tracing messages
61 static const wxChar *TRACE_ACTIVATE = _T("activation");
62
63 // ----------------------------------------------------------------------------
64 // globals
65 // ----------------------------------------------------------------------------
66
67 // list of all frames and modeless dialogs
68 wxWindowList wxModelessWindows;
69
70 static pascal long wxShapedMacWindowDef(short varCode, WindowRef window, SInt16 message, SInt32 param);
71
72 // ============================================================================
73 // wxTopLevelWindowMac implementation
74 // ============================================================================
75
76 BEGIN_EVENT_TABLE(wxTopLevelWindowMac, wxTopLevelWindowBase)
77 END_EVENT_TABLE()
78
79
80 // ---------------------------------------------------------------------------
81 // Carbon Events
82 // ---------------------------------------------------------------------------
83
84 extern long wxMacTranslateKey(unsigned char key, unsigned char code) ;
85
86 static const EventTypeSpec eventList[] =
87 {
88 // TODO: remove control related event like key and mouse (except for WindowLeave events)
89 #if 1
90 { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent } ,
91
92 { kEventClassKeyboard, kEventRawKeyDown } ,
93 { kEventClassKeyboard, kEventRawKeyRepeat } ,
94 { kEventClassKeyboard, kEventRawKeyUp } ,
95 { kEventClassKeyboard, kEventRawKeyModifiersChanged } ,
96 #endif
97
98 { kEventClassWindow , kEventWindowShown } ,
99 { kEventClassWindow , kEventWindowActivated } ,
100 { kEventClassWindow , kEventWindowDeactivated } ,
101 { kEventClassWindow , kEventWindowBoundsChanging } ,
102 { kEventClassWindow , kEventWindowBoundsChanged } ,
103 { kEventClassWindow , kEventWindowClose } ,
104
105 // we have to catch these events on the toplevel window level,
106 // as controls don't get the raw mouse events anymore
107
108 { kEventClassMouse , kEventMouseDown } ,
109 { kEventClassMouse , kEventMouseUp } ,
110 { kEventClassMouse , kEventMouseWheelMoved } ,
111 { kEventClassMouse , kEventMouseMoved } ,
112 { kEventClassMouse , kEventMouseDragged } ,
113 } ;
114
115 static pascal OSStatus TextInputEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
116 {
117 OSStatus result = eventNotHandledErr ;
118 wxWindow* focus ;
119 UInt32 keyCode, modifiers ;
120 Point point ;
121 EventRef rawEvent ;
122 unsigned char charCode ;
123
124 GetEventParameter( event, kEventParamTextInputSendKeyboardEvent, typeEventRef, NULL, sizeof(rawEvent), NULL, &rawEvent ) ;
125
126 GetEventParameter( rawEvent, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &charCode );
127 GetEventParameter( rawEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode );
128 GetEventParameter( rawEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers );
129 GetEventParameter( rawEvent, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &point );
130
131 focus = wxWindow::FindFocus() ;
132
133 switch ( GetEventKind( event ) )
134 {
135 case kEventTextInputUnicodeForKeyEvent :
136 // this is only called when no default handler has jumped in, e.g. a wxControl on a floater window does not
137 // get its own kEventTextInputUnicodeForKeyEvent, so we reroute the event back to the control
138 wxControl* control = wxDynamicCast( focus , wxControl ) ;
139 if ( control )
140 {
141 ControlRef macControl = (ControlRef) control->GetHandle() ;
142 if ( macControl )
143 {
144 ::HandleControlKey( macControl , keyCode , charCode , modifiers ) ;
145 result = noErr ;
146 }
147 }
148
149 #if 0
150 // this may lead to double events sent to a window in case all handlers have skipped the key down event
151 UInt32 when = EventTimeToTicks( GetEventTime( event ) ) ;
152 UInt32 message = (keyCode << 8) + charCode;
153
154 if ( (focus != NULL) &&
155 wxTheApp->MacSendKeyDownEvent( focus , message , modifiers , when , point.h , point.v ) )
156 {
157 result = noErr ;
158 }
159 #endif
160 break ;
161
162 default:
163 break ;
164 }
165
166 return result ;
167 }
168
169 static pascal OSStatus KeyboardEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
170 {
171 OSStatus result = eventNotHandledErr ;
172 // call DoFindFocus instead of FindFocus, because for Composite Windows(like WxGenericListCtrl)
173 // FindFocus does not return the actual focus window, but the enclosing window
174 wxWindow* focus = wxWindow::DoFindFocus();
175 if ( focus == NULL )
176 focus = (wxTopLevelWindowMac*) data ;
177
178 unsigned char charCode ;
179 wxChar uniChar = 0 ;
180 UInt32 keyCode ;
181 UInt32 modifiers ;
182 Point point ;
183 UInt32 when = EventTimeToTicks( GetEventTime( event ) ) ;
184
185 #if wxUSE_UNICODE
186 UInt32 dataSize = 0 ;
187 if ( GetEventParameter( event, kEventParamKeyUnicodes, typeUnicodeText, NULL, 0 , &dataSize, NULL ) == noErr )
188 {
189 UniChar buf[2] ;
190
191 UniChar* charBuf = buf ;
192
193 if ( dataSize > 4 )
194 charBuf = new UniChar[ dataSize / sizeof( UniChar) ] ;
195 GetEventParameter( event, kEventParamKeyUnicodes, typeUnicodeText, NULL, dataSize , NULL , charBuf ) ;
196
197 #if SIZEOF_WCHAR_T == 2
198 uniChar = charBuf[0] ;
199 #else
200 wxMBConvUTF16 converter ;
201 converter.MB2WC( &uniChar , (const char*)charBuf , 1 ) ;
202 #endif
203
204 if ( dataSize > 4 )
205 delete[] charBuf ;
206 }
207 #endif
208
209 GetEventParameter( event, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &charCode );
210 GetEventParameter( event, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode );
211 GetEventParameter( event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers );
212 GetEventParameter( event, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &point );
213
214 UInt32 message = (keyCode << 8) + charCode;
215 switch ( GetEventKind( event ) )
216 {
217 case kEventRawKeyRepeat :
218 case kEventRawKeyDown :
219 {
220 WXEVENTREF formerEvent = wxTheApp->MacGetCurrentEvent() ;
221 WXEVENTHANDLERCALLREF formerHandler = wxTheApp->MacGetCurrentEventHandlerCallRef() ;
222 wxTheApp->MacSetCurrentEvent( event , handler ) ;
223 if ( /* focus && */ wxTheApp->MacSendKeyDownEvent(
224 focus , message , modifiers , when , point.h , point.v , uniChar ) )
225 {
226 result = noErr ;
227 }
228 wxTheApp->MacSetCurrentEvent( formerEvent , formerHandler ) ;
229 }
230 break ;
231
232 case kEventRawKeyUp :
233 if ( /* focus && */ wxTheApp->MacSendKeyUpEvent(
234 focus , message , modifiers , when , point.h , point.v , uniChar ) )
235 {
236 result = noErr ;
237 }
238 break ;
239
240 case kEventRawKeyModifiersChanged :
241 {
242 wxKeyEvent event(wxEVT_KEY_DOWN);
243
244 event.m_shiftDown = modifiers & shiftKey;
245 event.m_controlDown = modifiers & controlKey;
246 event.m_altDown = modifiers & optionKey;
247 event.m_metaDown = modifiers & cmdKey;
248 event.m_x = point.h;
249 event.m_y = point.v;
250
251 #if wxUSE_UNICODE
252 event.m_uniChar = uniChar ;
253 #endif
254
255 event.SetTimestamp(when);
256 event.SetEventObject(focus);
257
258 if ( /* focus && */ (modifiers ^ wxApp::s_lastModifiers ) & controlKey )
259 {
260 event.m_keyCode = WXK_CONTROL ;
261 event.SetEventType( ( modifiers & controlKey ) ? wxEVT_KEY_DOWN : wxEVT_KEY_UP ) ;
262 focus->GetEventHandler()->ProcessEvent( event ) ;
263 }
264 if ( /* focus && */ (modifiers ^ wxApp::s_lastModifiers ) & shiftKey )
265 {
266 event.m_keyCode = WXK_SHIFT ;
267 event.SetEventType( ( modifiers & shiftKey ) ? wxEVT_KEY_DOWN : wxEVT_KEY_UP ) ;
268 focus->GetEventHandler()->ProcessEvent( event ) ;
269 }
270 if ( /* focus && */ (modifiers ^ wxApp::s_lastModifiers ) & optionKey )
271 {
272 event.m_keyCode = WXK_ALT ;
273 event.SetEventType( ( modifiers & optionKey ) ? wxEVT_KEY_DOWN : wxEVT_KEY_UP ) ;
274 focus->GetEventHandler()->ProcessEvent( event ) ;
275 }
276 if ( /* focus && */ (modifiers ^ wxApp::s_lastModifiers ) & cmdKey )
277 {
278 event.m_keyCode = WXK_COMMAND ;
279 event.SetEventType( ( modifiers & cmdKey ) ? wxEVT_KEY_DOWN : wxEVT_KEY_UP ) ;
280 focus->GetEventHandler()->ProcessEvent( event ) ;
281 }
282
283 wxApp::s_lastModifiers = modifiers ;
284 }
285 break ;
286
287 default:
288 break;
289 }
290
291 return result ;
292 }
293
294 // we don't interfere with foreign controls on our toplevel windows, therefore we always give back eventNotHandledErr
295 // for windows that we didn't create (like eg Scrollbars in a databrowser), or for controls where we did not handle the
296 // mouse down at all
297 //
298 // This handler can also be called from app level where data (ie target window) may be null or a non wx window
299
300 wxWindow* g_MacLastWindow = NULL ;
301
302 static EventMouseButton lastButton = 0 ;
303
304 static void SetupMouseEvent( wxMouseEvent &wxevent , wxMacCarbonEvent &cEvent )
305 {
306 UInt32 modifiers = cEvent.GetParameter<UInt32>(kEventParamKeyModifiers, typeUInt32) ;
307 Point screenMouseLocation = cEvent.GetParameter<Point>(kEventParamMouseLocation) ;
308
309 // this parameter are not given for all events
310 EventMouseButton button = 0 ;
311 UInt32 clickCount = 0 ;
312 cEvent.GetParameter<EventMouseButton>( kEventParamMouseButton, typeMouseButton , &button ) ;
313 cEvent.GetParameter<UInt32>( kEventParamClickCount, typeUInt32 , &clickCount ) ;
314
315 wxevent.m_x = screenMouseLocation.h;
316 wxevent.m_y = screenMouseLocation.v;
317 wxevent.m_shiftDown = modifiers & shiftKey;
318 wxevent.m_controlDown = modifiers & controlKey;
319 wxevent.m_altDown = modifiers & optionKey;
320 wxevent.m_metaDown = modifiers & cmdKey;
321 wxevent.SetTimestamp( cEvent.GetTicks() ) ;
322
323 // a control click is interpreted as a right click
324 if ( button == kEventMouseButtonPrimary && (modifiers & controlKey) )
325 button = kEventMouseButtonSecondary ;
326
327 // otherwise we report double clicks by connecting a left click with a ctrl-left click
328 if ( clickCount > 1 && button != lastButton )
329 clickCount = 1 ;
330
331 // we must make sure that our synthetic 'right' button corresponds in
332 // mouse down, moved and mouse up, and does not deliver a right down and left up
333
334 if ( cEvent.GetKind() == kEventMouseDown )
335 lastButton = button ;
336
337 if ( button == 0 )
338 lastButton = 0 ;
339 else if ( lastButton )
340 button = lastButton ;
341
342 // determine the correct down state, wx does not want a 'down' for a mouseUp event,
343 // while mac delivers this button
344 if ( button != 0 && cEvent.GetKind() != kEventMouseUp )
345 {
346 switch ( button )
347 {
348 case kEventMouseButtonPrimary :
349 wxevent.m_leftDown = true ;
350 break ;
351
352 case kEventMouseButtonSecondary :
353 wxevent.m_rightDown = true ;
354 break ;
355
356 case kEventMouseButtonTertiary :
357 wxevent.m_middleDown = true ;
358 break ;
359
360 default:
361 break ;
362 }
363 }
364
365 // translate into wx types
366 switch ( cEvent.GetKind() )
367 {
368 case kEventMouseDown :
369 switch ( button )
370 {
371 case kEventMouseButtonPrimary :
372 wxevent.SetEventType( clickCount > 1 ? wxEVT_LEFT_DCLICK : wxEVT_LEFT_DOWN ) ;
373 break ;
374
375 case kEventMouseButtonSecondary :
376 wxevent.SetEventType( clickCount > 1 ? wxEVT_RIGHT_DCLICK : wxEVT_RIGHT_DOWN ) ;
377 break ;
378
379 case kEventMouseButtonTertiary :
380 wxevent.SetEventType( clickCount > 1 ? wxEVT_MIDDLE_DCLICK : wxEVT_MIDDLE_DOWN ) ;
381 break ;
382
383 default:
384 break ;
385 }
386 break ;
387
388 case kEventMouseUp :
389 switch ( button )
390 {
391 case kEventMouseButtonPrimary :
392 wxevent.SetEventType( wxEVT_LEFT_UP ) ;
393 break ;
394
395 case kEventMouseButtonSecondary :
396 wxevent.SetEventType( wxEVT_RIGHT_UP ) ;
397 break ;
398
399 case kEventMouseButtonTertiary :
400 wxevent.SetEventType( wxEVT_MIDDLE_UP ) ;
401 break ;
402
403 default:
404 break ;
405 }
406 break ;
407
408 case kEventMouseWheelMoved :
409 {
410 wxevent.SetEventType( wxEVT_MOUSEWHEEL ) ;
411
412 // EventMouseWheelAxis axis = cEvent.GetParameter<EventMouseWheelAxis>(kEventParamMouseWheelAxis, typeMouseWheelAxis) ;
413 SInt32 delta = cEvent.GetParameter<SInt32>(kEventParamMouseWheelDelta, typeLongInteger) ;
414
415 wxevent.m_wheelRotation = delta;
416 wxevent.m_wheelDelta = 1;
417 wxevent.m_linesPerAction = 1;
418 }
419 break ;
420
421 default :
422 wxevent.SetEventType( wxEVT_MOTION ) ;
423 break ;
424 }
425 }
426
427 ControlRef wxMacFindSubControl( wxTopLevelWindowMac* toplevelWindow, const Point& location , ControlRef superControl , ControlPartCode *outPart )
428 {
429 if ( superControl )
430 {
431 UInt16 childrenCount = 0 ;
432 ControlHandle sibling ;
433 Rect r ;
434 OSStatus err = CountSubControls( superControl , &childrenCount ) ;
435 if ( err == errControlIsNotEmbedder )
436 return NULL ;
437
438 wxASSERT_MSG( err == noErr , wxT("Unexpected error when accessing subcontrols") ) ;
439
440 for ( UInt16 i = childrenCount ; i >=1 ; --i )
441 {
442 err = GetIndexedSubControl( superControl , i , & sibling ) ;
443 if ( err == errControlIsNotEmbedder )
444 return NULL ;
445
446 wxASSERT_MSG( err == noErr , wxT("Unexpected error when accessing subcontrols") ) ;
447 if ( IsControlVisible( sibling ) )
448 {
449 UMAGetControlBoundsInWindowCoords( sibling , &r ) ;
450 if ( MacPtInRect( location , &r ) )
451 {
452 ControlHandle child = wxMacFindSubControl( toplevelWindow , location , sibling , outPart ) ;
453 if ( child )
454 {
455 return child ;
456 }
457 else
458 {
459 Point testLocation = location ;
460
461 if ( toplevelWindow && toplevelWindow->MacUsesCompositing() )
462 {
463 testLocation.h -= r.left ;
464 testLocation.v -= r.top ;
465 }
466
467 *outPart = TestControl( sibling , testLocation ) ;
468
469 return sibling ;
470 }
471 }
472 }
473 }
474 }
475
476 return NULL ;
477 }
478
479 ControlRef wxMacFindControlUnderMouse( wxTopLevelWindowMac* toplevelWindow , const Point& location , WindowRef window , ControlPartCode *outPart )
480 {
481 #if TARGET_API_MAC_OSX
482 if ( UMAGetSystemVersion() >= 0x1030 && ( toplevelWindow == 0 || toplevelWindow->MacUsesCompositing() ) )
483 return FindControlUnderMouse( location , window , outPart ) ;
484 #endif
485
486 ControlRef rootControl = NULL ;
487 verify_noerr( GetRootControl( window , &rootControl ) ) ;
488
489 return wxMacFindSubControl( toplevelWindow , location , rootControl , outPart ) ;
490 }
491
492 #define NEW_CAPTURE_HANDLING 1
493
494 pascal OSStatus wxMacTopLevelMouseEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
495 {
496 wxTopLevelWindowMac* toplevelWindow = (wxTopLevelWindowMac*) data ;
497
498 OSStatus result = eventNotHandledErr ;
499
500 wxMacCarbonEvent cEvent( event ) ;
501
502 Point screenMouseLocation = cEvent.GetParameter<Point>(kEventParamMouseLocation) ;
503 Point windowMouseLocation = screenMouseLocation ;
504
505 WindowRef window ;
506 short windowPart = ::FindWindow(screenMouseLocation, &window);
507
508 wxWindow* currentMouseWindow = NULL ;
509 ControlRef control = NULL ;
510
511 #if NEW_CAPTURE_HANDLING
512 if ( wxApp::s_captureWindow )
513 {
514 window = (WindowRef) wxApp::s_captureWindow->MacGetTopLevelWindowRef() ;
515 windowPart = inContent ;
516 }
517 #endif
518
519 if ( window )
520 {
521 QDGlobalToLocalPoint( UMAGetWindowPort(window ) , &windowMouseLocation ) ;
522
523 if ( wxApp::s_captureWindow
524 #if !NEW_CAPTURE_HANDLING
525 && wxApp::s_captureWindow->MacGetTopLevelWindowRef() == (WXWindow) window && windowPart == inContent
526 #endif
527 )
528 {
529 currentMouseWindow = wxApp::s_captureWindow ;
530 }
531 else if ( (IsWindowActive(window) && windowPart == inContent) )
532 {
533 ControlPartCode part ;
534 control = wxMacFindControlUnderMouse( toplevelWindow , windowMouseLocation , window , &part ) ;
535 // if there is no control below the mouse position, send the event to the toplevel window itself
536 if ( control == 0 )
537 {
538 currentMouseWindow = (wxWindow*) data ;
539 }
540 else
541 {
542 currentMouseWindow = wxFindControlFromMacControl( control ) ;
543 if ( currentMouseWindow == NULL && cEvent.GetKind() == kEventMouseMoved )
544 {
545 #if wxUSE_TOOLBAR
546 // for wxToolBar to function we have to send certaint events to it
547 // instead of its children (wxToolBarTools)
548 ControlRef parent ;
549 GetSuperControl(control, &parent );
550 wxWindow *wxParent = wxFindControlFromMacControl( parent ) ;
551 if ( wxParent && wxParent->IsKindOf( CLASSINFO( wxToolBar ) ) )
552 currentMouseWindow = wxParent ;
553 #endif
554 }
555 }
556 }
557 }
558
559 wxMouseEvent wxevent(wxEVT_LEFT_DOWN);
560 SetupMouseEvent( wxevent , cEvent ) ;
561
562 // handle all enter / leave events
563
564 if ( currentMouseWindow != g_MacLastWindow )
565 {
566 if ( g_MacLastWindow )
567 {
568 wxMouseEvent eventleave(wxevent);
569 eventleave.SetEventType( wxEVT_LEAVE_WINDOW );
570 g_MacLastWindow->ScreenToClient( &eventleave.m_x, &eventleave.m_y );
571 eventleave.SetEventObject( g_MacLastWindow ) ;
572 wxevent.SetId( g_MacLastWindow->GetId() ) ;
573
574 #if wxUSE_TOOLTIPS
575 wxToolTip::RelayEvent( g_MacLastWindow , eventleave);
576 #endif
577
578 g_MacLastWindow->GetEventHandler()->ProcessEvent(eventleave);
579 }
580
581 if ( currentMouseWindow )
582 {
583 wxMouseEvent evententer(wxevent);
584 evententer.SetEventType( wxEVT_ENTER_WINDOW );
585 currentMouseWindow->ScreenToClient( &evententer.m_x, &evententer.m_y );
586 evententer.SetEventObject( currentMouseWindow ) ;
587 wxevent.SetId( currentMouseWindow->GetId() ) ;
588
589 #if wxUSE_TOOLTIPS
590 wxToolTip::RelayEvent( currentMouseWindow , evententer );
591 #endif
592
593 currentMouseWindow->GetEventHandler()->ProcessEvent(evententer);
594 }
595
596 g_MacLastWindow = currentMouseWindow ;
597 }
598
599 if ( windowPart == inMenuBar )
600 {
601 // special case menu bar, as we are having a low-level runloop we must do it ourselves
602 if ( cEvent.GetKind() == kEventMouseDown )
603 {
604 ::MenuSelect( screenMouseLocation ) ;
605 result = noErr ;
606 }
607 }
608 else if ( currentMouseWindow )
609 {
610 wxWindow *currentMouseWindowParent = currentMouseWindow->GetParent();
611
612 currentMouseWindow->ScreenToClient( &wxevent.m_x , &wxevent.m_y ) ;
613
614 wxevent.SetEventObject( currentMouseWindow ) ;
615 wxevent.SetId( currentMouseWindow->GetId() ) ;
616
617 // make tooltips current
618
619 #if wxUSE_TOOLTIPS
620 if ( wxevent.GetEventType() == wxEVT_MOTION
621 || wxevent.GetEventType() == wxEVT_ENTER_WINDOW
622 || wxevent.GetEventType() == wxEVT_LEAVE_WINDOW )
623 wxToolTip::RelayEvent( currentMouseWindow , wxevent );
624 #endif
625
626 if ( currentMouseWindow->GetEventHandler()->ProcessEvent(wxevent) )
627 {
628 if ((currentMouseWindowParent != NULL) &&
629 (currentMouseWindowParent->GetChildren().Find(currentMouseWindow) == NULL))
630 currentMouseWindow = NULL;
631
632 result = noErr;
633 }
634 else
635 {
636 // if the user code did _not_ handle the event, then perform the
637 // default processing
638 if ( wxevent.GetEventType() == wxEVT_LEFT_DOWN )
639 {
640 // ... that is set focus to this window
641 if (currentMouseWindow->AcceptsFocus() && wxWindow::FindFocus()!=currentMouseWindow)
642 currentMouseWindow->SetFocus();
643 }
644
645 ControlPartCode dummyPart ;
646 // if built-in find control is finding the wrong control (ie static box instead of overlaid
647 // button, we cannot let the standard handler do its job, but must handle manually
648
649 if ( ( cEvent.GetKind() == kEventMouseDown )
650 #ifdef __WXMAC_OSX__
651 &&
652 (FindControlUnderMouse(windowMouseLocation , window , &dummyPart) !=
653 wxMacFindControlUnderMouse( toplevelWindow , windowMouseLocation , window , &dummyPart ) )
654 #endif
655 )
656 {
657 if ( currentMouseWindow->MacIsReallyEnabled() )
658 {
659 EventModifiers modifiers = cEvent.GetParameter<EventModifiers>(kEventParamKeyModifiers, typeUInt32) ;
660 Point clickLocation = windowMouseLocation ;
661
662 if ( toplevelWindow->MacUsesCompositing() )
663 currentMouseWindow->MacRootWindowToWindow( &clickLocation.h , &clickLocation.v ) ;
664
665 HandleControlClick( (ControlRef) currentMouseWindow->GetHandle() , clickLocation ,
666 modifiers , (ControlActionUPP ) -1 ) ;
667
668 if ((currentMouseWindowParent != NULL) &&
669 (currentMouseWindowParent->GetChildren().Find(currentMouseWindow) == NULL))
670 {
671 currentMouseWindow = NULL;
672 }
673 }
674
675 result = noErr ;
676 }
677 }
678
679 if ( cEvent.GetKind() == kEventMouseUp && wxApp::s_captureWindow )
680 {
681 wxApp::s_captureWindow = NULL ;
682 // update cursor ?
683 }
684
685 // update cursor
686
687 wxWindow* cursorTarget = currentMouseWindow ;
688 wxPoint cursorPoint( wxevent.m_x , wxevent.m_y ) ;
689
690 while ( cursorTarget && !cursorTarget->MacSetupCursor( cursorPoint ) )
691 {
692 cursorTarget = cursorTarget->GetParent() ;
693 if ( cursorTarget )
694 cursorPoint += cursorTarget->GetPosition();
695 }
696
697 } // else if ( currentMouseWindow )
698 else
699 {
700 // don't mess with controls we don't know about
701 // for some reason returning eventNotHandledErr does not lead to the correct behaviour
702 // so we try sending them the correct control directly
703 if ( cEvent.GetKind() == kEventMouseDown && toplevelWindow && control )
704 {
705 EventModifiers modifiers = cEvent.GetParameter<EventModifiers>(kEventParamKeyModifiers, typeUInt32) ;
706 Point clickLocation = windowMouseLocation ;
707 if ( toplevelWindow->MacUsesCompositing() )
708 {
709 #ifdef __WXMAC_OSX__
710 HIPoint hiPoint ;
711 hiPoint.x = clickLocation.h ;
712 hiPoint.y = clickLocation.v ;
713 HIViewConvertPoint( &hiPoint , (ControlRef) toplevelWindow->GetHandle() , control ) ;
714 clickLocation.h = (int)hiPoint.x ;
715 clickLocation.v = (int)hiPoint.y ;
716 #endif
717 }
718
719 HandleControlClick( control , clickLocation , modifiers , (ControlActionUPP ) -1 ) ;
720 result = noErr ;
721 }
722 }
723
724 return result ;
725 }
726
727 static pascal OSStatus wxMacTopLevelWindowEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
728 {
729 OSStatus result = eventNotHandledErr ;
730
731 wxMacCarbonEvent cEvent( event ) ;
732
733 // WindowRef windowRef = cEvent.GetParameter<WindowRef>(kEventParamDirectObject) ;
734 wxTopLevelWindowMac* toplevelWindow = (wxTopLevelWindowMac*) data ;
735
736 switch ( GetEventKind( event ) )
737 {
738 case kEventWindowActivated :
739 {
740 toplevelWindow->MacActivate( cEvent.GetTicks() , true) ;
741 wxActivateEvent wxevent(wxEVT_ACTIVATE, true , toplevelWindow->GetId());
742 wxevent.SetTimestamp( cEvent.GetTicks() ) ;
743 wxevent.SetEventObject(toplevelWindow);
744 toplevelWindow->GetEventHandler()->ProcessEvent(wxevent);
745 // we still sending an eventNotHandledErr in order to allow for default processing
746 }
747 break ;
748
749 case kEventWindowDeactivated :
750 {
751 toplevelWindow->MacActivate(cEvent.GetTicks() , false) ;
752 wxActivateEvent wxevent(wxEVT_ACTIVATE, false , toplevelWindow->GetId());
753 wxevent.SetTimestamp( cEvent.GetTicks() ) ;
754 wxevent.SetEventObject(toplevelWindow);
755 toplevelWindow->GetEventHandler()->ProcessEvent(wxevent);
756 // we still sending an eventNotHandledErr in order to allow for default processing
757 }
758 break ;
759
760 case kEventWindowShown :
761 toplevelWindow->Refresh() ;
762 result = noErr ;
763 break ;
764
765 case kEventWindowClose :
766 toplevelWindow->Close() ;
767 result = noErr ;
768 break ;
769
770 case kEventWindowBoundsChanged :
771 {
772 UInt32 attributes = cEvent.GetParameter<UInt32>(kEventParamAttributes, typeUInt32) ;
773 Rect newRect = cEvent.GetParameter<Rect>(kEventParamCurrentBounds) ;
774 wxRect r( newRect.left , newRect.top , newRect.right - newRect.left , newRect.bottom - newRect.top ) ;
775 if ( attributes & kWindowBoundsChangeSizeChanged )
776 {
777 // according to the other ports we handle this within the OS level
778 // resize event, not within a wxSizeEvent
779 wxFrame *frame = wxDynamicCast( toplevelWindow , wxFrame ) ;
780 if ( frame )
781 {
782 #if wxUSE_STATUSBAR
783 frame->PositionStatusBar();
784 #endif
785 #if wxUSE_TOOLBAR
786 frame->PositionToolBar();
787 #endif
788 }
789
790 wxSizeEvent event( r.GetSize() , toplevelWindow->GetId() ) ;
791 event.SetEventObject( toplevelWindow ) ;
792
793 toplevelWindow->GetEventHandler()->ProcessEvent(event) ;
794 toplevelWindow->wxWindowMac::MacSuperChangedPosition() ; // like this only children will be notified
795 }
796
797 if ( attributes & kWindowBoundsChangeOriginChanged )
798 {
799 wxMoveEvent event( r.GetLeftTop() , toplevelWindow->GetId() ) ;
800 event.SetEventObject( toplevelWindow ) ;
801 toplevelWindow->GetEventHandler()->ProcessEvent(event) ;
802 }
803
804 result = noErr ;
805 }
806 break ;
807
808 case kEventWindowBoundsChanging :
809 {
810 UInt32 attributes = cEvent.GetParameter<UInt32>(kEventParamAttributes,typeUInt32) ;
811 Rect newRect = cEvent.GetParameter<Rect>(kEventParamCurrentBounds) ;
812
813 if ( (attributes & kWindowBoundsChangeSizeChanged) || (attributes & kWindowBoundsChangeOriginChanged) )
814 {
815 // all (Mac) rects are in content area coordinates, all wxRects in structure coordinates
816 int left , top , right , bottom ;
817 toplevelWindow->MacGetContentAreaInset( left , top , right , bottom ) ;
818
819 wxRect r(
820 newRect.left - left,
821 newRect.top - top,
822 newRect.right - newRect.left + left + right,
823 newRect.bottom - newRect.top + top + bottom ) ;
824
825 // this is a EVT_SIZING not a EVT_SIZE type !
826 wxSizeEvent wxevent( r , toplevelWindow->GetId() ) ;
827 wxevent.SetEventObject( toplevelWindow ) ;
828 wxRect adjustR = r ;
829 if ( toplevelWindow->GetEventHandler()->ProcessEvent(wxevent) )
830 adjustR = wxevent.GetRect() ;
831
832 if ( toplevelWindow->GetMaxWidth() != -1 && adjustR.GetWidth() > toplevelWindow->GetMaxWidth() )
833 adjustR.SetWidth( toplevelWindow->GetMaxWidth() ) ;
834 if ( toplevelWindow->GetMaxHeight() != -1 && adjustR.GetHeight() > toplevelWindow->GetMaxHeight() )
835 adjustR.SetHeight( toplevelWindow->GetMaxHeight() ) ;
836 if ( toplevelWindow->GetMinWidth() != -1 && adjustR.GetWidth() < toplevelWindow->GetMinWidth() )
837 adjustR.SetWidth( toplevelWindow->GetMinWidth() ) ;
838 if ( toplevelWindow->GetMinHeight() != -1 && adjustR.GetHeight() < toplevelWindow->GetMinHeight() )
839 adjustR.SetHeight( toplevelWindow->GetMinHeight() ) ;
840 const Rect adjustedRect = { adjustR.y + top , adjustR.x + left , adjustR.y + adjustR.height - bottom , adjustR.x + adjustR.width - right } ;
841 if ( !EqualRect( &newRect , &adjustedRect ) )
842 cEvent.SetParameter<Rect>( kEventParamCurrentBounds , &adjustedRect ) ;
843 toplevelWindow->wxWindowMac::MacSuperChangedPosition() ; // like this only children will be notified
844 }
845
846 result = noErr ;
847 }
848 break ;
849
850 default :
851 break ;
852 }
853
854 return result ;
855 }
856
857 pascal OSStatus wxMacTopLevelEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
858 {
859 OSStatus result = eventNotHandledErr ;
860
861 switch ( GetEventClass( event ) )
862 {
863 case kEventClassKeyboard :
864 result = KeyboardEventHandler( handler, event , data ) ;
865 break ;
866
867 case kEventClassTextInput :
868 result = TextInputEventHandler( handler, event , data ) ;
869 break ;
870
871 case kEventClassWindow :
872 result = wxMacTopLevelWindowEventHandler( handler, event , data ) ;
873 break ;
874
875 case kEventClassMouse :
876 result = wxMacTopLevelMouseEventHandler( handler, event , data ) ;
877 break ;
878
879 default :
880 break ;
881 }
882
883 return result ;
884 }
885
886 DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacTopLevelEventHandler )
887
888 // ---------------------------------------------------------------------------
889 // wxWindowMac utility functions
890 // ---------------------------------------------------------------------------
891
892 // Find an item given the Macintosh Window Reference
893
894 WX_DECLARE_HASH_MAP(WindowRef, wxTopLevelWindowMac*, wxPointerHash, wxPointerEqual, MacWindowMap);
895
896 static MacWindowMap wxWinMacWindowList;
897
898 wxTopLevelWindowMac *wxFindWinFromMacWindow(WindowRef inWindowRef)
899 {
900 MacWindowMap::iterator node = wxWinMacWindowList.find(inWindowRef);
901
902 return (node == wxWinMacWindowList.end()) ? NULL : node->second;
903 }
904
905 void wxAssociateWinWithMacWindow(WindowRef inWindowRef, wxTopLevelWindowMac *win) ;
906 void wxAssociateWinWithMacWindow(WindowRef inWindowRef, wxTopLevelWindowMac *win)
907 {
908 // adding NULL WindowRef is (first) surely a result of an error and
909 // nothing else :-)
910 wxCHECK_RET( inWindowRef != (WindowRef) NULL, wxT("attempt to add a NULL WindowRef to window list") );
911
912 wxWinMacWindowList[inWindowRef] = win;
913 }
914
915 void wxRemoveMacWindowAssociation(wxTopLevelWindowMac *win) ;
916 void wxRemoveMacWindowAssociation(wxTopLevelWindowMac *win)
917 {
918 MacWindowMap::iterator it;
919 for ( it = wxWinMacWindowList.begin(); it != wxWinMacWindowList.end(); ++it )
920 {
921 if ( it->second == win )
922 {
923 wxWinMacWindowList.erase(it);
924 break;
925 }
926 }
927 }
928
929 // ----------------------------------------------------------------------------
930 // wxTopLevelWindowMac creation
931 // ----------------------------------------------------------------------------
932
933 wxTopLevelWindowMac *wxTopLevelWindowMac::s_macDeactivateWindow = NULL;
934
935 typedef struct
936 {
937 wxPoint m_position ;
938 wxSize m_size ;
939 }
940 FullScreenData ;
941
942 void wxTopLevelWindowMac::Init()
943 {
944 m_iconized =
945 m_maximizeOnShow = false;
946 m_macWindow = NULL ;
947
948 #if TARGET_API_MAC_OSX
949 m_macUsesCompositing = ( UMAGetSystemVersion() >= 0x1030 );
950 #else
951 m_macUsesCompositing = false;
952 #endif
953
954 m_macEventHandler = NULL ;
955 m_macFullScreenData = NULL ;
956 }
957
958 class wxMacDeferredWindowDeleter : public wxObject
959 {
960 public :
961 wxMacDeferredWindowDeleter( WindowRef windowRef )
962 {
963 m_macWindow = windowRef ;
964 }
965
966 virtual ~wxMacDeferredWindowDeleter()
967 {
968 UMADisposeWindow( (WindowRef) m_macWindow ) ;
969 }
970
971 protected :
972 WindowRef m_macWindow ;
973 } ;
974
975 bool wxTopLevelWindowMac::Create(wxWindow *parent,
976 wxWindowID id,
977 const wxString& title,
978 const wxPoint& pos,
979 const wxSize& size,
980 long style,
981 const wxString& name)
982 {
983 // init our fields
984 Init();
985
986 m_windowStyle = style;
987
988 SetName( name );
989
990 m_windowId = id == -1 ? NewControlId() : id;
991 wxWindow::SetLabel( title ) ;
992
993 MacCreateRealWindow( title, pos , size , MacRemoveBordersFromStyle(style) , name ) ;
994
995 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
996
997 if (GetExtraStyle() & wxFRAME_EX_METAL)
998 MacSetMetalAppearance(true);
999
1000 wxTopLevelWindows.Append(this);
1001
1002 if ( parent )
1003 parent->AddChild(this);
1004
1005 return true;
1006 }
1007
1008 wxTopLevelWindowMac::~wxTopLevelWindowMac()
1009 {
1010 if ( m_macWindow )
1011 {
1012 #if wxUSE_TOOLTIPS
1013 wxToolTip::NotifyWindowDelete(m_macWindow) ;
1014 #endif
1015 wxPendingDelete.Append( new wxMacDeferredWindowDeleter( (WindowRef) m_macWindow ) ) ;
1016 }
1017
1018 if ( m_macEventHandler )
1019 {
1020 ::RemoveEventHandler((EventHandlerRef) m_macEventHandler);
1021 m_macEventHandler = NULL ;
1022 }
1023
1024 wxRemoveMacWindowAssociation( this ) ;
1025
1026 if ( wxModelessWindows.Find(this) )
1027 wxModelessWindows.DeleteObject(this);
1028
1029 FullScreenData *data = (FullScreenData *) m_macFullScreenData ;
1030 delete data ;
1031 m_macFullScreenData = NULL ;
1032 }
1033
1034
1035 // ----------------------------------------------------------------------------
1036 // wxTopLevelWindowMac maximize/minimize
1037 // ----------------------------------------------------------------------------
1038
1039 void wxTopLevelWindowMac::Maximize(bool maximize)
1040 {
1041 // TODO: check if this is still necessary
1042 #if 0
1043 wxMacPortStateHelper help( (GrafPtr)GetWindowPort( (WindowRef)m_macWindow) ) ;
1044 wxMacWindowClipper clip( this );
1045 #endif
1046
1047 if ( !IsWindowInStandardState( (WindowRef)m_macWindow, NULL, NULL ) )
1048 {
1049 Rect rect;
1050
1051 GetWindowBounds((WindowRef)m_macWindow, kWindowGlobalPortRgn, &rect);
1052 SetWindowIdealUserState((WindowRef)m_macWindow, &rect);
1053 SetWindowUserState((WindowRef)m_macWindow, &rect);
1054 }
1055
1056 ZoomWindow( (WindowRef)m_macWindow , maximize ? inZoomOut : inZoomIn , false ) ;
1057 }
1058
1059 bool wxTopLevelWindowMac::IsMaximized() const
1060 {
1061 return IsWindowInStandardState( (WindowRef)m_macWindow , NULL , NULL ) ;
1062 }
1063
1064 void wxTopLevelWindowMac::Iconize(bool iconize)
1065 {
1066 if ( IsWindowCollapsable( (WindowRef)m_macWindow) )
1067 CollapseWindow( (WindowRef)m_macWindow , iconize ) ;
1068 }
1069
1070 bool wxTopLevelWindowMac::IsIconized() const
1071 {
1072 return IsWindowCollapsed((WindowRef)m_macWindow ) ;
1073 }
1074
1075 void wxTopLevelWindowMac::Restore()
1076 {
1077 if ( IsMaximized() )
1078 Maximize(false);
1079 else if ( IsIconized() )
1080 Iconize(false);
1081 }
1082
1083 // ----------------------------------------------------------------------------
1084 // wxTopLevelWindowMac misc
1085 // ----------------------------------------------------------------------------
1086
1087 wxPoint wxTopLevelWindowMac::GetClientAreaOrigin() const
1088 {
1089 return wxPoint(0, 0) ;
1090 }
1091
1092 void wxTopLevelWindowMac::SetIcon(const wxIcon& icon)
1093 {
1094 // this sets m_icon
1095 wxTopLevelWindowBase::SetIcon(icon);
1096 }
1097
1098 void wxTopLevelWindowMac::MacSetBackgroundBrush( const wxBrush &brush )
1099 {
1100 wxTopLevelWindowBase::MacSetBackgroundBrush( brush ) ;
1101
1102 if ( m_macBackgroundBrush.Ok() && m_macBackgroundBrush.GetStyle() != wxTRANSPARENT && m_macBackgroundBrush.MacGetBrushKind() == kwxMacBrushTheme )
1103 {
1104 SetThemeWindowBackground( (WindowRef) m_macWindow , m_macBackgroundBrush.MacGetTheme() , false ) ;
1105 }
1106 }
1107
1108 void wxTopLevelWindowMac::MacInstallTopLevelWindowEventHandler()
1109 {
1110 if ( m_macEventHandler != NULL )
1111 {
1112 verify_noerr( ::RemoveEventHandler( (EventHandlerRef) m_macEventHandler ) ) ;
1113 }
1114
1115 InstallWindowEventHandler(
1116 MAC_WXHWND(m_macWindow), GetwxMacTopLevelEventHandlerUPP(),
1117 GetEventTypeCount(eventList), eventList, this, (EventHandlerRef *)&m_macEventHandler );
1118 }
1119
1120 void wxTopLevelWindowMac::MacCreateRealWindow(
1121 const wxString& title,
1122 const wxPoint& pos,
1123 const wxSize& size,
1124 long style,
1125 const wxString& name )
1126 {
1127 OSStatus err = noErr ;
1128 SetName(name);
1129 m_windowStyle = style;
1130 m_isShown = false;
1131
1132 // create frame.
1133 int x = (int)pos.x;
1134 int y = (int)pos.y;
1135
1136 Rect theBoundsRect;
1137 wxRect display = wxGetClientDisplayRect() ;
1138
1139 if ( x == wxDefaultPosition.x )
1140 x = display.x ;
1141
1142 if ( y == wxDefaultPosition.y )
1143 y = display.y ;
1144
1145 int w = WidthDefault(size.x);
1146 int h = HeightDefault(size.y);
1147
1148 ::SetRect(&theBoundsRect, x, y , x + w, y + h);
1149
1150 // translate the window attributes in the appropriate window class and attributes
1151 WindowClass wclass = 0;
1152 WindowAttributes attr = kWindowNoAttributes ;
1153 WindowGroupRef group = NULL ;
1154
1155 if ( HasFlag( wxFRAME_TOOL_WINDOW) )
1156 {
1157 if (
1158 HasFlag( wxMINIMIZE_BOX ) || HasFlag( wxMAXIMIZE_BOX ) ||
1159 HasFlag( wxSYSTEM_MENU ) || HasFlag( wxCAPTION ) ||
1160 HasFlag(wxTINY_CAPTION_HORIZ) || HasFlag(wxTINY_CAPTION_VERT)
1161 )
1162 {
1163 wclass = kFloatingWindowClass ;
1164
1165 if ( HasFlag(wxTINY_CAPTION_VERT) )
1166 attr |= kWindowSideTitlebarAttribute ;
1167 }
1168 else
1169 {
1170 wclass = kPlainWindowClass ;
1171 }
1172 }
1173 else if ( HasFlag( wxCAPTION ) )
1174 {
1175 wclass = kDocumentWindowClass ;
1176 attr |= kWindowInWindowMenuAttribute ;
1177 }
1178 #if defined( __WXMAC__ ) && TARGET_API_MAC_OSX && ( MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_2 )
1179 else if ( HasFlag( wxFRAME_DRAWER ) )
1180 {
1181 wclass = kDrawerWindowClass;
1182 // we must force compositing on a drawer
1183 m_macUsesCompositing = true ;
1184 }
1185 #endif //10.2 and up
1186 else
1187 {
1188 if ( HasFlag( wxMINIMIZE_BOX ) || HasFlag( wxMAXIMIZE_BOX ) ||
1189 HasFlag( wxCLOSE_BOX ) || HasFlag( wxSYSTEM_MENU ) )
1190 {
1191 wclass = kDocumentWindowClass ;
1192 }
1193 else
1194 {
1195 wclass = kPlainWindowClass ;
1196 }
1197 }
1198
1199 if ( wclass != kPlainWindowClass )
1200 {
1201 if ( HasFlag( wxMINIMIZE_BOX ) )
1202 attr |= kWindowCollapseBoxAttribute ;
1203
1204 if ( HasFlag( wxMAXIMIZE_BOX ) )
1205 attr |= kWindowFullZoomAttribute ;
1206
1207 if ( HasFlag( wxRESIZE_BORDER ) )
1208 attr |= kWindowResizableAttribute ;
1209
1210 if ( HasFlag( wxCLOSE_BOX) )
1211 attr |= kWindowCloseBoxAttribute ;
1212 }
1213
1214 // turn on live resizing (OS X only)
1215 if (UMAGetSystemVersion() >= 0x1000)
1216 attr |= kWindowLiveResizeAttribute;
1217
1218 if ( HasFlag(wxSTAY_ON_TOP) )
1219 group = GetWindowGroupOfClass(kUtilityWindowClass) ;
1220
1221 #if TARGET_API_MAC_OSX
1222 if ( m_macUsesCompositing )
1223 attr |= kWindowCompositingAttribute;
1224 #endif
1225
1226 if ( HasFlag(wxFRAME_SHAPED) )
1227 {
1228 WindowDefSpec customWindowDefSpec;
1229 customWindowDefSpec.defType = kWindowDefProcPtr;
1230 customWindowDefSpec.u.defProc = NewWindowDefUPP(wxShapedMacWindowDef);
1231
1232 err = ::CreateCustomWindow( &customWindowDefSpec, wclass,
1233 attr, &theBoundsRect,
1234 (WindowRef*) &m_macWindow);
1235 }
1236 else
1237 {
1238 err = ::CreateNewWindow( wclass , attr , &theBoundsRect , (WindowRef*)&m_macWindow ) ;
1239 }
1240
1241 if ( err == noErr && m_macWindow != NULL && group != NULL )
1242 SetWindowGroup( (WindowRef) m_macWindow , group ) ;
1243
1244 wxCHECK_RET( err == noErr, wxT("Mac OS error when trying to create new window") );
1245
1246 // the create commands are only for content rect,
1247 // so we have to set the size again as structure bounds
1248 SetWindowBounds( (WindowRef) m_macWindow , kWindowStructureRgn , &theBoundsRect ) ;
1249
1250 wxAssociateWinWithMacWindow( (WindowRef) m_macWindow , this ) ;
1251 UMASetWTitle( (WindowRef) m_macWindow , title , m_font.GetEncoding() ) ;
1252 m_peer = new wxMacControl(this , true /*isRootControl*/) ;
1253
1254 #if TARGET_API_MAC_OSX
1255 if ( m_macUsesCompositing )
1256 {
1257 // There is a bug in 10.2.X for ::GetRootControl returning the window view instead of
1258 // the content view, so we have to retrieve it explicitly
1259 HIViewFindByID( HIViewGetRoot( (WindowRef) m_macWindow ) , kHIViewWindowContentID ,
1260 m_peer->GetControlRefAddr() ) ;
1261 if ( !m_peer->Ok() )
1262 {
1263 // compatibility mode fallback
1264 GetRootControl( (WindowRef) m_macWindow , m_peer->GetControlRefAddr() ) ;
1265 }
1266 }
1267 #endif
1268 {
1269 ::CreateRootControl( (WindowRef)m_macWindow , m_peer->GetControlRefAddr() ) ;
1270 }
1271
1272 // the root control level handler
1273 MacInstallEventHandler( (WXWidget) m_peer->GetControlRef() ) ;
1274
1275 #if TARGET_API_MAC_OSX
1276 if ( m_macUsesCompositing && m_macWindow != NULL )
1277 {
1278 if ( GetExtraStyle() & wxFRAME_EX_METAL )
1279 MacSetMetalAppearance( true ) ;
1280 }
1281 #endif
1282
1283 // the frame window event handler
1284 InstallStandardEventHandler( GetWindowEventTarget(MAC_WXHWND(m_macWindow)) ) ;
1285 MacInstallTopLevelWindowEventHandler() ;
1286
1287 DoSetWindowVariant( m_windowVariant ) ;
1288
1289 m_macFocus = NULL ;
1290
1291 if ( HasFlag(wxFRAME_SHAPED) )
1292 {
1293 // default shape matches the window size
1294 wxRegion rgn( 0, 0, w, h );
1295 SetShape( rgn );
1296 }
1297
1298 wxWindowCreateEvent event(this);
1299 GetEventHandler()->ProcessEvent(event);
1300 }
1301
1302 void wxTopLevelWindowMac::ClearBackground()
1303 {
1304 wxWindow::ClearBackground() ;
1305 }
1306
1307 // Raise the window to the top of the Z order
1308 void wxTopLevelWindowMac::Raise()
1309 {
1310 ::SelectWindow( (WindowRef)m_macWindow ) ;
1311 }
1312
1313 // Lower the window to the bottom of the Z order
1314 void wxTopLevelWindowMac::Lower()
1315 {
1316 ::SendBehind( (WindowRef)m_macWindow , NULL ) ;
1317 }
1318
1319 void wxTopLevelWindowMac::MacDelayedDeactivation(long timestamp)
1320 {
1321 if (s_macDeactivateWindow)
1322 {
1323 wxLogTrace(TRACE_ACTIVATE,
1324 wxT("Doing delayed deactivation of %p"),
1325 s_macDeactivateWindow);
1326
1327 s_macDeactivateWindow->MacActivate(timestamp, false);
1328 }
1329 }
1330
1331 void wxTopLevelWindowMac::MacActivate( long timestamp , bool inIsActivating )
1332 {
1333 wxLogTrace(TRACE_ACTIVATE, wxT("TopLevel=%p::MacActivate"), this);
1334
1335 if (s_macDeactivateWindow == this)
1336 s_macDeactivateWindow = NULL;
1337
1338 MacDelayedDeactivation(timestamp);
1339 MacPropagateHiliteChanged() ;
1340 }
1341
1342 void wxTopLevelWindowMac::SetTitle(const wxString& title)
1343 {
1344 wxWindow::SetLabel( title ) ;
1345 UMASetWTitle( (WindowRef)m_macWindow , title , m_font.GetEncoding() ) ;
1346 }
1347
1348 wxString wxTopLevelWindowMac::GetTitle() const
1349 {
1350 return wxWindow::GetLabel();
1351 }
1352
1353 bool wxTopLevelWindowMac::Show(bool show)
1354 {
1355 if ( !wxTopLevelWindowBase::Show(show) )
1356 return false;
1357
1358 if (show)
1359 {
1360 #if wxUSE_SYSTEM_OPTIONS
1361 // code contributed by Ryan Wilcox December 18, 2003
1362 bool plainTransition = UMAGetSystemVersion() >= 0x1000 ;
1363 if ( wxSystemOptions::HasOption(wxMAC_WINDOW_PLAIN_TRANSITION) )
1364 plainTransition = ( wxSystemOptions::GetOptionInt( wxMAC_WINDOW_PLAIN_TRANSITION ) == 1 ) ;
1365
1366 if ( plainTransition )
1367 ::ShowWindow( (WindowRef)m_macWindow );
1368 else
1369 ::TransitionWindow( (WindowRef)m_macWindow, kWindowZoomTransitionEffect, kWindowShowTransitionAction, NULL );
1370 #else
1371
1372 ::TransitionWindow( (WindowRef)m_macWindow, kWindowZoomTransitionEffect, kWindowShowTransitionAction, NULL );
1373 #endif
1374
1375 ::SelectWindow( (WindowRef)m_macWindow ) ;
1376
1377 // because apps expect a size event to occur at this moment
1378 wxSizeEvent event(GetSize() , m_windowId);
1379 event.SetEventObject(this);
1380 GetEventHandler()->ProcessEvent(event);
1381 }
1382 else
1383 {
1384 #if wxUSE_SYSTEM_OPTIONS
1385 bool plainTransition = UMAGetSystemVersion() >= 0x1000 ;
1386 if ( wxSystemOptions::HasOption(wxMAC_WINDOW_PLAIN_TRANSITION) )
1387 plainTransition = ( wxSystemOptions::GetOptionInt( wxMAC_WINDOW_PLAIN_TRANSITION ) == 1 ) ;
1388 if ( plainTransition )
1389 {
1390 ::HideWindow((WindowRef) m_macWindow );
1391 }
1392 else
1393 #endif
1394 {
1395 ::TransitionWindow((WindowRef)m_macWindow, kWindowZoomTransitionEffect, kWindowHideTransitionAction, NULL );
1396 }
1397 }
1398
1399 MacPropagateVisibilityChanged() ;
1400
1401 return true ;
1402 }
1403
1404 bool wxTopLevelWindowMac::ShowFullScreen(bool show, long style)
1405 {
1406 if ( show )
1407 {
1408 FullScreenData *data = (FullScreenData *)m_macFullScreenData ;
1409 delete data ;
1410 data = new FullScreenData() ;
1411
1412 m_macFullScreenData = data ;
1413 data->m_position = GetPosition() ;
1414 data->m_size = GetSize() ;
1415
1416 if ( style & wxFULLSCREEN_NOMENUBAR )
1417 HideMenuBar() ;
1418
1419 wxRect client = wxGetClientDisplayRect() ;
1420
1421 int left , top , right , bottom ;
1422 int x, y, w, h ;
1423
1424 x = client.x ;
1425 y = client.y ;
1426 w = client.width ;
1427 h = client.height ;
1428
1429 MacGetContentAreaInset( left , top , right , bottom ) ;
1430
1431 if ( style & wxFULLSCREEN_NOCAPTION )
1432 {
1433 y -= top ;
1434 h += top ;
1435 }
1436
1437 if ( style & wxFULLSCREEN_NOBORDER )
1438 {
1439 x -= left ;
1440 w += left + right ;
1441 h += bottom ;
1442 }
1443
1444 if ( style & wxFULLSCREEN_NOTOOLBAR )
1445 {
1446 // TODO
1447 }
1448
1449 if ( style & wxFULLSCREEN_NOSTATUSBAR )
1450 {
1451 // TODO
1452 }
1453
1454 SetSize( x , y , w, h ) ;
1455 }
1456 else
1457 {
1458 ShowMenuBar() ;
1459 FullScreenData *data = (FullScreenData *) m_macFullScreenData ;
1460 SetPosition( data->m_position ) ;
1461 SetSize( data->m_size ) ;
1462
1463 delete data ;
1464 m_macFullScreenData = NULL ;
1465 }
1466
1467 return false;
1468 }
1469
1470 bool wxTopLevelWindowMac::IsFullScreen() const
1471 {
1472 return m_macFullScreenData != NULL ;
1473 }
1474
1475 void wxTopLevelWindowMac::SetExtraStyle(long exStyle)
1476 {
1477 if ( GetExtraStyle() == exStyle )
1478 return ;
1479
1480 wxTopLevelWindowBase::SetExtraStyle( exStyle ) ;
1481
1482 #if TARGET_API_MAC_OSX
1483 if ( m_macUsesCompositing && m_macWindow != NULL )
1484 {
1485 bool metal = GetExtraStyle() & wxFRAME_EX_METAL ;
1486 if ( MacGetMetalAppearance() != metal )
1487 MacSetMetalAppearance( metal ) ;
1488 }
1489 #endif
1490 }
1491
1492 // we are still using coordinates of the content view; TODO: switch to structure bounds
1493
1494 void wxTopLevelWindowMac::MacGetContentAreaInset( int &left , int &top , int &right , int &bottom )
1495 {
1496 Rect content ;
1497 Rect structure ;
1498 GetWindowBounds( (WindowRef) m_macWindow, kWindowStructureRgn , &structure ) ;
1499 GetWindowBounds( (WindowRef) m_macWindow, kWindowContentRgn , &content ) ;
1500
1501 left = content.left - structure.left ;
1502 top = content.top - structure.top ;
1503 right = structure.right - content.right ;
1504 bottom = structure.bottom - content.bottom ;
1505 }
1506
1507 void wxTopLevelWindowMac::DoMoveWindow(int x, int y, int width, int height)
1508 {
1509 m_cachedClippedRectValid = false ;
1510 Rect bounds = { y , x , y + height , x + width } ;
1511 verify_noerr(SetWindowBounds( (WindowRef) m_macWindow, kWindowStructureRgn , &bounds )) ;
1512 wxWindowMac::MacSuperChangedPosition() ; // like this only children will be notified
1513 }
1514
1515 void wxTopLevelWindowMac::DoGetPosition( int *x, int *y ) const
1516 {
1517 Rect bounds ;
1518
1519 verify_noerr(GetWindowBounds((WindowRef) m_macWindow, kWindowStructureRgn , &bounds )) ;
1520
1521 if (x)
1522 *x = bounds.left ;
1523 if (y)
1524 *y = bounds.top ;
1525 }
1526
1527 void wxTopLevelWindowMac::DoGetSize( int *width, int *height ) const
1528 {
1529 Rect bounds ;
1530
1531 verify_noerr(GetWindowBounds((WindowRef) m_macWindow, kWindowStructureRgn , &bounds )) ;
1532
1533 if (width)
1534 *width = bounds.right - bounds.left ;
1535 if (height)
1536 *height = bounds.bottom - bounds.top ;
1537 }
1538
1539 void wxTopLevelWindowMac::DoGetClientSize( int *width, int *height ) const
1540 {
1541 Rect bounds ;
1542
1543 verify_noerr(GetWindowBounds((WindowRef) m_macWindow, kWindowContentRgn , &bounds )) ;
1544
1545 if (width)
1546 *width = bounds.right - bounds.left ;
1547 if (height)
1548 *height = bounds.bottom - bounds.top ;
1549 }
1550
1551 void wxTopLevelWindowMac::MacSetMetalAppearance( bool set )
1552 {
1553 #if TARGET_API_MAC_OSX
1554 wxASSERT_MSG( m_macUsesCompositing ,
1555 wxT("Cannot set metal appearance on a non-compositing window") ) ;
1556
1557 MacChangeWindowAttributes( set ? kWindowMetalAttribute : kWindowNoAttributes ,
1558 set ? kWindowNoAttributes : kWindowMetalAttribute ) ;
1559 #endif
1560 }
1561
1562 bool wxTopLevelWindowMac::MacGetMetalAppearance() const
1563 {
1564 #if TARGET_API_MAC_OSX
1565 return MacGetWindowAttributes() & kWindowMetalAttribute ;
1566 #else
1567 return false ;
1568 #endif
1569 }
1570
1571 void wxTopLevelWindowMac::MacChangeWindowAttributes( wxUint32 attributesToSet , wxUint32 attributesToClear )
1572 {
1573 ChangeWindowAttributes( (WindowRef)m_macWindow, attributesToSet, attributesToClear ) ;
1574 }
1575
1576 wxUint32 wxTopLevelWindowMac::MacGetWindowAttributes() const
1577 {
1578 UInt32 attr = 0 ;
1579 GetWindowAttributes( (WindowRef) m_macWindow, &attr ) ;
1580
1581 return attr ;
1582 }
1583
1584 void wxTopLevelWindowMac::MacPerformUpdates()
1585 {
1586 #if TARGET_API_MAC_OSX
1587 if ( m_macUsesCompositing )
1588 {
1589 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3
1590 // for composited windows this also triggers a redraw of all
1591 // invalid views in the window
1592 if ( UMAGetSystemVersion() >= 0x1030 )
1593 HIWindowFlush((WindowRef) m_macWindow) ;
1594 else
1595 #endif
1596 {
1597 // the only way to trigger the redrawing on earlier systems is to call
1598 // ReceiveNextEvent
1599
1600 EventRef currentEvent = (EventRef) wxTheApp->MacGetCurrentEvent() ;
1601 UInt32 currentEventClass = 0 ;
1602 UInt32 currentEventKind = 0 ;
1603 if ( currentEvent != NULL )
1604 {
1605 currentEventClass = ::GetEventClass( currentEvent ) ;
1606 currentEventKind = ::GetEventKind( currentEvent ) ;
1607 }
1608
1609 if ( currentEventClass != kEventClassMenu )
1610 {
1611 // when tracking a menu, strange redraw errors occur if we flush now, so leave..
1612 EventRef theEvent;
1613 OSStatus status = noErr ;
1614 status = ReceiveNextEvent( 0 , NULL , kEventDurationNoWait , false , &theEvent ) ;
1615 }
1616 }
1617 }
1618 else
1619 #endif
1620 {
1621 BeginUpdate( (WindowRef) m_macWindow ) ;
1622
1623 RgnHandle updateRgn = NewRgn();
1624 if ( updateRgn )
1625 {
1626 GetPortVisibleRegion( GetWindowPort( (WindowRef)m_macWindow ), updateRgn );
1627 UpdateControls( (WindowRef)m_macWindow , updateRgn ) ;
1628
1629 // if ( !EmptyRgn( updateRgn ) )
1630 // MacDoRedraw( updateRgn , 0 , true) ;
1631
1632 DisposeRgn( updateRgn );
1633 }
1634
1635 EndUpdate( (WindowRef)m_macWindow ) ;
1636 QDFlushPortBuffer( GetWindowPort( (WindowRef)m_macWindow ) , NULL ) ;
1637 }
1638 }
1639
1640 // Attracts the users attention to this window if the application is
1641 // inactive (should be called when a background event occurs)
1642
1643 static pascal void wxMacNMResponse( NMRecPtr ptr )
1644 {
1645 NMRemove( ptr ) ;
1646 DisposePtr( (Ptr)ptr ) ;
1647 }
1648
1649 void wxTopLevelWindowMac::RequestUserAttention(int flags )
1650 {
1651 NMRecPtr notificationRequest = (NMRecPtr) NewPtr( sizeof( NMRec) ) ;
1652 static wxMacNMUPP nmupp( wxMacNMResponse );
1653
1654 memset( notificationRequest , 0 , sizeof(*notificationRequest) ) ;
1655 notificationRequest->qType = nmType ;
1656 notificationRequest->nmMark = 1 ;
1657 notificationRequest->nmIcon = 0 ;
1658 notificationRequest->nmSound = 0 ;
1659 notificationRequest->nmStr = NULL ;
1660 notificationRequest->nmResp = nmupp ;
1661
1662 verify_noerr( NMInstall( notificationRequest ) ) ;
1663 }
1664
1665 // ---------------------------------------------------------------------------
1666 // Shape implementation
1667 // ---------------------------------------------------------------------------
1668
1669
1670 bool wxTopLevelWindowMac::SetShape(const wxRegion& region)
1671 {
1672 wxCHECK_MSG( HasFlag(wxFRAME_SHAPED), false,
1673 _T("Shaped windows must be created with the wxFRAME_SHAPED style."));
1674
1675 // The empty region signifies that the shape
1676 // should be removed from the window.
1677 if ( region.IsEmpty() )
1678 {
1679 wxSize sz = GetClientSize();
1680 wxRegion rgn(0, 0, sz.x, sz.y);
1681 if ( rgn.IsEmpty() )
1682 return false ;
1683 else
1684 return SetShape(rgn);
1685 }
1686
1687 // Make a copy of the region
1688 RgnHandle shapeRegion = NewRgn();
1689 CopyRgn( (RgnHandle)region.GetWXHRGN(), shapeRegion );
1690
1691 // Dispose of any shape region we may already have
1692 RgnHandle oldRgn = (RgnHandle)GetWRefCon( (WindowRef)MacGetWindowRef() );
1693 if ( oldRgn )
1694 DisposeRgn(oldRgn);
1695
1696 // Save the region so we can use it later
1697 SetWRefCon((WindowRef)MacGetWindowRef(), (SInt32)shapeRegion);
1698
1699 // inform the window manager that the window has changed shape
1700 ReshapeCustomWindow((WindowRef)MacGetWindowRef());
1701
1702 return true;
1703 }
1704
1705 // ---------------------------------------------------------------------------
1706 // Support functions for shaped windows, based on Apple's CustomWindow sample at
1707 // http://developer.apple.com/samplecode/Sample_Code/Human_Interface_Toolbox/Mac_OS_High_Level_Toolbox/CustomWindow.htm
1708 // ---------------------------------------------------------------------------
1709
1710 static void wxShapedMacWindowGetPos(WindowRef window, Rect* inRect)
1711 {
1712 GetWindowPortBounds(window, inRect);
1713 Point pt = { inRect->left, inRect->top };
1714
1715 QDLocalToGlobalPoint( GetWindowPort(window), &pt ) ;
1716 inRect->top = pt.v;
1717 inRect->left = pt.h;
1718 inRect->bottom += pt.v;
1719 inRect->right += pt.h;
1720 }
1721
1722 static SInt32 wxShapedMacWindowGetFeatures(WindowRef window, SInt32 param)
1723 {
1724 /*------------------------------------------------------
1725 Define which options your custom window supports.
1726 --------------------------------------------------------*/
1727 //just enable everything for our demo
1728 *(OptionBits*)param =
1729 //kWindowCanGrow |
1730 //kWindowCanZoom |
1731 //kWindowCanCollapse |
1732 //kWindowCanGetWindowRegion |
1733 //kWindowHasTitleBar |
1734 //kWindowSupportsDragHilite |
1735 kWindowCanDrawInCurrentPort |
1736 //kWindowCanMeasureTitle |
1737 kWindowWantsDisposeAtProcessDeath |
1738 kWindowSupportsGetGrowImageRegion |
1739 kWindowDefSupportsColorGrafPort;
1740
1741 return 1;
1742 }
1743
1744 // The content region is left as a rectangle matching the window size, this is
1745 // so the origin in the paint event, and etc. still matches what the
1746 // programmer expects.
1747 static void wxShapedMacWindowContentRegion(WindowRef window, RgnHandle rgn)
1748 {
1749 SetEmptyRgn(rgn);
1750 wxTopLevelWindowMac* win = wxFindWinFromMacWindow(window);
1751 if (win)
1752 {
1753 Rect r ;
1754 wxShapedMacWindowGetPos( window, &r ) ;
1755 RectRgn( rgn , &r ) ;
1756 }
1757 }
1758
1759 // The structure region is set to the shape given to the SetShape method.
1760 static void wxShapedMacWindowStructureRegion(WindowRef window, RgnHandle rgn)
1761 {
1762 RgnHandle cachedRegion = (RgnHandle) GetWRefCon(window);
1763
1764 SetEmptyRgn(rgn);
1765 if (cachedRegion)
1766 {
1767 Rect windowRect;
1768 wxShapedMacWindowGetPos(window, &windowRect); // how big is the window
1769 CopyRgn(cachedRegion, rgn); // make a copy of our cached region
1770 OffsetRgn(rgn, windowRect.left, windowRect.top); // position it over window
1771 //MapRgn(rgn, &mMaskSize, &windowRect); //scale it to our actual window size
1772 }
1773 }
1774
1775 static SInt32 wxShapedMacWindowGetRegion(WindowRef window, SInt32 param)
1776 {
1777 GetWindowRegionPtr rgnRec = (GetWindowRegionPtr)param;
1778
1779 if (rgnRec == NULL)
1780 return paramErr;
1781
1782 switch (rgnRec->regionCode)
1783 {
1784 case kWindowStructureRgn:
1785 wxShapedMacWindowStructureRegion(window, rgnRec->winRgn);
1786 break;
1787
1788 case kWindowContentRgn:
1789 wxShapedMacWindowContentRegion(window, rgnRec->winRgn);
1790 break;
1791
1792 default:
1793 SetEmptyRgn(rgnRec->winRgn);
1794 break;
1795 }
1796
1797 return noErr;
1798 }
1799
1800 // Determine the region of the window which was hit
1801 //
1802 static SInt32 wxShapedMacWindowHitTest(WindowRef window, SInt32 param)
1803 {
1804 Point hitPoint;
1805 static RgnHandle tempRgn = NULL;
1806
1807 if (tempRgn == NULL)
1808 tempRgn = NewRgn();
1809
1810 // get the point clicked
1811 SetPt( &hitPoint, LoWord(param), HiWord(param) );
1812
1813 // Mac OS 8.5 or later
1814 wxShapedMacWindowStructureRegion(window, tempRgn);
1815 if (PtInRgn( hitPoint, tempRgn )) //in window content region?
1816 return wInContent;
1817
1818 // no significant area was hit
1819 return wNoHit;
1820 }
1821
1822 static pascal long wxShapedMacWindowDef(short varCode, WindowRef window, SInt16 message, SInt32 param)
1823 {
1824 switch (message)
1825 {
1826 case kWindowMsgHitTest:
1827 return wxShapedMacWindowHitTest(window, param);
1828
1829 case kWindowMsgGetFeatures:
1830 return wxShapedMacWindowGetFeatures(window, param);
1831
1832 // kWindowMsgGetRegion is sent during CreateCustomWindow and ReshapeCustomWindow
1833 case kWindowMsgGetRegion:
1834 return wxShapedMacWindowGetRegion(window, param);
1835
1836 default:
1837 break;
1838 }
1839
1840 return 0;
1841 }
1842