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