]> git.saurik.com Git - wxWidgets.git/blame - src/mac/toplevel.cpp
implementation changes to closer follow MSW, crashes fixed
[wxWidgets.git] / src / mac / toplevel.cpp
CommitLineData
a15eb0a5
SC
1///////////////////////////////////////////////////////////////////////////////
2// Name: mac/toplevel.cpp
3// Purpose: implements wxTopLevelWindow for MSW
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 24.09.01
7// RCS-ID: $Id$
8// Copyright: (c) 2001 SciTech Software, Inc. (www.scitechsoft.com)
6aa89a22 9// License: wxWindows licence
a15eb0a5
SC
10///////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20#ifdef __GNUG__
21 #pragma implementation "toplevel.h"
22#endif
23
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
27#ifdef __BORLANDC__
28 #pragma hdrstop
29#endif
30
31#ifndef WX_PRECOMP
32 #include "wx/app.h"
33 #include "wx/toplevel.h"
422644a3 34 #include "wx/frame.h"
a15eb0a5
SC
35 #include "wx/string.h"
36 #include "wx/log.h"
37 #include "wx/intl.h"
38#endif //WX_PRECOMP
39
5f0b2f22 40#include "wx/mac/uma.h"
422644a3 41#include "wx/mac/aga.h"
7c091673 42#include "wx/app.h"
5f0b2f22 43#include "wx/tooltip.h"
a07c1212 44#include "wx/dnd.h"
5f0b2f22 45
dd49c691
SC
46#include "ToolUtils.h"
47
48
34dc8f91
SC
49#define wxMAC_DEBUG_REDRAW 0
50#ifndef wxMAC_DEBUG_REDRAW
51#define wxMAC_DEBUG_REDRAW 0
52#endif
53
a15eb0a5
SC
54// ----------------------------------------------------------------------------
55// globals
56// ----------------------------------------------------------------------------
57
58// list of all frames and modeless dialogs
32b5be3d
RR
59wxWindowList wxModelessWindows;
60
61// double click testing
62static Point gs_lastWhere;
63static long gs_lastWhen = 0;
64
6a7e6411 65
45ff8005 66#if TARGET_CARBON
6a7e6411 67static pascal long wxShapedMacWindowDef(short varCode, WindowRef window, SInt16 message, SInt32 param);
45ff8005 68#endif
6a7e6411 69
a15eb0a5
SC
70// ============================================================================
71// wxTopLevelWindowMac implementation
72// ============================================================================
73
851b3a88
SC
74// ---------------------------------------------------------------------------
75// Carbon Events
76// ---------------------------------------------------------------------------
77
78#if TARGET_CARBON
79
80extern long wxMacTranslateKey(unsigned char key, unsigned char code) ;
81
1542ea39 82static const EventTypeSpec eventList[] =
851b3a88
SC
83{
84 { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent } ,
c5c9378c 85
e40298d5 86 { kEventClassKeyboard, kEventRawKeyDown } ,
c5c9378c
SC
87 { kEventClassKeyboard, kEventRawKeyRepeat } ,
88 { kEventClassKeyboard, kEventRawKeyUp } ,
89 { kEventClassKeyboard, kEventRawKeyModifiersChanged } ,
90
851b3a88
SC
91 { kEventClassWindow , kEventWindowUpdate } ,
92 { kEventClassWindow , kEventWindowActivated } ,
93 { kEventClassWindow , kEventWindowDeactivated } ,
94 { kEventClassWindow , kEventWindowBoundsChanging } ,
95 { kEventClassWindow , kEventWindowBoundsChanged } ,
96 { kEventClassWindow , kEventWindowClose } ,
97
98 { kEventClassMouse , kEventMouseDown } ,
99 { kEventClassMouse , kEventMouseUp } ,
100 { kEventClassMouse , kEventMouseMoved } ,
101 { kEventClassMouse , kEventMouseDragged } ,
102
103} ;
104
105static pascal OSStatus TextInputEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
106{
107 OSStatus result = eventNotHandledErr ;
851b3a88 108
c5c9378c 109 wxWindow* focus = wxWindow::FindFocus() ;
e40298d5 110 char charCode ;
1542ea39 111 UInt32 keyCode ;
c5c9378c 112 UInt32 modifiers ;
e40298d5 113 Point point ;
c5c9378c
SC
114
115 EventRef rawEvent ;
1542ea39 116
c5c9378c 117 GetEventParameter( event , kEventParamTextInputSendKeyboardEvent ,typeEventRef,NULL,sizeof(rawEvent),NULL,&rawEvent ) ;
1542ea39 118
e40298d5
JS
119 GetEventParameter( rawEvent, kEventParamKeyMacCharCodes, typeChar, NULL,sizeof(char), NULL,&charCode );
120 GetEventParameter( rawEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode );
121 GetEventParameter( rawEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers);
122 GetEventParameter( rawEvent, kEventParamMouseLocation, typeQDPoint, NULL,
123 sizeof( Point ), NULL, &point );
124
e40298d5
JS
125 switch ( GetEventKind( event ) )
126 {
127 case kEventTextInputUnicodeForKeyEvent :
ace07c80 128 // this is only called when no default handler has jumped in, eg a wxControl on a floater window does not
5d2e69e8 129 // get its own kEventTextInputUnicodeForKeyEvent, so we route back the
ace07c80
SC
130 wxControl* control = wxDynamicCast( focus , wxControl ) ;
131 if ( control )
132 {
133 ControlHandle macControl = (ControlHandle) control->GetMacControl() ;
134 if ( macControl )
135 {
136 ::HandleControlKey( macControl , keyCode , charCode , modifiers ) ;
137 result = noErr ;
138 }
139 }
140 /*
141 // this may lead to double events sent to a window in case all handlers have skipped the key down event
77a4354e
VZ
142 UInt32 when = EventTimeToTicks( GetEventTime( event ) ) ;
143 UInt32 message = (keyCode << 8) + charCode;
144
1542ea39 145 if ( (focus != NULL) && wxTheApp->MacSendKeyDownEvent(
e40298d5
JS
146 focus , message , modifiers , when , point.h , point.v ) )
147 {
148 result = noErr ;
149 }
ace07c80 150 */
e40298d5
JS
151 break ;
152 }
c5c9378c
SC
153
154 return result ;
155}
156
157static pascal OSStatus KeyboardEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
158{
159 OSStatus result = eventNotHandledErr ;
160
161 wxWindow* focus = wxWindow::FindFocus() ;
e40298d5 162 char charCode ;
1542ea39 163 UInt32 keyCode ;
c5c9378c 164 UInt32 modifiers ;
e40298d5
JS
165 Point point ;
166 UInt32 when = EventTimeToTicks( GetEventTime( event ) ) ;
167
168 GetEventParameter( event, kEventParamKeyMacCharCodes, typeChar, NULL,sizeof(char), NULL,&charCode );
169 GetEventParameter( event, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode );
170 GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers);
171 GetEventParameter( event, kEventParamMouseLocation, typeQDPoint, NULL,
172 sizeof( Point ), NULL, &point );
173
174 UInt32 message = (keyCode << 8) + charCode;
175 switch( GetEventKind( event ) )
176 {
177 case kEventRawKeyRepeat :
178 case kEventRawKeyDown :
e40298d5 179 {
404f1d80
SC
180 WXEVENTREF formerEvent = wxTheApp->MacGetCurrentEvent() ;
181 WXEVENTHANDLERCALLREF formerHandler = wxTheApp->MacGetCurrentEventHandlerCallRef() ;
182 wxTheApp->MacSetCurrentEvent( event , handler ) ;
183 if ( (focus != NULL) && wxTheApp->MacSendKeyDownEvent(
184 focus , message , modifiers , when , point.h , point.v ) )
185 {
186 result = noErr ;
187 }
188 wxTheApp->MacSetCurrentEvent( formerEvent , formerHandler ) ;
e40298d5
JS
189 }
190 break ;
191 case kEventRawKeyUp :
1542ea39 192 if ( (focus != NULL) && wxTheApp->MacSendKeyUpEvent(
e40298d5
JS
193 focus , message , modifiers , when , point.h , point.v ) )
194 {
195 result = noErr ;
196 }
197 break ;
198 case kEventRawKeyModifiersChanged :
199 {
200 wxKeyEvent event(wxEVT_KEY_DOWN);
201
202 event.m_shiftDown = modifiers & shiftKey;
203 event.m_controlDown = modifiers & controlKey;
204 event.m_altDown = modifiers & optionKey;
205 event.m_metaDown = modifiers & cmdKey;
206
207 event.m_x = point.h;
208 event.m_y = point.v;
209 event.m_timeStamp = when;
210 wxWindow* focus = wxWindow::FindFocus() ;
211 event.SetEventObject(focus);
212
8d60dc8a 213 if ( focus && (modifiers ^ wxTheApp->s_lastModifiers ) & controlKey )
e40298d5
JS
214 {
215 event.m_keyCode = WXK_CONTROL ;
216 event.SetEventType( ( modifiers & controlKey ) ? wxEVT_KEY_DOWN : wxEVT_KEY_UP ) ;
217 focus->GetEventHandler()->ProcessEvent( event ) ;
218 }
8d60dc8a 219 if ( focus && (modifiers ^ wxTheApp->s_lastModifiers ) & shiftKey )
e40298d5
JS
220 {
221 event.m_keyCode = WXK_SHIFT ;
222 event.SetEventType( ( modifiers & shiftKey ) ? wxEVT_KEY_DOWN : wxEVT_KEY_UP ) ;
223 focus->GetEventHandler()->ProcessEvent( event ) ;
224 }
8d60dc8a 225 if ( focus && (modifiers ^ wxTheApp->s_lastModifiers ) & optionKey )
e40298d5
JS
226 {
227 event.m_keyCode = WXK_ALT ;
228 event.SetEventType( ( modifiers & optionKey ) ? wxEVT_KEY_DOWN : wxEVT_KEY_UP ) ;
229 focus->GetEventHandler()->ProcessEvent( event ) ;
230 }
b7aec135
SC
231 if ( focus && (modifiers ^ wxTheApp->s_lastModifiers ) & cmdKey )
232 {
233 event.m_keyCode = WXK_COMMAND ;
234 event.SetEventType( ( modifiers & cmdKey ) ? wxEVT_KEY_DOWN : wxEVT_KEY_UP ) ;
235 focus->GetEventHandler()->ProcessEvent( event ) ;
236 }
e40298d5
JS
237 wxTheApp->s_lastModifiers = modifiers ;
238 }
239 break ;
240 }
851b3a88
SC
241
242 return result ;
243}
244
245static pascal OSStatus MouseEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
246{
247 OSStatus result = eventNotHandledErr ;
248
e40298d5
JS
249 wxTopLevelWindowMac* toplevelWindow = (wxTopLevelWindowMac*) data ;
250 Point point ;
251 UInt32 modifiers = 0;
252 EventMouseButton button = 0 ;
253 UInt32 click = 0 ;
1542ea39 254
e40298d5
JS
255 GetEventParameter( event, kEventParamMouseLocation, typeQDPoint, NULL,
256 sizeof( Point ), NULL, &point );
257 GetEventParameter( event, kEventParamKeyModifiers, typeUInt32, NULL,
258 sizeof( UInt32 ), NULL, &modifiers );
259 GetEventParameter( event, kEventParamMouseButton, typeMouseButton, NULL,
260 sizeof( EventMouseButton ), NULL, &button );
261 GetEventParameter( event, kEventParamClickCount, typeUInt32, NULL,
262 sizeof( UInt32 ), NULL, &click );
1542ea39 263
e40298d5
JS
264 if ( button == 0 || GetEventKind( event ) == kEventMouseUp )
265 modifiers += btnState ;
1542ea39 266
e40298d5 267 WindowRef window ;
851b3a88 268 short windowPart = ::FindWindow(point, &window);
a3195b73 269
e40298d5 270 if ( IsWindowActive(window) && windowPart == inContent )
851b3a88 271 {
e40298d5
JS
272 switch ( GetEventKind( event ) )
273 {
274 case kEventMouseDown :
275 toplevelWindow->MacFireMouseEvent( mouseDown , point.h , point.v , modifiers , EventTimeToTicks( GetEventTime( event ) ) ) ;
276 result = noErr ;
277 break ;
278 case kEventMouseUp :
279 toplevelWindow->MacFireMouseEvent( mouseUp , point.h , point.v , modifiers , EventTimeToTicks( GetEventTime( event ) ) ) ;
280 result = noErr ;
281 break ;
282 case kEventMouseMoved :
3c589c7f 283 wxTheApp->MacHandleMouseMovedEvent( point.h , point.v , modifiers , EventTimeToTicks( GetEventTime( event ) ) ) ;
e40298d5
JS
284 result = noErr ;
285 break ;
286 case kEventMouseDragged :
287 toplevelWindow->MacFireMouseEvent( nullEvent , point.h , point.v , modifiers , EventTimeToTicks( GetEventTime( event ) ) ) ;
288 result = noErr ;
289 break ;
290 default :
291 break ;
292 }
293 }
1542ea39 294
e40298d5 295 return result ;
1542ea39 296
851b3a88
SC
297
298}
299static pascal OSStatus WindowEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
300{
301 OSStatus result = eventNotHandledErr ;
302 OSStatus err = noErr ;
303
e40298d5
JS
304 UInt32 attributes;
305 WindowRef windowRef ;
306 wxTopLevelWindowMac* toplevelWindow = (wxTopLevelWindowMac*) data ;
1542ea39 307
e40298d5
JS
308 GetEventParameter( event, kEventParamDirectObject, typeWindowRef, NULL,
309 sizeof( WindowRef ), NULL, &windowRef );
1542ea39 310
e40298d5
JS
311 switch( GetEventKind( event ) )
312 {
313 case kEventWindowUpdate :
314 if ( !wxPendingDelete.Member(toplevelWindow) )
315 toplevelWindow->MacUpdate( EventTimeToTicks( GetEventTime( event ) ) ) ;
316 result = noErr ;
317 break ;
318 case kEventWindowActivated :
319 toplevelWindow->MacActivate( EventTimeToTicks( GetEventTime( event ) ) , true) ;
320 result = noErr ;
321 break ;
322 case kEventWindowDeactivated :
323 toplevelWindow->MacActivate( EventTimeToTicks( GetEventTime( event ) ) , false) ;
324 result = noErr ;
325 break ;
326 case kEventWindowClose :
327 toplevelWindow->Close() ;
328 result = noErr ;
329 break ;
330 case kEventWindowBoundsChanged :
331 err = GetEventParameter( event, kEventParamAttributes, typeUInt32,
332 NULL, sizeof( UInt32 ), NULL, &attributes );
333 if ( err == noErr )
334 {
335 Rect newContentRect ;
336
337 GetEventParameter( event, kEventParamCurrentBounds, typeQDRectangle, NULL,
338 sizeof( newContentRect ), NULL, &newContentRect );
1542ea39
RD
339
340 toplevelWindow->SetSize( newContentRect.left , newContentRect.top ,
341 newContentRect.right - newContentRect.left ,
851b3a88
SC
342 newContentRect.bottom - newContentRect.top, wxSIZE_USE_EXISTING);
343
e40298d5
JS
344 result = noErr;
345 }
346 break ;
f81bfef9
SC
347 case kEventWindowBoundsChanging :
348 err = GetEventParameter( event, kEventParamAttributes, typeUInt32,
349 NULL, sizeof( UInt32 ), NULL, &attributes );
350 if ( err == noErr )
351 {
352 Rect newContentRect ;
353
354 GetEventParameter( event, kEventParamCurrentBounds, typeQDRectangle, NULL,
355 sizeof( newContentRect ), NULL, &newContentRect );
5d2e69e8 356
83901ec2
SC
357 wxSize formerSize = toplevelWindow->GetSize() ;
358
359 if ( (attributes & kWindowBoundsChangeSizeChanged ) ||
360 ( attributes & kWindowBoundsChangeOriginChanged ) )
361 toplevelWindow->SetSize( newContentRect.left , newContentRect.top ,
362 newContentRect.right - newContentRect.left ,
363 newContentRect.bottom - newContentRect.top, wxSIZE_USE_EXISTING);
364
365 int x , y , w , h ;
366 toplevelWindow->GetPosition( &x , &y ) ;
367 toplevelWindow->GetSize( &w , &h ) ;
368 Rect adjustedRect = { y , x , y + h , x + w } ;
369
370 if ( !EqualRect( &newContentRect , &adjustedRect ) )
f81bfef9 371 {
83901ec2 372 SetEventParameter( event , kEventParamCurrentBounds , typeQDRectangle, sizeof( adjustedRect ) , &adjustedRect ) ;
f81bfef9 373 }
83901ec2
SC
374
375 if ( toplevelWindow->GetSize() != formerSize )
376 toplevelWindow->Update() ;
377
f81bfef9
SC
378 result = noErr ;
379 }
380 break ;
e40298d5
JS
381 default :
382 break ;
383 }
384 return result ;
851b3a88
SC
385}
386
387pascal OSStatus wxMacWindowEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
388{
389 OSStatus result = eventNotHandledErr ;
390
391 switch ( GetEventClass( event ) )
392 {
c5c9378c 393 case kEventClassKeyboard :
e40298d5 394 result = KeyboardEventHandler( handler, event , data ) ;
c5c9378c 395 break ;
851b3a88 396 case kEventClassTextInput :
e40298d5 397 result = TextInputEventHandler( handler, event , data ) ;
851b3a88
SC
398 break ;
399 case kEventClassWindow :
e40298d5
JS
400 result = WindowEventHandler( handler, event , data ) ;
401 break ;
851b3a88 402 case kEventClassMouse :
e40298d5
JS
403 result = MouseEventHandler( handler, event , data ) ;
404 break ;
851b3a88
SC
405 default :
406 break ;
407 }
408 return result ;
409}
410
411DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacWindowEventHandler )
412
413#endif
414
5f0b2f22
SC
415// ---------------------------------------------------------------------------
416// wxWindowMac utility functions
417// ---------------------------------------------------------------------------
418
419// Find an item given the Macintosh Window Reference
420
421wxList *wxWinMacWindowList = NULL;
76a5e5d2 422wxTopLevelWindowMac *wxFindWinFromMacWindow(WXWindow inWindowRef)
5f0b2f22 423{
46d0c707
SC
424 if ( wxWinMacWindowList == NULL )
425 return NULL ;
5f0b2f22
SC
426 wxNode *node = wxWinMacWindowList->Find((long)inWindowRef);
427 if (!node)
428 return NULL;
eb22f2a6 429 return (wxTopLevelWindowMac *)node->GetData();
5f0b2f22
SC
430}
431
76a5e5d2 432void wxAssociateWinWithMacWindow(WXWindow inWindowRef, wxTopLevelWindowMac *win)
5f0b2f22
SC
433{
434 // adding NULL WindowRef is (first) surely a result of an error and
435 // (secondly) breaks menu command processing
427ff662 436 wxCHECK_RET( inWindowRef != (WindowRef) NULL, wxT("attempt to add a NULL WindowRef to window list") );
5f0b2f22
SC
437
438 if ( !wxWinMacWindowList->Find((long)inWindowRef) )
439 wxWinMacWindowList->Append((long)inWindowRef, win);
440}
441
442void wxRemoveMacWindowAssociation(wxTopLevelWindowMac *win)
443{
444 wxWinMacWindowList->DeleteObject(win);
445}
446
447
a15eb0a5
SC
448// ----------------------------------------------------------------------------
449// wxTopLevelWindowMac creation
450// ----------------------------------------------------------------------------
451
76a5e5d2 452WXHWND wxTopLevelWindowMac::s_macWindowInUpdate = NULL;
245f3581 453wxTopLevelWindowMac *wxTopLevelWindowMac::s_macDeactivateWindow = NULL;
5f0b2f22 454
a15eb0a5
SC
455void wxTopLevelWindowMac::Init()
456{
457 m_iconized =
458 m_maximizeOnShow = FALSE;
5f0b2f22
SC
459 m_macNoEraseUpdateRgn = NewRgn() ;
460 m_macNeedsErasing = false ;
6a17ca35 461 m_macWindow = NULL ;
851b3a88 462#if TARGET_CARBON
7c091673 463 m_macEventHandler = NULL ;
851b3a88 464 #endif
a15eb0a5
SC
465}
466
118f012e
SC
467class wxMacDeferredWindowDeleter : public wxObject
468{
469public :
1542ea39
RD
470 wxMacDeferredWindowDeleter( WindowRef windowRef )
471 {
472 m_macWindow = windowRef ;
118f012e 473 }
1542ea39
RD
474 virtual ~wxMacDeferredWindowDeleter()
475 {
476 UMADisposeWindow( (WindowRef) m_macWindow ) ;
118f012e
SC
477 }
478 protected :
479 WindowRef m_macWindow ;
480} ;
481
a15eb0a5
SC
482bool wxTopLevelWindowMac::Create(wxWindow *parent,
483 wxWindowID id,
484 const wxString& title,
485 const wxPoint& pos,
486 const wxSize& size,
487 long style,
488 const wxString& name)
489{
490 // init our fields
491 Init();
492
493 m_windowStyle = style;
494
495 SetName(name);
496
497 m_windowId = id == -1 ? NewControlId() : id;
498
499 wxTopLevelWindows.Append(this);
500
501 if ( parent )
502 parent->AddChild(this);
503
504 return TRUE;
505}
506
507wxTopLevelWindowMac::~wxTopLevelWindowMac()
508{
6a17ca35
SC
509 if ( m_macWindow )
510 {
511 wxToolTip::NotifyWindowDelete(m_macWindow) ;
118f012e 512 wxPendingDelete.Append( new wxMacDeferredWindowDeleter( (WindowRef) m_macWindow ) ) ;
6a17ca35 513 }
1542ea39 514
f75363ee 515#if TARGET_CARBON
7c091673
SC
516 if ( m_macEventHandler )
517 {
518 ::RemoveEventHandler((EventHandlerRef) m_macEventHandler);
519 m_macEventHandler = NULL ;
520 }
1542ea39 521#endif
851b3a88 522
5f0b2f22
SC
523 wxRemoveMacWindowAssociation( this ) ;
524
a15eb0a5
SC
525 if ( wxModelessWindows.Find(this) )
526 wxModelessWindows.DeleteObject(this);
527
76a5e5d2 528 DisposeRgn( (RgnHandle) m_macNoEraseUpdateRgn ) ;
a15eb0a5
SC
529}
530
531
532// ----------------------------------------------------------------------------
533// wxTopLevelWindowMac maximize/minimize
534// ----------------------------------------------------------------------------
535
536void wxTopLevelWindowMac::Maximize(bool maximize)
537{
b7aec135
SC
538 ZoomWindow( (WindowRef)m_macWindow , maximize ? inZoomOut : inZoomIn , false ) ;
539
540 Rect tempRect ;
541 GrafPtr port ;
542 GetPort( &port ) ;
543 Point pt = { 0, 0 } ;
544 SetPortWindowPort((WindowRef)m_macWindow) ;
545 LocalToGlobal( &pt ) ;
546 SetPort( port ) ;
547
548 GetWindowPortBounds((WindowRef)m_macWindow, &tempRect ) ;
549 SetSize( pt.h , pt.v , tempRect.right-tempRect.left ,
550 tempRect.bottom-tempRect.top, wxSIZE_USE_EXISTING);
a15eb0a5
SC
551}
552
553bool wxTopLevelWindowMac::IsMaximized() const
554{
b7aec135 555 return IsWindowInStandardState( (WindowRef)m_macWindow , NULL , NULL ) ;
a15eb0a5
SC
556}
557
558void wxTopLevelWindowMac::Iconize(bool iconize)
559{
b7aec135
SC
560 if ( IsWindowCollapsable((WindowRef)m_macWindow) )
561 CollapseWindow((WindowRef)m_macWindow , iconize ) ;
a15eb0a5
SC
562}
563
564bool wxTopLevelWindowMac::IsIconized() const
565{
b7aec135 566 return IsWindowCollapsed((WindowRef)m_macWindow ) ;
a15eb0a5
SC
567}
568
569void wxTopLevelWindowMac::Restore()
570{
571 // not available on mac
572}
573
574// ----------------------------------------------------------------------------
575// wxTopLevelWindowMac misc
576// ----------------------------------------------------------------------------
577
578void wxTopLevelWindowMac::SetIcon(const wxIcon& icon)
579{
580 // this sets m_icon
581 wxTopLevelWindowBase::SetIcon(icon);
582}
5f0b2f22
SC
583
584void wxTopLevelWindowMac::MacCreateRealWindow( const wxString& title,
585 const wxPoint& pos,
586 const wxSize& size,
587 long style,
1542ea39 588 const wxString& name )
5f0b2f22 589{
47ac4f9b 590 OSStatus err = noErr ;
e40298d5
JS
591 SetName(name);
592 m_windowStyle = style;
593 m_isShown = FALSE;
1542ea39 594
e40298d5 595 // create frame.
1542ea39 596
5f0b2f22 597 Rect theBoundsRect;
1542ea39 598
e40298d5
JS
599 m_x = (int)pos.x;
600 m_y = (int)pos.y;
601 if ( m_y < 50 )
602 m_y = 50 ;
603 if ( m_x < 20 )
604 m_x = 20 ;
1542ea39 605
e40298d5 606 m_width = size.x;
1542ea39 607 if (m_width == -1)
5f0b2f22 608 m_width = 20;
e40298d5 609 m_height = size.y;
1542ea39 610 if (m_height == -1)
5f0b2f22 611 m_height = 20;
1542ea39 612
5f0b2f22 613 ::SetRect(&theBoundsRect, m_x, m_y , m_x + m_width, m_y + m_height);
1542ea39 614
5f0b2f22 615 // translate the window attributes in the appropriate window class and attributes
1542ea39 616
5f0b2f22
SC
617 WindowClass wclass = 0;
618 WindowAttributes attr = kWindowNoAttributes ;
1542ea39 619
f5744893 620 if ( HasFlag( wxFRAME_TOOL_WINDOW) )
5f0b2f22 621 {
1542ea39 622 if (
f5744893
SC
623 HasFlag( wxMINIMIZE_BOX ) || HasFlag( wxMAXIMIZE_BOX ) ||
624 HasFlag( wxSYSTEM_MENU ) || HasFlag( wxCAPTION ) ||
625 HasFlag(wxTINY_CAPTION_HORIZ) || HasFlag(wxTINY_CAPTION_VERT)
e40298d5 626 )
5f0b2f22 627 {
f5744893
SC
628 wclass = kFloatingWindowClass ;
629 if ( HasFlag(wxTINY_CAPTION_VERT) )
630 {
631 attr |= kWindowSideTitlebarAttribute ;
632 }
633 }
634 else
635 {
2b5f62a0 636#if TARGET_CARBON
f5744893 637 wclass = kPlainWindowClass ;
2b5f62a0
VZ
638#else
639 wclass = kFloatingWindowClass ;
640#endif
5f0b2f22
SC
641 }
642 }
643 else if ( HasFlag( wxCAPTION ) )
644 {
1542ea39 645 wclass = kDocumentWindowClass ;
5f0b2f22
SC
646 }
647 else
648 {
f5744893 649 if ( HasFlag( wxMINIMIZE_BOX ) || HasFlag( wxMAXIMIZE_BOX ) ||
47ac4f9b 650 HasFlag( wxCLOSE_BOX ) || HasFlag( wxSYSTEM_MENU ) )
f5744893
SC
651 {
652 wclass = kDocumentWindowClass ;
653 }
654 else
655 {
2b5f62a0 656#if TARGET_CARBON
f5744893 657 wclass = kPlainWindowClass ;
2b5f62a0
VZ
658#else
659 wclass = kModalWindowClass ;
660#endif
f5744893 661 }
5f0b2f22 662 }
1542ea39 663
47ac4f9b 664 if ( HasFlag( wxMINIMIZE_BOX ) )
5f0b2f22 665 {
5f0b2f22
SC
666 attr |= kWindowCollapseBoxAttribute ;
667 }
47ac4f9b
SC
668 if ( HasFlag( wxMAXIMIZE_BOX ) )
669 {
670 attr |= kWindowFullZoomAttribute ;
671 }
5f0b2f22
SC
672 if ( HasFlag( wxRESIZE_BORDER ) )
673 {
674 attr |= kWindowResizableAttribute ;
675 }
47ac4f9b 676 if ( HasFlag( wxCLOSE_BOX) )
5f0b2f22
SC
677 {
678 attr |= kWindowCloseBoxAttribute ;
679 }
1542ea39 680
b9c10231
SC
681#if TARGET_CARBON
682#if 0 // having problems right now with that
6a7e6411
RD
683 if (HasFlag(wxSTAY_ON_TOP))
684 wclass = kUtilityWindowClass;
b9c10231
SC
685#endif
686#endif
6a7e6411 687
45ff8005 688#if TARGET_CARBON
6a7e6411
RD
689 if ( HasFlag(wxFRAME_SHAPED) )
690 {
691 WindowDefSpec customWindowDefSpec;
692 customWindowDefSpec.defType = kWindowDefProcPtr;
693 customWindowDefSpec.u.defProc = NewWindowDefUPP(wxShapedMacWindowDef);
694
47ac4f9b 695 err = ::CreateCustomWindow( &customWindowDefSpec, wclass,
6a7e6411
RD
696 attr, &theBoundsRect,
697 (WindowRef*) &m_macWindow);
698 }
699 else
45ff8005 700#endif
6a7e6411 701 {
47ac4f9b 702 err = ::CreateNewWindow( wclass , attr , &theBoundsRect , (WindowRef*)&m_macWindow ) ;
6a7e6411
RD
703 }
704
47ac4f9b 705 wxCHECK_RET( err == noErr, wxT("Mac OS error when trying to create new window") );
5f0b2f22 706 wxAssociateWinWithMacWindow( m_macWindow , this ) ;
427ff662 707 UMASetWTitle( (WindowRef)m_macWindow , title ) ;
76a5e5d2 708 ::CreateRootControl( (WindowRef)m_macWindow , (ControlHandle*)&m_macRootControl ) ;
851b3a88 709#if TARGET_CARBON
e40298d5 710 InstallStandardEventHandler( GetWindowEventTarget(MAC_WXHWND(m_macWindow)) ) ;
1542ea39 711 InstallWindowEventHandler(MAC_WXHWND(m_macWindow), GetwxMacWindowEventHandlerUPP(),
73bdd73a 712 GetEventTypeCount(eventList), eventList, this, (EventHandlerRef *)&m_macEventHandler);
851b3a88 713#endif
5f0b2f22 714 m_macFocus = NULL ;
6a7e6411
RD
715
716
45ff8005 717#if TARGET_CARBON
6a7e6411
RD
718 if ( HasFlag(wxFRAME_SHAPED) )
719 {
720 // default shape matches the window size
721 wxRegion rgn(0, 0, m_width, m_height);
722 SetShape(rgn);
723 }
45ff8005 724#endif
5f0b2f22
SC
725}
726
1542ea39 727void wxTopLevelWindowMac::MacGetPortParams(WXPOINTPTR localOrigin, WXRECTPTR clipRect, WXHWND *window , wxWindowMac** rootwin)
5f0b2f22 728{
76a5e5d2
SC
729 ((Point*)localOrigin)->h = 0;
730 ((Point*)localOrigin)->v = 0;
731 ((Rect*)clipRect)->left = 0;
732 ((Rect*)clipRect)->top = 0;
733 ((Rect*)clipRect)->right = m_width;
734 ((Rect*)clipRect)->bottom = m_height;
5f0b2f22
SC
735 *window = m_macWindow ;
736 *rootwin = this ;
737}
738
5d2e69e8 739void wxTopLevelWindowMac::ClearBackground()
5f0b2f22 740{
5d2e69e8 741 wxWindow::ClearBackground() ;
5f0b2f22
SC
742}
743
1542ea39 744WXWidget wxTopLevelWindowMac::MacGetContainerForEmbedding()
5f0b2f22
SC
745{
746 return m_macRootControl ;
747}
748
749
750void wxTopLevelWindowMac::MacUpdate( long timestamp)
751{
66a09d47 752 wxMacPortStateHelper help( (GrafPtr) GetWindowPort( (WindowRef) m_macWindow) ) ;
76a5e5d2 753
1925be65
SC
754 RgnHandle visRgn = NewRgn() ;
755 GetPortVisibleRegion( GetWindowPort( (WindowRef)m_macWindow ), visRgn );
76a5e5d2 756 BeginUpdate( (WindowRef)m_macWindow ) ;
5f0b2f22 757
1542ea39 758 RgnHandle updateRgn = NewRgn();
5f0b2f22 759 RgnHandle diffRgn = NewRgn() ;
1925be65 760
5f0b2f22
SC
761 if ( updateRgn && diffRgn )
762 {
732b3a75
SC
763#if 1
764 // macos internal control redraws clean up areas we'd like to redraw ourselves
765 // therefore we pick the boundary rect and make sure we can redraw it
1925be65
SC
766 // this has to be intersected by the visRgn in order to avoid drawing over its own
767 // boundaries
732b3a75
SC
768 RgnHandle trueUpdateRgn = NewRgn() ;
769 Rect trueUpdateRgnBoundary ;
770 GetPortVisibleRegion( GetWindowPort( (WindowRef)m_macWindow ), trueUpdateRgn );
771 GetRegionBounds( trueUpdateRgn , &trueUpdateRgnBoundary ) ;
1925be65
SC
772 RectRgn( updateRgn , &trueUpdateRgnBoundary ) ;
773 SectRgn( updateRgn , visRgn , updateRgn ) ;
732b3a75
SC
774 if ( trueUpdateRgn )
775 DisposeRgn( trueUpdateRgn ) ;
776 SetPortVisibleRegion( GetWindowPort( (WindowRef)m_macWindow ), updateRgn ) ;
777#else
76a5e5d2 778 GetPortVisibleRegion( GetWindowPort( (WindowRef)m_macWindow ), updateRgn );
732b3a75 779#endif
76a5e5d2 780 DiffRgn( updateRgn , (RgnHandle) m_macNoEraseUpdateRgn , diffRgn ) ;
5f0b2f22
SC
781 if ( !EmptyRgn( updateRgn ) )
782 {
783 MacRedraw( updateRgn , timestamp , m_macNeedsErasing || !EmptyRgn( diffRgn ) ) ;
784 }
785 }
786 if ( updateRgn )
787 DisposeRgn( updateRgn );
788 if ( diffRgn )
789 DisposeRgn( diffRgn );
1925be65
SC
790 if ( visRgn )
791 DisposeRgn( visRgn ) ;
5d2e69e8 792
76a5e5d2
SC
793 EndUpdate( (WindowRef)m_macWindow ) ;
794 SetEmptyRgn( (RgnHandle) m_macNoEraseUpdateRgn ) ;
5f0b2f22
SC
795 m_macNeedsErasing = false ;
796}
797
798
799// Raise the window to the top of the Z order
800void wxTopLevelWindowMac::Raise()
801{
7f3c339c 802 ::SelectWindow( (WindowRef)m_macWindow ) ;
5f0b2f22
SC
803}
804
805// Lower the window to the bottom of the Z order
806void wxTopLevelWindowMac::Lower()
807{
76a5e5d2 808 ::SendBehind( (WindowRef)m_macWindow , NULL ) ;
5f0b2f22
SC
809}
810
1542ea39 811void wxTopLevelWindowMac::MacFireMouseEvent(
e40298d5 812 wxUint16 kind , wxInt32 x , wxInt32 y ,wxUint32 modifiers , long timestamp )
5f0b2f22
SC
813{
814 wxMouseEvent event(wxEVT_LEFT_DOWN);
851b3a88
SC
815 bool isDown = !(modifiers & btnState) ; // 1 is for up
816 bool controlDown = modifiers & controlKey ; // for simulating right mouse
1542ea39 817
5f0b2f22 818 event.m_leftDown = isDown && !controlDown;
1542ea39 819
5f0b2f22
SC
820 event.m_middleDown = FALSE;
821 event.m_rightDown = isDown && controlDown;
822
851b3a88 823 if ( kind == mouseDown )
5f0b2f22
SC
824 {
825 if ( controlDown )
826 event.SetEventType(wxEVT_RIGHT_DOWN ) ;
827 else
828 event.SetEventType(wxEVT_LEFT_DOWN ) ;
829 }
851b3a88 830 else if ( kind == mouseUp )
5f0b2f22
SC
831 {
832 if ( controlDown )
833 event.SetEventType(wxEVT_RIGHT_UP ) ;
834 else
835 event.SetEventType(wxEVT_LEFT_UP ) ;
836 }
837 else
838 {
839 event.SetEventType(wxEVT_MOTION ) ;
840 }
841
851b3a88
SC
842 event.m_shiftDown = modifiers & shiftKey;
843 event.m_controlDown = modifiers & controlKey;
844 event.m_altDown = modifiers & optionKey;
845 event.m_metaDown = modifiers & cmdKey;
5f0b2f22 846
851b3a88
SC
847 Point localwhere ;
848 localwhere.h = x ;
849 localwhere.v = y ;
1542ea39
RD
850
851 GrafPtr port ;
5f0b2f22 852 ::GetPort( &port ) ;
76a5e5d2 853 ::SetPort( UMAGetWindowPort( (WindowRef)m_macWindow ) ) ;
5f0b2f22
SC
854 ::GlobalToLocal( &localwhere ) ;
855 ::SetPort( port ) ;
856
851b3a88 857 if ( kind == mouseDown )
5f0b2f22 858 {
5be55d56 859 if ( timestamp - gs_lastWhen <= (long) GetDblTime() )
5f0b2f22 860 {
32b5be3d 861 if ( abs( localwhere.h - gs_lastWhere.h ) < 3 && abs( localwhere.v - gs_lastWhere.v ) < 3 )
5f0b2f22 862 {
32b5be3d
RR
863 // This is not right if the second mouse down
864 // event occured in a differen window. We
865 // correct this in MacDispatchMouseEvent.
5f0b2f22
SC
866 if ( controlDown )
867 event.SetEventType(wxEVT_RIGHT_DCLICK ) ;
868 else
869 event.SetEventType(wxEVT_LEFT_DCLICK ) ;
870 }
32b5be3d 871 gs_lastWhen = 0 ;
5f0b2f22
SC
872 }
873 else
874 {
851b3a88 875 gs_lastWhen = timestamp ;
5f0b2f22 876 }
32b5be3d 877 gs_lastWhere = localwhere ;
5f0b2f22
SC
878 }
879
880 event.m_x = localwhere.h;
881 event.m_y = localwhere.v;
882 event.m_x += m_x;
883 event.m_y += m_y;
884
851b3a88 885 event.m_timeStamp = timestamp;
5f0b2f22
SC
886 event.SetEventObject(this);
887 if ( wxTheApp->s_captureWindow )
888 {
889 int x = event.m_x ;
890 int y = event.m_y ;
891 wxTheApp->s_captureWindow->ScreenToClient( &x , &y ) ;
892 event.m_x = x ;
893 event.m_y = y ;
2e6857fa 894 event.SetEventObject( wxTheApp->s_captureWindow ) ;
5f0b2f22 895 wxTheApp->s_captureWindow->GetEventHandler()->ProcessEvent( event ) ;
1542ea39 896
851b3a88 897 if ( kind == mouseUp )
5f0b2f22
SC
898 {
899 wxTheApp->s_captureWindow = NULL ;
6b57b49a 900 if ( !wxIsBusy() )
5f0b2f22
SC
901 {
902 m_cursor.MacInstall() ;
903 }
904 }
905 }
906 else
907 {
908 MacDispatchMouseEvent( event ) ;
909 }
910}
e40298d5 911
851b3a88 912#if !TARGET_CARBON
5f0b2f22 913
76a5e5d2 914void wxTopLevelWindowMac::MacMouseDown( WXEVENTREF ev , short part)
5f0b2f22 915{
1542ea39 916 MacFireMouseEvent( mouseDown , ((EventRecord*)ev)->where.h , ((EventRecord*)ev)->where.v ,
e40298d5 917 ((EventRecord*)ev)->modifiers , ((EventRecord*)ev)->when ) ;
5f0b2f22
SC
918}
919
76a5e5d2 920void wxTopLevelWindowMac::MacMouseUp( WXEVENTREF ev , short part)
5f0b2f22
SC
921{
922 switch (part)
923 {
1542ea39 924 case inContent:
5f0b2f22 925 {
1542ea39 926 MacFireMouseEvent( mouseUp , ((EventRecord*)ev)->where.h , ((EventRecord*)ev)->where.v ,
e40298d5 927 ((EventRecord*)ev)->modifiers , ((EventRecord*)ev)->when ) ;
5f0b2f22
SC
928 }
929 break ;
930 }
931}
932
76a5e5d2 933void wxTopLevelWindowMac::MacMouseMoved( WXEVENTREF ev , short part)
5f0b2f22
SC
934{
935 switch (part)
936 {
1542ea39 937 case inContent:
5f0b2f22 938 {
1542ea39 939 MacFireMouseEvent( nullEvent /*moved*/ , ((EventRecord*)ev)->where.h , ((EventRecord*)ev)->where.v ,
e40298d5 940 ((EventRecord*)ev)->modifiers , ((EventRecord*)ev)->when ) ;
5f0b2f22
SC
941 }
942 break ;
943 }
944}
851b3a88
SC
945
946#endif
947
245f3581
DE
948void wxTopLevelWindowMac::MacDelayedDeactivation(long timestamp)
949{
950 if(s_macDeactivateWindow)
951 {
365796b1 952 wxLogDebug(wxT("Doing delayed deactivation of %p"),s_macDeactivateWindow);
245f3581
DE
953 s_macDeactivateWindow->MacActivate(timestamp, false);
954 }
955}
956
851b3a88 957void wxTopLevelWindowMac::MacActivate( long timestamp , bool inIsActivating )
5f0b2f22 958{
17f8d2a7
VZ
959 // wxLogDebug(wxT("TopLevel=%p::MacActivate"),this);
960
245f3581
DE
961 if(s_macDeactivateWindow==this)
962 s_macDeactivateWindow=NULL;
963 MacDelayedDeactivation(timestamp);
5f0b2f22 964 wxActivateEvent event(wxEVT_ACTIVATE, inIsActivating , m_windowId);
851b3a88 965 event.m_timeStamp = timestamp ;
5f0b2f22 966 event.SetEventObject(this);
1542ea39 967
5f0b2f22 968 GetEventHandler()->ProcessEvent(event);
1542ea39 969
76a5e5d2 970 UMAHighlightAndActivateWindow( (WindowRef)m_macWindow , inIsActivating ) ;
1542ea39 971
a006e78b
JS
972 // Early versions of MacOS X don't refresh backgrounds properly,
973 // so refresh the whole window on activation and deactivation.
974 long osVersion = UMAGetSystemVersion();
1925be65 975 if (osVersion >= 0x1000 && osVersion < 0x1020 )
732b3a75 976 {
a006e78b 977 Refresh(TRUE);
732b3a75 978 }
a006e78b 979 else
732b3a75
SC
980 {
981 // for the moment we have to resolve some redrawing issues like this
982 // the OS is stealing some redrawing areas as soon as it draws a control
983 Refresh(TRUE);
984 }
5f0b2f22
SC
985}
986
851b3a88
SC
987#if !TARGET_CARBON
988
1542ea39 989void wxTopLevelWindowMac::MacKeyDown( WXEVENTREF ev )
5f0b2f22
SC
990{
991}
992
851b3a88
SC
993#endif
994
5f0b2f22
SC
995void wxTopLevelWindowMac::SetTitle(const wxString& title)
996{
997 wxWindow::SetTitle( title ) ;
427ff662 998 UMASetWTitle( (WindowRef)m_macWindow , title ) ;
5f0b2f22
SC
999}
1000
1001bool wxTopLevelWindowMac::Show(bool show)
1002{
1003 if ( !wxWindow::Show(show) )
1004 return FALSE;
1005
1006 if (show)
1542ea39 1007 {
1925be65 1008 ::TransitionWindow((WindowRef)m_macWindow,kWindowZoomTransitionEffect,kWindowShowTransitionAction,nil);
76a5e5d2 1009 ::SelectWindow( (WindowRef)m_macWindow ) ;
5f0b2f22
SC
1010 // no need to generate events here, they will get them triggered by macos
1011 // actually they should be , but apparently they are not
1012 wxSize size(m_width, m_height);
1013 wxSizeEvent event(size, m_windowId);
1014 event.SetEventObject(this);
1015 GetEventHandler()->ProcessEvent(event);
1016 }
1017 else
1018 {
1925be65 1019 ::TransitionWindow((WindowRef)m_macWindow,kWindowZoomTransitionEffect,kWindowHideTransitionAction,nil);
5f0b2f22
SC
1020 }
1021
1022 if ( !show )
1023 {
1024 }
1025 else
1026 {
1542ea39 1027 Refresh() ;
5f0b2f22
SC
1028 }
1029
1030 return TRUE;
1031}
1032
1033void wxTopLevelWindowMac::DoMoveWindow(int x, int y, int width, int height)
1034{
1035 int former_x = m_x ;
1036 int former_y = m_y ;
1037 int former_w = m_width ;
1038 int former_h = m_height ;
1542ea39 1039
e40298d5
JS
1040 int actualWidth = width;
1041 int actualHeight = height;
1042 int actualX = x;
1043 int actualY = y;
1542ea39
RD
1044
1045 if ((m_minWidth != -1) && (actualWidth < m_minWidth))
5f0b2f22 1046 actualWidth = m_minWidth;
1542ea39 1047 if ((m_minHeight != -1) && (actualHeight < m_minHeight))
5f0b2f22 1048 actualHeight = m_minHeight;
1542ea39 1049 if ((m_maxWidth != -1) && (actualWidth > m_maxWidth))
5f0b2f22 1050 actualWidth = m_maxWidth;
1542ea39 1051 if ((m_maxHeight != -1) && (actualHeight > m_maxHeight))
5f0b2f22
SC
1052 actualHeight = m_maxHeight;
1053
1054 bool doMove = false ;
1055 bool doResize = false ;
1542ea39 1056
5f0b2f22
SC
1057 if ( actualX != former_x || actualY != former_y )
1058 {
1059 doMove = true ;
1060 }
1061 if ( actualWidth != former_w || actualHeight != former_h )
1062 {
1063 doResize = true ;
1064 }
1065
1066 if ( doMove || doResize )
1067 {
1068 m_x = actualX ;
1069 m_y = actualY ;
1070 m_width = actualWidth ;
1071 m_height = actualHeight ;
1072
1073 if ( doMove )
76a5e5d2 1074 ::MoveWindow((WindowRef)m_macWindow, m_x, m_y , false); // don't make frontmost
1542ea39 1075
5f0b2f22 1076 if ( doResize )
1542ea39
RD
1077 ::SizeWindow((WindowRef)m_macWindow, m_width, m_height , true);
1078
2b5f62a0
VZ
1079 // the OS takes care of invalidating and erasing the new area so we only have to
1080 // take care of refreshing for full repaints
1081
1082 if ( doResize && !HasFlag(wxNO_FULL_REPAINT_ON_RESIZE) )
1083 Refresh() ;
1542ea39
RD
1084
1085
5f0b2f22
SC
1086 if ( IsKindOf( CLASSINFO( wxFrame ) ) )
1087 {
1088 wxFrame* frame = (wxFrame*) this ;
1089 frame->PositionStatusBar();
1090 frame->PositionToolBar();
1091 }
1092 if ( doMove )
1093 wxWindowMac::MacTopLevelWindowChangedPosition() ; // like this only children will be notified
1094
1095 MacRepositionScrollBars() ;
1096 if ( doMove )
1097 {
1098 wxPoint point(m_x, m_y);
1099 wxMoveEvent event(point, m_windowId);
1100 event.SetEventObject(this);
1101 GetEventHandler()->ProcessEvent(event) ;
1102 }
1103 if ( doResize )
1104 {
1105 MacRepositionScrollBars() ;
1106 wxSize size(m_width, m_height);
1107 wxSizeEvent event(size, m_windowId);
1108 event.SetEventObject(this);
1109 GetEventHandler()->ProcessEvent(event);
1110 }
1111 }
1542ea39 1112
5f0b2f22
SC
1113}
1114
1115/*
1116 * Invalidation Mechanism
1117 *
1118 * The update mechanism reflects exactely the windows mechanism
1119 * the rect gets added to the window invalidate region, if the eraseBackground flag
1120 * has been true for any part of the update rgn the background is erased in the entire region
1121 * not just in the specified rect.
1122 *
1542ea39 1123 * In order to achive this, we also have an internal m_macNoEraseUpdateRgn, all rects that have
5f0b2f22
SC
1124 * the eraseBackground flag set to false are also added to this rgn. upon receiving an update event
1125 * the update rgn is compared to the m_macNoEraseUpdateRgn and in case they differ, every window
1126 * will get the eraseBackground event first
1127 */
1542ea39
RD
1128
1129void wxTopLevelWindowMac::MacInvalidate( const WXRECTPTR rect, bool eraseBackground )
5f0b2f22 1130{
e40298d5
JS
1131 GrafPtr formerPort ;
1132 GetPort( &formerPort ) ;
1133 SetPortWindowPort( (WindowRef)m_macWindow ) ;
1542ea39 1134
e40298d5 1135 m_macNeedsErasing |= eraseBackground ;
1542ea39 1136
e40298d5
JS
1137 // if we already know that we will have to erase, there's no need to track the rest
1138 if ( !m_macNeedsErasing)
5f0b2f22 1139 {
e40298d5
JS
1140 // we end only here if eraseBackground is false
1141 // if we already have a difference between m_macNoEraseUpdateRgn and UpdateRgn
1142 // we will have to erase anyway
1542ea39
RD
1143
1144 RgnHandle updateRgn = NewRgn();
e40298d5
JS
1145 RgnHandle diffRgn = NewRgn() ;
1146 if ( updateRgn && diffRgn )
1147 {
1148 GetWindowUpdateRgn( (WindowRef)m_macWindow , updateRgn );
1149 Point pt = {0,0} ;
1150 LocalToGlobal( &pt ) ;
1151 OffsetRgn( updateRgn , -pt.h , -pt.v ) ;
1152 DiffRgn( updateRgn , (RgnHandle) m_macNoEraseUpdateRgn , diffRgn ) ;
1153 if ( !EmptyRgn( diffRgn ) )
1154 {
1155 m_macNeedsErasing = true ;
1156 }
1157 }
1158 if ( updateRgn )
1159 DisposeRgn( updateRgn );
1160 if ( diffRgn )
1161 DisposeRgn( diffRgn );
1542ea39 1162
e40298d5 1163 if ( !m_macNeedsErasing )
5f0b2f22 1164 {
e40298d5
JS
1165 RgnHandle rectRgn = NewRgn() ;
1166 SetRectRgn( rectRgn , ((Rect*)rect)->left , ((Rect*)rect)->top , ((Rect*)rect)->right , ((Rect*)rect)->bottom ) ;
1167 UnionRgn( (RgnHandle) m_macNoEraseUpdateRgn , rectRgn , (RgnHandle) m_macNoEraseUpdateRgn ) ;
1168 DisposeRgn( rectRgn ) ;
5f0b2f22
SC
1169 }
1170 }
e40298d5
JS
1171 InvalWindowRect( (WindowRef)m_macWindow , (Rect*)rect ) ;
1172 // turn this on to debug the refreshing cycle
34dc8f91 1173#if wxMAC_DEBUG_REDRAW
e40298d5 1174 PaintRect( rect ) ;
5f0b2f22 1175#endif
e40298d5 1176 SetPort( formerPort ) ;
5f0b2f22 1177}
a07c1212 1178
6a7e6411 1179
1542ea39
RD
1180bool wxTopLevelWindowMac::SetShape(const wxRegion& region)
1181{
6a7e6411
RD
1182 wxCHECK_MSG( HasFlag(wxFRAME_SHAPED), FALSE,
1183 _T("Shaped windows must be created with the wxFRAME_SHAPED style."));
1184
45ff8005 1185#if TARGET_CARBON
6a7e6411
RD
1186 // The empty region signifies that the shape should be removed from the
1187 // window.
1188 if ( region.IsEmpty() )
1189 {
1190 wxSize sz = GetClientSize();
1191 wxRegion rgn(0, 0, sz.x, sz.y);
1192 return SetShape(rgn);
1193 }
1194
1195 // Make a copy of the region
1196 RgnHandle shapeRegion = NewRgn();
1197 CopyRgn( (RgnHandle)region.GetWXHRGN(), shapeRegion );
1198
1199 // Dispose of any shape region we may already have
1200 RgnHandle oldRgn = (RgnHandle)GetWRefCon( (WindowRef)MacGetWindowRef() );
1201 if ( oldRgn )
1202 DisposeRgn(oldRgn);
1203
1204 // Save the region so we can use it later
1205 SetWRefCon((WindowRef)MacGetWindowRef(), (SInt32)shapeRegion);
1206
1207 // Tell the window manager that the window has changed shape
1208 ReshapeCustomWindow((WindowRef)MacGetWindowRef());
1209 return TRUE;
45ff8005
RD
1210#else
1211 return FALSE;
1212#endif
6a7e6411
RD
1213}
1214
6a7e6411
RD
1215// ---------------------------------------------------------------------------
1216// Support functions for shaped windows, based on Apple's CustomWindow sample at
1217// http://developer.apple.com/samplecode/Sample_Code/Human_Interface_Toolbox/Mac_OS_High_Level_Toolbox/CustomWindow.htm
1218// ---------------------------------------------------------------------------
1219
45ff8005 1220#if TARGET_CARBON
1925be65 1221
6a7e6411
RD
1222static void wxShapedMacWindowGetPos(WindowRef window, Rect* inRect)
1223{
1224 GetWindowPortBounds(window, inRect);
1225 Point pt = {inRect->left, inRect->top};
1226 SetPort((GrafPtr) GetWindowPort(window));
1227 LocalToGlobal(&pt);
1228 inRect->top = pt.v;
1229 inRect->left = pt.h;
1230 inRect->bottom += pt.v;
1231 inRect->right += pt.h;
1232}
1233
1234
1235static SInt32 wxShapedMacWindowGetFeatures(WindowRef window, SInt32 param)
1236{
1237 /*------------------------------------------------------
1238 Define which options your custom window supports.
1239 --------------------------------------------------------*/
1240 //just enable everything for our demo
1241 *(OptionBits*)param=//kWindowCanGrow|
1242 //kWindowCanZoom|
1243 //kWindowCanCollapse|
1244 //kWindowCanGetWindowRegion|
1245 //kWindowHasTitleBar|
1246 //kWindowSupportsDragHilite|
1247 kWindowCanDrawInCurrentPort|
1248 //kWindowCanMeasureTitle|
1249 kWindowWantsDisposeAtProcessDeath|
1250 kWindowSupportsSetGrowImageRegion|
1251 kWindowDefSupportsColorGrafPort;
1252 return 1;
1542ea39 1253}
6a7e6411
RD
1254
1255// The content region is left as a rectangle matching the window size, this is
1256// so the origin in the paint event, and etc. still matches what the
1257// programmer expects.
1258static void wxShapedMacWindowContentRegion(WindowRef window, RgnHandle rgn)
1259{
1260 SetEmptyRgn(rgn);
1261 wxTopLevelWindowMac* win = wxFindWinFromMacWindow(window);
1262 if (win)
1263 {
1264 wxRect r = win->GetRect();
1265 SetRectRgn(rgn, r.GetLeft(), r.GetTop(), r.GetRight(), r.GetBottom());
1266 }
1267}
1268
1269// The structure region is set to the shape given to the SetShape method.
1270static void wxShapedMacWindowStructureRegion(WindowRef window, RgnHandle rgn)
1271{
1272 RgnHandle cachedRegion = (RgnHandle) GetWRefCon(window);
1273
1274 SetEmptyRgn(rgn);
1275 if (cachedRegion)
1276 {
1277 Rect windowRect;
1278 wxShapedMacWindowGetPos(window, &windowRect); //how big is the window
1279 CopyRgn(cachedRegion, rgn); //make a copy of our cached region
1280 OffsetRgn(rgn, windowRect.left, windowRect.top); // position it over window
1281 //MapRgn(rgn, &mMaskSize, &windowRect); //scale it to our actual window size
1282 }
1283}
1284
1285
1286
1287static SInt32 wxShapedMacWindowGetRegion(WindowRef window, SInt32 param)
1288{
1289 GetWindowRegionPtr rgnRec=(GetWindowRegionPtr)param;
1290
1291 switch(rgnRec->regionCode)
1292 {
1293 case kWindowStructureRgn:
1294 wxShapedMacWindowStructureRegion(window, rgnRec->winRgn);
1295 break;
1296 case kWindowContentRgn:
1297 wxShapedMacWindowContentRegion(window, rgnRec->winRgn);
1298 break;
1299 default:
1300 SetEmptyRgn(rgnRec->winRgn);
1301 } //switch
1302
1303 return noErr;
1304}
1305
1306
1307static SInt32 wxShapedMacWindowHitTest(WindowRef window,SInt32 param)
1308{
1309 /*------------------------------------------------------
1310 Determine the region of the window which was hit
1311 --------------------------------------------------------*/
1312 Point hitPoint;
1313 static RgnHandle tempRgn=nil;
1314
1315 if(!tempRgn)
1316 tempRgn=NewRgn();
1317
1318 SetPt(&hitPoint,LoWord(param),HiWord(param));//get the point clicked
1319
1320 //Mac OS 8.5 or later
1321 wxShapedMacWindowStructureRegion(window, tempRgn);
1322 if (PtInRgn(hitPoint, tempRgn)) //in window content region?
1323 return wInContent;
1324
1325 return wNoHit;//no significant area was hit.
1326}
1327
1328
1329static pascal long wxShapedMacWindowDef(short varCode, WindowRef window, SInt16 message, SInt32 param)
1330{
1331 switch(message)
1332 {
1333 case kWindowMsgHitTest:
1334 return wxShapedMacWindowHitTest(window,param);
1335
1336 case kWindowMsgGetFeatures:
1337 return wxShapedMacWindowGetFeatures(window,param);
1338
1339 // kWindowMsgGetRegion is sent during CreateCustomWindow and ReshapeCustomWindow
1340 case kWindowMsgGetRegion:
1341 return wxShapedMacWindowGetRegion(window,param);
1342 }
1343
1344 return 0;
1345}
1925be65 1346
45ff8005 1347#endif
6a7e6411 1348// ---------------------------------------------------------------------------
1925be65 1349