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