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