]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/window.cpp
unload msimg32.dll earlier (before static cleanup time) to avoid lockups when wx...
[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 ;
898d9035 2044
be346c26 2045#if TARGET_API_MAC_OSX
a01d9a25 2046 if ( !m_backgroundColour.Ok() || GetBackgroundStyle() == wxBG_STYLE_TRANSPARENT )
94abc21f 2047 {
facd6764 2048 event.Skip() ;
94abc21f
SC
2049 }
2050 else
be346c26 2051#endif
7ebf5540 2052 {
8b573fb8 2053 event.GetDC()->Clear() ;
7ebf5540 2054 }
1c310985
SC
2055}
2056
2057void wxWindowMac::OnNcPaint( wxNcPaintEvent& event )
2058{
af6b7b80 2059 event.Skip() ;
e9576ca5
SC
2060}
2061
e766c8a9 2062int wxWindowMac::GetScrollPos(int orient) const
e9576ca5 2063{
1c310985
SC
2064 if ( orient == wxHORIZONTAL )
2065 {
2066 if ( m_hScrollBar )
2067 return m_hScrollBar->GetThumbPosition() ;
2068 }
2069 else
2070 {
2071 if ( m_vScrollBar )
2072 return m_vScrollBar->GetThumbPosition() ;
2073 }
e15f0a5e 2074
e9576ca5
SC
2075 return 0;
2076}
2077
2078// This now returns the whole range, not just the number
2079// of positions that we can scroll.
e766c8a9 2080int wxWindowMac::GetScrollRange(int orient) const
e9576ca5 2081{
1c310985
SC
2082 if ( orient == wxHORIZONTAL )
2083 {
2084 if ( m_hScrollBar )
2085 return m_hScrollBar->GetRange() ;
2086 }
2087 else
2088 {
2089 if ( m_vScrollBar )
2090 return m_vScrollBar->GetRange() ;
2091 }
e15f0a5e 2092
e9576ca5
SC
2093 return 0;
2094}
2095
e766c8a9 2096int wxWindowMac::GetScrollThumb(int orient) const
e9576ca5 2097{
1c310985
SC
2098 if ( orient == wxHORIZONTAL )
2099 {
2100 if ( m_hScrollBar )
2101 return m_hScrollBar->GetThumbSize() ;
2102 }
2103 else
2104 {
2105 if ( m_vScrollBar )
2106 return m_vScrollBar->GetThumbSize() ;
2107 }
e15f0a5e 2108
e9576ca5
SC
2109 return 0;
2110}
2111
89954433 2112void wxWindowMac::SetScrollPos(int orient, int pos, bool WXUNUSED(refresh))
e9576ca5 2113{
1c310985 2114 if ( orient == wxHORIZONTAL )
6264b550 2115 {
1c310985
SC
2116 if ( m_hScrollBar )
2117 m_hScrollBar->SetThumbPosition( pos ) ;
6264b550
RR
2118 }
2119 else
2120 {
1c310985
SC
2121 if ( m_vScrollBar )
2122 m_vScrollBar->SetThumbPosition( pos ) ;
6264b550 2123 }
2f1ae414
SC
2124}
2125
c1142003
VZ
2126void
2127wxWindowMac::AlwaysShowScrollbars(bool hflag, bool vflag)
2128{
2129 bool needVisibilityUpdate = false;
2130
2131 if ( m_hScrollBarAlwaysShown != hflag )
2132 {
2133 m_hScrollBarAlwaysShown = hflag;
2134 needVisibilityUpdate = true;
2135 }
2136
2137 if ( m_vScrollBarAlwaysShown != vflag )
2138 {
2139 m_vScrollBarAlwaysShown = vflag;
2140 needVisibilityUpdate = true;
2141 }
2142
2143 if ( needVisibilityUpdate )
2144 DoUpdateScrollbarVisibility();
2145}
6239ee05 2146
c79aad8b
SC
2147//
2148// we draw borders and grow boxes, are already set up and clipped in the current port / cgContextRef
2149// our own window origin is at leftOrigin/rightOrigin
2150//
2151
6239ee05
SC
2152void wxWindowMac::MacPaintGrowBox()
2153{
2154 if ( IsTopLevel() )
2155 return ;
2156
6239ee05
SC
2157 if ( MacHasScrollBarCorner() )
2158 {
2159 Rect rect ;
2160
2161 CGContextRef cgContext = (CGContextRef) MacGetCGContextRef() ;
2162 wxASSERT( cgContext ) ;
2163
2164 m_peer->GetRect( &rect ) ;
2165
2166 int size = m_hScrollBar ? m_hScrollBar->GetSize().y : ( m_vScrollBar ? m_vScrollBar->GetSize().x : MAC_SCROLLBAR_SIZE ) ;
2167 CGRect cgrect = CGRectMake( rect.right - size , rect.bottom - size , size , size ) ;
2168 CGPoint cgpoint = CGPointMake( rect.right - size , rect.bottom - size ) ;
2169 CGContextSaveGState( cgContext );
2170
a01d9a25 2171 if ( m_backgroundColour.Ok() )
6239ee05 2172 {
a01d9a25 2173 CGContextSetFillColorWithColor( cgContext, m_backgroundColour.GetCGColor() );
6239ee05
SC
2174 }
2175 else
2176 {
2177 CGContextSetRGBFillColor( cgContext, 1.0, 1.0 , 1.0 , 1.0 );
2178 }
2179 CGContextFillRect( cgContext, cgrect );
2180 CGContextRestoreGState( cgContext );
2181 }
6239ee05
SC
2182}
2183
89954433 2184void wxWindowMac::MacPaintBorders( int WXUNUSED(leftOrigin) , int WXUNUSED(rightOrigin) )
2f1ae414 2185{
e15f0a5e 2186 if ( IsTopLevel() )
6264b550 2187 return ;
8b573fb8 2188
fd926bcc 2189 Rect rect ;
c79aad8b 2190 bool hasFocus = m_peer->NeedsFocusRect() && m_peer->HasFocus() ;
c79aad8b 2191
8f39b6c4 2192 // back to the surrounding frame rectangle
58603178 2193 m_peer->GetRect( &rect ) ;
8f39b6c4 2194 InsetRect( &rect, -1 , -1 ) ;
fd926bcc 2195
c79aad8b 2196 {
8f39b6c4
SC
2197 CGRect cgrect = CGRectMake( rect.left , rect.top , rect.right - rect.left ,
2198 rect.bottom - rect.top ) ;
2199
c79aad8b 2200 HIThemeFrameDrawInfo info ;
58603178 2201 memset( &info, 0 , sizeof(info) ) ;
902725ee 2202
c79aad8b
SC
2203 info.version = 0 ;
2204 info.kind = 0 ;
2205 info.state = IsEnabled() ? kThemeStateActive : kThemeStateInactive ;
2206 info.isFocused = hasFocus ;
c79aad8b
SC
2207
2208 CGContextRef cgContext = (CGContextRef) GetParent()->MacGetCGContextRef() ;
2209 wxASSERT( cgContext ) ;
902725ee 2210
e15f0a5e 2211 if ( HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER) || HasFlag(wxDOUBLE_BORDER) )
c79aad8b 2212 {
c79aad8b 2213 info.kind = kHIThemeFrameTextFieldSquare ;
8f39b6c4 2214 HIThemeDrawFrame( &cgrect , &info , cgContext , kHIThemeOrientationNormal ) ;
c79aad8b 2215 }
e15f0a5e 2216 else if ( HasFlag(wxSIMPLE_BORDER) )
c79aad8b 2217 {
c79aad8b 2218 info.kind = kHIThemeFrameListBox ;
c79aad8b
SC
2219 HIThemeDrawFrame( &cgrect , &info , cgContext , kHIThemeOrientationNormal ) ;
2220 }
2221 else if ( hasFocus )
2222 {
c79aad8b
SC
2223 HIThemeDrawFocusRect( &cgrect , true , cgContext , kHIThemeOrientationNormal ) ;
2224 }
6239ee05 2225#if 0 // TODO REMOVE now done in a separate call earlier in drawing the window itself
c79aad8b 2226 m_peer->GetRect( &rect ) ;
6239ee05 2227 if ( MacHasScrollBarCorner() )
c79aad8b 2228 {
6239ee05
SC
2229 int variant = (m_hScrollBar == NULL ? m_vScrollBar : m_hScrollBar ) ->GetWindowVariant();
2230 int size = m_hScrollBar ? m_hScrollBar->GetSize().y : ( m_vScrollBar ? m_vScrollBar->GetSize().x : MAC_SCROLLBAR_SIZE ) ;
8f39b6c4
SC
2231 CGRect cgrect = CGRectMake( rect.right - size , rect.bottom - size , size , size ) ;
2232 CGPoint cgpoint = CGPointMake( rect.right - size , rect.bottom - size ) ;
902725ee 2233 HIThemeGrowBoxDrawInfo info ;
e15f0a5e 2234 memset( &info, 0, sizeof(info) ) ;
c79aad8b
SC
2235 info.version = 0 ;
2236 info.state = IsEnabled() ? kThemeStateActive : kThemeStateInactive ;
2237 info.kind = kHIThemeGrowBoxKindNone ;
6239ee05 2238 // contrary to the docs ...SizeSmall does not work
c79aad8b 2239 info.size = kHIThemeGrowBoxSizeNormal ;
6239ee05 2240 info.direction = 0 ;
c79aad8b
SC
2241 HIThemeDrawGrowBox( &cgpoint , &info , cgContext , kHIThemeOrientationNormal ) ;
2242 }
6239ee05 2243#endif
c79aad8b 2244 }
8208e181
SC
2245}
2246
abda5788
SC
2247void wxWindowMac::RemoveChild( wxWindowBase *child )
2248{
2249 if ( child == m_hScrollBar )
2250 m_hScrollBar = NULL ;
2251 if ( child == m_vScrollBar )
2252 m_vScrollBar = NULL ;
14c9cbdb 2253
abda5788
SC
2254 wxWindowBase::RemoveChild( child ) ;
2255}
2256
c1142003 2257void wxWindowMac::DoUpdateScrollbarVisibility()
e9576ca5 2258{
42cc0b31 2259 bool triggerSizeEvent = false;
58603178 2260
c1142003 2261 if ( m_hScrollBar )
e40298d5 2262 {
c1142003 2263 bool showHScrollBar = m_hScrollBarAlwaysShown || m_hScrollBar->IsNeeded();
e15f0a5e 2264
c1142003
VZ
2265 if ( m_hScrollBar->IsShown() != showHScrollBar )
2266 {
2267 m_hScrollBar->Show( showHScrollBar );
2268 triggerSizeEvent = true;
6264b550 2269 }
e40298d5 2270 }
c1142003
VZ
2271
2272 if ( m_vScrollBar)
e40298d5 2273 {
c1142003 2274 bool showVScrollBar = m_vScrollBarAlwaysShown || m_vScrollBar->IsNeeded();
e15f0a5e 2275
c1142003
VZ
2276 if ( m_vScrollBar->IsShown() != showVScrollBar )
2277 {
2278 m_vScrollBar->Show( showVScrollBar ) ;
2279 triggerSizeEvent = true;
6264b550 2280 }
e40298d5 2281 }
e15f0a5e 2282
e40298d5 2283 MacRepositionScrollBars() ;
42cc0b31
SC
2284 if ( triggerSizeEvent )
2285 {
2286 wxSizeEvent event(GetSize(), m_windowId);
2287 event.SetEventObject(this);
2288 GetEventHandler()->ProcessEvent(event);
2289 }
e9576ca5
SC
2290}
2291
c1142003
VZ
2292// New function that will replace some of the above.
2293void wxWindowMac::SetScrollbar(int orient, int pos, int thumb,
2294 int range, bool refresh)
2295{
2296 if ( orient == wxHORIZONTAL && m_hScrollBar )
2297 m_hScrollBar->SetScrollbar(pos, thumb, range, thumb, refresh);
2298 else if ( orient == wxVERTICAL && m_vScrollBar )
2299 m_vScrollBar->SetScrollbar(pos, thumb, range, thumb, refresh);
2300
2301 DoUpdateScrollbarVisibility();
2302}
2303
e9576ca5 2304// Does a physical scroll
e766c8a9 2305void wxWindowMac::ScrollWindow(int dx, int dy, const wxRect *rect)
e9576ca5 2306{
898d9035 2307 if ( dx == 0 && dy == 0 )
ba87f54c 2308 return ;
8b573fb8 2309
3dee36ae
WS
2310 int width , height ;
2311 GetClientSize( &width , &height ) ;
e15f0a5e 2312
902725ee 2313 {
002c9672 2314 // note there currently is a bug in OSX which makes inefficient refreshes in case an entire control
8b573fb8 2315 // area is scrolled, this does not occur if width and height are 2 pixels less,
58603178 2316 // TODO: write optimal workaround
898d9035 2317 wxRect scrollrect( MacGetLeftBorderSize() , MacGetTopBorderSize() , width , height ) ;
8b573fb8 2318 if ( rect )
5ca0d812 2319 scrollrect.Intersect( *rect ) ;
e15f0a5e 2320
5ca0d812 2321 if ( m_peer->GetNeedsDisplay() )
002c9672 2322 {
58603178 2323 // because HIViewScrollRect does not scroll the already invalidated area we have two options:
8dd37b03 2324 // in case there is already a pending redraw on that area
002c9672
SC
2325 // either immediate redraw or full invalidate
2326#if 1
2327 // is the better overall solution, as it does not slow down scrolling
1f1c8bd4 2328 m_peer->SetNeedsDisplay() ;
002c9672 2329#else
8b573fb8 2330 // this would be the preferred version for fast drawing controls
80f3f3be 2331 HIViewRender(m_peer->GetControlRef()) ;
002c9672
SC
2332#endif
2333 }
e15f0a5e 2334
84e5d27d
SC
2335 // as the native control might be not a 0/0 wx window coordinates, we have to offset
2336 scrollrect.Offset( -MacGetLeftBorderSize() , -MacGetTopBorderSize() ) ;
898d9035 2337 m_peer->ScrollRect( &scrollrect , dx , dy ) ;
92346151 2338
92346151 2339#if 0
902725ee 2340 // this would be the preferred version for fast drawing controls
4f74e0d1 2341 HIViewRender(m_peer->GetControlRef()) ;
92346151 2342#endif
902725ee 2343 }
6ed71b4f 2344
e15f0a5e
DS
2345 wxWindowMac *child;
2346 int x, y, w, h;
71f2fb52 2347 for (wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); node; node = node->GetNext())
6264b550 2348 {
e15f0a5e
DS
2349 child = node->GetData();
2350 if (child == NULL)
2351 continue;
2352 if (child == m_vScrollBar)
2353 continue;
2354 if (child == m_hScrollBar)
2355 continue;
2356 if (child->IsTopLevel())
2357 continue;
6ed71b4f 2358
6264b550 2359 child->GetPosition( &x, &y );
6264b550 2360 child->GetSize( &w, &h );
00f55394
SC
2361 if (rect)
2362 {
e15f0a5e
DS
2363 wxRect rc( x, y, w, h );
2364 if (rect->Intersects( rc ))
8d1547ef 2365 child->SetSize( x + dx, y + dy, w, h, wxSIZE_AUTO|wxSIZE_ALLOW_MINUS_ONE );
00f55394
SC
2366 }
2367 else
2368 {
8d1547ef 2369 child->SetSize( x + dx, y + dy, w, h, wxSIZE_AUTO|wxSIZE_ALLOW_MINUS_ONE );
8b573fb8 2370 }
6264b550 2371 }
e9576ca5
SC
2372}
2373
e15f0a5e 2374void wxWindowMac::MacOnScroll( wxScrollEvent &event )
7c74e7fe 2375{
687706f5 2376 if ( event.GetEventObject() == m_vScrollBar || event.GetEventObject() == m_hScrollBar )
6264b550
RR
2377 {
2378 wxScrollWinEvent wevent;
2379 wevent.SetPosition(event.GetPosition());
2380 wevent.SetOrientation(event.GetOrientation());
687706f5
KH
2381 wevent.SetEventObject(this);
2382
2383 if (event.GetEventType() == wxEVT_SCROLL_TOP)
2384 wevent.SetEventType( wxEVT_SCROLLWIN_TOP );
2385 else if (event.GetEventType() == wxEVT_SCROLL_BOTTOM)
2386 wevent.SetEventType( wxEVT_SCROLLWIN_BOTTOM );
2387 else if (event.GetEventType() == wxEVT_SCROLL_LINEUP)
2388 wevent.SetEventType( wxEVT_SCROLLWIN_LINEUP );
2389 else if (event.GetEventType() == wxEVT_SCROLL_LINEDOWN)
2390 wevent.SetEventType( wxEVT_SCROLLWIN_LINEDOWN );
2391 else if (event.GetEventType() == wxEVT_SCROLL_PAGEUP)
2392 wevent.SetEventType( wxEVT_SCROLLWIN_PAGEUP );
2393 else if (event.GetEventType() == wxEVT_SCROLL_PAGEDOWN)
2394 wevent.SetEventType( wxEVT_SCROLLWIN_PAGEDOWN );
2395 else if (event.GetEventType() == wxEVT_SCROLL_THUMBTRACK)
2396 wevent.SetEventType( wxEVT_SCROLLWIN_THUMBTRACK );
2397 else if (event.GetEventType() == wxEVT_SCROLL_THUMBRELEASE)
2398 wevent.SetEventType( wxEVT_SCROLLWIN_THUMBRELEASE );
6ed71b4f
VZ
2399
2400 GetEventHandler()->ProcessEvent(wevent);
7c74e7fe
SC
2401 }
2402}
2403
e9576ca5 2404// Get the window with the focus
0fe02759 2405wxWindowMac *wxWindowBase::DoFindFocus()
e9576ca5 2406{
f1d527c1
SC
2407 ControlRef control ;
2408 GetKeyboardFocus( GetUserFocusWindow() , &control ) ;
2409 return wxFindControlFromMacControl( control ) ;
519cb848
SC
2410}
2411
e15f0a5e 2412void wxWindowMac::OnSetFocus( wxFocusEvent& event )
7810c95b
SC
2413{
2414 // panel wants to track the window which was the last to have focus in it,
2415 // so we want to set ourselves as the window which last had focus
2416 //
dac390e9 2417 // notice that it's also important to do it upwards the tree because
7810c95b
SC
2418 // otherwise when the top level panel gets focus, it won't set it back to
2419 // us, but to some other sibling
6ed71b4f 2420
dac390e9 2421 // CS: don't know if this is still needed:
c1fb8167
SC
2422 //wxChildFocusEvent eventFocus(this);
2423 //(void)GetEventHandler()->ProcessEvent(eventFocus);
7810c95b 2424
5ca0d812
SC
2425 if ( MacGetTopLevelWindow() && m_peer->NeedsFocusRect() )
2426 {
dac390e9 2427 GetParent()->Refresh() ;
788e118f 2428 wxMacWindowStateSaver sv( this ) ;
6449b3a8 2429 Rect rect ;
dac390e9 2430
6449b3a8 2431 m_peer->GetRect( &rect ) ;
6239ee05 2432 // auf den umgebenden Rahmen zurチᅡ゚ck
8f39b6c4 2433 InsetRect( &rect, -1 , -1 ) ;
1f1c8bd4 2434
6449b3a8 2435 wxTopLevelWindowMac* top = MacGetTopLevelWindow();
dac390e9 2436 if ( top )
6449b3a8 2437 {
898d9035 2438 wxPoint pt(0, 0) ;
6449b3a8
SC
2439 wxMacControl::Convert( &pt , GetParent()->m_peer , top->m_peer ) ;
2440 rect.left += pt.x ;
2441 rect.right += pt.x ;
2442 rect.top += pt.y ;
2443 rect.bottom += pt.y ;
2444 }
5ca0d812 2445
fbc1d11b 2446 bool bIsFocusEvent = (event.GetEventType() == wxEVT_SET_FOCUS);
c394a432 2447 DrawThemeFocusRect( &rect , bIsFocusEvent ) ;
dac390e9 2448 if ( !bIsFocusEvent )
af6b7b80 2449 {
af6b7b80 2450 // as this erases part of the frame we have to redraw borders
101634b2
SC
2451 // and because our z-ordering is not always correct (staticboxes)
2452 // we have to invalidate things, we cannot simple redraw
6449b3a8 2453 MacInvalidateBorders() ;
af6b7b80 2454 }
5ca0d812
SC
2455 }
2456
7810c95b
SC
2457 event.Skip();
2458}
2459
e39af974 2460void wxWindowMac::OnInternalIdle()
e9576ca5 2461{
e9576ca5
SC
2462 // This calls the UI-update mechanism (querying windows for
2463 // menu/toolbar/control state information)
6239ee05 2464 if (wxUpdateUIEvent::CanUpdate(this) && IsShown())
e39af974 2465 UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
e9576ca5
SC
2466}
2467
2468// Raise the window to the top of the Z order
e766c8a9 2469void wxWindowMac::Raise()
e9576ca5 2470{
5ca0d812 2471 m_peer->SetZOrder( true , NULL ) ;
e9576ca5
SC
2472}
2473
2474// Lower the window to the bottom of the Z order
e766c8a9 2475void wxWindowMac::Lower()
e9576ca5 2476{
5ca0d812 2477 m_peer->SetZOrder( false , NULL ) ;
e9576ca5
SC
2478}
2479
facd6764 2480// static wxWindow *gs_lastWhich = NULL;
519cb848 2481
e15f0a5e 2482bool wxWindowMac::MacSetupCursor( const wxPoint& pt )
467e3168
SC
2483{
2484 // first trigger a set cursor event
6ed71b4f 2485
467e3168
SC
2486 wxPoint clientorigin = GetClientAreaOrigin() ;
2487 wxSize clientsize = GetClientSize() ;
2488 wxCursor cursor ;
2489 if ( wxRect2DInt( clientorigin.x , clientorigin.y , clientsize.x , clientsize.y ).Contains( wxPoint2DInt( pt ) ) )
7de59551 2490 {
467e3168 2491 wxSetCursorEvent event( pt.x , pt.y );
6ed71b4f 2492
467e3168
SC
2493 bool processedEvtSetCursor = GetEventHandler()->ProcessEvent(event);
2494 if ( processedEvtSetCursor && event.HasCursor() )
2495 {
e40298d5 2496 cursor = event.GetCursor() ;
467e3168
SC
2497 }
2498 else
2499 {
467e3168
SC
2500 // the test for processedEvtSetCursor is here to prevent using m_cursor
2501 // if the user code caught EVT_SET_CURSOR() and returned nothing from
2502 // it - this is a way to say that our cursor shouldn't be used for this
2503 // point
2504 if ( !processedEvtSetCursor && m_cursor.Ok() )
467e3168 2505 cursor = m_cursor ;
e15f0a5e
DS
2506
2507 if ( !wxIsBusy() && !GetParent() )
2508 cursor = *wxSTANDARD_CURSOR ;
467e3168 2509 }
e15f0a5e 2510
467e3168
SC
2511 if ( cursor.Ok() )
2512 cursor.MacInstall() ;
2513 }
e15f0a5e 2514
467e3168
SC
2515 return cursor.Ok() ;
2516}
2517
89954433 2518wxString wxWindowMac::MacGetToolTipString( wxPoint &WXUNUSED(pt) )
2f1ae414 2519{
5e0526df 2520#if wxUSE_TOOLTIPS
6264b550 2521 if ( m_tooltip )
6264b550 2522 return m_tooltip->GetTip() ;
5e0526df 2523#endif
e15f0a5e 2524
427ff662 2525 return wxEmptyString ;
2f1ae414 2526}
6264b550 2527
cb4b0966
SC
2528void wxWindowMac::ClearBackground()
2529{
2530 Refresh() ;
2531 Update() ;
2532}
2533
1c310985 2534void wxWindowMac::Update()
519cb848 2535{
5bcdf503
JS
2536 wxTopLevelWindowMac* top = MacGetTopLevelWindow();
2537 if (top)
2538 top->MacPerformUpdates() ;
519cb848
SC
2539}
2540
14c9cbdb 2541wxTopLevelWindowMac* wxWindowMac::MacGetTopLevelWindow() const
519cb848 2542{
1c310985 2543 wxTopLevelWindowMac* win = NULL ;
facd6764 2544 WindowRef window = (WindowRef) MacGetTopLevelWindowRef() ;
1c310985 2545 if ( window )
1c310985 2546 win = wxFindWinFromMacWindow( window ) ;
e15f0a5e 2547
1c310985 2548 return win ;
519cb848 2549}
5c840e5b 2550
902725ee 2551const wxRect& wxWindowMac::MacGetClippedClientRect() const
e905b636
SC
2552{
2553 MacUpdateClippedRects() ;
e15f0a5e 2554
e905b636
SC
2555 return m_cachedClippedClientRect ;
2556}
2557
902725ee 2558const wxRect& wxWindowMac::MacGetClippedRect() const
5c840e5b
SC
2559{
2560 MacUpdateClippedRects() ;
e15f0a5e 2561
5c840e5b
SC
2562 return m_cachedClippedRect ;
2563}
2564
902725ee 2565const wxRect&wxWindowMac:: MacGetClippedRectWithOuterStructure() const
5c840e5b
SC
2566{
2567 MacUpdateClippedRects() ;
e15f0a5e 2568
5c840e5b
SC
2569 return m_cachedClippedRectWithOuterStructure ;
2570}
2571
2572const wxRegion& wxWindowMac::MacGetVisibleRegion( bool includeOuterStructures )
94abc21f 2573{
5c840e5b 2574 static wxRegion emptyrgn ;
898d9035 2575
5c840e5b
SC
2576 if ( !m_isBeingDeleted && MacIsReallyShown() /*m_peer->IsVisible() */ )
2577 {
2578 MacUpdateClippedRects() ;
2579 if ( includeOuterStructures )
2580 return m_cachedClippedRegionWithOuterStructure ;
2581 else
2582 return m_cachedClippedRegion ;
2583 }
2584 else
2585 {
2586 return emptyrgn ;
2587 }
2588}
2589
2590void wxWindowMac::MacUpdateClippedRects() const
2591{
2592 if ( m_cachedClippedRectValid )
2593 return ;
2594
0fa8508d
SC
2595 // includeOuterStructures is true if we try to draw somthing like a focus ring etc.
2596 // also a window dc uses this, in this case we only clip in the hierarchy for hard
2597 // borders like a scrollwindow, splitter etc otherwise we end up in a paranoia having
2598 // to add focus borders everywhere
8b573fb8 2599
e15f0a5e 2600 Rect r, rIncludingOuterStructures ;
902725ee 2601
5c840e5b
SC
2602 m_peer->GetRect( &r ) ;
2603 r.left -= MacGetLeftBorderSize() ;
2604 r.top -= MacGetTopBorderSize() ;
2605 r.bottom += MacGetBottomBorderSize() ;
2606 r.right += MacGetRightBorderSize() ;
2607
2608 r.right -= r.left ;
2609 r.bottom -= r.top ;
2610 r.left = 0 ;
2611 r.top = 0 ;
2612
2613 rIncludingOuterStructures = r ;
2614 InsetRect( &rIncludingOuterStructures , -4 , -4 ) ;
902725ee 2615
e905b636
SC
2616 wxRect cl = GetClientRect() ;
2617 Rect rClient = { cl.y , cl.x , cl.y + cl.height , cl.x + cl.width } ;
902725ee 2618
e15f0a5e
DS
2619 int x , y ;
2620 wxSize size ;
e905b636
SC
2621 const wxWindow* child = this ;
2622 const wxWindow* parent = NULL ;
898d9035 2623
e15f0a5e 2624 while ( !child->IsTopLevel() && ( parent = child->GetParent() ) != NULL )
e40298d5 2625 {
e905b636 2626 if ( parent->MacIsChildOfClientArea(child) )
94abc21f 2627 {
e905b636
SC
2628 size = parent->GetClientSize() ;
2629 wxPoint origin = parent->GetClientAreaOrigin() ;
2630 x = origin.x ;
2631 y = origin.y ;
2632 }
2633 else
2634 {
2635 // this will be true for scrollbars, toolbars etc.
2636 size = parent->GetSize() ;
2637 y = parent->MacGetTopBorderSize() ;
2638 x = parent->MacGetLeftBorderSize() ;
2639 size.x -= parent->MacGetLeftBorderSize() + parent->MacGetRightBorderSize() ;
2640 size.y -= parent->MacGetTopBorderSize() + parent->MacGetBottomBorderSize() ;
2641 }
21f9e953 2642
e905b636
SC
2643 parent->MacWindowToRootWindow( &x, &y ) ;
2644 MacRootWindowToWindow( &x , &y ) ;
21f9e953 2645
e905b636 2646 Rect rparent = { y , x , y + size.y , x + size.x } ;
5c840e5b 2647
e905b636
SC
2648 // the wxwindow and client rects will always be clipped
2649 SectRect( &r , &rparent , &r ) ;
2650 SectRect( &rClient , &rparent , &rClient ) ;
5c840e5b 2651
e905b636
SC
2652 // the structure only at 'hard' borders
2653 if ( parent->MacClipChildren() ||
2654 ( parent->GetParent() && parent->GetParent()->MacClipGrandChildren() ) )
2655 {
2656 SectRect( &rIncludingOuterStructures , &rparent , &rIncludingOuterStructures ) ;
94abc21f 2657 }
e15f0a5e 2658
e905b636 2659 child = parent ;
e40298d5 2660 }
902725ee 2661
5c840e5b 2662 m_cachedClippedRect = wxRect( r.left , r.top , r.right - r.left , r.bottom - r.top ) ;
902725ee 2663 m_cachedClippedClientRect = wxRect( rClient.left , rClient.top ,
e905b636 2664 rClient.right - rClient.left , rClient.bottom - rClient.top ) ;
902725ee
WS
2665 m_cachedClippedRectWithOuterStructure = wxRect(
2666 rIncludingOuterStructures.left , rIncludingOuterStructures.top ,
2667 rIncludingOuterStructures.right - rIncludingOuterStructures.left ,
5c840e5b 2668 rIncludingOuterStructures.bottom - rIncludingOuterStructures.top ) ;
902725ee 2669
5c840e5b
SC
2670 m_cachedClippedRegionWithOuterStructure = wxRegion( m_cachedClippedRectWithOuterStructure ) ;
2671 m_cachedClippedRegion = wxRegion( m_cachedClippedRect ) ;
e905b636 2672 m_cachedClippedClientRegion = wxRegion( m_cachedClippedClientRect ) ;
902725ee 2673
5c840e5b 2674 m_cachedClippedRectValid = true ;
94abc21f
SC
2675}
2676
facd6764
SC
2677/*
2678 This function must not change the updatergn !
2679 */
8e181eae 2680bool wxWindowMac::MacDoRedraw( void* updatergnr , long time )
519cb848 2681{
facd6764 2682 bool handled = false ;
42ef83fa 2683 Rect updatebounds ;
e15f0a5e 2684 RgnHandle updatergn = (RgnHandle) updatergnr ;
42ef83fa 2685 GetRegionBounds( updatergn , &updatebounds ) ;
20b69855 2686
e15f0a5e 2687 // wxLogDebug(wxT("update for %s bounds %d, %d, %d, %d"), wxString(GetClassInfo()->GetClassName()).c_str(), updatebounds.left, updatebounds.top , updatebounds.right , updatebounds.bottom ) ;
c79aad8b 2688
902725ee 2689 if ( !EmptyRgn(updatergn) )
6264b550 2690 {
1c310985
SC
2691 RgnHandle newupdate = NewRgn() ;
2692 wxSize point = GetClientSize() ;
2693 wxPoint origin = GetClientAreaOrigin() ;
e15f0a5e 2694 SetRectRgn( newupdate , origin.x , origin.y , origin.x + point.x , origin.y + point.y ) ;
facd6764 2695 SectRgn( newupdate , updatergn , newupdate ) ;
8b573fb8 2696
eec462f8
SC
2697 // first send an erase event to the entire update area
2698 {
c79aad8b
SC
2699 // for the toplevel window this really is the entire area
2700 // for all the others only their client area, otherwise they
2701 // might be drawing with full alpha and eg put blue into
2702 // the grow-box area of a scrolled window (scroll sample)
5c840e5b 2703 wxDC* dc = new wxWindowDC(this);
c79aad8b 2704 if ( IsTopLevel() )
8e181eae 2705 dc->SetClippingRegion(wxRegion(HIShapeCreateWithQDRgn(updatergn)));
c79aad8b 2706 else
8e181eae 2707 dc->SetClippingRegion(wxRegion(HIShapeCreateWithQDRgn(newupdate)));
902725ee 2708
c79aad8b 2709 wxEraseEvent eevent( GetId(), dc );
42ef83fa
SC
2710 eevent.SetEventObject( this );
2711 GetEventHandler()->ProcessEvent( eevent );
c79aad8b 2712 delete dc ;
eec462f8 2713 }
8b573fb8 2714
6239ee05
SC
2715 MacPaintGrowBox();
2716
42ef83fa 2717 // calculate a client-origin version of the update rgn and set m_updateRegion to that
1c310985 2718 OffsetRgn( newupdate , -origin.x , -origin.y ) ;
8e181eae 2719 m_updateRegion = wxRegion(HIShapeCreateWithQDRgn(newupdate)) ;
8b573fb8 2720 DisposeRgn( newupdate ) ;
6ed71b4f 2721
1c310985 2722 if ( !m_updateRegion.Empty() )
6264b550 2723 {
facd6764 2724 // paint the window itself
ff3795ee 2725
e40298d5 2726 wxPaintEvent event;
687706f5 2727 event.SetTimestamp(time);
e40298d5 2728 event.SetEventObject(this);
ff3795ee
SC
2729 GetEventHandler()->ProcessEvent(event);
2730 handled = true ;
eec462f8 2731 }
8b573fb8 2732
eec462f8
SC
2733 // now we cannot rely on having its borders drawn by a window itself, as it does not
2734 // get the updateRgn wide enough to always do so, so we do it from the parent
2735 // this would also be the place to draw any custom backgrounds for native controls
2736 // in Composited windowing
36d7f54e 2737 wxPoint clientOrigin = GetClientAreaOrigin() ;
8b573fb8 2738
e15f0a5e
DS
2739 wxWindowMac *child;
2740 int x, y, w, h;
71f2fb52 2741 for (wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); node; node = node->GetNext())
eec462f8 2742 {
e15f0a5e
DS
2743 child = node->GetData();
2744 if (child == NULL)
2745 continue;
2746 if (child == m_vScrollBar)
2747 continue;
2748 if (child == m_hScrollBar)
2749 continue;
2750 if (child->IsTopLevel())
2751 continue;
2752 if (!child->IsShown())
2753 continue;
fe779e40 2754
c79aad8b
SC
2755 // only draw those in the update region (add a safety margin of 10 pixels for shadow effects
2756
af6b7b80 2757 child->GetPosition( &x, &y );
af6b7b80
SC
2758 child->GetSize( &w, &h );
2759 Rect childRect = { y , x , y + h , x + w } ;
36d7f54e 2760 OffsetRect( &childRect , clientOrigin.x , clientOrigin.y ) ;
c79aad8b
SC
2761 InsetRect( &childRect , -10 , -10) ;
2762
2763 if ( RectInRgn( &childRect , updatergn ) )
eec462f8 2764 {
c79aad8b
SC
2765 // paint custom borders
2766 wxNcPaintEvent eventNc( child->GetId() );
2767 eventNc.SetEventObject( child );
2768 if ( !child->GetEventHandler()->ProcessEvent( eventNc ) )
eec462f8 2769 {
4f74e0d1 2770 child->MacPaintBorders(0, 0) ;
eec462f8 2771 }
8b573fb8 2772 }
14c9cbdb 2773 }
6264b550 2774 }
e15f0a5e 2775
facd6764
SC
2776 return handled ;
2777}
6ed71b4f 2778
519cb848 2779
facd6764 2780WXWindow wxWindowMac::MacGetTopLevelWindowRef() const
519cb848 2781{
6264b550 2782 wxWindowMac *iter = (wxWindowMac*)this ;
14c9cbdb 2783
e15f0a5e 2784 while ( iter )
6264b550 2785 {
1c310985 2786 if ( iter->IsTopLevel() )
6239ee05
SC
2787 {
2788 wxTopLevelWindow* toplevel = wxDynamicCast(iter,wxTopLevelWindow);
2789 if ( toplevel )
2790 return toplevel->MacGetWindowRef();
2791#if wxUSE_POPUPWIN
2792 wxPopupWindow* popupwin = wxDynamicCast(iter,wxPopupWindow);
2793 if ( popupwin )
2794 return popupwin->MacGetPopupWindowRef();
2795#endif
2796 }
6264b550 2797 iter = iter->GetParent() ;
14c9cbdb 2798 }
e15f0a5e 2799
6264b550 2800 return NULL ;
519cb848
SC
2801}
2802
6239ee05
SC
2803bool wxWindowMac::MacHasScrollBarCorner() const
2804{
2805 /* Returns whether the scroll bars in a wxScrolledWindow should be
2806 * shortened. Scroll bars should be shortened if either:
2807 *
2808 * - both scroll bars are visible, or
2809 *
2810 * - there is a resize box in the parent frame's corner and this
2811 * window shares the bottom and right edge with the parent
2812 * frame.
2813 */
2814
2815 if ( m_hScrollBar == NULL && m_vScrollBar == NULL )
2816 return false;
2817
2818 if ( ( m_hScrollBar && m_hScrollBar->IsShown() )
2819 && ( m_vScrollBar && m_vScrollBar->IsShown() ) )
2820 {
2821 // Both scroll bars visible
2822 return true;
2823 }
2824 else
2825 {
2826 wxPoint thisWindowBottomRight = GetScreenRect().GetBottomRight();
2827
2828 for ( const wxWindow *win = this; win; win = win->GetParent() )
2829 {
2830 const wxFrame *frame = wxDynamicCast( win, wxFrame ) ;
2831 if ( frame )
2832 {
2833 if ( frame->GetWindowStyleFlag() & wxRESIZE_BORDER )
2834 {
2835 // Parent frame has resize handle
2836 wxPoint frameBottomRight = frame->GetScreenRect().GetBottomRight();
2837
2838 // Note: allow for some wiggle room here as wxMac's
2839 // window rect calculations seem to be imprecise
2840 if ( abs( thisWindowBottomRight.x - frameBottomRight.x ) <= 2
2841 && abs( thisWindowBottomRight.y - frameBottomRight.y ) <= 2 )
2842 {
2843 // Parent frame has resize handle and shares
2844 // right bottom corner
2845 return true ;
2846 }
2847 else
2848 {
2849 // Parent frame has resize handle but doesn't
2850 // share right bottom corner
2851 return false ;
2852 }
2853 }
2854 else
2855 {
2856 // Parent frame doesn't have resize handle
2857 return false ;
2858 }
2859 }
2860 }
2861
2862 // No parent frame found
2863 return false ;
2864 }
2865}
2866
14c9cbdb 2867void wxWindowMac::MacCreateScrollBars( long style )
519cb848 2868{
427ff662 2869 wxASSERT_MSG( m_vScrollBar == NULL && m_hScrollBar == NULL , wxT("attempt to create window twice") ) ;
14c9cbdb 2870
aa99e0cd
SC
2871 if ( style & ( wxVSCROLL | wxHSCROLL ) )
2872 {
db7a550b 2873 int scrlsize = MAC_SCROLLBAR_SIZE ;
8b573fb8
VZ
2874 if ( GetWindowVariant() == wxWINDOW_VARIANT_SMALL || GetWindowVariant() == wxWINDOW_VARIANT_MINI )
2875 {
2876 scrlsize = MAC_SMALL_SCROLLBAR_SIZE ;
8b573fb8 2877 }
db7a550b 2878
6239ee05 2879 int adjust = MacHasScrollBarCorner() ? scrlsize - 1: 0 ;
aa99e0cd
SC
2880 int width, height ;
2881 GetClientSize( &width , &height ) ;
2882
898d9035 2883 wxPoint vPoint(width - scrlsize, 0) ;
db7a550b 2884 wxSize vSize(scrlsize, height - adjust) ;
fbc1d11b
DS
2885 wxPoint hPoint(0, height - scrlsize) ;
2886 wxSize hSize(width - adjust, scrlsize) ;
aa99e0cd 2887
6239ee05 2888 // we have to set the min size to a smaller value, otherwise they cannot get smaller (InitialSize sets MinSize)
aa99e0cd 2889 if ( style & wxVSCROLL )
6239ee05
SC
2890 {
2891 m_vScrollBar = new wxScrollBar((wxWindow*)this, wxID_ANY, vPoint, vSize , wxVERTICAL);
2892 m_vScrollBar->SetMinSize( wxDefaultSize );
2893 }
aa99e0cd
SC
2894
2895 if ( style & wxHSCROLL )
6239ee05
SC
2896 {
2897 m_hScrollBar = new wxScrollBar((wxWindow*)this, wxID_ANY, hPoint, hSize , wxHORIZONTAL);
2898 m_hScrollBar->SetMinSize( wxDefaultSize );
2899 }
aa99e0cd 2900 }
aa99e0cd 2901
6264b550 2902 // because the create does not take into account the client area origin
e15f0a5e
DS
2903 // we might have a real position shift
2904 MacRepositionScrollBars() ;
519cb848
SC
2905}
2906
e905b636
SC
2907bool wxWindowMac::MacIsChildOfClientArea( const wxWindow* child ) const
2908{
fbc1d11b
DS
2909 bool result = ((child == NULL) || ((child != m_hScrollBar) && (child != m_vScrollBar)));
2910
2911 return result ;
e905b636
SC
2912}
2913
e766c8a9 2914void wxWindowMac::MacRepositionScrollBars()
519cb848 2915{
aa99e0cd
SC
2916 if ( !m_hScrollBar && !m_vScrollBar )
2917 return ;
8b573fb8 2918
db7a550b 2919 int scrlsize = m_hScrollBar ? m_hScrollBar->GetSize().y : ( m_vScrollBar ? m_vScrollBar->GetSize().x : MAC_SCROLLBAR_SIZE ) ;
6239ee05 2920 int adjust = MacHasScrollBarCorner() ? scrlsize - 1 : 0 ;
14c9cbdb 2921
6264b550 2922 // get real client area
e15f0a5e
DS
2923 int width, height ;
2924 GetSize( &width , &height );
6264b550
RR
2925
2926 width -= MacGetLeftBorderSize() + MacGetRightBorderSize();
2927 height -= MacGetTopBorderSize() + MacGetBottomBorderSize();
14c9cbdb 2928
e15f0a5e
DS
2929 wxPoint vPoint( width - scrlsize, 0 ) ;
2930 wxSize vSize( scrlsize, height - adjust ) ;
2931 wxPoint hPoint( 0 , height - scrlsize ) ;
2932 wxSize hSize( width - adjust, scrlsize ) ;
2933
2934#if 0
2935 int x = 0, y = 0, w, h ;
facd6764 2936 GetSize( &w , &h ) ;
14c9cbdb 2937
6264b550
RR
2938 MacClientToRootWindow( &x , &y ) ;
2939 MacClientToRootWindow( &w , &h ) ;
14c9cbdb 2940
6264b550 2941 wxWindowMac *iter = (wxWindowMac*)this ;
14c9cbdb 2942
6264b550 2943 int totW = 10000 , totH = 10000;
e15f0a5e 2944 while ( iter )
6264b550 2945 {
1c310985 2946 if ( iter->IsTopLevel() )
6264b550 2947 {
facd6764 2948 iter->GetSize( &totW , &totH ) ;
6264b550
RR
2949 break ;
2950 }
2951
2952 iter = iter->GetParent() ;
14c9cbdb
RD
2953 }
2954
6264b550
RR
2955 if ( x == 0 )
2956 {
2957 hPoint.x = -1 ;
2958 hSize.x += 1 ;
2959 }
2960 if ( y == 0 )
2961 {
2962 vPoint.y = -1 ;
2963 vSize.y += 1 ;
2964 }
14c9cbdb 2965
e15f0a5e 2966 if ( w - x >= totW )
6264b550
RR
2967 {
2968 hSize.x += 1 ;
2969 vPoint.x += 1 ;
2970 }
e15f0a5e 2971 if ( h - y >= totH )
6264b550
RR
2972 {
2973 vSize.y += 1 ;
2974 hPoint.y += 1 ;
2975 }
e15f0a5e
DS
2976#endif
2977
6264b550 2978 if ( m_vScrollBar )
e15f0a5e 2979 m_vScrollBar->SetSize( vPoint.x , vPoint.y, vSize.x, vSize.y , wxSIZE_ALLOW_MINUS_ONE );
6264b550 2980 if ( m_hScrollBar )
e15f0a5e 2981 m_hScrollBar->SetSize( hPoint.x , hPoint.y, hSize.x, hSize.y, wxSIZE_ALLOW_MINUS_ONE );
519cb848
SC
2982}
2983
e766c8a9 2984bool wxWindowMac::AcceptsFocus() const
7c551d95
SC
2985{
2986 return MacCanFocus() && wxWindowBase::AcceptsFocus();
2987}
519cb848 2988
14c9cbdb 2989void wxWindowMac::MacSuperChangedPosition()
519cb848 2990{
6264b550 2991 // only window-absolute structures have to be moved i.e. controls
519cb848 2992
e15f0a5e
DS
2993 m_cachedClippedRectValid = false ;
2994
2995 wxWindowMac *child;
71f2fb52 2996 wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
6264b550
RR
2997 while ( node )
2998 {
e15f0a5e 2999 child = node->GetData();
6264b550 3000 child->MacSuperChangedPosition() ;
e15f0a5e 3001
eb22f2a6 3002 node = node->GetNext();
6264b550 3003 }
519cb848 3004}
519cb848 3005
14c9cbdb 3006void wxWindowMac::MacTopLevelWindowChangedPosition()
a3bf4a62 3007{
6264b550 3008 // only screen-absolute structures have to be moved i.e. glcanvas
a3bf4a62 3009
e15f0a5e 3010 wxWindowMac *child;
71f2fb52 3011 wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
6264b550
RR
3012 while ( node )
3013 {
e15f0a5e 3014 child = node->GetData();
6264b550 3015 child->MacTopLevelWindowChangedPosition() ;
e15f0a5e 3016
eb22f2a6 3017 node = node->GetNext();
6264b550 3018 }
a3bf4a62 3019}
facd6764 3020
e15f0a5e 3021long wxWindowMac::MacGetLeftBorderSize() const
2f1ae414 3022{
e15f0a5e 3023 if ( IsTopLevel() )
6264b550 3024 return 0 ;
2f1ae414 3025
8f39b6c4 3026 SInt32 border = 0 ;
902725ee 3027
e15f0a5e 3028 if (HasFlag(wxRAISED_BORDER) || HasFlag( wxSUNKEN_BORDER) || HasFlag(wxDOUBLE_BORDER))
2f1ae414 3029 {
fbc1d11b 3030 // this metric is only the 'outset' outside the simple frame rect
8f39b6c4 3031 GetThemeMetric( kThemeMetricEditTextFrameOutset , &border ) ;
fbc1d11b 3032 border += 1 ;
2f1ae414 3033 }
8f39b6c4 3034 else if (HasFlag(wxSIMPLE_BORDER))
2f1ae414 3035 {
fbc1d11b 3036 // this metric is only the 'outset' outside the simple frame rect
8f39b6c4 3037 GetThemeMetric( kThemeMetricListBoxFrameOutset , &border ) ;
fbc1d11b 3038 border += 1 ;
2f1ae414 3039 }
e15f0a5e 3040
8f39b6c4 3041 return border ;
2f1ae414
SC
3042}
3043
e15f0a5e 3044long wxWindowMac::MacGetRightBorderSize() const
5b781a67 3045{
1c310985
SC
3046 // they are all symmetric in mac themes
3047 return MacGetLeftBorderSize() ;
5b781a67
SC
3048}
3049
e15f0a5e 3050long wxWindowMac::MacGetTopBorderSize() const
5b781a67 3051{
1c310985
SC
3052 // they are all symmetric in mac themes
3053 return MacGetLeftBorderSize() ;
5b781a67
SC
3054}
3055
e15f0a5e 3056long wxWindowMac::MacGetBottomBorderSize() const
5b781a67 3057{
1c310985
SC
3058 // they are all symmetric in mac themes
3059 return MacGetLeftBorderSize() ;
5b781a67
SC
3060}
3061
14c9cbdb 3062long wxWindowMac::MacRemoveBordersFromStyle( long style )
2f1ae414 3063{
055a486b 3064 return style & ~wxBORDER_MASK ;
2f1ae414 3065}
0a67a93b 3066
e766c8a9 3067// Find the wxWindowMac at the current mouse position, returning the mouse
3723b7b1 3068// position.
e15f0a5e 3069wxWindowMac * wxFindWindowAtPointer( wxPoint& pt )
3723b7b1 3070{
59a12e90 3071 pt = wxGetMousePosition();
e766c8a9 3072 wxWindowMac* found = wxFindWindowAtPoint(pt);
e15f0a5e 3073
59a12e90 3074 return found;
3723b7b1
JS
3075}
3076
3077// Get the current mouse position.
3078wxPoint wxGetMousePosition()
3079{
57591e0e 3080 int x, y;
e15f0a5e
DS
3081
3082 wxGetMousePosition( &x, &y );
3083
57591e0e 3084 return wxPoint(x, y);
3723b7b1
JS
3085}
3086
6ed71b4f 3087void wxWindowMac::OnMouseEvent( wxMouseEvent &event )
8950f7cc 3088{
8b573fb8
VZ
3089 if ( event.GetEventType() == wxEVT_RIGHT_DOWN )
3090 {
3091 // copied from wxGTK : CS
fe224552
VZ
3092 // VZ: shouldn't we move this to base class then?
3093
249aad30 3094 // generate a "context menu" event: this is similar to wxEVT_RIGHT_DOWN
8950f7cc
SC
3095 // except that:
3096 //
3097 // (a) it's a command event and so is propagated to the parent
3098 // (b) under MSW it can be generated from kbd too
3099 // (c) it uses screen coords (because of (a))
3100 wxContextMenuEvent evtCtx(wxEVT_CONTEXT_MENU,
3101 this->GetId(),
3102 this->ClientToScreen(event.GetPosition()));
249aad30
SC
3103 if ( ! GetEventHandler()->ProcessEvent(evtCtx) )
3104 event.Skip() ;
8b573fb8 3105 }
facd6764
SC
3106 else
3107 {
8b573fb8 3108 event.Skip() ;
facd6764 3109 }
8950f7cc
SC
3110}
3111
89954433 3112void wxWindowMac::OnPaint( wxPaintEvent & WXUNUSED(event) )
ff3795ee 3113{
4488a1d3
VZ
3114 if ( wxTheApp->MacGetCurrentEvent() != NULL && wxTheApp->MacGetCurrentEventHandlerCallRef() != NULL
3115 && GetBackgroundStyle() != wxBG_STYLE_TRANSPARENT )
e15f0a5e
DS
3116 CallNextEventHandler(
3117 (EventHandlerCallRef)wxTheApp->MacGetCurrentEventHandlerCallRef() ,
3118 (EventRef) wxTheApp->MacGetCurrentEvent() ) ;
ff3795ee
SC
3119}
3120
89954433
VZ
3121void wxWindowMac::MacHandleControlClick(WXWidget WXUNUSED(control),
3122 wxInt16 WXUNUSED(controlpart),
3123 bool WXUNUSED(mouseStillDown))
facd6764 3124{
facd6764
SC
3125}
3126
8b573fb8 3127Rect wxMacGetBoundsForControl( wxWindow* window , const wxPoint& pos , const wxSize &size , bool adjustForOrigin )
3083eb85 3128{
e15f0a5e 3129 int x, y, w, h ;
8b573fb8 3130
58603178
DS
3131 window->MacGetBoundsForControl( pos , size , x , y, w, h , adjustForOrigin ) ;
3132 Rect bounds = { y, x, y + h, x + w };
e15f0a5e 3133
3083eb85
SC
3134 return bounds ;
3135}
3136
8b573fb8 3137wxInt32 wxWindowMac::MacControlHit(WXEVENTHANDLERREF WXUNUSED(handler) , WXEVENTREF WXUNUSED(event) )
f1d527c1
SC
3138{
3139 return eventNotHandledErr ;
3140}
3141
50779e06
JS
3142bool wxWindowMac::Reparent(wxWindowBase *newParentBase)
3143{
3144 wxWindowMac *newParent = (wxWindowMac *)newParentBase;
50779e06 3145 if ( !wxWindowBase::Reparent(newParent) )
3dee36ae
WS
3146 return false;
3147
e15f0a5e 3148 // copied from MacPostControlCreate
50779e06 3149 ControlRef container = (ControlRef) GetParent()->GetHandle() ;
e15f0a5e 3150
50779e06 3151 wxASSERT_MSG( container != NULL , wxT("No valid mac container control") ) ;
e15f0a5e 3152
50779e06 3153 ::EmbedControl( m_peer->GetControlRef() , container ) ;
facd6764 3154
3dee36ae
WS
3155 return true;
3156}
a9b456ff
SC
3157
3158bool wxWindowMac::SetTransparent(wxByte alpha)
3159{
4488a1d3
VZ
3160 SetBackgroundStyle(wxBG_STYLE_TRANSPARENT);
3161
a9b456ff
SC
3162 if ( alpha != m_macAlpha )
3163 {
3164 m_macAlpha = alpha ;
3165 Refresh() ;
3166 }
3167 return true ;
a9b456ff
SC
3168}
3169
3170
3171bool wxWindowMac::CanSetTransparent()
3172{
a9b456ff 3173 return true ;
a9b456ff
SC
3174}
3175
89954433 3176wxByte wxWindowMac::GetTransparent() const
a9b456ff
SC
3177{
3178 return m_macAlpha ;
8444b6cb 3179}