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