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 ( IsShownOnScreen() )
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
= IsShownOnScreen() ;
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 ( IsShownOnScreen() )
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::MacIsReallyEnabled()
1993 return m_peer
->IsEnabled() ;
1996 bool wxWindowMac::MacIsReallyHilited()
1998 return m_peer
->IsActive();
2001 void wxWindowMac::MacFlashInvalidAreas()
2003 #if TARGET_API_MAC_OSX
2004 HIViewFlashDirtyArea( (WindowRef
) MacGetTopLevelWindowRef() ) ;
2008 int wxWindowMac::GetCharHeight() const
2010 wxClientDC
dc( (wxWindowMac
*)this ) ;
2012 return dc
.GetCharHeight() ;
2015 int wxWindowMac::GetCharWidth() const
2017 wxClientDC
dc( (wxWindowMac
*)this ) ;
2019 return dc
.GetCharWidth() ;
2022 void wxWindowMac::GetTextExtent(const wxString
& string
, int *x
, int *y
,
2023 int *descent
, int *externalLeading
, const wxFont
*theFont
) const
2025 const wxFont
*fontToUse
= theFont
;
2027 fontToUse
= &m_font
;
2029 wxClientDC
dc( (wxWindowMac
*) this ) ;
2030 wxCoord lx
,ly
,ld
,le
;
2031 dc
.GetTextExtent( string
, &lx
, &ly
, &ld
, &le
, (wxFont
*)fontToUse
) ;
2032 if ( externalLeading
)
2033 *externalLeading
= le
;
2043 * Rect is given in client coordinates, for further reading, read wxTopLevelWindowMac::InvalidateRect
2044 * we always intersect with the entire window, not only with the client area
2047 void wxWindowMac::Refresh(bool WXUNUSED(eraseBack
), const wxRect
*rect
)
2049 if ( m_peer
== NULL
)
2052 if ( !IsShownOnScreen() )
2059 wxMacRectToNative( rect
, &r
) ;
2060 m_peer
->SetNeedsDisplay( &r
) ;
2064 m_peer
->SetNeedsDisplay() ;
2068 void wxWindowMac::DoFreeze()
2070 #if TARGET_API_MAC_OSX
2071 if ( m_peer
&& m_peer
->Ok() )
2072 m_peer
->SetDrawingEnabled( false ) ;
2076 void wxWindowMac::DoThaw()
2078 #if TARGET_API_MAC_OSX
2079 if ( m_peer
&& m_peer
->Ok() )
2081 m_peer
->SetDrawingEnabled( true ) ;
2082 m_peer
->InvalidateWithChildren() ;
2087 wxWindowMac
*wxGetActiveWindow()
2089 // actually this is a windows-only concept
2093 // Coordinates relative to the window
2094 void wxWindowMac::WarpPointer(int WXUNUSED(x_pos
), int WXUNUSED(y_pos
))
2096 // We really don't move the mouse programmatically under Mac.
2099 void wxWindowMac::OnEraseBackground(wxEraseEvent
& event
)
2101 if ( MacGetTopLevelWindow() == NULL
)
2104 #if TARGET_API_MAC_OSX
2105 if ( !m_backgroundColour.Ok() || GetBackgroundStyle() == wxBG_STYLE_TRANSPARENT )
2111 if ( GetBackgroundStyle() == wxBG_STYLE_COLOUR
)
2113 event
.GetDC()->Clear() ;
2121 void wxWindowMac::OnNcPaint( wxNcPaintEvent
& event
)
2126 int wxWindowMac::GetScrollPos(int orient
) const
2128 if ( orient
== wxHORIZONTAL
)
2131 return m_hScrollBar
->GetThumbPosition() ;
2136 return m_vScrollBar
->GetThumbPosition() ;
2142 // This now returns the whole range, not just the number
2143 // of positions that we can scroll.
2144 int wxWindowMac::GetScrollRange(int orient
) const
2146 if ( orient
== wxHORIZONTAL
)
2149 return m_hScrollBar
->GetRange() ;
2154 return m_vScrollBar
->GetRange() ;
2160 int wxWindowMac::GetScrollThumb(int orient
) const
2162 if ( orient
== wxHORIZONTAL
)
2165 return m_hScrollBar
->GetThumbSize() ;
2170 return m_vScrollBar
->GetThumbSize() ;
2176 void wxWindowMac::SetScrollPos(int orient
, int pos
, bool WXUNUSED(refresh
))
2178 if ( orient
== wxHORIZONTAL
)
2181 m_hScrollBar
->SetThumbPosition( pos
) ;
2186 m_vScrollBar
->SetThumbPosition( pos
) ;
2191 wxWindowMac::AlwaysShowScrollbars(bool hflag
, bool vflag
)
2193 bool needVisibilityUpdate
= false;
2195 if ( m_hScrollBarAlwaysShown
!= hflag
)
2197 m_hScrollBarAlwaysShown
= hflag
;
2198 needVisibilityUpdate
= true;
2201 if ( m_vScrollBarAlwaysShown
!= vflag
)
2203 m_vScrollBarAlwaysShown
= vflag
;
2204 needVisibilityUpdate
= true;
2207 if ( needVisibilityUpdate
)
2208 DoUpdateScrollbarVisibility();
2212 // we draw borders and grow boxes, are already set up and clipped in the current port / cgContextRef
2213 // our own window origin is at leftOrigin/rightOrigin
2216 void wxWindowMac::MacPaintGrowBox()
2221 if ( MacHasScrollBarCorner() )
2225 CGContextRef cgContext
= (CGContextRef
) MacGetCGContextRef() ;
2226 wxASSERT( cgContext
) ;
2228 m_peer
->GetRect( &rect
) ;
2230 int size
= m_hScrollBar
? m_hScrollBar
->GetSize().y
: ( m_vScrollBar
? m_vScrollBar
->GetSize().x
: MAC_SCROLLBAR_SIZE
) ;
2231 CGRect cgrect
= CGRectMake( rect
.right
- size
, rect
.bottom
- size
, size
, size
) ;
2232 CGPoint cgpoint
= CGPointMake( rect
.right
- size
, rect
.bottom
- size
) ;
2233 CGContextSaveGState( cgContext
);
2235 if ( m_backgroundColour
.Ok() )
2237 CGContextSetFillColorWithColor( cgContext
, m_backgroundColour
.GetCGColor() );
2241 CGContextSetRGBFillColor( cgContext
, 1.0, 1.0 , 1.0 , 1.0 );
2243 CGContextFillRect( cgContext
, cgrect
);
2244 CGContextRestoreGState( cgContext
);
2248 void wxWindowMac::MacPaintBorders( int WXUNUSED(leftOrigin
) , int WXUNUSED(rightOrigin
) )
2254 bool hasFocus
= m_peer
->NeedsFocusRect() && m_peer
->HasFocus() ;
2256 // back to the surrounding frame rectangle
2257 m_peer
->GetRect( &rect
) ;
2258 InsetRect( &rect
, -1 , -1 ) ;
2261 CGRect cgrect
= CGRectMake( rect
.left
, rect
.top
, rect
.right
- rect
.left
,
2262 rect
.bottom
- rect
.top
) ;
2264 HIThemeFrameDrawInfo info
;
2265 memset( &info
, 0 , sizeof(info
) ) ;
2269 info
.state
= IsEnabled() ? kThemeStateActive
: kThemeStateInactive
;
2270 info
.isFocused
= hasFocus
;
2272 CGContextRef cgContext
= (CGContextRef
) GetParent()->MacGetCGContextRef() ;
2273 wxASSERT( cgContext
) ;
2275 if ( HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
) || HasFlag(wxDOUBLE_BORDER
) )
2277 info
.kind
= kHIThemeFrameTextFieldSquare
;
2278 HIThemeDrawFrame( &cgrect
, &info
, cgContext
, kHIThemeOrientationNormal
) ;
2280 else if ( HasFlag(wxSIMPLE_BORDER
) )
2282 info
.kind
= kHIThemeFrameListBox
;
2283 HIThemeDrawFrame( &cgrect
, &info
, cgContext
, kHIThemeOrientationNormal
) ;
2285 else if ( hasFocus
)
2287 HIThemeDrawFocusRect( &cgrect
, true , cgContext
, kHIThemeOrientationNormal
) ;
2289 #if 0 // TODO REMOVE now done in a separate call earlier in drawing the window itself
2290 m_peer
->GetRect( &rect
) ;
2291 if ( MacHasScrollBarCorner() )
2293 int variant
= (m_hScrollBar
== NULL
? m_vScrollBar
: m_hScrollBar
) ->GetWindowVariant();
2294 int size
= m_hScrollBar
? m_hScrollBar
->GetSize().y
: ( m_vScrollBar
? m_vScrollBar
->GetSize().x
: MAC_SCROLLBAR_SIZE
) ;
2295 CGRect cgrect
= CGRectMake( rect
.right
- size
, rect
.bottom
- size
, size
, size
) ;
2296 CGPoint cgpoint
= CGPointMake( rect
.right
- size
, rect
.bottom
- size
) ;
2297 HIThemeGrowBoxDrawInfo info
;
2298 memset( &info
, 0, sizeof(info
) ) ;
2300 info
.state
= IsEnabled() ? kThemeStateActive
: kThemeStateInactive
;
2301 info
.kind
= kHIThemeGrowBoxKindNone
;
2302 // contrary to the docs ...SizeSmall does not work
2303 info
.size
= kHIThemeGrowBoxSizeNormal
;
2304 info
.direction
= 0 ;
2305 HIThemeDrawGrowBox( &cgpoint
, &info
, cgContext
, kHIThemeOrientationNormal
) ;
2311 void wxWindowMac::RemoveChild( wxWindowBase
*child
)
2313 if ( child
== m_hScrollBar
)
2314 m_hScrollBar
= NULL
;
2315 if ( child
== m_vScrollBar
)
2316 m_vScrollBar
= NULL
;
2318 wxWindowBase::RemoveChild( child
) ;
2321 void wxWindowMac::DoUpdateScrollbarVisibility()
2323 bool triggerSizeEvent
= false;
2327 bool showHScrollBar
= m_hScrollBarAlwaysShown
|| m_hScrollBar
->IsNeeded();
2329 if ( m_hScrollBar
->IsShown() != showHScrollBar
)
2331 m_hScrollBar
->Show( showHScrollBar
);
2332 triggerSizeEvent
= true;
2338 bool showVScrollBar
= m_vScrollBarAlwaysShown
|| m_vScrollBar
->IsNeeded();
2340 if ( m_vScrollBar
->IsShown() != showVScrollBar
)
2342 m_vScrollBar
->Show( showVScrollBar
) ;
2343 triggerSizeEvent
= true;
2347 MacRepositionScrollBars() ;
2348 if ( triggerSizeEvent
)
2350 wxSizeEvent
event(GetSize(), m_windowId
);
2351 event
.SetEventObject(this);
2352 HandleWindowEvent(event
);
2356 // New function that will replace some of the above.
2357 void wxWindowMac::SetScrollbar(int orient
, int pos
, int thumb
,
2358 int range
, bool refresh
)
2360 if ( orient
== wxHORIZONTAL
&& m_hScrollBar
)
2361 m_hScrollBar
->SetScrollbar(pos
, thumb
, range
, thumb
, refresh
);
2362 else if ( orient
== wxVERTICAL
&& m_vScrollBar
)
2363 m_vScrollBar
->SetScrollbar(pos
, thumb
, range
, thumb
, refresh
);
2365 DoUpdateScrollbarVisibility();
2368 // Does a physical scroll
2369 void wxWindowMac::ScrollWindow(int dx
, int dy
, const wxRect
*rect
)
2371 if ( dx
== 0 && dy
== 0 )
2374 int width
, height
;
2375 GetClientSize( &width
, &height
) ;
2378 // note there currently is a bug in OSX which makes inefficient refreshes in case an entire control
2379 // area is scrolled, this does not occur if width and height are 2 pixels less,
2380 // TODO: write optimal workaround
2381 wxRect
scrollrect( MacGetLeftBorderSize() , MacGetTopBorderSize() , width
, height
) ;
2383 scrollrect
.Intersect( *rect
) ;
2385 if ( m_peer
->GetNeedsDisplay() )
2387 // because HIViewScrollRect does not scroll the already invalidated area we have two options:
2388 // in case there is already a pending redraw on that area
2389 // either immediate redraw or full invalidate
2391 // is the better overall solution, as it does not slow down scrolling
2392 m_peer
->SetNeedsDisplay() ;
2394 // this would be the preferred version for fast drawing controls
2395 HIViewRender(m_peer
->GetControlRef()) ;
2399 // as the native control might be not a 0/0 wx window coordinates, we have to offset
2400 scrollrect
.Offset( -MacGetLeftBorderSize() , -MacGetTopBorderSize() ) ;
2401 m_peer
->ScrollRect( &scrollrect
, dx
, dy
) ;
2404 // this would be the preferred version for fast drawing controls
2405 HIViewRender(m_peer
->GetControlRef()) ;
2411 for (wxWindowList::compatibility_iterator node
= GetChildren().GetFirst(); node
; node
= node
->GetNext())
2413 child
= node
->GetData();
2416 if (child
== m_vScrollBar
)
2418 if (child
== m_hScrollBar
)
2420 if (child
->IsTopLevel())
2423 child
->GetPosition( &x
, &y
);
2424 child
->GetSize( &w
, &h
);
2427 wxRect
rc( x
, y
, w
, h
);
2428 if (rect
->Intersects( rc
))
2429 child
->SetSize( x
+ dx
, y
+ dy
, w
, h
, wxSIZE_AUTO
|wxSIZE_ALLOW_MINUS_ONE
);
2433 child
->SetSize( x
+ dx
, y
+ dy
, w
, h
, wxSIZE_AUTO
|wxSIZE_ALLOW_MINUS_ONE
);
2438 void wxWindowMac::MacOnScroll( wxScrollEvent
&event
)
2440 if ( event
.GetEventObject() == m_vScrollBar
|| event
.GetEventObject() == m_hScrollBar
)
2442 wxScrollWinEvent wevent
;
2443 wevent
.SetPosition(event
.GetPosition());
2444 wevent
.SetOrientation(event
.GetOrientation());
2445 wevent
.SetEventObject(this);
2447 if (event
.GetEventType() == wxEVT_SCROLL_TOP
)
2448 wevent
.SetEventType( wxEVT_SCROLLWIN_TOP
);
2449 else if (event
.GetEventType() == wxEVT_SCROLL_BOTTOM
)
2450 wevent
.SetEventType( wxEVT_SCROLLWIN_BOTTOM
);
2451 else if (event
.GetEventType() == wxEVT_SCROLL_LINEUP
)
2452 wevent
.SetEventType( wxEVT_SCROLLWIN_LINEUP
);
2453 else if (event
.GetEventType() == wxEVT_SCROLL_LINEDOWN
)
2454 wevent
.SetEventType( wxEVT_SCROLLWIN_LINEDOWN
);
2455 else if (event
.GetEventType() == wxEVT_SCROLL_PAGEUP
)
2456 wevent
.SetEventType( wxEVT_SCROLLWIN_PAGEUP
);
2457 else if (event
.GetEventType() == wxEVT_SCROLL_PAGEDOWN
)
2458 wevent
.SetEventType( wxEVT_SCROLLWIN_PAGEDOWN
);
2459 else if (event
.GetEventType() == wxEVT_SCROLL_THUMBTRACK
)
2460 wevent
.SetEventType( wxEVT_SCROLLWIN_THUMBTRACK
);
2461 else if (event
.GetEventType() == wxEVT_SCROLL_THUMBRELEASE
)
2462 wevent
.SetEventType( wxEVT_SCROLLWIN_THUMBRELEASE
);
2464 HandleWindowEvent(wevent
);
2468 // Get the window with the focus
2469 wxWindowMac
*wxWindowBase::DoFindFocus()
2471 ControlRef control
;
2472 GetKeyboardFocus( GetUserFocusWindow() , &control
) ;
2473 return wxFindControlFromMacControl( control
) ;
2476 void wxWindowMac::OnInternalIdle()
2478 // This calls the UI-update mechanism (querying windows for
2479 // menu/toolbar/control state information)
2480 if (wxUpdateUIEvent::CanUpdate(this) && IsShownOnScreen())
2481 UpdateWindowUI(wxUPDATE_UI_FROMIDLE
);
2484 // Raise the window to the top of the Z order
2485 void wxWindowMac::Raise()
2487 m_peer
->SetZOrder( true , NULL
) ;
2490 // Lower the window to the bottom of the Z order
2491 void wxWindowMac::Lower()
2493 m_peer
->SetZOrder( false , NULL
) ;
2496 // static wxWindow *gs_lastWhich = NULL;
2498 bool wxWindowMac::MacSetupCursor( const wxPoint
& pt
)
2500 // first trigger a set cursor event
2502 wxPoint clientorigin
= GetClientAreaOrigin() ;
2503 wxSize clientsize
= GetClientSize() ;
2505 if ( wxRect2DInt( clientorigin
.x
, clientorigin
.y
, clientsize
.x
, clientsize
.y
).Contains( wxPoint2DInt( pt
) ) )
2507 wxSetCursorEvent
event( pt
.x
, pt
.y
);
2509 bool processedEvtSetCursor
= HandleWindowEvent(event
);
2510 if ( processedEvtSetCursor
&& event
.HasCursor() )
2512 cursor
= event
.GetCursor() ;
2516 // the test for processedEvtSetCursor is here to prevent using m_cursor
2517 // if the user code caught EVT_SET_CURSOR() and returned nothing from
2518 // it - this is a way to say that our cursor shouldn't be used for this
2520 if ( !processedEvtSetCursor
&& m_cursor
.Ok() )
2523 if ( !wxIsBusy() && !GetParent() )
2524 cursor
= *wxSTANDARD_CURSOR
;
2528 cursor
.MacInstall() ;
2531 return cursor
.Ok() ;
2534 wxString
wxWindowMac::MacGetToolTipString( wxPoint
&WXUNUSED(pt
) )
2538 return m_tooltip
->GetTip() ;
2541 return wxEmptyString
;
2544 void wxWindowMac::ClearBackground()
2550 void wxWindowMac::Update()
2552 wxTopLevelWindowMac
* top
= MacGetTopLevelWindow();
2554 top
->MacPerformUpdates() ;
2557 wxTopLevelWindowMac
* wxWindowMac::MacGetTopLevelWindow() const
2559 wxTopLevelWindowMac
* win
= NULL
;
2560 WindowRef window
= (WindowRef
) MacGetTopLevelWindowRef() ;
2562 win
= wxFindWinFromMacWindow( window
) ;
2567 const wxRect
& wxWindowMac::MacGetClippedClientRect() const
2569 MacUpdateClippedRects() ;
2571 return m_cachedClippedClientRect
;
2574 const wxRect
& wxWindowMac::MacGetClippedRect() const
2576 MacUpdateClippedRects() ;
2578 return m_cachedClippedRect
;
2581 const wxRect
&wxWindowMac:: MacGetClippedRectWithOuterStructure() const
2583 MacUpdateClippedRects() ;
2585 return m_cachedClippedRectWithOuterStructure
;
2588 const wxRegion
& wxWindowMac::MacGetVisibleRegion( bool includeOuterStructures
)
2590 static wxRegion emptyrgn
;
2592 if ( !m_isBeingDeleted
&& IsShownOnScreen() )
2594 MacUpdateClippedRects() ;
2595 if ( includeOuterStructures
)
2596 return m_cachedClippedRegionWithOuterStructure
;
2598 return m_cachedClippedRegion
;
2606 void wxWindowMac::MacUpdateClippedRects() const
2608 if ( m_cachedClippedRectValid
)
2611 // includeOuterStructures is true if we try to draw somthing like a focus ring etc.
2612 // also a window dc uses this, in this case we only clip in the hierarchy for hard
2613 // borders like a scrollwindow, splitter etc otherwise we end up in a paranoia having
2614 // to add focus borders everywhere
2616 Rect r
, rIncludingOuterStructures
;
2618 m_peer
->GetRect( &r
) ;
2619 r
.left
-= MacGetLeftBorderSize() ;
2620 r
.top
-= MacGetTopBorderSize() ;
2621 r
.bottom
+= MacGetBottomBorderSize() ;
2622 r
.right
+= MacGetRightBorderSize() ;
2629 rIncludingOuterStructures
= r
;
2630 InsetRect( &rIncludingOuterStructures
, -4 , -4 ) ;
2632 wxRect cl
= GetClientRect() ;
2633 Rect rClient
= { cl
.y
, cl
.x
, cl
.y
+ cl
.height
, cl
.x
+ cl
.width
} ;
2637 const wxWindow
* child
= this ;
2638 const wxWindow
* parent
= NULL
;
2640 while ( !child
->IsTopLevel() && ( parent
= child
->GetParent() ) != NULL
)
2642 if ( parent
->MacIsChildOfClientArea(child
) )
2644 size
= parent
->GetClientSize() ;
2645 wxPoint origin
= parent
->GetClientAreaOrigin() ;
2651 // this will be true for scrollbars, toolbars etc.
2652 size
= parent
->GetSize() ;
2653 y
= parent
->MacGetTopBorderSize() ;
2654 x
= parent
->MacGetLeftBorderSize() ;
2655 size
.x
-= parent
->MacGetLeftBorderSize() + parent
->MacGetRightBorderSize() ;
2656 size
.y
-= parent
->MacGetTopBorderSize() + parent
->MacGetBottomBorderSize() ;
2659 parent
->MacWindowToRootWindow( &x
, &y
) ;
2660 MacRootWindowToWindow( &x
, &y
) ;
2662 Rect rparent
= { y
, x
, y
+ size
.y
, x
+ size
.x
} ;
2664 // the wxwindow and client rects will always be clipped
2665 SectRect( &r
, &rparent
, &r
) ;
2666 SectRect( &rClient
, &rparent
, &rClient
) ;
2668 // the structure only at 'hard' borders
2669 if ( parent
->MacClipChildren() ||
2670 ( parent
->GetParent() && parent
->GetParent()->MacClipGrandChildren() ) )
2672 SectRect( &rIncludingOuterStructures
, &rparent
, &rIncludingOuterStructures
) ;
2678 m_cachedClippedRect
= wxRect( r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
) ;
2679 m_cachedClippedClientRect
= wxRect( rClient
.left
, rClient
.top
,
2680 rClient
.right
- rClient
.left
, rClient
.bottom
- rClient
.top
) ;
2681 m_cachedClippedRectWithOuterStructure
= wxRect(
2682 rIncludingOuterStructures
.left
, rIncludingOuterStructures
.top
,
2683 rIncludingOuterStructures
.right
- rIncludingOuterStructures
.left
,
2684 rIncludingOuterStructures
.bottom
- rIncludingOuterStructures
.top
) ;
2686 m_cachedClippedRegionWithOuterStructure
= wxRegion( m_cachedClippedRectWithOuterStructure
) ;
2687 m_cachedClippedRegion
= wxRegion( m_cachedClippedRect
) ;
2688 m_cachedClippedClientRegion
= wxRegion( m_cachedClippedClientRect
) ;
2690 m_cachedClippedRectValid
= true ;
2694 This function must not change the updatergn !
2696 bool wxWindowMac::MacDoRedraw( void* updatergnr
, long time
)
2698 bool handled
= false ;
2700 RgnHandle updatergn
= (RgnHandle
) updatergnr
;
2701 GetRegionBounds( updatergn
, &updatebounds
) ;
2703 // wxLogDebug(wxT("update for %s bounds %d, %d, %d, %d"), wxString(GetClassInfo()->GetClassName()).c_str(), updatebounds.left, updatebounds.top , updatebounds.right , updatebounds.bottom ) ;
2705 if ( !EmptyRgn(updatergn
) )
2707 RgnHandle newupdate
= NewRgn() ;
2708 wxSize point
= GetClientSize() ;
2709 wxPoint origin
= GetClientAreaOrigin() ;
2710 SetRectRgn( newupdate
, origin
.x
, origin
.y
, origin
.x
+ point
.x
, origin
.y
+ point
.y
) ;
2711 SectRgn( newupdate
, updatergn
, newupdate
) ;
2713 // first send an erase event to the entire update area
2715 // for the toplevel window this really is the entire area
2716 // for all the others only their client area, otherwise they
2717 // might be drawing with full alpha and eg put blue into
2718 // the grow-box area of a scrolled window (scroll sample)
2719 wxDC
* dc
= new wxWindowDC(this);
2721 dc
->SetClippingRegion(wxRegion(HIShapeCreateWithQDRgn(updatergn
)));
2723 dc
->SetClippingRegion(wxRegion(HIShapeCreateWithQDRgn(newupdate
)));
2725 wxEraseEvent
eevent( GetId(), dc
);
2726 eevent
.SetEventObject( this );
2727 HandleWindowEvent( eevent
);
2733 // calculate a client-origin version of the update rgn and set m_updateRegion to that
2734 OffsetRgn( newupdate
, -origin
.x
, -origin
.y
) ;
2735 m_updateRegion
= wxRegion(HIShapeCreateWithQDRgn(newupdate
)) ;
2736 DisposeRgn( newupdate
) ;
2738 if ( !m_updateRegion
.Empty() )
2740 // paint the window itself
2743 event
.SetTimestamp(time
);
2744 event
.SetEventObject(this);
2745 HandleWindowEvent(event
);
2749 // now we cannot rely on having its borders drawn by a window itself, as it does not
2750 // get the updateRgn wide enough to always do so, so we do it from the parent
2751 // this would also be the place to draw any custom backgrounds for native controls
2752 // in Composited windowing
2753 wxPoint clientOrigin
= GetClientAreaOrigin() ;
2757 for (wxWindowList::compatibility_iterator node
= GetChildren().GetFirst(); node
; node
= node
->GetNext())
2759 child
= node
->GetData();
2762 if (child
== m_vScrollBar
)
2764 if (child
== m_hScrollBar
)
2766 if (child
->IsTopLevel())
2768 if (!child
->IsShown())
2771 // only draw those in the update region (add a safety margin of 10 pixels for shadow effects
2773 child
->GetPosition( &x
, &y
);
2774 child
->GetSize( &w
, &h
);
2775 Rect childRect
= { y
, x
, y
+ h
, x
+ w
} ;
2776 OffsetRect( &childRect
, clientOrigin
.x
, clientOrigin
.y
) ;
2777 InsetRect( &childRect
, -10 , -10) ;
2779 if ( RectInRgn( &childRect
, updatergn
) )
2781 // paint custom borders
2782 wxNcPaintEvent
eventNc( child
->GetId() );
2783 eventNc
.SetEventObject( child
);
2784 if ( !child
->HandleWindowEvent( eventNc
) )
2786 child
->MacPaintBorders(0, 0) ;
2796 WXWindow
wxWindowMac::MacGetTopLevelWindowRef() const
2798 wxWindowMac
*iter
= (wxWindowMac
*)this ;
2802 if ( iter
->IsTopLevel() )
2804 wxTopLevelWindow
* toplevel
= wxDynamicCast(iter
,wxTopLevelWindow
);
2806 return toplevel
->MacGetWindowRef();
2808 wxPopupWindow
* popupwin
= wxDynamicCast(iter
,wxPopupWindow
);
2810 return popupwin
->MacGetPopupWindowRef();
2813 iter
= iter
->GetParent() ;
2819 bool wxWindowMac::MacHasScrollBarCorner() const
2821 /* Returns whether the scroll bars in a wxScrolledWindow should be
2822 * shortened. Scroll bars should be shortened if either:
2824 * - both scroll bars are visible, or
2826 * - there is a resize box in the parent frame's corner and this
2827 * window shares the bottom and right edge with the parent
2831 if ( m_hScrollBar
== NULL
&& m_vScrollBar
== NULL
)
2834 if ( ( m_hScrollBar
&& m_hScrollBar
->IsShown() )
2835 && ( m_vScrollBar
&& m_vScrollBar
->IsShown() ) )
2837 // Both scroll bars visible
2842 wxPoint thisWindowBottomRight
= GetScreenRect().GetBottomRight();
2844 for ( const wxWindow
*win
= this; win
; win
= win
->GetParent() )
2846 const wxFrame
*frame
= wxDynamicCast( win
, wxFrame
) ;
2849 if ( frame
->GetWindowStyleFlag() & wxRESIZE_BORDER
)
2851 // Parent frame has resize handle
2852 wxPoint frameBottomRight
= frame
->GetScreenRect().GetBottomRight();
2854 // Note: allow for some wiggle room here as wxMac's
2855 // window rect calculations seem to be imprecise
2856 if ( abs( thisWindowBottomRight
.x
- frameBottomRight
.x
) <= 2
2857 && abs( thisWindowBottomRight
.y
- frameBottomRight
.y
) <= 2 )
2859 // Parent frame has resize handle and shares
2860 // right bottom corner
2865 // Parent frame has resize handle but doesn't
2866 // share right bottom corner
2872 // Parent frame doesn't have resize handle
2878 // No parent frame found
2883 void wxWindowMac::MacCreateScrollBars( long style
)
2885 wxASSERT_MSG( m_vScrollBar
== NULL
&& m_hScrollBar
== NULL
, wxT("attempt to create window twice") ) ;
2887 if ( style
& ( wxVSCROLL
| wxHSCROLL
) )
2889 int scrlsize
= MAC_SCROLLBAR_SIZE
;
2890 if ( GetWindowVariant() == wxWINDOW_VARIANT_SMALL
|| GetWindowVariant() == wxWINDOW_VARIANT_MINI
)
2892 scrlsize
= MAC_SMALL_SCROLLBAR_SIZE
;
2895 int adjust
= MacHasScrollBarCorner() ? scrlsize
- 1: 0 ;
2897 GetClientSize( &width
, &height
) ;
2899 wxPoint
vPoint(width
- scrlsize
, 0) ;
2900 wxSize
vSize(scrlsize
, height
- adjust
) ;
2901 wxPoint
hPoint(0, height
- scrlsize
) ;
2902 wxSize
hSize(width
- adjust
, scrlsize
) ;
2904 // we have to set the min size to a smaller value, otherwise they cannot get smaller (InitialSize sets MinSize)
2905 if ( style
& wxVSCROLL
)
2907 m_vScrollBar
= new wxScrollBar((wxWindow
*)this, wxID_ANY
, vPoint
, vSize
, wxVERTICAL
);
2908 m_vScrollBar
->SetMinSize( wxDefaultSize
);
2911 if ( style
& wxHSCROLL
)
2913 m_hScrollBar
= new wxScrollBar((wxWindow
*)this, wxID_ANY
, hPoint
, hSize
, wxHORIZONTAL
);
2914 m_hScrollBar
->SetMinSize( wxDefaultSize
);
2918 // because the create does not take into account the client area origin
2919 // we might have a real position shift
2920 MacRepositionScrollBars() ;
2923 bool wxWindowMac::MacIsChildOfClientArea( const wxWindow
* child
) const
2925 bool result
= ((child
== NULL
) || ((child
!= m_hScrollBar
) && (child
!= m_vScrollBar
)));
2930 void wxWindowMac::MacRepositionScrollBars()
2932 if ( !m_hScrollBar
&& !m_vScrollBar
)
2935 int scrlsize
= m_hScrollBar
? m_hScrollBar
->GetSize().y
: ( m_vScrollBar
? m_vScrollBar
->GetSize().x
: MAC_SCROLLBAR_SIZE
) ;
2936 int adjust
= MacHasScrollBarCorner() ? scrlsize
- 1 : 0 ;
2938 // get real client area
2940 GetSize( &width
, &height
);
2942 width
-= MacGetLeftBorderSize() + MacGetRightBorderSize();
2943 height
-= MacGetTopBorderSize() + MacGetBottomBorderSize();
2945 wxPoint
vPoint( width
- scrlsize
, 0 ) ;
2946 wxSize
vSize( scrlsize
, height
- adjust
) ;
2947 wxPoint
hPoint( 0 , height
- scrlsize
) ;
2948 wxSize
hSize( width
- adjust
, scrlsize
) ;
2951 int x
= 0, y
= 0, w
, h
;
2952 GetSize( &w
, &h
) ;
2954 MacClientToRootWindow( &x
, &y
) ;
2955 MacClientToRootWindow( &w
, &h
) ;
2957 wxWindowMac
*iter
= (wxWindowMac
*)this ;
2959 int totW
= 10000 , totH
= 10000;
2962 if ( iter
->IsTopLevel() )
2964 iter
->GetSize( &totW
, &totH
) ;
2968 iter
= iter
->GetParent() ;
2982 if ( w
- x
>= totW
)
2987 if ( h
- y
>= totH
)
2995 m_vScrollBar
->SetSize( vPoint
.x
, vPoint
.y
, vSize
.x
, vSize
.y
, wxSIZE_ALLOW_MINUS_ONE
);
2997 m_hScrollBar
->SetSize( hPoint
.x
, hPoint
.y
, hSize
.x
, hSize
.y
, wxSIZE_ALLOW_MINUS_ONE
);
3000 bool wxWindowMac::AcceptsFocus() const
3002 return MacCanFocus() && wxWindowBase::AcceptsFocus();
3005 void wxWindowMac::MacSuperChangedPosition()
3007 // only window-absolute structures have to be moved i.e. controls
3009 m_cachedClippedRectValid
= false ;
3012 wxWindowList::compatibility_iterator node
= GetChildren().GetFirst();
3015 child
= node
->GetData();
3016 child
->MacSuperChangedPosition() ;
3018 node
= node
->GetNext();
3022 void wxWindowMac::MacTopLevelWindowChangedPosition()
3024 // only screen-absolute structures have to be moved i.e. glcanvas
3027 wxWindowList::compatibility_iterator node
= GetChildren().GetFirst();
3030 child
= node
->GetData();
3031 child
->MacTopLevelWindowChangedPosition() ;
3033 node
= node
->GetNext();
3037 long wxWindowMac::MacGetLeftBorderSize() const
3044 if (HasFlag(wxRAISED_BORDER
) || HasFlag( wxSUNKEN_BORDER
) || HasFlag(wxDOUBLE_BORDER
))
3046 // this metric is only the 'outset' outside the simple frame rect
3047 GetThemeMetric( kThemeMetricEditTextFrameOutset
, &border
) ;
3050 else if (HasFlag(wxSIMPLE_BORDER
))
3052 // this metric is only the 'outset' outside the simple frame rect
3053 GetThemeMetric( kThemeMetricListBoxFrameOutset
, &border
) ;
3060 long wxWindowMac::MacGetRightBorderSize() const
3062 // they are all symmetric in mac themes
3063 return MacGetLeftBorderSize() ;
3066 long wxWindowMac::MacGetTopBorderSize() const
3068 // they are all symmetric in mac themes
3069 return MacGetLeftBorderSize() ;
3072 long wxWindowMac::MacGetBottomBorderSize() const
3074 // they are all symmetric in mac themes
3075 return MacGetLeftBorderSize() ;
3078 long wxWindowMac::MacRemoveBordersFromStyle( long style
)
3080 return style
& ~wxBORDER_MASK
;
3083 // Find the wxWindowMac at the current mouse position, returning the mouse
3085 wxWindowMac
* wxFindWindowAtPointer( wxPoint
& pt
)
3087 pt
= wxGetMousePosition();
3088 wxWindowMac
* found
= wxFindWindowAtPoint(pt
);
3093 // Get the current mouse position.
3094 wxPoint
wxGetMousePosition()
3098 wxGetMousePosition( &x
, &y
);
3100 return wxPoint(x
, y
);
3103 void wxWindowMac::OnMouseEvent( wxMouseEvent
&event
)
3105 if ( event
.GetEventType() == wxEVT_RIGHT_DOWN
)
3107 // copied from wxGTK : CS
3108 // VZ: shouldn't we move this to base class then?
3110 // generate a "context menu" event: this is similar to wxEVT_RIGHT_DOWN
3113 // (a) it's a command event and so is propagated to the parent
3114 // (b) under MSW it can be generated from kbd too
3115 // (c) it uses screen coords (because of (a))
3116 wxContextMenuEvent
evtCtx(wxEVT_CONTEXT_MENU
,
3118 this->ClientToScreen(event
.GetPosition()));
3119 evtCtx
.SetEventObject(this);
3120 if ( ! HandleWindowEvent(evtCtx
) )
3129 void wxWindowMac::OnPaint( wxPaintEvent
& WXUNUSED(event
) )
3131 if ( wxTheApp
->MacGetCurrentEvent() != NULL
&& wxTheApp
->MacGetCurrentEventHandlerCallRef() != NULL
3132 && GetBackgroundStyle() != wxBG_STYLE_TRANSPARENT
)
3133 CallNextEventHandler(
3134 (EventHandlerCallRef
)wxTheApp
->MacGetCurrentEventHandlerCallRef() ,
3135 (EventRef
) wxTheApp
->MacGetCurrentEvent() ) ;
3138 void wxWindowMac::MacHandleControlClick(WXWidget
WXUNUSED(control
),
3139 wxInt16
WXUNUSED(controlpart
),
3140 bool WXUNUSED(mouseStillDown
))
3144 Rect
wxMacGetBoundsForControl( wxWindow
* window
, const wxPoint
& pos
, const wxSize
&size
, bool adjustForOrigin
)
3148 window
->MacGetBoundsForControl( pos
, size
, x
, y
, w
, h
, adjustForOrigin
) ;
3149 Rect bounds
= { y
, x
, y
+ h
, x
+ w
};
3154 wxInt32
wxWindowMac::MacControlHit(WXEVENTHANDLERREF
WXUNUSED(handler
) , WXEVENTREF
WXUNUSED(event
) )
3156 return eventNotHandledErr
;
3159 bool wxWindowMac::Reparent(wxWindowBase
*newParentBase
)
3161 wxWindowMac
*newParent
= (wxWindowMac
*)newParentBase
;
3162 if ( !wxWindowBase::Reparent(newParent
) )
3165 // copied from MacPostControlCreate
3166 ControlRef container
= (ControlRef
) GetParent()->GetHandle() ;
3168 wxASSERT_MSG( container
!= NULL
, wxT("No valid mac container control") ) ;
3170 ::EmbedControl( m_peer
->GetControlRef() , container
) ;
3175 bool wxWindowMac::SetTransparent(wxByte alpha
)
3177 SetBackgroundStyle(wxBG_STYLE_TRANSPARENT
);
3179 if ( alpha
!= m_macAlpha
)
3181 m_macAlpha
= alpha
;
3188 bool wxWindowMac::CanSetTransparent()
3193 wxByte
wxWindowMac::GetTransparent() const
3198 bool wxWindowMac::IsShownOnScreen() const
3200 #if TARGET_API_MAC_OSX
3201 if ( m_peer
&& m_peer
->Ok() )
3202 return m_peer
->IsVisible();
3205 return wxWindowBase::IsShownOnScreen();