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