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