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()
870 m_cgContextRef
= NULL
;
872 // as all windows are created with WS_VISIBLE style...
875 m_hScrollBar
= NULL
;
876 m_vScrollBar
= NULL
;
877 m_hScrollBarAlwaysShown
= false;
878 m_vScrollBarAlwaysShown
= false;
880 m_macIsUserPane
= true;
881 m_clipChildren
= false ;
882 m_cachedClippedRectValid
= false ;
884 // we need a valid font for the encodings
885 wxWindowBase::SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
));
888 wxWindowMac::~wxWindowMac()
892 m_isBeingDeleted
= true;
894 MacInvalidateBorders() ;
896 #ifndef __WXUNIVERSAL__
897 // VS: make sure there's no wxFrame with last focus set to us:
898 for ( wxWindow
*win
= GetParent(); win
; win
= win
->GetParent() )
900 wxFrame
*frame
= wxDynamicCast(win
, wxFrame
);
903 if ( frame
->GetLastFocus() == this )
904 frame
->SetLastFocus((wxWindow
*)NULL
);
910 // destroy children before destroying this window itself
913 // wxRemoveMacControlAssociation( this ) ;
914 // If we delete an item, we should initialize the parent panel,
915 // because it could now be invalid.
916 wxTopLevelWindow
*tlw
= wxDynamicCast(wxGetTopLevelParent(this), wxTopLevelWindow
);
919 if ( tlw
->GetDefaultItem() == (wxButton
*) this)
920 tlw
->SetDefaultItem(NULL
);
923 if ( m_peer
&& m_peer
->Ok() )
925 // in case the callback might be called during destruction
926 wxRemoveMacControlAssociation( this) ;
927 ::RemoveEventHandler( (EventHandlerRef
) m_macControlEventHandler
) ;
928 // we currently are not using this hook
929 // ::SetControlColorProc( *m_peer , NULL ) ;
933 if ( g_MacLastWindow
== this )
934 g_MacLastWindow
= NULL
;
936 #ifndef __WXUNIVERSAL__
937 wxFrame
* frame
= wxDynamicCast( wxGetTopLevelParent( (wxWindow
*)this ) , wxFrame
) ;
940 if ( frame
->GetLastFocus() == this )
941 frame
->SetLastFocus( NULL
) ;
945 // delete our drop target if we've got one
946 #if wxUSE_DRAG_AND_DROP
947 if ( m_dropTarget
!= NULL
)
957 WXWidget
wxWindowMac::GetHandle() const
959 return (WXWidget
) m_peer
->GetControlRef() ;
962 void wxWindowMac::MacInstallEventHandler( WXWidget control
)
964 wxAssociateControlWithMacControl( (ControlRef
) control
, this ) ;
965 InstallControlEventHandler( (ControlRef
)control
, GetwxMacWindowEventHandlerUPP(),
966 GetEventTypeCount(eventList
), eventList
, this,
967 (EventHandlerRef
*)&m_macControlEventHandler
);
971 bool wxWindowMac::Create(wxWindowMac
*parent
,
976 const wxString
& name
)
978 wxCHECK_MSG( parent
, false, wxT("can't create wxWindowMac without parent") );
980 if ( !CreateBase(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
) )
983 m_windowVariant
= parent
->GetWindowVariant() ;
985 if ( m_macIsUserPane
)
987 Rect bounds
= wxMacGetBoundsForControl( this , pos
, size
) ;
990 | kControlSupportsEmbedding
991 | kControlSupportsLiveFeedback
992 | kControlGetsFocusOnClick
993 // | kControlHasSpecialBackground
994 // | kControlSupportsCalcBestRect
995 | kControlHandlesTracking
996 | kControlSupportsFocus
997 | kControlWantsActivate
998 | kControlWantsIdle
;
1000 m_peer
= new wxMacControl(this) ;
1001 OSStatus err
=::CreateUserPaneControl( MAC_WXHWND(GetParent()->MacGetTopLevelWindowRef()) , &bounds
, features
, m_peer
->GetControlRefAddr() );
1002 verify_noerr( err
);
1004 MacPostControlCreate(pos
, size
) ;
1007 #ifndef __WXUNIVERSAL__
1008 // Don't give scrollbars to wxControls unless they ask for them
1009 if ( (! IsKindOf(CLASSINFO(wxControl
)) && ! IsKindOf(CLASSINFO(wxStatusBar
)))
1010 || (IsKindOf(CLASSINFO(wxControl
)) && ((style
& wxHSCROLL
) || (style
& wxVSCROLL
))))
1012 MacCreateScrollBars( style
) ;
1016 wxWindowCreateEvent
event(this);
1017 GetEventHandler()->AddPendingEvent(event
);
1022 void wxWindowMac::MacChildAdded()
1025 m_vScrollBar
->Raise() ;
1027 m_hScrollBar
->Raise() ;
1030 void wxWindowMac::MacPostControlCreate(const wxPoint
& WXUNUSED(pos
), const wxSize
& size
)
1032 wxASSERT_MSG( m_peer
!= NULL
&& m_peer
->Ok() , wxT("No valid mac control") ) ;
1034 m_peer
->SetReference( (URefCon
) this ) ;
1035 GetParent()->AddChild( this );
1037 MacInstallEventHandler( (WXWidget
) m_peer
->GetControlRef() );
1039 ControlRef container
= (ControlRef
) GetParent()->GetHandle() ;
1040 wxASSERT_MSG( container
!= NULL
, wxT("No valid mac container control") ) ;
1041 ::EmbedControl( m_peer
->GetControlRef() , container
) ;
1042 GetParent()->MacChildAdded() ;
1044 // adjust font, controlsize etc
1045 DoSetWindowVariant( m_windowVariant
) ;
1047 m_peer
->SetLabel( wxStripMenuCodes(m_label
, wxStrip_Mnemonics
) ) ;
1049 if (!m_macIsUserPane
)
1050 SetInitialSize(size
);
1052 SetCursor( *wxSTANDARD_CURSOR
) ;
1055 void wxWindowMac::DoSetWindowVariant( wxWindowVariant variant
)
1057 // Don't assert, in case we set the window variant before
1058 // the window is created
1059 // wxASSERT( m_peer->Ok() ) ;
1061 m_windowVariant
= variant
;
1063 if (m_peer
== NULL
|| !m_peer
->Ok())
1067 ThemeFontID themeFont
= kThemeSystemFont
;
1069 // we will get that from the settings later
1070 // and make this NORMAL later, but first
1071 // we have a few calculations that we must fix
1075 case wxWINDOW_VARIANT_NORMAL
:
1076 size
= kControlSizeNormal
;
1077 themeFont
= kThemeSystemFont
;
1080 case wxWINDOW_VARIANT_SMALL
:
1081 size
= kControlSizeSmall
;
1082 themeFont
= kThemeSmallSystemFont
;
1085 case wxWINDOW_VARIANT_MINI
:
1086 // not always defined in the headers
1091 case wxWINDOW_VARIANT_LARGE
:
1092 size
= kControlSizeLarge
;
1093 themeFont
= kThemeSystemFont
;
1097 wxFAIL_MSG(_T("unexpected window variant"));
1101 m_peer
->SetData
<ControlSize
>(kControlEntireControl
, kControlSizeTag
, &size
) ;
1104 font
.MacCreateThemeFont( themeFont
) ;
1108 void wxWindowMac::MacUpdateControlFont()
1110 m_peer
->SetFont( GetFont() , GetForegroundColour() , GetWindowStyle() ) ;
1111 // do not trigger refreshes upon invisible and possible partly created objects
1112 if ( MacIsReallyShown() )
1116 bool wxWindowMac::SetFont(const wxFont
& font
)
1118 bool retval
= wxWindowBase::SetFont( font
);
1120 MacUpdateControlFont() ;
1125 bool wxWindowMac::SetForegroundColour(const wxColour
& col
)
1127 bool retval
= wxWindowBase::SetForegroundColour( col
);
1130 MacUpdateControlFont();
1135 bool wxWindowMac::SetBackgroundColour(const wxColour
& col
)
1137 if ( !wxWindowBase::SetBackgroundColour(col
) && m_hasBgCol
)
1140 m_peer
->SetBackgroundColour( col
) ;
1145 bool wxWindowMac::MacCanFocus() const
1147 // TODO : evaluate performance hits by looking up this value, eventually cache the results for a 1 sec or so
1148 // CAUTION : the value returned currently is 0 or 2, I've also found values of 1 having the same meaning,
1149 // but the value range is nowhere documented
1150 Boolean keyExistsAndHasValidFormat
;
1151 CFIndex fullKeyboardAccess
= CFPreferencesGetAppIntegerValue( CFSTR("AppleKeyboardUIMode" ) ,
1152 kCFPreferencesCurrentApplication
, &keyExistsAndHasValidFormat
);
1154 if ( keyExistsAndHasValidFormat
&& fullKeyboardAccess
> 0 )
1160 UInt32 features
= 0 ;
1161 m_peer
->GetFeatures( &features
) ;
1163 return features
& ( kControlSupportsFocus
| kControlGetsFocusOnClick
) ;
1167 void wxWindowMac::SetFocus()
1169 if ( !AcceptsFocus() )
1172 wxWindow
* former
= FindFocus() ;
1173 if ( former
== this )
1176 // as we cannot rely on the control features to find out whether we are in full keyboard mode,
1177 // we can only leave in case of an error
1178 OSStatus err
= m_peer
->SetFocus( kControlFocusNextPart
) ;
1179 if ( err
== errCouldntSetFocus
)
1182 SetUserFocusWindow( (WindowRef
)MacGetTopLevelWindowRef() );
1185 void wxWindowMac::DoCaptureMouse()
1187 wxApp::s_captureWindow
= this ;
1190 wxWindow
* wxWindowBase::GetCapture()
1192 return wxApp::s_captureWindow
;
1195 void wxWindowMac::DoReleaseMouse()
1197 wxApp::s_captureWindow
= NULL
;
1200 #if wxUSE_DRAG_AND_DROP
1202 void wxWindowMac::SetDropTarget(wxDropTarget
*pDropTarget
)
1204 if ( m_dropTarget
!= NULL
)
1205 delete m_dropTarget
;
1207 m_dropTarget
= pDropTarget
;
1208 if ( m_dropTarget
!= NULL
)
1216 // Old-style File Manager Drag & Drop
1217 void wxWindowMac::DragAcceptFiles(bool WXUNUSED(accept
))
1222 // Returns the size of the native control. In the case of the toplevel window
1223 // this is the content area root control
1225 void wxWindowMac::MacGetPositionAndSizeFromControl(int& WXUNUSED(x
),
1228 int& WXUNUSED(h
)) const
1230 wxFAIL_MSG( wxT("Not currently supported") ) ;
1233 // From a wx position / size calculate the appropriate size of the native control
1235 bool wxWindowMac::MacGetBoundsForControl(
1239 int& w
, int& h
, bool adjustOrigin
) const
1241 // the desired size, minus the border pixels gives the correct size of the control
1245 // TODO: the default calls may be used as soon as PostCreateControl Is moved here
1246 w
= wxMax(size
.x
, 0) ; // WidthDefault( size.x );
1247 h
= wxMax(size
.y
, 0) ; // HeightDefault( size.y ) ;
1249 x
+= MacGetLeftBorderSize() ;
1250 y
+= MacGetTopBorderSize() ;
1251 w
-= MacGetLeftBorderSize() + MacGetRightBorderSize() ;
1252 h
-= MacGetTopBorderSize() + MacGetBottomBorderSize() ;
1255 AdjustForParentClientOrigin( x
, y
) ;
1257 // this is in window relative coordinate, as this parent may have a border, its physical position is offset by this border
1258 if ( !GetParent()->IsTopLevel() )
1260 x
-= GetParent()->MacGetLeftBorderSize() ;
1261 y
-= GetParent()->MacGetTopBorderSize() ;
1267 // Get window size (not client size)
1268 void wxWindowMac::DoGetSize(int *x
, int *y
) const
1271 m_peer
->GetRect( &bounds
) ;
1274 *x
= bounds
.right
- bounds
.left
+ MacGetLeftBorderSize() + MacGetRightBorderSize() ;
1276 *y
= bounds
.bottom
- bounds
.top
+ MacGetTopBorderSize() + MacGetBottomBorderSize() ;
1279 // get the position of the bounds of this window in client coordinates of its parent
1280 void wxWindowMac::DoGetPosition(int *x
, int *y
) const
1283 m_peer
->GetRect( &bounds
) ;
1285 int x1
= bounds
.left
;
1286 int y1
= bounds
.top
;
1288 // get the wx window position from the native one
1289 x1
-= MacGetLeftBorderSize() ;
1290 y1
-= MacGetTopBorderSize() ;
1292 if ( !IsTopLevel() )
1294 wxWindow
*parent
= GetParent();
1297 // we must first adjust it to be in window coordinates of the parent,
1298 // as otherwise it gets lost by the ClientAreaOrigin fix
1299 x1
+= parent
->MacGetLeftBorderSize() ;
1300 y1
+= parent
->MacGetTopBorderSize() ;
1302 // and now to client coordinates
1303 wxPoint
pt(parent
->GetClientAreaOrigin());
1315 void wxWindowMac::DoScreenToClient(int *x
, int *y
) const
1317 WindowRef window
= (WindowRef
) MacGetTopLevelWindowRef() ;
1318 wxCHECK_RET( window
, wxT("TopLevel Window missing") ) ;
1320 Point localwhere
= { 0, 0 } ;
1327 wxMacGlobalToLocal( window
, &localwhere
) ;
1334 MacRootWindowToWindow( x
, y
) ;
1336 wxPoint origin
= GetClientAreaOrigin() ;
1343 void wxWindowMac::DoClientToScreen(int *x
, int *y
) const
1345 WindowRef window
= (WindowRef
) MacGetTopLevelWindowRef() ;
1346 wxCHECK_RET( window
, wxT("TopLevel window missing") ) ;
1348 wxPoint origin
= GetClientAreaOrigin() ;
1354 MacWindowToRootWindow( x
, y
) ;
1356 Point localwhere
= { 0, 0 };
1362 wxMacLocalToGlobal( window
, &localwhere
) ;
1370 void wxWindowMac::MacClientToRootWindow( int *x
, int *y
) const
1372 wxPoint origin
= GetClientAreaOrigin() ;
1378 MacWindowToRootWindow( x
, y
) ;
1381 void wxWindowMac::MacRootWindowToClient( int *x
, int *y
) const
1383 MacRootWindowToWindow( x
, y
) ;
1385 wxPoint origin
= GetClientAreaOrigin() ;
1392 void wxWindowMac::MacWindowToRootWindow( int *x
, int *y
) const
1401 if ( !IsTopLevel() )
1403 wxTopLevelWindowMac
* top
= MacGetTopLevelWindow();
1406 pt
.x
-= MacGetLeftBorderSize() ;
1407 pt
.y
-= MacGetTopBorderSize() ;
1408 wxMacControl::Convert( &pt
, m_peer
, top
->m_peer
) ;
1418 void wxWindowMac::MacWindowToRootWindow( short *x
, short *y
) const
1427 MacWindowToRootWindow( &x1
, &y1
) ;
1435 void wxWindowMac::MacRootWindowToWindow( int *x
, int *y
) const
1444 if ( !IsTopLevel() )
1446 wxTopLevelWindowMac
* top
= MacGetTopLevelWindow();
1449 wxMacControl::Convert( &pt
, top
->m_peer
, m_peer
) ;
1450 pt
.x
+= MacGetLeftBorderSize() ;
1451 pt
.y
+= MacGetTopBorderSize() ;
1461 void wxWindowMac::MacRootWindowToWindow( short *x
, short *y
) const
1470 MacRootWindowToWindow( &x1
, &y1
) ;
1478 void wxWindowMac::MacGetContentAreaInset( int &left
, int &top
, int &right
, int &bottom
)
1480 RgnHandle rgn
= NewRgn() ;
1482 if ( m_peer
->GetRegion( kControlContentMetaPart
, rgn
) == noErr
)
1484 Rect structure
, content
;
1486 GetRegionBounds( rgn
, &content
) ;
1487 m_peer
->GetRect( &structure
) ;
1488 OffsetRect( &structure
, -structure
.left
, -structure
.top
) ;
1490 left
= content
.left
- structure
.left
;
1491 top
= content
.top
- structure
.top
;
1492 right
= structure
.right
- content
.right
;
1493 bottom
= structure
.bottom
- content
.bottom
;
1497 left
= top
= right
= bottom
= 0 ;
1503 wxSize
wxWindowMac::DoGetSizeFromClientSize( const wxSize
& size
) const
1505 wxSize sizeTotal
= size
;
1507 RgnHandle rgn
= NewRgn() ;
1508 if ( m_peer
->GetRegion( kControlContentMetaPart
, rgn
) == noErr
)
1510 Rect content
, structure
;
1511 GetRegionBounds( rgn
, &content
) ;
1512 m_peer
->GetRect( &structure
) ;
1514 // structure is in parent coordinates, but we only need width and height, so it's ok
1516 sizeTotal
.x
+= (structure
.right
- structure
.left
) - (content
.right
- content
.left
) ;
1517 sizeTotal
.y
+= (structure
.bottom
- structure
.top
) - (content
.bottom
- content
.top
) ;
1522 sizeTotal
.x
+= MacGetLeftBorderSize() + MacGetRightBorderSize() ;
1523 sizeTotal
.y
+= MacGetTopBorderSize() + MacGetBottomBorderSize() ;
1528 // Get size *available for subwindows* i.e. excluding menu bar etc.
1529 void wxWindowMac::DoGetClientSize( int *x
, int *y
) const
1533 RgnHandle rgn
= NewRgn() ;
1535 if ( m_peer
->GetRegion( kControlContentMetaPart
, rgn
) == noErr
)
1536 GetRegionBounds( rgn
, &content
) ;
1538 m_peer
->GetRect( &content
) ;
1541 ww
= content
.right
- content
.left
;
1542 hh
= content
.bottom
- content
.top
;
1544 if (m_hScrollBar
&& m_hScrollBar
->IsShown() )
1545 hh
-= m_hScrollBar
->GetSize().y
;
1547 if (m_vScrollBar
&& m_vScrollBar
->IsShown() )
1548 ww
-= m_vScrollBar
->GetSize().x
;
1556 bool wxWindowMac::SetCursor(const wxCursor
& cursor
)
1558 if (m_cursor
.IsSameAs(cursor
))
1563 if ( ! wxWindowBase::SetCursor( *wxSTANDARD_CURSOR
) )
1568 if ( ! wxWindowBase::SetCursor( cursor
) )
1572 wxASSERT_MSG( m_cursor
.Ok(),
1573 wxT("cursor must be valid after call to the base version"));
1575 wxWindowMac
*mouseWin
= 0 ;
1577 wxTopLevelWindowMac
*tlw
= MacGetTopLevelWindow() ;
1578 WindowRef window
= (WindowRef
) ( tlw
? tlw
->MacGetWindowRef() : 0 ) ;
1580 ControlPartCode part
;
1581 ControlRef control
;
1583 #if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
1585 HIGetMousePosition(kHICoordSpaceWindow
, window
, &hiPoint
);
1589 GetGlobalMouse( &pt
);
1592 ScreenToClient(&x
, &y
);
1596 control
= FindControlUnderMouse( pt
, window
, &part
) ;
1598 mouseWin
= wxFindControlFromMacControl( control
) ;
1602 if ( mouseWin
== this && !wxIsBusy() )
1603 m_cursor
.MacInstall() ;
1609 bool wxWindowMac::DoPopupMenu(wxMenu
*menu
, int x
, int y
)
1611 #ifndef __WXUNIVERSAL__
1612 menu
->SetInvokingWindow((wxWindow
*)this);
1615 if ( x
== wxDefaultCoord
&& y
== wxDefaultCoord
)
1617 wxPoint mouse
= wxGetMousePosition();
1623 ClientToScreen( &x
, &y
) ;
1626 menu
->MacBeforeDisplay( true ) ;
1627 long menuResult
= ::PopUpMenuSelect((MenuHandle
) menu
->GetHMenu() , y
, x
, 0) ;
1628 if ( HiWord(menuResult
) != 0 )
1631 GetMenuItemCommandID( GetMenuHandle(HiWord(menuResult
)) , LoWord(menuResult
) , &macid
);
1632 int id
= wxMacCommandToId( macid
);
1633 wxMenuItem
* item
= NULL
;
1635 item
= menu
->FindItem( id
, &realmenu
) ;
1638 if (item
->IsCheckable())
1639 item
->Check( !item
->IsChecked() ) ;
1641 menu
->SendEvent( id
, item
->IsCheckable() ? item
->IsChecked() : -1 ) ;
1645 menu
->MacAfterDisplay( true ) ;
1646 menu
->SetInvokingWindow( NULL
);
1650 // actually this shouldn't be called, because universal is having its own implementation
1656 // ----------------------------------------------------------------------------
1658 // ----------------------------------------------------------------------------
1662 void wxWindowMac::DoSetToolTip(wxToolTip
*tooltip
)
1664 wxWindowBase::DoSetToolTip(tooltip
);
1667 m_tooltip
->SetWindow(this);
1672 void wxWindowMac::MacInvalidateBorders()
1674 if ( m_peer
== NULL
)
1677 bool vis
= MacIsReallyShown() ;
1681 int outerBorder
= MacGetLeftBorderSize() ;
1682 if ( m_peer
->NeedsFocusRect() /* && m_peer->HasFocus() */ )
1685 if ( outerBorder
== 0 )
1688 // now we know that we have something to do at all
1690 // as the borders are drawn on the parent we have to properly invalidate all these areas
1691 RgnHandle updateInner
, updateOuter
;
1694 // this rectangle is in HIViewCoordinates under OSX and in Window Coordinates under Carbon
1695 updateInner
= NewRgn() ;
1696 updateOuter
= NewRgn() ;
1698 m_peer
->GetRect( &rect
) ;
1699 RectRgn( updateInner
, &rect
) ;
1700 InsetRect( &rect
, -outerBorder
, -outerBorder
) ;
1701 RectRgn( updateOuter
, &rect
) ;
1702 DiffRgn( updateOuter
, updateInner
, updateOuter
) ;
1704 GetParent()->m_peer
->SetNeedsDisplay( updateOuter
) ;
1706 DisposeRgn( updateOuter
) ;
1707 DisposeRgn( updateInner
) ;
1710 void wxWindowMac::DoMoveWindow(int x
, int y
, int width
, int height
)
1712 // this is never called for a toplevel window, so we know we have a parent
1713 int former_x
, former_y
, former_w
, former_h
;
1715 // Get true coordinates of former position
1716 DoGetPosition( &former_x
, &former_y
) ;
1717 DoGetSize( &former_w
, &former_h
) ;
1719 wxWindow
*parent
= GetParent();
1722 wxPoint
pt(parent
->GetClientAreaOrigin());
1727 int actualWidth
= width
;
1728 int actualHeight
= height
;
1732 if ((m_minWidth
!= -1) && (actualWidth
< m_minWidth
))
1733 actualWidth
= m_minWidth
;
1734 if ((m_minHeight
!= -1) && (actualHeight
< m_minHeight
))
1735 actualHeight
= m_minHeight
;
1736 if ((m_maxWidth
!= -1) && (actualWidth
> m_maxWidth
))
1737 actualWidth
= m_maxWidth
;
1738 if ((m_maxHeight
!= -1) && (actualHeight
> m_maxHeight
))
1739 actualHeight
= m_maxHeight
;
1741 bool doMove
= false, doResize
= false ;
1743 if ( actualX
!= former_x
|| actualY
!= former_y
)
1746 if ( actualWidth
!= former_w
|| actualHeight
!= former_h
)
1749 if ( doMove
|| doResize
)
1751 // as the borders are drawn outside the native control, we adjust now
1753 wxRect
bounds( wxPoint( actualX
+ MacGetLeftBorderSize() ,actualY
+ MacGetTopBorderSize() ),
1754 wxSize( actualWidth
- (MacGetLeftBorderSize() + MacGetRightBorderSize()) ,
1755 actualHeight
- (MacGetTopBorderSize() + MacGetBottomBorderSize()) ) ) ;
1758 wxMacRectToNative( &bounds
, &r
) ;
1760 if ( !GetParent()->IsTopLevel() )
1761 wxMacWindowToNative( GetParent() , &r
) ;
1763 MacInvalidateBorders() ;
1765 m_cachedClippedRectValid
= false ;
1766 m_peer
->SetRect( &r
) ;
1768 wxWindowMac::MacSuperChangedPosition() ; // like this only children will be notified
1770 MacInvalidateBorders() ;
1772 MacRepositionScrollBars() ;
1775 wxPoint
point(actualX
, actualY
);
1776 wxMoveEvent
event(point
, m_windowId
);
1777 event
.SetEventObject(this);
1778 HandleWindowEvent(event
) ;
1783 MacRepositionScrollBars() ;
1784 wxSize
size(actualWidth
, actualHeight
);
1785 wxSizeEvent
event(size
, m_windowId
);
1786 event
.SetEventObject(this);
1787 HandleWindowEvent(event
);
1792 wxSize
wxWindowMac::DoGetBestSize() const
1794 if ( m_macIsUserPane
|| IsTopLevel() )
1795 return wxWindowBase::DoGetBestSize() ;
1797 Rect bestsize
= { 0 , 0 , 0 , 0 } ;
1798 int bestWidth
, bestHeight
;
1800 m_peer
->GetBestRect( &bestsize
) ;
1801 if ( EmptyRect( &bestsize
) )
1806 bestsize
.bottom
= 16 ;
1808 if ( IsKindOf( CLASSINFO( wxScrollBar
) ) )
1810 bestsize
.bottom
= 16 ;
1813 else if ( IsKindOf( CLASSINFO( wxSpinButton
) ) )
1815 bestsize
.bottom
= 24 ;
1820 // return wxWindowBase::DoGetBestSize() ;
1824 bestWidth
= bestsize
.right
- bestsize
.left
;
1825 bestHeight
= bestsize
.bottom
- bestsize
.top
;
1826 if ( bestHeight
< 10 )
1829 return wxSize(bestWidth
, bestHeight
);
1832 // set the size of the window: if the dimensions are positive, just use them,
1833 // but if any of them is equal to -1, it means that we must find the value for
1834 // it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in
1835 // which case -1 is a valid value for x and y)
1837 // If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate
1838 // the width/height to best suit our contents, otherwise we reuse the current
1840 void wxWindowMac::DoSetSize(int x
, int y
, int width
, int height
, int sizeFlags
)
1842 // get the current size and position...
1843 int currentX
, currentY
;
1844 int currentW
, currentH
;
1846 GetPosition(¤tX
, ¤tY
);
1847 GetSize(¤tW
, ¤tH
);
1849 // ... and don't do anything (avoiding flicker) if it's already ok
1850 if ( x
== currentX
&& y
== currentY
&&
1851 width
== currentW
&& height
== currentH
&& ( height
!= -1 && width
!= -1 ) )
1854 MacRepositionScrollBars() ; // we might have a real position shift
1859 if ( !(sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) )
1861 if ( x
== wxDefaultCoord
)
1863 if ( y
== wxDefaultCoord
)
1867 AdjustForParentClientOrigin( x
, y
, sizeFlags
);
1869 wxSize size
= wxDefaultSize
;
1870 if ( width
== wxDefaultCoord
)
1872 if ( sizeFlags
& wxSIZE_AUTO_WIDTH
)
1874 size
= DoGetBestSize();
1879 // just take the current one
1884 if ( height
== wxDefaultCoord
)
1886 if ( sizeFlags
& wxSIZE_AUTO_HEIGHT
)
1888 if ( size
.x
== wxDefaultCoord
)
1889 size
= DoGetBestSize();
1890 // else: already called DoGetBestSize() above
1896 // just take the current one
1901 DoMoveWindow( x
, y
, width
, height
);
1904 wxPoint
wxWindowMac::GetClientAreaOrigin() const
1906 RgnHandle rgn
= NewRgn() ;
1908 if ( m_peer
->GetRegion( kControlContentMetaPart
, rgn
) == noErr
)
1910 GetRegionBounds( rgn
, &content
) ;
1920 return wxPoint( content
.left
+ MacGetLeftBorderSize() , content
.top
+ MacGetTopBorderSize() );
1923 void wxWindowMac::DoSetClientSize(int clientwidth
, int clientheight
)
1925 if ( clientwidth
!= wxDefaultCoord
|| clientheight
!= wxDefaultCoord
)
1927 int currentclientwidth
, currentclientheight
;
1928 int currentwidth
, currentheight
;
1930 GetClientSize( ¤tclientwidth
, ¤tclientheight
) ;
1931 GetSize( ¤twidth
, ¤theight
) ;
1933 DoSetSize( wxDefaultCoord
, wxDefaultCoord
, currentwidth
+ clientwidth
- currentclientwidth
,
1934 currentheight
+ clientheight
- currentclientheight
, wxSIZE_USE_EXISTING
) ;
1938 void wxWindowMac::SetLabel(const wxString
& title
)
1942 if ( m_peer
&& m_peer
->Ok() )
1943 m_peer
->SetLabel( wxStripMenuCodes(m_label
, wxStrip_Mnemonics
) ) ;
1945 // do not trigger refreshes upon invisible and possible partly created objects
1946 if ( MacIsReallyShown() )
1950 wxString
wxWindowMac::GetLabel() const
1955 bool wxWindowMac::Show(bool show
)
1957 if ( !wxWindowBase::Show(show
) )
1961 m_peer
->SetVisibility( show
, true ) ;
1966 void wxWindowMac::DoEnable(bool enable
)
1968 m_peer
->Enable( enable
) ;
1972 // status change notifications
1975 void wxWindowMac::MacVisibilityChanged()
1979 void wxWindowMac::MacHiliteChanged()
1983 void wxWindowMac::MacEnabledStateChanged()
1985 OnEnabled( m_peer
->IsEnabled() );
1989 // status queries on the inherited window's state
1992 bool wxWindowMac::MacIsReallyShown()
1994 // only under OSX the visibility of the TLW is taken into account
1995 if ( m_isBeingDeleted
)
1998 #if TARGET_API_MAC_OSX
1999 if ( m_peer
&& m_peer
->Ok() )
2000 return m_peer
->IsVisible();
2003 wxWindow
* win
= this ;
2004 while ( win
->IsShown() )
2006 if ( win
->IsTopLevel() )
2009 win
= win
->GetParent() ;
2017 bool wxWindowMac::MacIsReallyEnabled()
2019 return m_peer
->IsEnabled() ;
2022 bool wxWindowMac::MacIsReallyHilited()
2024 return m_peer
->IsActive();
2027 void wxWindowMac::MacFlashInvalidAreas()
2029 #if TARGET_API_MAC_OSX
2030 HIViewFlashDirtyArea( (WindowRef
) MacGetTopLevelWindowRef() ) ;
2034 int wxWindowMac::GetCharHeight() const
2036 wxClientDC
dc( (wxWindowMac
*)this ) ;
2038 return dc
.GetCharHeight() ;
2041 int wxWindowMac::GetCharWidth() const
2043 wxClientDC
dc( (wxWindowMac
*)this ) ;
2045 return dc
.GetCharWidth() ;
2048 void wxWindowMac::GetTextExtent(const wxString
& string
, int *x
, int *y
,
2049 int *descent
, int *externalLeading
, const wxFont
*theFont
) const
2051 const wxFont
*fontToUse
= theFont
;
2053 fontToUse
= &m_font
;
2055 wxClientDC
dc( (wxWindowMac
*) this ) ;
2056 wxCoord lx
,ly
,ld
,le
;
2057 dc
.GetTextExtent( string
, &lx
, &ly
, &ld
, &le
, (wxFont
*)fontToUse
) ;
2058 if ( externalLeading
)
2059 *externalLeading
= le
;
2069 * Rect is given in client coordinates, for further reading, read wxTopLevelWindowMac::InvalidateRect
2070 * we always intersect with the entire window, not only with the client area
2073 void wxWindowMac::Refresh(bool WXUNUSED(eraseBack
), const wxRect
*rect
)
2075 if ( m_peer
== NULL
)
2078 if ( !MacIsReallyShown() )
2085 wxMacRectToNative( rect
, &r
) ;
2086 m_peer
->SetNeedsDisplay( &r
) ;
2090 m_peer
->SetNeedsDisplay() ;
2094 void wxWindowMac::Freeze()
2096 #if TARGET_API_MAC_OSX
2097 if ( !m_frozenness
++ )
2099 if ( m_peer
&& m_peer
->Ok() )
2100 m_peer
->SetDrawingEnabled( false ) ;
2105 void wxWindowMac::Thaw()
2107 #if TARGET_API_MAC_OSX
2108 wxASSERT_MSG( m_frozenness
> 0, wxT("Thaw() without matching Freeze()") );
2110 if ( !--m_frozenness
)
2112 if ( m_peer
&& m_peer
->Ok() )
2114 m_peer
->SetDrawingEnabled( true ) ;
2115 m_peer
->InvalidateWithChildren() ;
2121 bool wxWindowMac::IsFrozen() const
2123 return m_frozenness
!= 0;
2126 wxWindowMac
*wxGetActiveWindow()
2128 // actually this is a windows-only concept
2132 // Coordinates relative to the window
2133 void wxWindowMac::WarpPointer(int WXUNUSED(x_pos
), int WXUNUSED(y_pos
))
2135 // We really don't move the mouse programmatically under Mac.
2138 void wxWindowMac::OnEraseBackground(wxEraseEvent
& event
)
2140 if ( MacGetTopLevelWindow() == NULL
)
2143 #if TARGET_API_MAC_OSX
2144 if ( !m_backgroundColour.Ok() || GetBackgroundStyle() == wxBG_STYLE_TRANSPARENT )
2150 if ( GetBackgroundStyle() == wxBG_STYLE_COLOUR
)
2152 event
.GetDC()->Clear() ;
2160 void wxWindowMac::OnNcPaint( wxNcPaintEvent
& event
)
2165 int wxWindowMac::GetScrollPos(int orient
) const
2167 if ( orient
== wxHORIZONTAL
)
2170 return m_hScrollBar
->GetThumbPosition() ;
2175 return m_vScrollBar
->GetThumbPosition() ;
2181 // This now returns the whole range, not just the number
2182 // of positions that we can scroll.
2183 int wxWindowMac::GetScrollRange(int orient
) const
2185 if ( orient
== wxHORIZONTAL
)
2188 return m_hScrollBar
->GetRange() ;
2193 return m_vScrollBar
->GetRange() ;
2199 int wxWindowMac::GetScrollThumb(int orient
) const
2201 if ( orient
== wxHORIZONTAL
)
2204 return m_hScrollBar
->GetThumbSize() ;
2209 return m_vScrollBar
->GetThumbSize() ;
2215 void wxWindowMac::SetScrollPos(int orient
, int pos
, bool WXUNUSED(refresh
))
2217 if ( orient
== wxHORIZONTAL
)
2220 m_hScrollBar
->SetThumbPosition( pos
) ;
2225 m_vScrollBar
->SetThumbPosition( pos
) ;
2230 wxWindowMac::AlwaysShowScrollbars(bool hflag
, bool vflag
)
2232 bool needVisibilityUpdate
= false;
2234 if ( m_hScrollBarAlwaysShown
!= hflag
)
2236 m_hScrollBarAlwaysShown
= hflag
;
2237 needVisibilityUpdate
= true;
2240 if ( m_vScrollBarAlwaysShown
!= vflag
)
2242 m_vScrollBarAlwaysShown
= vflag
;
2243 needVisibilityUpdate
= true;
2246 if ( needVisibilityUpdate
)
2247 DoUpdateScrollbarVisibility();
2251 // we draw borders and grow boxes, are already set up and clipped in the current port / cgContextRef
2252 // our own window origin is at leftOrigin/rightOrigin
2255 void wxWindowMac::MacPaintGrowBox()
2260 if ( MacHasScrollBarCorner() )
2264 CGContextRef cgContext
= (CGContextRef
) MacGetCGContextRef() ;
2265 wxASSERT( cgContext
) ;
2267 m_peer
->GetRect( &rect
) ;
2269 int size
= m_hScrollBar
? m_hScrollBar
->GetSize().y
: ( m_vScrollBar
? m_vScrollBar
->GetSize().x
: MAC_SCROLLBAR_SIZE
) ;
2270 CGRect cgrect
= CGRectMake( rect
.right
- size
, rect
.bottom
- size
, size
, size
) ;
2271 CGPoint cgpoint
= CGPointMake( rect
.right
- size
, rect
.bottom
- size
) ;
2272 CGContextSaveGState( cgContext
);
2274 if ( m_backgroundColour
.Ok() )
2276 CGContextSetFillColorWithColor( cgContext
, m_backgroundColour
.GetCGColor() );
2280 CGContextSetRGBFillColor( cgContext
, 1.0, 1.0 , 1.0 , 1.0 );
2282 CGContextFillRect( cgContext
, cgrect
);
2283 CGContextRestoreGState( cgContext
);
2287 void wxWindowMac::MacPaintBorders( int WXUNUSED(leftOrigin
) , int WXUNUSED(rightOrigin
) )
2293 bool hasFocus
= m_peer
->NeedsFocusRect() && m_peer
->HasFocus() ;
2295 // back to the surrounding frame rectangle
2296 m_peer
->GetRect( &rect
) ;
2297 InsetRect( &rect
, -1 , -1 ) ;
2300 CGRect cgrect
= CGRectMake( rect
.left
, rect
.top
, rect
.right
- rect
.left
,
2301 rect
.bottom
- rect
.top
) ;
2303 HIThemeFrameDrawInfo info
;
2304 memset( &info
, 0 , sizeof(info
) ) ;
2308 info
.state
= IsEnabled() ? kThemeStateActive
: kThemeStateInactive
;
2309 info
.isFocused
= hasFocus
;
2311 CGContextRef cgContext
= (CGContextRef
) GetParent()->MacGetCGContextRef() ;
2312 wxASSERT( cgContext
) ;
2314 if ( HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
) || HasFlag(wxDOUBLE_BORDER
) )
2316 info
.kind
= kHIThemeFrameTextFieldSquare
;
2317 HIThemeDrawFrame( &cgrect
, &info
, cgContext
, kHIThemeOrientationNormal
) ;
2319 else if ( HasFlag(wxSIMPLE_BORDER
) )
2321 info
.kind
= kHIThemeFrameListBox
;
2322 HIThemeDrawFrame( &cgrect
, &info
, cgContext
, kHIThemeOrientationNormal
) ;
2324 else if ( hasFocus
)
2326 HIThemeDrawFocusRect( &cgrect
, true , cgContext
, kHIThemeOrientationNormal
) ;
2328 #if 0 // TODO REMOVE now done in a separate call earlier in drawing the window itself
2329 m_peer
->GetRect( &rect
) ;
2330 if ( MacHasScrollBarCorner() )
2332 int variant
= (m_hScrollBar
== NULL
? m_vScrollBar
: m_hScrollBar
) ->GetWindowVariant();
2333 int size
= m_hScrollBar
? m_hScrollBar
->GetSize().y
: ( m_vScrollBar
? m_vScrollBar
->GetSize().x
: MAC_SCROLLBAR_SIZE
) ;
2334 CGRect cgrect
= CGRectMake( rect
.right
- size
, rect
.bottom
- size
, size
, size
) ;
2335 CGPoint cgpoint
= CGPointMake( rect
.right
- size
, rect
.bottom
- size
) ;
2336 HIThemeGrowBoxDrawInfo info
;
2337 memset( &info
, 0, sizeof(info
) ) ;
2339 info
.state
= IsEnabled() ? kThemeStateActive
: kThemeStateInactive
;
2340 info
.kind
= kHIThemeGrowBoxKindNone
;
2341 // contrary to the docs ...SizeSmall does not work
2342 info
.size
= kHIThemeGrowBoxSizeNormal
;
2343 info
.direction
= 0 ;
2344 HIThemeDrawGrowBox( &cgpoint
, &info
, cgContext
, kHIThemeOrientationNormal
) ;
2350 void wxWindowMac::RemoveChild( wxWindowBase
*child
)
2352 if ( child
== m_hScrollBar
)
2353 m_hScrollBar
= NULL
;
2354 if ( child
== m_vScrollBar
)
2355 m_vScrollBar
= NULL
;
2357 wxWindowBase::RemoveChild( child
) ;
2360 void wxWindowMac::DoUpdateScrollbarVisibility()
2362 bool triggerSizeEvent
= false;
2366 bool showHScrollBar
= m_hScrollBarAlwaysShown
|| m_hScrollBar
->IsNeeded();
2368 if ( m_hScrollBar
->IsShown() != showHScrollBar
)
2370 m_hScrollBar
->Show( showHScrollBar
);
2371 triggerSizeEvent
= true;
2377 bool showVScrollBar
= m_vScrollBarAlwaysShown
|| m_vScrollBar
->IsNeeded();
2379 if ( m_vScrollBar
->IsShown() != showVScrollBar
)
2381 m_vScrollBar
->Show( showVScrollBar
) ;
2382 triggerSizeEvent
= true;
2386 MacRepositionScrollBars() ;
2387 if ( triggerSizeEvent
)
2389 wxSizeEvent
event(GetSize(), m_windowId
);
2390 event
.SetEventObject(this);
2391 HandleWindowEvent(event
);
2395 // New function that will replace some of the above.
2396 void wxWindowMac::SetScrollbar(int orient
, int pos
, int thumb
,
2397 int range
, bool refresh
)
2399 if ( orient
== wxHORIZONTAL
&& m_hScrollBar
)
2400 m_hScrollBar
->SetScrollbar(pos
, thumb
, range
, thumb
, refresh
);
2401 else if ( orient
== wxVERTICAL
&& m_vScrollBar
)
2402 m_vScrollBar
->SetScrollbar(pos
, thumb
, range
, thumb
, refresh
);
2404 DoUpdateScrollbarVisibility();
2407 // Does a physical scroll
2408 void wxWindowMac::ScrollWindow(int dx
, int dy
, const wxRect
*rect
)
2410 if ( dx
== 0 && dy
== 0 )
2413 int width
, height
;
2414 GetClientSize( &width
, &height
) ;
2417 // note there currently is a bug in OSX which makes inefficient refreshes in case an entire control
2418 // area is scrolled, this does not occur if width and height are 2 pixels less,
2419 // TODO: write optimal workaround
2420 wxRect
scrollrect( MacGetLeftBorderSize() , MacGetTopBorderSize() , width
, height
) ;
2422 scrollrect
.Intersect( *rect
) ;
2424 if ( m_peer
->GetNeedsDisplay() )
2426 // because HIViewScrollRect does not scroll the already invalidated area we have two options:
2427 // in case there is already a pending redraw on that area
2428 // either immediate redraw or full invalidate
2430 // is the better overall solution, as it does not slow down scrolling
2431 m_peer
->SetNeedsDisplay() ;
2433 // this would be the preferred version for fast drawing controls
2434 HIViewRender(m_peer
->GetControlRef()) ;
2438 // as the native control might be not a 0/0 wx window coordinates, we have to offset
2439 scrollrect
.Offset( -MacGetLeftBorderSize() , -MacGetTopBorderSize() ) ;
2440 m_peer
->ScrollRect( &scrollrect
, dx
, dy
) ;
2443 // this would be the preferred version for fast drawing controls
2444 HIViewRender(m_peer
->GetControlRef()) ;
2450 for (wxWindowList::compatibility_iterator node
= GetChildren().GetFirst(); node
; node
= node
->GetNext())
2452 child
= node
->GetData();
2455 if (child
== m_vScrollBar
)
2457 if (child
== m_hScrollBar
)
2459 if (child
->IsTopLevel())
2462 child
->GetPosition( &x
, &y
);
2463 child
->GetSize( &w
, &h
);
2466 wxRect
rc( x
, y
, w
, h
);
2467 if (rect
->Intersects( rc
))
2468 child
->SetSize( x
+ dx
, y
+ dy
, w
, h
, wxSIZE_AUTO
|wxSIZE_ALLOW_MINUS_ONE
);
2472 child
->SetSize( x
+ dx
, y
+ dy
, w
, h
, wxSIZE_AUTO
|wxSIZE_ALLOW_MINUS_ONE
);
2477 void wxWindowMac::MacOnScroll( wxScrollEvent
&event
)
2479 if ( event
.GetEventObject() == m_vScrollBar
|| event
.GetEventObject() == m_hScrollBar
)
2481 wxScrollWinEvent wevent
;
2482 wevent
.SetPosition(event
.GetPosition());
2483 wevent
.SetOrientation(event
.GetOrientation());
2484 wevent
.SetEventObject(this);
2486 if (event
.GetEventType() == wxEVT_SCROLL_TOP
)
2487 wevent
.SetEventType( wxEVT_SCROLLWIN_TOP
);
2488 else if (event
.GetEventType() == wxEVT_SCROLL_BOTTOM
)
2489 wevent
.SetEventType( wxEVT_SCROLLWIN_BOTTOM
);
2490 else if (event
.GetEventType() == wxEVT_SCROLL_LINEUP
)
2491 wevent
.SetEventType( wxEVT_SCROLLWIN_LINEUP
);
2492 else if (event
.GetEventType() == wxEVT_SCROLL_LINEDOWN
)
2493 wevent
.SetEventType( wxEVT_SCROLLWIN_LINEDOWN
);
2494 else if (event
.GetEventType() == wxEVT_SCROLL_PAGEUP
)
2495 wevent
.SetEventType( wxEVT_SCROLLWIN_PAGEUP
);
2496 else if (event
.GetEventType() == wxEVT_SCROLL_PAGEDOWN
)
2497 wevent
.SetEventType( wxEVT_SCROLLWIN_PAGEDOWN
);
2498 else if (event
.GetEventType() == wxEVT_SCROLL_THUMBTRACK
)
2499 wevent
.SetEventType( wxEVT_SCROLLWIN_THUMBTRACK
);
2500 else if (event
.GetEventType() == wxEVT_SCROLL_THUMBRELEASE
)
2501 wevent
.SetEventType( wxEVT_SCROLLWIN_THUMBRELEASE
);
2503 HandleWindowEvent(wevent
);
2507 // Get the window with the focus
2508 wxWindowMac
*wxWindowBase::DoFindFocus()
2510 ControlRef control
;
2511 GetKeyboardFocus( GetUserFocusWindow() , &control
) ;
2512 return wxFindControlFromMacControl( control
) ;
2515 void wxWindowMac::OnInternalIdle()
2517 // This calls the UI-update mechanism (querying windows for
2518 // menu/toolbar/control state information)
2519 if (wxUpdateUIEvent::CanUpdate(this) && IsShown())
2520 UpdateWindowUI(wxUPDATE_UI_FROMIDLE
);
2523 // Raise the window to the top of the Z order
2524 void wxWindowMac::Raise()
2526 m_peer
->SetZOrder( true , NULL
) ;
2529 // Lower the window to the bottom of the Z order
2530 void wxWindowMac::Lower()
2532 m_peer
->SetZOrder( false , NULL
) ;
2535 // static wxWindow *gs_lastWhich = NULL;
2537 bool wxWindowMac::MacSetupCursor( const wxPoint
& pt
)
2539 // first trigger a set cursor event
2541 wxPoint clientorigin
= GetClientAreaOrigin() ;
2542 wxSize clientsize
= GetClientSize() ;
2544 if ( wxRect2DInt( clientorigin
.x
, clientorigin
.y
, clientsize
.x
, clientsize
.y
).Contains( wxPoint2DInt( pt
) ) )
2546 wxSetCursorEvent
event( pt
.x
, pt
.y
);
2548 bool processedEvtSetCursor
= HandleWindowEvent(event
);
2549 if ( processedEvtSetCursor
&& event
.HasCursor() )
2551 cursor
= event
.GetCursor() ;
2555 // the test for processedEvtSetCursor is here to prevent using m_cursor
2556 // if the user code caught EVT_SET_CURSOR() and returned nothing from
2557 // it - this is a way to say that our cursor shouldn't be used for this
2559 if ( !processedEvtSetCursor
&& m_cursor
.Ok() )
2562 if ( !wxIsBusy() && !GetParent() )
2563 cursor
= *wxSTANDARD_CURSOR
;
2567 cursor
.MacInstall() ;
2570 return cursor
.Ok() ;
2573 wxString
wxWindowMac::MacGetToolTipString( wxPoint
&WXUNUSED(pt
) )
2577 return m_tooltip
->GetTip() ;
2580 return wxEmptyString
;
2583 void wxWindowMac::ClearBackground()
2589 void wxWindowMac::Update()
2591 wxTopLevelWindowMac
* top
= MacGetTopLevelWindow();
2593 top
->MacPerformUpdates() ;
2596 wxTopLevelWindowMac
* wxWindowMac::MacGetTopLevelWindow() const
2598 wxTopLevelWindowMac
* win
= NULL
;
2599 WindowRef window
= (WindowRef
) MacGetTopLevelWindowRef() ;
2601 win
= wxFindWinFromMacWindow( window
) ;
2606 const wxRect
& wxWindowMac::MacGetClippedClientRect() const
2608 MacUpdateClippedRects() ;
2610 return m_cachedClippedClientRect
;
2613 const wxRect
& wxWindowMac::MacGetClippedRect() const
2615 MacUpdateClippedRects() ;
2617 return m_cachedClippedRect
;
2620 const wxRect
&wxWindowMac:: MacGetClippedRectWithOuterStructure() const
2622 MacUpdateClippedRects() ;
2624 return m_cachedClippedRectWithOuterStructure
;
2627 const wxRegion
& wxWindowMac::MacGetVisibleRegion( bool includeOuterStructures
)
2629 static wxRegion emptyrgn
;
2631 if ( !m_isBeingDeleted
&& MacIsReallyShown() /*m_peer->IsVisible() */ )
2633 MacUpdateClippedRects() ;
2634 if ( includeOuterStructures
)
2635 return m_cachedClippedRegionWithOuterStructure
;
2637 return m_cachedClippedRegion
;
2645 void wxWindowMac::MacUpdateClippedRects() const
2647 if ( m_cachedClippedRectValid
)
2650 // includeOuterStructures is true if we try to draw somthing like a focus ring etc.
2651 // also a window dc uses this, in this case we only clip in the hierarchy for hard
2652 // borders like a scrollwindow, splitter etc otherwise we end up in a paranoia having
2653 // to add focus borders everywhere
2655 Rect r
, rIncludingOuterStructures
;
2657 m_peer
->GetRect( &r
) ;
2658 r
.left
-= MacGetLeftBorderSize() ;
2659 r
.top
-= MacGetTopBorderSize() ;
2660 r
.bottom
+= MacGetBottomBorderSize() ;
2661 r
.right
+= MacGetRightBorderSize() ;
2668 rIncludingOuterStructures
= r
;
2669 InsetRect( &rIncludingOuterStructures
, -4 , -4 ) ;
2671 wxRect cl
= GetClientRect() ;
2672 Rect rClient
= { cl
.y
, cl
.x
, cl
.y
+ cl
.height
, cl
.x
+ cl
.width
} ;
2676 const wxWindow
* child
= this ;
2677 const wxWindow
* parent
= NULL
;
2679 while ( !child
->IsTopLevel() && ( parent
= child
->GetParent() ) != NULL
)
2681 if ( parent
->MacIsChildOfClientArea(child
) )
2683 size
= parent
->GetClientSize() ;
2684 wxPoint origin
= parent
->GetClientAreaOrigin() ;
2690 // this will be true for scrollbars, toolbars etc.
2691 size
= parent
->GetSize() ;
2692 y
= parent
->MacGetTopBorderSize() ;
2693 x
= parent
->MacGetLeftBorderSize() ;
2694 size
.x
-= parent
->MacGetLeftBorderSize() + parent
->MacGetRightBorderSize() ;
2695 size
.y
-= parent
->MacGetTopBorderSize() + parent
->MacGetBottomBorderSize() ;
2698 parent
->MacWindowToRootWindow( &x
, &y
) ;
2699 MacRootWindowToWindow( &x
, &y
) ;
2701 Rect rparent
= { y
, x
, y
+ size
.y
, x
+ size
.x
} ;
2703 // the wxwindow and client rects will always be clipped
2704 SectRect( &r
, &rparent
, &r
) ;
2705 SectRect( &rClient
, &rparent
, &rClient
) ;
2707 // the structure only at 'hard' borders
2708 if ( parent
->MacClipChildren() ||
2709 ( parent
->GetParent() && parent
->GetParent()->MacClipGrandChildren() ) )
2711 SectRect( &rIncludingOuterStructures
, &rparent
, &rIncludingOuterStructures
) ;
2717 m_cachedClippedRect
= wxRect( r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
) ;
2718 m_cachedClippedClientRect
= wxRect( rClient
.left
, rClient
.top
,
2719 rClient
.right
- rClient
.left
, rClient
.bottom
- rClient
.top
) ;
2720 m_cachedClippedRectWithOuterStructure
= wxRect(
2721 rIncludingOuterStructures
.left
, rIncludingOuterStructures
.top
,
2722 rIncludingOuterStructures
.right
- rIncludingOuterStructures
.left
,
2723 rIncludingOuterStructures
.bottom
- rIncludingOuterStructures
.top
) ;
2725 m_cachedClippedRegionWithOuterStructure
= wxRegion( m_cachedClippedRectWithOuterStructure
) ;
2726 m_cachedClippedRegion
= wxRegion( m_cachedClippedRect
) ;
2727 m_cachedClippedClientRegion
= wxRegion( m_cachedClippedClientRect
) ;
2729 m_cachedClippedRectValid
= true ;
2733 This function must not change the updatergn !
2735 bool wxWindowMac::MacDoRedraw( void* updatergnr
, long time
)
2737 bool handled
= false ;
2739 RgnHandle updatergn
= (RgnHandle
) updatergnr
;
2740 GetRegionBounds( updatergn
, &updatebounds
) ;
2742 // wxLogDebug(wxT("update for %s bounds %d, %d, %d, %d"), wxString(GetClassInfo()->GetClassName()).c_str(), updatebounds.left, updatebounds.top , updatebounds.right , updatebounds.bottom ) ;
2744 if ( !EmptyRgn(updatergn
) )
2746 RgnHandle newupdate
= NewRgn() ;
2747 wxSize point
= GetClientSize() ;
2748 wxPoint origin
= GetClientAreaOrigin() ;
2749 SetRectRgn( newupdate
, origin
.x
, origin
.y
, origin
.x
+ point
.x
, origin
.y
+ point
.y
) ;
2750 SectRgn( newupdate
, updatergn
, newupdate
) ;
2752 // first send an erase event to the entire update area
2754 // for the toplevel window this really is the entire area
2755 // for all the others only their client area, otherwise they
2756 // might be drawing with full alpha and eg put blue into
2757 // the grow-box area of a scrolled window (scroll sample)
2758 wxDC
* dc
= new wxWindowDC(this);
2760 dc
->SetClippingRegion(wxRegion(HIShapeCreateWithQDRgn(updatergn
)));
2762 dc
->SetClippingRegion(wxRegion(HIShapeCreateWithQDRgn(newupdate
)));
2764 wxEraseEvent
eevent( GetId(), dc
);
2765 eevent
.SetEventObject( this );
2766 HandleWindowEvent( eevent
);
2772 // calculate a client-origin version of the update rgn and set m_updateRegion to that
2773 OffsetRgn( newupdate
, -origin
.x
, -origin
.y
) ;
2774 m_updateRegion
= wxRegion(HIShapeCreateWithQDRgn(newupdate
)) ;
2775 DisposeRgn( newupdate
) ;
2777 if ( !m_updateRegion
.Empty() )
2779 // paint the window itself
2782 event
.SetTimestamp(time
);
2783 event
.SetEventObject(this);
2784 HandleWindowEvent(event
);
2788 // now we cannot rely on having its borders drawn by a window itself, as it does not
2789 // get the updateRgn wide enough to always do so, so we do it from the parent
2790 // this would also be the place to draw any custom backgrounds for native controls
2791 // in Composited windowing
2792 wxPoint clientOrigin
= GetClientAreaOrigin() ;
2796 for (wxWindowList::compatibility_iterator node
= GetChildren().GetFirst(); node
; node
= node
->GetNext())
2798 child
= node
->GetData();
2801 if (child
== m_vScrollBar
)
2803 if (child
== m_hScrollBar
)
2805 if (child
->IsTopLevel())
2807 if (!child
->IsShown())
2810 // only draw those in the update region (add a safety margin of 10 pixels for shadow effects
2812 child
->GetPosition( &x
, &y
);
2813 child
->GetSize( &w
, &h
);
2814 Rect childRect
= { y
, x
, y
+ h
, x
+ w
} ;
2815 OffsetRect( &childRect
, clientOrigin
.x
, clientOrigin
.y
) ;
2816 InsetRect( &childRect
, -10 , -10) ;
2818 if ( RectInRgn( &childRect
, updatergn
) )
2820 // paint custom borders
2821 wxNcPaintEvent
eventNc( child
->GetId() );
2822 eventNc
.SetEventObject( child
);
2823 if ( !child
->HandleWindowEvent( eventNc
) )
2825 child
->MacPaintBorders(0, 0) ;
2835 WXWindow
wxWindowMac::MacGetTopLevelWindowRef() const
2837 wxWindowMac
*iter
= (wxWindowMac
*)this ;
2841 if ( iter
->IsTopLevel() )
2843 wxTopLevelWindow
* toplevel
= wxDynamicCast(iter
,wxTopLevelWindow
);
2845 return toplevel
->MacGetWindowRef();
2847 wxPopupWindow
* popupwin
= wxDynamicCast(iter
,wxPopupWindow
);
2849 return popupwin
->MacGetPopupWindowRef();
2852 iter
= iter
->GetParent() ;
2858 bool wxWindowMac::MacHasScrollBarCorner() const
2860 /* Returns whether the scroll bars in a wxScrolledWindow should be
2861 * shortened. Scroll bars should be shortened if either:
2863 * - both scroll bars are visible, or
2865 * - there is a resize box in the parent frame's corner and this
2866 * window shares the bottom and right edge with the parent
2870 if ( m_hScrollBar
== NULL
&& m_vScrollBar
== NULL
)
2873 if ( ( m_hScrollBar
&& m_hScrollBar
->IsShown() )
2874 && ( m_vScrollBar
&& m_vScrollBar
->IsShown() ) )
2876 // Both scroll bars visible
2881 wxPoint thisWindowBottomRight
= GetScreenRect().GetBottomRight();
2883 for ( const wxWindow
*win
= this; win
; win
= win
->GetParent() )
2885 const wxFrame
*frame
= wxDynamicCast( win
, wxFrame
) ;
2888 if ( frame
->GetWindowStyleFlag() & wxRESIZE_BORDER
)
2890 // Parent frame has resize handle
2891 wxPoint frameBottomRight
= frame
->GetScreenRect().GetBottomRight();
2893 // Note: allow for some wiggle room here as wxMac's
2894 // window rect calculations seem to be imprecise
2895 if ( abs( thisWindowBottomRight
.x
- frameBottomRight
.x
) <= 2
2896 && abs( thisWindowBottomRight
.y
- frameBottomRight
.y
) <= 2 )
2898 // Parent frame has resize handle and shares
2899 // right bottom corner
2904 // Parent frame has resize handle but doesn't
2905 // share right bottom corner
2911 // Parent frame doesn't have resize handle
2917 // No parent frame found
2922 void wxWindowMac::MacCreateScrollBars( long style
)
2924 wxASSERT_MSG( m_vScrollBar
== NULL
&& m_hScrollBar
== NULL
, wxT("attempt to create window twice") ) ;
2926 if ( style
& ( wxVSCROLL
| wxHSCROLL
) )
2928 int scrlsize
= MAC_SCROLLBAR_SIZE
;
2929 if ( GetWindowVariant() == wxWINDOW_VARIANT_SMALL
|| GetWindowVariant() == wxWINDOW_VARIANT_MINI
)
2931 scrlsize
= MAC_SMALL_SCROLLBAR_SIZE
;
2934 int adjust
= MacHasScrollBarCorner() ? scrlsize
- 1: 0 ;
2936 GetClientSize( &width
, &height
) ;
2938 wxPoint
vPoint(width
- scrlsize
, 0) ;
2939 wxSize
vSize(scrlsize
, height
- adjust
) ;
2940 wxPoint
hPoint(0, height
- scrlsize
) ;
2941 wxSize
hSize(width
- adjust
, scrlsize
) ;
2943 // we have to set the min size to a smaller value, otherwise they cannot get smaller (InitialSize sets MinSize)
2944 if ( style
& wxVSCROLL
)
2946 m_vScrollBar
= new wxScrollBar((wxWindow
*)this, wxID_ANY
, vPoint
, vSize
, wxVERTICAL
);
2947 m_vScrollBar
->SetMinSize( wxDefaultSize
);
2950 if ( style
& wxHSCROLL
)
2952 m_hScrollBar
= new wxScrollBar((wxWindow
*)this, wxID_ANY
, hPoint
, hSize
, wxHORIZONTAL
);
2953 m_hScrollBar
->SetMinSize( wxDefaultSize
);
2957 // because the create does not take into account the client area origin
2958 // we might have a real position shift
2959 MacRepositionScrollBars() ;
2962 bool wxWindowMac::MacIsChildOfClientArea( const wxWindow
* child
) const
2964 bool result
= ((child
== NULL
) || ((child
!= m_hScrollBar
) && (child
!= m_vScrollBar
)));
2969 void wxWindowMac::MacRepositionScrollBars()
2971 if ( !m_hScrollBar
&& !m_vScrollBar
)
2974 int scrlsize
= m_hScrollBar
? m_hScrollBar
->GetSize().y
: ( m_vScrollBar
? m_vScrollBar
->GetSize().x
: MAC_SCROLLBAR_SIZE
) ;
2975 int adjust
= MacHasScrollBarCorner() ? scrlsize
- 1 : 0 ;
2977 // get real client area
2979 GetSize( &width
, &height
);
2981 width
-= MacGetLeftBorderSize() + MacGetRightBorderSize();
2982 height
-= MacGetTopBorderSize() + MacGetBottomBorderSize();
2984 wxPoint
vPoint( width
- scrlsize
, 0 ) ;
2985 wxSize
vSize( scrlsize
, height
- adjust
) ;
2986 wxPoint
hPoint( 0 , height
- scrlsize
) ;
2987 wxSize
hSize( width
- adjust
, scrlsize
) ;
2990 int x
= 0, y
= 0, w
, h
;
2991 GetSize( &w
, &h
) ;
2993 MacClientToRootWindow( &x
, &y
) ;
2994 MacClientToRootWindow( &w
, &h
) ;
2996 wxWindowMac
*iter
= (wxWindowMac
*)this ;
2998 int totW
= 10000 , totH
= 10000;
3001 if ( iter
->IsTopLevel() )
3003 iter
->GetSize( &totW
, &totH
) ;
3007 iter
= iter
->GetParent() ;
3021 if ( w
- x
>= totW
)
3026 if ( h
- y
>= totH
)
3034 m_vScrollBar
->SetSize( vPoint
.x
, vPoint
.y
, vSize
.x
, vSize
.y
, wxSIZE_ALLOW_MINUS_ONE
);
3036 m_hScrollBar
->SetSize( hPoint
.x
, hPoint
.y
, hSize
.x
, hSize
.y
, wxSIZE_ALLOW_MINUS_ONE
);
3039 bool wxWindowMac::AcceptsFocus() const
3041 return MacCanFocus() && wxWindowBase::AcceptsFocus();
3044 void wxWindowMac::MacSuperChangedPosition()
3046 // only window-absolute structures have to be moved i.e. controls
3048 m_cachedClippedRectValid
= false ;
3051 wxWindowList::compatibility_iterator node
= GetChildren().GetFirst();
3054 child
= node
->GetData();
3055 child
->MacSuperChangedPosition() ;
3057 node
= node
->GetNext();
3061 void wxWindowMac::MacTopLevelWindowChangedPosition()
3063 // only screen-absolute structures have to be moved i.e. glcanvas
3066 wxWindowList::compatibility_iterator node
= GetChildren().GetFirst();
3069 child
= node
->GetData();
3070 child
->MacTopLevelWindowChangedPosition() ;
3072 node
= node
->GetNext();
3076 long wxWindowMac::MacGetLeftBorderSize() const
3083 if (HasFlag(wxRAISED_BORDER
) || HasFlag( wxSUNKEN_BORDER
) || HasFlag(wxDOUBLE_BORDER
))
3085 // this metric is only the 'outset' outside the simple frame rect
3086 GetThemeMetric( kThemeMetricEditTextFrameOutset
, &border
) ;
3089 else if (HasFlag(wxSIMPLE_BORDER
))
3091 // this metric is only the 'outset' outside the simple frame rect
3092 GetThemeMetric( kThemeMetricListBoxFrameOutset
, &border
) ;
3099 long wxWindowMac::MacGetRightBorderSize() const
3101 // they are all symmetric in mac themes
3102 return MacGetLeftBorderSize() ;
3105 long wxWindowMac::MacGetTopBorderSize() const
3107 // they are all symmetric in mac themes
3108 return MacGetLeftBorderSize() ;
3111 long wxWindowMac::MacGetBottomBorderSize() const
3113 // they are all symmetric in mac themes
3114 return MacGetLeftBorderSize() ;
3117 long wxWindowMac::MacRemoveBordersFromStyle( long style
)
3119 return style
& ~wxBORDER_MASK
;
3122 // Find the wxWindowMac at the current mouse position, returning the mouse
3124 wxWindowMac
* wxFindWindowAtPointer( wxPoint
& pt
)
3126 pt
= wxGetMousePosition();
3127 wxWindowMac
* found
= wxFindWindowAtPoint(pt
);
3132 // Get the current mouse position.
3133 wxPoint
wxGetMousePosition()
3137 wxGetMousePosition( &x
, &y
);
3139 return wxPoint(x
, y
);
3142 void wxWindowMac::OnMouseEvent( wxMouseEvent
&event
)
3144 if ( event
.GetEventType() == wxEVT_RIGHT_DOWN
)
3146 // copied from wxGTK : CS
3147 // VZ: shouldn't we move this to base class then?
3149 // generate a "context menu" event: this is similar to wxEVT_RIGHT_DOWN
3152 // (a) it's a command event and so is propagated to the parent
3153 // (b) under MSW it can be generated from kbd too
3154 // (c) it uses screen coords (because of (a))
3155 wxContextMenuEvent
evtCtx(wxEVT_CONTEXT_MENU
,
3157 this->ClientToScreen(event
.GetPosition()));
3158 if ( ! HandleWindowEvent(evtCtx
) )
3167 void wxWindowMac::OnPaint( wxPaintEvent
& WXUNUSED(event
) )
3169 if ( wxTheApp
->MacGetCurrentEvent() != NULL
&& wxTheApp
->MacGetCurrentEventHandlerCallRef() != NULL
3170 && GetBackgroundStyle() != wxBG_STYLE_TRANSPARENT
)
3171 CallNextEventHandler(
3172 (EventHandlerCallRef
)wxTheApp
->MacGetCurrentEventHandlerCallRef() ,
3173 (EventRef
) wxTheApp
->MacGetCurrentEvent() ) ;
3176 void wxWindowMac::MacHandleControlClick(WXWidget
WXUNUSED(control
),
3177 wxInt16
WXUNUSED(controlpart
),
3178 bool WXUNUSED(mouseStillDown
))
3182 Rect
wxMacGetBoundsForControl( wxWindow
* window
, const wxPoint
& pos
, const wxSize
&size
, bool adjustForOrigin
)
3186 window
->MacGetBoundsForControl( pos
, size
, x
, y
, w
, h
, adjustForOrigin
) ;
3187 Rect bounds
= { y
, x
, y
+ h
, x
+ w
};
3192 wxInt32
wxWindowMac::MacControlHit(WXEVENTHANDLERREF
WXUNUSED(handler
) , WXEVENTREF
WXUNUSED(event
) )
3194 return eventNotHandledErr
;
3197 bool wxWindowMac::Reparent(wxWindowBase
*newParentBase
)
3199 wxWindowMac
*newParent
= (wxWindowMac
*)newParentBase
;
3200 if ( !wxWindowBase::Reparent(newParent
) )
3203 // copied from MacPostControlCreate
3204 ControlRef container
= (ControlRef
) GetParent()->GetHandle() ;
3206 wxASSERT_MSG( container
!= NULL
, wxT("No valid mac container control") ) ;
3208 ::EmbedControl( m_peer
->GetControlRef() , container
) ;
3213 bool wxWindowMac::SetTransparent(wxByte alpha
)
3215 SetBackgroundStyle(wxBG_STYLE_TRANSPARENT
);
3217 if ( alpha
!= m_macAlpha
)
3219 m_macAlpha
= alpha
;
3226 bool wxWindowMac::CanSetTransparent()
3231 wxByte
wxWindowMac::GetTransparent() const