]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/window.cpp
remove unneccessary header dependencies on wx/thread.h
[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
8e181eae
SC
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 //
307
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 }
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
ec7ff71b
SC
326
327 wxLogTrace(_T("Focus"), _T("focus lost(%p)"), wx_static_cast(void*, thisWindow));
328
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);
ec7ff71b 348
e15f0a5e 349#if wxUSE_CARET
f1d527c1 350 if ( thisWindow->GetCaret() )
f1d527c1 351 thisWindow->GetCaret()->OnSetFocus();
e15f0a5e 352#endif
ec7ff71b 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 }
368#endif
369 ControlPartCode controlPart = cEvent.GetParameter<ControlPartCode>(kEventParamControlPart , typeControlPartCode );
370
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);
382
383 if ( UMAGetSystemVersion() < 0x1050 )
384 {
385// set back to 0 if problems arise
386#if 1
387 ControlPartCode currentControlPart = cEvent.GetParameter<ControlPartCode>(kEventParamControlPart , typeControlPartCode );
388 // synthesize the event focus changed event
389 EventRef evRef = NULL ;
390
391 OSStatus err = MacCreateEvent(
392 NULL , kEventClassControl , kEventControlFocusPartChanged , TicksToEventTime( TickCount() ) ,
393 kEventAttributeUserEvent , &evRef );
394 verify_noerr( err );
395
396 wxMacCarbonEvent iEvent( evRef ) ;
397 iEvent.SetParameter<ControlRef>( kEventParamDirectObject , controlRef ) ;
398 iEvent.SetParameter<ControlPartCode>( kEventParamControlPreviousPart, typeControlPartCode, previousControlPart ) ;
399 iEvent.SetParameter<ControlPartCode>( kEventParamControlCurrentPart, typeControlPartCode, currentControlPart ) ;
400
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));
418
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 {
457 // fix to always have a proper activation for DataBrowser controls (stay in bkgnd otherwise)
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 ;
5ca930b1 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/*
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.
89954433 637
5ca930b1 638 However, the code that was being used caused additional problems:
980ee83f 639 UInt32 message = (0 << 8) + ((char)uniChars[pos] );
5ca930b1
VZ
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
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 ;
79392158 868 m_frozenness = 0 ;
a9b456ff 869 m_macAlpha = 255 ;
e15f0a5e 870 m_cgContextRef = NULL ;
e15f0a5e 871
e7549107 872 // as all windows are created with WS_VISIBLE style...
902725ee 873 m_isShown = true;
e7549107 874
6264b550
RR
875 m_hScrollBar = NULL ;
876 m_vScrollBar = NULL ;
c1142003
VZ
877 m_hScrollBarAlwaysShown = false;
878 m_vScrollBarAlwaysShown = false;
879
902725ee 880 m_macIsUserPane = true;
8adc196b 881 m_clipChildren = false ;
5c840e5b 882 m_cachedClippedRectValid = false ;
e15f0a5e 883
c6f9fb05
SC
884 // we need a valid font for the encodings
885 wxWindowBase::SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
e9576ca5
SC
886}
887
e766c8a9 888wxWindowMac::~wxWindowMac()
e9576ca5 889{
7de59551
RD
890 SendDestroyEvent();
891
902725ee 892 m_isBeingDeleted = true;
6ed71b4f 893
6449b3a8 894 MacInvalidateBorders() ;
7ebf5540 895
d4380aaf
SC
896#ifndef __WXUNIVERSAL__
897 // VS: make sure there's no wxFrame with last focus set to us:
898 for ( wxWindow *win = GetParent(); win; win = win->GetParent() )
899 {
900 wxFrame *frame = wxDynamicCast(win, wxFrame);
901 if ( frame )
902 {
903 if ( frame->GetLastFocus() == this )
d4380aaf 904 frame->SetLastFocus((wxWindow*)NULL);
d4380aaf
SC
905 break;
906 }
907 }
b46dde27 908#endif
8b573fb8
VZ
909
910 // destroy children before destroying this window itself
911 DestroyChildren();
912
facd6764
SC
913 // wxRemoveMacControlAssociation( this ) ;
914 // If we delete an item, we should initialize the parent panel,
915 // because it could now be invalid.
6c20e8f8
VZ
916 wxTopLevelWindow *tlw = wxDynamicCast(wxGetTopLevelParent(this), wxTopLevelWindow);
917 if ( tlw )
facd6764 918 {
6c20e8f8
VZ
919 if ( tlw->GetDefaultItem() == (wxButton*) this)
920 tlw->SetDefaultItem(NULL);
facd6764 921 }
e15f0a5e 922
21fd5529 923 if ( m_peer && m_peer->Ok() )
facd6764
SC
924 {
925 // in case the callback might be called during destruction
926 wxRemoveMacControlAssociation( this) ;
229f6270 927 ::RemoveEventHandler( (EventHandlerRef ) m_macControlEventHandler ) ;
5ca0d812
SC
928 // we currently are not using this hook
929 // ::SetControlColorProc( *m_peer , NULL ) ;
930 m_peer->Dispose() ;
facd6764 931 }
d4380aaf 932
facd6764 933 if ( g_MacLastWindow == this )
facd6764 934 g_MacLastWindow = NULL ;
7de59551 935
6239ee05
SC
936#ifndef __WXUNIVERSAL__
937 wxFrame* frame = wxDynamicCast( wxGetTopLevelParent( (wxWindow*)this ) , wxFrame ) ;
fd76aa8d
SC
938 if ( frame )
939 {
e40298d5
JS
940 if ( frame->GetLastFocus() == this )
941 frame->SetLastFocus( NULL ) ;
fd76aa8d 942 }
6239ee05 943#endif
e7549107 944
42683dfb
SC
945 // delete our drop target if we've got one
946#if wxUSE_DRAG_AND_DROP
947 if ( m_dropTarget != NULL )
948 {
949 delete m_dropTarget;
950 m_dropTarget = NULL;
951 }
e15f0a5e
DS
952#endif
953
21fd5529
SC
954 delete m_peer ;
955}
956
8b573fb8
VZ
957WXWidget wxWindowMac::GetHandle() const
958{
959 return (WXWidget) m_peer->GetControlRef() ;
e9576ca5
SC
960}
961
5ca0d812 962void wxWindowMac::MacInstallEventHandler( WXWidget control )
facd6764 963{
898d9035
DS
964 wxAssociateControlWithMacControl( (ControlRef) control , this ) ;
965 InstallControlEventHandler( (ControlRef)control , GetwxMacWindowEventHandlerUPP(),
8b573fb8 966 GetEventTypeCount(eventList), eventList, this,
facd6764 967 (EventHandlerRef *)&m_macControlEventHandler);
facd6764
SC
968}
969
e9576ca5 970// Constructor
58603178
DS
971bool wxWindowMac::Create(wxWindowMac *parent,
972 wxWindowID id,
973 const wxPoint& pos,
974 const wxSize& size,
975 long style,
976 const wxString& name)
e9576ca5 977{
902725ee 978 wxCHECK_MSG( parent, false, wxT("can't create wxWindowMac without parent") );
e9576ca5 979
e7549107 980 if ( !CreateBase(parent, id, pos, size, style, wxDefaultValidator, name) )
902725ee 981 return false;
e9576ca5 982
facd6764 983 m_windowVariant = parent->GetWindowVariant() ;
8b573fb8 984
facd6764
SC
985 if ( m_macIsUserPane )
986 {
987 Rect bounds = wxMacGetBoundsForControl( this , pos , size ) ;
8b573fb8 988
ebe86b1e 989 UInt32 features = 0
8b573fb8 990 | kControlSupportsEmbedding
1f1c8bd4
SC
991 | kControlSupportsLiveFeedback
992 | kControlGetsFocusOnClick
8b573fb8
VZ
993// | kControlHasSpecialBackground
994// | kControlSupportsCalcBestRect
1f1c8bd4 995 | kControlHandlesTracking
8b573fb8 996 | kControlSupportsFocus
1f1c8bd4 997 | kControlWantsActivate
58603178 998 | kControlWantsIdle ;
ebe86b1e 999
6449b3a8 1000 m_peer = new wxMacControl(this) ;
58603178
DS
1001 OSStatus err =::CreateUserPaneControl( MAC_WXHWND(GetParent()->MacGetTopLevelWindowRef()) , &bounds, features , m_peer->GetControlRefAddr() );
1002 verify_noerr( err );
8b573fb8 1003
898d9035 1004 MacPostControlCreate(pos, size) ;
facd6764 1005 }
898d9035 1006
e766c8a9 1007#ifndef __WXUNIVERSAL__
14c9cbdb 1008 // Don't give scrollbars to wxControls unless they ask for them
58603178
DS
1009 if ( (! IsKindOf(CLASSINFO(wxControl)) && ! IsKindOf(CLASSINFO(wxStatusBar)))
1010 || (IsKindOf(CLASSINFO(wxControl)) && ((style & wxHSCROLL) || (style & wxVSCROLL))))
6264b550
RR
1011 {
1012 MacCreateScrollBars( style ) ;
1013 }
e766c8a9 1014#endif
3dfafdb9
RD
1015
1016 wxWindowCreateEvent event(this);
7e4a196e 1017 GetEventHandler()->AddPendingEvent(event);
3dfafdb9 1018
902725ee 1019 return true;
e9576ca5
SC
1020}
1021
902725ee 1022void wxWindowMac::MacChildAdded()
08422003
SC
1023{
1024 if ( m_vScrollBar )
08422003 1025 m_vScrollBar->Raise() ;
08422003 1026 if ( m_hScrollBar )
08422003 1027 m_hScrollBar->Raise() ;
08422003
SC
1028}
1029
89954433 1030void wxWindowMac::MacPostControlCreate(const wxPoint& WXUNUSED(pos), const wxSize& size)
facd6764 1031{
21fd5529 1032 wxASSERT_MSG( m_peer != NULL && m_peer->Ok() , wxT("No valid mac control") ) ;
facd6764 1033
4f74e0d1 1034 m_peer->SetReference( (URefCon) this ) ;
58603178 1035 GetParent()->AddChild( this );
facd6764 1036
5ca0d812 1037 MacInstallEventHandler( (WXWidget) m_peer->GetControlRef() );
facd6764
SC
1038
1039 ControlRef container = (ControlRef) GetParent()->GetHandle() ;
1040 wxASSERT_MSG( container != NULL , wxT("No valid mac container control") ) ;
5ca0d812 1041 ::EmbedControl( m_peer->GetControlRef() , container ) ;
08422003 1042 GetParent()->MacChildAdded() ;
facd6764
SC
1043
1044 // adjust font, controlsize etc
1045 DoSetWindowVariant( m_windowVariant ) ;
1046
32cd189d 1047 m_peer->SetLabel( wxStripMenuCodes(m_label, wxStrip_Mnemonics) ) ;
facd6764 1048
facd6764 1049 if (!m_macIsUserPane)
170acdc9 1050 SetInitialSize(size);
facd6764
SC
1051
1052 SetCursor( *wxSTANDARD_CURSOR ) ;
facd6764
SC
1053}
1054
1055void wxWindowMac::DoSetWindowVariant( wxWindowVariant variant )
1056{
23176131
JS
1057 // Don't assert, in case we set the window variant before
1058 // the window is created
21fd5529 1059 // wxASSERT( m_peer->Ok() ) ;
facd6764 1060
23176131
JS
1061 m_windowVariant = variant ;
1062
21fd5529 1063 if (m_peer == NULL || !m_peer->Ok())
23176131 1064 return;
facd6764 1065
8b573fb8 1066 ControlSize size ;
facd6764
SC
1067 ThemeFontID themeFont = kThemeSystemFont ;
1068
1069 // we will get that from the settings later
8b573fb8 1070 // and make this NORMAL later, but first
facd6764 1071 // we have a few calculations that we must fix
8b573fb8 1072
facd6764
SC
1073 switch ( variant )
1074 {
1075 case wxWINDOW_VARIANT_NORMAL :
8b573fb8
VZ
1076 size = kControlSizeNormal;
1077 themeFont = kThemeSystemFont ;
facd6764 1078 break ;
e15f0a5e 1079
facd6764 1080 case wxWINDOW_VARIANT_SMALL :
8b573fb8
VZ
1081 size = kControlSizeSmall;
1082 themeFont = kThemeSmallSystemFont ;
facd6764 1083 break ;
e15f0a5e 1084
facd6764 1085 case wxWINDOW_VARIANT_MINI :
9d463591
SC
1086 // not always defined in the headers
1087 size = 3 ;
1088 themeFont = 109 ;
facd6764 1089 break ;
e15f0a5e 1090
facd6764 1091 case wxWINDOW_VARIANT_LARGE :
8b573fb8
VZ
1092 size = kControlSizeLarge;
1093 themeFont = kThemeSystemFont ;
facd6764 1094 break ;
e15f0a5e 1095
facd6764
SC
1096 default:
1097 wxFAIL_MSG(_T("unexpected window variant"));
1098 break ;
1099 }
e15f0a5e 1100
898d9035 1101 m_peer->SetData<ControlSize>(kControlEntireControl, kControlSizeTag, &size ) ;
facd6764
SC
1102
1103 wxFont font ;
b7dbd50c 1104 font.MacCreateFromThemeFont( themeFont ) ;
facd6764
SC
1105 SetFont( font ) ;
1106}
1107
8b573fb8 1108void wxWindowMac::MacUpdateControlFont()
facd6764 1109{
ac99838a 1110 m_peer->SetFont( GetFont() , GetForegroundColour() , GetWindowStyle() ) ;
6239ee05
SC
1111 // do not trigger refreshes upon invisible and possible partly created objects
1112 if ( MacIsReallyShown() )
1113 Refresh() ;
facd6764
SC
1114}
1115
1116bool wxWindowMac::SetFont(const wxFont& font)
1117{
58603178 1118 bool retval = wxWindowBase::SetFont( font );
8b573fb8 1119
facd6764 1120 MacUpdateControlFont() ;
8b573fb8 1121
facd6764
SC
1122 return retval;
1123}
1124
1125bool wxWindowMac::SetForegroundColour(const wxColour& col )
1126{
58603178 1127 bool retval = wxWindowBase::SetForegroundColour( col );
8b573fb8 1128
898d9035 1129 if (retval)
58603178 1130 MacUpdateControlFont();
8b573fb8 1131
898d9035 1132 return retval;
facd6764
SC
1133}
1134
1135bool wxWindowMac::SetBackgroundColour(const wxColour& col )
1136{
1137 if ( !wxWindowBase::SetBackgroundColour(col) && m_hasBgCol )
1138 return false ;
1139
a01d9a25 1140 m_peer->SetBackgroundColour( col ) ;
8b573fb8 1141
facd6764
SC
1142 return true ;
1143}
1144
facd6764
SC
1145bool wxWindowMac::MacCanFocus() const
1146{
90b4f7b5 1147 // TODO : evaluate performance hits by looking up this value, eventually cache the results for a 1 sec or so
2e91d506
DS
1148 // CAUTION : the value returned currently is 0 or 2, I've also found values of 1 having the same meaning,
1149 // but the value range is nowhere documented
90b4f7b5 1150 Boolean keyExistsAndHasValidFormat ;
2e91d506
DS
1151 CFIndex fullKeyboardAccess = CFPreferencesGetAppIntegerValue( CFSTR("AppleKeyboardUIMode" ) ,
1152 kCFPreferencesCurrentApplication, &keyExistsAndHasValidFormat );
1153
90b4f7b5 1154 if ( keyExistsAndHasValidFormat && fullKeyboardAccess > 0 )
2e91d506 1155 {
90b4f7b5 1156 return true ;
2e91d506 1157 }
90b4f7b5
SC
1158 else
1159 {
1160 UInt32 features = 0 ;
1161 m_peer->GetFeatures( &features ) ;
1162
1163 return features & ( kControlSupportsFocus | kControlGetsFocusOnClick ) ;
1164 }
facd6764
SC
1165}
1166
e766c8a9 1167void wxWindowMac::SetFocus()
e9576ca5 1168{
e15f0a5e 1169 if ( !AcceptsFocus() )
7d0cfe71
SC
1170 return ;
1171
e15f0a5e
DS
1172 wxWindow* former = FindFocus() ;
1173 if ( former == this )
1174 return ;
1175
1176 // as we cannot rely on the control features to find out whether we are in full keyboard mode,
1177 // we can only leave in case of an error
1178 OSStatus err = m_peer->SetFocus( kControlFocusNextPart ) ;
1179 if ( err == errCouldntSetFocus )
1180 return ;
1181
e15f0a5e 1182 SetUserFocusWindow( (WindowRef)MacGetTopLevelWindowRef() );
e9576ca5
SC
1183}
1184
4116c221 1185void wxWindowMac::DoCaptureMouse()
e9576ca5 1186{
2a1f999f 1187 wxApp::s_captureWindow = this ;
e9576ca5
SC
1188}
1189
2e91d506 1190wxWindow * wxWindowBase::GetCapture()
90b959ae 1191{
2a1f999f 1192 return wxApp::s_captureWindow ;
90b959ae
SC
1193}
1194
4116c221 1195void wxWindowMac::DoReleaseMouse()
e9576ca5 1196{
2a1f999f 1197 wxApp::s_captureWindow = NULL ;
e9576ca5
SC
1198}
1199
e15f0a5e 1200#if wxUSE_DRAG_AND_DROP
e9576ca5 1201
e766c8a9 1202void wxWindowMac::SetDropTarget(wxDropTarget *pDropTarget)
e9576ca5 1203{
e15f0a5e 1204 if ( m_dropTarget != NULL )
e40298d5 1205 delete m_dropTarget;
6ed71b4f 1206
e40298d5 1207 m_dropTarget = pDropTarget;
e15f0a5e 1208 if ( m_dropTarget != NULL )
e40298d5 1209 {
58603178 1210 // TODO:
e40298d5 1211 }
e9576ca5
SC
1212}
1213
1214#endif
1215
2e91d506 1216// Old-style File Manager Drag & Drop
89954433 1217void wxWindowMac::DragAcceptFiles(bool WXUNUSED(accept))
e9576ca5 1218{
58603178 1219 // TODO:
e9576ca5
SC
1220}
1221
055a486b
SC
1222// Returns the size of the native control. In the case of the toplevel window
1223// this is the content area root control
1224
89954433
VZ
1225void wxWindowMac::MacGetPositionAndSizeFromControl(int& WXUNUSED(x),
1226 int& WXUNUSED(y),
1227 int& WXUNUSED(w),
1228 int& WXUNUSED(h)) const
e9576ca5 1229{
898d9035 1230 wxFAIL_MSG( wxT("Not currently supported") ) ;
e9576ca5
SC
1231}
1232
055a486b 1233// From a wx position / size calculate the appropriate size of the native control
8b573fb8 1234
898d9035
DS
1235bool wxWindowMac::MacGetBoundsForControl(
1236 const wxPoint& pos,
1237 const wxSize& size,
1238 int& x, int& y,
1239 int& w, int& h , bool adjustOrigin ) const
51abe921 1240{
5ca0d812 1241 // the desired size, minus the border pixels gives the correct size of the control
facd6764
SC
1242 x = (int)pos.x;
1243 y = (int)pos.y;
58603178
DS
1244
1245 // TODO: the default calls may be used as soon as PostCreateControl Is moved here
898d9035
DS
1246 w = wxMax(size.x, 0) ; // WidthDefault( size.x );
1247 h = wxMax(size.y, 0) ; // HeightDefault( size.y ) ;
789ae0cf 1248
5ca0d812
SC
1249 x += MacGetLeftBorderSize() ;
1250 y += MacGetTopBorderSize() ;
1251 w -= MacGetLeftBorderSize() + MacGetRightBorderSize() ;
1252 h -= MacGetTopBorderSize() + MacGetBottomBorderSize() ;
8b573fb8 1253
79392158
SC
1254 if ( adjustOrigin )
1255 AdjustForParentClientOrigin( x , y ) ;
789ae0cf 1256
7ebf5540 1257 // this is in window relative coordinate, as this parent may have a border, its physical position is offset by this border
789ae0cf 1258 if ( !GetParent()->IsTopLevel() )
7ebf5540
SC
1259 {
1260 x -= GetParent()->MacGetLeftBorderSize() ;
1261 y -= GetParent()->MacGetTopBorderSize() ;
1262 }
789ae0cf 1263
facd6764
SC
1264 return true ;
1265}
1266
42ef83fa 1267// Get window size (not client size)
facd6764
SC
1268void wxWindowMac::DoGetSize(int *x, int *y) const
1269{
1f1c8bd4
SC
1270 Rect bounds ;
1271 m_peer->GetRect( &bounds ) ;
8b573fb8 1272
e15f0a5e
DS
1273 if (x)
1274 *x = bounds.right - bounds.left + MacGetLeftBorderSize() + MacGetRightBorderSize() ;
1275 if (y)
1276 *y = bounds.bottom - bounds.top + MacGetTopBorderSize() + MacGetBottomBorderSize() ;
facd6764
SC
1277}
1278
42ef83fa 1279// get the position of the bounds of this window in client coordinates of its parent
facd6764
SC
1280void wxWindowMac::DoGetPosition(int *x, int *y) const
1281{
1f1c8bd4
SC
1282 Rect bounds ;
1283 m_peer->GetRect( &bounds ) ;
902725ee 1284
1f1c8bd4
SC
1285 int x1 = bounds.left ;
1286 int y1 = bounds.top ;
789ae0cf 1287
bc2b0c1b
SC
1288 // get the wx window position from the native one
1289 x1 -= MacGetLeftBorderSize() ;
1290 y1 -= MacGetTopBorderSize() ;
1291
facd6764 1292 if ( !IsTopLevel() )
2b5f62a0 1293 {
facd6764
SC
1294 wxWindow *parent = GetParent();
1295 if ( parent )
8950f7cc 1296 {
e15f0a5e
DS
1297 // we must first adjust it to be in window coordinates of the parent,
1298 // as otherwise it gets lost by the ClientAreaOrigin fix
1a02aff9
SC
1299 x1 += parent->MacGetLeftBorderSize() ;
1300 y1 += parent->MacGetTopBorderSize() ;
e15f0a5e 1301
1a02aff9 1302 // and now to client coordinates
facd6764
SC
1303 wxPoint pt(parent->GetClientAreaOrigin());
1304 x1 -= pt.x ;
1305 y1 -= pt.y ;
6ed71b4f 1306 }
2b5f62a0 1307 }
e15f0a5e
DS
1308
1309 if (x)
1310 *x = x1 ;
1311 if (y)
1312 *y = y1 ;
facd6764 1313}
51abe921 1314
e766c8a9 1315void wxWindowMac::DoScreenToClient(int *x, int *y) const
e9576ca5 1316{
facd6764 1317 WindowRef window = (WindowRef) MacGetTopLevelWindowRef() ;
58603178 1318 wxCHECK_RET( window , wxT("TopLevel Window missing") ) ;
8b573fb8 1319
58603178 1320 Point localwhere = { 0, 0 } ;
519cb848 1321
58603178
DS
1322 if (x)
1323 localwhere.h = *x ;
1324 if (y)
1325 localwhere.v = *y ;
8b573fb8 1326
4f74e0d1 1327 wxMacGlobalToLocal( window , &localwhere ) ;
6ed71b4f 1328
58603178
DS
1329 if (x)
1330 *x = localwhere.h ;
1331 if (y)
1332 *y = localwhere.v ;
e15f0a5e 1333
2078220e 1334 MacRootWindowToWindow( x , y ) ;
8b573fb8 1335
facd6764 1336 wxPoint origin = GetClientAreaOrigin() ;
e15f0a5e
DS
1337 if (x)
1338 *x -= origin.x ;
1339 if (y)
1340 *y -= origin.y ;
e9576ca5
SC
1341}
1342
e766c8a9 1343void wxWindowMac::DoClientToScreen(int *x, int *y) const
e9576ca5 1344{
facd6764 1345 WindowRef window = (WindowRef) MacGetTopLevelWindowRef() ;
8523a5f5 1346 wxCHECK_RET( window , wxT("TopLevel window missing") ) ;
14c9cbdb 1347
facd6764 1348 wxPoint origin = GetClientAreaOrigin() ;
e15f0a5e
DS
1349 if (x)
1350 *x += origin.x ;
1351 if (y)
1352 *y += origin.y ;
14c9cbdb 1353
2078220e 1354 MacWindowToRootWindow( x , y ) ;
14c9cbdb 1355
58603178
DS
1356 Point localwhere = { 0, 0 };
1357 if (x)
1358 localwhere.h = *x ;
1359 if (y)
1360 localwhere.v = *y ;
e15f0a5e 1361
4f74e0d1 1362 wxMacLocalToGlobal( window, &localwhere ) ;
e15f0a5e 1363
58603178
DS
1364 if (x)
1365 *x = localwhere.h ;
1366 if (y)
1367 *y = localwhere.v ;
519cb848
SC
1368}
1369
e766c8a9 1370void wxWindowMac::MacClientToRootWindow( int *x , int *y ) const
519cb848 1371{
1c310985 1372 wxPoint origin = GetClientAreaOrigin() ;
e15f0a5e
DS
1373 if (x)
1374 *x += origin.x ;
1375 if (y)
1376 *y += origin.y ;
14c9cbdb 1377
1c310985
SC
1378 MacWindowToRootWindow( x , y ) ;
1379}
1380
1381void wxWindowMac::MacRootWindowToClient( int *x , int *y ) const
1382{
1c310985 1383 MacRootWindowToWindow( x , y ) ;
facd6764
SC
1384
1385 wxPoint origin = GetClientAreaOrigin() ;
e15f0a5e
DS
1386 if (x)
1387 *x -= origin.x ;
1388 if (y)
1389 *y -= origin.y ;
1c310985
SC
1390}
1391
1392void wxWindowMac::MacWindowToRootWindow( int *x , int *y ) const
1393{
5ca0d812 1394 wxPoint pt ;
58603178 1395
e15f0a5e
DS
1396 if (x)
1397 pt.x = *x ;
1398 if (y)
1399 pt.y = *y ;
facd6764 1400
125c7984 1401 if ( !IsTopLevel() )
5437ff47
RD
1402 {
1403 wxTopLevelWindowMac* top = MacGetTopLevelWindow();
1404 if (top)
5ca0d812
SC
1405 {
1406 pt.x -= MacGetLeftBorderSize() ;
1407 pt.y -= MacGetTopBorderSize() ;
1408 wxMacControl::Convert( &pt , m_peer , top->m_peer ) ;
1409 }
5437ff47 1410 }
8b573fb8 1411
e15f0a5e
DS
1412 if (x)
1413 *x = (int) pt.x ;
1414 if (y)
1415 *y = (int) pt.y ;
facd6764
SC
1416}
1417
1418void wxWindowMac::MacWindowToRootWindow( short *x , short *y ) const
1419{
1420 int x1 , y1 ;
e15f0a5e
DS
1421
1422 if (x)
1423 x1 = *x ;
1424 if (y)
1425 y1 = *y ;
1426
facd6764 1427 MacWindowToRootWindow( &x1 , &y1 ) ;
e15f0a5e
DS
1428
1429 if (x)
1430 *x = x1 ;
1431 if (y)
1432 *y = y1 ;
519cb848
SC
1433}
1434
1c310985 1435void wxWindowMac::MacRootWindowToWindow( int *x , int *y ) const
519cb848 1436{
5ca0d812 1437 wxPoint pt ;
e15f0a5e
DS
1438
1439 if (x)
1440 pt.x = *x ;
1441 if (y)
1442 pt.y = *y ;
facd6764 1443
125c7984 1444 if ( !IsTopLevel() )
5ca0d812 1445 {
5c840e5b
SC
1446 wxTopLevelWindowMac* top = MacGetTopLevelWindow();
1447 if (top)
1448 {
1449 wxMacControl::Convert( &pt , top->m_peer , m_peer ) ;
1450 pt.x += MacGetLeftBorderSize() ;
1451 pt.y += MacGetTopBorderSize() ;
1452 }
5ca0d812 1453 }
8b573fb8 1454
e15f0a5e
DS
1455 if (x)
1456 *x = (int) pt.x ;
1457 if (y)
1458 *y = (int) pt.y ;
e9576ca5
SC
1459}
1460
facd6764 1461void wxWindowMac::MacRootWindowToWindow( short *x , short *y ) const
e9576ca5 1462{
facd6764 1463 int x1 , y1 ;
e15f0a5e
DS
1464
1465 if (x)
1466 x1 = *x ;
1467 if (y)
1468 y1 = *y ;
1469
facd6764 1470 MacRootWindowToWindow( &x1 , &y1 ) ;
e15f0a5e
DS
1471
1472 if (x)
1473 *x = x1 ;
1474 if (y)
1475 *y = y1 ;
facd6764 1476}
6ed71b4f 1477
29281095
SC
1478void wxWindowMac::MacGetContentAreaInset( int &left , int &top , int &right , int &bottom )
1479{
1480 RgnHandle rgn = NewRgn() ;
898d9035 1481
5ca0d812 1482 if ( m_peer->GetRegion( kControlContentMetaPart , rgn ) == noErr )
29281095 1483 {
898d9035
DS
1484 Rect structure, content ;
1485
29281095 1486 GetRegionBounds( rgn , &content ) ;
1f1c8bd4
SC
1487 m_peer->GetRect( &structure ) ;
1488 OffsetRect( &structure, -structure.left , -structure.top ) ;
902725ee 1489
1f1c8bd4 1490 left = content.left - structure.left ;
898d9035 1491 top = content.top - structure.top ;
1f1c8bd4
SC
1492 right = structure.right - content.right ;
1493 bottom = structure.bottom - content.bottom ;
29281095
SC
1494 }
1495 else
1496 {
1f1c8bd4 1497 left = top = right = bottom = 0 ;
29281095 1498 }
898d9035 1499
7596e51d 1500 DisposeRgn( rgn ) ;
29281095
SC
1501}
1502
facd6764
SC
1503wxSize wxWindowMac::DoGetSizeFromClientSize( const wxSize & size ) const
1504{
1505 wxSize sizeTotal = size;
1506
1507 RgnHandle rgn = NewRgn() ;
5ca0d812 1508 if ( m_peer->GetRegion( kControlContentMetaPart , rgn ) == noErr )
6618870d 1509 {
898d9035 1510 Rect content, structure ;
facd6764 1511 GetRegionBounds( rgn , &content ) ;
1f1c8bd4 1512 m_peer->GetRect( &structure ) ;
898d9035 1513
1f1c8bd4 1514 // structure is in parent coordinates, but we only need width and height, so it's ok
6ed71b4f 1515
1f1c8bd4 1516 sizeTotal.x += (structure.right - structure.left) - (content.right - content.left) ;
8523a5f5 1517 sizeTotal.y += (structure.bottom - structure.top) - (content.bottom - content.top) ;
1f1c8bd4 1518 }
898d9035 1519
1f1c8bd4 1520 DisposeRgn( rgn ) ;
6ed71b4f 1521
e15f0a5e
DS
1522 sizeTotal.x += MacGetLeftBorderSize() + MacGetRightBorderSize() ;
1523 sizeTotal.y += MacGetTopBorderSize() + MacGetBottomBorderSize() ;
6ed71b4f 1524
facd6764 1525 return sizeTotal;
e9576ca5
SC
1526}
1527
e9576ca5 1528// Get size *available for subwindows* i.e. excluding menu bar etc.
e15f0a5e 1529void wxWindowMac::DoGetClientSize( int *x, int *y ) const
e9576ca5 1530{
9453cf2b 1531 int ww, hh;
6ed71b4f 1532
facd6764
SC
1533 RgnHandle rgn = NewRgn() ;
1534 Rect content ;
5ca0d812 1535 if ( m_peer->GetRegion( kControlContentMetaPart , rgn ) == noErr )
facd6764 1536 GetRegionBounds( rgn , &content ) ;
facd6764 1537 else
5ca0d812 1538 m_peer->GetRect( &content ) ;
7596e51d 1539 DisposeRgn( rgn ) ;
789ae0cf 1540
facd6764
SC
1541 ww = content.right - content.left ;
1542 hh = content.bottom - content.top ;
6ed71b4f 1543
db7a550b 1544 if (m_hScrollBar && m_hScrollBar->IsShown() )
e905b636 1545 hh -= m_hScrollBar->GetSize().y ;
e15f0a5e 1546
db7a550b 1547 if (m_vScrollBar && m_vScrollBar->IsShown() )
e905b636 1548 ww -= m_vScrollBar->GetSize().x ;
e15f0a5e
DS
1549
1550 if (x)
1551 *x = ww;
1552 if (y)
1553 *y = hh;
facd6764
SC
1554}
1555
1556bool wxWindowMac::SetCursor(const wxCursor& cursor)
1557{
a3ab1c18 1558 if (m_cursor.IsSameAs(cursor))
902725ee 1559 return false;
facd6764 1560
2e573683 1561 if (!cursor.IsOk())
facd6764
SC
1562 {
1563 if ( ! wxWindowBase::SetCursor( *wxSTANDARD_CURSOR ) )
902725ee 1564 return false ;
facd6764
SC
1565 }
1566 else
1567 {
1568 if ( ! wxWindowBase::SetCursor( cursor ) )
902725ee 1569 return false ;
facd6764
SC
1570 }
1571
1572 wxASSERT_MSG( m_cursor.Ok(),
1573 wxT("cursor must be valid after call to the base version"));
8b573fb8 1574
2d1760d3 1575 wxWindowMac *mouseWin = 0 ;
facd6764 1576 {
789ae0cf
SC
1577 wxTopLevelWindowMac *tlw = MacGetTopLevelWindow() ;
1578 WindowRef window = (WindowRef) ( tlw ? tlw->MacGetWindowRef() : 0 ) ;
4f74e0d1
SC
1579
1580 ControlPartCode part ;
1581 ControlRef control ;
1582 Point pt ;
1583 #if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
1584 HIPoint hiPoint ;
1585 HIGetMousePosition(kHICoordSpaceWindow, window, &hiPoint);
1586 pt.h = hiPoint.x;
1587 pt.v = hiPoint.y;
89954433 1588 #else
8e181eae
SC
1589 GetGlobalMouse( &pt );
1590 int x = pt.h;
1591 int y = pt.v;
1592 ScreenToClient(&x, &y);
1593 pt.h = x;
1594 pt.v = y;
4f74e0d1 1595#endif
9d463591 1596 control = FindControlUnderMouse( pt , window , &part ) ;
2d1760d3
SC
1597 if ( control )
1598 mouseWin = wxFindControlFromMacControl( control ) ;
8b573fb8 1599
facd6764 1600 }
2d1760d3
SC
1601
1602 if ( mouseWin == this && !wxIsBusy() )
facd6764 1603 m_cursor.MacInstall() ;
facd6764 1604
902725ee 1605 return true ;
519cb848
SC
1606}
1607
facd6764
SC
1608#if wxUSE_MENUS
1609bool wxWindowMac::DoPopupMenu(wxMenu *menu, int x, int y)
1610{
6239ee05
SC
1611#ifndef __WXUNIVERSAL__
1612 menu->SetInvokingWindow((wxWindow*)this);
facd6764 1613 menu->UpdateUI();
8b573fb8 1614
851dee09 1615 if ( x == wxDefaultCoord && y == wxDefaultCoord )
971562cb
VS
1616 {
1617 wxPoint mouse = wxGetMousePosition();
898d9035
DS
1618 x = mouse.x;
1619 y = mouse.y;
971562cb
VS
1620 }
1621 else
1622 {
1623 ClientToScreen( &x , &y ) ;
1624 }
facd6764
SC
1625
1626 menu->MacBeforeDisplay( true ) ;
898d9035 1627 long menuResult = ::PopUpMenuSelect((MenuHandle) menu->GetHMenu() , y, x, 0) ;
facd6764
SC
1628 if ( HiWord(menuResult) != 0 )
1629 {
e8027adb
SC
1630 MenuCommand macid;
1631 GetMenuItemCommandID( GetMenuHandle(HiWord(menuResult)) , LoWord(menuResult) , &macid );
b46dde27
DS
1632 int id = wxMacCommandToId( macid );
1633 wxMenuItem* item = NULL ;
facd6764 1634 wxMenu* realmenu ;
58603178 1635 item = menu->FindItem( id, &realmenu ) ;
e8027adb
SC
1636 if ( item )
1637 {
1638 if (item->IsCheckable())
1639 item->Check( !item->IsChecked() ) ;
e15f0a5e 1640
e8027adb
SC
1641 menu->SendEvent( id , item->IsCheckable() ? item->IsChecked() : -1 ) ;
1642 }
facd6764 1643 }
facd6764 1644
898d9035 1645 menu->MacAfterDisplay( true ) ;
8523a5f5 1646 menu->SetInvokingWindow( NULL );
facd6764 1647
902725ee 1648 return true;
6239ee05
SC
1649#else
1650 // actually this shouldn't be called, because universal is having its own implementation
1651 return false;
1652#endif
facd6764
SC
1653}
1654#endif
51abe921
SC
1655
1656// ----------------------------------------------------------------------------
1657// tooltips
1658// ----------------------------------------------------------------------------
1659
1660#if wxUSE_TOOLTIPS
1661
e766c8a9 1662void wxWindowMac::DoSetToolTip(wxToolTip *tooltip)
51abe921
SC
1663{
1664 wxWindowBase::DoSetToolTip(tooltip);
6ed71b4f 1665
6264b550
RR
1666 if ( m_tooltip )
1667 m_tooltip->SetWindow(this);
51abe921
SC
1668}
1669
898d9035 1670#endif
51abe921 1671
902725ee 1672void wxWindowMac::MacInvalidateBorders()
6449b3a8
SC
1673{
1674 if ( m_peer == NULL )
1675 return ;
1676
1677 bool vis = MacIsReallyShown() ;
1678 if ( !vis )
1679 return ;
902725ee 1680
6449b3a8 1681 int outerBorder = MacGetLeftBorderSize() ;
a0a2b5c4 1682 if ( m_peer->NeedsFocusRect() /* && m_peer->HasFocus() */ )
6449b3a8
SC
1683 outerBorder += 4 ;
1684
1685 if ( outerBorder == 0 )
1686 return ;
902725ee
WS
1687
1688 // now we know that we have something to do at all
6449b3a8
SC
1689
1690 // as the borders are drawn on the parent we have to properly invalidate all these areas
58603178
DS
1691 RgnHandle updateInner , updateOuter;
1692 Rect rect ;
6449b3a8
SC
1693
1694 // this rectangle is in HIViewCoordinates under OSX and in Window Coordinates under Carbon
58603178
DS
1695 updateInner = NewRgn() ;
1696 updateOuter = NewRgn() ;
1697
6449b3a8 1698 m_peer->GetRect( &rect ) ;
898d9035 1699 RectRgn( updateInner, &rect ) ;
6449b3a8 1700 InsetRect( &rect , -outerBorder , -outerBorder ) ;
898d9035
DS
1701 RectRgn( updateOuter, &rect ) ;
1702 DiffRgn( updateOuter, updateInner , updateOuter ) ;
e15f0a5e 1703
1f1c8bd4 1704 GetParent()->m_peer->SetNeedsDisplay( updateOuter ) ;
e15f0a5e 1705
58603178
DS
1706 DisposeRgn( updateOuter ) ;
1707 DisposeRgn( updateInner ) ;
6449b3a8
SC
1708}
1709
e766c8a9 1710void wxWindowMac::DoMoveWindow(int x, int y, int width, int height)
51abe921 1711{
db7a550b 1712 // this is never called for a toplevel window, so we know we have a parent
facd6764 1713 int former_x , former_y , former_w, former_h ;
db7a550b
SC
1714
1715 // Get true coordinates of former position
facd6764
SC
1716 DoGetPosition( &former_x , &former_y ) ;
1717 DoGetSize( &former_w , &former_h ) ;
db7a550b
SC
1718
1719 wxWindow *parent = GetParent();
1720 if ( parent )
1721 {
1722 wxPoint pt(parent->GetClientAreaOrigin());
1723 former_x += pt.x ;
1724 former_y += pt.y ;
1725 }
6ed71b4f 1726
29ee02df
SC
1727 int actualWidth = width ;
1728 int actualHeight = height ;
e40298d5
JS
1729 int actualX = x;
1730 int actualY = y;
6ed71b4f 1731
14c9cbdb 1732 if ((m_minWidth != -1) && (actualWidth < m_minWidth))
6264b550 1733 actualWidth = m_minWidth;
14c9cbdb 1734 if ((m_minHeight != -1) && (actualHeight < m_minHeight))
6264b550 1735 actualHeight = m_minHeight;
14c9cbdb 1736 if ((m_maxWidth != -1) && (actualWidth > m_maxWidth))
6264b550 1737 actualWidth = m_maxWidth;
14c9cbdb 1738 if ((m_maxHeight != -1) && (actualHeight > m_maxHeight))
902725ee 1739 actualHeight = m_maxHeight;
6ed71b4f 1740
898d9035 1741 bool doMove = false, doResize = false ;
6ed71b4f 1742
6264b550 1743 if ( actualX != former_x || actualY != former_y )
6264b550 1744 doMove = true ;
e15f0a5e 1745
6264b550 1746 if ( actualWidth != former_w || actualHeight != former_h )
6264b550 1747 doResize = true ;
6ed71b4f 1748
6264b550
RR
1749 if ( doMove || doResize )
1750 {
902725ee 1751 // as the borders are drawn outside the native control, we adjust now
1f1c8bd4 1752
902725ee
WS
1753 wxRect bounds( wxPoint( actualX + MacGetLeftBorderSize() ,actualY + MacGetTopBorderSize() ),
1754 wxSize( actualWidth - (MacGetLeftBorderSize() + MacGetRightBorderSize()) ,
1f1c8bd4
SC
1755 actualHeight - (MacGetTopBorderSize() + MacGetBottomBorderSize()) ) ) ;
1756
1757 Rect r ;
1758 wxMacRectToNative( &bounds , &r ) ;
1759
1760 if ( !GetParent()->IsTopLevel() )
1f1c8bd4 1761 wxMacWindowToNative( GetParent() , &r ) ;
8b573fb8 1762
6449b3a8 1763 MacInvalidateBorders() ;
902725ee 1764
5c840e5b 1765 m_cachedClippedRectValid = false ;
8b573fb8 1766 m_peer->SetRect( &r ) ;
902725ee 1767
e905b636 1768 wxWindowMac::MacSuperChangedPosition() ; // like this only children will be notified
91ae6e3a 1769
6449b3a8
SC
1770 MacInvalidateBorders() ;
1771
6264b550
RR
1772 MacRepositionScrollBars() ;
1773 if ( doMove )
1774 {
898d9035 1775 wxPoint point(actualX, actualY);
6264b550
RR
1776 wxMoveEvent event(point, m_windowId);
1777 event.SetEventObject(this);
937013e0 1778 HandleWindowEvent(event) ;
6264b550 1779 }
e15f0a5e 1780
6264b550
RR
1781 if ( doResize )
1782 {
e40298d5 1783 MacRepositionScrollBars() ;
facd6764 1784 wxSize size(actualWidth, actualHeight);
e40298d5
JS
1785 wxSizeEvent event(size, m_windowId);
1786 event.SetEventObject(this);
937013e0 1787 HandleWindowEvent(event);
6264b550
RR
1788 }
1789 }
954fc50b
SC
1790}
1791
facd6764
SC
1792wxSize wxWindowMac::DoGetBestSize() const
1793{
eb69d46e
SC
1794 if ( m_macIsUserPane || IsTopLevel() )
1795 return wxWindowBase::DoGetBestSize() ;
8b573fb8 1796
facd6764 1797 Rect bestsize = { 0 , 0 , 0 , 0 } ;
facd6764 1798 int bestWidth, bestHeight ;
facd6764 1799
898d9035 1800 m_peer->GetBestRect( &bestsize ) ;
facd6764
SC
1801 if ( EmptyRect( &bestsize ) )
1802 {
898d9035
DS
1803 bestsize.left =
1804 bestsize.top = 0 ;
1805 bestsize.right =
facd6764 1806 bestsize.bottom = 16 ;
898d9035 1807
facd6764
SC
1808 if ( IsKindOf( CLASSINFO( wxScrollBar ) ) )
1809 {
1810 bestsize.bottom = 16 ;
1811 }
902725ee 1812#if wxUSE_SPINBTN
facd6764
SC
1813 else if ( IsKindOf( CLASSINFO( wxSpinButton ) ) )
1814 {
8b573fb8 1815 bestsize.bottom = 24 ;
facd6764 1816 }
898d9035 1817#endif
facd6764
SC
1818 else
1819 {
8b573fb8 1820 // return wxWindowBase::DoGetBestSize() ;
facd6764
SC
1821 }
1822 }
1823
1824 bestWidth = bestsize.right - bestsize.left ;
1825 bestHeight = bestsize.bottom - bestsize.top ;
1826 if ( bestHeight < 10 )
1827 bestHeight = 13 ;
8b573fb8 1828
facd6764
SC
1829 return wxSize(bestWidth, bestHeight);
1830}
1831
954fc50b
SC
1832// set the size of the window: if the dimensions are positive, just use them,
1833// but if any of them is equal to -1, it means that we must find the value for
1834// it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in
1835// which case -1 is a valid value for x and y)
1836//
1837// If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate
1838// the width/height to best suit our contents, otherwise we reuse the current
1839// width/height
1840void wxWindowMac::DoSetSize(int x, int y, int width, int height, int sizeFlags)
1841{
1842 // get the current size and position...
1843 int currentX, currentY;
898d9035 1844 int currentW, currentH;
6ed71b4f 1845
898d9035 1846 GetPosition(&currentX, &currentY);
954fc50b 1847 GetSize(&currentW, &currentH);
6ed71b4f 1848
954fc50b
SC
1849 // ... and don't do anything (avoiding flicker) if it's already ok
1850 if ( x == currentX && y == currentY &&
769ac869 1851 width == currentW && height == currentH && ( height != -1 && width != -1 ) )
954fc50b 1852 {
e15f0a5e 1853 // TODO: REMOVE
6264b550 1854 MacRepositionScrollBars() ; // we might have a real position shift
898d9035 1855
954fc50b
SC
1856 return;
1857 }
6ed71b4f 1858
58603178
DS
1859 if ( !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) )
1860 {
1861 if ( x == wxDefaultCoord )
1862 x = currentX;
1863 if ( y == wxDefaultCoord )
1864 y = currentY;
1865 }
6ed71b4f 1866
58603178 1867 AdjustForParentClientOrigin( x, y, sizeFlags );
6ed71b4f 1868
3dee36ae
WS
1869 wxSize size = wxDefaultSize;
1870 if ( width == wxDefaultCoord )
954fc50b
SC
1871 {
1872 if ( sizeFlags & wxSIZE_AUTO_WIDTH )
1873 {
1874 size = DoGetBestSize();
1875 width = size.x;
1876 }
1877 else
1878 {
1879 // just take the current one
1880 width = currentW;
1881 }
1882 }
6ed71b4f 1883
3dee36ae 1884 if ( height == wxDefaultCoord )
954fc50b
SC
1885 {
1886 if ( sizeFlags & wxSIZE_AUTO_HEIGHT )
1887 {
3dee36ae 1888 if ( size.x == wxDefaultCoord )
954fc50b 1889 size = DoGetBestSize();
898d9035 1890 // else: already called DoGetBestSize() above
6ed71b4f 1891
954fc50b
SC
1892 height = size.y;
1893 }
1894 else
1895 {
1896 // just take the current one
1897 height = currentH;
1898 }
1899 }
6ed71b4f 1900
58603178 1901 DoMoveWindow( x, y, width, height );
e9576ca5 1902}
519cb848 1903
e766c8a9 1904wxPoint wxWindowMac::GetClientAreaOrigin() const
e9576ca5 1905{
facd6764
SC
1906 RgnHandle rgn = NewRgn() ;
1907 Rect content ;
04d4e684 1908 if ( m_peer->GetRegion( kControlContentMetaPart , rgn ) == noErr )
21638402
SC
1909 {
1910 GetRegionBounds( rgn , &content ) ;
1911 }
1912 else
1913 {
898d9035
DS
1914 content.left =
1915 content.top = 0 ;
21638402 1916 }
898d9035 1917
facd6764 1918 DisposeRgn( rgn ) ;
e15f0a5e
DS
1919
1920 return wxPoint( content.left + MacGetLeftBorderSize() , content.top + MacGetTopBorderSize() );
facd6764
SC
1921}
1922
1923void wxWindowMac::DoSetClientSize(int clientwidth, int clientheight)
1924{
d0dec992 1925 if ( clientwidth != wxDefaultCoord || clientheight != wxDefaultCoord )
facd6764
SC
1926 {
1927 int currentclientwidth , currentclientheight ;
1928 int currentwidth , currentheight ;
1929
1930 GetClientSize( &currentclientwidth , &currentclientheight ) ;
1931 GetSize( &currentwidth , &currentheight ) ;
1932
3dee36ae 1933 DoSetSize( wxDefaultCoord , wxDefaultCoord , currentwidth + clientwidth - currentclientwidth ,
facd6764
SC
1934 currentheight + clientheight - currentclientheight , wxSIZE_USE_EXISTING ) ;
1935 }
e9576ca5
SC
1936}
1937
fb5246be 1938void wxWindowMac::SetLabel(const wxString& title)
e9576ca5 1939{
6239ee05 1940 m_label = title ;
facd6764 1941
21fd5529 1942 if ( m_peer && m_peer->Ok() )
6239ee05 1943 m_peer->SetLabel( wxStripMenuCodes(m_label, wxStrip_Mnemonics) ) ;
e15f0a5e 1944
6239ee05
SC
1945 // do not trigger refreshes upon invisible and possible partly created objects
1946 if ( MacIsReallyShown() )
1947 Refresh() ;
519cb848
SC
1948}
1949
fb5246be 1950wxString wxWindowMac::GetLabel() const
519cb848 1951{
ed60b502 1952 return m_label ;
519cb848
SC
1953}
1954
8ab50549
SC
1955bool wxWindowMac::Show(bool show)
1956{
1957 if ( !wxWindowBase::Show(show) )
902725ee 1958 return false;
8b573fb8 1959
2c899c20 1960 if ( m_peer )
2c899c20 1961 m_peer->SetVisibility( show , true ) ;
e15f0a5e 1962
902725ee 1963 return true;
8ab50549
SC
1964}
1965
47a8a4d5 1966void wxWindowMac::DoEnable(bool enable)
8ab50549 1967{
5ca0d812 1968 m_peer->Enable( enable ) ;
8ab50549
SC
1969}
1970
8ab50549
SC
1971//
1972// status change notifications
8b573fb8 1973//
8ab50549 1974
8b573fb8 1975void wxWindowMac::MacVisibilityChanged()
8ab50549
SC
1976{
1977}
1978
8b573fb8 1979void wxWindowMac::MacHiliteChanged()
8ab50549
SC
1980{
1981}
1982
8b573fb8 1983void wxWindowMac::MacEnabledStateChanged()
8ab50549 1984{
8e181eae 1985 OnEnabled( m_peer->IsEnabled() );
facd6764 1986}
e7549107 1987
8ab50549
SC
1988//
1989// status queries on the inherited window's state
1990//
1991
8b573fb8 1992bool wxWindowMac::MacIsReallyShown()
facd6764
SC
1993{
1994 // only under OSX the visibility of the TLW is taken into account
66ffb23b
SC
1995 if ( m_isBeingDeleted )
1996 return false ;
902725ee 1997
facd6764 1998#if TARGET_API_MAC_OSX
aa522e33
SC
1999 if ( m_peer && m_peer->Ok() )
2000 return m_peer->IsVisible();
2001#endif
e15f0a5e 2002
facd6764 2003 wxWindow* win = this ;
898d9035 2004 while ( win->IsShown() )
facd6764
SC
2005 {
2006 if ( win->IsTopLevel() )
2007 return true ;
8b573fb8 2008
facd6764
SC
2009 win = win->GetParent() ;
2010 if ( win == NULL )
2011 return true ;
e15f0a5e 2012 }
8b573fb8 2013
facd6764 2014 return false ;
facd6764 2015}
4241baae 2016
8b573fb8 2017bool wxWindowMac::MacIsReallyEnabled()
facd6764 2018{
5ca0d812 2019 return m_peer->IsEnabled() ;
facd6764
SC
2020}
2021
8b573fb8 2022bool wxWindowMac::MacIsReallyHilited()
c809f3be 2023{
5ca0d812 2024 return m_peer->IsActive();
c809f3be
SC
2025}
2026
8b573fb8 2027void wxWindowMac::MacFlashInvalidAreas()
002c9672
SC
2028{
2029#if TARGET_API_MAC_OSX
2030 HIViewFlashDirtyArea( (WindowRef) MacGetTopLevelWindowRef() ) ;
2031#endif
2032}
2033
e766c8a9 2034int wxWindowMac::GetCharHeight() const
e9576ca5 2035{
e15f0a5e
DS
2036 wxClientDC dc( (wxWindowMac*)this ) ;
2037
6264b550 2038 return dc.GetCharHeight() ;
e9576ca5
SC
2039}
2040
e766c8a9 2041int wxWindowMac::GetCharWidth() const
e9576ca5 2042{
e15f0a5e
DS
2043 wxClientDC dc( (wxWindowMac*)this ) ;
2044
6264b550 2045 return dc.GetCharWidth() ;
e9576ca5
SC
2046}
2047
e766c8a9 2048void wxWindowMac::GetTextExtent(const wxString& string, int *x, int *y,
e7549107 2049 int *descent, int *externalLeading, const wxFont *theFont ) const
e9576ca5 2050{
e7549107
SC
2051 const wxFont *fontToUse = theFont;
2052 if ( !fontToUse )
2053 fontToUse = &m_font;
14c9cbdb 2054
e766c8a9 2055 wxClientDC dc( (wxWindowMac*) this ) ;
659863d8 2056 wxCoord lx,ly,ld,le ;
5fde6fcc 2057 dc.GetTextExtent( string , &lx , &ly , &ld, &le, (wxFont *)fontToUse ) ;
2f1ae414 2058 if ( externalLeading )
6264b550 2059 *externalLeading = le ;
2f1ae414 2060 if ( descent )
6264b550 2061 *descent = ld ;
2f1ae414 2062 if ( x )
6264b550 2063 *x = lx ;
2f1ae414 2064 if ( y )
6264b550 2065 *y = ly ;
e9576ca5
SC
2066}
2067
0a67a93b 2068/*
14c9cbdb 2069 * Rect is given in client coordinates, for further reading, read wxTopLevelWindowMac::InvalidateRect
1c310985
SC
2070 * we always intersect with the entire window, not only with the client area
2071 */
14c9cbdb 2072
89954433 2073void wxWindowMac::Refresh(bool WXUNUSED(eraseBack), const wxRect *rect)
e9576ca5 2074{
065ab451
SC
2075 if ( m_peer == NULL )
2076 return ;
8b573fb8 2077
1f1c8bd4
SC
2078 if ( !MacIsReallyShown() )
2079 return ;
789ae0cf 2080
1f1c8bd4 2081 if ( rect )
1e8cde71 2082 {
1f1c8bd4 2083 Rect r ;
898d9035 2084
1f1c8bd4
SC
2085 wxMacRectToNative( rect , &r ) ;
2086 m_peer->SetNeedsDisplay( &r ) ;
facd6764 2087 }
1f1c8bd4 2088 else
9a456218 2089 {
1f1c8bd4 2090 m_peer->SetNeedsDisplay() ;
e9576ca5 2091 }
facd6764
SC
2092}
2093
79392158
SC
2094void wxWindowMac::Freeze()
2095{
2096#if TARGET_API_MAC_OSX
2097 if ( !m_frozenness++ )
2098 {
52ef5c3c
RD
2099 if ( m_peer && m_peer->Ok() )
2100 m_peer->SetDrawingEnabled( false ) ;
79392158
SC
2101 }
2102#endif
2103}
2104
2105void wxWindowMac::Thaw()
2106{
2107#if TARGET_API_MAC_OSX
898d9035 2108 wxASSERT_MSG( m_frozenness > 0, wxT("Thaw() without matching Freeze()") );
79392158
SC
2109
2110 if ( !--m_frozenness )
2111 {
52ef5c3c
RD
2112 if ( m_peer && m_peer->Ok() )
2113 {
2114 m_peer->SetDrawingEnabled( true ) ;
2115 m_peer->InvalidateWithChildren() ;
2116 }
79392158
SC
2117 }
2118#endif
2119}
2120
fd39f7a8
RD
2121bool wxWindowMac::IsFrozen() const
2122{
2123 return m_frozenness != 0;
2124}
2125
e766c8a9 2126wxWindowMac *wxGetActiveWindow()
e9576ca5 2127{
519cb848 2128 // actually this is a windows-only concept
e9576ca5
SC
2129 return NULL;
2130}
2131
e9576ca5 2132// Coordinates relative to the window
89954433 2133void wxWindowMac::WarpPointer(int WXUNUSED(x_pos), int WXUNUSED(y_pos))
e9576ca5 2134{
e40298d5 2135 // We really don't move the mouse programmatically under Mac.
e9576ca5
SC
2136}
2137
facd6764 2138void wxWindowMac::OnEraseBackground(wxEraseEvent& event)
e9576ca5 2139{
3dee36ae
WS
2140 if ( MacGetTopLevelWindow() == NULL )
2141 return ;
af06e625 2142/*
be346c26 2143#if TARGET_API_MAC_OSX
a01d9a25 2144 if ( !m_backgroundColour.Ok() || GetBackgroundStyle() == wxBG_STYLE_TRANSPARENT )
94abc21f 2145 {
94abc21f
SC
2146 }
2147 else
be346c26 2148#endif
af06e625
SC
2149*/
2150 if ( GetBackgroundStyle() == wxBG_STYLE_COLOUR )
7ebf5540 2151 {
8b573fb8 2152 event.GetDC()->Clear() ;
7ebf5540 2153 }
af06e625
SC
2154 else
2155 {
2156 event.Skip() ;
2157 }
1c310985
SC
2158}
2159
2160void wxWindowMac::OnNcPaint( wxNcPaintEvent& event )
2161{
af6b7b80 2162 event.Skip() ;
e9576ca5
SC
2163}
2164
e766c8a9 2165int wxWindowMac::GetScrollPos(int orient) const
e9576ca5 2166{
1c310985
SC
2167 if ( orient == wxHORIZONTAL )
2168 {
2169 if ( m_hScrollBar )
2170 return m_hScrollBar->GetThumbPosition() ;
2171 }
2172 else
2173 {
2174 if ( m_vScrollBar )
2175 return m_vScrollBar->GetThumbPosition() ;
2176 }
e15f0a5e 2177
e9576ca5
SC
2178 return 0;
2179}
2180
2181// This now returns the whole range, not just the number
2182// of positions that we can scroll.
e766c8a9 2183int wxWindowMac::GetScrollRange(int orient) const
e9576ca5 2184{
1c310985
SC
2185 if ( orient == wxHORIZONTAL )
2186 {
2187 if ( m_hScrollBar )
2188 return m_hScrollBar->GetRange() ;
2189 }
2190 else
2191 {
2192 if ( m_vScrollBar )
2193 return m_vScrollBar->GetRange() ;
2194 }
e15f0a5e 2195
e9576ca5
SC
2196 return 0;
2197}
2198
e766c8a9 2199int wxWindowMac::GetScrollThumb(int orient) const
e9576ca5 2200{
1c310985
SC
2201 if ( orient == wxHORIZONTAL )
2202 {
2203 if ( m_hScrollBar )
2204 return m_hScrollBar->GetThumbSize() ;
2205 }
2206 else
2207 {
2208 if ( m_vScrollBar )
2209 return m_vScrollBar->GetThumbSize() ;
2210 }
e15f0a5e 2211
e9576ca5
SC
2212 return 0;
2213}
2214
89954433 2215void wxWindowMac::SetScrollPos(int orient, int pos, bool WXUNUSED(refresh))
e9576ca5 2216{
1c310985 2217 if ( orient == wxHORIZONTAL )
6264b550 2218 {
1c310985
SC
2219 if ( m_hScrollBar )
2220 m_hScrollBar->SetThumbPosition( pos ) ;
6264b550
RR
2221 }
2222 else
2223 {
1c310985
SC
2224 if ( m_vScrollBar )
2225 m_vScrollBar->SetThumbPosition( pos ) ;
6264b550 2226 }
2f1ae414
SC
2227}
2228
c1142003
VZ
2229void
2230wxWindowMac::AlwaysShowScrollbars(bool hflag, bool vflag)
2231{
2232 bool needVisibilityUpdate = false;
2233
2234 if ( m_hScrollBarAlwaysShown != hflag )
2235 {
2236 m_hScrollBarAlwaysShown = hflag;
2237 needVisibilityUpdate = true;
2238 }
2239
2240 if ( m_vScrollBarAlwaysShown != vflag )
2241 {
2242 m_vScrollBarAlwaysShown = vflag;
2243 needVisibilityUpdate = true;
2244 }
2245
2246 if ( needVisibilityUpdate )
2247 DoUpdateScrollbarVisibility();
2248}
6239ee05 2249
c79aad8b
SC
2250//
2251// we draw borders and grow boxes, are already set up and clipped in the current port / cgContextRef
2252// our own window origin is at leftOrigin/rightOrigin
2253//
2254
6239ee05
SC
2255void wxWindowMac::MacPaintGrowBox()
2256{
2257 if ( IsTopLevel() )
2258 return ;
2259
6239ee05
SC
2260 if ( MacHasScrollBarCorner() )
2261 {
2262 Rect rect ;
2263
2264 CGContextRef cgContext = (CGContextRef) MacGetCGContextRef() ;
2265 wxASSERT( cgContext ) ;
2266
2267 m_peer->GetRect( &rect ) ;
2268
2269 int size = m_hScrollBar ? m_hScrollBar->GetSize().y : ( m_vScrollBar ? m_vScrollBar->GetSize().x : MAC_SCROLLBAR_SIZE ) ;
2270 CGRect cgrect = CGRectMake( rect.right - size , rect.bottom - size , size , size ) ;
2271 CGPoint cgpoint = CGPointMake( rect.right - size , rect.bottom - size ) ;
2272 CGContextSaveGState( cgContext );
2273
a01d9a25 2274 if ( m_backgroundColour.Ok() )
6239ee05 2275 {
a01d9a25 2276 CGContextSetFillColorWithColor( cgContext, m_backgroundColour.GetCGColor() );
6239ee05
SC
2277 }
2278 else
2279 {
2280 CGContextSetRGBFillColor( cgContext, 1.0, 1.0 , 1.0 , 1.0 );
2281 }
2282 CGContextFillRect( cgContext, cgrect );
2283 CGContextRestoreGState( cgContext );
2284 }
6239ee05
SC
2285}
2286
89954433 2287void wxWindowMac::MacPaintBorders( int WXUNUSED(leftOrigin) , int WXUNUSED(rightOrigin) )
2f1ae414 2288{
e15f0a5e 2289 if ( IsTopLevel() )
6264b550 2290 return ;
8b573fb8 2291
fd926bcc 2292 Rect rect ;
c79aad8b 2293 bool hasFocus = m_peer->NeedsFocusRect() && m_peer->HasFocus() ;
c79aad8b 2294
8f39b6c4 2295 // back to the surrounding frame rectangle
58603178 2296 m_peer->GetRect( &rect ) ;
8f39b6c4 2297 InsetRect( &rect, -1 , -1 ) ;
fd926bcc 2298
c79aad8b 2299 {
8f39b6c4
SC
2300 CGRect cgrect = CGRectMake( rect.left , rect.top , rect.right - rect.left ,
2301 rect.bottom - rect.top ) ;
2302
c79aad8b 2303 HIThemeFrameDrawInfo info ;
58603178 2304 memset( &info, 0 , sizeof(info) ) ;
902725ee 2305
c79aad8b
SC
2306 info.version = 0 ;
2307 info.kind = 0 ;
2308 info.state = IsEnabled() ? kThemeStateActive : kThemeStateInactive ;
2309 info.isFocused = hasFocus ;
c79aad8b
SC
2310
2311 CGContextRef cgContext = (CGContextRef) GetParent()->MacGetCGContextRef() ;
2312 wxASSERT( cgContext ) ;
902725ee 2313
e15f0a5e 2314 if ( HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER) || HasFlag(wxDOUBLE_BORDER) )
c79aad8b 2315 {
c79aad8b 2316 info.kind = kHIThemeFrameTextFieldSquare ;
8f39b6c4 2317 HIThemeDrawFrame( &cgrect , &info , cgContext , kHIThemeOrientationNormal ) ;
c79aad8b 2318 }
e15f0a5e 2319 else if ( HasFlag(wxSIMPLE_BORDER) )
c79aad8b 2320 {
c79aad8b 2321 info.kind = kHIThemeFrameListBox ;
c79aad8b
SC
2322 HIThemeDrawFrame( &cgrect , &info , cgContext , kHIThemeOrientationNormal ) ;
2323 }
2324 else if ( hasFocus )
2325 {
c79aad8b
SC
2326 HIThemeDrawFocusRect( &cgrect , true , cgContext , kHIThemeOrientationNormal ) ;
2327 }
6239ee05 2328#if 0 // TODO REMOVE now done in a separate call earlier in drawing the window itself
c79aad8b 2329 m_peer->GetRect( &rect ) ;
6239ee05 2330 if ( MacHasScrollBarCorner() )
c79aad8b 2331 {
6239ee05
SC
2332 int variant = (m_hScrollBar == NULL ? m_vScrollBar : m_hScrollBar ) ->GetWindowVariant();
2333 int size = m_hScrollBar ? m_hScrollBar->GetSize().y : ( m_vScrollBar ? m_vScrollBar->GetSize().x : MAC_SCROLLBAR_SIZE ) ;
8f39b6c4
SC
2334 CGRect cgrect = CGRectMake( rect.right - size , rect.bottom - size , size , size ) ;
2335 CGPoint cgpoint = CGPointMake( rect.right - size , rect.bottom - size ) ;
902725ee 2336 HIThemeGrowBoxDrawInfo info ;
e15f0a5e 2337 memset( &info, 0, sizeof(info) ) ;
c79aad8b
SC
2338 info.version = 0 ;
2339 info.state = IsEnabled() ? kThemeStateActive : kThemeStateInactive ;
2340 info.kind = kHIThemeGrowBoxKindNone ;
6239ee05 2341 // contrary to the docs ...SizeSmall does not work
c79aad8b 2342 info.size = kHIThemeGrowBoxSizeNormal ;
6239ee05 2343 info.direction = 0 ;
c79aad8b
SC
2344 HIThemeDrawGrowBox( &cgpoint , &info , cgContext , kHIThemeOrientationNormal ) ;
2345 }
6239ee05 2346#endif
c79aad8b 2347 }
8208e181
SC
2348}
2349
abda5788
SC
2350void wxWindowMac::RemoveChild( wxWindowBase *child )
2351{
2352 if ( child == m_hScrollBar )
2353 m_hScrollBar = NULL ;
2354 if ( child == m_vScrollBar )
2355 m_vScrollBar = NULL ;
14c9cbdb 2356
abda5788
SC
2357 wxWindowBase::RemoveChild( child ) ;
2358}
2359
c1142003 2360void wxWindowMac::DoUpdateScrollbarVisibility()
e9576ca5 2361{
42cc0b31 2362 bool triggerSizeEvent = false;
58603178 2363
c1142003 2364 if ( m_hScrollBar )
e40298d5 2365 {
c1142003 2366 bool showHScrollBar = m_hScrollBarAlwaysShown || m_hScrollBar->IsNeeded();
e15f0a5e 2367
c1142003
VZ
2368 if ( m_hScrollBar->IsShown() != showHScrollBar )
2369 {
2370 m_hScrollBar->Show( showHScrollBar );
2371 triggerSizeEvent = true;
6264b550 2372 }
e40298d5 2373 }
c1142003
VZ
2374
2375 if ( m_vScrollBar)
e40298d5 2376 {
c1142003 2377 bool showVScrollBar = m_vScrollBarAlwaysShown || m_vScrollBar->IsNeeded();
e15f0a5e 2378
c1142003
VZ
2379 if ( m_vScrollBar->IsShown() != showVScrollBar )
2380 {
2381 m_vScrollBar->Show( showVScrollBar ) ;
2382 triggerSizeEvent = true;
6264b550 2383 }
e40298d5 2384 }
e15f0a5e 2385
e40298d5 2386 MacRepositionScrollBars() ;
42cc0b31
SC
2387 if ( triggerSizeEvent )
2388 {
2389 wxSizeEvent event(GetSize(), m_windowId);
2390 event.SetEventObject(this);
937013e0 2391 HandleWindowEvent(event);
42cc0b31 2392 }
e9576ca5
SC
2393}
2394
c1142003
VZ
2395// New function that will replace some of the above.
2396void wxWindowMac::SetScrollbar(int orient, int pos, int thumb,
2397 int range, bool refresh)
2398{
2399 if ( orient == wxHORIZONTAL && m_hScrollBar )
2400 m_hScrollBar->SetScrollbar(pos, thumb, range, thumb, refresh);
2401 else if ( orient == wxVERTICAL && m_vScrollBar )
2402 m_vScrollBar->SetScrollbar(pos, thumb, range, thumb, refresh);
2403
2404 DoUpdateScrollbarVisibility();
2405}
2406
e9576ca5 2407// Does a physical scroll
e766c8a9 2408void wxWindowMac::ScrollWindow(int dx, int dy, const wxRect *rect)
e9576ca5 2409{
898d9035 2410 if ( dx == 0 && dy == 0 )
ba87f54c 2411 return ;
8b573fb8 2412
3dee36ae
WS
2413 int width , height ;
2414 GetClientSize( &width , &height ) ;
e15f0a5e 2415
902725ee 2416 {
002c9672 2417 // note there currently is a bug in OSX which makes inefficient refreshes in case an entire control
8b573fb8 2418 // area is scrolled, this does not occur if width and height are 2 pixels less,
58603178 2419 // TODO: write optimal workaround
898d9035 2420 wxRect scrollrect( MacGetLeftBorderSize() , MacGetTopBorderSize() , width , height ) ;
8b573fb8 2421 if ( rect )
5ca0d812 2422 scrollrect.Intersect( *rect ) ;
e15f0a5e 2423
5ca0d812 2424 if ( m_peer->GetNeedsDisplay() )
002c9672 2425 {
58603178 2426 // because HIViewScrollRect does not scroll the already invalidated area we have two options:
8dd37b03 2427 // in case there is already a pending redraw on that area
002c9672
SC
2428 // either immediate redraw or full invalidate
2429#if 1
2430 // is the better overall solution, as it does not slow down scrolling
1f1c8bd4 2431 m_peer->SetNeedsDisplay() ;
002c9672 2432#else
8b573fb8 2433 // this would be the preferred version for fast drawing controls
80f3f3be 2434 HIViewRender(m_peer->GetControlRef()) ;
002c9672
SC
2435#endif
2436 }
e15f0a5e 2437
84e5d27d
SC
2438 // as the native control might be not a 0/0 wx window coordinates, we have to offset
2439 scrollrect.Offset( -MacGetLeftBorderSize() , -MacGetTopBorderSize() ) ;
898d9035 2440 m_peer->ScrollRect( &scrollrect , dx , dy ) ;
92346151 2441
92346151 2442#if 0
902725ee 2443 // this would be the preferred version for fast drawing controls
4f74e0d1 2444 HIViewRender(m_peer->GetControlRef()) ;
92346151 2445#endif
902725ee 2446 }
6ed71b4f 2447
e15f0a5e
DS
2448 wxWindowMac *child;
2449 int x, y, w, h;
71f2fb52 2450 for (wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); node; node = node->GetNext())
6264b550 2451 {
e15f0a5e
DS
2452 child = node->GetData();
2453 if (child == NULL)
2454 continue;
2455 if (child == m_vScrollBar)
2456 continue;
2457 if (child == m_hScrollBar)
2458 continue;
2459 if (child->IsTopLevel())
2460 continue;
6ed71b4f 2461
6264b550 2462 child->GetPosition( &x, &y );
6264b550 2463 child->GetSize( &w, &h );
00f55394
SC
2464 if (rect)
2465 {
e15f0a5e
DS
2466 wxRect rc( x, y, w, h );
2467 if (rect->Intersects( rc ))
8d1547ef 2468 child->SetSize( x + dx, y + dy, w, h, wxSIZE_AUTO|wxSIZE_ALLOW_MINUS_ONE );
00f55394
SC
2469 }
2470 else
2471 {
8d1547ef 2472 child->SetSize( x + dx, y + dy, w, h, wxSIZE_AUTO|wxSIZE_ALLOW_MINUS_ONE );
8b573fb8 2473 }
6264b550 2474 }
e9576ca5
SC
2475}
2476
e15f0a5e 2477void wxWindowMac::MacOnScroll( wxScrollEvent &event )
7c74e7fe 2478{
687706f5 2479 if ( event.GetEventObject() == m_vScrollBar || event.GetEventObject() == m_hScrollBar )
6264b550
RR
2480 {
2481 wxScrollWinEvent wevent;
2482 wevent.SetPosition(event.GetPosition());
2483 wevent.SetOrientation(event.GetOrientation());
687706f5
KH
2484 wevent.SetEventObject(this);
2485
2486 if (event.GetEventType() == wxEVT_SCROLL_TOP)
2487 wevent.SetEventType( wxEVT_SCROLLWIN_TOP );
2488 else if (event.GetEventType() == wxEVT_SCROLL_BOTTOM)
2489 wevent.SetEventType( wxEVT_SCROLLWIN_BOTTOM );
2490 else if (event.GetEventType() == wxEVT_SCROLL_LINEUP)
2491 wevent.SetEventType( wxEVT_SCROLLWIN_LINEUP );
2492 else if (event.GetEventType() == wxEVT_SCROLL_LINEDOWN)
2493 wevent.SetEventType( wxEVT_SCROLLWIN_LINEDOWN );
2494 else if (event.GetEventType() == wxEVT_SCROLL_PAGEUP)
2495 wevent.SetEventType( wxEVT_SCROLLWIN_PAGEUP );
2496 else if (event.GetEventType() == wxEVT_SCROLL_PAGEDOWN)
2497 wevent.SetEventType( wxEVT_SCROLLWIN_PAGEDOWN );
2498 else if (event.GetEventType() == wxEVT_SCROLL_THUMBTRACK)
2499 wevent.SetEventType( wxEVT_SCROLLWIN_THUMBTRACK );
2500 else if (event.GetEventType() == wxEVT_SCROLL_THUMBRELEASE)
2501 wevent.SetEventType( wxEVT_SCROLLWIN_THUMBRELEASE );
6ed71b4f 2502
937013e0 2503 HandleWindowEvent(wevent);
7c74e7fe
SC
2504 }
2505}
2506
e9576ca5 2507// Get the window with the focus
0fe02759 2508wxWindowMac *wxWindowBase::DoFindFocus()
e9576ca5 2509{
f1d527c1
SC
2510 ControlRef control ;
2511 GetKeyboardFocus( GetUserFocusWindow() , &control ) ;
2512 return wxFindControlFromMacControl( control ) ;
519cb848
SC
2513}
2514
e39af974 2515void wxWindowMac::OnInternalIdle()
e9576ca5 2516{
e9576ca5
SC
2517 // This calls the UI-update mechanism (querying windows for
2518 // menu/toolbar/control state information)
6239ee05 2519 if (wxUpdateUIEvent::CanUpdate(this) && IsShown())
e39af974 2520 UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
e9576ca5
SC
2521}
2522
2523// Raise the window to the top of the Z order
e766c8a9 2524void wxWindowMac::Raise()
e9576ca5 2525{
5ca0d812 2526 m_peer->SetZOrder( true , NULL ) ;
e9576ca5
SC
2527}
2528
2529// Lower the window to the bottom of the Z order
e766c8a9 2530void wxWindowMac::Lower()
e9576ca5 2531{
5ca0d812 2532 m_peer->SetZOrder( false , NULL ) ;
e9576ca5
SC
2533}
2534
facd6764 2535// static wxWindow *gs_lastWhich = NULL;
519cb848 2536
e15f0a5e 2537bool wxWindowMac::MacSetupCursor( const wxPoint& pt )
467e3168
SC
2538{
2539 // first trigger a set cursor event
6ed71b4f 2540
467e3168
SC
2541 wxPoint clientorigin = GetClientAreaOrigin() ;
2542 wxSize clientsize = GetClientSize() ;
2543 wxCursor cursor ;
2544 if ( wxRect2DInt( clientorigin.x , clientorigin.y , clientsize.x , clientsize.y ).Contains( wxPoint2DInt( pt ) ) )
7de59551 2545 {
467e3168 2546 wxSetCursorEvent event( pt.x , pt.y );
6ed71b4f 2547
937013e0 2548 bool processedEvtSetCursor = HandleWindowEvent(event);
467e3168
SC
2549 if ( processedEvtSetCursor && event.HasCursor() )
2550 {
e40298d5 2551 cursor = event.GetCursor() ;
467e3168
SC
2552 }
2553 else
2554 {
467e3168
SC
2555 // the test for processedEvtSetCursor is here to prevent using m_cursor
2556 // if the user code caught EVT_SET_CURSOR() and returned nothing from
2557 // it - this is a way to say that our cursor shouldn't be used for this
2558 // point
2559 if ( !processedEvtSetCursor && m_cursor.Ok() )
467e3168 2560 cursor = m_cursor ;
e15f0a5e
DS
2561
2562 if ( !wxIsBusy() && !GetParent() )
2563 cursor = *wxSTANDARD_CURSOR ;
467e3168 2564 }
e15f0a5e 2565
467e3168
SC
2566 if ( cursor.Ok() )
2567 cursor.MacInstall() ;
2568 }
e15f0a5e 2569
467e3168
SC
2570 return cursor.Ok() ;
2571}
2572
89954433 2573wxString wxWindowMac::MacGetToolTipString( wxPoint &WXUNUSED(pt) )
2f1ae414 2574{
5e0526df 2575#if wxUSE_TOOLTIPS
6264b550 2576 if ( m_tooltip )
6264b550 2577 return m_tooltip->GetTip() ;
5e0526df 2578#endif
e15f0a5e 2579
427ff662 2580 return wxEmptyString ;
2f1ae414 2581}
6264b550 2582
cb4b0966
SC
2583void wxWindowMac::ClearBackground()
2584{
2585 Refresh() ;
2586 Update() ;
2587}
2588
1c310985 2589void wxWindowMac::Update()
519cb848 2590{
5bcdf503
JS
2591 wxTopLevelWindowMac* top = MacGetTopLevelWindow();
2592 if (top)
2593 top->MacPerformUpdates() ;
519cb848
SC
2594}
2595
14c9cbdb 2596wxTopLevelWindowMac* wxWindowMac::MacGetTopLevelWindow() const
519cb848 2597{
1c310985 2598 wxTopLevelWindowMac* win = NULL ;
facd6764 2599 WindowRef window = (WindowRef) MacGetTopLevelWindowRef() ;
1c310985 2600 if ( window )
1c310985 2601 win = wxFindWinFromMacWindow( window ) ;
e15f0a5e 2602
1c310985 2603 return win ;
519cb848 2604}
5c840e5b 2605
902725ee 2606const wxRect& wxWindowMac::MacGetClippedClientRect() const
e905b636
SC
2607{
2608 MacUpdateClippedRects() ;
e15f0a5e 2609
e905b636
SC
2610 return m_cachedClippedClientRect ;
2611}
2612
902725ee 2613const wxRect& wxWindowMac::MacGetClippedRect() const
5c840e5b
SC
2614{
2615 MacUpdateClippedRects() ;
e15f0a5e 2616
5c840e5b
SC
2617 return m_cachedClippedRect ;
2618}
2619
902725ee 2620const wxRect&wxWindowMac:: MacGetClippedRectWithOuterStructure() const
5c840e5b
SC
2621{
2622 MacUpdateClippedRects() ;
e15f0a5e 2623
5c840e5b
SC
2624 return m_cachedClippedRectWithOuterStructure ;
2625}
2626
2627const wxRegion& wxWindowMac::MacGetVisibleRegion( bool includeOuterStructures )
94abc21f 2628{
5c840e5b 2629 static wxRegion emptyrgn ;
898d9035 2630
5c840e5b
SC
2631 if ( !m_isBeingDeleted && MacIsReallyShown() /*m_peer->IsVisible() */ )
2632 {
2633 MacUpdateClippedRects() ;
2634 if ( includeOuterStructures )
2635 return m_cachedClippedRegionWithOuterStructure ;
2636 else
2637 return m_cachedClippedRegion ;
2638 }
2639 else
2640 {
2641 return emptyrgn ;
2642 }
2643}
2644
2645void wxWindowMac::MacUpdateClippedRects() const
2646{
2647 if ( m_cachedClippedRectValid )
2648 return ;
2649
0fa8508d
SC
2650 // includeOuterStructures is true if we try to draw somthing like a focus ring etc.
2651 // also a window dc uses this, in this case we only clip in the hierarchy for hard
2652 // borders like a scrollwindow, splitter etc otherwise we end up in a paranoia having
2653 // to add focus borders everywhere
8b573fb8 2654
e15f0a5e 2655 Rect r, rIncludingOuterStructures ;
902725ee 2656
5c840e5b
SC
2657 m_peer->GetRect( &r ) ;
2658 r.left -= MacGetLeftBorderSize() ;
2659 r.top -= MacGetTopBorderSize() ;
2660 r.bottom += MacGetBottomBorderSize() ;
2661 r.right += MacGetRightBorderSize() ;
2662
2663 r.right -= r.left ;
2664 r.bottom -= r.top ;
2665 r.left = 0 ;
2666 r.top = 0 ;
2667
2668 rIncludingOuterStructures = r ;
2669 InsetRect( &rIncludingOuterStructures , -4 , -4 ) ;
902725ee 2670
e905b636
SC
2671 wxRect cl = GetClientRect() ;
2672 Rect rClient = { cl.y , cl.x , cl.y + cl.height , cl.x + cl.width } ;
902725ee 2673
e15f0a5e
DS
2674 int x , y ;
2675 wxSize size ;
e905b636
SC
2676 const wxWindow* child = this ;
2677 const wxWindow* parent = NULL ;
898d9035 2678
e15f0a5e 2679 while ( !child->IsTopLevel() && ( parent = child->GetParent() ) != NULL )
e40298d5 2680 {
e905b636 2681 if ( parent->MacIsChildOfClientArea(child) )
94abc21f 2682 {
e905b636
SC
2683 size = parent->GetClientSize() ;
2684 wxPoint origin = parent->GetClientAreaOrigin() ;
2685 x = origin.x ;
2686 y = origin.y ;
2687 }
2688 else
2689 {
2690 // this will be true for scrollbars, toolbars etc.
2691 size = parent->GetSize() ;
2692 y = parent->MacGetTopBorderSize() ;
2693 x = parent->MacGetLeftBorderSize() ;
2694 size.x -= parent->MacGetLeftBorderSize() + parent->MacGetRightBorderSize() ;
2695 size.y -= parent->MacGetTopBorderSize() + parent->MacGetBottomBorderSize() ;
2696 }
21f9e953 2697
e905b636
SC
2698 parent->MacWindowToRootWindow( &x, &y ) ;
2699 MacRootWindowToWindow( &x , &y ) ;
21f9e953 2700
e905b636 2701 Rect rparent = { y , x , y + size.y , x + size.x } ;
5c840e5b 2702
e905b636
SC
2703 // the wxwindow and client rects will always be clipped
2704 SectRect( &r , &rparent , &r ) ;
2705 SectRect( &rClient , &rparent , &rClient ) ;
5c840e5b 2706
e905b636
SC
2707 // the structure only at 'hard' borders
2708 if ( parent->MacClipChildren() ||
2709 ( parent->GetParent() && parent->GetParent()->MacClipGrandChildren() ) )
2710 {
2711 SectRect( &rIncludingOuterStructures , &rparent , &rIncludingOuterStructures ) ;
94abc21f 2712 }
e15f0a5e 2713
e905b636 2714 child = parent ;
e40298d5 2715 }
902725ee 2716
5c840e5b 2717 m_cachedClippedRect = wxRect( r.left , r.top , r.right - r.left , r.bottom - r.top ) ;
902725ee 2718 m_cachedClippedClientRect = wxRect( rClient.left , rClient.top ,
e905b636 2719 rClient.right - rClient.left , rClient.bottom - rClient.top ) ;
902725ee
WS
2720 m_cachedClippedRectWithOuterStructure = wxRect(
2721 rIncludingOuterStructures.left , rIncludingOuterStructures.top ,
2722 rIncludingOuterStructures.right - rIncludingOuterStructures.left ,
5c840e5b 2723 rIncludingOuterStructures.bottom - rIncludingOuterStructures.top ) ;
902725ee 2724
5c840e5b
SC
2725 m_cachedClippedRegionWithOuterStructure = wxRegion( m_cachedClippedRectWithOuterStructure ) ;
2726 m_cachedClippedRegion = wxRegion( m_cachedClippedRect ) ;
e905b636 2727 m_cachedClippedClientRegion = wxRegion( m_cachedClippedClientRect ) ;
902725ee 2728
5c840e5b 2729 m_cachedClippedRectValid = true ;
94abc21f
SC
2730}
2731
facd6764
SC
2732/*
2733 This function must not change the updatergn !
2734 */
8e181eae 2735bool wxWindowMac::MacDoRedraw( void* updatergnr , long time )
519cb848 2736{
facd6764 2737 bool handled = false ;
42ef83fa 2738 Rect updatebounds ;
e15f0a5e 2739 RgnHandle updatergn = (RgnHandle) updatergnr ;
42ef83fa 2740 GetRegionBounds( updatergn , &updatebounds ) ;
20b69855 2741
e15f0a5e 2742 // wxLogDebug(wxT("update for %s bounds %d, %d, %d, %d"), wxString(GetClassInfo()->GetClassName()).c_str(), updatebounds.left, updatebounds.top , updatebounds.right , updatebounds.bottom ) ;
c79aad8b 2743
902725ee 2744 if ( !EmptyRgn(updatergn) )
6264b550 2745 {
1c310985
SC
2746 RgnHandle newupdate = NewRgn() ;
2747 wxSize point = GetClientSize() ;
2748 wxPoint origin = GetClientAreaOrigin() ;
e15f0a5e 2749 SetRectRgn( newupdate , origin.x , origin.y , origin.x + point.x , origin.y + point.y ) ;
facd6764 2750 SectRgn( newupdate , updatergn , newupdate ) ;
8b573fb8 2751
eec462f8
SC
2752 // first send an erase event to the entire update area
2753 {
c79aad8b
SC
2754 // for the toplevel window this really is the entire area
2755 // for all the others only their client area, otherwise they
2756 // might be drawing with full alpha and eg put blue into
2757 // the grow-box area of a scrolled window (scroll sample)
5c840e5b 2758 wxDC* dc = new wxWindowDC(this);
c79aad8b 2759 if ( IsTopLevel() )
8e181eae 2760 dc->SetClippingRegion(wxRegion(HIShapeCreateWithQDRgn(updatergn)));
c79aad8b 2761 else
8e181eae 2762 dc->SetClippingRegion(wxRegion(HIShapeCreateWithQDRgn(newupdate)));
902725ee 2763
c79aad8b 2764 wxEraseEvent eevent( GetId(), dc );
42ef83fa 2765 eevent.SetEventObject( this );
937013e0 2766 HandleWindowEvent( eevent );
c79aad8b 2767 delete dc ;
eec462f8 2768 }
8b573fb8 2769
6239ee05
SC
2770 MacPaintGrowBox();
2771
42ef83fa 2772 // calculate a client-origin version of the update rgn and set m_updateRegion to that
1c310985 2773 OffsetRgn( newupdate , -origin.x , -origin.y ) ;
8e181eae 2774 m_updateRegion = wxRegion(HIShapeCreateWithQDRgn(newupdate)) ;
8b573fb8 2775 DisposeRgn( newupdate ) ;
6ed71b4f 2776
1c310985 2777 if ( !m_updateRegion.Empty() )
6264b550 2778 {
facd6764 2779 // paint the window itself
ff3795ee 2780
e40298d5 2781 wxPaintEvent event;
687706f5 2782 event.SetTimestamp(time);
e40298d5 2783 event.SetEventObject(this);
937013e0 2784 HandleWindowEvent(event);
ff3795ee 2785 handled = true ;
eec462f8 2786 }
8b573fb8 2787
eec462f8
SC
2788 // now we cannot rely on having its borders drawn by a window itself, as it does not
2789 // get the updateRgn wide enough to always do so, so we do it from the parent
2790 // this would also be the place to draw any custom backgrounds for native controls
2791 // in Composited windowing
36d7f54e 2792 wxPoint clientOrigin = GetClientAreaOrigin() ;
8b573fb8 2793
e15f0a5e
DS
2794 wxWindowMac *child;
2795 int x, y, w, h;
71f2fb52 2796 for (wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); node; node = node->GetNext())
eec462f8 2797 {
e15f0a5e
DS
2798 child = node->GetData();
2799 if (child == NULL)
2800 continue;
2801 if (child == m_vScrollBar)
2802 continue;
2803 if (child == m_hScrollBar)
2804 continue;
2805 if (child->IsTopLevel())
2806 continue;
2807 if (!child->IsShown())
2808 continue;
fe779e40 2809
c79aad8b
SC
2810 // only draw those in the update region (add a safety margin of 10 pixels for shadow effects
2811
af6b7b80 2812 child->GetPosition( &x, &y );
af6b7b80
SC
2813 child->GetSize( &w, &h );
2814 Rect childRect = { y , x , y + h , x + w } ;
36d7f54e 2815 OffsetRect( &childRect , clientOrigin.x , clientOrigin.y ) ;
c79aad8b
SC
2816 InsetRect( &childRect , -10 , -10) ;
2817
2818 if ( RectInRgn( &childRect , updatergn ) )
eec462f8 2819 {
c79aad8b
SC
2820 // paint custom borders
2821 wxNcPaintEvent eventNc( child->GetId() );
2822 eventNc.SetEventObject( child );
937013e0 2823 if ( !child->HandleWindowEvent( eventNc ) )
eec462f8 2824 {
4f74e0d1 2825 child->MacPaintBorders(0, 0) ;
eec462f8 2826 }
8b573fb8 2827 }
14c9cbdb 2828 }
6264b550 2829 }
e15f0a5e 2830
facd6764
SC
2831 return handled ;
2832}
6ed71b4f 2833
519cb848 2834
facd6764 2835WXWindow wxWindowMac::MacGetTopLevelWindowRef() const
519cb848 2836{
6264b550 2837 wxWindowMac *iter = (wxWindowMac*)this ;
14c9cbdb 2838
e15f0a5e 2839 while ( iter )
6264b550 2840 {
1c310985 2841 if ( iter->IsTopLevel() )
6239ee05
SC
2842 {
2843 wxTopLevelWindow* toplevel = wxDynamicCast(iter,wxTopLevelWindow);
2844 if ( toplevel )
2845 return toplevel->MacGetWindowRef();
2846#if wxUSE_POPUPWIN
2847 wxPopupWindow* popupwin = wxDynamicCast(iter,wxPopupWindow);
2848 if ( popupwin )
2849 return popupwin->MacGetPopupWindowRef();
2850#endif
2851 }
6264b550 2852 iter = iter->GetParent() ;
14c9cbdb 2853 }
e15f0a5e 2854
6264b550 2855 return NULL ;
519cb848
SC
2856}
2857
6239ee05
SC
2858bool wxWindowMac::MacHasScrollBarCorner() const
2859{
2860 /* Returns whether the scroll bars in a wxScrolledWindow should be
2861 * shortened. Scroll bars should be shortened if either:
2862 *
2863 * - both scroll bars are visible, or
2864 *
2865 * - there is a resize box in the parent frame's corner and this
2866 * window shares the bottom and right edge with the parent
2867 * frame.
2868 */
2869
2870 if ( m_hScrollBar == NULL && m_vScrollBar == NULL )
2871 return false;
2872
2873 if ( ( m_hScrollBar && m_hScrollBar->IsShown() )
2874 && ( m_vScrollBar && m_vScrollBar->IsShown() ) )
2875 {
2876 // Both scroll bars visible
2877 return true;
2878 }
2879 else
2880 {
2881 wxPoint thisWindowBottomRight = GetScreenRect().GetBottomRight();
2882
2883 for ( const wxWindow *win = this; win; win = win->GetParent() )
2884 {
2885 const wxFrame *frame = wxDynamicCast( win, wxFrame ) ;
2886 if ( frame )
2887 {
2888 if ( frame->GetWindowStyleFlag() & wxRESIZE_BORDER )
2889 {
2890 // Parent frame has resize handle
2891 wxPoint frameBottomRight = frame->GetScreenRect().GetBottomRight();
2892
2893 // Note: allow for some wiggle room here as wxMac's
2894 // window rect calculations seem to be imprecise
2895 if ( abs( thisWindowBottomRight.x - frameBottomRight.x ) <= 2
2896 && abs( thisWindowBottomRight.y - frameBottomRight.y ) <= 2 )
2897 {
2898 // Parent frame has resize handle and shares
2899 // right bottom corner
2900 return true ;
2901 }
2902 else
2903 {
2904 // Parent frame has resize handle but doesn't
2905 // share right bottom corner
2906 return false ;
2907 }
2908 }
2909 else
2910 {
2911 // Parent frame doesn't have resize handle
2912 return false ;
2913 }
2914 }
2915 }
2916
2917 // No parent frame found
2918 return false ;
2919 }
2920}
2921
14c9cbdb 2922void wxWindowMac::MacCreateScrollBars( long style )
519cb848 2923{
427ff662 2924 wxASSERT_MSG( m_vScrollBar == NULL && m_hScrollBar == NULL , wxT("attempt to create window twice") ) ;
14c9cbdb 2925
aa99e0cd
SC
2926 if ( style & ( wxVSCROLL | wxHSCROLL ) )
2927 {
db7a550b 2928 int scrlsize = MAC_SCROLLBAR_SIZE ;
8b573fb8
VZ
2929 if ( GetWindowVariant() == wxWINDOW_VARIANT_SMALL || GetWindowVariant() == wxWINDOW_VARIANT_MINI )
2930 {
2931 scrlsize = MAC_SMALL_SCROLLBAR_SIZE ;
8b573fb8 2932 }
db7a550b 2933
6239ee05 2934 int adjust = MacHasScrollBarCorner() ? scrlsize - 1: 0 ;
aa99e0cd
SC
2935 int width, height ;
2936 GetClientSize( &width , &height ) ;
2937
898d9035 2938 wxPoint vPoint(width - scrlsize, 0) ;
db7a550b 2939 wxSize vSize(scrlsize, height - adjust) ;
fbc1d11b
DS
2940 wxPoint hPoint(0, height - scrlsize) ;
2941 wxSize hSize(width - adjust, scrlsize) ;
aa99e0cd 2942
6239ee05 2943 // we have to set the min size to a smaller value, otherwise they cannot get smaller (InitialSize sets MinSize)
aa99e0cd 2944 if ( style & wxVSCROLL )
6239ee05
SC
2945 {
2946 m_vScrollBar = new wxScrollBar((wxWindow*)this, wxID_ANY, vPoint, vSize , wxVERTICAL);
2947 m_vScrollBar->SetMinSize( wxDefaultSize );
2948 }
aa99e0cd
SC
2949
2950 if ( style & wxHSCROLL )
6239ee05
SC
2951 {
2952 m_hScrollBar = new wxScrollBar((wxWindow*)this, wxID_ANY, hPoint, hSize , wxHORIZONTAL);
2953 m_hScrollBar->SetMinSize( wxDefaultSize );
2954 }
aa99e0cd 2955 }
aa99e0cd 2956
6264b550 2957 // because the create does not take into account the client area origin
e15f0a5e
DS
2958 // we might have a real position shift
2959 MacRepositionScrollBars() ;
519cb848
SC
2960}
2961
e905b636
SC
2962bool wxWindowMac::MacIsChildOfClientArea( const wxWindow* child ) const
2963{
fbc1d11b
DS
2964 bool result = ((child == NULL) || ((child != m_hScrollBar) && (child != m_vScrollBar)));
2965
2966 return result ;
e905b636
SC
2967}
2968
e766c8a9 2969void wxWindowMac::MacRepositionScrollBars()
519cb848 2970{
aa99e0cd
SC
2971 if ( !m_hScrollBar && !m_vScrollBar )
2972 return ;
8b573fb8 2973
db7a550b 2974 int scrlsize = m_hScrollBar ? m_hScrollBar->GetSize().y : ( m_vScrollBar ? m_vScrollBar->GetSize().x : MAC_SCROLLBAR_SIZE ) ;
6239ee05 2975 int adjust = MacHasScrollBarCorner() ? scrlsize - 1 : 0 ;
14c9cbdb 2976
6264b550 2977 // get real client area
e15f0a5e
DS
2978 int width, height ;
2979 GetSize( &width , &height );
6264b550
RR
2980
2981 width -= MacGetLeftBorderSize() + MacGetRightBorderSize();
2982 height -= MacGetTopBorderSize() + MacGetBottomBorderSize();
14c9cbdb 2983
e15f0a5e
DS
2984 wxPoint vPoint( width - scrlsize, 0 ) ;
2985 wxSize vSize( scrlsize, height - adjust ) ;
2986 wxPoint hPoint( 0 , height - scrlsize ) ;
2987 wxSize hSize( width - adjust, scrlsize ) ;
2988
2989#if 0
2990 int x = 0, y = 0, w, h ;
facd6764 2991 GetSize( &w , &h ) ;
14c9cbdb 2992
6264b550
RR
2993 MacClientToRootWindow( &x , &y ) ;
2994 MacClientToRootWindow( &w , &h ) ;
14c9cbdb 2995
6264b550 2996 wxWindowMac *iter = (wxWindowMac*)this ;
14c9cbdb 2997
6264b550 2998 int totW = 10000 , totH = 10000;
e15f0a5e 2999 while ( iter )
6264b550 3000 {
1c310985 3001 if ( iter->IsTopLevel() )
6264b550 3002 {
facd6764 3003 iter->GetSize( &totW , &totH ) ;
6264b550
RR
3004 break ;
3005 }
3006
3007 iter = iter->GetParent() ;
14c9cbdb
RD
3008 }
3009
6264b550
RR
3010 if ( x == 0 )
3011 {
3012 hPoint.x = -1 ;
3013 hSize.x += 1 ;
3014 }
3015 if ( y == 0 )
3016 {
3017 vPoint.y = -1 ;
3018 vSize.y += 1 ;
3019 }
14c9cbdb 3020
e15f0a5e 3021 if ( w - x >= totW )
6264b550
RR
3022 {
3023 hSize.x += 1 ;
3024 vPoint.x += 1 ;
3025 }
e15f0a5e 3026 if ( h - y >= totH )
6264b550
RR
3027 {
3028 vSize.y += 1 ;
3029 hPoint.y += 1 ;
3030 }
e15f0a5e
DS
3031#endif
3032
6264b550 3033 if ( m_vScrollBar )
e15f0a5e 3034 m_vScrollBar->SetSize( vPoint.x , vPoint.y, vSize.x, vSize.y , wxSIZE_ALLOW_MINUS_ONE );
6264b550 3035 if ( m_hScrollBar )
e15f0a5e 3036 m_hScrollBar->SetSize( hPoint.x , hPoint.y, hSize.x, hSize.y, wxSIZE_ALLOW_MINUS_ONE );
519cb848
SC
3037}
3038
e766c8a9 3039bool wxWindowMac::AcceptsFocus() const
7c551d95
SC
3040{
3041 return MacCanFocus() && wxWindowBase::AcceptsFocus();
3042}
519cb848 3043
14c9cbdb 3044void wxWindowMac::MacSuperChangedPosition()
519cb848 3045{
6264b550 3046 // only window-absolute structures have to be moved i.e. controls
519cb848 3047
e15f0a5e
DS
3048 m_cachedClippedRectValid = false ;
3049
3050 wxWindowMac *child;
71f2fb52 3051 wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
6264b550
RR
3052 while ( node )
3053 {
e15f0a5e 3054 child = node->GetData();
6264b550 3055 child->MacSuperChangedPosition() ;
e15f0a5e 3056
eb22f2a6 3057 node = node->GetNext();
6264b550 3058 }
519cb848 3059}
519cb848 3060
14c9cbdb 3061void wxWindowMac::MacTopLevelWindowChangedPosition()
a3bf4a62 3062{
6264b550 3063 // only screen-absolute structures have to be moved i.e. glcanvas
a3bf4a62 3064
e15f0a5e 3065 wxWindowMac *child;
71f2fb52 3066 wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
6264b550
RR
3067 while ( node )
3068 {
e15f0a5e 3069 child = node->GetData();
6264b550 3070 child->MacTopLevelWindowChangedPosition() ;
e15f0a5e 3071
eb22f2a6 3072 node = node->GetNext();
6264b550 3073 }
a3bf4a62 3074}
facd6764 3075
e15f0a5e 3076long wxWindowMac::MacGetLeftBorderSize() const
2f1ae414 3077{
e15f0a5e 3078 if ( IsTopLevel() )
6264b550 3079 return 0 ;
2f1ae414 3080
8f39b6c4 3081 SInt32 border = 0 ;
902725ee 3082
e15f0a5e 3083 if (HasFlag(wxRAISED_BORDER) || HasFlag( wxSUNKEN_BORDER) || HasFlag(wxDOUBLE_BORDER))
2f1ae414 3084 {
fbc1d11b 3085 // this metric is only the 'outset' outside the simple frame rect
8f39b6c4 3086 GetThemeMetric( kThemeMetricEditTextFrameOutset , &border ) ;
fbc1d11b 3087 border += 1 ;
2f1ae414 3088 }
8f39b6c4 3089 else if (HasFlag(wxSIMPLE_BORDER))
2f1ae414 3090 {
fbc1d11b 3091 // this metric is only the 'outset' outside the simple frame rect
8f39b6c4 3092 GetThemeMetric( kThemeMetricListBoxFrameOutset , &border ) ;
fbc1d11b 3093 border += 1 ;
2f1ae414 3094 }
e15f0a5e 3095
8f39b6c4 3096 return border ;
2f1ae414
SC
3097}
3098
e15f0a5e 3099long wxWindowMac::MacGetRightBorderSize() const
5b781a67 3100{
1c310985
SC
3101 // they are all symmetric in mac themes
3102 return MacGetLeftBorderSize() ;
5b781a67
SC
3103}
3104
e15f0a5e 3105long wxWindowMac::MacGetTopBorderSize() const
5b781a67 3106{
1c310985
SC
3107 // they are all symmetric in mac themes
3108 return MacGetLeftBorderSize() ;
5b781a67
SC
3109}
3110
e15f0a5e 3111long wxWindowMac::MacGetBottomBorderSize() const
5b781a67 3112{
1c310985
SC
3113 // they are all symmetric in mac themes
3114 return MacGetLeftBorderSize() ;
5b781a67
SC
3115}
3116
14c9cbdb 3117long wxWindowMac::MacRemoveBordersFromStyle( long style )
2f1ae414 3118{
055a486b 3119 return style & ~wxBORDER_MASK ;
2f1ae414 3120}
0a67a93b 3121
e766c8a9 3122// Find the wxWindowMac at the current mouse position, returning the mouse
3723b7b1 3123// position.
e15f0a5e 3124wxWindowMac * wxFindWindowAtPointer( wxPoint& pt )
3723b7b1 3125{
59a12e90 3126 pt = wxGetMousePosition();
e766c8a9 3127 wxWindowMac* found = wxFindWindowAtPoint(pt);
e15f0a5e 3128
59a12e90 3129 return found;
3723b7b1
JS
3130}
3131
3132// Get the current mouse position.
3133wxPoint wxGetMousePosition()
3134{
57591e0e 3135 int x, y;
e15f0a5e
DS
3136
3137 wxGetMousePosition( &x, &y );
3138
57591e0e 3139 return wxPoint(x, y);
3723b7b1
JS
3140}
3141
6ed71b4f 3142void wxWindowMac::OnMouseEvent( wxMouseEvent &event )
8950f7cc 3143{
8b573fb8
VZ
3144 if ( event.GetEventType() == wxEVT_RIGHT_DOWN )
3145 {
3146 // copied from wxGTK : CS
fe224552
VZ
3147 // VZ: shouldn't we move this to base class then?
3148
249aad30 3149 // generate a "context menu" event: this is similar to wxEVT_RIGHT_DOWN
8950f7cc
SC
3150 // except that:
3151 //
3152 // (a) it's a command event and so is propagated to the parent
3153 // (b) under MSW it can be generated from kbd too
3154 // (c) it uses screen coords (because of (a))
3155 wxContextMenuEvent evtCtx(wxEVT_CONTEXT_MENU,
3156 this->GetId(),
3157 this->ClientToScreen(event.GetPosition()));
937013e0 3158 if ( ! HandleWindowEvent(evtCtx) )
249aad30 3159 event.Skip() ;
8b573fb8 3160 }
facd6764
SC
3161 else
3162 {
8b573fb8 3163 event.Skip() ;
facd6764 3164 }
8950f7cc
SC
3165}
3166
89954433 3167void wxWindowMac::OnPaint( wxPaintEvent & WXUNUSED(event) )
ff3795ee 3168{
4488a1d3
VZ
3169 if ( wxTheApp->MacGetCurrentEvent() != NULL && wxTheApp->MacGetCurrentEventHandlerCallRef() != NULL
3170 && GetBackgroundStyle() != wxBG_STYLE_TRANSPARENT )
e15f0a5e
DS
3171 CallNextEventHandler(
3172 (EventHandlerCallRef)wxTheApp->MacGetCurrentEventHandlerCallRef() ,
3173 (EventRef) wxTheApp->MacGetCurrentEvent() ) ;
ff3795ee
SC
3174}
3175
89954433
VZ
3176void wxWindowMac::MacHandleControlClick(WXWidget WXUNUSED(control),
3177 wxInt16 WXUNUSED(controlpart),
3178 bool WXUNUSED(mouseStillDown))
facd6764 3179{
facd6764
SC
3180}
3181
8b573fb8 3182Rect wxMacGetBoundsForControl( wxWindow* window , const wxPoint& pos , const wxSize &size , bool adjustForOrigin )
3083eb85 3183{
e15f0a5e 3184 int x, y, w, h ;
8b573fb8 3185
58603178
DS
3186 window->MacGetBoundsForControl( pos , size , x , y, w, h , adjustForOrigin ) ;
3187 Rect bounds = { y, x, y + h, x + w };
e15f0a5e 3188
3083eb85
SC
3189 return bounds ;
3190}
3191
8b573fb8 3192wxInt32 wxWindowMac::MacControlHit(WXEVENTHANDLERREF WXUNUSED(handler) , WXEVENTREF WXUNUSED(event) )
f1d527c1
SC
3193{
3194 return eventNotHandledErr ;
3195}
3196
50779e06
JS
3197bool wxWindowMac::Reparent(wxWindowBase *newParentBase)
3198{
3199 wxWindowMac *newParent = (wxWindowMac *)newParentBase;
50779e06 3200 if ( !wxWindowBase::Reparent(newParent) )
3dee36ae
WS
3201 return false;
3202
e15f0a5e 3203 // copied from MacPostControlCreate
50779e06 3204 ControlRef container = (ControlRef) GetParent()->GetHandle() ;
e15f0a5e 3205
50779e06 3206 wxASSERT_MSG( container != NULL , wxT("No valid mac container control") ) ;
e15f0a5e 3207
50779e06 3208 ::EmbedControl( m_peer->GetControlRef() , container ) ;
facd6764 3209
3dee36ae
WS
3210 return true;
3211}
a9b456ff
SC
3212
3213bool wxWindowMac::SetTransparent(wxByte alpha)
3214{
4488a1d3
VZ
3215 SetBackgroundStyle(wxBG_STYLE_TRANSPARENT);
3216
a9b456ff
SC
3217 if ( alpha != m_macAlpha )
3218 {
3219 m_macAlpha = alpha ;
3220 Refresh() ;
3221 }
3222 return true ;
a9b456ff
SC
3223}
3224
3225
3226bool wxWindowMac::CanSetTransparent()
3227{
a9b456ff 3228 return true ;
a9b456ff
SC
3229}
3230
89954433 3231wxByte wxWindowMac::GetTransparent() const
a9b456ff
SC
3232{
3233 return m_macAlpha ;
8444b6cb 3234}