]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/window.cpp
Use wxStdDialogButtonSizer
[wxWidgets.git] / src / mac / carbon / window.cpp
CommitLineData
e9576ca5 1/////////////////////////////////////////////////////////////////////////////
fb5246be 2// Name: src/mac/carbon/window.cpp
e766c8a9 3// Purpose: wxWindowMac
a31a5f85 4// Author: Stefan Csomor
e9576ca5 5// Modified by:
a31a5f85 6// Created: 1998-01-01
e9576ca5 7// RCS-ID: $Id$
a31a5f85 8// Copyright: (c) Stefan Csomor
65571936 9// Licence: wxWindows licence
e9576ca5
SC
10/////////////////////////////////////////////////////////////////////////////
11
3d1a4878
SC
12#include "wx/wxprec.h"
13
5fde6fcc 14#include "wx/window.h"
e4db172a
WS
15
16#ifndef WX_PRECOMP
17 #include "wx/log.h"
670f9935 18 #include "wx/app.h"
de6185e2 19 #include "wx/utils.h"
8e609c82 20 #include "wx/panel.h"
76b49cf4 21 #include "wx/frame.h"
da80ae71 22 #include "wx/dc.h"
ed4b0fdc 23 #include "wx/dcclient.h"
f1e01716 24 #include "wx/button.h"
3b3dc801 25 #include "wx/menu.h"
fdf565fe 26 #include "wx/dialog.h"
9eddec69 27 #include "wx/settings.h"
246c5004 28 #include "wx/msgdlg.h"
851dee09 29 #include "wx/scrolbar.h"
876cd6f7 30 #include "wx/statbox.h"
fec9cc08 31 #include "wx/textctrl.h"
4e3e485b 32 #include "wx/toolbar.h"
ed2fbeb8 33 #include "wx/layout.h"
3304646d 34 #include "wx/statusbr.h"
25466131 35 #include "wx/menuitem.h"
ed9a7a63
KO
36 #include "wx/treectrl.h"
37 #include "wx/listctrl.h"
e4db172a
WS
38#endif
39
2f1ae414 40#include "wx/tooltip.h"
4ac219f6 41#include "wx/spinctrl.h"
467e3168 42#include "wx/geometry.h"
e9576ca5 43
c1cef60b
CE
44#if wxUSE_LISTCTRL
45 #include "wx/listctrl.h"
46#endif
47
48#if wxUSE_TREECTRL
49 #include "wx/treectrl.h"
50#endif
51
7c551d95
SC
52#if wxUSE_CARET
53 #include "wx/caret.h"
e15f0a5e 54#endif
7c551d95 55
6239ee05
SC
56#if wxUSE_POPUPWIN
57 #include "wx/popupwin.h"
58#endif
59
b46dde27
DS
60#if wxUSE_DRAG_AND_DROP
61#include "wx/dnd.h"
62#endif
519cb848 63
d497dca4 64#include "wx/mac/uma.h"
898d9035 65
b46dde27
DS
66#define MAC_SCROLLBAR_SIZE 15
67#define MAC_SMALL_SCROLLBAR_SIZE 11
68
e9576ca5
SC
69#include <string.h>
70
fc0daf84
SC
71#ifdef __WXUNIVERSAL__
72 IMPLEMENT_ABSTRACT_CLASS(wxWindowMac, wxWindowBase)
898d9035 73#else
fc0daf84 74 IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowBase)
898d9035 75#endif
fc0daf84 76
fc0daf84 77BEGIN_EVENT_TABLE(wxWindowMac, wxWindowBase)
facd6764
SC
78 EVT_NC_PAINT(wxWindowMac::OnNcPaint)
79 EVT_ERASE_BACKGROUND(wxWindowMac::OnEraseBackground)
ff3795ee 80 EVT_PAINT(wxWindowMac::OnPaint)
5ca0d812
SC
81 EVT_SET_FOCUS(wxWindowMac::OnSetFocus)
82 EVT_KILL_FOCUS(wxWindowMac::OnSetFocus)
facd6764 83 EVT_MOUSE_EVENTS(wxWindowMac::OnMouseEvent)
e9576ca5
SC
84END_EVENT_TABLE()
85
94abc21f
SC
86#define wxMAC_DEBUG_REDRAW 0
87#ifndef wxMAC_DEBUG_REDRAW
88#define wxMAC_DEBUG_REDRAW 0
89#endif
90
42ef83fa
SC
91// ---------------------------------------------------------------------------
92// Utility Routines to move between different coordinate systems
93// ---------------------------------------------------------------------------
94
95/*
96 * Right now we have the following setup :
97 * a border that is not part of the native control is always outside the
98 * control's border (otherwise we loose all native intelligence, future ways
99 * may be to have a second embedding control responsible for drawing borders
100 * and backgrounds eventually)
101 * so all this border calculations have to be taken into account when calling
102 * native methods or getting native oriented data
103 * so we have three coordinate systems here
104 * wx client coordinates
105 * wx window coordinates (including window frames)
106 * native coordinates
107 */
8b573fb8 108
42ef83fa
SC
109//
110// originating from native control
111//
112
113
114void wxMacNativeToWindow( const wxWindow* window , RgnHandle handle )
115{
8b573fb8 116 OffsetRgn( handle , window->MacGetLeftBorderSize() , window->MacGetTopBorderSize() ) ;
42ef83fa
SC
117}
118
119void wxMacNativeToWindow( const wxWindow* window , Rect *rect )
120{
8b573fb8 121 OffsetRect( rect , window->MacGetLeftBorderSize() , window->MacGetTopBorderSize() ) ;
42ef83fa
SC
122}
123
124//
125// directed towards native control
126//
127
128void wxMacWindowToNative( const wxWindow* window , RgnHandle handle )
129{
8b573fb8 130 OffsetRgn( handle , -window->MacGetLeftBorderSize() , -window->MacGetTopBorderSize() );
42ef83fa
SC
131}
132
133void wxMacWindowToNative( const wxWindow* window , Rect *rect )
134{
8b573fb8 135 OffsetRect( rect , -window->MacGetLeftBorderSize() , -window->MacGetTopBorderSize() ) ;
42ef83fa
SC
136}
137
facd6764
SC
138// ---------------------------------------------------------------------------
139// Carbon Events
140// ---------------------------------------------------------------------------
8b573fb8 141
facd6764
SC
142static const EventTypeSpec eventList[] =
143{
e3aeade0
SC
144 { kEventClassCommand, kEventProcessCommand } ,
145 { kEventClassCommand, kEventCommandUpdateStatus } ,
b46dde27 146
e9a4bf7d 147 { kEventClassControl , kEventControlGetClickActivation } ,
f1d527c1 148 { kEventClassControl , kEventControlHit } ,
898d9035 149
980ee83f
SC
150 { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent } ,
151 { kEventClassTextInput, kEventTextInputUpdateActiveInputArea } ,
b46dde27 152
73fe67bd 153 { kEventClassControl , kEventControlDraw } ,
8e181eae 154
73fe67bd
SC
155 { kEventClassControl , kEventControlVisibilityChanged } ,
156 { kEventClassControl , kEventControlEnabledStateChanged } ,
157 { kEventClassControl , kEventControlHiliteChanged } ,
ed9a7a63
KO
158
159 { kEventClassControl , kEventControlActivate } ,
160 { kEventClassControl , kEventControlDeactivate } ,
8e181eae 161
f1d527c1 162 { kEventClassControl , kEventControlSetFocusPart } ,
8b573fb8
VZ
163
164 { kEventClassService , kEventServiceGetTypes },
165 { kEventClassService , kEventServiceCopy },
166 { kEventClassService , kEventServicePaste },
167
898d9035
DS
168// { kEventClassControl , kEventControlInvalidateForSizeChange } , // 10.3 only
169// { kEventClassControl , kEventControlBoundsChanged } ,
facd6764
SC
170} ;
171
172static pascal OSStatus wxMacWindowControlEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
173{
174 OSStatus result = eventNotHandledErr ;
175
176 wxMacCarbonEvent cEvent( event ) ;
8b573fb8 177
facd6764
SC
178 ControlRef controlRef ;
179 wxWindowMac* thisWindow = (wxWindowMac*) data ;
180
181 cEvent.GetParameter( kEventParamDirectObject , &controlRef ) ;
182
898d9035 183 switch ( GetEventKind( event ) )
facd6764
SC
184 {
185 case kEventControlDraw :
186 {
1e8cde71 187 RgnHandle updateRgn = NULL ;
055a486b 188 RgnHandle allocatedRgn = NULL ;
1e8cde71 189 wxRegion visRegion = thisWindow->MacGetVisibleRegion() ;
898d9035 190
76c7012c 191 if ( cEvent.GetParameter<RgnHandle>(kEventParamRgnHandle, &updateRgn) != noErr )
1e8cde71
SC
192 {
193 updateRgn = (RgnHandle) visRegion.GetWXHRGN() ;
194 }
055a486b
SC
195 else
196 {
a9b456ff 197 if ( thisWindow->MacGetLeftBorderSize() != 0 || thisWindow->MacGetTopBorderSize() != 0 )
055a486b 198 {
a9b456ff 199 // as this update region is in native window locals we must adapt it to wx window local
055a486b
SC
200 allocatedRgn = NewRgn() ;
201 CopyRgn( updateRgn , allocatedRgn ) ;
898d9035 202
42ef83fa
SC
203 // hide the given region by the new region that must be shifted
204 wxMacNativeToWindow( thisWindow , allocatedRgn ) ;
902725ee 205 updateRgn = allocatedRgn ;
e6616741 206 }
055a486b 207 }
e15f0a5e 208
1f1c8bd4 209#if wxMAC_DEBUG_REDRAW
facd6764
SC
210 if ( thisWindow->MacIsUserPane() )
211 {
bcbd6987
SC
212 static float color = 0.5 ;
213 static channel = 0 ;
898d9035
DS
214 HIRect bounds;
215 CGContextRef cgContext = cEvent.GetParameter<CGContextRef>(kEventParamCGContextRef) ;
216
217 HIViewGetBounds( controlRef, &bounds );
8b573fb8
VZ
218 CGContextSetRGBFillColor( cgContext, channel == 0 ? color : 0.5 ,
219 channel == 1 ? color : 0.5 , channel == 2 ? color : 0.5 , 1 );
220 CGContextFillRect( cgContext, bounds );
221 color += 0.1 ;
222 if ( color > 0.9 )
223 {
224 color = 0.5 ;
225 channel++ ;
226 if ( channel == 3 )
227 channel = 0 ;
228 }
facd6764 229 }
20b69855 230#endif
898d9035 231
c79aad8b 232 {
e6616741 233 bool created = false ;
8523a5f5 234 CGContextRef cgContext = NULL ;
a9b456ff
SC
235 OSStatus err = cEvent.GetParameter<CGContextRef>(kEventParamCGContextRef, &cgContext) ;
236 wxASSERT_MSG( err == noErr , wxT("Unable to retrieve CGContextRef") ) ;
c79aad8b 237 thisWindow->MacSetCGContextRef( cgContext ) ;
898d9035 238
e6616741
SC
239 {
240 wxMacCGContextStateSaver sg( cgContext ) ;
a9b456ff
SC
241 float alpha = 1.0 ;
242 {
243 wxWindow* iter = thisWindow ;
89954433 244 while ( iter )
a9b456ff
SC
245 {
246 alpha *= (float) iter->GetTransparent()/255.0 ;
247 if ( iter->IsTopLevel() )
248 iter = NULL ;
249 else
250 iter = iter->GetParent() ;
251 }
252 }
253 CGContextSetAlpha( cgContext , alpha ) ;
4488a1d3
VZ
254
255 if ( thisWindow->GetBackgroundStyle() == wxBG_STYLE_TRANSPARENT )
256 {
257 HIRect bounds;
258 HIViewGetBounds( controlRef, &bounds );
259 CGContextClearRect( cgContext, bounds );
260 }
261
8e181eae
SC
262
263
e6616741
SC
264 if ( thisWindow->MacDoRedraw( updateRgn , cEvent.GetTicks() ) )
265 result = noErr ;
898d9035 266
e6616741
SC
267 thisWindow->MacSetCGContextRef( NULL ) ;
268 }
898d9035 269
e6616741 270 if ( created )
e6616741 271 CGContextRelease( cgContext ) ;
c79aad8b 272 }
e15f0a5e 273
055a486b
SC
274 if ( allocatedRgn )
275 DisposeRgn( allocatedRgn ) ;
facd6764
SC
276 }
277 break ;
e15f0a5e 278
73fe67bd 279 case kEventControlVisibilityChanged :
e15f0a5e 280 thisWindow->MacVisibilityChanged() ;
73fe67bd 281 break ;
e15f0a5e 282
73fe67bd 283 case kEventControlEnabledStateChanged :
8e181eae 284 thisWindow->MacEnabledStateChanged();
73fe67bd 285 break ;
e15f0a5e 286
73fe67bd 287 case kEventControlHiliteChanged :
e15f0a5e 288 thisWindow->MacHiliteChanged() ;
73fe67bd 289 break ;
89954433 290
ed9a7a63
KO
291 case kEventControlActivate :
292 case kEventControlDeactivate :
0b8055d2
VZ
293 // FIXME: we should have a virtual function for this!
294#if wxUSE_TREECTRL
295 if ( thisWindow->IsKindOf( CLASSINFO( wxTreeCtrl ) ) )
ed9a7a63 296 thisWindow->Refresh();
6449b3a8 297#endif
0b8055d2
VZ
298#if wxUSE_LISTCTRL
299 if ( thisWindow->IsKindOf( CLASSINFO( wxListCtrl ) ) )
300 thisWindow->Refresh();
301#endif
302 break ;
e15f0a5e 303
6449b3a8 304 // we emulate this event under Carbon CFM
f1d527c1
SC
305 case kEventControlSetFocusPart :
306 {
307 Boolean focusEverything = false ;
308 ControlPartCode controlPart = cEvent.GetParameter<ControlPartCode>(kEventParamControlPart , typeControlPartCode );
898d9035 309
f1d527c1
SC
310 if ( cEvent.GetParameter<Boolean>(kEventParamControlFocusEverything , &focusEverything ) == noErr )
311 {
312 }
e15f0a5e 313
6a74af89
VZ
314 if ( thisWindow->MacIsUserPane() )
315 result = noErr ;
316
f1d527c1
SC
317 if ( controlPart == kControlFocusNoPart )
318 {
e15f0a5e 319#if wxUSE_CARET
f1d527c1 320 if ( thisWindow->GetCaret() )
f1d527c1 321 thisWindow->GetCaret()->OnKillFocus();
e15f0a5e
DS
322#endif
323
92b6cd62 324 static bool inKillFocusEvent = false ;
898d9035 325
92b6cd62
SC
326 if ( !inKillFocusEvent )
327 {
328 inKillFocusEvent = true ;
329 wxFocusEvent event( wxEVT_KILL_FOCUS, thisWindow->GetId());
330 event.SetEventObject(thisWindow);
331 thisWindow->GetEventHandler()->ProcessEvent(event) ;
332 inKillFocusEvent = false ;
333 }
f1d527c1
SC
334 }
335 else
336 {
337 // panel wants to track the window which was the last to have focus in it
338 wxChildFocusEvent eventFocus(thisWindow);
339 thisWindow->GetEventHandler()->ProcessEvent(eventFocus);
8b573fb8 340
e15f0a5e 341#if wxUSE_CARET
f1d527c1 342 if ( thisWindow->GetCaret() )
f1d527c1 343 thisWindow->GetCaret()->OnSetFocus();
e15f0a5e 344#endif
f1d527c1
SC
345
346 wxFocusEvent event(wxEVT_SET_FOCUS, thisWindow->GetId());
347 event.SetEventObject(thisWindow);
348 thisWindow->GetEventHandler()->ProcessEvent(event) ;
349 }
350 }
351 break ;
e15f0a5e 352
f1d527c1 353 case kEventControlHit :
e15f0a5e 354 result = thisWindow->MacControlHit( handler , event ) ;
f1d527c1 355 break ;
e15f0a5e 356
e9a4bf7d
SC
357 case kEventControlGetClickActivation :
358 {
359 // fix to always have a proper activation for DataBrowser controls (stay in bkgnd otherwise)
360 WindowRef owner = cEvent.GetParameter<WindowRef>(kEventParamWindowRef);
361 if ( !IsWindowActive(owner) )
362 {
363 cEvent.SetParameter(kEventParamClickActivation,(UInt32) kActivateAndIgnoreClick) ;
364 result = noErr ;
365 }
366 }
367 break ;
368
facd6764
SC
369 default :
370 break ;
371 }
e15f0a5e 372
facd6764
SC
373 return result ;
374}
375
89954433
VZ
376static pascal OSStatus
377wxMacWindowServiceEventHandler(EventHandlerCallRef WXUNUSED(handler),
378 EventRef event,
379 void *data)
e4727773
SC
380{
381 OSStatus result = eventNotHandledErr ;
382
383 wxMacCarbonEvent cEvent( event ) ;
8b573fb8 384
e4727773
SC
385 ControlRef controlRef ;
386 wxWindowMac* thisWindow = (wxWindowMac*) data ;
387 wxTextCtrl* textCtrl = wxDynamicCast( thisWindow , wxTextCtrl ) ;
388 cEvent.GetParameter( kEventParamDirectObject , &controlRef ) ;
389
e15f0a5e 390 switch ( GetEventKind( event ) )
e4727773
SC
391 {
392 case kEventServiceGetTypes :
e15f0a5e 393 if ( textCtrl )
e4727773
SC
394 {
395 long from, to ;
396 textCtrl->GetSelection( &from , &to ) ;
397
8b573fb8 398 CFMutableArrayRef copyTypes = 0 , pasteTypes = 0;
e15f0a5e 399 if ( from != to )
e4727773
SC
400 copyTypes = cEvent.GetParameter< CFMutableArrayRef >( kEventParamServiceCopyTypes , typeCFMutableArrayRef ) ;
401 if ( textCtrl->IsEditable() )
402 pasteTypes = cEvent.GetParameter< CFMutableArrayRef >( kEventParamServicePasteTypes , typeCFMutableArrayRef ) ;
8b573fb8 403
898d9035 404 static const OSType textDataTypes[] = { kTXNTextData /* , 'utxt', 'PICT', 'MooV', 'AIFF' */ };
e4727773
SC
405 for ( size_t i = 0 ; i < WXSIZEOF(textDataTypes) ; ++i )
406 {
407 CFStringRef typestring = CreateTypeStringWithOSType(textDataTypes[i]);
408 if ( typestring )
409 {
410 if ( copyTypes )
898d9035 411 CFArrayAppendValue(copyTypes, typestring) ;
e4727773 412 if ( pasteTypes )
898d9035 413 CFArrayAppendValue(pasteTypes, typestring) ;
e15f0a5e 414
e4727773
SC
415 CFRelease( typestring ) ;
416 }
417 }
e15f0a5e 418
e4727773
SC
419 result = noErr ;
420 }
421 break ;
e15f0a5e 422
e4727773
SC
423 case kEventServiceCopy :
424 if ( textCtrl )
425 {
426 long from, to ;
e15f0a5e 427
e4727773
SC
428 textCtrl->GetSelection( &from , &to ) ;
429 wxString val = textCtrl->GetValue() ;
430 val = val.Mid( from , to - from ) ;
6239ee05
SC
431 PasteboardRef pasteboard = cEvent.GetParameter<PasteboardRef>( kEventParamPasteboardRef, typePasteboardRef );
432 verify_noerr( PasteboardClear( pasteboard ) ) ;
433 PasteboardSynchronize( pasteboard );
434 // TODO add proper conversion
435 CFDataRef data = CFDataCreate( kCFAllocatorDefault, (const UInt8*)val.c_str(), val.length() );
436 PasteboardPutItemFlavor( pasteboard, (PasteboardItemID) 1, CFSTR("com.apple.traditional-mac-plain-text"), data, 0);
437 CFRelease( data );
e4727773
SC
438 result = noErr ;
439 }
440 break ;
e15f0a5e 441
e4727773
SC
442 case kEventServicePaste :
443 if ( textCtrl )
444 {
6239ee05
SC
445 PasteboardRef pasteboard = cEvent.GetParameter<PasteboardRef>( kEventParamPasteboardRef, typePasteboardRef );
446 PasteboardSynchronize( pasteboard );
447 ItemCount itemCount;
448 verify_noerr( PasteboardGetItemCount( pasteboard, &itemCount ) );
449 for( UInt32 itemIndex = 1; itemIndex <= itemCount; itemIndex++ )
450 {
451 PasteboardItemID itemID;
452 if ( PasteboardGetItemIdentifier( pasteboard, itemIndex, &itemID ) == noErr )
453 {
454 CFDataRef flavorData = NULL;
455 if ( PasteboardCopyItemFlavorData( pasteboard, itemID, CFSTR("com.apple.traditional-mac-plain-text"), &flavorData ) == noErr )
456 {
457 CFIndex flavorDataSize = CFDataGetLength( flavorData );
458 char *content = new char[flavorDataSize+1] ;
459 memcpy( content, CFDataGetBytePtr( flavorData ), flavorDataSize );
460 content[flavorDataSize]=0;
461 CFRelease( flavorData );
8ef4d6e2 462#if wxUSE_UNICODE
6239ee05 463 textCtrl->WriteText( wxString( content , wxConvLocal ) );
8ef4d6e2 464#else
6239ee05 465 textCtrl->WriteText( wxString( content ) ) ;
8ef4d6e2 466#endif
e15f0a5e 467
6239ee05
SC
468 delete[] content ;
469 result = noErr ;
470 }
471 }
472 }
e4727773
SC
473 }
474 break ;
e15f0a5e
DS
475
476 default:
477 break ;
e4727773 478 }
8b573fb8 479
e4727773 480 return result ;
8b573fb8 481}
e4727773 482
980ee83f
SC
483pascal OSStatus wxMacUnicodeTextEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
484{
485 OSStatus result = eventNotHandledErr ;
486 wxWindowMac* focus = (wxWindowMac*) data ;
b46dde27 487
980ee83f
SC
488 wchar_t* uniChars = NULL ;
489 UInt32 when = EventTimeToTicks( GetEventTime( event ) ) ;
b46dde27 490
75b32421 491 UniChar* charBuf = NULL;
4f74e0d1 492 ByteCount dataSize = 0 ;
980ee83f
SC
493 int numChars = 0 ;
494 UniChar buf[2] ;
495 if ( GetEventParameter( event, kEventParamTextInputSendText, typeUnicodeText, NULL, 0 , &dataSize, NULL ) == noErr )
496 {
3281bf67 497 numChars = dataSize / sizeof( UniChar) + 1;
980ee83f 498 charBuf = buf ;
b46dde27 499
6d49e4bb 500 if ( (size_t) numChars * 2 > sizeof(buf) )
980ee83f
SC
501 charBuf = new UniChar[ numChars ] ;
502 else
503 charBuf = buf ;
b46dde27 504
980ee83f
SC
505 uniChars = new wchar_t[ numChars ] ;
506 GetEventParameter( event, kEventParamTextInputSendText, typeUnicodeText, NULL, dataSize , NULL , charBuf ) ;
e4db172a 507 charBuf[ numChars - 1 ] = 0;
980ee83f 508#if SIZEOF_WCHAR_T == 2
cdef0334 509 uniChars = (wchar_t*) charBuf ;
5ca930b1 510/* memcpy( uniChars , charBuf , numChars * 2 ) ;*/ // is there any point in copying charBuf over itself? (in fact, memcpy isn't even guaranteed to work correctly if the source and destination ranges overlap...)
980ee83f
SC
511#else
512 // the resulting string will never have more chars than the utf16 version, so this is safe
513 wxMBConvUTF16 converter ;
514 numChars = converter.MB2WC( uniChars , (const char*)charBuf , numChars ) ;
515#endif
516 }
b46dde27 517
980ee83f
SC
518 switch ( GetEventKind( event ) )
519 {
520 case kEventTextInputUpdateActiveInputArea :
521 {
522 // An IME input event may return several characters, but we need to send one char at a time to
523 // EVT_CHAR
524 for (int pos=0 ; pos < numChars ; pos++)
525 {
980ee83f
SC
526 WXEVENTREF formerEvent = wxTheApp->MacGetCurrentEvent() ;
527 WXEVENTHANDLERCALLREF formerHandler = wxTheApp->MacGetCurrentEventHandlerCallRef() ;
528 wxTheApp->MacSetCurrentEvent( event , handler ) ;
b46dde27 529
5ca930b1
VZ
530 UInt32 message = uniChars[pos] < 128 ? (char)uniChars[pos] : '?';
531/*
532 NB: faking a charcode here is problematic. The kEventTextInputUpdateActiveInputArea event is sent
533 multiple times to update the active range during inline input, so this handler will often receive
534 uncommited text, which should usually not trigger side effects. It might be a good idea to check the
535 kEventParamTextInputSendFixLen parameter and verify if input is being confirmed (see CarbonEvents.h).
536 On the other hand, it can be useful for some applications to react to uncommitted text (for example,
537 to update a status display), as long as it does not disrupt the inline input session. Ideally, wx
538 should add new event types to support advanced text input. For now, I would keep things as they are.
89954433 539
5ca930b1 540 However, the code that was being used caused additional problems:
980ee83f 541 UInt32 message = (0 << 8) + ((char)uniChars[pos] );
5ca930b1
VZ
542 Since it simply truncated the unichar to the last byte, it ended up causing weird bugs with inline
543 input, such as switching to another field when one attempted to insert the character U+4E09 (the kanji
544 for "three"), because it was truncated to 09 (kTabCharCode), which was later "converted" to WXK_TAB
545 (still 09) in wxMacTranslateKey; or triggering the default button when one attempted to insert U+840D
546 (the kanji for "name"), which got truncated to 0D and interpreted as a carriage return keypress.
547 Note that even single-byte characters could have been misinterpreted, since MacRoman charcodes only
548 overlap with Unicode within the (7-bit) ASCII range.
549 But simply passing a NUL charcode would disable text updated events, because wxTextCtrl::OnChar checks
550 for codes within a specific range. Therefore I went for the solution seen above, which keeps ASCII
551 characters as they are and replaces the rest with '?', ensuring that update events are triggered.
552 It would be better to change wxTextCtrl::OnChar to look at the actual unicode character instead, but
553 I don't have time to look into that right now.
554 -- CL
555*/
980ee83f
SC
556 if ( wxTheApp->MacSendCharEvent(
557 focus , message , 0 , when , 0 , 0 , uniChars[pos] ) )
558 {
559 result = noErr ;
560 }
b46dde27 561
980ee83f
SC
562 wxTheApp->MacSetCurrentEvent( formerEvent , formerHandler ) ;
563 }
564 }
565 break ;
566 case kEventTextInputUnicodeForKeyEvent :
567 {
568 UInt32 keyCode, modifiers ;
569 Point point ;
570 EventRef rawEvent ;
571 unsigned char charCode ;
572
573 GetEventParameter( event, kEventParamTextInputSendKeyboardEvent, typeEventRef, NULL, sizeof(rawEvent), NULL, &rawEvent ) ;
574 GetEventParameter( rawEvent, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &charCode );
575 GetEventParameter( rawEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode );
576 GetEventParameter( rawEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers );
577 GetEventParameter( rawEvent, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &point );
b46dde27 578
980ee83f 579 UInt32 message = (keyCode << 8) + charCode;
aa44b55d 580
980ee83f
SC
581 // An IME input event may return several characters, but we need to send one char at a time to
582 // EVT_CHAR
583 for (int pos=0 ; pos < numChars ; pos++)
584 {
980ee83f
SC
585 WXEVENTREF formerEvent = wxTheApp->MacGetCurrentEvent() ;
586 WXEVENTHANDLERCALLREF formerHandler = wxTheApp->MacGetCurrentEventHandlerCallRef() ;
587 wxTheApp->MacSetCurrentEvent( event , handler ) ;
b46dde27 588
980ee83f
SC
589 if ( wxTheApp->MacSendCharEvent(
590 focus , message , modifiers , when , point.h , point.v , uniChars[pos] ) )
591 {
592 result = noErr ;
593 }
b46dde27 594
980ee83f
SC
595 wxTheApp->MacSetCurrentEvent( formerEvent , formerHandler ) ;
596 }
597 }
598 break;
599 default:
600 break ;
601 }
b46dde27
DS
602
603 delete [] uniChars ;
980ee83f 604 if ( charBuf != buf )
b46dde27 605 delete [] charBuf ;
2e91d506 606
980ee83f 607 return result ;
980ee83f
SC
608}
609
89954433
VZ
610static pascal OSStatus
611wxMacWindowCommandEventHandler(EventHandlerCallRef WXUNUSED(handler),
612 EventRef event,
613 void *data)
e3aeade0
SC
614{
615 OSStatus result = eventNotHandledErr ;
616 wxWindowMac* focus = (wxWindowMac*) data ;
b46dde27 617
e3aeade0 618 HICommand command ;
b46dde27 619
e3aeade0
SC
620 wxMacCarbonEvent cEvent( event ) ;
621 cEvent.GetParameter<HICommand>(kEventParamDirectObject,typeHICommand,&command) ;
b46dde27 622
e3aeade0
SC
623 wxMenuItem* item = NULL ;
624 wxMenu* itemMenu = wxFindMenuFromMacCommand( command , item ) ;
625 int id = wxMacCommandToId( command.commandID ) ;
b46dde27 626
e3aeade0
SC
627 if ( item )
628 {
629 wxASSERT( itemMenu != NULL ) ;
b46dde27 630
e3aeade0
SC
631 switch ( cEvent.GetKind() )
632 {
633 case kEventProcessCommand :
6239ee05 634 result = itemMenu->MacHandleCommandProcess( item, id, focus );
e3aeade0 635 break ;
b46dde27 636
e3aeade0 637 case kEventCommandUpdateStatus:
6239ee05 638 result = itemMenu->MacHandleCommandUpdateStatus( item, id, focus );
e3aeade0 639 break ;
b46dde27 640
e3aeade0
SC
641 default :
642 break ;
643 }
644 }
645 return result ;
646}
647
facd6764
SC
648pascal OSStatus wxMacWindowEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
649{
af6b7b80
SC
650 EventRef formerEvent = (EventRef) wxTheApp->MacGetCurrentEvent() ;
651 EventHandlerCallRef formerEventHandlerCallRef = (EventHandlerCallRef) wxTheApp->MacGetCurrentEventHandlerCallRef() ;
652 wxTheApp->MacSetCurrentEvent( event , handler ) ;
facd6764
SC
653 OSStatus result = eventNotHandledErr ;
654
655 switch ( GetEventClass( event ) )
656 {
e3aeade0
SC
657 case kEventClassCommand :
658 result = wxMacWindowCommandEventHandler( handler , event , data ) ;
659 break ;
660
facd6764
SC
661 case kEventClassControl :
662 result = wxMacWindowControlEventHandler( handler, event, data ) ;
663 break ;
e15f0a5e 664
e4727773
SC
665 case kEventClassService :
666 result = wxMacWindowServiceEventHandler( handler, event , data ) ;
902725ee 667 break ;
e15f0a5e 668
980ee83f
SC
669 case kEventClassTextInput :
670 result = wxMacUnicodeTextEventHandler( handler , event , data ) ;
671 break ;
b46dde27 672
facd6764
SC
673 default :
674 break ;
675 }
e15f0a5e 676
af6b7b80 677 wxTheApp->MacSetCurrentEvent( formerEvent, formerEventHandlerCallRef ) ;
e15f0a5e 678
facd6764
SC
679 return result ;
680}
681
682DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacWindowEventHandler )
683
1f1c8bd4
SC
684// ---------------------------------------------------------------------------
685// Scrollbar Tracking for all
686// ---------------------------------------------------------------------------
687
688pascal void wxMacLiveScrollbarActionProc( ControlRef control , ControlPartCode partCode ) ;
689pascal void wxMacLiveScrollbarActionProc( ControlRef control , ControlPartCode partCode )
690{
691 if ( partCode != 0)
692 {
693 wxWindow* wx = wxFindControlFromMacControl( control ) ;
694 if ( wx )
1f1c8bd4 695 wx->MacHandleControlClick( (WXWidget) control , partCode , true /* stillDown */ ) ;
1f1c8bd4
SC
696 }
697}
698wxMAC_DEFINE_PROC_GETTER( ControlActionUPP , wxMacLiveScrollbarActionProc ) ;
699
e7549107
SC
700// ===========================================================================
701// implementation
702// ===========================================================================
703
71f2fb52
RN
704WX_DECLARE_HASH_MAP(ControlRef, wxWindow*, wxPointerHash, wxPointerEqual, MacControlMap);
705
706static MacControlMap wxWinMacControlList;
707
708wxWindow *wxFindControlFromMacControl(ControlRef inControl )
709{
710 MacControlMap::iterator node = wxWinMacControlList.find(inControl);
711
712 return (node == wxWinMacControlList.end()) ? NULL : node->second;
713}
714
715void wxAssociateControlWithMacControl(ControlRef inControl, wxWindow *control)
716{
717 // adding NULL ControlRef is (first) surely a result of an error and
718 // (secondly) breaks native event processing
719 wxCHECK_RET( inControl != (ControlRef) NULL, wxT("attempt to add a NULL WindowRef to window list") );
720
721 wxWinMacControlList[inControl] = control;
722}
723
724void wxRemoveMacControlAssociation(wxWindow *control)
725{
726 // iterate over all the elements in the class
a8683134
SC
727 // is the iterator stable ? as we might have two associations pointing to the same wxWindow
728 // we should go on...
729
730 bool found = true ;
e15f0a5e 731 while ( found )
71f2fb52 732 {
a8683134
SC
733 found = false ;
734 MacControlMap::iterator it;
735 for ( it = wxWinMacControlList.begin(); it != wxWinMacControlList.end(); ++it )
71f2fb52 736 {
a8683134
SC
737 if ( it->second == control )
738 {
739 wxWinMacControlList.erase(it);
740 found = true ;
741 break;
742 }
71f2fb52
RN
743 }
744 }
745}
facd6764 746
e7549107 747// ----------------------------------------------------------------------------
facd6764 748 // constructors and such
e7549107
SC
749// ----------------------------------------------------------------------------
750
94f9b1f0 751wxWindowMac::wxWindowMac()
8b573fb8
VZ
752{
753 Init();
94f9b1f0
SC
754}
755
756wxWindowMac::wxWindowMac(wxWindowMac *parent,
757 wxWindowID id,
758 const wxPoint& pos ,
759 const wxSize& size ,
760 long style ,
761 const wxString& name )
762{
763 Init();
764 Create(parent, id, pos, size, style, name);
765}
766
e766c8a9 767void wxWindowMac::Init()
519cb848 768{
21fd5529 769 m_peer = NULL ;
79392158 770 m_frozenness = 0 ;
a9b456ff 771 m_macAlpha = 255 ;
e15f0a5e 772 m_cgContextRef = NULL ;
e15f0a5e 773
e7549107 774 // as all windows are created with WS_VISIBLE style...
902725ee 775 m_isShown = true;
e7549107 776
6264b550
RR
777 m_hScrollBar = NULL ;
778 m_vScrollBar = NULL ;
c1142003
VZ
779 m_hScrollBarAlwaysShown = false;
780 m_vScrollBarAlwaysShown = false;
781
902725ee 782 m_macIsUserPane = true;
8adc196b 783 m_clipChildren = false ;
5c840e5b 784 m_cachedClippedRectValid = false ;
e15f0a5e 785
c6f9fb05
SC
786 // we need a valid font for the encodings
787 wxWindowBase::SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
e9576ca5
SC
788}
789
e766c8a9 790wxWindowMac::~wxWindowMac()
e9576ca5 791{
7de59551
RD
792 SendDestroyEvent();
793
902725ee 794 m_isBeingDeleted = true;
6ed71b4f 795
6449b3a8 796 MacInvalidateBorders() ;
7ebf5540 797
d4380aaf
SC
798#ifndef __WXUNIVERSAL__
799 // VS: make sure there's no wxFrame with last focus set to us:
800 for ( wxWindow *win = GetParent(); win; win = win->GetParent() )
801 {
802 wxFrame *frame = wxDynamicCast(win, wxFrame);
803 if ( frame )
804 {
805 if ( frame->GetLastFocus() == this )
d4380aaf 806 frame->SetLastFocus((wxWindow*)NULL);
d4380aaf
SC
807 break;
808 }
809 }
b46dde27 810#endif
8b573fb8
VZ
811
812 // destroy children before destroying this window itself
813 DestroyChildren();
814
facd6764
SC
815 // wxRemoveMacControlAssociation( this ) ;
816 // If we delete an item, we should initialize the parent panel,
817 // because it could now be invalid.
6c20e8f8
VZ
818 wxTopLevelWindow *tlw = wxDynamicCast(wxGetTopLevelParent(this), wxTopLevelWindow);
819 if ( tlw )
facd6764 820 {
6c20e8f8
VZ
821 if ( tlw->GetDefaultItem() == (wxButton*) this)
822 tlw->SetDefaultItem(NULL);
facd6764 823 }
e15f0a5e 824
21fd5529 825 if ( m_peer && m_peer->Ok() )
facd6764
SC
826 {
827 // in case the callback might be called during destruction
828 wxRemoveMacControlAssociation( this) ;
229f6270 829 ::RemoveEventHandler( (EventHandlerRef ) m_macControlEventHandler ) ;
5ca0d812
SC
830 // we currently are not using this hook
831 // ::SetControlColorProc( *m_peer , NULL ) ;
832 m_peer->Dispose() ;
facd6764 833 }
d4380aaf 834
facd6764 835 if ( g_MacLastWindow == this )
facd6764 836 g_MacLastWindow = NULL ;
7de59551 837
6239ee05
SC
838#ifndef __WXUNIVERSAL__
839 wxFrame* frame = wxDynamicCast( wxGetTopLevelParent( (wxWindow*)this ) , wxFrame ) ;
fd76aa8d
SC
840 if ( frame )
841 {
e40298d5
JS
842 if ( frame->GetLastFocus() == this )
843 frame->SetLastFocus( NULL ) ;
fd76aa8d 844 }
6239ee05 845#endif
e7549107 846
42683dfb
SC
847 // delete our drop target if we've got one
848#if wxUSE_DRAG_AND_DROP
849 if ( m_dropTarget != NULL )
850 {
851 delete m_dropTarget;
852 m_dropTarget = NULL;
853 }
e15f0a5e
DS
854#endif
855
21fd5529
SC
856 delete m_peer ;
857}
858
8b573fb8
VZ
859WXWidget wxWindowMac::GetHandle() const
860{
861 return (WXWidget) m_peer->GetControlRef() ;
e9576ca5
SC
862}
863
5ca0d812 864void wxWindowMac::MacInstallEventHandler( WXWidget control )
facd6764 865{
898d9035
DS
866 wxAssociateControlWithMacControl( (ControlRef) control , this ) ;
867 InstallControlEventHandler( (ControlRef)control , GetwxMacWindowEventHandlerUPP(),
8b573fb8 868 GetEventTypeCount(eventList), eventList, this,
facd6764 869 (EventHandlerRef *)&m_macControlEventHandler);
facd6764
SC
870}
871
e9576ca5 872// Constructor
58603178
DS
873bool wxWindowMac::Create(wxWindowMac *parent,
874 wxWindowID id,
875 const wxPoint& pos,
876 const wxSize& size,
877 long style,
878 const wxString& name)
e9576ca5 879{
902725ee 880 wxCHECK_MSG( parent, false, wxT("can't create wxWindowMac without parent") );
e9576ca5 881
e7549107 882 if ( !CreateBase(parent, id, pos, size, style, wxDefaultValidator, name) )
902725ee 883 return false;
e9576ca5 884
facd6764 885 m_windowVariant = parent->GetWindowVariant() ;
8b573fb8 886
facd6764
SC
887 if ( m_macIsUserPane )
888 {
889 Rect bounds = wxMacGetBoundsForControl( this , pos , size ) ;
8b573fb8 890
ebe86b1e 891 UInt32 features = 0
8b573fb8 892 | kControlSupportsEmbedding
1f1c8bd4
SC
893 | kControlSupportsLiveFeedback
894 | kControlGetsFocusOnClick
8b573fb8
VZ
895// | kControlHasSpecialBackground
896// | kControlSupportsCalcBestRect
1f1c8bd4 897 | kControlHandlesTracking
8b573fb8 898 | kControlSupportsFocus
1f1c8bd4 899 | kControlWantsActivate
58603178 900 | kControlWantsIdle ;
ebe86b1e 901
6449b3a8 902 m_peer = new wxMacControl(this) ;
58603178
DS
903 OSStatus err =::CreateUserPaneControl( MAC_WXHWND(GetParent()->MacGetTopLevelWindowRef()) , &bounds, features , m_peer->GetControlRefAddr() );
904 verify_noerr( err );
8b573fb8 905
898d9035 906 MacPostControlCreate(pos, size) ;
facd6764 907 }
898d9035 908
e766c8a9 909#ifndef __WXUNIVERSAL__
14c9cbdb 910 // Don't give scrollbars to wxControls unless they ask for them
58603178
DS
911 if ( (! IsKindOf(CLASSINFO(wxControl)) && ! IsKindOf(CLASSINFO(wxStatusBar)))
912 || (IsKindOf(CLASSINFO(wxControl)) && ((style & wxHSCROLL) || (style & wxVSCROLL))))
6264b550
RR
913 {
914 MacCreateScrollBars( style ) ;
915 }
e766c8a9 916#endif
3dfafdb9
RD
917
918 wxWindowCreateEvent event(this);
7e4a196e 919 GetEventHandler()->AddPendingEvent(event);
3dfafdb9 920
902725ee 921 return true;
e9576ca5
SC
922}
923
902725ee 924void wxWindowMac::MacChildAdded()
08422003
SC
925{
926 if ( m_vScrollBar )
08422003 927 m_vScrollBar->Raise() ;
08422003 928 if ( m_hScrollBar )
08422003 929 m_hScrollBar->Raise() ;
08422003
SC
930}
931
89954433 932void wxWindowMac::MacPostControlCreate(const wxPoint& WXUNUSED(pos), const wxSize& size)
facd6764 933{
21fd5529 934 wxASSERT_MSG( m_peer != NULL && m_peer->Ok() , wxT("No valid mac control") ) ;
facd6764 935
4f74e0d1 936 m_peer->SetReference( (URefCon) this ) ;
58603178 937 GetParent()->AddChild( this );
facd6764 938
5ca0d812 939 MacInstallEventHandler( (WXWidget) m_peer->GetControlRef() );
facd6764
SC
940
941 ControlRef container = (ControlRef) GetParent()->GetHandle() ;
942 wxASSERT_MSG( container != NULL , wxT("No valid mac container control") ) ;
5ca0d812 943 ::EmbedControl( m_peer->GetControlRef() , container ) ;
08422003 944 GetParent()->MacChildAdded() ;
facd6764
SC
945
946 // adjust font, controlsize etc
947 DoSetWindowVariant( m_windowVariant ) ;
948
32cd189d 949 m_peer->SetLabel( wxStripMenuCodes(m_label, wxStrip_Mnemonics) ) ;
facd6764 950
facd6764 951 if (!m_macIsUserPane)
170acdc9 952 SetInitialSize(size);
facd6764
SC
953
954 SetCursor( *wxSTANDARD_CURSOR ) ;
facd6764
SC
955}
956
957void wxWindowMac::DoSetWindowVariant( wxWindowVariant variant )
958{
23176131
JS
959 // Don't assert, in case we set the window variant before
960 // the window is created
21fd5529 961 // wxASSERT( m_peer->Ok() ) ;
facd6764 962
23176131
JS
963 m_windowVariant = variant ;
964
21fd5529 965 if (m_peer == NULL || !m_peer->Ok())
23176131 966 return;
facd6764 967
8b573fb8 968 ControlSize size ;
facd6764
SC
969 ThemeFontID themeFont = kThemeSystemFont ;
970
971 // we will get that from the settings later
8b573fb8 972 // and make this NORMAL later, but first
facd6764 973 // we have a few calculations that we must fix
8b573fb8 974
facd6764
SC
975 switch ( variant )
976 {
977 case wxWINDOW_VARIANT_NORMAL :
8b573fb8
VZ
978 size = kControlSizeNormal;
979 themeFont = kThemeSystemFont ;
facd6764 980 break ;
e15f0a5e 981
facd6764 982 case wxWINDOW_VARIANT_SMALL :
8b573fb8
VZ
983 size = kControlSizeSmall;
984 themeFont = kThemeSmallSystemFont ;
facd6764 985 break ;
e15f0a5e 986
facd6764 987 case wxWINDOW_VARIANT_MINI :
9d463591
SC
988 // not always defined in the headers
989 size = 3 ;
990 themeFont = 109 ;
facd6764 991 break ;
e15f0a5e 992
facd6764 993 case wxWINDOW_VARIANT_LARGE :
8b573fb8
VZ
994 size = kControlSizeLarge;
995 themeFont = kThemeSystemFont ;
facd6764 996 break ;
e15f0a5e 997
facd6764
SC
998 default:
999 wxFAIL_MSG(_T("unexpected window variant"));
1000 break ;
1001 }
e15f0a5e 1002
898d9035 1003 m_peer->SetData<ControlSize>(kControlEntireControl, kControlSizeTag, &size ) ;
facd6764
SC
1004
1005 wxFont font ;
1006 font.MacCreateThemeFont( themeFont ) ;
1007 SetFont( font ) ;
1008}
1009
8b573fb8 1010void wxWindowMac::MacUpdateControlFont()
facd6764 1011{
ac99838a 1012 m_peer->SetFont( GetFont() , GetForegroundColour() , GetWindowStyle() ) ;
6239ee05
SC
1013 // do not trigger refreshes upon invisible and possible partly created objects
1014 if ( MacIsReallyShown() )
1015 Refresh() ;
facd6764
SC
1016}
1017
1018bool wxWindowMac::SetFont(const wxFont& font)
1019{
58603178 1020 bool retval = wxWindowBase::SetFont( font );
8b573fb8 1021
facd6764 1022 MacUpdateControlFont() ;
8b573fb8 1023
facd6764
SC
1024 return retval;
1025}
1026
1027bool wxWindowMac::SetForegroundColour(const wxColour& col )
1028{
58603178 1029 bool retval = wxWindowBase::SetForegroundColour( col );
8b573fb8 1030
898d9035 1031 if (retval)
58603178 1032 MacUpdateControlFont();
8b573fb8 1033
898d9035 1034 return retval;
facd6764
SC
1035}
1036
1037bool wxWindowMac::SetBackgroundColour(const wxColour& col )
1038{
1039 if ( !wxWindowBase::SetBackgroundColour(col) && m_hasBgCol )
1040 return false ;
1041
a01d9a25 1042 m_peer->SetBackgroundColour( col ) ;
8b573fb8 1043
facd6764
SC
1044 return true ;
1045}
1046
facd6764
SC
1047bool wxWindowMac::MacCanFocus() const
1048{
90b4f7b5 1049 // TODO : evaluate performance hits by looking up this value, eventually cache the results for a 1 sec or so
2e91d506
DS
1050 // CAUTION : the value returned currently is 0 or 2, I've also found values of 1 having the same meaning,
1051 // but the value range is nowhere documented
90b4f7b5 1052 Boolean keyExistsAndHasValidFormat ;
2e91d506
DS
1053 CFIndex fullKeyboardAccess = CFPreferencesGetAppIntegerValue( CFSTR("AppleKeyboardUIMode" ) ,
1054 kCFPreferencesCurrentApplication, &keyExistsAndHasValidFormat );
1055
90b4f7b5 1056 if ( keyExistsAndHasValidFormat && fullKeyboardAccess > 0 )
2e91d506 1057 {
90b4f7b5 1058 return true ;
2e91d506 1059 }
90b4f7b5
SC
1060 else
1061 {
1062 UInt32 features = 0 ;
1063 m_peer->GetFeatures( &features ) ;
1064
1065 return features & ( kControlSupportsFocus | kControlGetsFocusOnClick ) ;
1066 }
facd6764
SC
1067}
1068
e766c8a9 1069void wxWindowMac::SetFocus()
e9576ca5 1070{
e15f0a5e 1071 if ( !AcceptsFocus() )
7d0cfe71
SC
1072 return ;
1073
e15f0a5e
DS
1074 wxWindow* former = FindFocus() ;
1075 if ( former == this )
1076 return ;
1077
1078 // as we cannot rely on the control features to find out whether we are in full keyboard mode,
1079 // we can only leave in case of an error
1080 OSStatus err = m_peer->SetFocus( kControlFocusNextPart ) ;
1081 if ( err == errCouldntSetFocus )
1082 return ;
1083
e15f0a5e 1084 SetUserFocusWindow( (WindowRef)MacGetTopLevelWindowRef() );
e9576ca5
SC
1085}
1086
4116c221 1087void wxWindowMac::DoCaptureMouse()
e9576ca5 1088{
2a1f999f 1089 wxApp::s_captureWindow = this ;
e9576ca5
SC
1090}
1091
2e91d506 1092wxWindow * wxWindowBase::GetCapture()
90b959ae 1093{
2a1f999f 1094 return wxApp::s_captureWindow ;
90b959ae
SC
1095}
1096
4116c221 1097void wxWindowMac::DoReleaseMouse()
e9576ca5 1098{
2a1f999f 1099 wxApp::s_captureWindow = NULL ;
e9576ca5
SC
1100}
1101
e15f0a5e 1102#if wxUSE_DRAG_AND_DROP
e9576ca5 1103
e766c8a9 1104void wxWindowMac::SetDropTarget(wxDropTarget *pDropTarget)
e9576ca5 1105{
e15f0a5e 1106 if ( m_dropTarget != NULL )
e40298d5 1107 delete m_dropTarget;
6ed71b4f 1108
e40298d5 1109 m_dropTarget = pDropTarget;
e15f0a5e 1110 if ( m_dropTarget != NULL )
e40298d5 1111 {
58603178 1112 // TODO:
e40298d5 1113 }
e9576ca5
SC
1114}
1115
1116#endif
1117
2e91d506 1118// Old-style File Manager Drag & Drop
89954433 1119void wxWindowMac::DragAcceptFiles(bool WXUNUSED(accept))
e9576ca5 1120{
58603178 1121 // TODO:
e9576ca5
SC
1122}
1123
055a486b
SC
1124// Returns the size of the native control. In the case of the toplevel window
1125// this is the content area root control
1126
89954433
VZ
1127void wxWindowMac::MacGetPositionAndSizeFromControl(int& WXUNUSED(x),
1128 int& WXUNUSED(y),
1129 int& WXUNUSED(w),
1130 int& WXUNUSED(h)) const
e9576ca5 1131{
898d9035 1132 wxFAIL_MSG( wxT("Not currently supported") ) ;
e9576ca5
SC
1133}
1134
055a486b 1135// From a wx position / size calculate the appropriate size of the native control
8b573fb8 1136
898d9035
DS
1137bool wxWindowMac::MacGetBoundsForControl(
1138 const wxPoint& pos,
1139 const wxSize& size,
1140 int& x, int& y,
1141 int& w, int& h , bool adjustOrigin ) const
51abe921 1142{
5ca0d812 1143 // the desired size, minus the border pixels gives the correct size of the control
facd6764
SC
1144 x = (int)pos.x;
1145 y = (int)pos.y;
58603178
DS
1146
1147 // TODO: the default calls may be used as soon as PostCreateControl Is moved here
898d9035
DS
1148 w = wxMax(size.x, 0) ; // WidthDefault( size.x );
1149 h = wxMax(size.y, 0) ; // HeightDefault( size.y ) ;
789ae0cf 1150
5ca0d812
SC
1151 x += MacGetLeftBorderSize() ;
1152 y += MacGetTopBorderSize() ;
1153 w -= MacGetLeftBorderSize() + MacGetRightBorderSize() ;
1154 h -= MacGetTopBorderSize() + MacGetBottomBorderSize() ;
8b573fb8 1155
79392158
SC
1156 if ( adjustOrigin )
1157 AdjustForParentClientOrigin( x , y ) ;
789ae0cf 1158
7ebf5540 1159 // this is in window relative coordinate, as this parent may have a border, its physical position is offset by this border
789ae0cf 1160 if ( !GetParent()->IsTopLevel() )
7ebf5540
SC
1161 {
1162 x -= GetParent()->MacGetLeftBorderSize() ;
1163 y -= GetParent()->MacGetTopBorderSize() ;
1164 }
789ae0cf 1165
facd6764
SC
1166 return true ;
1167}
1168
42ef83fa 1169// Get window size (not client size)
facd6764
SC
1170void wxWindowMac::DoGetSize(int *x, int *y) const
1171{
1f1c8bd4
SC
1172 Rect bounds ;
1173 m_peer->GetRect( &bounds ) ;
8b573fb8 1174
e15f0a5e
DS
1175 if (x)
1176 *x = bounds.right - bounds.left + MacGetLeftBorderSize() + MacGetRightBorderSize() ;
1177 if (y)
1178 *y = bounds.bottom - bounds.top + MacGetTopBorderSize() + MacGetBottomBorderSize() ;
facd6764
SC
1179}
1180
42ef83fa 1181// get the position of the bounds of this window in client coordinates of its parent
facd6764
SC
1182void wxWindowMac::DoGetPosition(int *x, int *y) const
1183{
1f1c8bd4
SC
1184 Rect bounds ;
1185 m_peer->GetRect( &bounds ) ;
902725ee 1186
1f1c8bd4
SC
1187 int x1 = bounds.left ;
1188 int y1 = bounds.top ;
789ae0cf 1189
bc2b0c1b
SC
1190 // get the wx window position from the native one
1191 x1 -= MacGetLeftBorderSize() ;
1192 y1 -= MacGetTopBorderSize() ;
1193
facd6764 1194 if ( !IsTopLevel() )
2b5f62a0 1195 {
facd6764
SC
1196 wxWindow *parent = GetParent();
1197 if ( parent )
8950f7cc 1198 {
e15f0a5e
DS
1199 // we must first adjust it to be in window coordinates of the parent,
1200 // as otherwise it gets lost by the ClientAreaOrigin fix
1a02aff9
SC
1201 x1 += parent->MacGetLeftBorderSize() ;
1202 y1 += parent->MacGetTopBorderSize() ;
e15f0a5e 1203
1a02aff9 1204 // and now to client coordinates
facd6764
SC
1205 wxPoint pt(parent->GetClientAreaOrigin());
1206 x1 -= pt.x ;
1207 y1 -= pt.y ;
6ed71b4f 1208 }
2b5f62a0 1209 }
e15f0a5e
DS
1210
1211 if (x)
1212 *x = x1 ;
1213 if (y)
1214 *y = y1 ;
facd6764 1215}
51abe921 1216
e766c8a9 1217void wxWindowMac::DoScreenToClient(int *x, int *y) const
e9576ca5 1218{
facd6764 1219 WindowRef window = (WindowRef) MacGetTopLevelWindowRef() ;
58603178 1220 wxCHECK_RET( window , wxT("TopLevel Window missing") ) ;
8b573fb8 1221
58603178 1222 Point localwhere = { 0, 0 } ;
519cb848 1223
58603178
DS
1224 if (x)
1225 localwhere.h = *x ;
1226 if (y)
1227 localwhere.v = *y ;
8b573fb8 1228
4f74e0d1 1229 wxMacGlobalToLocal( window , &localwhere ) ;
6ed71b4f 1230
58603178
DS
1231 if (x)
1232 *x = localwhere.h ;
1233 if (y)
1234 *y = localwhere.v ;
e15f0a5e 1235
2078220e 1236 MacRootWindowToWindow( x , y ) ;
8b573fb8 1237
facd6764 1238 wxPoint origin = GetClientAreaOrigin() ;
e15f0a5e
DS
1239 if (x)
1240 *x -= origin.x ;
1241 if (y)
1242 *y -= origin.y ;
e9576ca5
SC
1243}
1244
e766c8a9 1245void wxWindowMac::DoClientToScreen(int *x, int *y) const
e9576ca5 1246{
facd6764 1247 WindowRef window = (WindowRef) MacGetTopLevelWindowRef() ;
8523a5f5 1248 wxCHECK_RET( window , wxT("TopLevel window missing") ) ;
14c9cbdb 1249
facd6764 1250 wxPoint origin = GetClientAreaOrigin() ;
e15f0a5e
DS
1251 if (x)
1252 *x += origin.x ;
1253 if (y)
1254 *y += origin.y ;
14c9cbdb 1255
2078220e 1256 MacWindowToRootWindow( x , y ) ;
14c9cbdb 1257
58603178
DS
1258 Point localwhere = { 0, 0 };
1259 if (x)
1260 localwhere.h = *x ;
1261 if (y)
1262 localwhere.v = *y ;
e15f0a5e 1263
4f74e0d1 1264 wxMacLocalToGlobal( window, &localwhere ) ;
e15f0a5e 1265
58603178
DS
1266 if (x)
1267 *x = localwhere.h ;
1268 if (y)
1269 *y = localwhere.v ;
519cb848
SC
1270}
1271
e766c8a9 1272void wxWindowMac::MacClientToRootWindow( int *x , int *y ) const
519cb848 1273{
1c310985 1274 wxPoint origin = GetClientAreaOrigin() ;
e15f0a5e
DS
1275 if (x)
1276 *x += origin.x ;
1277 if (y)
1278 *y += origin.y ;
14c9cbdb 1279
1c310985
SC
1280 MacWindowToRootWindow( x , y ) ;
1281}
1282
1283void wxWindowMac::MacRootWindowToClient( int *x , int *y ) const
1284{
1c310985 1285 MacRootWindowToWindow( x , y ) ;
facd6764
SC
1286
1287 wxPoint origin = GetClientAreaOrigin() ;
e15f0a5e
DS
1288 if (x)
1289 *x -= origin.x ;
1290 if (y)
1291 *y -= origin.y ;
1c310985
SC
1292}
1293
1294void wxWindowMac::MacWindowToRootWindow( int *x , int *y ) const
1295{
5ca0d812 1296 wxPoint pt ;
58603178 1297
e15f0a5e
DS
1298 if (x)
1299 pt.x = *x ;
1300 if (y)
1301 pt.y = *y ;
facd6764 1302
125c7984 1303 if ( !IsTopLevel() )
5437ff47
RD
1304 {
1305 wxTopLevelWindowMac* top = MacGetTopLevelWindow();
1306 if (top)
5ca0d812
SC
1307 {
1308 pt.x -= MacGetLeftBorderSize() ;
1309 pt.y -= MacGetTopBorderSize() ;
1310 wxMacControl::Convert( &pt , m_peer , top->m_peer ) ;
1311 }
5437ff47 1312 }
8b573fb8 1313
e15f0a5e
DS
1314 if (x)
1315 *x = (int) pt.x ;
1316 if (y)
1317 *y = (int) pt.y ;
facd6764
SC
1318}
1319
1320void wxWindowMac::MacWindowToRootWindow( short *x , short *y ) const
1321{
1322 int x1 , y1 ;
e15f0a5e
DS
1323
1324 if (x)
1325 x1 = *x ;
1326 if (y)
1327 y1 = *y ;
1328
facd6764 1329 MacWindowToRootWindow( &x1 , &y1 ) ;
e15f0a5e
DS
1330
1331 if (x)
1332 *x = x1 ;
1333 if (y)
1334 *y = y1 ;
519cb848
SC
1335}
1336
1c310985 1337void wxWindowMac::MacRootWindowToWindow( int *x , int *y ) const
519cb848 1338{
5ca0d812 1339 wxPoint pt ;
e15f0a5e
DS
1340
1341 if (x)
1342 pt.x = *x ;
1343 if (y)
1344 pt.y = *y ;
facd6764 1345
125c7984 1346 if ( !IsTopLevel() )
5ca0d812 1347 {
5c840e5b
SC
1348 wxTopLevelWindowMac* top = MacGetTopLevelWindow();
1349 if (top)
1350 {
1351 wxMacControl::Convert( &pt , top->m_peer , m_peer ) ;
1352 pt.x += MacGetLeftBorderSize() ;
1353 pt.y += MacGetTopBorderSize() ;
1354 }
5ca0d812 1355 }
8b573fb8 1356
e15f0a5e
DS
1357 if (x)
1358 *x = (int) pt.x ;
1359 if (y)
1360 *y = (int) pt.y ;
e9576ca5
SC
1361}
1362
facd6764 1363void wxWindowMac::MacRootWindowToWindow( short *x , short *y ) const
e9576ca5 1364{
facd6764 1365 int x1 , y1 ;
e15f0a5e
DS
1366
1367 if (x)
1368 x1 = *x ;
1369 if (y)
1370 y1 = *y ;
1371
facd6764 1372 MacRootWindowToWindow( &x1 , &y1 ) ;
e15f0a5e
DS
1373
1374 if (x)
1375 *x = x1 ;
1376 if (y)
1377 *y = y1 ;
facd6764 1378}
6ed71b4f 1379
29281095
SC
1380void wxWindowMac::MacGetContentAreaInset( int &left , int &top , int &right , int &bottom )
1381{
1382 RgnHandle rgn = NewRgn() ;
898d9035 1383
5ca0d812 1384 if ( m_peer->GetRegion( kControlContentMetaPart , rgn ) == noErr )
29281095 1385 {
898d9035
DS
1386 Rect structure, content ;
1387
29281095 1388 GetRegionBounds( rgn , &content ) ;
1f1c8bd4
SC
1389 m_peer->GetRect( &structure ) ;
1390 OffsetRect( &structure, -structure.left , -structure.top ) ;
902725ee 1391
1f1c8bd4 1392 left = content.left - structure.left ;
898d9035 1393 top = content.top - structure.top ;
1f1c8bd4
SC
1394 right = structure.right - content.right ;
1395 bottom = structure.bottom - content.bottom ;
29281095
SC
1396 }
1397 else
1398 {
1f1c8bd4 1399 left = top = right = bottom = 0 ;
29281095 1400 }
898d9035 1401
7596e51d 1402 DisposeRgn( rgn ) ;
29281095
SC
1403}
1404
facd6764
SC
1405wxSize wxWindowMac::DoGetSizeFromClientSize( const wxSize & size ) const
1406{
1407 wxSize sizeTotal = size;
1408
1409 RgnHandle rgn = NewRgn() ;
5ca0d812 1410 if ( m_peer->GetRegion( kControlContentMetaPart , rgn ) == noErr )
6618870d 1411 {
898d9035 1412 Rect content, structure ;
facd6764 1413 GetRegionBounds( rgn , &content ) ;
1f1c8bd4 1414 m_peer->GetRect( &structure ) ;
898d9035 1415
1f1c8bd4 1416 // structure is in parent coordinates, but we only need width and height, so it's ok
6ed71b4f 1417
1f1c8bd4 1418 sizeTotal.x += (structure.right - structure.left) - (content.right - content.left) ;
8523a5f5 1419 sizeTotal.y += (structure.bottom - structure.top) - (content.bottom - content.top) ;
1f1c8bd4 1420 }
898d9035 1421
1f1c8bd4 1422 DisposeRgn( rgn ) ;
6ed71b4f 1423
e15f0a5e
DS
1424 sizeTotal.x += MacGetLeftBorderSize() + MacGetRightBorderSize() ;
1425 sizeTotal.y += MacGetTopBorderSize() + MacGetBottomBorderSize() ;
6ed71b4f 1426
facd6764 1427 return sizeTotal;
e9576ca5
SC
1428}
1429
e9576ca5 1430// Get size *available for subwindows* i.e. excluding menu bar etc.
e15f0a5e 1431void wxWindowMac::DoGetClientSize( int *x, int *y ) const
e9576ca5 1432{
9453cf2b 1433 int ww, hh;
6ed71b4f 1434
facd6764
SC
1435 RgnHandle rgn = NewRgn() ;
1436 Rect content ;
5ca0d812 1437 if ( m_peer->GetRegion( kControlContentMetaPart , rgn ) == noErr )
facd6764 1438 GetRegionBounds( rgn , &content ) ;
facd6764 1439 else
5ca0d812 1440 m_peer->GetRect( &content ) ;
7596e51d 1441 DisposeRgn( rgn ) ;
789ae0cf 1442
facd6764
SC
1443 ww = content.right - content.left ;
1444 hh = content.bottom - content.top ;
6ed71b4f 1445
db7a550b 1446 if (m_hScrollBar && m_hScrollBar->IsShown() )
e905b636 1447 hh -= m_hScrollBar->GetSize().y ;
e15f0a5e 1448
db7a550b 1449 if (m_vScrollBar && m_vScrollBar->IsShown() )
e905b636 1450 ww -= m_vScrollBar->GetSize().x ;
e15f0a5e
DS
1451
1452 if (x)
1453 *x = ww;
1454 if (y)
1455 *y = hh;
facd6764
SC
1456}
1457
1458bool wxWindowMac::SetCursor(const wxCursor& cursor)
1459{
a3ab1c18 1460 if (m_cursor.IsSameAs(cursor))
902725ee 1461 return false;
facd6764 1462
2e573683 1463 if (!cursor.IsOk())
facd6764
SC
1464 {
1465 if ( ! wxWindowBase::SetCursor( *wxSTANDARD_CURSOR ) )
902725ee 1466 return false ;
facd6764
SC
1467 }
1468 else
1469 {
1470 if ( ! wxWindowBase::SetCursor( cursor ) )
902725ee 1471 return false ;
facd6764
SC
1472 }
1473
1474 wxASSERT_MSG( m_cursor.Ok(),
1475 wxT("cursor must be valid after call to the base version"));
8b573fb8 1476
2d1760d3 1477 wxWindowMac *mouseWin = 0 ;
facd6764 1478 {
789ae0cf
SC
1479 wxTopLevelWindowMac *tlw = MacGetTopLevelWindow() ;
1480 WindowRef window = (WindowRef) ( tlw ? tlw->MacGetWindowRef() : 0 ) ;
4f74e0d1
SC
1481
1482 ControlPartCode part ;
1483 ControlRef control ;
1484 Point pt ;
1485 #if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
1486 HIPoint hiPoint ;
1487 HIGetMousePosition(kHICoordSpaceWindow, window, &hiPoint);
1488 pt.h = hiPoint.x;
1489 pt.v = hiPoint.y;
89954433 1490 #else
8e181eae
SC
1491 GetGlobalMouse( &pt );
1492 int x = pt.h;
1493 int y = pt.v;
1494 ScreenToClient(&x, &y);
1495 pt.h = x;
1496 pt.v = y;
4f74e0d1 1497#endif
9d463591 1498 control = FindControlUnderMouse( pt , window , &part ) ;
2d1760d3
SC
1499 if ( control )
1500 mouseWin = wxFindControlFromMacControl( control ) ;
8b573fb8 1501
facd6764 1502 }
2d1760d3
SC
1503
1504 if ( mouseWin == this && !wxIsBusy() )
facd6764 1505 m_cursor.MacInstall() ;
facd6764 1506
902725ee 1507 return true ;
519cb848
SC
1508}
1509
facd6764
SC
1510#if wxUSE_MENUS
1511bool wxWindowMac::DoPopupMenu(wxMenu *menu, int x, int y)
1512{
6239ee05
SC
1513#ifndef __WXUNIVERSAL__
1514 menu->SetInvokingWindow((wxWindow*)this);
facd6764 1515 menu->UpdateUI();
8b573fb8 1516
851dee09 1517 if ( x == wxDefaultCoord && y == wxDefaultCoord )
971562cb
VS
1518 {
1519 wxPoint mouse = wxGetMousePosition();
898d9035
DS
1520 x = mouse.x;
1521 y = mouse.y;
971562cb
VS
1522 }
1523 else
1524 {
1525 ClientToScreen( &x , &y ) ;
1526 }
facd6764
SC
1527
1528 menu->MacBeforeDisplay( true ) ;
898d9035 1529 long menuResult = ::PopUpMenuSelect((MenuHandle) menu->GetHMenu() , y, x, 0) ;
facd6764
SC
1530 if ( HiWord(menuResult) != 0 )
1531 {
e8027adb
SC
1532 MenuCommand macid;
1533 GetMenuItemCommandID( GetMenuHandle(HiWord(menuResult)) , LoWord(menuResult) , &macid );
b46dde27
DS
1534 int id = wxMacCommandToId( macid );
1535 wxMenuItem* item = NULL ;
facd6764 1536 wxMenu* realmenu ;
58603178 1537 item = menu->FindItem( id, &realmenu ) ;
e8027adb
SC
1538 if ( item )
1539 {
1540 if (item->IsCheckable())
1541 item->Check( !item->IsChecked() ) ;
e15f0a5e 1542
e8027adb
SC
1543 menu->SendEvent( id , item->IsCheckable() ? item->IsChecked() : -1 ) ;
1544 }
facd6764 1545 }
facd6764 1546
898d9035 1547 menu->MacAfterDisplay( true ) ;
8523a5f5 1548 menu->SetInvokingWindow( NULL );
facd6764 1549
902725ee 1550 return true;
6239ee05
SC
1551#else
1552 // actually this shouldn't be called, because universal is having its own implementation
1553 return false;
1554#endif
facd6764
SC
1555}
1556#endif
51abe921
SC
1557
1558// ----------------------------------------------------------------------------
1559// tooltips
1560// ----------------------------------------------------------------------------
1561
1562#if wxUSE_TOOLTIPS
1563
e766c8a9 1564void wxWindowMac::DoSetToolTip(wxToolTip *tooltip)
51abe921
SC
1565{
1566 wxWindowBase::DoSetToolTip(tooltip);
6ed71b4f 1567
6264b550
RR
1568 if ( m_tooltip )
1569 m_tooltip->SetWindow(this);
51abe921
SC
1570}
1571
898d9035 1572#endif
51abe921 1573
902725ee 1574void wxWindowMac::MacInvalidateBorders()
6449b3a8
SC
1575{
1576 if ( m_peer == NULL )
1577 return ;
1578
1579 bool vis = MacIsReallyShown() ;
1580 if ( !vis )
1581 return ;
902725ee 1582
6449b3a8
SC
1583 int outerBorder = MacGetLeftBorderSize() ;
1584 if ( m_peer->NeedsFocusRect() && m_peer->HasFocus() )
1585 outerBorder += 4 ;
1586
1587 if ( outerBorder == 0 )
1588 return ;
902725ee
WS
1589
1590 // now we know that we have something to do at all
6449b3a8
SC
1591
1592 // as the borders are drawn on the parent we have to properly invalidate all these areas
58603178
DS
1593 RgnHandle updateInner , updateOuter;
1594 Rect rect ;
6449b3a8
SC
1595
1596 // this rectangle is in HIViewCoordinates under OSX and in Window Coordinates under Carbon
58603178
DS
1597 updateInner = NewRgn() ;
1598 updateOuter = NewRgn() ;
1599
6449b3a8 1600 m_peer->GetRect( &rect ) ;
898d9035 1601 RectRgn( updateInner, &rect ) ;
6449b3a8 1602 InsetRect( &rect , -outerBorder , -outerBorder ) ;
898d9035
DS
1603 RectRgn( updateOuter, &rect ) ;
1604 DiffRgn( updateOuter, updateInner , updateOuter ) ;
e15f0a5e 1605
1f1c8bd4 1606 GetParent()->m_peer->SetNeedsDisplay( updateOuter ) ;
e15f0a5e 1607
58603178
DS
1608 DisposeRgn( updateOuter ) ;
1609 DisposeRgn( updateInner ) ;
6449b3a8
SC
1610}
1611
e766c8a9 1612void wxWindowMac::DoMoveWindow(int x, int y, int width, int height)
51abe921 1613{
db7a550b 1614 // this is never called for a toplevel window, so we know we have a parent
facd6764 1615 int former_x , former_y , former_w, former_h ;
db7a550b
SC
1616
1617 // Get true coordinates of former position
facd6764
SC
1618 DoGetPosition( &former_x , &former_y ) ;
1619 DoGetSize( &former_w , &former_h ) ;
db7a550b
SC
1620
1621 wxWindow *parent = GetParent();
1622 if ( parent )
1623 {
1624 wxPoint pt(parent->GetClientAreaOrigin());
1625 former_x += pt.x ;
1626 former_y += pt.y ;
1627 }
6ed71b4f 1628
29ee02df
SC
1629 int actualWidth = width ;
1630 int actualHeight = height ;
e40298d5
JS
1631 int actualX = x;
1632 int actualY = y;
6ed71b4f 1633
14c9cbdb 1634 if ((m_minWidth != -1) && (actualWidth < m_minWidth))
6264b550 1635 actualWidth = m_minWidth;
14c9cbdb 1636 if ((m_minHeight != -1) && (actualHeight < m_minHeight))
6264b550 1637 actualHeight = m_minHeight;
14c9cbdb 1638 if ((m_maxWidth != -1) && (actualWidth > m_maxWidth))
6264b550 1639 actualWidth = m_maxWidth;
14c9cbdb 1640 if ((m_maxHeight != -1) && (actualHeight > m_maxHeight))
902725ee 1641 actualHeight = m_maxHeight;
6ed71b4f 1642
898d9035 1643 bool doMove = false, doResize = false ;
6ed71b4f 1644
6264b550 1645 if ( actualX != former_x || actualY != former_y )
6264b550 1646 doMove = true ;
e15f0a5e 1647
6264b550 1648 if ( actualWidth != former_w || actualHeight != former_h )
6264b550 1649 doResize = true ;
6ed71b4f 1650
6264b550
RR
1651 if ( doMove || doResize )
1652 {
902725ee 1653 // as the borders are drawn outside the native control, we adjust now
1f1c8bd4 1654
902725ee
WS
1655 wxRect bounds( wxPoint( actualX + MacGetLeftBorderSize() ,actualY + MacGetTopBorderSize() ),
1656 wxSize( actualWidth - (MacGetLeftBorderSize() + MacGetRightBorderSize()) ,
1f1c8bd4
SC
1657 actualHeight - (MacGetTopBorderSize() + MacGetBottomBorderSize()) ) ) ;
1658
1659 Rect r ;
1660 wxMacRectToNative( &bounds , &r ) ;
1661
1662 if ( !GetParent()->IsTopLevel() )
1f1c8bd4 1663 wxMacWindowToNative( GetParent() , &r ) ;
8b573fb8 1664
6449b3a8 1665 MacInvalidateBorders() ;
902725ee 1666
5c840e5b 1667 m_cachedClippedRectValid = false ;
8b573fb8 1668 m_peer->SetRect( &r ) ;
902725ee 1669
e905b636 1670 wxWindowMac::MacSuperChangedPosition() ; // like this only children will be notified
91ae6e3a 1671
6449b3a8
SC
1672 MacInvalidateBorders() ;
1673
6264b550
RR
1674 MacRepositionScrollBars() ;
1675 if ( doMove )
1676 {
898d9035 1677 wxPoint point(actualX, actualY);
6264b550
RR
1678 wxMoveEvent event(point, m_windowId);
1679 event.SetEventObject(this);
1680 GetEventHandler()->ProcessEvent(event) ;
1681 }
e15f0a5e 1682
6264b550
RR
1683 if ( doResize )
1684 {
e40298d5 1685 MacRepositionScrollBars() ;
facd6764 1686 wxSize size(actualWidth, actualHeight);
e40298d5
JS
1687 wxSizeEvent event(size, m_windowId);
1688 event.SetEventObject(this);
1689 GetEventHandler()->ProcessEvent(event);
6264b550
RR
1690 }
1691 }
954fc50b
SC
1692}
1693
facd6764
SC
1694wxSize wxWindowMac::DoGetBestSize() const
1695{
eb69d46e
SC
1696 if ( m_macIsUserPane || IsTopLevel() )
1697 return wxWindowBase::DoGetBestSize() ;
8b573fb8 1698
facd6764 1699 Rect bestsize = { 0 , 0 , 0 , 0 } ;
facd6764 1700 int bestWidth, bestHeight ;
facd6764 1701
898d9035 1702 m_peer->GetBestRect( &bestsize ) ;
facd6764
SC
1703 if ( EmptyRect( &bestsize ) )
1704 {
898d9035
DS
1705 bestsize.left =
1706 bestsize.top = 0 ;
1707 bestsize.right =
facd6764 1708 bestsize.bottom = 16 ;
898d9035 1709
facd6764
SC
1710 if ( IsKindOf( CLASSINFO( wxScrollBar ) ) )
1711 {
1712 bestsize.bottom = 16 ;
1713 }
902725ee 1714#if wxUSE_SPINBTN
facd6764
SC
1715 else if ( IsKindOf( CLASSINFO( wxSpinButton ) ) )
1716 {
8b573fb8 1717 bestsize.bottom = 24 ;
facd6764 1718 }
898d9035 1719#endif
facd6764
SC
1720 else
1721 {
8b573fb8 1722 // return wxWindowBase::DoGetBestSize() ;
facd6764
SC
1723 }
1724 }
1725
1726 bestWidth = bestsize.right - bestsize.left ;
1727 bestHeight = bestsize.bottom - bestsize.top ;
1728 if ( bestHeight < 10 )
1729 bestHeight = 13 ;
8b573fb8 1730
facd6764
SC
1731 return wxSize(bestWidth, bestHeight);
1732}
1733
954fc50b
SC
1734// set the size of the window: if the dimensions are positive, just use them,
1735// but if any of them is equal to -1, it means that we must find the value for
1736// it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in
1737// which case -1 is a valid value for x and y)
1738//
1739// If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate
1740// the width/height to best suit our contents, otherwise we reuse the current
1741// width/height
1742void wxWindowMac::DoSetSize(int x, int y, int width, int height, int sizeFlags)
1743{
1744 // get the current size and position...
1745 int currentX, currentY;
898d9035 1746 int currentW, currentH;
6ed71b4f 1747
898d9035 1748 GetPosition(&currentX, &currentY);
954fc50b 1749 GetSize(&currentW, &currentH);
6ed71b4f 1750
954fc50b
SC
1751 // ... and don't do anything (avoiding flicker) if it's already ok
1752 if ( x == currentX && y == currentY &&
769ac869 1753 width == currentW && height == currentH && ( height != -1 && width != -1 ) )
954fc50b 1754 {
e15f0a5e 1755 // TODO: REMOVE
6264b550 1756 MacRepositionScrollBars() ; // we might have a real position shift
898d9035 1757
954fc50b
SC
1758 return;
1759 }
6ed71b4f 1760
58603178
DS
1761 if ( !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) )
1762 {
1763 if ( x == wxDefaultCoord )
1764 x = currentX;
1765 if ( y == wxDefaultCoord )
1766 y = currentY;
1767 }
6ed71b4f 1768
58603178 1769 AdjustForParentClientOrigin( x, y, sizeFlags );
6ed71b4f 1770
3dee36ae
WS
1771 wxSize size = wxDefaultSize;
1772 if ( width == wxDefaultCoord )
954fc50b
SC
1773 {
1774 if ( sizeFlags & wxSIZE_AUTO_WIDTH )
1775 {
1776 size = DoGetBestSize();
1777 width = size.x;
1778 }
1779 else
1780 {
1781 // just take the current one
1782 width = currentW;
1783 }
1784 }
6ed71b4f 1785
3dee36ae 1786 if ( height == wxDefaultCoord )
954fc50b
SC
1787 {
1788 if ( sizeFlags & wxSIZE_AUTO_HEIGHT )
1789 {
3dee36ae 1790 if ( size.x == wxDefaultCoord )
954fc50b 1791 size = DoGetBestSize();
898d9035 1792 // else: already called DoGetBestSize() above
6ed71b4f 1793
954fc50b
SC
1794 height = size.y;
1795 }
1796 else
1797 {
1798 // just take the current one
1799 height = currentH;
1800 }
1801 }
6ed71b4f 1802
58603178 1803 DoMoveWindow( x, y, width, height );
e9576ca5 1804}
519cb848 1805
e766c8a9 1806wxPoint wxWindowMac::GetClientAreaOrigin() const
e9576ca5 1807{
facd6764
SC
1808 RgnHandle rgn = NewRgn() ;
1809 Rect content ;
04d4e684 1810 if ( m_peer->GetRegion( kControlContentMetaPart , rgn ) == noErr )
21638402
SC
1811 {
1812 GetRegionBounds( rgn , &content ) ;
1813 }
1814 else
1815 {
898d9035
DS
1816 content.left =
1817 content.top = 0 ;
21638402 1818 }
898d9035 1819
facd6764 1820 DisposeRgn( rgn ) ;
e15f0a5e
DS
1821
1822 return wxPoint( content.left + MacGetLeftBorderSize() , content.top + MacGetTopBorderSize() );
facd6764
SC
1823}
1824
1825void wxWindowMac::DoSetClientSize(int clientwidth, int clientheight)
1826{
d0dec992 1827 if ( clientwidth != wxDefaultCoord || clientheight != wxDefaultCoord )
facd6764
SC
1828 {
1829 int currentclientwidth , currentclientheight ;
1830 int currentwidth , currentheight ;
1831
1832 GetClientSize( &currentclientwidth , &currentclientheight ) ;
1833 GetSize( &currentwidth , &currentheight ) ;
1834
3dee36ae 1835 DoSetSize( wxDefaultCoord , wxDefaultCoord , currentwidth + clientwidth - currentclientwidth ,
facd6764
SC
1836 currentheight + clientheight - currentclientheight , wxSIZE_USE_EXISTING ) ;
1837 }
e9576ca5
SC
1838}
1839
fb5246be 1840void wxWindowMac::SetLabel(const wxString& title)
e9576ca5 1841{
6239ee05 1842 m_label = title ;
facd6764 1843
21fd5529 1844 if ( m_peer && m_peer->Ok() )
6239ee05 1845 m_peer->SetLabel( wxStripMenuCodes(m_label, wxStrip_Mnemonics) ) ;
e15f0a5e 1846
6239ee05
SC
1847 // do not trigger refreshes upon invisible and possible partly created objects
1848 if ( MacIsReallyShown() )
1849 Refresh() ;
519cb848
SC
1850}
1851
fb5246be 1852wxString wxWindowMac::GetLabel() const
519cb848 1853{
ed60b502 1854 return m_label ;
519cb848
SC
1855}
1856
8ab50549
SC
1857bool wxWindowMac::Show(bool show)
1858{
1859 if ( !wxWindowBase::Show(show) )
902725ee 1860 return false;
8b573fb8 1861
2c899c20 1862 if ( m_peer )
2c899c20 1863 m_peer->SetVisibility( show , true ) ;
e15f0a5e 1864
902725ee 1865 return true;
8ab50549
SC
1866}
1867
47a8a4d5 1868void wxWindowMac::DoEnable(bool enable)
8ab50549 1869{
5ca0d812 1870 m_peer->Enable( enable ) ;
8ab50549
SC
1871}
1872
8ab50549
SC
1873//
1874// status change notifications
8b573fb8 1875//
8ab50549 1876
8b573fb8 1877void wxWindowMac::MacVisibilityChanged()
8ab50549
SC
1878{
1879}
1880
8b573fb8 1881void wxWindowMac::MacHiliteChanged()
8ab50549
SC
1882{
1883}
1884
8b573fb8 1885void wxWindowMac::MacEnabledStateChanged()
8ab50549 1886{
8e181eae 1887 OnEnabled( m_peer->IsEnabled() );
facd6764 1888}
e7549107 1889
8ab50549
SC
1890//
1891// status queries on the inherited window's state
1892//
1893
8b573fb8 1894bool wxWindowMac::MacIsReallyShown()
facd6764
SC
1895{
1896 // only under OSX the visibility of the TLW is taken into account
66ffb23b
SC
1897 if ( m_isBeingDeleted )
1898 return false ;
902725ee 1899
facd6764 1900#if TARGET_API_MAC_OSX
aa522e33
SC
1901 if ( m_peer && m_peer->Ok() )
1902 return m_peer->IsVisible();
1903#endif
e15f0a5e 1904
facd6764 1905 wxWindow* win = this ;
898d9035 1906 while ( win->IsShown() )
facd6764
SC
1907 {
1908 if ( win->IsTopLevel() )
1909 return true ;
8b573fb8 1910
facd6764
SC
1911 win = win->GetParent() ;
1912 if ( win == NULL )
1913 return true ;
e15f0a5e 1914 }
8b573fb8 1915
facd6764 1916 return false ;
facd6764 1917}
4241baae 1918
8b573fb8 1919bool wxWindowMac::MacIsReallyEnabled()
facd6764 1920{
5ca0d812 1921 return m_peer->IsEnabled() ;
facd6764
SC
1922}
1923
8b573fb8 1924bool wxWindowMac::MacIsReallyHilited()
c809f3be 1925{
5ca0d812 1926 return m_peer->IsActive();
c809f3be
SC
1927}
1928
8b573fb8 1929void wxWindowMac::MacFlashInvalidAreas()
002c9672
SC
1930{
1931#if TARGET_API_MAC_OSX
1932 HIViewFlashDirtyArea( (WindowRef) MacGetTopLevelWindowRef() ) ;
1933#endif
1934}
1935
e766c8a9 1936int wxWindowMac::GetCharHeight() const
e9576ca5 1937{
e15f0a5e
DS
1938 wxClientDC dc( (wxWindowMac*)this ) ;
1939
6264b550 1940 return dc.GetCharHeight() ;
e9576ca5
SC
1941}
1942
e766c8a9 1943int wxWindowMac::GetCharWidth() const
e9576ca5 1944{
e15f0a5e
DS
1945 wxClientDC dc( (wxWindowMac*)this ) ;
1946
6264b550 1947 return dc.GetCharWidth() ;
e9576ca5
SC
1948}
1949
e766c8a9 1950void wxWindowMac::GetTextExtent(const wxString& string, int *x, int *y,
e7549107 1951 int *descent, int *externalLeading, const wxFont *theFont ) const
e9576ca5 1952{
e7549107
SC
1953 const wxFont *fontToUse = theFont;
1954 if ( !fontToUse )
1955 fontToUse = &m_font;
14c9cbdb 1956
e766c8a9 1957 wxClientDC dc( (wxWindowMac*) this ) ;
659863d8 1958 wxCoord lx,ly,ld,le ;
5fde6fcc 1959 dc.GetTextExtent( string , &lx , &ly , &ld, &le, (wxFont *)fontToUse ) ;
2f1ae414 1960 if ( externalLeading )
6264b550 1961 *externalLeading = le ;
2f1ae414 1962 if ( descent )
6264b550 1963 *descent = ld ;
2f1ae414 1964 if ( x )
6264b550 1965 *x = lx ;
2f1ae414 1966 if ( y )
6264b550 1967 *y = ly ;
e9576ca5
SC
1968}
1969
0a67a93b 1970/*
14c9cbdb 1971 * Rect is given in client coordinates, for further reading, read wxTopLevelWindowMac::InvalidateRect
1c310985
SC
1972 * we always intersect with the entire window, not only with the client area
1973 */
14c9cbdb 1974
89954433 1975void wxWindowMac::Refresh(bool WXUNUSED(eraseBack), const wxRect *rect)
e9576ca5 1976{
065ab451
SC
1977 if ( m_peer == NULL )
1978 return ;
8b573fb8 1979
1f1c8bd4
SC
1980 if ( !MacIsReallyShown() )
1981 return ;
789ae0cf 1982
1f1c8bd4 1983 if ( rect )
1e8cde71 1984 {
1f1c8bd4 1985 Rect r ;
898d9035 1986
1f1c8bd4
SC
1987 wxMacRectToNative( rect , &r ) ;
1988 m_peer->SetNeedsDisplay( &r ) ;
facd6764 1989 }
1f1c8bd4 1990 else
9a456218 1991 {
1f1c8bd4 1992 m_peer->SetNeedsDisplay() ;
e9576ca5 1993 }
facd6764
SC
1994}
1995
79392158
SC
1996void wxWindowMac::Freeze()
1997{
1998#if TARGET_API_MAC_OSX
1999 if ( !m_frozenness++ )
2000 {
52ef5c3c
RD
2001 if ( m_peer && m_peer->Ok() )
2002 m_peer->SetDrawingEnabled( false ) ;
79392158
SC
2003 }
2004#endif
2005}
2006
2007void wxWindowMac::Thaw()
2008{
2009#if TARGET_API_MAC_OSX
898d9035 2010 wxASSERT_MSG( m_frozenness > 0, wxT("Thaw() without matching Freeze()") );
79392158
SC
2011
2012 if ( !--m_frozenness )
2013 {
52ef5c3c
RD
2014 if ( m_peer && m_peer->Ok() )
2015 {
2016 m_peer->SetDrawingEnabled( true ) ;
2017 m_peer->InvalidateWithChildren() ;
2018 }
79392158
SC
2019 }
2020#endif
2021}
2022
fd39f7a8
RD
2023bool wxWindowMac::IsFrozen() const
2024{
2025 return m_frozenness != 0;
2026}
2027
e766c8a9 2028wxWindowMac *wxGetActiveWindow()
e9576ca5 2029{
519cb848 2030 // actually this is a windows-only concept
e9576ca5
SC
2031 return NULL;
2032}
2033
e9576ca5 2034// Coordinates relative to the window
89954433 2035void wxWindowMac::WarpPointer(int WXUNUSED(x_pos), int WXUNUSED(y_pos))
e9576ca5 2036{
e40298d5 2037 // We really don't move the mouse programmatically under Mac.
e9576ca5
SC
2038}
2039
facd6764 2040void wxWindowMac::OnEraseBackground(wxEraseEvent& event)
e9576ca5 2041{
3dee36ae
WS
2042 if ( MacGetTopLevelWindow() == NULL )
2043 return ;
af06e625 2044/*
be346c26 2045#if TARGET_API_MAC_OSX
a01d9a25 2046 if ( !m_backgroundColour.Ok() || GetBackgroundStyle() == wxBG_STYLE_TRANSPARENT )
94abc21f 2047 {
94abc21f
SC
2048 }
2049 else
be346c26 2050#endif
af06e625
SC
2051*/
2052 if ( GetBackgroundStyle() == wxBG_STYLE_COLOUR )
7ebf5540 2053 {
8b573fb8 2054 event.GetDC()->Clear() ;
7ebf5540 2055 }
af06e625
SC
2056 else
2057 {
2058 event.Skip() ;
2059 }
1c310985
SC
2060}
2061
2062void wxWindowMac::OnNcPaint( wxNcPaintEvent& event )
2063{
af6b7b80 2064 event.Skip() ;
e9576ca5
SC
2065}
2066
e766c8a9 2067int wxWindowMac::GetScrollPos(int orient) const
e9576ca5 2068{
1c310985
SC
2069 if ( orient == wxHORIZONTAL )
2070 {
2071 if ( m_hScrollBar )
2072 return m_hScrollBar->GetThumbPosition() ;
2073 }
2074 else
2075 {
2076 if ( m_vScrollBar )
2077 return m_vScrollBar->GetThumbPosition() ;
2078 }
e15f0a5e 2079
e9576ca5
SC
2080 return 0;
2081}
2082
2083// This now returns the whole range, not just the number
2084// of positions that we can scroll.
e766c8a9 2085int wxWindowMac::GetScrollRange(int orient) const
e9576ca5 2086{
1c310985
SC
2087 if ( orient == wxHORIZONTAL )
2088 {
2089 if ( m_hScrollBar )
2090 return m_hScrollBar->GetRange() ;
2091 }
2092 else
2093 {
2094 if ( m_vScrollBar )
2095 return m_vScrollBar->GetRange() ;
2096 }
e15f0a5e 2097
e9576ca5
SC
2098 return 0;
2099}
2100
e766c8a9 2101int wxWindowMac::GetScrollThumb(int orient) const
e9576ca5 2102{
1c310985
SC
2103 if ( orient == wxHORIZONTAL )
2104 {
2105 if ( m_hScrollBar )
2106 return m_hScrollBar->GetThumbSize() ;
2107 }
2108 else
2109 {
2110 if ( m_vScrollBar )
2111 return m_vScrollBar->GetThumbSize() ;
2112 }
e15f0a5e 2113
e9576ca5
SC
2114 return 0;
2115}
2116
89954433 2117void wxWindowMac::SetScrollPos(int orient, int pos, bool WXUNUSED(refresh))
e9576ca5 2118{
1c310985 2119 if ( orient == wxHORIZONTAL )
6264b550 2120 {
1c310985
SC
2121 if ( m_hScrollBar )
2122 m_hScrollBar->SetThumbPosition( pos ) ;
6264b550
RR
2123 }
2124 else
2125 {
1c310985
SC
2126 if ( m_vScrollBar )
2127 m_vScrollBar->SetThumbPosition( pos ) ;
6264b550 2128 }
2f1ae414
SC
2129}
2130
c1142003
VZ
2131void
2132wxWindowMac::AlwaysShowScrollbars(bool hflag, bool vflag)
2133{
2134 bool needVisibilityUpdate = false;
2135
2136 if ( m_hScrollBarAlwaysShown != hflag )
2137 {
2138 m_hScrollBarAlwaysShown = hflag;
2139 needVisibilityUpdate = true;
2140 }
2141
2142 if ( m_vScrollBarAlwaysShown != vflag )
2143 {
2144 m_vScrollBarAlwaysShown = vflag;
2145 needVisibilityUpdate = true;
2146 }
2147
2148 if ( needVisibilityUpdate )
2149 DoUpdateScrollbarVisibility();
2150}
6239ee05 2151
c79aad8b
SC
2152//
2153// we draw borders and grow boxes, are already set up and clipped in the current port / cgContextRef
2154// our own window origin is at leftOrigin/rightOrigin
2155//
2156
6239ee05
SC
2157void wxWindowMac::MacPaintGrowBox()
2158{
2159 if ( IsTopLevel() )
2160 return ;
2161
6239ee05
SC
2162 if ( MacHasScrollBarCorner() )
2163 {
2164 Rect rect ;
2165
2166 CGContextRef cgContext = (CGContextRef) MacGetCGContextRef() ;
2167 wxASSERT( cgContext ) ;
2168
2169 m_peer->GetRect( &rect ) ;
2170
2171 int size = m_hScrollBar ? m_hScrollBar->GetSize().y : ( m_vScrollBar ? m_vScrollBar->GetSize().x : MAC_SCROLLBAR_SIZE ) ;
2172 CGRect cgrect = CGRectMake( rect.right - size , rect.bottom - size , size , size ) ;
2173 CGPoint cgpoint = CGPointMake( rect.right - size , rect.bottom - size ) ;
2174 CGContextSaveGState( cgContext );
2175
a01d9a25 2176 if ( m_backgroundColour.Ok() )
6239ee05 2177 {
a01d9a25 2178 CGContextSetFillColorWithColor( cgContext, m_backgroundColour.GetCGColor() );
6239ee05
SC
2179 }
2180 else
2181 {
2182 CGContextSetRGBFillColor( cgContext, 1.0, 1.0 , 1.0 , 1.0 );
2183 }
2184 CGContextFillRect( cgContext, cgrect );
2185 CGContextRestoreGState( cgContext );
2186 }
6239ee05
SC
2187}
2188
89954433 2189void wxWindowMac::MacPaintBorders( int WXUNUSED(leftOrigin) , int WXUNUSED(rightOrigin) )
2f1ae414 2190{
e15f0a5e 2191 if ( IsTopLevel() )
6264b550 2192 return ;
8b573fb8 2193
fd926bcc 2194 Rect rect ;
c79aad8b 2195 bool hasFocus = m_peer->NeedsFocusRect() && m_peer->HasFocus() ;
c79aad8b 2196
8f39b6c4 2197 // back to the surrounding frame rectangle
58603178 2198 m_peer->GetRect( &rect ) ;
8f39b6c4 2199 InsetRect( &rect, -1 , -1 ) ;
fd926bcc 2200
c79aad8b 2201 {
8f39b6c4
SC
2202 CGRect cgrect = CGRectMake( rect.left , rect.top , rect.right - rect.left ,
2203 rect.bottom - rect.top ) ;
2204
c79aad8b 2205 HIThemeFrameDrawInfo info ;
58603178 2206 memset( &info, 0 , sizeof(info) ) ;
902725ee 2207
c79aad8b
SC
2208 info.version = 0 ;
2209 info.kind = 0 ;
2210 info.state = IsEnabled() ? kThemeStateActive : kThemeStateInactive ;
2211 info.isFocused = hasFocus ;
c79aad8b
SC
2212
2213 CGContextRef cgContext = (CGContextRef) GetParent()->MacGetCGContextRef() ;
2214 wxASSERT( cgContext ) ;
902725ee 2215
e15f0a5e 2216 if ( HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER) || HasFlag(wxDOUBLE_BORDER) )
c79aad8b 2217 {
c79aad8b 2218 info.kind = kHIThemeFrameTextFieldSquare ;
8f39b6c4 2219 HIThemeDrawFrame( &cgrect , &info , cgContext , kHIThemeOrientationNormal ) ;
c79aad8b 2220 }
e15f0a5e 2221 else if ( HasFlag(wxSIMPLE_BORDER) )
c79aad8b 2222 {
c79aad8b 2223 info.kind = kHIThemeFrameListBox ;
c79aad8b
SC
2224 HIThemeDrawFrame( &cgrect , &info , cgContext , kHIThemeOrientationNormal ) ;
2225 }
2226 else if ( hasFocus )
2227 {
c79aad8b
SC
2228 HIThemeDrawFocusRect( &cgrect , true , cgContext , kHIThemeOrientationNormal ) ;
2229 }
6239ee05 2230#if 0 // TODO REMOVE now done in a separate call earlier in drawing the window itself
c79aad8b 2231 m_peer->GetRect( &rect ) ;
6239ee05 2232 if ( MacHasScrollBarCorner() )
c79aad8b 2233 {
6239ee05
SC
2234 int variant = (m_hScrollBar == NULL ? m_vScrollBar : m_hScrollBar ) ->GetWindowVariant();
2235 int size = m_hScrollBar ? m_hScrollBar->GetSize().y : ( m_vScrollBar ? m_vScrollBar->GetSize().x : MAC_SCROLLBAR_SIZE ) ;
8f39b6c4
SC
2236 CGRect cgrect = CGRectMake( rect.right - size , rect.bottom - size , size , size ) ;
2237 CGPoint cgpoint = CGPointMake( rect.right - size , rect.bottom - size ) ;
902725ee 2238 HIThemeGrowBoxDrawInfo info ;
e15f0a5e 2239 memset( &info, 0, sizeof(info) ) ;
c79aad8b
SC
2240 info.version = 0 ;
2241 info.state = IsEnabled() ? kThemeStateActive : kThemeStateInactive ;
2242 info.kind = kHIThemeGrowBoxKindNone ;
6239ee05 2243 // contrary to the docs ...SizeSmall does not work
c79aad8b 2244 info.size = kHIThemeGrowBoxSizeNormal ;
6239ee05 2245 info.direction = 0 ;
c79aad8b
SC
2246 HIThemeDrawGrowBox( &cgpoint , &info , cgContext , kHIThemeOrientationNormal ) ;
2247 }
6239ee05 2248#endif
c79aad8b 2249 }
8208e181
SC
2250}
2251
abda5788
SC
2252void wxWindowMac::RemoveChild( wxWindowBase *child )
2253{
2254 if ( child == m_hScrollBar )
2255 m_hScrollBar = NULL ;
2256 if ( child == m_vScrollBar )
2257 m_vScrollBar = NULL ;
14c9cbdb 2258
abda5788
SC
2259 wxWindowBase::RemoveChild( child ) ;
2260}
2261
c1142003 2262void wxWindowMac::DoUpdateScrollbarVisibility()
e9576ca5 2263{
42cc0b31 2264 bool triggerSizeEvent = false;
58603178 2265
c1142003 2266 if ( m_hScrollBar )
e40298d5 2267 {
c1142003 2268 bool showHScrollBar = m_hScrollBarAlwaysShown || m_hScrollBar->IsNeeded();
e15f0a5e 2269
c1142003
VZ
2270 if ( m_hScrollBar->IsShown() != showHScrollBar )
2271 {
2272 m_hScrollBar->Show( showHScrollBar );
2273 triggerSizeEvent = true;
6264b550 2274 }
e40298d5 2275 }
c1142003
VZ
2276
2277 if ( m_vScrollBar)
e40298d5 2278 {
c1142003 2279 bool showVScrollBar = m_vScrollBarAlwaysShown || m_vScrollBar->IsNeeded();
e15f0a5e 2280
c1142003
VZ
2281 if ( m_vScrollBar->IsShown() != showVScrollBar )
2282 {
2283 m_vScrollBar->Show( showVScrollBar ) ;
2284 triggerSizeEvent = true;
6264b550 2285 }
e40298d5 2286 }
e15f0a5e 2287
e40298d5 2288 MacRepositionScrollBars() ;
42cc0b31
SC
2289 if ( triggerSizeEvent )
2290 {
2291 wxSizeEvent event(GetSize(), m_windowId);
2292 event.SetEventObject(this);
2293 GetEventHandler()->ProcessEvent(event);
2294 }
e9576ca5
SC
2295}
2296
c1142003
VZ
2297// New function that will replace some of the above.
2298void wxWindowMac::SetScrollbar(int orient, int pos, int thumb,
2299 int range, bool refresh)
2300{
2301 if ( orient == wxHORIZONTAL && m_hScrollBar )
2302 m_hScrollBar->SetScrollbar(pos, thumb, range, thumb, refresh);
2303 else if ( orient == wxVERTICAL && m_vScrollBar )
2304 m_vScrollBar->SetScrollbar(pos, thumb, range, thumb, refresh);
2305
2306 DoUpdateScrollbarVisibility();
2307}
2308
e9576ca5 2309// Does a physical scroll
e766c8a9 2310void wxWindowMac::ScrollWindow(int dx, int dy, const wxRect *rect)
e9576ca5 2311{
898d9035 2312 if ( dx == 0 && dy == 0 )
ba87f54c 2313 return ;
8b573fb8 2314
3dee36ae
WS
2315 int width , height ;
2316 GetClientSize( &width , &height ) ;
e15f0a5e 2317
902725ee 2318 {
002c9672 2319 // note there currently is a bug in OSX which makes inefficient refreshes in case an entire control
8b573fb8 2320 // area is scrolled, this does not occur if width and height are 2 pixels less,
58603178 2321 // TODO: write optimal workaround
898d9035 2322 wxRect scrollrect( MacGetLeftBorderSize() , MacGetTopBorderSize() , width , height ) ;
8b573fb8 2323 if ( rect )
5ca0d812 2324 scrollrect.Intersect( *rect ) ;
e15f0a5e 2325
5ca0d812 2326 if ( m_peer->GetNeedsDisplay() )
002c9672 2327 {
58603178 2328 // because HIViewScrollRect does not scroll the already invalidated area we have two options:
8dd37b03 2329 // in case there is already a pending redraw on that area
002c9672
SC
2330 // either immediate redraw or full invalidate
2331#if 1
2332 // is the better overall solution, as it does not slow down scrolling
1f1c8bd4 2333 m_peer->SetNeedsDisplay() ;
002c9672 2334#else
8b573fb8 2335 // this would be the preferred version for fast drawing controls
80f3f3be 2336 HIViewRender(m_peer->GetControlRef()) ;
002c9672
SC
2337#endif
2338 }
e15f0a5e 2339
84e5d27d
SC
2340 // as the native control might be not a 0/0 wx window coordinates, we have to offset
2341 scrollrect.Offset( -MacGetLeftBorderSize() , -MacGetTopBorderSize() ) ;
898d9035 2342 m_peer->ScrollRect( &scrollrect , dx , dy ) ;
92346151 2343
92346151 2344#if 0
902725ee 2345 // this would be the preferred version for fast drawing controls
4f74e0d1 2346 HIViewRender(m_peer->GetControlRef()) ;
92346151 2347#endif
902725ee 2348 }
6ed71b4f 2349
e15f0a5e
DS
2350 wxWindowMac *child;
2351 int x, y, w, h;
71f2fb52 2352 for (wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); node; node = node->GetNext())
6264b550 2353 {
e15f0a5e
DS
2354 child = node->GetData();
2355 if (child == NULL)
2356 continue;
2357 if (child == m_vScrollBar)
2358 continue;
2359 if (child == m_hScrollBar)
2360 continue;
2361 if (child->IsTopLevel())
2362 continue;
6ed71b4f 2363
6264b550 2364 child->GetPosition( &x, &y );
6264b550 2365 child->GetSize( &w, &h );
00f55394
SC
2366 if (rect)
2367 {
e15f0a5e
DS
2368 wxRect rc( x, y, w, h );
2369 if (rect->Intersects( rc ))
8d1547ef 2370 child->SetSize( x + dx, y + dy, w, h, wxSIZE_AUTO|wxSIZE_ALLOW_MINUS_ONE );
00f55394
SC
2371 }
2372 else
2373 {
8d1547ef 2374 child->SetSize( x + dx, y + dy, w, h, wxSIZE_AUTO|wxSIZE_ALLOW_MINUS_ONE );
8b573fb8 2375 }
6264b550 2376 }
e9576ca5
SC
2377}
2378
e15f0a5e 2379void wxWindowMac::MacOnScroll( wxScrollEvent &event )
7c74e7fe 2380{
687706f5 2381 if ( event.GetEventObject() == m_vScrollBar || event.GetEventObject() == m_hScrollBar )
6264b550
RR
2382 {
2383 wxScrollWinEvent wevent;
2384 wevent.SetPosition(event.GetPosition());
2385 wevent.SetOrientation(event.GetOrientation());
687706f5
KH
2386 wevent.SetEventObject(this);
2387
2388 if (event.GetEventType() == wxEVT_SCROLL_TOP)
2389 wevent.SetEventType( wxEVT_SCROLLWIN_TOP );
2390 else if (event.GetEventType() == wxEVT_SCROLL_BOTTOM)
2391 wevent.SetEventType( wxEVT_SCROLLWIN_BOTTOM );
2392 else if (event.GetEventType() == wxEVT_SCROLL_LINEUP)
2393 wevent.SetEventType( wxEVT_SCROLLWIN_LINEUP );
2394 else if (event.GetEventType() == wxEVT_SCROLL_LINEDOWN)
2395 wevent.SetEventType( wxEVT_SCROLLWIN_LINEDOWN );
2396 else if (event.GetEventType() == wxEVT_SCROLL_PAGEUP)
2397 wevent.SetEventType( wxEVT_SCROLLWIN_PAGEUP );
2398 else if (event.GetEventType() == wxEVT_SCROLL_PAGEDOWN)
2399 wevent.SetEventType( wxEVT_SCROLLWIN_PAGEDOWN );
2400 else if (event.GetEventType() == wxEVT_SCROLL_THUMBTRACK)
2401 wevent.SetEventType( wxEVT_SCROLLWIN_THUMBTRACK );
2402 else if (event.GetEventType() == wxEVT_SCROLL_THUMBRELEASE)
2403 wevent.SetEventType( wxEVT_SCROLLWIN_THUMBRELEASE );
6ed71b4f
VZ
2404
2405 GetEventHandler()->ProcessEvent(wevent);
7c74e7fe
SC
2406 }
2407}
2408
e9576ca5 2409// Get the window with the focus
0fe02759 2410wxWindowMac *wxWindowBase::DoFindFocus()
e9576ca5 2411{
f1d527c1
SC
2412 ControlRef control ;
2413 GetKeyboardFocus( GetUserFocusWindow() , &control ) ;
2414 return wxFindControlFromMacControl( control ) ;
519cb848
SC
2415}
2416
e15f0a5e 2417void wxWindowMac::OnSetFocus( wxFocusEvent& event )
7810c95b
SC
2418{
2419 // panel wants to track the window which was the last to have focus in it,
2420 // so we want to set ourselves as the window which last had focus
2421 //
dac390e9 2422 // notice that it's also important to do it upwards the tree because
7810c95b
SC
2423 // otherwise when the top level panel gets focus, it won't set it back to
2424 // us, but to some other sibling
6ed71b4f 2425
dac390e9 2426 // CS: don't know if this is still needed:
c1fb8167
SC
2427 //wxChildFocusEvent eventFocus(this);
2428 //(void)GetEventHandler()->ProcessEvent(eventFocus);
7810c95b 2429
5ca0d812
SC
2430 if ( MacGetTopLevelWindow() && m_peer->NeedsFocusRect() )
2431 {
dac390e9 2432 GetParent()->Refresh() ;
788e118f 2433 wxMacWindowStateSaver sv( this ) ;
6449b3a8 2434 Rect rect ;
dac390e9 2435
6449b3a8 2436 m_peer->GetRect( &rect ) ;
6239ee05 2437 // auf den umgebenden Rahmen zurチᅡ゚ck
8f39b6c4 2438 InsetRect( &rect, -1 , -1 ) ;
1f1c8bd4 2439
6449b3a8 2440 wxTopLevelWindowMac* top = MacGetTopLevelWindow();
dac390e9 2441 if ( top )
6449b3a8 2442 {
898d9035 2443 wxPoint pt(0, 0) ;
6449b3a8
SC
2444 wxMacControl::Convert( &pt , GetParent()->m_peer , top->m_peer ) ;
2445 rect.left += pt.x ;
2446 rect.right += pt.x ;
2447 rect.top += pt.y ;
2448 rect.bottom += pt.y ;
2449 }
5ca0d812 2450
fbc1d11b 2451 bool bIsFocusEvent = (event.GetEventType() == wxEVT_SET_FOCUS);
c394a432 2452 DrawThemeFocusRect( &rect , bIsFocusEvent ) ;
dac390e9 2453 if ( !bIsFocusEvent )
af6b7b80 2454 {
af6b7b80 2455 // as this erases part of the frame we have to redraw borders
101634b2
SC
2456 // and because our z-ordering is not always correct (staticboxes)
2457 // we have to invalidate things, we cannot simple redraw
6449b3a8 2458 MacInvalidateBorders() ;
af6b7b80 2459 }
5ca0d812
SC
2460 }
2461
7810c95b
SC
2462 event.Skip();
2463}
2464
e39af974 2465void wxWindowMac::OnInternalIdle()
e9576ca5 2466{
e9576ca5
SC
2467 // This calls the UI-update mechanism (querying windows for
2468 // menu/toolbar/control state information)
6239ee05 2469 if (wxUpdateUIEvent::CanUpdate(this) && IsShown())
e39af974 2470 UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
e9576ca5
SC
2471}
2472
2473// Raise the window to the top of the Z order
e766c8a9 2474void wxWindowMac::Raise()
e9576ca5 2475{
5ca0d812 2476 m_peer->SetZOrder( true , NULL ) ;
e9576ca5
SC
2477}
2478
2479// Lower the window to the bottom of the Z order
e766c8a9 2480void wxWindowMac::Lower()
e9576ca5 2481{
5ca0d812 2482 m_peer->SetZOrder( false , NULL ) ;
e9576ca5
SC
2483}
2484
facd6764 2485// static wxWindow *gs_lastWhich = NULL;
519cb848 2486
e15f0a5e 2487bool wxWindowMac::MacSetupCursor( const wxPoint& pt )
467e3168
SC
2488{
2489 // first trigger a set cursor event
6ed71b4f 2490
467e3168
SC
2491 wxPoint clientorigin = GetClientAreaOrigin() ;
2492 wxSize clientsize = GetClientSize() ;
2493 wxCursor cursor ;
2494 if ( wxRect2DInt( clientorigin.x , clientorigin.y , clientsize.x , clientsize.y ).Contains( wxPoint2DInt( pt ) ) )
7de59551 2495 {
467e3168 2496 wxSetCursorEvent event( pt.x , pt.y );
6ed71b4f 2497
467e3168
SC
2498 bool processedEvtSetCursor = GetEventHandler()->ProcessEvent(event);
2499 if ( processedEvtSetCursor && event.HasCursor() )
2500 {
e40298d5 2501 cursor = event.GetCursor() ;
467e3168
SC
2502 }
2503 else
2504 {
467e3168
SC
2505 // the test for processedEvtSetCursor is here to prevent using m_cursor
2506 // if the user code caught EVT_SET_CURSOR() and returned nothing from
2507 // it - this is a way to say that our cursor shouldn't be used for this
2508 // point
2509 if ( !processedEvtSetCursor && m_cursor.Ok() )
467e3168 2510 cursor = m_cursor ;
e15f0a5e
DS
2511
2512 if ( !wxIsBusy() && !GetParent() )
2513 cursor = *wxSTANDARD_CURSOR ;
467e3168 2514 }
e15f0a5e 2515
467e3168
SC
2516 if ( cursor.Ok() )
2517 cursor.MacInstall() ;
2518 }
e15f0a5e 2519
467e3168
SC
2520 return cursor.Ok() ;
2521}
2522
89954433 2523wxString wxWindowMac::MacGetToolTipString( wxPoint &WXUNUSED(pt) )
2f1ae414 2524{
5e0526df 2525#if wxUSE_TOOLTIPS
6264b550 2526 if ( m_tooltip )
6264b550 2527 return m_tooltip->GetTip() ;
5e0526df 2528#endif
e15f0a5e 2529
427ff662 2530 return wxEmptyString ;
2f1ae414 2531}
6264b550 2532
cb4b0966
SC
2533void wxWindowMac::ClearBackground()
2534{
2535 Refresh() ;
2536 Update() ;
2537}
2538
1c310985 2539void wxWindowMac::Update()
519cb848 2540{
5bcdf503
JS
2541 wxTopLevelWindowMac* top = MacGetTopLevelWindow();
2542 if (top)
2543 top->MacPerformUpdates() ;
519cb848
SC
2544}
2545
14c9cbdb 2546wxTopLevelWindowMac* wxWindowMac::MacGetTopLevelWindow() const
519cb848 2547{
1c310985 2548 wxTopLevelWindowMac* win = NULL ;
facd6764 2549 WindowRef window = (WindowRef) MacGetTopLevelWindowRef() ;
1c310985 2550 if ( window )
1c310985 2551 win = wxFindWinFromMacWindow( window ) ;
e15f0a5e 2552
1c310985 2553 return win ;
519cb848 2554}
5c840e5b 2555
902725ee 2556const wxRect& wxWindowMac::MacGetClippedClientRect() const
e905b636
SC
2557{
2558 MacUpdateClippedRects() ;
e15f0a5e 2559
e905b636
SC
2560 return m_cachedClippedClientRect ;
2561}
2562
902725ee 2563const wxRect& wxWindowMac::MacGetClippedRect() const
5c840e5b
SC
2564{
2565 MacUpdateClippedRects() ;
e15f0a5e 2566
5c840e5b
SC
2567 return m_cachedClippedRect ;
2568}
2569
902725ee 2570const wxRect&wxWindowMac:: MacGetClippedRectWithOuterStructure() const
5c840e5b
SC
2571{
2572 MacUpdateClippedRects() ;
e15f0a5e 2573
5c840e5b
SC
2574 return m_cachedClippedRectWithOuterStructure ;
2575}
2576
2577const wxRegion& wxWindowMac::MacGetVisibleRegion( bool includeOuterStructures )
94abc21f 2578{
5c840e5b 2579 static wxRegion emptyrgn ;
898d9035 2580
5c840e5b
SC
2581 if ( !m_isBeingDeleted && MacIsReallyShown() /*m_peer->IsVisible() */ )
2582 {
2583 MacUpdateClippedRects() ;
2584 if ( includeOuterStructures )
2585 return m_cachedClippedRegionWithOuterStructure ;
2586 else
2587 return m_cachedClippedRegion ;
2588 }
2589 else
2590 {
2591 return emptyrgn ;
2592 }
2593}
2594
2595void wxWindowMac::MacUpdateClippedRects() const
2596{
2597 if ( m_cachedClippedRectValid )
2598 return ;
2599
0fa8508d
SC
2600 // includeOuterStructures is true if we try to draw somthing like a focus ring etc.
2601 // also a window dc uses this, in this case we only clip in the hierarchy for hard
2602 // borders like a scrollwindow, splitter etc otherwise we end up in a paranoia having
2603 // to add focus borders everywhere
8b573fb8 2604
e15f0a5e 2605 Rect r, rIncludingOuterStructures ;
902725ee 2606
5c840e5b
SC
2607 m_peer->GetRect( &r ) ;
2608 r.left -= MacGetLeftBorderSize() ;
2609 r.top -= MacGetTopBorderSize() ;
2610 r.bottom += MacGetBottomBorderSize() ;
2611 r.right += MacGetRightBorderSize() ;
2612
2613 r.right -= r.left ;
2614 r.bottom -= r.top ;
2615 r.left = 0 ;
2616 r.top = 0 ;
2617
2618 rIncludingOuterStructures = r ;
2619 InsetRect( &rIncludingOuterStructures , -4 , -4 ) ;
902725ee 2620
e905b636
SC
2621 wxRect cl = GetClientRect() ;
2622 Rect rClient = { cl.y , cl.x , cl.y + cl.height , cl.x + cl.width } ;
902725ee 2623
e15f0a5e
DS
2624 int x , y ;
2625 wxSize size ;
e905b636
SC
2626 const wxWindow* child = this ;
2627 const wxWindow* parent = NULL ;
898d9035 2628
e15f0a5e 2629 while ( !child->IsTopLevel() && ( parent = child->GetParent() ) != NULL )
e40298d5 2630 {
e905b636 2631 if ( parent->MacIsChildOfClientArea(child) )
94abc21f 2632 {
e905b636
SC
2633 size = parent->GetClientSize() ;
2634 wxPoint origin = parent->GetClientAreaOrigin() ;
2635 x = origin.x ;
2636 y = origin.y ;
2637 }
2638 else
2639 {
2640 // this will be true for scrollbars, toolbars etc.
2641 size = parent->GetSize() ;
2642 y = parent->MacGetTopBorderSize() ;
2643 x = parent->MacGetLeftBorderSize() ;
2644 size.x -= parent->MacGetLeftBorderSize() + parent->MacGetRightBorderSize() ;
2645 size.y -= parent->MacGetTopBorderSize() + parent->MacGetBottomBorderSize() ;
2646 }
21f9e953 2647
e905b636
SC
2648 parent->MacWindowToRootWindow( &x, &y ) ;
2649 MacRootWindowToWindow( &x , &y ) ;
21f9e953 2650
e905b636 2651 Rect rparent = { y , x , y + size.y , x + size.x } ;
5c840e5b 2652
e905b636
SC
2653 // the wxwindow and client rects will always be clipped
2654 SectRect( &r , &rparent , &r ) ;
2655 SectRect( &rClient , &rparent , &rClient ) ;
5c840e5b 2656
e905b636
SC
2657 // the structure only at 'hard' borders
2658 if ( parent->MacClipChildren() ||
2659 ( parent->GetParent() && parent->GetParent()->MacClipGrandChildren() ) )
2660 {
2661 SectRect( &rIncludingOuterStructures , &rparent , &rIncludingOuterStructures ) ;
94abc21f 2662 }
e15f0a5e 2663
e905b636 2664 child = parent ;
e40298d5 2665 }
902725ee 2666
5c840e5b 2667 m_cachedClippedRect = wxRect( r.left , r.top , r.right - r.left , r.bottom - r.top ) ;
902725ee 2668 m_cachedClippedClientRect = wxRect( rClient.left , rClient.top ,
e905b636 2669 rClient.right - rClient.left , rClient.bottom - rClient.top ) ;
902725ee
WS
2670 m_cachedClippedRectWithOuterStructure = wxRect(
2671 rIncludingOuterStructures.left , rIncludingOuterStructures.top ,
2672 rIncludingOuterStructures.right - rIncludingOuterStructures.left ,
5c840e5b 2673 rIncludingOuterStructures.bottom - rIncludingOuterStructures.top ) ;
902725ee 2674
5c840e5b
SC
2675 m_cachedClippedRegionWithOuterStructure = wxRegion( m_cachedClippedRectWithOuterStructure ) ;
2676 m_cachedClippedRegion = wxRegion( m_cachedClippedRect ) ;
e905b636 2677 m_cachedClippedClientRegion = wxRegion( m_cachedClippedClientRect ) ;
902725ee 2678
5c840e5b 2679 m_cachedClippedRectValid = true ;
94abc21f
SC
2680}
2681
facd6764
SC
2682/*
2683 This function must not change the updatergn !
2684 */
8e181eae 2685bool wxWindowMac::MacDoRedraw( void* updatergnr , long time )
519cb848 2686{
facd6764 2687 bool handled = false ;
42ef83fa 2688 Rect updatebounds ;
e15f0a5e 2689 RgnHandle updatergn = (RgnHandle) updatergnr ;
42ef83fa 2690 GetRegionBounds( updatergn , &updatebounds ) ;
20b69855 2691
e15f0a5e 2692 // wxLogDebug(wxT("update for %s bounds %d, %d, %d, %d"), wxString(GetClassInfo()->GetClassName()).c_str(), updatebounds.left, updatebounds.top , updatebounds.right , updatebounds.bottom ) ;
c79aad8b 2693
902725ee 2694 if ( !EmptyRgn(updatergn) )
6264b550 2695 {
1c310985
SC
2696 RgnHandle newupdate = NewRgn() ;
2697 wxSize point = GetClientSize() ;
2698 wxPoint origin = GetClientAreaOrigin() ;
e15f0a5e 2699 SetRectRgn( newupdate , origin.x , origin.y , origin.x + point.x , origin.y + point.y ) ;
facd6764 2700 SectRgn( newupdate , updatergn , newupdate ) ;
8b573fb8 2701
eec462f8
SC
2702 // first send an erase event to the entire update area
2703 {
c79aad8b
SC
2704 // for the toplevel window this really is the entire area
2705 // for all the others only their client area, otherwise they
2706 // might be drawing with full alpha and eg put blue into
2707 // the grow-box area of a scrolled window (scroll sample)
5c840e5b 2708 wxDC* dc = new wxWindowDC(this);
c79aad8b 2709 if ( IsTopLevel() )
8e181eae 2710 dc->SetClippingRegion(wxRegion(HIShapeCreateWithQDRgn(updatergn)));
c79aad8b 2711 else
8e181eae 2712 dc->SetClippingRegion(wxRegion(HIShapeCreateWithQDRgn(newupdate)));
902725ee 2713
c79aad8b 2714 wxEraseEvent eevent( GetId(), dc );
42ef83fa
SC
2715 eevent.SetEventObject( this );
2716 GetEventHandler()->ProcessEvent( eevent );
c79aad8b 2717 delete dc ;
eec462f8 2718 }
8b573fb8 2719
6239ee05
SC
2720 MacPaintGrowBox();
2721
42ef83fa 2722 // calculate a client-origin version of the update rgn and set m_updateRegion to that
1c310985 2723 OffsetRgn( newupdate , -origin.x , -origin.y ) ;
8e181eae 2724 m_updateRegion = wxRegion(HIShapeCreateWithQDRgn(newupdate)) ;
8b573fb8 2725 DisposeRgn( newupdate ) ;
6ed71b4f 2726
1c310985 2727 if ( !m_updateRegion.Empty() )
6264b550 2728 {
facd6764 2729 // paint the window itself
ff3795ee 2730
e40298d5 2731 wxPaintEvent event;
687706f5 2732 event.SetTimestamp(time);
e40298d5 2733 event.SetEventObject(this);
ff3795ee
SC
2734 GetEventHandler()->ProcessEvent(event);
2735 handled = true ;
eec462f8 2736 }
8b573fb8 2737
eec462f8
SC
2738 // now we cannot rely on having its borders drawn by a window itself, as it does not
2739 // get the updateRgn wide enough to always do so, so we do it from the parent
2740 // this would also be the place to draw any custom backgrounds for native controls
2741 // in Composited windowing
36d7f54e 2742 wxPoint clientOrigin = GetClientAreaOrigin() ;
8b573fb8 2743
e15f0a5e
DS
2744 wxWindowMac *child;
2745 int x, y, w, h;
71f2fb52 2746 for (wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); node; node = node->GetNext())
eec462f8 2747 {
e15f0a5e
DS
2748 child = node->GetData();
2749 if (child == NULL)
2750 continue;
2751 if (child == m_vScrollBar)
2752 continue;
2753 if (child == m_hScrollBar)
2754 continue;
2755 if (child->IsTopLevel())
2756 continue;
2757 if (!child->IsShown())
2758 continue;
fe779e40 2759
c79aad8b
SC
2760 // only draw those in the update region (add a safety margin of 10 pixels for shadow effects
2761
af6b7b80 2762 child->GetPosition( &x, &y );
af6b7b80
SC
2763 child->GetSize( &w, &h );
2764 Rect childRect = { y , x , y + h , x + w } ;
36d7f54e 2765 OffsetRect( &childRect , clientOrigin.x , clientOrigin.y ) ;
c79aad8b
SC
2766 InsetRect( &childRect , -10 , -10) ;
2767
2768 if ( RectInRgn( &childRect , updatergn ) )
eec462f8 2769 {
c79aad8b
SC
2770 // paint custom borders
2771 wxNcPaintEvent eventNc( child->GetId() );
2772 eventNc.SetEventObject( child );
2773 if ( !child->GetEventHandler()->ProcessEvent( eventNc ) )
eec462f8 2774 {
4f74e0d1 2775 child->MacPaintBorders(0, 0) ;
eec462f8 2776 }
8b573fb8 2777 }
14c9cbdb 2778 }
6264b550 2779 }
e15f0a5e 2780
facd6764
SC
2781 return handled ;
2782}
6ed71b4f 2783
519cb848 2784
facd6764 2785WXWindow wxWindowMac::MacGetTopLevelWindowRef() const
519cb848 2786{
6264b550 2787 wxWindowMac *iter = (wxWindowMac*)this ;
14c9cbdb 2788
e15f0a5e 2789 while ( iter )
6264b550 2790 {
1c310985 2791 if ( iter->IsTopLevel() )
6239ee05
SC
2792 {
2793 wxTopLevelWindow* toplevel = wxDynamicCast(iter,wxTopLevelWindow);
2794 if ( toplevel )
2795 return toplevel->MacGetWindowRef();
2796#if wxUSE_POPUPWIN
2797 wxPopupWindow* popupwin = wxDynamicCast(iter,wxPopupWindow);
2798 if ( popupwin )
2799 return popupwin->MacGetPopupWindowRef();
2800#endif
2801 }
6264b550 2802 iter = iter->GetParent() ;
14c9cbdb 2803 }
e15f0a5e 2804
6264b550 2805 return NULL ;
519cb848
SC
2806}
2807
6239ee05
SC
2808bool wxWindowMac::MacHasScrollBarCorner() const
2809{
2810 /* Returns whether the scroll bars in a wxScrolledWindow should be
2811 * shortened. Scroll bars should be shortened if either:
2812 *
2813 * - both scroll bars are visible, or
2814 *
2815 * - there is a resize box in the parent frame's corner and this
2816 * window shares the bottom and right edge with the parent
2817 * frame.
2818 */
2819
2820 if ( m_hScrollBar == NULL && m_vScrollBar == NULL )
2821 return false;
2822
2823 if ( ( m_hScrollBar && m_hScrollBar->IsShown() )
2824 && ( m_vScrollBar && m_vScrollBar->IsShown() ) )
2825 {
2826 // Both scroll bars visible
2827 return true;
2828 }
2829 else
2830 {
2831 wxPoint thisWindowBottomRight = GetScreenRect().GetBottomRight();
2832
2833 for ( const wxWindow *win = this; win; win = win->GetParent() )
2834 {
2835 const wxFrame *frame = wxDynamicCast( win, wxFrame ) ;
2836 if ( frame )
2837 {
2838 if ( frame->GetWindowStyleFlag() & wxRESIZE_BORDER )
2839 {
2840 // Parent frame has resize handle
2841 wxPoint frameBottomRight = frame->GetScreenRect().GetBottomRight();
2842
2843 // Note: allow for some wiggle room here as wxMac's
2844 // window rect calculations seem to be imprecise
2845 if ( abs( thisWindowBottomRight.x - frameBottomRight.x ) <= 2
2846 && abs( thisWindowBottomRight.y - frameBottomRight.y ) <= 2 )
2847 {
2848 // Parent frame has resize handle and shares
2849 // right bottom corner
2850 return true ;
2851 }
2852 else
2853 {
2854 // Parent frame has resize handle but doesn't
2855 // share right bottom corner
2856 return false ;
2857 }
2858 }
2859 else
2860 {
2861 // Parent frame doesn't have resize handle
2862 return false ;
2863 }
2864 }
2865 }
2866
2867 // No parent frame found
2868 return false ;
2869 }
2870}
2871
14c9cbdb 2872void wxWindowMac::MacCreateScrollBars( long style )
519cb848 2873{
427ff662 2874 wxASSERT_MSG( m_vScrollBar == NULL && m_hScrollBar == NULL , wxT("attempt to create window twice") ) ;
14c9cbdb 2875
aa99e0cd
SC
2876 if ( style & ( wxVSCROLL | wxHSCROLL ) )
2877 {
db7a550b 2878 int scrlsize = MAC_SCROLLBAR_SIZE ;
8b573fb8
VZ
2879 if ( GetWindowVariant() == wxWINDOW_VARIANT_SMALL || GetWindowVariant() == wxWINDOW_VARIANT_MINI )
2880 {
2881 scrlsize = MAC_SMALL_SCROLLBAR_SIZE ;
8b573fb8 2882 }
db7a550b 2883
6239ee05 2884 int adjust = MacHasScrollBarCorner() ? scrlsize - 1: 0 ;
aa99e0cd
SC
2885 int width, height ;
2886 GetClientSize( &width , &height ) ;
2887
898d9035 2888 wxPoint vPoint(width - scrlsize, 0) ;
db7a550b 2889 wxSize vSize(scrlsize, height - adjust) ;
fbc1d11b
DS
2890 wxPoint hPoint(0, height - scrlsize) ;
2891 wxSize hSize(width - adjust, scrlsize) ;
aa99e0cd 2892
6239ee05 2893 // we have to set the min size to a smaller value, otherwise they cannot get smaller (InitialSize sets MinSize)
aa99e0cd 2894 if ( style & wxVSCROLL )
6239ee05
SC
2895 {
2896 m_vScrollBar = new wxScrollBar((wxWindow*)this, wxID_ANY, vPoint, vSize , wxVERTICAL);
2897 m_vScrollBar->SetMinSize( wxDefaultSize );
2898 }
aa99e0cd
SC
2899
2900 if ( style & wxHSCROLL )
6239ee05
SC
2901 {
2902 m_hScrollBar = new wxScrollBar((wxWindow*)this, wxID_ANY, hPoint, hSize , wxHORIZONTAL);
2903 m_hScrollBar->SetMinSize( wxDefaultSize );
2904 }
aa99e0cd 2905 }
aa99e0cd 2906
6264b550 2907 // because the create does not take into account the client area origin
e15f0a5e
DS
2908 // we might have a real position shift
2909 MacRepositionScrollBars() ;
519cb848
SC
2910}
2911
e905b636
SC
2912bool wxWindowMac::MacIsChildOfClientArea( const wxWindow* child ) const
2913{
fbc1d11b
DS
2914 bool result = ((child == NULL) || ((child != m_hScrollBar) && (child != m_vScrollBar)));
2915
2916 return result ;
e905b636
SC
2917}
2918
e766c8a9 2919void wxWindowMac::MacRepositionScrollBars()
519cb848 2920{
aa99e0cd
SC
2921 if ( !m_hScrollBar && !m_vScrollBar )
2922 return ;
8b573fb8 2923
db7a550b 2924 int scrlsize = m_hScrollBar ? m_hScrollBar->GetSize().y : ( m_vScrollBar ? m_vScrollBar->GetSize().x : MAC_SCROLLBAR_SIZE ) ;
6239ee05 2925 int adjust = MacHasScrollBarCorner() ? scrlsize - 1 : 0 ;
14c9cbdb 2926
6264b550 2927 // get real client area
e15f0a5e
DS
2928 int width, height ;
2929 GetSize( &width , &height );
6264b550
RR
2930
2931 width -= MacGetLeftBorderSize() + MacGetRightBorderSize();
2932 height -= MacGetTopBorderSize() + MacGetBottomBorderSize();
14c9cbdb 2933
e15f0a5e
DS
2934 wxPoint vPoint( width - scrlsize, 0 ) ;
2935 wxSize vSize( scrlsize, height - adjust ) ;
2936 wxPoint hPoint( 0 , height - scrlsize ) ;
2937 wxSize hSize( width - adjust, scrlsize ) ;
2938
2939#if 0
2940 int x = 0, y = 0, w, h ;
facd6764 2941 GetSize( &w , &h ) ;
14c9cbdb 2942
6264b550
RR
2943 MacClientToRootWindow( &x , &y ) ;
2944 MacClientToRootWindow( &w , &h ) ;
14c9cbdb 2945
6264b550 2946 wxWindowMac *iter = (wxWindowMac*)this ;
14c9cbdb 2947
6264b550 2948 int totW = 10000 , totH = 10000;
e15f0a5e 2949 while ( iter )
6264b550 2950 {
1c310985 2951 if ( iter->IsTopLevel() )
6264b550 2952 {
facd6764 2953 iter->GetSize( &totW , &totH ) ;
6264b550
RR
2954 break ;
2955 }
2956
2957 iter = iter->GetParent() ;
14c9cbdb
RD
2958 }
2959
6264b550
RR
2960 if ( x == 0 )
2961 {
2962 hPoint.x = -1 ;
2963 hSize.x += 1 ;
2964 }
2965 if ( y == 0 )
2966 {
2967 vPoint.y = -1 ;
2968 vSize.y += 1 ;
2969 }
14c9cbdb 2970
e15f0a5e 2971 if ( w - x >= totW )
6264b550
RR
2972 {
2973 hSize.x += 1 ;
2974 vPoint.x += 1 ;
2975 }
e15f0a5e 2976 if ( h - y >= totH )
6264b550
RR
2977 {
2978 vSize.y += 1 ;
2979 hPoint.y += 1 ;
2980 }
e15f0a5e
DS
2981#endif
2982
6264b550 2983 if ( m_vScrollBar )
e15f0a5e 2984 m_vScrollBar->SetSize( vPoint.x , vPoint.y, vSize.x, vSize.y , wxSIZE_ALLOW_MINUS_ONE );
6264b550 2985 if ( m_hScrollBar )
e15f0a5e 2986 m_hScrollBar->SetSize( hPoint.x , hPoint.y, hSize.x, hSize.y, wxSIZE_ALLOW_MINUS_ONE );
519cb848
SC
2987}
2988
e766c8a9 2989bool wxWindowMac::AcceptsFocus() const
7c551d95
SC
2990{
2991 return MacCanFocus() && wxWindowBase::AcceptsFocus();
2992}
519cb848 2993
14c9cbdb 2994void wxWindowMac::MacSuperChangedPosition()
519cb848 2995{
6264b550 2996 // only window-absolute structures have to be moved i.e. controls
519cb848 2997
e15f0a5e
DS
2998 m_cachedClippedRectValid = false ;
2999
3000 wxWindowMac *child;
71f2fb52 3001 wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
6264b550
RR
3002 while ( node )
3003 {
e15f0a5e 3004 child = node->GetData();
6264b550 3005 child->MacSuperChangedPosition() ;
e15f0a5e 3006
eb22f2a6 3007 node = node->GetNext();
6264b550 3008 }
519cb848 3009}
519cb848 3010
14c9cbdb 3011void wxWindowMac::MacTopLevelWindowChangedPosition()
a3bf4a62 3012{
6264b550 3013 // only screen-absolute structures have to be moved i.e. glcanvas
a3bf4a62 3014
e15f0a5e 3015 wxWindowMac *child;
71f2fb52 3016 wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
6264b550
RR
3017 while ( node )
3018 {
e15f0a5e 3019 child = node->GetData();
6264b550 3020 child->MacTopLevelWindowChangedPosition() ;
e15f0a5e 3021
eb22f2a6 3022 node = node->GetNext();
6264b550 3023 }
a3bf4a62 3024}
facd6764 3025
e15f0a5e 3026long wxWindowMac::MacGetLeftBorderSize() const
2f1ae414 3027{
e15f0a5e 3028 if ( IsTopLevel() )
6264b550 3029 return 0 ;
2f1ae414 3030
8f39b6c4 3031 SInt32 border = 0 ;
902725ee 3032
e15f0a5e 3033 if (HasFlag(wxRAISED_BORDER) || HasFlag( wxSUNKEN_BORDER) || HasFlag(wxDOUBLE_BORDER))
2f1ae414 3034 {
fbc1d11b 3035 // this metric is only the 'outset' outside the simple frame rect
8f39b6c4 3036 GetThemeMetric( kThemeMetricEditTextFrameOutset , &border ) ;
fbc1d11b 3037 border += 1 ;
2f1ae414 3038 }
8f39b6c4 3039 else if (HasFlag(wxSIMPLE_BORDER))
2f1ae414 3040 {
fbc1d11b 3041 // this metric is only the 'outset' outside the simple frame rect
8f39b6c4 3042 GetThemeMetric( kThemeMetricListBoxFrameOutset , &border ) ;
fbc1d11b 3043 border += 1 ;
2f1ae414 3044 }
e15f0a5e 3045
8f39b6c4 3046 return border ;
2f1ae414
SC
3047}
3048
e15f0a5e 3049long wxWindowMac::MacGetRightBorderSize() const
5b781a67 3050{
1c310985
SC
3051 // they are all symmetric in mac themes
3052 return MacGetLeftBorderSize() ;
5b781a67
SC
3053}
3054
e15f0a5e 3055long wxWindowMac::MacGetTopBorderSize() const
5b781a67 3056{
1c310985
SC
3057 // they are all symmetric in mac themes
3058 return MacGetLeftBorderSize() ;
5b781a67
SC
3059}
3060
e15f0a5e 3061long wxWindowMac::MacGetBottomBorderSize() const
5b781a67 3062{
1c310985
SC
3063 // they are all symmetric in mac themes
3064 return MacGetLeftBorderSize() ;
5b781a67
SC
3065}
3066
14c9cbdb 3067long wxWindowMac::MacRemoveBordersFromStyle( long style )
2f1ae414 3068{
055a486b 3069 return style & ~wxBORDER_MASK ;
2f1ae414 3070}
0a67a93b 3071
e766c8a9 3072// Find the wxWindowMac at the current mouse position, returning the mouse
3723b7b1 3073// position.
e15f0a5e 3074wxWindowMac * wxFindWindowAtPointer( wxPoint& pt )
3723b7b1 3075{
59a12e90 3076 pt = wxGetMousePosition();
e766c8a9 3077 wxWindowMac* found = wxFindWindowAtPoint(pt);
e15f0a5e 3078
59a12e90 3079 return found;
3723b7b1
JS
3080}
3081
3082// Get the current mouse position.
3083wxPoint wxGetMousePosition()
3084{
57591e0e 3085 int x, y;
e15f0a5e
DS
3086
3087 wxGetMousePosition( &x, &y );
3088
57591e0e 3089 return wxPoint(x, y);
3723b7b1
JS
3090}
3091
6ed71b4f 3092void wxWindowMac::OnMouseEvent( wxMouseEvent &event )
8950f7cc 3093{
8b573fb8
VZ
3094 if ( event.GetEventType() == wxEVT_RIGHT_DOWN )
3095 {
3096 // copied from wxGTK : CS
fe224552
VZ
3097 // VZ: shouldn't we move this to base class then?
3098
249aad30 3099 // generate a "context menu" event: this is similar to wxEVT_RIGHT_DOWN
8950f7cc
SC
3100 // except that:
3101 //
3102 // (a) it's a command event and so is propagated to the parent
3103 // (b) under MSW it can be generated from kbd too
3104 // (c) it uses screen coords (because of (a))
3105 wxContextMenuEvent evtCtx(wxEVT_CONTEXT_MENU,
3106 this->GetId(),
3107 this->ClientToScreen(event.GetPosition()));
249aad30
SC
3108 if ( ! GetEventHandler()->ProcessEvent(evtCtx) )
3109 event.Skip() ;
8b573fb8 3110 }
facd6764
SC
3111 else
3112 {
8b573fb8 3113 event.Skip() ;
facd6764 3114 }
8950f7cc
SC
3115}
3116
89954433 3117void wxWindowMac::OnPaint( wxPaintEvent & WXUNUSED(event) )
ff3795ee 3118{
4488a1d3
VZ
3119 if ( wxTheApp->MacGetCurrentEvent() != NULL && wxTheApp->MacGetCurrentEventHandlerCallRef() != NULL
3120 && GetBackgroundStyle() != wxBG_STYLE_TRANSPARENT )
e15f0a5e
DS
3121 CallNextEventHandler(
3122 (EventHandlerCallRef)wxTheApp->MacGetCurrentEventHandlerCallRef() ,
3123 (EventRef) wxTheApp->MacGetCurrentEvent() ) ;
ff3795ee
SC
3124}
3125
89954433
VZ
3126void wxWindowMac::MacHandleControlClick(WXWidget WXUNUSED(control),
3127 wxInt16 WXUNUSED(controlpart),
3128 bool WXUNUSED(mouseStillDown))
facd6764 3129{
facd6764
SC
3130}
3131
8b573fb8 3132Rect wxMacGetBoundsForControl( wxWindow* window , const wxPoint& pos , const wxSize &size , bool adjustForOrigin )
3083eb85 3133{
e15f0a5e 3134 int x, y, w, h ;
8b573fb8 3135
58603178
DS
3136 window->MacGetBoundsForControl( pos , size , x , y, w, h , adjustForOrigin ) ;
3137 Rect bounds = { y, x, y + h, x + w };
e15f0a5e 3138
3083eb85
SC
3139 return bounds ;
3140}
3141
8b573fb8 3142wxInt32 wxWindowMac::MacControlHit(WXEVENTHANDLERREF WXUNUSED(handler) , WXEVENTREF WXUNUSED(event) )
f1d527c1
SC
3143{
3144 return eventNotHandledErr ;
3145}
3146
50779e06
JS
3147bool wxWindowMac::Reparent(wxWindowBase *newParentBase)
3148{
3149 wxWindowMac *newParent = (wxWindowMac *)newParentBase;
50779e06 3150 if ( !wxWindowBase::Reparent(newParent) )
3dee36ae
WS
3151 return false;
3152
e15f0a5e 3153 // copied from MacPostControlCreate
50779e06 3154 ControlRef container = (ControlRef) GetParent()->GetHandle() ;
e15f0a5e 3155
50779e06 3156 wxASSERT_MSG( container != NULL , wxT("No valid mac container control") ) ;
e15f0a5e 3157
50779e06 3158 ::EmbedControl( m_peer->GetControlRef() , container ) ;
facd6764 3159
3dee36ae
WS
3160 return true;
3161}
a9b456ff
SC
3162
3163bool wxWindowMac::SetTransparent(wxByte alpha)
3164{
4488a1d3
VZ
3165 SetBackgroundStyle(wxBG_STYLE_TRANSPARENT);
3166
a9b456ff
SC
3167 if ( alpha != m_macAlpha )
3168 {
3169 m_macAlpha = alpha ;
3170 Refresh() ;
3171 }
3172 return true ;
a9b456ff
SC
3173}
3174
3175
3176bool wxWindowMac::CanSetTransparent()
3177{
a9b456ff 3178 return true ;
a9b456ff
SC
3179}
3180
89954433 3181wxByte wxWindowMac::GetTransparent() const
a9b456ff
SC
3182{
3183 return m_macAlpha ;
8444b6cb 3184}