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