1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/mac/carbon/window.cpp
3 // Purpose: wxWindowMac
4 // Author: Stefan Csomor
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 #include "wx/wxprec.h"
14 #include "wx/window.h"
23 #include "wx/dcclient.h"
24 #include "wx/button.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"
40 #include "wx/tooltip.h"
41 #include "wx/spinctrl.h"
42 #include "wx/geometry.h"
45 #include "wx/listctrl.h"
49 #include "wx/treectrl.h"
57 #include "wx/popupwin.h"
60 #if wxUSE_DRAG_AND_DROP
64 #include "wx/mac/uma.h"
66 #define MAC_SCROLLBAR_SIZE 15
67 #define MAC_SMALL_SCROLLBAR_SIZE 11
71 #ifdef __WXUNIVERSAL__
72 IMPLEMENT_ABSTRACT_CLASS(wxWindowMac
, wxWindowBase
)
74 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
77 BEGIN_EVENT_TABLE(wxWindowMac
, wxWindowBase
)
78 EVT_NC_PAINT(wxWindowMac::OnNcPaint
)
79 EVT_ERASE_BACKGROUND(wxWindowMac::OnEraseBackground
)
80 EVT_PAINT(wxWindowMac::OnPaint
)
81 EVT_MOUSE_EVENTS(wxWindowMac::OnMouseEvent
)
84 #define wxMAC_DEBUG_REDRAW 0
85 #ifndef wxMAC_DEBUG_REDRAW
86 #define wxMAC_DEBUG_REDRAW 0
89 // ---------------------------------------------------------------------------
90 // Utility Routines to move between different coordinate systems
91 // ---------------------------------------------------------------------------
94 * Right now we have the following setup :
95 * a border that is not part of the native control is always outside the
96 * control's border (otherwise we loose all native intelligence, future ways
97 * may be to have a second embedding control responsible for drawing borders
98 * and backgrounds eventually)
99 * so all this border calculations have to be taken into account when calling
100 * native methods or getting native oriented data
101 * so we have three coordinate systems here
102 * wx client coordinates
103 * wx window coordinates (including window frames)
108 // originating from native control
112 void wxMacNativeToWindow( const wxWindow
* window
, RgnHandle handle
)
114 OffsetRgn( handle
, window
->MacGetLeftBorderSize() , window
->MacGetTopBorderSize() ) ;
117 void wxMacNativeToWindow( const wxWindow
* window
, Rect
*rect
)
119 OffsetRect( rect
, window
->MacGetLeftBorderSize() , window
->MacGetTopBorderSize() ) ;
123 // directed towards native control
126 void wxMacWindowToNative( const wxWindow
* window
, RgnHandle handle
)
128 OffsetRgn( handle
, -window
->MacGetLeftBorderSize() , -window
->MacGetTopBorderSize() );
131 void wxMacWindowToNative( const wxWindow
* window
, Rect
*rect
)
133 OffsetRect( rect
, -window
->MacGetLeftBorderSize() , -window
->MacGetTopBorderSize() ) ;
136 // ---------------------------------------------------------------------------
138 // ---------------------------------------------------------------------------
140 static const EventTypeSpec eventList
[] =
142 { kEventClassCommand
, kEventProcessCommand
} ,
143 { kEventClassCommand
, kEventCommandUpdateStatus
} ,
145 { kEventClassControl
, kEventControlGetClickActivation
} ,
146 { kEventClassControl
, kEventControlHit
} ,
148 { kEventClassTextInput
, kEventTextInputUnicodeForKeyEvent
} ,
149 { kEventClassTextInput
, kEventTextInputUpdateActiveInputArea
} ,
151 { kEventClassControl
, kEventControlDraw
} ,
153 { kEventClassControl
, kEventControlVisibilityChanged
} ,
154 { kEventClassControl
, kEventControlEnabledStateChanged
} ,
155 { kEventClassControl
, kEventControlHiliteChanged
} ,
157 { kEventClassControl
, kEventControlActivate
} ,
158 { kEventClassControl
, kEventControlDeactivate
} ,
160 { kEventClassControl
, kEventControlSetFocusPart
} ,
161 { kEventClassControl
, kEventControlFocusPartChanged
} ,
163 { kEventClassService
, kEventServiceGetTypes
},
164 { kEventClassService
, kEventServiceCopy
},
165 { kEventClassService
, kEventServicePaste
},
167 // { kEventClassControl , kEventControlInvalidateForSizeChange } , // 10.3 only
168 // { kEventClassControl , kEventControlBoundsChanged } ,
171 static pascal OSStatus
wxMacWindowControlEventHandler( EventHandlerCallRef handler
, EventRef event
, void *data
)
173 OSStatus result
= eventNotHandledErr
;
175 wxMacCarbonEvent
cEvent( event
) ;
177 ControlRef controlRef
;
178 wxWindowMac
* thisWindow
= (wxWindowMac
*) data
;
180 cEvent
.GetParameter( kEventParamDirectObject
, &controlRef
) ;
182 switch ( GetEventKind( event
) )
184 case kEventControlDraw
:
186 RgnHandle updateRgn
= NULL
;
187 RgnHandle allocatedRgn
= NULL
;
188 wxRegion visRegion
= thisWindow
->MacGetVisibleRegion() ;
190 if ( cEvent
.GetParameter
<RgnHandle
>(kEventParamRgnHandle
, &updateRgn
) != noErr
)
192 HIShapeGetAsQDRgn( visRegion
.GetWXHRGN(), updateRgn
);
196 if ( thisWindow
->MacGetLeftBorderSize() != 0 || thisWindow
->MacGetTopBorderSize() != 0 )
198 // as this update region is in native window locals we must adapt it to wx window local
199 allocatedRgn
= NewRgn() ;
200 CopyRgn( updateRgn
, allocatedRgn
) ;
202 // hide the given region by the new region that must be shifted
203 wxMacNativeToWindow( thisWindow
, allocatedRgn
) ;
204 updateRgn
= allocatedRgn
;
208 #if wxMAC_DEBUG_REDRAW
209 if ( thisWindow
->MacIsUserPane() )
211 static float color
= 0.5 ;
214 CGContextRef cgContext
= cEvent
.GetParameter
<CGContextRef
>(kEventParamCGContextRef
) ;
216 HIViewGetBounds( controlRef
, &bounds
);
217 CGContextSetRGBFillColor( cgContext
, channel
== 0 ? color
: 0.5 ,
218 channel
== 1 ? color
: 0.5 , channel
== 2 ? color
: 0.5 , 1 );
219 CGContextFillRect( cgContext
, bounds
);
232 bool created
= false ;
233 CGContextRef cgContext
= NULL
;
234 OSStatus err
= cEvent
.GetParameter
<CGContextRef
>(kEventParamCGContextRef
, &cgContext
) ;
235 wxASSERT_MSG( err
== noErr
, wxT("Unable to retrieve CGContextRef") ) ;
236 thisWindow
->MacSetCGContextRef( cgContext
) ;
239 wxMacCGContextStateSaver
sg( cgContext
) ;
242 wxWindow
* iter
= thisWindow
;
245 alpha
*= (float) iter
->GetTransparent()/255.0 ;
246 if ( iter
->IsTopLevel() )
249 iter
= iter
->GetParent() ;
252 CGContextSetAlpha( cgContext
, alpha
) ;
254 if ( thisWindow
->GetBackgroundStyle() == wxBG_STYLE_TRANSPARENT
)
257 HIViewGetBounds( controlRef
, &bounds
);
258 CGContextClearRect( cgContext
, bounds
);
263 if ( thisWindow
->MacDoRedraw( updateRgn
, cEvent
.GetTicks() ) )
266 thisWindow
->MacSetCGContextRef( NULL
) ;
270 CGContextRelease( cgContext
) ;
274 DisposeRgn( allocatedRgn
) ;
278 case kEventControlVisibilityChanged
:
279 thisWindow
->MacVisibilityChanged() ;
282 case kEventControlEnabledStateChanged
:
283 thisWindow
->MacEnabledStateChanged();
286 case kEventControlHiliteChanged
:
287 thisWindow
->MacHiliteChanged() ;
290 case kEventControlActivate
:
291 case kEventControlDeactivate
:
292 // FIXME: we should have a virtual function for this!
294 if ( thisWindow
->IsKindOf( CLASSINFO( wxTreeCtrl
) ) )
295 thisWindow
->Refresh();
298 if ( thisWindow
->IsKindOf( CLASSINFO( wxListCtrl
) ) )
299 thisWindow
->Refresh();
305 // different handling on OS X
308 case kEventControlFocusPartChanged
:
309 // the event is emulated by wxmac for systems lower than 10.5
311 ControlPartCode previousControlPart
= cEvent
.GetParameter
<ControlPartCode
>(kEventParamControlPreviousPart
, typeControlPartCode
);
312 ControlPartCode currentControlPart
= cEvent
.GetParameter
<ControlPartCode
>(kEventParamControlCurrentPart
, typeControlPartCode
);
314 if ( thisWindow
->MacGetTopLevelWindow() && thisWindow
->GetPeer()->NeedsFocusRect() )
316 thisWindow
->MacInvalidateBorders();
319 if ( currentControlPart
== 0 )
323 if ( thisWindow
->GetCaret() )
324 thisWindow
->GetCaret()->OnKillFocus();
327 wxLogTrace(_T("Focus"), _T("focus lost(%p)"), wx_static_cast(void*, thisWindow
));
329 // remove this as soon as posting the synthesized event works properly
330 static bool inKillFocusEvent
= false ;
332 if ( !inKillFocusEvent
)
334 inKillFocusEvent
= true ;
335 wxFocusEvent
event( wxEVT_KILL_FOCUS
, thisWindow
->GetId());
336 event
.SetEventObject(thisWindow
);
337 thisWindow
->HandleWindowEvent(event
) ;
338 inKillFocusEvent
= false ;
341 else if ( previousControlPart
== 0 )
344 // panel wants to track the window which was the last to have focus in it
345 wxLogTrace(_T("Focus"), _T("focus set(%p)"), wx_static_cast(void*, thisWindow
));
346 wxChildFocusEvent
eventFocus((wxWindow
*)thisWindow
);
347 thisWindow
->HandleWindowEvent(eventFocus
);
350 if ( thisWindow
->GetCaret() )
351 thisWindow
->GetCaret()->OnSetFocus();
354 wxFocusEvent
event(wxEVT_SET_FOCUS
, thisWindow
->GetId());
355 event
.SetEventObject(thisWindow
);
356 thisWindow
->HandleWindowEvent(event
) ;
360 case kEventControlSetFocusPart
:
363 Boolean focusEverything
= false ;
364 if ( cEvent
.GetParameter
<Boolean
>(kEventParamControlFocusEverything
, &focusEverything
) == noErr
)
366 // put a breakpoint here to catch focus everything events
369 ControlPartCode controlPart
= cEvent
.GetParameter
<ControlPartCode
>(kEventParamControlPart
, typeControlPartCode
);
371 ControlPartCode previousControlPart
= 0;
372 verify_noerr( HIViewGetFocusPart(controlRef
, &previousControlPart
));
374 if ( thisWindow
->MacIsUserPane() )
376 if ( controlPart
!= kControlFocusNoPart
)
377 cEvent
.SetParameter
<ControlPartCode
>( kEventParamControlPart
, typeControlPartCode
, 1 ) ;
381 result
= CallNextEventHandler(handler
, event
);
383 if ( UMAGetSystemVersion() < 0x1050 )
385 // set back to 0 if problems arise
387 ControlPartCode currentControlPart
= cEvent
.GetParameter
<ControlPartCode
>(kEventParamControlPart
, typeControlPartCode
);
388 // synthesize the event focus changed event
389 EventRef evRef
= NULL
;
391 OSStatus err
= MacCreateEvent(
392 NULL
, kEventClassControl
, kEventControlFocusPartChanged
, TicksToEventTime( TickCount() ) ,
393 kEventAttributeUserEvent
, &evRef
);
396 wxMacCarbonEvent
iEvent( evRef
) ;
397 iEvent
.SetParameter
<ControlRef
>( kEventParamDirectObject
, controlRef
) ;
398 iEvent
.SetParameter
<ControlPartCode
>( kEventParamControlPreviousPart
, typeControlPartCode
, previousControlPart
) ;
399 iEvent
.SetParameter
<ControlPartCode
>( kEventParamControlCurrentPart
, typeControlPartCode
, currentControlPart
) ;
402 // TODO test this first, avoid double posts etc...
403 PostEventToQueue( GetMainEventQueue(), evRef
, kEventPriorityHigh
);
405 wxMacWindowControlEventHandler( NULL
, evRef
, data
) ;
407 ReleaseEvent( evRef
) ;
409 // old implementation, to be removed if the new one works
410 if ( controlPart
== kControlFocusNoPart
)
413 if ( thisWindow
->GetCaret() )
414 thisWindow
->GetCaret()->OnKillFocus();
417 wxLogTrace(_T("Focus"), _T("focus lost(%p)"), wx_static_cast(void*, thisWindow
));
419 static bool inKillFocusEvent
= false ;
421 if ( !inKillFocusEvent
)
423 inKillFocusEvent
= true ;
424 wxFocusEvent
event( wxEVT_KILL_FOCUS
, thisWindow
->GetId());
425 event
.SetEventObject(thisWindow
);
426 thisWindow
->HandleWindowEvent(event
) ;
427 inKillFocusEvent
= false ;
432 // panel wants to track the window which was the last to have focus in it
433 wxLogTrace(_T("Focus"), _T("focus set(%p)"), wx_static_cast(void*, thisWindow
));
434 wxChildFocusEvent
eventFocus((wxWindow
*)thisWindow
);
435 thisWindow
->HandleWindowEvent(eventFocus
);
438 if ( thisWindow
->GetCaret() )
439 thisWindow
->GetCaret()->OnSetFocus();
442 wxFocusEvent
event(wxEVT_SET_FOCUS
, thisWindow
->GetId());
443 event
.SetEventObject(thisWindow
);
444 thisWindow
->HandleWindowEvent(event
) ;
451 case kEventControlHit
:
452 result
= thisWindow
->MacControlHit( handler
, event
) ;
455 case kEventControlGetClickActivation
:
457 // fix to always have a proper activation for DataBrowser controls (stay in bkgnd otherwise)
458 WindowRef owner
= cEvent
.GetParameter
<WindowRef
>(kEventParamWindowRef
);
459 if ( !IsWindowActive(owner
) )
461 cEvent
.SetParameter(kEventParamClickActivation
,(UInt32
) kActivateAndIgnoreClick
) ;
474 static pascal OSStatus
475 wxMacWindowServiceEventHandler(EventHandlerCallRef
WXUNUSED(handler
),
479 OSStatus result
= eventNotHandledErr
;
481 wxMacCarbonEvent
cEvent( event
) ;
483 ControlRef controlRef
;
484 wxWindowMac
* thisWindow
= (wxWindowMac
*) data
;
485 wxTextCtrl
* textCtrl
= wxDynamicCast( thisWindow
, wxTextCtrl
) ;
486 cEvent
.GetParameter( kEventParamDirectObject
, &controlRef
) ;
488 switch ( GetEventKind( event
) )
490 case kEventServiceGetTypes
:
494 textCtrl
->GetSelection( &from
, &to
) ;
496 CFMutableArrayRef copyTypes
= 0 , pasteTypes
= 0;
498 copyTypes
= cEvent
.GetParameter
< CFMutableArrayRef
>( kEventParamServiceCopyTypes
, typeCFMutableArrayRef
) ;
499 if ( textCtrl
->IsEditable() )
500 pasteTypes
= cEvent
.GetParameter
< CFMutableArrayRef
>( kEventParamServicePasteTypes
, typeCFMutableArrayRef
) ;
502 static const OSType textDataTypes
[] = { kTXNTextData
/* , 'utxt', 'PICT', 'MooV', 'AIFF' */ };
503 for ( size_t i
= 0 ; i
< WXSIZEOF(textDataTypes
) ; ++i
)
505 CFStringRef typestring
= CreateTypeStringWithOSType(textDataTypes
[i
]);
509 CFArrayAppendValue(copyTypes
, typestring
) ;
511 CFArrayAppendValue(pasteTypes
, typestring
) ;
513 CFRelease( typestring
) ;
521 case kEventServiceCopy
:
526 textCtrl
->GetSelection( &from
, &to
) ;
527 wxString val
= textCtrl
->GetValue() ;
528 val
= val
.Mid( from
, to
- from
) ;
529 PasteboardRef pasteboard
= cEvent
.GetParameter
<PasteboardRef
>( kEventParamPasteboardRef
, typePasteboardRef
);
530 verify_noerr( PasteboardClear( pasteboard
) ) ;
531 PasteboardSynchronize( pasteboard
);
532 // TODO add proper conversion
533 CFDataRef data
= CFDataCreate( kCFAllocatorDefault
, (const UInt8
*)val
.c_str(), val
.length() );
534 PasteboardPutItemFlavor( pasteboard
, (PasteboardItemID
) 1, CFSTR("com.apple.traditional-mac-plain-text"), data
, 0);
540 case kEventServicePaste
:
543 PasteboardRef pasteboard
= cEvent
.GetParameter
<PasteboardRef
>( kEventParamPasteboardRef
, typePasteboardRef
);
544 PasteboardSynchronize( pasteboard
);
546 verify_noerr( PasteboardGetItemCount( pasteboard
, &itemCount
) );
547 for( UInt32 itemIndex
= 1; itemIndex
<= itemCount
; itemIndex
++ )
549 PasteboardItemID itemID
;
550 if ( PasteboardGetItemIdentifier( pasteboard
, itemIndex
, &itemID
) == noErr
)
552 CFDataRef flavorData
= NULL
;
553 if ( PasteboardCopyItemFlavorData( pasteboard
, itemID
, CFSTR("com.apple.traditional-mac-plain-text"), &flavorData
) == noErr
)
555 CFIndex flavorDataSize
= CFDataGetLength( flavorData
);
556 char *content
= new char[flavorDataSize
+1] ;
557 memcpy( content
, CFDataGetBytePtr( flavorData
), flavorDataSize
);
558 content
[flavorDataSize
]=0;
559 CFRelease( flavorData
);
561 textCtrl
->WriteText( wxString( content
, wxConvLocal
) );
563 textCtrl
->WriteText( wxString( content
) ) ;
581 pascal OSStatus
wxMacUnicodeTextEventHandler( EventHandlerCallRef handler
, EventRef event
, void *data
)
583 OSStatus result
= eventNotHandledErr
;
584 wxWindowMac
* focus
= (wxWindowMac
*) data
;
586 wchar_t* uniChars
= NULL
;
587 UInt32 when
= EventTimeToTicks( GetEventTime( event
) ) ;
589 UniChar
* charBuf
= NULL
;
590 ByteCount dataSize
= 0 ;
593 if ( GetEventParameter( event
, kEventParamTextInputSendText
, typeUnicodeText
, NULL
, 0 , &dataSize
, NULL
) == noErr
)
595 numChars
= dataSize
/ sizeof( UniChar
) + 1;
598 if ( (size_t) numChars
* 2 > sizeof(buf
) )
599 charBuf
= new UniChar
[ numChars
] ;
603 uniChars
= new wchar_t[ numChars
] ;
604 GetEventParameter( event
, kEventParamTextInputSendText
, typeUnicodeText
, NULL
, dataSize
, NULL
, charBuf
) ;
605 charBuf
[ numChars
- 1 ] = 0;
606 #if SIZEOF_WCHAR_T == 2
607 uniChars
= (wchar_t*) charBuf
;
608 /* 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...)
610 // the resulting string will never have more chars than the utf16 version, so this is safe
611 wxMBConvUTF16 converter
;
612 numChars
= converter
.MB2WC( uniChars
, (const char*)charBuf
, numChars
) ;
616 switch ( GetEventKind( event
) )
618 case kEventTextInputUpdateActiveInputArea
:
620 // An IME input event may return several characters, but we need to send one char at a time to
622 for (int pos
=0 ; pos
< numChars
; pos
++)
624 WXEVENTREF formerEvent
= wxTheApp
->MacGetCurrentEvent() ;
625 WXEVENTHANDLERCALLREF formerHandler
= wxTheApp
->MacGetCurrentEventHandlerCallRef() ;
626 wxTheApp
->MacSetCurrentEvent( event
, handler
) ;
628 UInt32 message
= uniChars
[pos
] < 128 ? (char)uniChars
[pos
] : '?';
630 NB: faking a charcode here is problematic. The kEventTextInputUpdateActiveInputArea event is sent
631 multiple times to update the active range during inline input, so this handler will often receive
632 uncommited text, which should usually not trigger side effects. It might be a good idea to check the
633 kEventParamTextInputSendFixLen parameter and verify if input is being confirmed (see CarbonEvents.h).
634 On the other hand, it can be useful for some applications to react to uncommitted text (for example,
635 to update a status display), as long as it does not disrupt the inline input session. Ideally, wx
636 should add new event types to support advanced text input. For now, I would keep things as they are.
638 However, the code that was being used caused additional problems:
639 UInt32 message = (0 << 8) + ((char)uniChars[pos] );
640 Since it simply truncated the unichar to the last byte, it ended up causing weird bugs with inline
641 input, such as switching to another field when one attempted to insert the character U+4E09 (the kanji
642 for "three"), because it was truncated to 09 (kTabCharCode), which was later "converted" to WXK_TAB
643 (still 09) in wxMacTranslateKey; or triggering the default button when one attempted to insert U+840D
644 (the kanji for "name"), which got truncated to 0D and interpreted as a carriage return keypress.
645 Note that even single-byte characters could have been misinterpreted, since MacRoman charcodes only
646 overlap with Unicode within the (7-bit) ASCII range.
647 But simply passing a NUL charcode would disable text updated events, because wxTextCtrl::OnChar checks
648 for codes within a specific range. Therefore I went for the solution seen above, which keeps ASCII
649 characters as they are and replaces the rest with '?', ensuring that update events are triggered.
650 It would be better to change wxTextCtrl::OnChar to look at the actual unicode character instead, but
651 I don't have time to look into that right now.
654 if ( wxTheApp
->MacSendCharEvent(
655 focus
, message
, 0 , when
, 0 , 0 , uniChars
[pos
] ) )
660 wxTheApp
->MacSetCurrentEvent( formerEvent
, formerHandler
) ;
664 case kEventTextInputUnicodeForKeyEvent
:
666 UInt32 keyCode
, modifiers
;
669 unsigned char charCode
;
671 GetEventParameter( event
, kEventParamTextInputSendKeyboardEvent
, typeEventRef
, NULL
, sizeof(rawEvent
), NULL
, &rawEvent
) ;
672 GetEventParameter( rawEvent
, kEventParamKeyMacCharCodes
, typeChar
, NULL
, sizeof(char), NULL
, &charCode
);
673 GetEventParameter( rawEvent
, kEventParamKeyCode
, typeUInt32
, NULL
, sizeof(UInt32
), NULL
, &keyCode
);
674 GetEventParameter( rawEvent
, kEventParamKeyModifiers
, typeUInt32
, NULL
, sizeof(UInt32
), NULL
, &modifiers
);
675 GetEventParameter( rawEvent
, kEventParamMouseLocation
, typeQDPoint
, NULL
, sizeof(Point
), NULL
, &point
);
677 UInt32 message
= (keyCode
<< 8) + charCode
;
679 // An IME input event may return several characters, but we need to send one char at a time to
681 for (int pos
=0 ; pos
< numChars
; pos
++)
683 WXEVENTREF formerEvent
= wxTheApp
->MacGetCurrentEvent() ;
684 WXEVENTHANDLERCALLREF formerHandler
= wxTheApp
->MacGetCurrentEventHandlerCallRef() ;
685 wxTheApp
->MacSetCurrentEvent( event
, handler
) ;
687 if ( wxTheApp
->MacSendCharEvent(
688 focus
, message
, modifiers
, when
, point
.h
, point
.v
, uniChars
[pos
] ) )
693 wxTheApp
->MacSetCurrentEvent( formerEvent
, formerHandler
) ;
702 if ( charBuf
!= buf
)
708 static pascal OSStatus
709 wxMacWindowCommandEventHandler(EventHandlerCallRef
WXUNUSED(handler
),
713 OSStatus result
= eventNotHandledErr
;
714 wxWindowMac
* focus
= (wxWindowMac
*) data
;
718 wxMacCarbonEvent
cEvent( event
) ;
719 cEvent
.GetParameter
<HICommand
>(kEventParamDirectObject
,typeHICommand
,&command
) ;
721 wxMenuItem
* item
= NULL
;
722 wxMenu
* itemMenu
= wxFindMenuFromMacCommand( command
, item
) ;
723 int id
= wxMacCommandToId( command
.commandID
) ;
727 wxASSERT( itemMenu
!= NULL
) ;
729 switch ( cEvent
.GetKind() )
731 case kEventProcessCommand
:
732 result
= itemMenu
->MacHandleCommandProcess( item
, id
, focus
);
735 case kEventCommandUpdateStatus
:
736 result
= itemMenu
->MacHandleCommandUpdateStatus( item
, id
, focus
);
746 pascal OSStatus
wxMacWindowEventHandler( EventHandlerCallRef handler
, EventRef event
, void *data
)
748 EventRef formerEvent
= (EventRef
) wxTheApp
->MacGetCurrentEvent() ;
749 EventHandlerCallRef formerEventHandlerCallRef
= (EventHandlerCallRef
) wxTheApp
->MacGetCurrentEventHandlerCallRef() ;
750 wxTheApp
->MacSetCurrentEvent( event
, handler
) ;
751 OSStatus result
= eventNotHandledErr
;
753 switch ( GetEventClass( event
) )
755 case kEventClassCommand
:
756 result
= wxMacWindowCommandEventHandler( handler
, event
, data
) ;
759 case kEventClassControl
:
760 result
= wxMacWindowControlEventHandler( handler
, event
, data
) ;
763 case kEventClassService
:
764 result
= wxMacWindowServiceEventHandler( handler
, event
, data
) ;
767 case kEventClassTextInput
:
768 result
= wxMacUnicodeTextEventHandler( handler
, event
, data
) ;
775 wxTheApp
->MacSetCurrentEvent( formerEvent
, formerEventHandlerCallRef
) ;
780 DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacWindowEventHandler
)
782 // ---------------------------------------------------------------------------
783 // Scrollbar Tracking for all
784 // ---------------------------------------------------------------------------
786 pascal void wxMacLiveScrollbarActionProc( ControlRef control
, ControlPartCode partCode
) ;
787 pascal void wxMacLiveScrollbarActionProc( ControlRef control
, ControlPartCode partCode
)
791 wxWindow
* wx
= wxFindControlFromMacControl( control
) ;
793 wx
->MacHandleControlClick( (WXWidget
) control
, partCode
, true /* stillDown */ ) ;
796 wxMAC_DEFINE_PROC_GETTER( ControlActionUPP
, wxMacLiveScrollbarActionProc
) ;
798 // ===========================================================================
800 // ===========================================================================
802 WX_DECLARE_HASH_MAP(ControlRef
, wxWindow
*, wxPointerHash
, wxPointerEqual
, MacControlMap
);
804 static MacControlMap wxWinMacControlList
;
806 wxWindow
*wxFindControlFromMacControl(ControlRef inControl
)
808 MacControlMap::iterator node
= wxWinMacControlList
.find(inControl
);
810 return (node
== wxWinMacControlList
.end()) ? NULL
: node
->second
;
813 void wxAssociateControlWithMacControl(ControlRef inControl
, wxWindow
*control
)
815 // adding NULL ControlRef is (first) surely a result of an error and
816 // (secondly) breaks native event processing
817 wxCHECK_RET( inControl
!= (ControlRef
) NULL
, wxT("attempt to add a NULL WindowRef to window list") );
819 wxWinMacControlList
[inControl
] = control
;
822 void wxRemoveMacControlAssociation(wxWindow
*control
)
824 // iterate over all the elements in the class
825 // is the iterator stable ? as we might have two associations pointing to the same wxWindow
826 // we should go on...
832 MacControlMap::iterator it
;
833 for ( it
= wxWinMacControlList
.begin(); it
!= wxWinMacControlList
.end(); ++it
)
835 if ( it
->second
== control
)
837 wxWinMacControlList
.erase(it
);
845 // ----------------------------------------------------------------------------
846 // constructors and such
847 // ----------------------------------------------------------------------------
849 wxWindowMac::wxWindowMac()
854 wxWindowMac::wxWindowMac(wxWindowMac
*parent
,
859 const wxString
& name
)
862 Create(parent
, id
, pos
, size
, style
, name
);
865 void wxWindowMac::Init()
869 m_cgContextRef
= NULL
;
871 // as all windows are created with WS_VISIBLE style...
874 m_hScrollBar
= NULL
;
875 m_vScrollBar
= NULL
;
876 m_hScrollBarAlwaysShown
= false;
877 m_vScrollBarAlwaysShown
= false;
879 m_macIsUserPane
= true;
880 m_clipChildren
= false ;
881 m_cachedClippedRectValid
= false ;
883 // we need a valid font for the encodings
884 wxWindowBase::SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
));
887 wxWindowMac::~wxWindowMac()
891 m_isBeingDeleted
= true;
893 MacInvalidateBorders() ;
895 #ifndef __WXUNIVERSAL__
896 // VS: make sure there's no wxFrame with last focus set to us:
897 for ( wxWindow
*win
= GetParent(); win
; win
= win
->GetParent() )
899 wxFrame
*frame
= wxDynamicCast(win
, wxFrame
);
902 if ( frame
->GetLastFocus() == this )
903 frame
->SetLastFocus((wxWindow
*)NULL
);
909 // destroy children before destroying this window itself
912 // wxRemoveMacControlAssociation( this ) ;
913 // If we delete an item, we should initialize the parent panel,
914 // because it could now be invalid.
915 wxTopLevelWindow
*tlw
= wxDynamicCast(wxGetTopLevelParent(this), wxTopLevelWindow
);
918 if ( tlw
->GetDefaultItem() == (wxButton
*) this)
919 tlw
->SetDefaultItem(NULL
);
922 if ( m_peer
&& m_peer
->Ok() )
924 // in case the callback might be called during destruction
925 wxRemoveMacControlAssociation( this) ;
926 ::RemoveEventHandler( (EventHandlerRef
) m_macControlEventHandler
) ;
927 // we currently are not using this hook
928 // ::SetControlColorProc( *m_peer , NULL ) ;
932 if ( g_MacLastWindow
== this )
933 g_MacLastWindow
= NULL
;
935 #ifndef __WXUNIVERSAL__
936 wxFrame
* frame
= wxDynamicCast( wxGetTopLevelParent( (wxWindow
*)this ) , wxFrame
) ;
939 if ( frame
->GetLastFocus() == this )
940 frame
->SetLastFocus( NULL
) ;
944 // delete our drop target if we've got one
945 #if wxUSE_DRAG_AND_DROP
946 if ( m_dropTarget
!= NULL
)
956 WXWidget
wxWindowMac::GetHandle() const
958 return (WXWidget
) m_peer
->GetControlRef() ;
961 void wxWindowMac::MacInstallEventHandler( WXWidget control
)
963 wxAssociateControlWithMacControl( (ControlRef
) control
, this ) ;
964 InstallControlEventHandler( (ControlRef
)control
, GetwxMacWindowEventHandlerUPP(),
965 GetEventTypeCount(eventList
), eventList
, this,
966 (EventHandlerRef
*)&m_macControlEventHandler
);
970 bool wxWindowMac::Create(wxWindowMac
*parent
,
975 const wxString
& name
)
977 wxCHECK_MSG( parent
, false, wxT("can't create wxWindowMac without parent") );
979 if ( !CreateBase(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
) )
982 m_windowVariant
= parent
->GetWindowVariant() ;
984 if ( m_macIsUserPane
)
986 Rect bounds
= wxMacGetBoundsForControl( this , pos
, size
) ;
989 | kControlSupportsEmbedding
990 | kControlSupportsLiveFeedback
991 | kControlGetsFocusOnClick
992 // | kControlHasSpecialBackground
993 // | kControlSupportsCalcBestRect
994 | kControlHandlesTracking
995 | kControlSupportsFocus
996 | kControlWantsActivate
997 | kControlWantsIdle
;
999 m_peer
= new wxMacControl(this) ;
1000 OSStatus err
=::CreateUserPaneControl( MAC_WXHWND(GetParent()->MacGetTopLevelWindowRef()) , &bounds
, features
, m_peer
->GetControlRefAddr() );
1001 verify_noerr( err
);
1003 MacPostControlCreate(pos
, size
) ;
1006 #ifndef __WXUNIVERSAL__
1007 // Don't give scrollbars to wxControls unless they ask for them
1008 if ( (! IsKindOf(CLASSINFO(wxControl
)) && ! IsKindOf(CLASSINFO(wxStatusBar
)))
1009 || (IsKindOf(CLASSINFO(wxControl
)) && ((style
& wxHSCROLL
) || (style
& wxVSCROLL
))))
1011 MacCreateScrollBars( style
) ;
1015 wxWindowCreateEvent
event(this);
1016 GetEventHandler()->AddPendingEvent(event
);
1021 void wxWindowMac::MacChildAdded()
1024 m_vScrollBar
->Raise() ;
1026 m_hScrollBar
->Raise() ;
1029 void wxWindowMac::MacPostControlCreate(const wxPoint
& WXUNUSED(pos
), const wxSize
& size
)
1031 wxASSERT_MSG( m_peer
!= NULL
&& m_peer
->Ok() , wxT("No valid mac control") ) ;
1033 m_peer
->SetReference( (URefCon
) this ) ;
1034 GetParent()->AddChild( this );
1036 MacInstallEventHandler( (WXWidget
) m_peer
->GetControlRef() );
1038 ControlRef container
= (ControlRef
) GetParent()->GetHandle() ;
1039 wxASSERT_MSG( container
!= NULL
, wxT("No valid mac container control") ) ;
1040 ::EmbedControl( m_peer
->GetControlRef() , container
) ;
1041 GetParent()->MacChildAdded() ;
1043 // adjust font, controlsize etc
1044 DoSetWindowVariant( m_windowVariant
) ;
1046 m_peer
->SetLabel( wxStripMenuCodes(m_label
, wxStrip_Mnemonics
) ) ;
1048 if (!m_macIsUserPane
)
1049 SetInitialSize(size
);
1051 SetCursor( *wxSTANDARD_CURSOR
) ;
1054 void wxWindowMac::DoSetWindowVariant( wxWindowVariant variant
)
1056 // Don't assert, in case we set the window variant before
1057 // the window is created
1058 // wxASSERT( m_peer->Ok() ) ;
1060 m_windowVariant
= variant
;
1062 if (m_peer
== NULL
|| !m_peer
->Ok())
1066 ThemeFontID themeFont
= kThemeSystemFont
;
1068 // we will get that from the settings later
1069 // and make this NORMAL later, but first
1070 // we have a few calculations that we must fix
1074 case wxWINDOW_VARIANT_NORMAL
:
1075 size
= kControlSizeNormal
;
1076 themeFont
= kThemeSystemFont
;
1079 case wxWINDOW_VARIANT_SMALL
:
1080 size
= kControlSizeSmall
;
1081 themeFont
= kThemeSmallSystemFont
;
1084 case wxWINDOW_VARIANT_MINI
:
1085 // not always defined in the headers
1090 case wxWINDOW_VARIANT_LARGE
:
1091 size
= kControlSizeLarge
;
1092 themeFont
= kThemeSystemFont
;
1096 wxFAIL_MSG(_T("unexpected window variant"));
1100 m_peer
->SetData
<ControlSize
>(kControlEntireControl
, kControlSizeTag
, &size
) ;
1103 font
.MacCreateFromThemeFont( themeFont
) ;
1107 void wxWindowMac::MacUpdateControlFont()
1109 m_peer
->SetFont( GetFont() , GetForegroundColour() , GetWindowStyle() ) ;
1110 // do not trigger refreshes upon invisible and possible partly created objects
1111 if ( MacIsReallyShown() )
1115 bool wxWindowMac::SetFont(const wxFont
& font
)
1117 bool retval
= wxWindowBase::SetFont( font
);
1119 MacUpdateControlFont() ;
1124 bool wxWindowMac::SetForegroundColour(const wxColour
& col
)
1126 bool retval
= wxWindowBase::SetForegroundColour( col
);
1129 MacUpdateControlFont();
1134 bool wxWindowMac::SetBackgroundColour(const wxColour
& col
)
1136 if ( !wxWindowBase::SetBackgroundColour(col
) && m_hasBgCol
)
1139 m_peer
->SetBackgroundColour( col
) ;
1144 bool wxWindowMac::MacCanFocus() const
1146 // TODO : evaluate performance hits by looking up this value, eventually cache the results for a 1 sec or so
1147 // CAUTION : the value returned currently is 0 or 2, I've also found values of 1 having the same meaning,
1148 // but the value range is nowhere documented
1149 Boolean keyExistsAndHasValidFormat
;
1150 CFIndex fullKeyboardAccess
= CFPreferencesGetAppIntegerValue( CFSTR("AppleKeyboardUIMode" ) ,
1151 kCFPreferencesCurrentApplication
, &keyExistsAndHasValidFormat
);
1153 if ( keyExistsAndHasValidFormat
&& fullKeyboardAccess
> 0 )
1159 UInt32 features
= 0 ;
1160 m_peer
->GetFeatures( &features
) ;
1162 return features
& ( kControlSupportsFocus
| kControlGetsFocusOnClick
) ;
1166 void wxWindowMac::SetFocus()
1168 if ( !AcceptsFocus() )
1171 wxWindow
* former
= FindFocus() ;
1172 if ( former
== this )
1175 // as we cannot rely on the control features to find out whether we are in full keyboard mode,
1176 // we can only leave in case of an error
1177 OSStatus err
= m_peer
->SetFocus( kControlFocusNextPart
) ;
1178 if ( err
== errCouldntSetFocus
)
1181 SetUserFocusWindow( (WindowRef
)MacGetTopLevelWindowRef() );
1184 void wxWindowMac::DoCaptureMouse()
1186 wxApp::s_captureWindow
= this ;
1189 wxWindow
* wxWindowBase::GetCapture()
1191 return wxApp::s_captureWindow
;
1194 void wxWindowMac::DoReleaseMouse()
1196 wxApp::s_captureWindow
= NULL
;
1199 #if wxUSE_DRAG_AND_DROP
1201 void wxWindowMac::SetDropTarget(wxDropTarget
*pDropTarget
)
1203 if ( m_dropTarget
!= NULL
)
1204 delete m_dropTarget
;
1206 m_dropTarget
= pDropTarget
;
1207 if ( m_dropTarget
!= NULL
)
1215 // Old-style File Manager Drag & Drop
1216 void wxWindowMac::DragAcceptFiles(bool WXUNUSED(accept
))
1221 // Returns the size of the native control. In the case of the toplevel window
1222 // this is the content area root control
1224 void wxWindowMac::MacGetPositionAndSizeFromControl(int& WXUNUSED(x
),
1227 int& WXUNUSED(h
)) const
1229 wxFAIL_MSG( wxT("Not currently supported") ) ;
1232 // From a wx position / size calculate the appropriate size of the native control
1234 bool wxWindowMac::MacGetBoundsForControl(
1238 int& w
, int& h
, bool adjustOrigin
) const
1240 // the desired size, minus the border pixels gives the correct size of the control
1244 // TODO: the default calls may be used as soon as PostCreateControl Is moved here
1245 w
= wxMax(size
.x
, 0) ; // WidthDefault( size.x );
1246 h
= wxMax(size
.y
, 0) ; // HeightDefault( size.y ) ;
1248 x
+= MacGetLeftBorderSize() ;
1249 y
+= MacGetTopBorderSize() ;
1250 w
-= MacGetLeftBorderSize() + MacGetRightBorderSize() ;
1251 h
-= MacGetTopBorderSize() + MacGetBottomBorderSize() ;
1254 AdjustForParentClientOrigin( x
, y
) ;
1256 // this is in window relative coordinate, as this parent may have a border, its physical position is offset by this border
1257 if ( !GetParent()->IsTopLevel() )
1259 x
-= GetParent()->MacGetLeftBorderSize() ;
1260 y
-= GetParent()->MacGetTopBorderSize() ;
1266 // Get window size (not client size)
1267 void wxWindowMac::DoGetSize(int *x
, int *y
) const
1270 m_peer
->GetRect( &bounds
) ;
1273 *x
= bounds
.right
- bounds
.left
+ MacGetLeftBorderSize() + MacGetRightBorderSize() ;
1275 *y
= bounds
.bottom
- bounds
.top
+ MacGetTopBorderSize() + MacGetBottomBorderSize() ;
1278 // get the position of the bounds of this window in client coordinates of its parent
1279 void wxWindowMac::DoGetPosition(int *x
, int *y
) const
1282 m_peer
->GetRect( &bounds
) ;
1284 int x1
= bounds
.left
;
1285 int y1
= bounds
.top
;
1287 // get the wx window position from the native one
1288 x1
-= MacGetLeftBorderSize() ;
1289 y1
-= MacGetTopBorderSize() ;
1291 if ( !IsTopLevel() )
1293 wxWindow
*parent
= GetParent();
1296 // we must first adjust it to be in window coordinates of the parent,
1297 // as otherwise it gets lost by the ClientAreaOrigin fix
1298 x1
+= parent
->MacGetLeftBorderSize() ;
1299 y1
+= parent
->MacGetTopBorderSize() ;
1301 // and now to client coordinates
1302 wxPoint
pt(parent
->GetClientAreaOrigin());
1314 void wxWindowMac::DoScreenToClient(int *x
, int *y
) const
1316 WindowRef window
= (WindowRef
) MacGetTopLevelWindowRef() ;
1317 wxCHECK_RET( window
, wxT("TopLevel Window missing") ) ;
1319 Point localwhere
= { 0, 0 } ;
1326 wxMacGlobalToLocal( window
, &localwhere
) ;
1333 MacRootWindowToWindow( x
, y
) ;
1335 wxPoint origin
= GetClientAreaOrigin() ;
1342 void wxWindowMac::DoClientToScreen(int *x
, int *y
) const
1344 WindowRef window
= (WindowRef
) MacGetTopLevelWindowRef() ;
1345 wxCHECK_RET( window
, wxT("TopLevel window missing") ) ;
1347 wxPoint origin
= GetClientAreaOrigin() ;
1353 MacWindowToRootWindow( x
, y
) ;
1355 Point localwhere
= { 0, 0 };
1361 wxMacLocalToGlobal( window
, &localwhere
) ;
1369 void wxWindowMac::MacClientToRootWindow( int *x
, int *y
) const
1371 wxPoint origin
= GetClientAreaOrigin() ;
1377 MacWindowToRootWindow( x
, y
) ;
1380 void wxWindowMac::MacRootWindowToClient( int *x
, int *y
) const
1382 MacRootWindowToWindow( x
, y
) ;
1384 wxPoint origin
= GetClientAreaOrigin() ;
1391 void wxWindowMac::MacWindowToRootWindow( int *x
, int *y
) const
1400 if ( !IsTopLevel() )
1402 wxTopLevelWindowMac
* top
= MacGetTopLevelWindow();
1405 pt
.x
-= MacGetLeftBorderSize() ;
1406 pt
.y
-= MacGetTopBorderSize() ;
1407 wxMacControl::Convert( &pt
, m_peer
, top
->m_peer
) ;
1417 void wxWindowMac::MacWindowToRootWindow( short *x
, short *y
) const
1426 MacWindowToRootWindow( &x1
, &y1
) ;
1434 void wxWindowMac::MacRootWindowToWindow( int *x
, int *y
) const
1443 if ( !IsTopLevel() )
1445 wxTopLevelWindowMac
* top
= MacGetTopLevelWindow();
1448 wxMacControl::Convert( &pt
, top
->m_peer
, m_peer
) ;
1449 pt
.x
+= MacGetLeftBorderSize() ;
1450 pt
.y
+= MacGetTopBorderSize() ;
1460 void wxWindowMac::MacRootWindowToWindow( short *x
, short *y
) const
1469 MacRootWindowToWindow( &x1
, &y1
) ;
1477 void wxWindowMac::MacGetContentAreaInset( int &left
, int &top
, int &right
, int &bottom
)
1479 RgnHandle rgn
= NewRgn() ;
1481 if ( m_peer
->GetRegion( kControlContentMetaPart
, rgn
) == noErr
)
1483 Rect structure
, content
;
1485 GetRegionBounds( rgn
, &content
) ;
1486 m_peer
->GetRect( &structure
) ;
1487 OffsetRect( &structure
, -structure
.left
, -structure
.top
) ;
1489 left
= content
.left
- structure
.left
;
1490 top
= content
.top
- structure
.top
;
1491 right
= structure
.right
- content
.right
;
1492 bottom
= structure
.bottom
- content
.bottom
;
1496 left
= top
= right
= bottom
= 0 ;
1502 wxSize
wxWindowMac::DoGetSizeFromClientSize( const wxSize
& size
) const
1504 wxSize sizeTotal
= size
;
1506 RgnHandle rgn
= NewRgn() ;
1507 if ( m_peer
->GetRegion( kControlContentMetaPart
, rgn
) == noErr
)
1509 Rect content
, structure
;
1510 GetRegionBounds( rgn
, &content
) ;
1511 m_peer
->GetRect( &structure
) ;
1513 // structure is in parent coordinates, but we only need width and height, so it's ok
1515 sizeTotal
.x
+= (structure
.right
- structure
.left
) - (content
.right
- content
.left
) ;
1516 sizeTotal
.y
+= (structure
.bottom
- structure
.top
) - (content
.bottom
- content
.top
) ;
1521 sizeTotal
.x
+= MacGetLeftBorderSize() + MacGetRightBorderSize() ;
1522 sizeTotal
.y
+= MacGetTopBorderSize() + MacGetBottomBorderSize() ;
1527 // Get size *available for subwindows* i.e. excluding menu bar etc.
1528 void wxWindowMac::DoGetClientSize( int *x
, int *y
) const
1532 RgnHandle rgn
= NewRgn() ;
1534 if ( m_peer
->GetRegion( kControlContentMetaPart
, rgn
) == noErr
)
1535 GetRegionBounds( rgn
, &content
) ;
1537 m_peer
->GetRect( &content
) ;
1540 ww
= content
.right
- content
.left
;
1541 hh
= content
.bottom
- content
.top
;
1543 if (m_hScrollBar
&& m_hScrollBar
->IsShown() )
1544 hh
-= m_hScrollBar
->GetSize().y
;
1546 if (m_vScrollBar
&& m_vScrollBar
->IsShown() )
1547 ww
-= m_vScrollBar
->GetSize().x
;
1555 bool wxWindowMac::SetCursor(const wxCursor
& cursor
)
1557 if (m_cursor
.IsSameAs(cursor
))
1562 if ( ! wxWindowBase::SetCursor( *wxSTANDARD_CURSOR
) )
1567 if ( ! wxWindowBase::SetCursor( cursor
) )
1571 wxASSERT_MSG( m_cursor
.Ok(),
1572 wxT("cursor must be valid after call to the base version"));
1574 wxWindowMac
*mouseWin
= 0 ;
1576 wxTopLevelWindowMac
*tlw
= MacGetTopLevelWindow() ;
1577 WindowRef window
= (WindowRef
) ( tlw
? tlw
->MacGetWindowRef() : 0 ) ;
1579 ControlPartCode part
;
1580 ControlRef control
;
1582 #if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
1584 HIGetMousePosition(kHICoordSpaceWindow
, window
, &hiPoint
);
1588 GetGlobalMouse( &pt
);
1591 ScreenToClient(&x
, &y
);
1595 control
= FindControlUnderMouse( pt
, window
, &part
) ;
1597 mouseWin
= wxFindControlFromMacControl( control
) ;
1601 if ( mouseWin
== this && !wxIsBusy() )
1602 m_cursor
.MacInstall() ;
1608 bool wxWindowMac::DoPopupMenu(wxMenu
*menu
, int x
, int y
)
1610 #ifndef __WXUNIVERSAL__
1611 menu
->SetInvokingWindow((wxWindow
*)this);
1614 if ( x
== wxDefaultCoord
&& y
== wxDefaultCoord
)
1616 wxPoint mouse
= wxGetMousePosition();
1622 ClientToScreen( &x
, &y
) ;
1625 menu
->MacBeforeDisplay( true ) ;
1626 long menuResult
= ::PopUpMenuSelect((MenuHandle
) menu
->GetHMenu() , y
, x
, 0) ;
1627 if ( HiWord(menuResult
) != 0 )
1630 GetMenuItemCommandID( GetMenuHandle(HiWord(menuResult
)) , LoWord(menuResult
) , &macid
);
1631 int id
= wxMacCommandToId( macid
);
1632 wxMenuItem
* item
= NULL
;
1634 item
= menu
->FindItem( id
, &realmenu
) ;
1637 if (item
->IsCheckable())
1638 item
->Check( !item
->IsChecked() ) ;
1640 menu
->SendEvent( id
, item
->IsCheckable() ? item
->IsChecked() : -1 ) ;
1644 menu
->MacAfterDisplay( true ) ;
1645 menu
->SetInvokingWindow( NULL
);
1649 // actually this shouldn't be called, because universal is having its own implementation
1655 // ----------------------------------------------------------------------------
1657 // ----------------------------------------------------------------------------
1661 void wxWindowMac::DoSetToolTip(wxToolTip
*tooltip
)
1663 wxWindowBase::DoSetToolTip(tooltip
);
1666 m_tooltip
->SetWindow(this);
1671 void wxWindowMac::MacInvalidateBorders()
1673 if ( m_peer
== NULL
)
1676 bool vis
= MacIsReallyShown() ;
1680 int outerBorder
= MacGetLeftBorderSize() ;
1681 if ( m_peer
->NeedsFocusRect() /* && m_peer->HasFocus() */ )
1684 if ( outerBorder
== 0 )
1687 // now we know that we have something to do at all
1689 // as the borders are drawn on the parent we have to properly invalidate all these areas
1690 RgnHandle updateInner
, updateOuter
;
1693 // this rectangle is in HIViewCoordinates under OSX and in Window Coordinates under Carbon
1694 updateInner
= NewRgn() ;
1695 updateOuter
= NewRgn() ;
1697 m_peer
->GetRect( &rect
) ;
1698 RectRgn( updateInner
, &rect
) ;
1699 InsetRect( &rect
, -outerBorder
, -outerBorder
) ;
1700 RectRgn( updateOuter
, &rect
) ;
1701 DiffRgn( updateOuter
, updateInner
, updateOuter
) ;
1703 GetParent()->m_peer
->SetNeedsDisplay( updateOuter
) ;
1705 DisposeRgn( updateOuter
) ;
1706 DisposeRgn( updateInner
) ;
1709 void wxWindowMac::DoMoveWindow(int x
, int y
, int width
, int height
)
1711 // this is never called for a toplevel window, so we know we have a parent
1712 int former_x
, former_y
, former_w
, former_h
;
1714 // Get true coordinates of former position
1715 DoGetPosition( &former_x
, &former_y
) ;
1716 DoGetSize( &former_w
, &former_h
) ;
1718 wxWindow
*parent
= GetParent();
1721 wxPoint
pt(parent
->GetClientAreaOrigin());
1726 int actualWidth
= width
;
1727 int actualHeight
= height
;
1731 if ((m_minWidth
!= -1) && (actualWidth
< m_minWidth
))
1732 actualWidth
= m_minWidth
;
1733 if ((m_minHeight
!= -1) && (actualHeight
< m_minHeight
))
1734 actualHeight
= m_minHeight
;
1735 if ((m_maxWidth
!= -1) && (actualWidth
> m_maxWidth
))
1736 actualWidth
= m_maxWidth
;
1737 if ((m_maxHeight
!= -1) && (actualHeight
> m_maxHeight
))
1738 actualHeight
= m_maxHeight
;
1740 bool doMove
= false, doResize
= false ;
1742 if ( actualX
!= former_x
|| actualY
!= former_y
)
1745 if ( actualWidth
!= former_w
|| actualHeight
!= former_h
)
1748 if ( doMove
|| doResize
)
1750 // as the borders are drawn outside the native control, we adjust now
1752 wxRect
bounds( wxPoint( actualX
+ MacGetLeftBorderSize() ,actualY
+ MacGetTopBorderSize() ),
1753 wxSize( actualWidth
- (MacGetLeftBorderSize() + MacGetRightBorderSize()) ,
1754 actualHeight
- (MacGetTopBorderSize() + MacGetBottomBorderSize()) ) ) ;
1757 wxMacRectToNative( &bounds
, &r
) ;
1759 if ( !GetParent()->IsTopLevel() )
1760 wxMacWindowToNative( GetParent() , &r
) ;
1762 MacInvalidateBorders() ;
1764 m_cachedClippedRectValid
= false ;
1765 m_peer
->SetRect( &r
) ;
1767 wxWindowMac::MacSuperChangedPosition() ; // like this only children will be notified
1769 MacInvalidateBorders() ;
1771 MacRepositionScrollBars() ;
1774 wxPoint
point(actualX
, actualY
);
1775 wxMoveEvent
event(point
, m_windowId
);
1776 event
.SetEventObject(this);
1777 HandleWindowEvent(event
) ;
1782 MacRepositionScrollBars() ;
1783 wxSize
size(actualWidth
, actualHeight
);
1784 wxSizeEvent
event(size
, m_windowId
);
1785 event
.SetEventObject(this);
1786 HandleWindowEvent(event
);
1791 wxSize
wxWindowMac::DoGetBestSize() const
1793 if ( m_macIsUserPane
|| IsTopLevel() )
1794 return wxWindowBase::DoGetBestSize() ;
1796 Rect bestsize
= { 0 , 0 , 0 , 0 } ;
1797 int bestWidth
, bestHeight
;
1799 m_peer
->GetBestRect( &bestsize
) ;
1800 if ( EmptyRect( &bestsize
) )
1805 bestsize
.bottom
= 16 ;
1807 if ( IsKindOf( CLASSINFO( wxScrollBar
) ) )
1809 bestsize
.bottom
= 16 ;
1812 else if ( IsKindOf( CLASSINFO( wxSpinButton
) ) )
1814 bestsize
.bottom
= 24 ;
1819 // return wxWindowBase::DoGetBestSize() ;
1823 bestWidth
= bestsize
.right
- bestsize
.left
;
1824 bestHeight
= bestsize
.bottom
- bestsize
.top
;
1825 if ( bestHeight
< 10 )
1828 return wxSize(bestWidth
, bestHeight
);
1831 // set the size of the window: if the dimensions are positive, just use them,
1832 // but if any of them is equal to -1, it means that we must find the value for
1833 // it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in
1834 // which case -1 is a valid value for x and y)
1836 // If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate
1837 // the width/height to best suit our contents, otherwise we reuse the current
1839 void wxWindowMac::DoSetSize(int x
, int y
, int width
, int height
, int sizeFlags
)
1841 // get the current size and position...
1842 int currentX
, currentY
;
1843 int currentW
, currentH
;
1845 GetPosition(¤tX
, ¤tY
);
1846 GetSize(¤tW
, ¤tH
);
1848 // ... and don't do anything (avoiding flicker) if it's already ok
1849 if ( x
== currentX
&& y
== currentY
&&
1850 width
== currentW
&& height
== currentH
&& ( height
!= -1 && width
!= -1 ) )
1853 MacRepositionScrollBars() ; // we might have a real position shift
1858 if ( !(sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) )
1860 if ( x
== wxDefaultCoord
)
1862 if ( y
== wxDefaultCoord
)
1866 AdjustForParentClientOrigin( x
, y
, sizeFlags
);
1868 wxSize size
= wxDefaultSize
;
1869 if ( width
== wxDefaultCoord
)
1871 if ( sizeFlags
& wxSIZE_AUTO_WIDTH
)
1873 size
= DoGetBestSize();
1878 // just take the current one
1883 if ( height
== wxDefaultCoord
)
1885 if ( sizeFlags
& wxSIZE_AUTO_HEIGHT
)
1887 if ( size
.x
== wxDefaultCoord
)
1888 size
= DoGetBestSize();
1889 // else: already called DoGetBestSize() above
1895 // just take the current one
1900 DoMoveWindow( x
, y
, width
, height
);
1903 wxPoint
wxWindowMac::GetClientAreaOrigin() const
1905 RgnHandle rgn
= NewRgn() ;
1907 if ( m_peer
->GetRegion( kControlContentMetaPart
, rgn
) == noErr
)
1909 GetRegionBounds( rgn
, &content
) ;
1919 return wxPoint( content
.left
+ MacGetLeftBorderSize() , content
.top
+ MacGetTopBorderSize() );
1922 void wxWindowMac::DoSetClientSize(int clientwidth
, int clientheight
)
1924 if ( clientwidth
!= wxDefaultCoord
|| clientheight
!= wxDefaultCoord
)
1926 int currentclientwidth
, currentclientheight
;
1927 int currentwidth
, currentheight
;
1929 GetClientSize( ¤tclientwidth
, ¤tclientheight
) ;
1930 GetSize( ¤twidth
, ¤theight
) ;
1932 DoSetSize( wxDefaultCoord
, wxDefaultCoord
, currentwidth
+ clientwidth
- currentclientwidth
,
1933 currentheight
+ clientheight
- currentclientheight
, wxSIZE_USE_EXISTING
) ;
1937 void wxWindowMac::SetLabel(const wxString
& title
)
1941 if ( m_peer
&& m_peer
->Ok() )
1942 m_peer
->SetLabel( wxStripMenuCodes(m_label
, wxStrip_Mnemonics
) ) ;
1944 // do not trigger refreshes upon invisible and possible partly created objects
1945 if ( MacIsReallyShown() )
1949 wxString
wxWindowMac::GetLabel() const
1954 bool wxWindowMac::Show(bool show
)
1956 if ( !wxWindowBase::Show(show
) )
1960 m_peer
->SetVisibility( show
, true ) ;
1965 void wxWindowMac::DoEnable(bool enable
)
1967 m_peer
->Enable( enable
) ;
1971 // status change notifications
1974 void wxWindowMac::MacVisibilityChanged()
1978 void wxWindowMac::MacHiliteChanged()
1982 void wxWindowMac::MacEnabledStateChanged()
1984 OnEnabled( m_peer
->IsEnabled() );
1988 // status queries on the inherited window's state
1991 bool wxWindowMac::MacIsReallyShown()
1993 // only under OSX the visibility of the TLW is taken into account
1994 if ( m_isBeingDeleted
)
1997 #if TARGET_API_MAC_OSX
1998 if ( m_peer
&& m_peer
->Ok() )
1999 return m_peer
->IsVisible();
2002 wxWindow
* win
= this ;
2003 while ( win
->IsShown() )
2005 if ( win
->IsTopLevel() )
2008 win
= win
->GetParent() ;
2016 bool wxWindowMac::MacIsReallyEnabled()
2018 return m_peer
->IsEnabled() ;
2021 bool wxWindowMac::MacIsReallyHilited()
2023 return m_peer
->IsActive();
2026 void wxWindowMac::MacFlashInvalidAreas()
2028 #if TARGET_API_MAC_OSX
2029 HIViewFlashDirtyArea( (WindowRef
) MacGetTopLevelWindowRef() ) ;
2033 int wxWindowMac::GetCharHeight() const
2035 wxClientDC
dc( (wxWindowMac
*)this ) ;
2037 return dc
.GetCharHeight() ;
2040 int wxWindowMac::GetCharWidth() const
2042 wxClientDC
dc( (wxWindowMac
*)this ) ;
2044 return dc
.GetCharWidth() ;
2047 void wxWindowMac::GetTextExtent(const wxString
& string
, int *x
, int *y
,
2048 int *descent
, int *externalLeading
, const wxFont
*theFont
) const
2050 const wxFont
*fontToUse
= theFont
;
2052 fontToUse
= &m_font
;
2054 wxClientDC
dc( (wxWindowMac
*) this ) ;
2055 wxCoord lx
,ly
,ld
,le
;
2056 dc
.GetTextExtent( string
, &lx
, &ly
, &ld
, &le
, (wxFont
*)fontToUse
) ;
2057 if ( externalLeading
)
2058 *externalLeading
= le
;
2068 * Rect is given in client coordinates, for further reading, read wxTopLevelWindowMac::InvalidateRect
2069 * we always intersect with the entire window, not only with the client area
2072 void wxWindowMac::Refresh(bool WXUNUSED(eraseBack
), const wxRect
*rect
)
2074 if ( m_peer
== NULL
)
2077 if ( !MacIsReallyShown() )
2084 wxMacRectToNative( rect
, &r
) ;
2085 m_peer
->SetNeedsDisplay( &r
) ;
2089 m_peer
->SetNeedsDisplay() ;
2093 void wxWindowMac::DoFreeze()
2095 #if TARGET_API_MAC_OSX
2096 if ( m_peer
&& m_peer
->Ok() )
2097 m_peer
->SetDrawingEnabled( false ) ;
2101 void wxWindowMac::DoThaw()
2103 #if TARGET_API_MAC_OSX
2104 if ( m_peer
&& m_peer
->Ok() )
2106 m_peer
->SetDrawingEnabled( true ) ;
2107 m_peer
->InvalidateWithChildren() ;
2112 wxWindowMac
*wxGetActiveWindow()
2114 // actually this is a windows-only concept
2118 // Coordinates relative to the window
2119 void wxWindowMac::WarpPointer(int WXUNUSED(x_pos
), int WXUNUSED(y_pos
))
2121 // We really don't move the mouse programmatically under Mac.
2124 void wxWindowMac::OnEraseBackground(wxEraseEvent
& event
)
2126 if ( MacGetTopLevelWindow() == NULL
)
2129 #if TARGET_API_MAC_OSX
2130 if ( !m_backgroundColour.Ok() || GetBackgroundStyle() == wxBG_STYLE_TRANSPARENT )
2136 if ( GetBackgroundStyle() == wxBG_STYLE_COLOUR
)
2138 event
.GetDC()->Clear() ;
2146 void wxWindowMac::OnNcPaint( wxNcPaintEvent
& event
)
2151 int wxWindowMac::GetScrollPos(int orient
) const
2153 if ( orient
== wxHORIZONTAL
)
2156 return m_hScrollBar
->GetThumbPosition() ;
2161 return m_vScrollBar
->GetThumbPosition() ;
2167 // This now returns the whole range, not just the number
2168 // of positions that we can scroll.
2169 int wxWindowMac::GetScrollRange(int orient
) const
2171 if ( orient
== wxHORIZONTAL
)
2174 return m_hScrollBar
->GetRange() ;
2179 return m_vScrollBar
->GetRange() ;
2185 int wxWindowMac::GetScrollThumb(int orient
) const
2187 if ( orient
== wxHORIZONTAL
)
2190 return m_hScrollBar
->GetThumbSize() ;
2195 return m_vScrollBar
->GetThumbSize() ;
2201 void wxWindowMac::SetScrollPos(int orient
, int pos
, bool WXUNUSED(refresh
))
2203 if ( orient
== wxHORIZONTAL
)
2206 m_hScrollBar
->SetThumbPosition( pos
) ;
2211 m_vScrollBar
->SetThumbPosition( pos
) ;
2216 wxWindowMac::AlwaysShowScrollbars(bool hflag
, bool vflag
)
2218 bool needVisibilityUpdate
= false;
2220 if ( m_hScrollBarAlwaysShown
!= hflag
)
2222 m_hScrollBarAlwaysShown
= hflag
;
2223 needVisibilityUpdate
= true;
2226 if ( m_vScrollBarAlwaysShown
!= vflag
)
2228 m_vScrollBarAlwaysShown
= vflag
;
2229 needVisibilityUpdate
= true;
2232 if ( needVisibilityUpdate
)
2233 DoUpdateScrollbarVisibility();
2237 // we draw borders and grow boxes, are already set up and clipped in the current port / cgContextRef
2238 // our own window origin is at leftOrigin/rightOrigin
2241 void wxWindowMac::MacPaintGrowBox()
2246 if ( MacHasScrollBarCorner() )
2250 CGContextRef cgContext
= (CGContextRef
) MacGetCGContextRef() ;
2251 wxASSERT( cgContext
) ;
2253 m_peer
->GetRect( &rect
) ;
2255 int size
= m_hScrollBar
? m_hScrollBar
->GetSize().y
: ( m_vScrollBar
? m_vScrollBar
->GetSize().x
: MAC_SCROLLBAR_SIZE
) ;
2256 CGRect cgrect
= CGRectMake( rect
.right
- size
, rect
.bottom
- size
, size
, size
) ;
2257 CGPoint cgpoint
= CGPointMake( rect
.right
- size
, rect
.bottom
- size
) ;
2258 CGContextSaveGState( cgContext
);
2260 if ( m_backgroundColour
.Ok() )
2262 CGContextSetFillColorWithColor( cgContext
, m_backgroundColour
.GetCGColor() );
2266 CGContextSetRGBFillColor( cgContext
, 1.0, 1.0 , 1.0 , 1.0 );
2268 CGContextFillRect( cgContext
, cgrect
);
2269 CGContextRestoreGState( cgContext
);
2273 void wxWindowMac::MacPaintBorders( int WXUNUSED(leftOrigin
) , int WXUNUSED(rightOrigin
) )
2279 bool hasFocus
= m_peer
->NeedsFocusRect() && m_peer
->HasFocus() ;
2281 // back to the surrounding frame rectangle
2282 m_peer
->GetRect( &rect
) ;
2283 InsetRect( &rect
, -1 , -1 ) ;
2286 CGRect cgrect
= CGRectMake( rect
.left
, rect
.top
, rect
.right
- rect
.left
,
2287 rect
.bottom
- rect
.top
) ;
2289 HIThemeFrameDrawInfo info
;
2290 memset( &info
, 0 , sizeof(info
) ) ;
2294 info
.state
= IsEnabled() ? kThemeStateActive
: kThemeStateInactive
;
2295 info
.isFocused
= hasFocus
;
2297 CGContextRef cgContext
= (CGContextRef
) GetParent()->MacGetCGContextRef() ;
2298 wxASSERT( cgContext
) ;
2300 if ( HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
) || HasFlag(wxDOUBLE_BORDER
) )
2302 info
.kind
= kHIThemeFrameTextFieldSquare
;
2303 HIThemeDrawFrame( &cgrect
, &info
, cgContext
, kHIThemeOrientationNormal
) ;
2305 else if ( HasFlag(wxSIMPLE_BORDER
) )
2307 info
.kind
= kHIThemeFrameListBox
;
2308 HIThemeDrawFrame( &cgrect
, &info
, cgContext
, kHIThemeOrientationNormal
) ;
2310 else if ( hasFocus
)
2312 HIThemeDrawFocusRect( &cgrect
, true , cgContext
, kHIThemeOrientationNormal
) ;
2314 #if 0 // TODO REMOVE now done in a separate call earlier in drawing the window itself
2315 m_peer
->GetRect( &rect
) ;
2316 if ( MacHasScrollBarCorner() )
2318 int variant
= (m_hScrollBar
== NULL
? m_vScrollBar
: m_hScrollBar
) ->GetWindowVariant();
2319 int size
= m_hScrollBar
? m_hScrollBar
->GetSize().y
: ( m_vScrollBar
? m_vScrollBar
->GetSize().x
: MAC_SCROLLBAR_SIZE
) ;
2320 CGRect cgrect
= CGRectMake( rect
.right
- size
, rect
.bottom
- size
, size
, size
) ;
2321 CGPoint cgpoint
= CGPointMake( rect
.right
- size
, rect
.bottom
- size
) ;
2322 HIThemeGrowBoxDrawInfo info
;
2323 memset( &info
, 0, sizeof(info
) ) ;
2325 info
.state
= IsEnabled() ? kThemeStateActive
: kThemeStateInactive
;
2326 info
.kind
= kHIThemeGrowBoxKindNone
;
2327 // contrary to the docs ...SizeSmall does not work
2328 info
.size
= kHIThemeGrowBoxSizeNormal
;
2329 info
.direction
= 0 ;
2330 HIThemeDrawGrowBox( &cgpoint
, &info
, cgContext
, kHIThemeOrientationNormal
) ;
2336 void wxWindowMac::RemoveChild( wxWindowBase
*child
)
2338 if ( child
== m_hScrollBar
)
2339 m_hScrollBar
= NULL
;
2340 if ( child
== m_vScrollBar
)
2341 m_vScrollBar
= NULL
;
2343 wxWindowBase::RemoveChild( child
) ;
2346 void wxWindowMac::DoUpdateScrollbarVisibility()
2348 bool triggerSizeEvent
= false;
2352 bool showHScrollBar
= m_hScrollBarAlwaysShown
|| m_hScrollBar
->IsNeeded();
2354 if ( m_hScrollBar
->IsShown() != showHScrollBar
)
2356 m_hScrollBar
->Show( showHScrollBar
);
2357 triggerSizeEvent
= true;
2363 bool showVScrollBar
= m_vScrollBarAlwaysShown
|| m_vScrollBar
->IsNeeded();
2365 if ( m_vScrollBar
->IsShown() != showVScrollBar
)
2367 m_vScrollBar
->Show( showVScrollBar
) ;
2368 triggerSizeEvent
= true;
2372 MacRepositionScrollBars() ;
2373 if ( triggerSizeEvent
)
2375 wxSizeEvent
event(GetSize(), m_windowId
);
2376 event
.SetEventObject(this);
2377 HandleWindowEvent(event
);
2381 // New function that will replace some of the above.
2382 void wxWindowMac::SetScrollbar(int orient
, int pos
, int thumb
,
2383 int range
, bool refresh
)
2385 if ( orient
== wxHORIZONTAL
&& m_hScrollBar
)
2386 m_hScrollBar
->SetScrollbar(pos
, thumb
, range
, thumb
, refresh
);
2387 else if ( orient
== wxVERTICAL
&& m_vScrollBar
)
2388 m_vScrollBar
->SetScrollbar(pos
, thumb
, range
, thumb
, refresh
);
2390 DoUpdateScrollbarVisibility();
2393 // Does a physical scroll
2394 void wxWindowMac::ScrollWindow(int dx
, int dy
, const wxRect
*rect
)
2396 if ( dx
== 0 && dy
== 0 )
2399 int width
, height
;
2400 GetClientSize( &width
, &height
) ;
2403 // note there currently is a bug in OSX which makes inefficient refreshes in case an entire control
2404 // area is scrolled, this does not occur if width and height are 2 pixels less,
2405 // TODO: write optimal workaround
2406 wxRect
scrollrect( MacGetLeftBorderSize() , MacGetTopBorderSize() , width
, height
) ;
2408 scrollrect
.Intersect( *rect
) ;
2410 if ( m_peer
->GetNeedsDisplay() )
2412 // because HIViewScrollRect does not scroll the already invalidated area we have two options:
2413 // in case there is already a pending redraw on that area
2414 // either immediate redraw or full invalidate
2416 // is the better overall solution, as it does not slow down scrolling
2417 m_peer
->SetNeedsDisplay() ;
2419 // this would be the preferred version for fast drawing controls
2420 HIViewRender(m_peer
->GetControlRef()) ;
2424 // as the native control might be not a 0/0 wx window coordinates, we have to offset
2425 scrollrect
.Offset( -MacGetLeftBorderSize() , -MacGetTopBorderSize() ) ;
2426 m_peer
->ScrollRect( &scrollrect
, dx
, dy
) ;
2429 // this would be the preferred version for fast drawing controls
2430 HIViewRender(m_peer
->GetControlRef()) ;
2436 for (wxWindowList::compatibility_iterator node
= GetChildren().GetFirst(); node
; node
= node
->GetNext())
2438 child
= node
->GetData();
2441 if (child
== m_vScrollBar
)
2443 if (child
== m_hScrollBar
)
2445 if (child
->IsTopLevel())
2448 child
->GetPosition( &x
, &y
);
2449 child
->GetSize( &w
, &h
);
2452 wxRect
rc( x
, y
, w
, h
);
2453 if (rect
->Intersects( rc
))
2454 child
->SetSize( x
+ dx
, y
+ dy
, w
, h
, wxSIZE_AUTO
|wxSIZE_ALLOW_MINUS_ONE
);
2458 child
->SetSize( x
+ dx
, y
+ dy
, w
, h
, wxSIZE_AUTO
|wxSIZE_ALLOW_MINUS_ONE
);
2463 void wxWindowMac::MacOnScroll( wxScrollEvent
&event
)
2465 if ( event
.GetEventObject() == m_vScrollBar
|| event
.GetEventObject() == m_hScrollBar
)
2467 wxScrollWinEvent wevent
;
2468 wevent
.SetPosition(event
.GetPosition());
2469 wevent
.SetOrientation(event
.GetOrientation());
2470 wevent
.SetEventObject(this);
2472 if (event
.GetEventType() == wxEVT_SCROLL_TOP
)
2473 wevent
.SetEventType( wxEVT_SCROLLWIN_TOP
);
2474 else if (event
.GetEventType() == wxEVT_SCROLL_BOTTOM
)
2475 wevent
.SetEventType( wxEVT_SCROLLWIN_BOTTOM
);
2476 else if (event
.GetEventType() == wxEVT_SCROLL_LINEUP
)
2477 wevent
.SetEventType( wxEVT_SCROLLWIN_LINEUP
);
2478 else if (event
.GetEventType() == wxEVT_SCROLL_LINEDOWN
)
2479 wevent
.SetEventType( wxEVT_SCROLLWIN_LINEDOWN
);
2480 else if (event
.GetEventType() == wxEVT_SCROLL_PAGEUP
)
2481 wevent
.SetEventType( wxEVT_SCROLLWIN_PAGEUP
);
2482 else if (event
.GetEventType() == wxEVT_SCROLL_PAGEDOWN
)
2483 wevent
.SetEventType( wxEVT_SCROLLWIN_PAGEDOWN
);
2484 else if (event
.GetEventType() == wxEVT_SCROLL_THUMBTRACK
)
2485 wevent
.SetEventType( wxEVT_SCROLLWIN_THUMBTRACK
);
2486 else if (event
.GetEventType() == wxEVT_SCROLL_THUMBRELEASE
)
2487 wevent
.SetEventType( wxEVT_SCROLLWIN_THUMBRELEASE
);
2489 HandleWindowEvent(wevent
);
2493 // Get the window with the focus
2494 wxWindowMac
*wxWindowBase::DoFindFocus()
2496 ControlRef control
;
2497 GetKeyboardFocus( GetUserFocusWindow() , &control
) ;
2498 return wxFindControlFromMacControl( control
) ;
2501 void wxWindowMac::OnInternalIdle()
2503 // This calls the UI-update mechanism (querying windows for
2504 // menu/toolbar/control state information)
2505 if (wxUpdateUIEvent::CanUpdate(this) && IsShownOnScreen())
2506 UpdateWindowUI(wxUPDATE_UI_FROMIDLE
);
2509 // Raise the window to the top of the Z order
2510 void wxWindowMac::Raise()
2512 m_peer
->SetZOrder( true , NULL
) ;
2515 // Lower the window to the bottom of the Z order
2516 void wxWindowMac::Lower()
2518 m_peer
->SetZOrder( false , NULL
) ;
2521 // static wxWindow *gs_lastWhich = NULL;
2523 bool wxWindowMac::MacSetupCursor( const wxPoint
& pt
)
2525 // first trigger a set cursor event
2527 wxPoint clientorigin
= GetClientAreaOrigin() ;
2528 wxSize clientsize
= GetClientSize() ;
2530 if ( wxRect2DInt( clientorigin
.x
, clientorigin
.y
, clientsize
.x
, clientsize
.y
).Contains( wxPoint2DInt( pt
) ) )
2532 wxSetCursorEvent
event( pt
.x
, pt
.y
);
2534 bool processedEvtSetCursor
= HandleWindowEvent(event
);
2535 if ( processedEvtSetCursor
&& event
.HasCursor() )
2537 cursor
= event
.GetCursor() ;
2541 // the test for processedEvtSetCursor is here to prevent using m_cursor
2542 // if the user code caught EVT_SET_CURSOR() and returned nothing from
2543 // it - this is a way to say that our cursor shouldn't be used for this
2545 if ( !processedEvtSetCursor
&& m_cursor
.Ok() )
2548 if ( !wxIsBusy() && !GetParent() )
2549 cursor
= *wxSTANDARD_CURSOR
;
2553 cursor
.MacInstall() ;
2556 return cursor
.Ok() ;
2559 wxString
wxWindowMac::MacGetToolTipString( wxPoint
&WXUNUSED(pt
) )
2563 return m_tooltip
->GetTip() ;
2566 return wxEmptyString
;
2569 void wxWindowMac::ClearBackground()
2575 void wxWindowMac::Update()
2577 wxTopLevelWindowMac
* top
= MacGetTopLevelWindow();
2579 top
->MacPerformUpdates() ;
2582 wxTopLevelWindowMac
* wxWindowMac::MacGetTopLevelWindow() const
2584 wxTopLevelWindowMac
* win
= NULL
;
2585 WindowRef window
= (WindowRef
) MacGetTopLevelWindowRef() ;
2587 win
= wxFindWinFromMacWindow( window
) ;
2592 const wxRect
& wxWindowMac::MacGetClippedClientRect() const
2594 MacUpdateClippedRects() ;
2596 return m_cachedClippedClientRect
;
2599 const wxRect
& wxWindowMac::MacGetClippedRect() const
2601 MacUpdateClippedRects() ;
2603 return m_cachedClippedRect
;
2606 const wxRect
&wxWindowMac:: MacGetClippedRectWithOuterStructure() const
2608 MacUpdateClippedRects() ;
2610 return m_cachedClippedRectWithOuterStructure
;
2613 const wxRegion
& wxWindowMac::MacGetVisibleRegion( bool includeOuterStructures
)
2615 static wxRegion emptyrgn
;
2617 if ( !m_isBeingDeleted
&& MacIsReallyShown() /*m_peer->IsVisible() */ )
2619 MacUpdateClippedRects() ;
2620 if ( includeOuterStructures
)
2621 return m_cachedClippedRegionWithOuterStructure
;
2623 return m_cachedClippedRegion
;
2631 void wxWindowMac::MacUpdateClippedRects() const
2633 if ( m_cachedClippedRectValid
)
2636 // includeOuterStructures is true if we try to draw somthing like a focus ring etc.
2637 // also a window dc uses this, in this case we only clip in the hierarchy for hard
2638 // borders like a scrollwindow, splitter etc otherwise we end up in a paranoia having
2639 // to add focus borders everywhere
2641 Rect r
, rIncludingOuterStructures
;
2643 m_peer
->GetRect( &r
) ;
2644 r
.left
-= MacGetLeftBorderSize() ;
2645 r
.top
-= MacGetTopBorderSize() ;
2646 r
.bottom
+= MacGetBottomBorderSize() ;
2647 r
.right
+= MacGetRightBorderSize() ;
2654 rIncludingOuterStructures
= r
;
2655 InsetRect( &rIncludingOuterStructures
, -4 , -4 ) ;
2657 wxRect cl
= GetClientRect() ;
2658 Rect rClient
= { cl
.y
, cl
.x
, cl
.y
+ cl
.height
, cl
.x
+ cl
.width
} ;
2662 const wxWindow
* child
= this ;
2663 const wxWindow
* parent
= NULL
;
2665 while ( !child
->IsTopLevel() && ( parent
= child
->GetParent() ) != NULL
)
2667 if ( parent
->MacIsChildOfClientArea(child
) )
2669 size
= parent
->GetClientSize() ;
2670 wxPoint origin
= parent
->GetClientAreaOrigin() ;
2676 // this will be true for scrollbars, toolbars etc.
2677 size
= parent
->GetSize() ;
2678 y
= parent
->MacGetTopBorderSize() ;
2679 x
= parent
->MacGetLeftBorderSize() ;
2680 size
.x
-= parent
->MacGetLeftBorderSize() + parent
->MacGetRightBorderSize() ;
2681 size
.y
-= parent
->MacGetTopBorderSize() + parent
->MacGetBottomBorderSize() ;
2684 parent
->MacWindowToRootWindow( &x
, &y
) ;
2685 MacRootWindowToWindow( &x
, &y
) ;
2687 Rect rparent
= { y
, x
, y
+ size
.y
, x
+ size
.x
} ;
2689 // the wxwindow and client rects will always be clipped
2690 SectRect( &r
, &rparent
, &r
) ;
2691 SectRect( &rClient
, &rparent
, &rClient
) ;
2693 // the structure only at 'hard' borders
2694 if ( parent
->MacClipChildren() ||
2695 ( parent
->GetParent() && parent
->GetParent()->MacClipGrandChildren() ) )
2697 SectRect( &rIncludingOuterStructures
, &rparent
, &rIncludingOuterStructures
) ;
2703 m_cachedClippedRect
= wxRect( r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
) ;
2704 m_cachedClippedClientRect
= wxRect( rClient
.left
, rClient
.top
,
2705 rClient
.right
- rClient
.left
, rClient
.bottom
- rClient
.top
) ;
2706 m_cachedClippedRectWithOuterStructure
= wxRect(
2707 rIncludingOuterStructures
.left
, rIncludingOuterStructures
.top
,
2708 rIncludingOuterStructures
.right
- rIncludingOuterStructures
.left
,
2709 rIncludingOuterStructures
.bottom
- rIncludingOuterStructures
.top
) ;
2711 m_cachedClippedRegionWithOuterStructure
= wxRegion( m_cachedClippedRectWithOuterStructure
) ;
2712 m_cachedClippedRegion
= wxRegion( m_cachedClippedRect
) ;
2713 m_cachedClippedClientRegion
= wxRegion( m_cachedClippedClientRect
) ;
2715 m_cachedClippedRectValid
= true ;
2719 This function must not change the updatergn !
2721 bool wxWindowMac::MacDoRedraw( void* updatergnr
, long time
)
2723 bool handled
= false ;
2725 RgnHandle updatergn
= (RgnHandle
) updatergnr
;
2726 GetRegionBounds( updatergn
, &updatebounds
) ;
2728 // wxLogDebug(wxT("update for %s bounds %d, %d, %d, %d"), wxString(GetClassInfo()->GetClassName()).c_str(), updatebounds.left, updatebounds.top , updatebounds.right , updatebounds.bottom ) ;
2730 if ( !EmptyRgn(updatergn
) )
2732 RgnHandle newupdate
= NewRgn() ;
2733 wxSize point
= GetClientSize() ;
2734 wxPoint origin
= GetClientAreaOrigin() ;
2735 SetRectRgn( newupdate
, origin
.x
, origin
.y
, origin
.x
+ point
.x
, origin
.y
+ point
.y
) ;
2736 SectRgn( newupdate
, updatergn
, newupdate
) ;
2738 // first send an erase event to the entire update area
2740 // for the toplevel window this really is the entire area
2741 // for all the others only their client area, otherwise they
2742 // might be drawing with full alpha and eg put blue into
2743 // the grow-box area of a scrolled window (scroll sample)
2744 wxDC
* dc
= new wxWindowDC(this);
2746 dc
->SetClippingRegion(wxRegion(HIShapeCreateWithQDRgn(updatergn
)));
2748 dc
->SetClippingRegion(wxRegion(HIShapeCreateWithQDRgn(newupdate
)));
2750 wxEraseEvent
eevent( GetId(), dc
);
2751 eevent
.SetEventObject( this );
2752 HandleWindowEvent( eevent
);
2758 // calculate a client-origin version of the update rgn and set m_updateRegion to that
2759 OffsetRgn( newupdate
, -origin
.x
, -origin
.y
) ;
2760 m_updateRegion
= wxRegion(HIShapeCreateWithQDRgn(newupdate
)) ;
2761 DisposeRgn( newupdate
) ;
2763 if ( !m_updateRegion
.Empty() )
2765 // paint the window itself
2768 event
.SetTimestamp(time
);
2769 event
.SetEventObject(this);
2770 HandleWindowEvent(event
);
2774 // now we cannot rely on having its borders drawn by a window itself, as it does not
2775 // get the updateRgn wide enough to always do so, so we do it from the parent
2776 // this would also be the place to draw any custom backgrounds for native controls
2777 // in Composited windowing
2778 wxPoint clientOrigin
= GetClientAreaOrigin() ;
2782 for (wxWindowList::compatibility_iterator node
= GetChildren().GetFirst(); node
; node
= node
->GetNext())
2784 child
= node
->GetData();
2787 if (child
== m_vScrollBar
)
2789 if (child
== m_hScrollBar
)
2791 if (child
->IsTopLevel())
2793 if (!child
->IsShown())
2796 // only draw those in the update region (add a safety margin of 10 pixels for shadow effects
2798 child
->GetPosition( &x
, &y
);
2799 child
->GetSize( &w
, &h
);
2800 Rect childRect
= { y
, x
, y
+ h
, x
+ w
} ;
2801 OffsetRect( &childRect
, clientOrigin
.x
, clientOrigin
.y
) ;
2802 InsetRect( &childRect
, -10 , -10) ;
2804 if ( RectInRgn( &childRect
, updatergn
) )
2806 // paint custom borders
2807 wxNcPaintEvent
eventNc( child
->GetId() );
2808 eventNc
.SetEventObject( child
);
2809 if ( !child
->HandleWindowEvent( eventNc
) )
2811 child
->MacPaintBorders(0, 0) ;
2821 WXWindow
wxWindowMac::MacGetTopLevelWindowRef() const
2823 wxWindowMac
*iter
= (wxWindowMac
*)this ;
2827 if ( iter
->IsTopLevel() )
2829 wxTopLevelWindow
* toplevel
= wxDynamicCast(iter
,wxTopLevelWindow
);
2831 return toplevel
->MacGetWindowRef();
2833 wxPopupWindow
* popupwin
= wxDynamicCast(iter
,wxPopupWindow
);
2835 return popupwin
->MacGetPopupWindowRef();
2838 iter
= iter
->GetParent() ;
2844 bool wxWindowMac::MacHasScrollBarCorner() const
2846 /* Returns whether the scroll bars in a wxScrolledWindow should be
2847 * shortened. Scroll bars should be shortened if either:
2849 * - both scroll bars are visible, or
2851 * - there is a resize box in the parent frame's corner and this
2852 * window shares the bottom and right edge with the parent
2856 if ( m_hScrollBar
== NULL
&& m_vScrollBar
== NULL
)
2859 if ( ( m_hScrollBar
&& m_hScrollBar
->IsShown() )
2860 && ( m_vScrollBar
&& m_vScrollBar
->IsShown() ) )
2862 // Both scroll bars visible
2867 wxPoint thisWindowBottomRight
= GetScreenRect().GetBottomRight();
2869 for ( const wxWindow
*win
= this; win
; win
= win
->GetParent() )
2871 const wxFrame
*frame
= wxDynamicCast( win
, wxFrame
) ;
2874 if ( frame
->GetWindowStyleFlag() & wxRESIZE_BORDER
)
2876 // Parent frame has resize handle
2877 wxPoint frameBottomRight
= frame
->GetScreenRect().GetBottomRight();
2879 // Note: allow for some wiggle room here as wxMac's
2880 // window rect calculations seem to be imprecise
2881 if ( abs( thisWindowBottomRight
.x
- frameBottomRight
.x
) <= 2
2882 && abs( thisWindowBottomRight
.y
- frameBottomRight
.y
) <= 2 )
2884 // Parent frame has resize handle and shares
2885 // right bottom corner
2890 // Parent frame has resize handle but doesn't
2891 // share right bottom corner
2897 // Parent frame doesn't have resize handle
2903 // No parent frame found
2908 void wxWindowMac::MacCreateScrollBars( long style
)
2910 wxASSERT_MSG( m_vScrollBar
== NULL
&& m_hScrollBar
== NULL
, wxT("attempt to create window twice") ) ;
2912 if ( style
& ( wxVSCROLL
| wxHSCROLL
) )
2914 int scrlsize
= MAC_SCROLLBAR_SIZE
;
2915 if ( GetWindowVariant() == wxWINDOW_VARIANT_SMALL
|| GetWindowVariant() == wxWINDOW_VARIANT_MINI
)
2917 scrlsize
= MAC_SMALL_SCROLLBAR_SIZE
;
2920 int adjust
= MacHasScrollBarCorner() ? scrlsize
- 1: 0 ;
2922 GetClientSize( &width
, &height
) ;
2924 wxPoint
vPoint(width
- scrlsize
, 0) ;
2925 wxSize
vSize(scrlsize
, height
- adjust
) ;
2926 wxPoint
hPoint(0, height
- scrlsize
) ;
2927 wxSize
hSize(width
- adjust
, scrlsize
) ;
2929 // we have to set the min size to a smaller value, otherwise they cannot get smaller (InitialSize sets MinSize)
2930 if ( style
& wxVSCROLL
)
2932 m_vScrollBar
= new wxScrollBar((wxWindow
*)this, wxID_ANY
, vPoint
, vSize
, wxVERTICAL
);
2933 m_vScrollBar
->SetMinSize( wxDefaultSize
);
2936 if ( style
& wxHSCROLL
)
2938 m_hScrollBar
= new wxScrollBar((wxWindow
*)this, wxID_ANY
, hPoint
, hSize
, wxHORIZONTAL
);
2939 m_hScrollBar
->SetMinSize( wxDefaultSize
);
2943 // because the create does not take into account the client area origin
2944 // we might have a real position shift
2945 MacRepositionScrollBars() ;
2948 bool wxWindowMac::MacIsChildOfClientArea( const wxWindow
* child
) const
2950 bool result
= ((child
== NULL
) || ((child
!= m_hScrollBar
) && (child
!= m_vScrollBar
)));
2955 void wxWindowMac::MacRepositionScrollBars()
2957 if ( !m_hScrollBar
&& !m_vScrollBar
)
2960 int scrlsize
= m_hScrollBar
? m_hScrollBar
->GetSize().y
: ( m_vScrollBar
? m_vScrollBar
->GetSize().x
: MAC_SCROLLBAR_SIZE
) ;
2961 int adjust
= MacHasScrollBarCorner() ? scrlsize
- 1 : 0 ;
2963 // get real client area
2965 GetSize( &width
, &height
);
2967 width
-= MacGetLeftBorderSize() + MacGetRightBorderSize();
2968 height
-= MacGetTopBorderSize() + MacGetBottomBorderSize();
2970 wxPoint
vPoint( width
- scrlsize
, 0 ) ;
2971 wxSize
vSize( scrlsize
, height
- adjust
) ;
2972 wxPoint
hPoint( 0 , height
- scrlsize
) ;
2973 wxSize
hSize( width
- adjust
, scrlsize
) ;
2976 int x
= 0, y
= 0, w
, h
;
2977 GetSize( &w
, &h
) ;
2979 MacClientToRootWindow( &x
, &y
) ;
2980 MacClientToRootWindow( &w
, &h
) ;
2982 wxWindowMac
*iter
= (wxWindowMac
*)this ;
2984 int totW
= 10000 , totH
= 10000;
2987 if ( iter
->IsTopLevel() )
2989 iter
->GetSize( &totW
, &totH
) ;
2993 iter
= iter
->GetParent() ;
3007 if ( w
- x
>= totW
)
3012 if ( h
- y
>= totH
)
3020 m_vScrollBar
->SetSize( vPoint
.x
, vPoint
.y
, vSize
.x
, vSize
.y
, wxSIZE_ALLOW_MINUS_ONE
);
3022 m_hScrollBar
->SetSize( hPoint
.x
, hPoint
.y
, hSize
.x
, hSize
.y
, wxSIZE_ALLOW_MINUS_ONE
);
3025 bool wxWindowMac::AcceptsFocus() const
3027 return MacCanFocus() && wxWindowBase::AcceptsFocus();
3030 void wxWindowMac::MacSuperChangedPosition()
3032 // only window-absolute structures have to be moved i.e. controls
3034 m_cachedClippedRectValid
= false ;
3037 wxWindowList::compatibility_iterator node
= GetChildren().GetFirst();
3040 child
= node
->GetData();
3041 child
->MacSuperChangedPosition() ;
3043 node
= node
->GetNext();
3047 void wxWindowMac::MacTopLevelWindowChangedPosition()
3049 // only screen-absolute structures have to be moved i.e. glcanvas
3052 wxWindowList::compatibility_iterator node
= GetChildren().GetFirst();
3055 child
= node
->GetData();
3056 child
->MacTopLevelWindowChangedPosition() ;
3058 node
= node
->GetNext();
3062 long wxWindowMac::MacGetLeftBorderSize() const
3069 if (HasFlag(wxRAISED_BORDER
) || HasFlag( wxSUNKEN_BORDER
) || HasFlag(wxDOUBLE_BORDER
))
3071 // this metric is only the 'outset' outside the simple frame rect
3072 GetThemeMetric( kThemeMetricEditTextFrameOutset
, &border
) ;
3075 else if (HasFlag(wxSIMPLE_BORDER
))
3077 // this metric is only the 'outset' outside the simple frame rect
3078 GetThemeMetric( kThemeMetricListBoxFrameOutset
, &border
) ;
3085 long wxWindowMac::MacGetRightBorderSize() const
3087 // they are all symmetric in mac themes
3088 return MacGetLeftBorderSize() ;
3091 long wxWindowMac::MacGetTopBorderSize() const
3093 // they are all symmetric in mac themes
3094 return MacGetLeftBorderSize() ;
3097 long wxWindowMac::MacGetBottomBorderSize() const
3099 // they are all symmetric in mac themes
3100 return MacGetLeftBorderSize() ;
3103 long wxWindowMac::MacRemoveBordersFromStyle( long style
)
3105 return style
& ~wxBORDER_MASK
;
3108 // Find the wxWindowMac at the current mouse position, returning the mouse
3110 wxWindowMac
* wxFindWindowAtPointer( wxPoint
& pt
)
3112 pt
= wxGetMousePosition();
3113 wxWindowMac
* found
= wxFindWindowAtPoint(pt
);
3118 // Get the current mouse position.
3119 wxPoint
wxGetMousePosition()
3123 wxGetMousePosition( &x
, &y
);
3125 return wxPoint(x
, y
);
3128 void wxWindowMac::OnMouseEvent( wxMouseEvent
&event
)
3130 if ( event
.GetEventType() == wxEVT_RIGHT_DOWN
)
3132 // copied from wxGTK : CS
3133 // VZ: shouldn't we move this to base class then?
3135 // generate a "context menu" event: this is similar to wxEVT_RIGHT_DOWN
3138 // (a) it's a command event and so is propagated to the parent
3139 // (b) under MSW it can be generated from kbd too
3140 // (c) it uses screen coords (because of (a))
3141 wxContextMenuEvent
evtCtx(wxEVT_CONTEXT_MENU
,
3143 this->ClientToScreen(event
.GetPosition()));
3144 evtCtx
.SetEventObject(this);
3145 if ( ! HandleWindowEvent(evtCtx
) )
3154 void wxWindowMac::OnPaint( wxPaintEvent
& WXUNUSED(event
) )
3156 if ( wxTheApp
->MacGetCurrentEvent() != NULL
&& wxTheApp
->MacGetCurrentEventHandlerCallRef() != NULL
3157 && GetBackgroundStyle() != wxBG_STYLE_TRANSPARENT
)
3158 CallNextEventHandler(
3159 (EventHandlerCallRef
)wxTheApp
->MacGetCurrentEventHandlerCallRef() ,
3160 (EventRef
) wxTheApp
->MacGetCurrentEvent() ) ;
3163 void wxWindowMac::MacHandleControlClick(WXWidget
WXUNUSED(control
),
3164 wxInt16
WXUNUSED(controlpart
),
3165 bool WXUNUSED(mouseStillDown
))
3169 Rect
wxMacGetBoundsForControl( wxWindow
* window
, const wxPoint
& pos
, const wxSize
&size
, bool adjustForOrigin
)
3173 window
->MacGetBoundsForControl( pos
, size
, x
, y
, w
, h
, adjustForOrigin
) ;
3174 Rect bounds
= { y
, x
, y
+ h
, x
+ w
};
3179 wxInt32
wxWindowMac::MacControlHit(WXEVENTHANDLERREF
WXUNUSED(handler
) , WXEVENTREF
WXUNUSED(event
) )
3181 return eventNotHandledErr
;
3184 bool wxWindowMac::Reparent(wxWindowBase
*newParentBase
)
3186 wxWindowMac
*newParent
= (wxWindowMac
*)newParentBase
;
3187 if ( !wxWindowBase::Reparent(newParent
) )
3190 // copied from MacPostControlCreate
3191 ControlRef container
= (ControlRef
) GetParent()->GetHandle() ;
3193 wxASSERT_MSG( container
!= NULL
, wxT("No valid mac container control") ) ;
3195 ::EmbedControl( m_peer
->GetControlRef() , container
) ;
3200 bool wxWindowMac::SetTransparent(wxByte alpha
)
3202 SetBackgroundStyle(wxBG_STYLE_TRANSPARENT
);
3204 if ( alpha
!= m_macAlpha
)
3206 m_macAlpha
= alpha
;
3213 bool wxWindowMac::CanSetTransparent()
3218 wxByte
wxWindowMac::GetTransparent() const