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 // we might have two native controls attributed to the same wxWindow instance
280 // eg a scrollview and an embedded textview, make sure we only fire for the 'outer'
281 // control, as otherwise native and wx visibility are different
282 if ( thisWindow
->GetPeer() != NULL
&& thisWindow
->GetPeer()->GetControlRef() == controlRef
)
284 thisWindow
->MacVisibilityChanged() ;
288 case kEventControlEnabledStateChanged
:
289 thisWindow
->MacEnabledStateChanged();
292 case kEventControlHiliteChanged
:
293 thisWindow
->MacHiliteChanged() ;
296 case kEventControlActivate
:
297 case kEventControlDeactivate
:
298 // FIXME: we should have a virtual function for this!
300 if ( thisWindow
->IsKindOf( CLASSINFO( wxTreeCtrl
) ) )
301 thisWindow
->Refresh();
304 if ( thisWindow
->IsKindOf( CLASSINFO( wxListCtrl
) ) )
305 thisWindow
->Refresh();
311 // different handling on OS X
314 case kEventControlFocusPartChanged
:
315 // the event is emulated by wxmac for systems lower than 10.5
317 ControlPartCode previousControlPart
= cEvent
.GetParameter
<ControlPartCode
>(kEventParamControlPreviousPart
, typeControlPartCode
);
318 ControlPartCode currentControlPart
= cEvent
.GetParameter
<ControlPartCode
>(kEventParamControlCurrentPart
, typeControlPartCode
);
320 if ( thisWindow
->MacGetTopLevelWindow() && thisWindow
->GetPeer()->NeedsFocusRect() )
322 thisWindow
->MacInvalidateBorders();
325 if ( currentControlPart
== 0 )
329 if ( thisWindow
->GetCaret() )
330 thisWindow
->GetCaret()->OnKillFocus();
333 wxLogTrace(_T("Focus"), _T("focus lost(%p)"), wx_static_cast(void*, thisWindow
));
335 // remove this as soon as posting the synthesized event works properly
336 static bool inKillFocusEvent
= false ;
338 if ( !inKillFocusEvent
)
340 inKillFocusEvent
= true ;
341 wxFocusEvent
event( wxEVT_KILL_FOCUS
, thisWindow
->GetId());
342 event
.SetEventObject(thisWindow
);
343 thisWindow
->HandleWindowEvent(event
) ;
344 inKillFocusEvent
= false ;
347 else if ( previousControlPart
== 0 )
350 // panel wants to track the window which was the last to have focus in it
351 wxLogTrace(_T("Focus"), _T("focus set(%p)"), wx_static_cast(void*, thisWindow
));
352 wxChildFocusEvent
eventFocus((wxWindow
*)thisWindow
);
353 thisWindow
->HandleWindowEvent(eventFocus
);
356 if ( thisWindow
->GetCaret() )
357 thisWindow
->GetCaret()->OnSetFocus();
360 wxFocusEvent
event(wxEVT_SET_FOCUS
, thisWindow
->GetId());
361 event
.SetEventObject(thisWindow
);
362 thisWindow
->HandleWindowEvent(event
) ;
366 case kEventControlSetFocusPart
:
369 Boolean focusEverything
= false ;
370 if ( cEvent
.GetParameter
<Boolean
>(kEventParamControlFocusEverything
, &focusEverything
) == noErr
)
372 // put a breakpoint here to catch focus everything events
375 ControlPartCode controlPart
= cEvent
.GetParameter
<ControlPartCode
>(kEventParamControlPart
, typeControlPartCode
);
377 ControlPartCode previousControlPart
= 0;
378 verify_noerr( HIViewGetFocusPart(controlRef
, &previousControlPart
));
380 if ( thisWindow
->MacIsUserPane() )
382 if ( controlPart
!= kControlFocusNoPart
)
383 cEvent
.SetParameter
<ControlPartCode
>( kEventParamControlPart
, typeControlPartCode
, 1 ) ;
387 result
= CallNextEventHandler(handler
, event
);
389 if ( UMAGetSystemVersion() < 0x1050 )
391 // set back to 0 if problems arise
393 ControlPartCode currentControlPart
= cEvent
.GetParameter
<ControlPartCode
>(kEventParamControlPart
, typeControlPartCode
);
394 // synthesize the event focus changed event
395 EventRef evRef
= NULL
;
397 OSStatus err
= MacCreateEvent(
398 NULL
, kEventClassControl
, kEventControlFocusPartChanged
, TicksToEventTime( TickCount() ) ,
399 kEventAttributeUserEvent
, &evRef
);
402 wxMacCarbonEvent
iEvent( evRef
) ;
403 iEvent
.SetParameter
<ControlRef
>( kEventParamDirectObject
, controlRef
) ;
404 iEvent
.SetParameter
<ControlPartCode
>( kEventParamControlPreviousPart
, typeControlPartCode
, previousControlPart
) ;
405 iEvent
.SetParameter
<ControlPartCode
>( kEventParamControlCurrentPart
, typeControlPartCode
, currentControlPart
) ;
408 // TODO test this first, avoid double posts etc...
409 PostEventToQueue( GetMainEventQueue(), evRef
, kEventPriorityHigh
);
411 wxMacWindowControlEventHandler( NULL
, evRef
, data
) ;
413 ReleaseEvent( evRef
) ;
415 // old implementation, to be removed if the new one works
416 if ( controlPart
== kControlFocusNoPart
)
419 if ( thisWindow
->GetCaret() )
420 thisWindow
->GetCaret()->OnKillFocus();
423 wxLogTrace(_T("Focus"), _T("focus lost(%p)"), wx_static_cast(void*, thisWindow
));
425 static bool inKillFocusEvent
= false ;
427 if ( !inKillFocusEvent
)
429 inKillFocusEvent
= true ;
430 wxFocusEvent
event( wxEVT_KILL_FOCUS
, thisWindow
->GetId());
431 event
.SetEventObject(thisWindow
);
432 thisWindow
->HandleWindowEvent(event
) ;
433 inKillFocusEvent
= false ;
438 // panel wants to track the window which was the last to have focus in it
439 wxLogTrace(_T("Focus"), _T("focus set(%p)"), wx_static_cast(void*, thisWindow
));
440 wxChildFocusEvent
eventFocus((wxWindow
*)thisWindow
);
441 thisWindow
->HandleWindowEvent(eventFocus
);
444 if ( thisWindow
->GetCaret() )
445 thisWindow
->GetCaret()->OnSetFocus();
448 wxFocusEvent
event(wxEVT_SET_FOCUS
, thisWindow
->GetId());
449 event
.SetEventObject(thisWindow
);
450 thisWindow
->HandleWindowEvent(event
) ;
457 case kEventControlHit
:
458 result
= thisWindow
->MacControlHit( handler
, event
) ;
461 case kEventControlGetClickActivation
:
463 // fix to always have a proper activation for DataBrowser controls (stay in bkgnd otherwise)
464 WindowRef owner
= cEvent
.GetParameter
<WindowRef
>(kEventParamWindowRef
);
465 if ( !IsWindowActive(owner
) )
467 cEvent
.SetParameter(kEventParamClickActivation
,(UInt32
) kActivateAndIgnoreClick
) ;
480 static pascal OSStatus
481 wxMacWindowServiceEventHandler(EventHandlerCallRef
WXUNUSED(handler
),
485 OSStatus result
= eventNotHandledErr
;
487 wxMacCarbonEvent
cEvent( event
) ;
489 ControlRef controlRef
;
490 wxWindowMac
* thisWindow
= (wxWindowMac
*) data
;
491 wxTextCtrl
* textCtrl
= wxDynamicCast( thisWindow
, wxTextCtrl
) ;
492 cEvent
.GetParameter( kEventParamDirectObject
, &controlRef
) ;
494 switch ( GetEventKind( event
) )
496 case kEventServiceGetTypes
:
500 textCtrl
->GetSelection( &from
, &to
) ;
502 CFMutableArrayRef copyTypes
= 0 , pasteTypes
= 0;
504 copyTypes
= cEvent
.GetParameter
< CFMutableArrayRef
>( kEventParamServiceCopyTypes
, typeCFMutableArrayRef
) ;
505 if ( textCtrl
->IsEditable() )
506 pasteTypes
= cEvent
.GetParameter
< CFMutableArrayRef
>( kEventParamServicePasteTypes
, typeCFMutableArrayRef
) ;
508 static const OSType textDataTypes
[] = { kTXNTextData
/* , 'utxt', 'PICT', 'MooV', 'AIFF' */ };
509 for ( size_t i
= 0 ; i
< WXSIZEOF(textDataTypes
) ; ++i
)
511 CFStringRef typestring
= CreateTypeStringWithOSType(textDataTypes
[i
]);
515 CFArrayAppendValue(copyTypes
, typestring
) ;
517 CFArrayAppendValue(pasteTypes
, typestring
) ;
519 CFRelease( typestring
) ;
527 case kEventServiceCopy
:
532 textCtrl
->GetSelection( &from
, &to
) ;
533 wxString val
= textCtrl
->GetValue() ;
534 val
= val
.Mid( from
, to
- from
) ;
535 PasteboardRef pasteboard
= cEvent
.GetParameter
<PasteboardRef
>( kEventParamPasteboardRef
, typePasteboardRef
);
536 verify_noerr( PasteboardClear( pasteboard
) ) ;
537 PasteboardSynchronize( pasteboard
);
538 // TODO add proper conversion
539 CFDataRef data
= CFDataCreate( kCFAllocatorDefault
, (const UInt8
*)val
.c_str(), val
.length() );
540 PasteboardPutItemFlavor( pasteboard
, (PasteboardItemID
) 1, CFSTR("com.apple.traditional-mac-plain-text"), data
, 0);
546 case kEventServicePaste
:
549 PasteboardRef pasteboard
= cEvent
.GetParameter
<PasteboardRef
>( kEventParamPasteboardRef
, typePasteboardRef
);
550 PasteboardSynchronize( pasteboard
);
552 verify_noerr( PasteboardGetItemCount( pasteboard
, &itemCount
) );
553 for( UInt32 itemIndex
= 1; itemIndex
<= itemCount
; itemIndex
++ )
555 PasteboardItemID itemID
;
556 if ( PasteboardGetItemIdentifier( pasteboard
, itemIndex
, &itemID
) == noErr
)
558 CFDataRef flavorData
= NULL
;
559 if ( PasteboardCopyItemFlavorData( pasteboard
, itemID
, CFSTR("com.apple.traditional-mac-plain-text"), &flavorData
) == noErr
)
561 CFIndex flavorDataSize
= CFDataGetLength( flavorData
);
562 char *content
= new char[flavorDataSize
+1] ;
563 memcpy( content
, CFDataGetBytePtr( flavorData
), flavorDataSize
);
564 content
[flavorDataSize
]=0;
565 CFRelease( flavorData
);
567 textCtrl
->WriteText( wxString( content
, wxConvLocal
) );
569 textCtrl
->WriteText( wxString( content
) ) ;
587 pascal OSStatus
wxMacUnicodeTextEventHandler( EventHandlerCallRef handler
, EventRef event
, void *data
)
589 OSStatus result
= eventNotHandledErr
;
590 wxWindowMac
* focus
= (wxWindowMac
*) data
;
592 wchar_t* uniChars
= NULL
;
593 UInt32 when
= EventTimeToTicks( GetEventTime( event
) ) ;
595 UniChar
* charBuf
= NULL
;
596 ByteCount dataSize
= 0 ;
599 if ( GetEventParameter( event
, kEventParamTextInputSendText
, typeUnicodeText
, NULL
, 0 , &dataSize
, NULL
) == noErr
)
601 numChars
= dataSize
/ sizeof( UniChar
) + 1;
604 if ( (size_t) numChars
* 2 > sizeof(buf
) )
605 charBuf
= new UniChar
[ numChars
] ;
609 uniChars
= new wchar_t[ numChars
] ;
610 GetEventParameter( event
, kEventParamTextInputSendText
, typeUnicodeText
, NULL
, dataSize
, NULL
, charBuf
) ;
611 charBuf
[ numChars
- 1 ] = 0;
612 #if SIZEOF_WCHAR_T == 2
613 uniChars
= (wchar_t*) charBuf
;
614 /* 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...)
616 // the resulting string will never have more chars than the utf16 version, so this is safe
617 wxMBConvUTF16 converter
;
618 numChars
= converter
.MB2WC( uniChars
, (const char*)charBuf
, numChars
) ;
622 switch ( GetEventKind( event
) )
624 case kEventTextInputUpdateActiveInputArea
:
626 // An IME input event may return several characters, but we need to send one char at a time to
628 for (int pos
=0 ; pos
< numChars
; pos
++)
630 WXEVENTREF formerEvent
= wxTheApp
->MacGetCurrentEvent() ;
631 WXEVENTHANDLERCALLREF formerHandler
= wxTheApp
->MacGetCurrentEventHandlerCallRef() ;
632 wxTheApp
->MacSetCurrentEvent( event
, handler
) ;
634 UInt32 message
= uniChars
[pos
] < 128 ? (char)uniChars
[pos
] : '?';
636 NB: faking a charcode here is problematic. The kEventTextInputUpdateActiveInputArea event is sent
637 multiple times to update the active range during inline input, so this handler will often receive
638 uncommited text, which should usually not trigger side effects. It might be a good idea to check the
639 kEventParamTextInputSendFixLen parameter and verify if input is being confirmed (see CarbonEvents.h).
640 On the other hand, it can be useful for some applications to react to uncommitted text (for example,
641 to update a status display), as long as it does not disrupt the inline input session. Ideally, wx
642 should add new event types to support advanced text input. For now, I would keep things as they are.
644 However, the code that was being used caused additional problems:
645 UInt32 message = (0 << 8) + ((char)uniChars[pos] );
646 Since it simply truncated the unichar to the last byte, it ended up causing weird bugs with inline
647 input, such as switching to another field when one attempted to insert the character U+4E09 (the kanji
648 for "three"), because it was truncated to 09 (kTabCharCode), which was later "converted" to WXK_TAB
649 (still 09) in wxMacTranslateKey; or triggering the default button when one attempted to insert U+840D
650 (the kanji for "name"), which got truncated to 0D and interpreted as a carriage return keypress.
651 Note that even single-byte characters could have been misinterpreted, since MacRoman charcodes only
652 overlap with Unicode within the (7-bit) ASCII range.
653 But simply passing a NUL charcode would disable text updated events, because wxTextCtrl::OnChar checks
654 for codes within a specific range. Therefore I went for the solution seen above, which keeps ASCII
655 characters as they are and replaces the rest with '?', ensuring that update events are triggered.
656 It would be better to change wxTextCtrl::OnChar to look at the actual unicode character instead, but
657 I don't have time to look into that right now.
660 if ( wxTheApp
->MacSendCharEvent(
661 focus
, message
, 0 , when
, 0 , 0 , uniChars
[pos
] ) )
666 wxTheApp
->MacSetCurrentEvent( formerEvent
, formerHandler
) ;
670 case kEventTextInputUnicodeForKeyEvent
:
672 UInt32 keyCode
, modifiers
;
675 unsigned char charCode
;
677 GetEventParameter( event
, kEventParamTextInputSendKeyboardEvent
, typeEventRef
, NULL
, sizeof(rawEvent
), NULL
, &rawEvent
) ;
678 GetEventParameter( rawEvent
, kEventParamKeyMacCharCodes
, typeChar
, NULL
, sizeof(char), NULL
, &charCode
);
679 GetEventParameter( rawEvent
, kEventParamKeyCode
, typeUInt32
, NULL
, sizeof(UInt32
), NULL
, &keyCode
);
680 GetEventParameter( rawEvent
, kEventParamKeyModifiers
, typeUInt32
, NULL
, sizeof(UInt32
), NULL
, &modifiers
);
681 GetEventParameter( rawEvent
, kEventParamMouseLocation
, typeQDPoint
, NULL
, sizeof(Point
), NULL
, &point
);
683 UInt32 message
= (keyCode
<< 8) + charCode
;
685 // An IME input event may return several characters, but we need to send one char at a time to
687 for (int pos
=0 ; pos
< numChars
; pos
++)
689 WXEVENTREF formerEvent
= wxTheApp
->MacGetCurrentEvent() ;
690 WXEVENTHANDLERCALLREF formerHandler
= wxTheApp
->MacGetCurrentEventHandlerCallRef() ;
691 wxTheApp
->MacSetCurrentEvent( event
, handler
) ;
693 if ( wxTheApp
->MacSendCharEvent(
694 focus
, message
, modifiers
, when
, point
.h
, point
.v
, uniChars
[pos
] ) )
699 wxTheApp
->MacSetCurrentEvent( formerEvent
, formerHandler
) ;
708 if ( charBuf
!= buf
)
714 static pascal OSStatus
715 wxMacWindowCommandEventHandler(EventHandlerCallRef
WXUNUSED(handler
),
719 OSStatus result
= eventNotHandledErr
;
720 wxWindowMac
* focus
= (wxWindowMac
*) data
;
724 wxMacCarbonEvent
cEvent( event
) ;
725 cEvent
.GetParameter
<HICommand
>(kEventParamDirectObject
,typeHICommand
,&command
) ;
727 wxMenuItem
* item
= NULL
;
728 wxMenu
* itemMenu
= wxFindMenuFromMacCommand( command
, item
) ;
729 int id
= wxMacCommandToId( command
.commandID
) ;
733 wxASSERT( itemMenu
!= NULL
) ;
735 switch ( cEvent
.GetKind() )
737 case kEventProcessCommand
:
738 result
= itemMenu
->MacHandleCommandProcess( item
, id
, focus
);
741 case kEventCommandUpdateStatus
:
742 result
= itemMenu
->MacHandleCommandUpdateStatus( item
, id
, focus
);
752 pascal OSStatus
wxMacWindowEventHandler( EventHandlerCallRef handler
, EventRef event
, void *data
)
754 EventRef formerEvent
= (EventRef
) wxTheApp
->MacGetCurrentEvent() ;
755 EventHandlerCallRef formerEventHandlerCallRef
= (EventHandlerCallRef
) wxTheApp
->MacGetCurrentEventHandlerCallRef() ;
756 wxTheApp
->MacSetCurrentEvent( event
, handler
) ;
757 OSStatus result
= eventNotHandledErr
;
759 switch ( GetEventClass( event
) )
761 case kEventClassCommand
:
762 result
= wxMacWindowCommandEventHandler( handler
, event
, data
) ;
765 case kEventClassControl
:
766 result
= wxMacWindowControlEventHandler( handler
, event
, data
) ;
769 case kEventClassService
:
770 result
= wxMacWindowServiceEventHandler( handler
, event
, data
) ;
773 case kEventClassTextInput
:
774 result
= wxMacUnicodeTextEventHandler( handler
, event
, data
) ;
781 wxTheApp
->MacSetCurrentEvent( formerEvent
, formerEventHandlerCallRef
) ;
786 DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacWindowEventHandler
)
788 // ---------------------------------------------------------------------------
789 // Scrollbar Tracking for all
790 // ---------------------------------------------------------------------------
792 pascal void wxMacLiveScrollbarActionProc( ControlRef control
, ControlPartCode partCode
) ;
793 pascal void wxMacLiveScrollbarActionProc( ControlRef control
, ControlPartCode partCode
)
797 wxWindow
* wx
= wxFindControlFromMacControl( control
) ;
799 wx
->MacHandleControlClick( (WXWidget
) control
, partCode
, true /* stillDown */ ) ;
802 wxMAC_DEFINE_PROC_GETTER( ControlActionUPP
, wxMacLiveScrollbarActionProc
) ;
804 // ===========================================================================
806 // ===========================================================================
808 WX_DECLARE_HASH_MAP(ControlRef
, wxWindow
*, wxPointerHash
, wxPointerEqual
, MacControlMap
);
810 static MacControlMap wxWinMacControlList
;
812 wxWindow
*wxFindControlFromMacControl(ControlRef inControl
)
814 MacControlMap::iterator node
= wxWinMacControlList
.find(inControl
);
816 return (node
== wxWinMacControlList
.end()) ? NULL
: node
->second
;
819 void wxAssociateControlWithMacControl(ControlRef inControl
, wxWindow
*control
)
821 // adding NULL ControlRef is (first) surely a result of an error and
822 // (secondly) breaks native event processing
823 wxCHECK_RET( inControl
!= (ControlRef
) NULL
, wxT("attempt to add a NULL WindowRef to window list") );
825 wxWinMacControlList
[inControl
] = control
;
828 void wxRemoveMacControlAssociation(wxWindow
*control
)
830 // iterate over all the elements in the class
831 // is the iterator stable ? as we might have two associations pointing to the same wxWindow
832 // we should go on...
838 MacControlMap::iterator it
;
839 for ( it
= wxWinMacControlList
.begin(); it
!= wxWinMacControlList
.end(); ++it
)
841 if ( it
->second
== control
)
843 wxWinMacControlList
.erase(it
);
851 // ----------------------------------------------------------------------------
852 // constructors and such
853 // ----------------------------------------------------------------------------
855 wxWindowMac::wxWindowMac()
860 wxWindowMac::wxWindowMac(wxWindowMac
*parent
,
865 const wxString
& name
)
868 Create(parent
, id
, pos
, size
, style
, name
);
871 void wxWindowMac::Init()
875 m_cgContextRef
= NULL
;
877 // as all windows are created with WS_VISIBLE style...
880 m_hScrollBar
= NULL
;
881 m_vScrollBar
= NULL
;
882 m_hScrollBarAlwaysShown
= false;
883 m_vScrollBarAlwaysShown
= false;
885 m_macIsUserPane
= true;
886 m_clipChildren
= false ;
887 m_cachedClippedRectValid
= false ;
890 wxWindowMac::~wxWindowMac()
894 m_isBeingDeleted
= true;
896 MacInvalidateBorders() ;
898 #ifndef __WXUNIVERSAL__
899 // VS: make sure there's no wxFrame with last focus set to us:
900 for ( wxWindow
*win
= GetParent(); win
; win
= win
->GetParent() )
902 wxFrame
*frame
= wxDynamicCast(win
, wxFrame
);
905 if ( frame
->GetLastFocus() == this )
906 frame
->SetLastFocus((wxWindow
*)NULL
);
912 // destroy children before destroying this window itself
915 // wxRemoveMacControlAssociation( this ) ;
916 // If we delete an item, we should initialize the parent panel,
917 // because it could now be invalid.
918 wxTopLevelWindow
*tlw
= wxDynamicCast(wxGetTopLevelParent(this), wxTopLevelWindow
);
921 if ( tlw
->GetDefaultItem() == (wxButton
*) this)
922 tlw
->SetDefaultItem(NULL
);
925 if ( m_peer
&& m_peer
->Ok() )
927 // in case the callback might be called during destruction
928 wxRemoveMacControlAssociation( this) ;
929 ::RemoveEventHandler( (EventHandlerRef
) m_macControlEventHandler
) ;
930 // we currently are not using this hook
931 // ::SetControlColorProc( *m_peer , NULL ) ;
935 if ( g_MacLastWindow
== this )
936 g_MacLastWindow
= NULL
;
938 #ifndef __WXUNIVERSAL__
939 wxFrame
* frame
= wxDynamicCast( wxGetTopLevelParent( (wxWindow
*)this ) , wxFrame
) ;
942 if ( frame
->GetLastFocus() == this )
943 frame
->SetLastFocus( NULL
) ;
947 // delete our drop target if we've got one
948 #if wxUSE_DRAG_AND_DROP
949 if ( m_dropTarget
!= NULL
)
959 WXWidget
wxWindowMac::GetHandle() const
961 return (WXWidget
) m_peer
->GetControlRef() ;
964 void wxWindowMac::MacInstallEventHandler( WXWidget control
)
966 wxAssociateControlWithMacControl( (ControlRef
) control
, this ) ;
967 InstallControlEventHandler( (ControlRef
)control
, GetwxMacWindowEventHandlerUPP(),
968 GetEventTypeCount(eventList
), eventList
, this,
969 (EventHandlerRef
*)&m_macControlEventHandler
);
973 bool wxWindowMac::Create(wxWindowMac
*parent
,
978 const wxString
& name
)
980 wxCHECK_MSG( parent
, false, wxT("can't create wxWindowMac without parent") );
982 if ( !CreateBase(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
) )
985 m_windowVariant
= parent
->GetWindowVariant() ;
987 if ( m_macIsUserPane
)
989 Rect bounds
= wxMacGetBoundsForControl( this , pos
, size
) ;
992 | kControlSupportsEmbedding
993 | kControlSupportsLiveFeedback
994 | kControlGetsFocusOnClick
995 // | kControlHasSpecialBackground
996 // | kControlSupportsCalcBestRect
997 | kControlHandlesTracking
998 | kControlSupportsFocus
999 | kControlWantsActivate
1000 | kControlWantsIdle
;
1002 m_peer
= new wxMacControl(this) ;
1003 OSStatus err
=::CreateUserPaneControl( MAC_WXHWND(GetParent()->MacGetTopLevelWindowRef()) , &bounds
, features
, m_peer
->GetControlRefAddr() );
1004 verify_noerr( err
);
1006 MacPostControlCreate(pos
, size
) ;
1009 #ifndef __WXUNIVERSAL__
1010 // Don't give scrollbars to wxControls unless they ask for them
1011 if ( (! IsKindOf(CLASSINFO(wxControl
)) && ! IsKindOf(CLASSINFO(wxStatusBar
)))
1012 || (IsKindOf(CLASSINFO(wxControl
)) && ((style
& wxHSCROLL
) || (style
& wxVSCROLL
))))
1014 MacCreateScrollBars( style
) ;
1018 wxWindowCreateEvent
event(this);
1019 GetEventHandler()->AddPendingEvent(event
);
1024 void wxWindowMac::MacChildAdded()
1027 m_vScrollBar
->Raise() ;
1029 m_hScrollBar
->Raise() ;
1032 void wxWindowMac::MacPostControlCreate(const wxPoint
& WXUNUSED(pos
), const wxSize
& size
)
1034 wxASSERT_MSG( m_peer
!= NULL
&& m_peer
->Ok() , wxT("No valid mac control") ) ;
1036 m_peer
->SetReference( (URefCon
) this ) ;
1037 GetParent()->AddChild( this );
1039 MacInstallEventHandler( (WXWidget
) m_peer
->GetControlRef() );
1041 ControlRef container
= (ControlRef
) GetParent()->GetHandle() ;
1042 wxASSERT_MSG( container
!= NULL
, wxT("No valid mac container control") ) ;
1043 ::EmbedControl( m_peer
->GetControlRef() , container
) ;
1044 GetParent()->MacChildAdded() ;
1046 // adjust font, controlsize etc
1047 DoSetWindowVariant( m_windowVariant
) ;
1049 m_peer
->SetLabel( wxStripMenuCodes(m_label
, wxStrip_Mnemonics
) ) ;
1051 if (!m_macIsUserPane
)
1052 SetInitialSize(size
);
1054 SetCursor( *wxSTANDARD_CURSOR
) ;
1057 void wxWindowMac::DoSetWindowVariant( wxWindowVariant variant
)
1059 // Don't assert, in case we set the window variant before
1060 // the window is created
1061 // wxASSERT( m_peer->Ok() ) ;
1063 m_windowVariant
= variant
;
1065 if (m_peer
== NULL
|| !m_peer
->Ok())
1069 ThemeFontID themeFont
= kThemeSystemFont
;
1071 // we will get that from the settings later
1072 // and make this NORMAL later, but first
1073 // we have a few calculations that we must fix
1077 case wxWINDOW_VARIANT_NORMAL
:
1078 size
= kControlSizeNormal
;
1079 themeFont
= kThemeSystemFont
;
1082 case wxWINDOW_VARIANT_SMALL
:
1083 size
= kControlSizeSmall
;
1084 themeFont
= kThemeSmallSystemFont
;
1087 case wxWINDOW_VARIANT_MINI
:
1088 // not always defined in the headers
1093 case wxWINDOW_VARIANT_LARGE
:
1094 size
= kControlSizeLarge
;
1095 themeFont
= kThemeSystemFont
;
1099 wxFAIL_MSG(_T("unexpected window variant"));
1103 m_peer
->SetData
<ControlSize
>(kControlEntireControl
, kControlSizeTag
, &size
) ;
1106 font
.MacCreateFromThemeFont( themeFont
) ;
1110 void wxWindowMac::MacUpdateControlFont()
1112 m_peer
->SetFont( GetFont() , GetForegroundColour() , GetWindowStyle() ) ;
1113 // do not trigger refreshes upon invisible and possible partly created objects
1114 if ( IsShownOnScreen() )
1118 bool wxWindowMac::SetFont(const wxFont
& font
)
1120 bool retval
= wxWindowBase::SetFont( font
);
1122 MacUpdateControlFont() ;
1127 bool wxWindowMac::SetForegroundColour(const wxColour
& col
)
1129 bool retval
= wxWindowBase::SetForegroundColour( col
);
1132 MacUpdateControlFont();
1137 bool wxWindowMac::SetBackgroundColour(const wxColour
& col
)
1139 if ( !wxWindowBase::SetBackgroundColour(col
) && m_hasBgCol
)
1142 m_peer
->SetBackgroundColour( col
) ;
1147 bool wxWindowMac::MacCanFocus() const
1149 // TODO : evaluate performance hits by looking up this value, eventually cache the results for a 1 sec or so
1150 // CAUTION : the value returned currently is 0 or 2, I've also found values of 1 having the same meaning,
1151 // but the value range is nowhere documented
1152 Boolean keyExistsAndHasValidFormat
;
1153 CFIndex fullKeyboardAccess
= CFPreferencesGetAppIntegerValue( CFSTR("AppleKeyboardUIMode" ) ,
1154 kCFPreferencesCurrentApplication
, &keyExistsAndHasValidFormat
);
1156 if ( keyExistsAndHasValidFormat
&& fullKeyboardAccess
> 0 )
1162 UInt32 features
= 0 ;
1163 m_peer
->GetFeatures( &features
) ;
1165 return features
& ( kControlSupportsFocus
| kControlGetsFocusOnClick
) ;
1169 void wxWindowMac::SetFocus()
1171 if ( !AcceptsFocus() )
1174 wxWindow
* former
= FindFocus() ;
1175 if ( former
== this )
1178 // as we cannot rely on the control features to find out whether we are in full keyboard mode,
1179 // we can only leave in case of an error
1180 OSStatus err
= m_peer
->SetFocus( kControlFocusNextPart
) ;
1181 if ( err
== errCouldntSetFocus
)
1184 SetUserFocusWindow( (WindowRef
)MacGetTopLevelWindowRef() );
1187 void wxWindowMac::DoCaptureMouse()
1189 wxApp::s_captureWindow
= this ;
1192 wxWindow
* wxWindowBase::GetCapture()
1194 return wxApp::s_captureWindow
;
1197 void wxWindowMac::DoReleaseMouse()
1199 wxApp::s_captureWindow
= NULL
;
1202 #if wxUSE_DRAG_AND_DROP
1204 void wxWindowMac::SetDropTarget(wxDropTarget
*pDropTarget
)
1206 if ( m_dropTarget
!= NULL
)
1207 delete m_dropTarget
;
1209 m_dropTarget
= pDropTarget
;
1210 if ( m_dropTarget
!= NULL
)
1218 // Old-style File Manager Drag & Drop
1219 void wxWindowMac::DragAcceptFiles(bool WXUNUSED(accept
))
1224 // Returns the size of the native control. In the case of the toplevel window
1225 // this is the content area root control
1227 void wxWindowMac::MacGetPositionAndSizeFromControl(int& WXUNUSED(x
),
1230 int& WXUNUSED(h
)) const
1232 wxFAIL_MSG( wxT("Not currently supported") ) ;
1235 // From a wx position / size calculate the appropriate size of the native control
1237 bool wxWindowMac::MacGetBoundsForControl(
1241 int& w
, int& h
, bool adjustOrigin
) const
1243 // the desired size, minus the border pixels gives the correct size of the control
1247 // TODO: the default calls may be used as soon as PostCreateControl Is moved here
1248 w
= wxMax(size
.x
, 0) ; // WidthDefault( size.x );
1249 h
= wxMax(size
.y
, 0) ; // HeightDefault( size.y ) ;
1251 x
+= MacGetLeftBorderSize() ;
1252 y
+= MacGetTopBorderSize() ;
1253 w
-= MacGetLeftBorderSize() + MacGetRightBorderSize() ;
1254 h
-= MacGetTopBorderSize() + MacGetBottomBorderSize() ;
1257 AdjustForParentClientOrigin( x
, y
) ;
1259 // this is in window relative coordinate, as this parent may have a border, its physical position is offset by this border
1260 if ( !GetParent()->IsTopLevel() )
1262 x
-= GetParent()->MacGetLeftBorderSize() ;
1263 y
-= GetParent()->MacGetTopBorderSize() ;
1269 // Get window size (not client size)
1270 void wxWindowMac::DoGetSize(int *x
, int *y
) const
1273 m_peer
->GetRect( &bounds
) ;
1276 *x
= bounds
.right
- bounds
.left
+ MacGetLeftBorderSize() + MacGetRightBorderSize() ;
1278 *y
= bounds
.bottom
- bounds
.top
+ MacGetTopBorderSize() + MacGetBottomBorderSize() ;
1281 // get the position of the bounds of this window in client coordinates of its parent
1282 void wxWindowMac::DoGetPosition(int *x
, int *y
) const
1285 m_peer
->GetRect( &bounds
) ;
1287 int x1
= bounds
.left
;
1288 int y1
= bounds
.top
;
1290 // get the wx window position from the native one
1291 x1
-= MacGetLeftBorderSize() ;
1292 y1
-= MacGetTopBorderSize() ;
1294 if ( !IsTopLevel() )
1296 wxWindow
*parent
= GetParent();
1299 // we must first adjust it to be in window coordinates of the parent,
1300 // as otherwise it gets lost by the ClientAreaOrigin fix
1301 x1
+= parent
->MacGetLeftBorderSize() ;
1302 y1
+= parent
->MacGetTopBorderSize() ;
1304 // and now to client coordinates
1305 wxPoint
pt(parent
->GetClientAreaOrigin());
1317 void wxWindowMac::DoScreenToClient(int *x
, int *y
) const
1319 WindowRef window
= (WindowRef
) MacGetTopLevelWindowRef() ;
1320 wxCHECK_RET( window
, wxT("TopLevel Window missing") ) ;
1322 Point localwhere
= { 0, 0 } ;
1329 wxMacGlobalToLocal( window
, &localwhere
) ;
1336 MacRootWindowToWindow( x
, y
) ;
1338 wxPoint origin
= GetClientAreaOrigin() ;
1345 void wxWindowMac::DoClientToScreen(int *x
, int *y
) const
1347 WindowRef window
= (WindowRef
) MacGetTopLevelWindowRef() ;
1348 wxCHECK_RET( window
, wxT("TopLevel window missing") ) ;
1350 wxPoint origin
= GetClientAreaOrigin() ;
1356 MacWindowToRootWindow( x
, y
) ;
1358 Point localwhere
= { 0, 0 };
1364 wxMacLocalToGlobal( window
, &localwhere
) ;
1372 void wxWindowMac::MacClientToRootWindow( int *x
, int *y
) const
1374 wxPoint origin
= GetClientAreaOrigin() ;
1380 MacWindowToRootWindow( x
, y
) ;
1383 void wxWindowMac::MacRootWindowToClient( int *x
, int *y
) const
1385 MacRootWindowToWindow( x
, y
) ;
1387 wxPoint origin
= GetClientAreaOrigin() ;
1394 void wxWindowMac::MacWindowToRootWindow( int *x
, int *y
) const
1403 if ( !IsTopLevel() )
1405 wxTopLevelWindowMac
* top
= MacGetTopLevelWindow();
1408 pt
.x
-= MacGetLeftBorderSize() ;
1409 pt
.y
-= MacGetTopBorderSize() ;
1410 wxMacControl::Convert( &pt
, m_peer
, top
->m_peer
) ;
1420 void wxWindowMac::MacWindowToRootWindow( short *x
, short *y
) const
1429 MacWindowToRootWindow( &x1
, &y1
) ;
1437 void wxWindowMac::MacRootWindowToWindow( int *x
, int *y
) const
1446 if ( !IsTopLevel() )
1448 wxTopLevelWindowMac
* top
= MacGetTopLevelWindow();
1451 wxMacControl::Convert( &pt
, top
->m_peer
, m_peer
) ;
1452 pt
.x
+= MacGetLeftBorderSize() ;
1453 pt
.y
+= MacGetTopBorderSize() ;
1463 void wxWindowMac::MacRootWindowToWindow( short *x
, short *y
) const
1472 MacRootWindowToWindow( &x1
, &y1
) ;
1480 void wxWindowMac::MacGetContentAreaInset( int &left
, int &top
, int &right
, int &bottom
)
1482 RgnHandle rgn
= NewRgn() ;
1484 if ( m_peer
->GetRegion( kControlContentMetaPart
, rgn
) == noErr
)
1486 Rect structure
, content
;
1488 GetRegionBounds( rgn
, &content
) ;
1489 m_peer
->GetRect( &structure
) ;
1490 OffsetRect( &structure
, -structure
.left
, -structure
.top
) ;
1492 left
= content
.left
- structure
.left
;
1493 top
= content
.top
- structure
.top
;
1494 right
= structure
.right
- content
.right
;
1495 bottom
= structure
.bottom
- content
.bottom
;
1499 left
= top
= right
= bottom
= 0 ;
1505 wxSize
wxWindowMac::DoGetSizeFromClientSize( const wxSize
& size
) const
1507 wxSize sizeTotal
= size
;
1509 RgnHandle rgn
= NewRgn() ;
1510 if ( m_peer
->GetRegion( kControlContentMetaPart
, rgn
) == noErr
)
1512 Rect content
, structure
;
1513 GetRegionBounds( rgn
, &content
) ;
1514 m_peer
->GetRect( &structure
) ;
1516 // structure is in parent coordinates, but we only need width and height, so it's ok
1518 sizeTotal
.x
+= (structure
.right
- structure
.left
) - (content
.right
- content
.left
) ;
1519 sizeTotal
.y
+= (structure
.bottom
- structure
.top
) - (content
.bottom
- content
.top
) ;
1524 sizeTotal
.x
+= MacGetLeftBorderSize() + MacGetRightBorderSize() ;
1525 sizeTotal
.y
+= MacGetTopBorderSize() + MacGetBottomBorderSize() ;
1530 // Get size *available for subwindows* i.e. excluding menu bar etc.
1531 void wxWindowMac::DoGetClientSize( int *x
, int *y
) const
1535 RgnHandle rgn
= NewRgn() ;
1537 if ( m_peer
->GetRegion( kControlContentMetaPart
, rgn
) == noErr
)
1538 GetRegionBounds( rgn
, &content
) ;
1540 m_peer
->GetRect( &content
) ;
1543 ww
= content
.right
- content
.left
;
1544 hh
= content
.bottom
- content
.top
;
1546 if (m_hScrollBar
&& m_hScrollBar
->IsShown() )
1547 hh
-= m_hScrollBar
->GetSize().y
;
1549 if (m_vScrollBar
&& m_vScrollBar
->IsShown() )
1550 ww
-= m_vScrollBar
->GetSize().x
;
1558 bool wxWindowMac::SetCursor(const wxCursor
& cursor
)
1560 if (m_cursor
.IsSameAs(cursor
))
1565 if ( ! wxWindowBase::SetCursor( *wxSTANDARD_CURSOR
) )
1570 if ( ! wxWindowBase::SetCursor( cursor
) )
1574 wxASSERT_MSG( m_cursor
.Ok(),
1575 wxT("cursor must be valid after call to the base version"));
1577 wxWindowMac
*mouseWin
= 0 ;
1579 wxTopLevelWindowMac
*tlw
= MacGetTopLevelWindow() ;
1580 WindowRef window
= (WindowRef
) ( tlw
? tlw
->MacGetWindowRef() : 0 ) ;
1582 ControlPartCode part
;
1583 ControlRef control
;
1585 #if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
1587 HIGetMousePosition(kHICoordSpaceWindow
, window
, &hiPoint
);
1591 GetGlobalMouse( &pt
);
1594 ScreenToClient(&x
, &y
);
1598 control
= FindControlUnderMouse( pt
, window
, &part
) ;
1600 mouseWin
= wxFindControlFromMacControl( control
) ;
1604 if ( mouseWin
== this && !wxIsBusy() )
1605 m_cursor
.MacInstall() ;
1611 bool wxWindowMac::DoPopupMenu(wxMenu
*menu
, int x
, int y
)
1613 #ifndef __WXUNIVERSAL__
1614 menu
->SetInvokingWindow((wxWindow
*)this);
1617 if ( x
== wxDefaultCoord
&& y
== wxDefaultCoord
)
1619 wxPoint mouse
= wxGetMousePosition();
1625 ClientToScreen( &x
, &y
) ;
1628 menu
->MacBeforeDisplay( true ) ;
1629 long menuResult
= ::PopUpMenuSelect((MenuHandle
) menu
->GetHMenu() , y
, x
, 0) ;
1630 if ( HiWord(menuResult
) != 0 )
1633 GetMenuItemCommandID( GetMenuHandle(HiWord(menuResult
)) , LoWord(menuResult
) , &macid
);
1634 int id
= wxMacCommandToId( macid
);
1635 wxMenuItem
* item
= NULL
;
1637 item
= menu
->FindItem( id
, &realmenu
) ;
1640 if (item
->IsCheckable())
1641 item
->Check( !item
->IsChecked() ) ;
1643 menu
->SendEvent( id
, item
->IsCheckable() ? item
->IsChecked() : -1 ) ;
1647 menu
->MacAfterDisplay( true ) ;
1648 menu
->SetInvokingWindow( NULL
);
1652 // actually this shouldn't be called, because universal is having its own implementation
1658 // ----------------------------------------------------------------------------
1660 // ----------------------------------------------------------------------------
1664 void wxWindowMac::DoSetToolTip(wxToolTip
*tooltip
)
1666 wxWindowBase::DoSetToolTip(tooltip
);
1669 m_tooltip
->SetWindow(this);
1674 void wxWindowMac::MacInvalidateBorders()
1676 if ( m_peer
== NULL
)
1679 bool vis
= IsShownOnScreen() ;
1683 int outerBorder
= MacGetLeftBorderSize() ;
1684 if ( m_peer
->NeedsFocusRect() /* && m_peer->HasFocus() */ )
1687 if ( outerBorder
== 0 )
1690 // now we know that we have something to do at all
1692 // as the borders are drawn on the parent we have to properly invalidate all these areas
1693 RgnHandle updateInner
, updateOuter
;
1696 // this rectangle is in HIViewCoordinates under OSX and in Window Coordinates under Carbon
1697 updateInner
= NewRgn() ;
1698 updateOuter
= NewRgn() ;
1700 m_peer
->GetRect( &rect
) ;
1701 RectRgn( updateInner
, &rect
) ;
1702 InsetRect( &rect
, -outerBorder
, -outerBorder
) ;
1703 RectRgn( updateOuter
, &rect
) ;
1704 DiffRgn( updateOuter
, updateInner
, updateOuter
) ;
1706 GetParent()->m_peer
->SetNeedsDisplay( updateOuter
) ;
1708 DisposeRgn( updateOuter
) ;
1709 DisposeRgn( updateInner
) ;
1712 void wxWindowMac::DoMoveWindow(int x
, int y
, int width
, int height
)
1714 // this is never called for a toplevel window, so we know we have a parent
1715 int former_x
, former_y
, former_w
, former_h
;
1717 // Get true coordinates of former position
1718 DoGetPosition( &former_x
, &former_y
) ;
1719 DoGetSize( &former_w
, &former_h
) ;
1721 wxWindow
*parent
= GetParent();
1724 wxPoint
pt(parent
->GetClientAreaOrigin());
1729 int actualWidth
= width
;
1730 int actualHeight
= height
;
1734 if ((m_minWidth
!= -1) && (actualWidth
< m_minWidth
))
1735 actualWidth
= m_minWidth
;
1736 if ((m_minHeight
!= -1) && (actualHeight
< m_minHeight
))
1737 actualHeight
= m_minHeight
;
1738 if ((m_maxWidth
!= -1) && (actualWidth
> m_maxWidth
))
1739 actualWidth
= m_maxWidth
;
1740 if ((m_maxHeight
!= -1) && (actualHeight
> m_maxHeight
))
1741 actualHeight
= m_maxHeight
;
1743 bool doMove
= false, doResize
= false ;
1745 if ( actualX
!= former_x
|| actualY
!= former_y
)
1748 if ( actualWidth
!= former_w
|| actualHeight
!= former_h
)
1751 if ( doMove
|| doResize
)
1753 // as the borders are drawn outside the native control, we adjust now
1755 wxRect
bounds( wxPoint( actualX
+ MacGetLeftBorderSize() ,actualY
+ MacGetTopBorderSize() ),
1756 wxSize( actualWidth
- (MacGetLeftBorderSize() + MacGetRightBorderSize()) ,
1757 actualHeight
- (MacGetTopBorderSize() + MacGetBottomBorderSize()) ) ) ;
1760 wxMacRectToNative( &bounds
, &r
) ;
1762 if ( !GetParent()->IsTopLevel() )
1763 wxMacWindowToNative( GetParent() , &r
) ;
1765 MacInvalidateBorders() ;
1767 m_cachedClippedRectValid
= false ;
1768 m_peer
->SetRect( &r
) ;
1770 wxWindowMac::MacSuperChangedPosition() ; // like this only children will be notified
1772 MacInvalidateBorders() ;
1774 MacRepositionScrollBars() ;
1777 wxPoint
point(actualX
, actualY
);
1778 wxMoveEvent
event(point
, m_windowId
);
1779 event
.SetEventObject(this);
1780 HandleWindowEvent(event
) ;
1785 MacRepositionScrollBars() ;
1786 wxSize
size(actualWidth
, actualHeight
);
1787 wxSizeEvent
event(size
, m_windowId
);
1788 event
.SetEventObject(this);
1789 HandleWindowEvent(event
);
1794 wxSize
wxWindowMac::DoGetBestSize() const
1796 if ( m_macIsUserPane
|| IsTopLevel() )
1797 return wxWindowBase::DoGetBestSize() ;
1799 Rect bestsize
= { 0 , 0 , 0 , 0 } ;
1800 int bestWidth
, bestHeight
;
1802 m_peer
->GetBestRect( &bestsize
) ;
1803 if ( EmptyRect( &bestsize
) )
1808 bestsize
.bottom
= 16 ;
1810 if ( IsKindOf( CLASSINFO( wxScrollBar
) ) )
1812 bestsize
.bottom
= 16 ;
1815 else if ( IsKindOf( CLASSINFO( wxSpinButton
) ) )
1817 bestsize
.bottom
= 24 ;
1822 // return wxWindowBase::DoGetBestSize() ;
1826 bestWidth
= bestsize
.right
- bestsize
.left
;
1827 bestHeight
= bestsize
.bottom
- bestsize
.top
;
1828 if ( bestHeight
< 10 )
1831 return wxSize(bestWidth
, bestHeight
);
1834 // set the size of the window: if the dimensions are positive, just use them,
1835 // but if any of them is equal to -1, it means that we must find the value for
1836 // it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in
1837 // which case -1 is a valid value for x and y)
1839 // If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate
1840 // the width/height to best suit our contents, otherwise we reuse the current
1842 void wxWindowMac::DoSetSize(int x
, int y
, int width
, int height
, int sizeFlags
)
1844 // get the current size and position...
1845 int currentX
, currentY
;
1846 int currentW
, currentH
;
1848 GetPosition(¤tX
, ¤tY
);
1849 GetSize(¤tW
, ¤tH
);
1851 // ... and don't do anything (avoiding flicker) if it's already ok
1852 if ( x
== currentX
&& y
== currentY
&&
1853 width
== currentW
&& height
== currentH
&& ( height
!= -1 && width
!= -1 ) )
1856 MacRepositionScrollBars() ; // we might have a real position shift
1861 if ( !(sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) )
1863 if ( x
== wxDefaultCoord
)
1865 if ( y
== wxDefaultCoord
)
1869 AdjustForParentClientOrigin( x
, y
, sizeFlags
);
1871 wxSize size
= wxDefaultSize
;
1872 if ( width
== wxDefaultCoord
)
1874 if ( sizeFlags
& wxSIZE_AUTO_WIDTH
)
1876 size
= DoGetBestSize();
1881 // just take the current one
1886 if ( height
== wxDefaultCoord
)
1888 if ( sizeFlags
& wxSIZE_AUTO_HEIGHT
)
1890 if ( size
.x
== wxDefaultCoord
)
1891 size
= DoGetBestSize();
1892 // else: already called DoGetBestSize() above
1898 // just take the current one
1903 DoMoveWindow( x
, y
, width
, height
);
1906 wxPoint
wxWindowMac::GetClientAreaOrigin() const
1908 RgnHandle rgn
= NewRgn() ;
1910 if ( m_peer
->GetRegion( kControlContentMetaPart
, rgn
) == noErr
)
1912 GetRegionBounds( rgn
, &content
) ;
1922 return wxPoint( content
.left
+ MacGetLeftBorderSize() , content
.top
+ MacGetTopBorderSize() );
1925 void wxWindowMac::DoSetClientSize(int clientwidth
, int clientheight
)
1927 if ( clientwidth
!= wxDefaultCoord
|| clientheight
!= wxDefaultCoord
)
1929 int currentclientwidth
, currentclientheight
;
1930 int currentwidth
, currentheight
;
1932 GetClientSize( ¤tclientwidth
, ¤tclientheight
) ;
1933 GetSize( ¤twidth
, ¤theight
) ;
1935 DoSetSize( wxDefaultCoord
, wxDefaultCoord
, currentwidth
+ clientwidth
- currentclientwidth
,
1936 currentheight
+ clientheight
- currentclientheight
, wxSIZE_USE_EXISTING
) ;
1940 void wxWindowMac::SetLabel(const wxString
& title
)
1944 if ( m_peer
&& m_peer
->Ok() )
1945 m_peer
->SetLabel( wxStripMenuCodes(m_label
, wxStrip_Mnemonics
) ) ;
1947 // do not trigger refreshes upon invisible and possible partly created objects
1948 if ( IsShownOnScreen() )
1952 wxString
wxWindowMac::GetLabel() const
1957 bool wxWindowMac::Show(bool show
)
1959 if ( !wxWindowBase::Show(show
) )
1963 m_peer
->SetVisibility( show
, true ) ;
1968 void wxWindowMac::DoEnable(bool enable
)
1970 m_peer
->Enable( enable
) ;
1974 // status change notifications
1977 void wxWindowMac::MacVisibilityChanged()
1981 void wxWindowMac::MacHiliteChanged()
1985 void wxWindowMac::MacEnabledStateChanged()
1987 OnEnabled( m_peer
->IsEnabled() );
1991 // status queries on the inherited window's state
1994 bool wxWindowMac::MacIsReallyEnabled()
1996 return m_peer
->IsEnabled() ;
1999 bool wxWindowMac::MacIsReallyHilited()
2001 return m_peer
->IsActive();
2004 void wxWindowMac::MacFlashInvalidAreas()
2006 #if TARGET_API_MAC_OSX
2007 HIViewFlashDirtyArea( (WindowRef
) MacGetTopLevelWindowRef() ) ;
2011 int wxWindowMac::GetCharHeight() const
2013 wxClientDC
dc( (wxWindowMac
*)this ) ;
2015 return dc
.GetCharHeight() ;
2018 int wxWindowMac::GetCharWidth() const
2020 wxClientDC
dc( (wxWindowMac
*)this ) ;
2022 return dc
.GetCharWidth() ;
2025 void wxWindowMac::GetTextExtent(const wxString
& string
, int *x
, int *y
,
2026 int *descent
, int *externalLeading
, const wxFont
*theFont
) const
2028 const wxFont
*fontToUse
= theFont
;
2030 fontToUse
= &m_font
;
2032 wxClientDC
dc( (wxWindowMac
*) this ) ;
2033 wxCoord lx
,ly
,ld
,le
;
2034 dc
.GetTextExtent( string
, &lx
, &ly
, &ld
, &le
, (wxFont
*)fontToUse
) ;
2035 if ( externalLeading
)
2036 *externalLeading
= le
;
2046 * Rect is given in client coordinates, for further reading, read wxTopLevelWindowMac::InvalidateRect
2047 * we always intersect with the entire window, not only with the client area
2050 void wxWindowMac::Refresh(bool WXUNUSED(eraseBack
), const wxRect
*rect
)
2052 if ( m_peer
== NULL
)
2055 if ( !IsShownOnScreen() )
2062 wxMacRectToNative( rect
, &r
) ;
2063 m_peer
->SetNeedsDisplay( &r
) ;
2067 m_peer
->SetNeedsDisplay() ;
2071 void wxWindowMac::DoFreeze()
2073 #if TARGET_API_MAC_OSX
2074 if ( m_peer
&& m_peer
->Ok() )
2075 m_peer
->SetDrawingEnabled( false ) ;
2079 void wxWindowMac::DoThaw()
2081 #if TARGET_API_MAC_OSX
2082 if ( m_peer
&& m_peer
->Ok() )
2084 m_peer
->SetDrawingEnabled( true ) ;
2085 m_peer
->InvalidateWithChildren() ;
2090 wxWindowMac
*wxGetActiveWindow()
2092 // actually this is a windows-only concept
2096 // Coordinates relative to the window
2097 void wxWindowMac::WarpPointer(int WXUNUSED(x_pos
), int WXUNUSED(y_pos
))
2099 // We really don't move the mouse programmatically under Mac.
2102 void wxWindowMac::OnEraseBackground(wxEraseEvent
& event
)
2104 if ( MacGetTopLevelWindow() == NULL
)
2107 #if TARGET_API_MAC_OSX
2108 if ( !m_backgroundColour.Ok() || GetBackgroundStyle() == wxBG_STYLE_TRANSPARENT )
2114 if ( GetBackgroundStyle() == wxBG_STYLE_COLOUR
)
2116 event
.GetDC()->Clear() ;
2124 void wxWindowMac::OnNcPaint( wxNcPaintEvent
& event
)
2129 int wxWindowMac::GetScrollPos(int orient
) const
2131 if ( orient
== wxHORIZONTAL
)
2134 return m_hScrollBar
->GetThumbPosition() ;
2139 return m_vScrollBar
->GetThumbPosition() ;
2145 // This now returns the whole range, not just the number
2146 // of positions that we can scroll.
2147 int wxWindowMac::GetScrollRange(int orient
) const
2149 if ( orient
== wxHORIZONTAL
)
2152 return m_hScrollBar
->GetRange() ;
2157 return m_vScrollBar
->GetRange() ;
2163 int wxWindowMac::GetScrollThumb(int orient
) const
2165 if ( orient
== wxHORIZONTAL
)
2168 return m_hScrollBar
->GetThumbSize() ;
2173 return m_vScrollBar
->GetThumbSize() ;
2179 void wxWindowMac::SetScrollPos(int orient
, int pos
, bool WXUNUSED(refresh
))
2181 if ( orient
== wxHORIZONTAL
)
2184 m_hScrollBar
->SetThumbPosition( pos
) ;
2189 m_vScrollBar
->SetThumbPosition( pos
) ;
2194 wxWindowMac::AlwaysShowScrollbars(bool hflag
, bool vflag
)
2196 bool needVisibilityUpdate
= false;
2198 if ( m_hScrollBarAlwaysShown
!= hflag
)
2200 m_hScrollBarAlwaysShown
= hflag
;
2201 needVisibilityUpdate
= true;
2204 if ( m_vScrollBarAlwaysShown
!= vflag
)
2206 m_vScrollBarAlwaysShown
= vflag
;
2207 needVisibilityUpdate
= true;
2210 if ( needVisibilityUpdate
)
2211 DoUpdateScrollbarVisibility();
2215 // we draw borders and grow boxes, are already set up and clipped in the current port / cgContextRef
2216 // our own window origin is at leftOrigin/rightOrigin
2219 void wxWindowMac::MacPaintGrowBox()
2224 if ( MacHasScrollBarCorner() )
2228 CGContextRef cgContext
= (CGContextRef
) MacGetCGContextRef() ;
2229 wxASSERT( cgContext
) ;
2231 m_peer
->GetRect( &rect
) ;
2233 int size
= m_hScrollBar
? m_hScrollBar
->GetSize().y
: ( m_vScrollBar
? m_vScrollBar
->GetSize().x
: MAC_SCROLLBAR_SIZE
) ;
2234 CGRect cgrect
= CGRectMake( rect
.right
- size
, rect
.bottom
- size
, size
, size
) ;
2235 CGPoint cgpoint
= CGPointMake( rect
.right
- size
, rect
.bottom
- size
) ;
2236 CGContextSaveGState( cgContext
);
2238 if ( m_backgroundColour
.Ok() )
2240 CGContextSetFillColorWithColor( cgContext
, m_backgroundColour
.GetCGColor() );
2244 CGContextSetRGBFillColor( cgContext
, 1.0, 1.0 , 1.0 , 1.0 );
2246 CGContextFillRect( cgContext
, cgrect
);
2247 CGContextRestoreGState( cgContext
);
2251 void wxWindowMac::MacPaintBorders( int WXUNUSED(leftOrigin
) , int WXUNUSED(rightOrigin
) )
2257 bool hasFocus
= m_peer
->NeedsFocusRect() && m_peer
->HasFocus() ;
2259 // back to the surrounding frame rectangle
2260 m_peer
->GetRect( &rect
) ;
2261 InsetRect( &rect
, -1 , -1 ) ;
2264 CGRect cgrect
= CGRectMake( rect
.left
, rect
.top
, rect
.right
- rect
.left
,
2265 rect
.bottom
- rect
.top
) ;
2267 HIThemeFrameDrawInfo info
;
2268 memset( &info
, 0 , sizeof(info
) ) ;
2272 info
.state
= IsEnabled() ? kThemeStateActive
: kThemeStateInactive
;
2273 info
.isFocused
= hasFocus
;
2275 CGContextRef cgContext
= (CGContextRef
) GetParent()->MacGetCGContextRef() ;
2276 wxASSERT( cgContext
) ;
2278 if ( HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
) || HasFlag(wxDOUBLE_BORDER
) )
2280 info
.kind
= kHIThemeFrameTextFieldSquare
;
2281 HIThemeDrawFrame( &cgrect
, &info
, cgContext
, kHIThemeOrientationNormal
) ;
2283 else if ( HasFlag(wxSIMPLE_BORDER
) )
2285 info
.kind
= kHIThemeFrameListBox
;
2286 HIThemeDrawFrame( &cgrect
, &info
, cgContext
, kHIThemeOrientationNormal
) ;
2288 else if ( hasFocus
)
2290 HIThemeDrawFocusRect( &cgrect
, true , cgContext
, kHIThemeOrientationNormal
) ;
2292 #if 0 // TODO REMOVE now done in a separate call earlier in drawing the window itself
2293 m_peer
->GetRect( &rect
) ;
2294 if ( MacHasScrollBarCorner() )
2296 int variant
= (m_hScrollBar
== NULL
? m_vScrollBar
: m_hScrollBar
) ->GetWindowVariant();
2297 int size
= m_hScrollBar
? m_hScrollBar
->GetSize().y
: ( m_vScrollBar
? m_vScrollBar
->GetSize().x
: MAC_SCROLLBAR_SIZE
) ;
2298 CGRect cgrect
= CGRectMake( rect
.right
- size
, rect
.bottom
- size
, size
, size
) ;
2299 CGPoint cgpoint
= CGPointMake( rect
.right
- size
, rect
.bottom
- size
) ;
2300 HIThemeGrowBoxDrawInfo info
;
2301 memset( &info
, 0, sizeof(info
) ) ;
2303 info
.state
= IsEnabled() ? kThemeStateActive
: kThemeStateInactive
;
2304 info
.kind
= kHIThemeGrowBoxKindNone
;
2305 // contrary to the docs ...SizeSmall does not work
2306 info
.size
= kHIThemeGrowBoxSizeNormal
;
2307 info
.direction
= 0 ;
2308 HIThemeDrawGrowBox( &cgpoint
, &info
, cgContext
, kHIThemeOrientationNormal
) ;
2314 void wxWindowMac::RemoveChild( wxWindowBase
*child
)
2316 if ( child
== m_hScrollBar
)
2317 m_hScrollBar
= NULL
;
2318 if ( child
== m_vScrollBar
)
2319 m_vScrollBar
= NULL
;
2321 wxWindowBase::RemoveChild( child
) ;
2324 void wxWindowMac::DoUpdateScrollbarVisibility()
2326 bool triggerSizeEvent
= false;
2330 bool showHScrollBar
= m_hScrollBarAlwaysShown
|| m_hScrollBar
->IsNeeded();
2332 if ( m_hScrollBar
->IsShown() != showHScrollBar
)
2334 m_hScrollBar
->Show( showHScrollBar
);
2335 triggerSizeEvent
= true;
2341 bool showVScrollBar
= m_vScrollBarAlwaysShown
|| m_vScrollBar
->IsNeeded();
2343 if ( m_vScrollBar
->IsShown() != showVScrollBar
)
2345 m_vScrollBar
->Show( showVScrollBar
) ;
2346 triggerSizeEvent
= true;
2350 MacRepositionScrollBars() ;
2351 if ( triggerSizeEvent
)
2353 wxSizeEvent
event(GetSize(), m_windowId
);
2354 event
.SetEventObject(this);
2355 HandleWindowEvent(event
);
2359 // New function that will replace some of the above.
2360 void wxWindowMac::SetScrollbar(int orient
, int pos
, int thumb
,
2361 int range
, bool refresh
)
2363 if ( orient
== wxHORIZONTAL
&& m_hScrollBar
)
2364 m_hScrollBar
->SetScrollbar(pos
, thumb
, range
, thumb
, refresh
);
2365 else if ( orient
== wxVERTICAL
&& m_vScrollBar
)
2366 m_vScrollBar
->SetScrollbar(pos
, thumb
, range
, thumb
, refresh
);
2368 DoUpdateScrollbarVisibility();
2371 // Does a physical scroll
2372 void wxWindowMac::ScrollWindow(int dx
, int dy
, const wxRect
*rect
)
2374 if ( dx
== 0 && dy
== 0 )
2377 int width
, height
;
2378 GetClientSize( &width
, &height
) ;
2381 // note there currently is a bug in OSX which makes inefficient refreshes in case an entire control
2382 // area is scrolled, this does not occur if width and height are 2 pixels less,
2383 // TODO: write optimal workaround
2384 wxRect
scrollrect( MacGetLeftBorderSize() , MacGetTopBorderSize() , width
, height
) ;
2386 scrollrect
.Intersect( *rect
) ;
2388 if ( m_peer
->GetNeedsDisplay() )
2390 // because HIViewScrollRect does not scroll the already invalidated area we have two options:
2391 // in case there is already a pending redraw on that area
2392 // either immediate redraw or full invalidate
2394 // is the better overall solution, as it does not slow down scrolling
2395 m_peer
->SetNeedsDisplay() ;
2397 // this would be the preferred version for fast drawing controls
2398 HIViewRender(m_peer
->GetControlRef()) ;
2402 // as the native control might be not a 0/0 wx window coordinates, we have to offset
2403 scrollrect
.Offset( -MacGetLeftBorderSize() , -MacGetTopBorderSize() ) ;
2404 m_peer
->ScrollRect( &scrollrect
, dx
, dy
) ;
2407 // this would be the preferred version for fast drawing controls
2408 HIViewRender(m_peer
->GetControlRef()) ;
2414 for (wxWindowList::compatibility_iterator node
= GetChildren().GetFirst(); node
; node
= node
->GetNext())
2416 child
= node
->GetData();
2419 if (child
== m_vScrollBar
)
2421 if (child
== m_hScrollBar
)
2423 if (child
->IsTopLevel())
2426 child
->GetPosition( &x
, &y
);
2427 child
->GetSize( &w
, &h
);
2430 wxRect
rc( x
, y
, w
, h
);
2431 if (rect
->Intersects( rc
))
2432 child
->SetSize( x
+ dx
, y
+ dy
, w
, h
, wxSIZE_AUTO
|wxSIZE_ALLOW_MINUS_ONE
);
2436 child
->SetSize( x
+ dx
, y
+ dy
, w
, h
, wxSIZE_AUTO
|wxSIZE_ALLOW_MINUS_ONE
);
2441 void wxWindowMac::MacOnScroll( wxScrollEvent
&event
)
2443 if ( event
.GetEventObject() == m_vScrollBar
|| event
.GetEventObject() == m_hScrollBar
)
2445 wxScrollWinEvent wevent
;
2446 wevent
.SetPosition(event
.GetPosition());
2447 wevent
.SetOrientation(event
.GetOrientation());
2448 wevent
.SetEventObject(this);
2450 if (event
.GetEventType() == wxEVT_SCROLL_TOP
)
2451 wevent
.SetEventType( wxEVT_SCROLLWIN_TOP
);
2452 else if (event
.GetEventType() == wxEVT_SCROLL_BOTTOM
)
2453 wevent
.SetEventType( wxEVT_SCROLLWIN_BOTTOM
);
2454 else if (event
.GetEventType() == wxEVT_SCROLL_LINEUP
)
2455 wevent
.SetEventType( wxEVT_SCROLLWIN_LINEUP
);
2456 else if (event
.GetEventType() == wxEVT_SCROLL_LINEDOWN
)
2457 wevent
.SetEventType( wxEVT_SCROLLWIN_LINEDOWN
);
2458 else if (event
.GetEventType() == wxEVT_SCROLL_PAGEUP
)
2459 wevent
.SetEventType( wxEVT_SCROLLWIN_PAGEUP
);
2460 else if (event
.GetEventType() == wxEVT_SCROLL_PAGEDOWN
)
2461 wevent
.SetEventType( wxEVT_SCROLLWIN_PAGEDOWN
);
2462 else if (event
.GetEventType() == wxEVT_SCROLL_THUMBTRACK
)
2463 wevent
.SetEventType( wxEVT_SCROLLWIN_THUMBTRACK
);
2464 else if (event
.GetEventType() == wxEVT_SCROLL_THUMBRELEASE
)
2465 wevent
.SetEventType( wxEVT_SCROLLWIN_THUMBRELEASE
);
2467 HandleWindowEvent(wevent
);
2471 // Get the window with the focus
2472 wxWindowMac
*wxWindowBase::DoFindFocus()
2474 ControlRef control
;
2475 GetKeyboardFocus( GetUserFocusWindow() , &control
) ;
2476 return wxFindControlFromMacControl( control
) ;
2479 void wxWindowMac::OnInternalIdle()
2481 // This calls the UI-update mechanism (querying windows for
2482 // menu/toolbar/control state information)
2483 if (wxUpdateUIEvent::CanUpdate(this) && IsShownOnScreen())
2484 UpdateWindowUI(wxUPDATE_UI_FROMIDLE
);
2487 // Raise the window to the top of the Z order
2488 void wxWindowMac::Raise()
2490 m_peer
->SetZOrder( true , NULL
) ;
2493 // Lower the window to the bottom of the Z order
2494 void wxWindowMac::Lower()
2496 m_peer
->SetZOrder( false , NULL
) ;
2499 // static wxWindow *gs_lastWhich = NULL;
2501 bool wxWindowMac::MacSetupCursor( const wxPoint
& pt
)
2503 // first trigger a set cursor event
2505 wxPoint clientorigin
= GetClientAreaOrigin() ;
2506 wxSize clientsize
= GetClientSize() ;
2508 if ( wxRect2DInt( clientorigin
.x
, clientorigin
.y
, clientsize
.x
, clientsize
.y
).Contains( wxPoint2DInt( pt
) ) )
2510 wxSetCursorEvent
event( pt
.x
, pt
.y
);
2512 bool processedEvtSetCursor
= HandleWindowEvent(event
);
2513 if ( processedEvtSetCursor
&& event
.HasCursor() )
2515 cursor
= event
.GetCursor() ;
2519 // the test for processedEvtSetCursor is here to prevent using m_cursor
2520 // if the user code caught EVT_SET_CURSOR() and returned nothing from
2521 // it - this is a way to say that our cursor shouldn't be used for this
2523 if ( !processedEvtSetCursor
&& m_cursor
.Ok() )
2526 if ( !wxIsBusy() && !GetParent() )
2527 cursor
= *wxSTANDARD_CURSOR
;
2531 cursor
.MacInstall() ;
2534 return cursor
.Ok() ;
2537 wxString
wxWindowMac::MacGetToolTipString( wxPoint
&WXUNUSED(pt
) )
2541 return m_tooltip
->GetTip() ;
2544 return wxEmptyString
;
2547 void wxWindowMac::ClearBackground()
2553 void wxWindowMac::Update()
2555 wxTopLevelWindowMac
* top
= MacGetTopLevelWindow();
2557 top
->MacPerformUpdates() ;
2560 wxTopLevelWindowMac
* wxWindowMac::MacGetTopLevelWindow() const
2562 wxTopLevelWindowMac
* win
= NULL
;
2563 WindowRef window
= (WindowRef
) MacGetTopLevelWindowRef() ;
2565 win
= wxFindWinFromMacWindow( window
) ;
2570 const wxRect
& wxWindowMac::MacGetClippedClientRect() const
2572 MacUpdateClippedRects() ;
2574 return m_cachedClippedClientRect
;
2577 const wxRect
& wxWindowMac::MacGetClippedRect() const
2579 MacUpdateClippedRects() ;
2581 return m_cachedClippedRect
;
2584 const wxRect
&wxWindowMac:: MacGetClippedRectWithOuterStructure() const
2586 MacUpdateClippedRects() ;
2588 return m_cachedClippedRectWithOuterStructure
;
2591 const wxRegion
& wxWindowMac::MacGetVisibleRegion( bool includeOuterStructures
)
2593 static wxRegion emptyrgn
;
2595 if ( !m_isBeingDeleted
&& IsShownOnScreen() )
2597 MacUpdateClippedRects() ;
2598 if ( includeOuterStructures
)
2599 return m_cachedClippedRegionWithOuterStructure
;
2601 return m_cachedClippedRegion
;
2609 void wxWindowMac::MacUpdateClippedRects() const
2611 if ( m_cachedClippedRectValid
)
2614 // includeOuterStructures is true if we try to draw somthing like a focus ring etc.
2615 // also a window dc uses this, in this case we only clip in the hierarchy for hard
2616 // borders like a scrollwindow, splitter etc otherwise we end up in a paranoia having
2617 // to add focus borders everywhere
2619 Rect r
, rIncludingOuterStructures
;
2621 m_peer
->GetRect( &r
) ;
2622 r
.left
-= MacGetLeftBorderSize() ;
2623 r
.top
-= MacGetTopBorderSize() ;
2624 r
.bottom
+= MacGetBottomBorderSize() ;
2625 r
.right
+= MacGetRightBorderSize() ;
2632 rIncludingOuterStructures
= r
;
2633 InsetRect( &rIncludingOuterStructures
, -4 , -4 ) ;
2635 wxRect cl
= GetClientRect() ;
2636 Rect rClient
= { cl
.y
, cl
.x
, cl
.y
+ cl
.height
, cl
.x
+ cl
.width
} ;
2640 const wxWindow
* child
= this ;
2641 const wxWindow
* parent
= NULL
;
2643 while ( !child
->IsTopLevel() && ( parent
= child
->GetParent() ) != NULL
)
2645 if ( parent
->MacIsChildOfClientArea(child
) )
2647 size
= parent
->GetClientSize() ;
2648 wxPoint origin
= parent
->GetClientAreaOrigin() ;
2654 // this will be true for scrollbars, toolbars etc.
2655 size
= parent
->GetSize() ;
2656 y
= parent
->MacGetTopBorderSize() ;
2657 x
= parent
->MacGetLeftBorderSize() ;
2658 size
.x
-= parent
->MacGetLeftBorderSize() + parent
->MacGetRightBorderSize() ;
2659 size
.y
-= parent
->MacGetTopBorderSize() + parent
->MacGetBottomBorderSize() ;
2662 parent
->MacWindowToRootWindow( &x
, &y
) ;
2663 MacRootWindowToWindow( &x
, &y
) ;
2665 Rect rparent
= { y
, x
, y
+ size
.y
, x
+ size
.x
} ;
2667 // the wxwindow and client rects will always be clipped
2668 SectRect( &r
, &rparent
, &r
) ;
2669 SectRect( &rClient
, &rparent
, &rClient
) ;
2671 // the structure only at 'hard' borders
2672 if ( parent
->MacClipChildren() ||
2673 ( parent
->GetParent() && parent
->GetParent()->MacClipGrandChildren() ) )
2675 SectRect( &rIncludingOuterStructures
, &rparent
, &rIncludingOuterStructures
) ;
2681 m_cachedClippedRect
= wxRect( r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
) ;
2682 m_cachedClippedClientRect
= wxRect( rClient
.left
, rClient
.top
,
2683 rClient
.right
- rClient
.left
, rClient
.bottom
- rClient
.top
) ;
2684 m_cachedClippedRectWithOuterStructure
= wxRect(
2685 rIncludingOuterStructures
.left
, rIncludingOuterStructures
.top
,
2686 rIncludingOuterStructures
.right
- rIncludingOuterStructures
.left
,
2687 rIncludingOuterStructures
.bottom
- rIncludingOuterStructures
.top
) ;
2689 m_cachedClippedRegionWithOuterStructure
= wxRegion( m_cachedClippedRectWithOuterStructure
) ;
2690 m_cachedClippedRegion
= wxRegion( m_cachedClippedRect
) ;
2691 m_cachedClippedClientRegion
= wxRegion( m_cachedClippedClientRect
) ;
2693 m_cachedClippedRectValid
= true ;
2697 This function must not change the updatergn !
2699 bool wxWindowMac::MacDoRedraw( void* updatergnr
, long time
)
2701 bool handled
= false ;
2703 RgnHandle updatergn
= (RgnHandle
) updatergnr
;
2704 GetRegionBounds( updatergn
, &updatebounds
) ;
2706 // wxLogDebug(wxT("update for %s bounds %d, %d, %d, %d"), wxString(GetClassInfo()->GetClassName()).c_str(), updatebounds.left, updatebounds.top , updatebounds.right , updatebounds.bottom ) ;
2708 if ( !EmptyRgn(updatergn
) )
2710 RgnHandle newupdate
= NewRgn() ;
2711 wxSize point
= GetClientSize() ;
2712 wxPoint origin
= GetClientAreaOrigin() ;
2713 SetRectRgn( newupdate
, origin
.x
, origin
.y
, origin
.x
+ point
.x
, origin
.y
+ point
.y
) ;
2714 SectRgn( newupdate
, updatergn
, newupdate
) ;
2716 // first send an erase event to the entire update area
2718 // for the toplevel window this really is the entire area
2719 // for all the others only their client area, otherwise they
2720 // might be drawing with full alpha and eg put blue into
2721 // the grow-box area of a scrolled window (scroll sample)
2722 wxDC
* dc
= new wxWindowDC(this);
2724 dc
->SetClippingRegion(wxRegion(HIShapeCreateWithQDRgn(updatergn
)));
2726 dc
->SetClippingRegion(wxRegion(HIShapeCreateWithQDRgn(newupdate
)));
2728 wxEraseEvent
eevent( GetId(), dc
);
2729 eevent
.SetEventObject( this );
2730 HandleWindowEvent( eevent
);
2736 // calculate a client-origin version of the update rgn and set m_updateRegion to that
2737 OffsetRgn( newupdate
, -origin
.x
, -origin
.y
) ;
2738 m_updateRegion
= wxRegion(HIShapeCreateWithQDRgn(newupdate
)) ;
2739 DisposeRgn( newupdate
) ;
2741 if ( !m_updateRegion
.Empty() )
2743 // paint the window itself
2746 event
.SetTimestamp(time
);
2747 event
.SetEventObject(this);
2748 HandleWindowEvent(event
);
2752 // now we cannot rely on having its borders drawn by a window itself, as it does not
2753 // get the updateRgn wide enough to always do so, so we do it from the parent
2754 // this would also be the place to draw any custom backgrounds for native controls
2755 // in Composited windowing
2756 wxPoint clientOrigin
= GetClientAreaOrigin() ;
2760 for (wxWindowList::compatibility_iterator node
= GetChildren().GetFirst(); node
; node
= node
->GetNext())
2762 child
= node
->GetData();
2765 if (child
== m_vScrollBar
)
2767 if (child
== m_hScrollBar
)
2769 if (child
->IsTopLevel())
2771 if (!child
->IsShown())
2774 // only draw those in the update region (add a safety margin of 10 pixels for shadow effects
2776 child
->GetPosition( &x
, &y
);
2777 child
->GetSize( &w
, &h
);
2778 Rect childRect
= { y
, x
, y
+ h
, x
+ w
} ;
2779 OffsetRect( &childRect
, clientOrigin
.x
, clientOrigin
.y
) ;
2780 InsetRect( &childRect
, -10 , -10) ;
2782 if ( RectInRgn( &childRect
, updatergn
) )
2784 // paint custom borders
2785 wxNcPaintEvent
eventNc( child
->GetId() );
2786 eventNc
.SetEventObject( child
);
2787 if ( !child
->HandleWindowEvent( eventNc
) )
2789 child
->MacPaintBorders(0, 0) ;
2799 WXWindow
wxWindowMac::MacGetTopLevelWindowRef() const
2801 wxWindowMac
*iter
= (wxWindowMac
*)this ;
2805 if ( iter
->IsTopLevel() )
2807 wxTopLevelWindow
* toplevel
= wxDynamicCast(iter
,wxTopLevelWindow
);
2809 return toplevel
->MacGetWindowRef();
2811 wxPopupWindow
* popupwin
= wxDynamicCast(iter
,wxPopupWindow
);
2813 return popupwin
->MacGetPopupWindowRef();
2816 iter
= iter
->GetParent() ;
2822 bool wxWindowMac::MacHasScrollBarCorner() const
2824 /* Returns whether the scroll bars in a wxScrolledWindow should be
2825 * shortened. Scroll bars should be shortened if either:
2827 * - both scroll bars are visible, or
2829 * - there is a resize box in the parent frame's corner and this
2830 * window shares the bottom and right edge with the parent
2834 if ( m_hScrollBar
== NULL
&& m_vScrollBar
== NULL
)
2837 if ( ( m_hScrollBar
&& m_hScrollBar
->IsShown() )
2838 && ( m_vScrollBar
&& m_vScrollBar
->IsShown() ) )
2840 // Both scroll bars visible
2845 wxPoint thisWindowBottomRight
= GetScreenRect().GetBottomRight();
2847 for ( const wxWindow
*win
= this; win
; win
= win
->GetParent() )
2849 const wxFrame
*frame
= wxDynamicCast( win
, wxFrame
) ;
2852 if ( frame
->GetWindowStyleFlag() & wxRESIZE_BORDER
)
2854 // Parent frame has resize handle
2855 wxPoint frameBottomRight
= frame
->GetScreenRect().GetBottomRight();
2857 // Note: allow for some wiggle room here as wxMac's
2858 // window rect calculations seem to be imprecise
2859 if ( abs( thisWindowBottomRight
.x
- frameBottomRight
.x
) <= 2
2860 && abs( thisWindowBottomRight
.y
- frameBottomRight
.y
) <= 2 )
2862 // Parent frame has resize handle and shares
2863 // right bottom corner
2868 // Parent frame has resize handle but doesn't
2869 // share right bottom corner
2875 // Parent frame doesn't have resize handle
2881 // No parent frame found
2886 void wxWindowMac::MacCreateScrollBars( long style
)
2888 wxASSERT_MSG( m_vScrollBar
== NULL
&& m_hScrollBar
== NULL
, wxT("attempt to create window twice") ) ;
2890 if ( style
& ( wxVSCROLL
| wxHSCROLL
) )
2892 int scrlsize
= MAC_SCROLLBAR_SIZE
;
2893 if ( GetWindowVariant() == wxWINDOW_VARIANT_SMALL
|| GetWindowVariant() == wxWINDOW_VARIANT_MINI
)
2895 scrlsize
= MAC_SMALL_SCROLLBAR_SIZE
;
2898 int adjust
= MacHasScrollBarCorner() ? scrlsize
- 1: 0 ;
2900 GetClientSize( &width
, &height
) ;
2902 wxPoint
vPoint(width
- scrlsize
, 0) ;
2903 wxSize
vSize(scrlsize
, height
- adjust
) ;
2904 wxPoint
hPoint(0, height
- scrlsize
) ;
2905 wxSize
hSize(width
- adjust
, scrlsize
) ;
2907 // we have to set the min size to a smaller value, otherwise they cannot get smaller (InitialSize sets MinSize)
2908 if ( style
& wxVSCROLL
)
2910 m_vScrollBar
= new wxScrollBar((wxWindow
*)this, wxID_ANY
, vPoint
, vSize
, wxVERTICAL
);
2911 m_vScrollBar
->SetMinSize( wxDefaultSize
);
2914 if ( style
& wxHSCROLL
)
2916 m_hScrollBar
= new wxScrollBar((wxWindow
*)this, wxID_ANY
, hPoint
, hSize
, wxHORIZONTAL
);
2917 m_hScrollBar
->SetMinSize( wxDefaultSize
);
2921 // because the create does not take into account the client area origin
2922 // we might have a real position shift
2923 MacRepositionScrollBars() ;
2926 bool wxWindowMac::MacIsChildOfClientArea( const wxWindow
* child
) const
2928 bool result
= ((child
== NULL
) || ((child
!= m_hScrollBar
) && (child
!= m_vScrollBar
)));
2933 void wxWindowMac::MacRepositionScrollBars()
2935 if ( !m_hScrollBar
&& !m_vScrollBar
)
2938 int scrlsize
= m_hScrollBar
? m_hScrollBar
->GetSize().y
: ( m_vScrollBar
? m_vScrollBar
->GetSize().x
: MAC_SCROLLBAR_SIZE
) ;
2939 int adjust
= MacHasScrollBarCorner() ? scrlsize
- 1 : 0 ;
2941 // get real client area
2943 GetSize( &width
, &height
);
2945 width
-= MacGetLeftBorderSize() + MacGetRightBorderSize();
2946 height
-= MacGetTopBorderSize() + MacGetBottomBorderSize();
2948 wxPoint
vPoint( width
- scrlsize
, 0 ) ;
2949 wxSize
vSize( scrlsize
, height
- adjust
) ;
2950 wxPoint
hPoint( 0 , height
- scrlsize
) ;
2951 wxSize
hSize( width
- adjust
, scrlsize
) ;
2954 int x
= 0, y
= 0, w
, h
;
2955 GetSize( &w
, &h
) ;
2957 MacClientToRootWindow( &x
, &y
) ;
2958 MacClientToRootWindow( &w
, &h
) ;
2960 wxWindowMac
*iter
= (wxWindowMac
*)this ;
2962 int totW
= 10000 , totH
= 10000;
2965 if ( iter
->IsTopLevel() )
2967 iter
->GetSize( &totW
, &totH
) ;
2971 iter
= iter
->GetParent() ;
2985 if ( w
- x
>= totW
)
2990 if ( h
- y
>= totH
)
2998 m_vScrollBar
->SetSize( vPoint
.x
, vPoint
.y
, vSize
.x
, vSize
.y
, wxSIZE_ALLOW_MINUS_ONE
);
3000 m_hScrollBar
->SetSize( hPoint
.x
, hPoint
.y
, hSize
.x
, hSize
.y
, wxSIZE_ALLOW_MINUS_ONE
);
3003 bool wxWindowMac::AcceptsFocus() const
3005 return MacCanFocus() && wxWindowBase::AcceptsFocus();
3008 void wxWindowMac::MacSuperChangedPosition()
3010 // only window-absolute structures have to be moved i.e. controls
3012 m_cachedClippedRectValid
= false ;
3015 wxWindowList::compatibility_iterator node
= GetChildren().GetFirst();
3018 child
= node
->GetData();
3019 child
->MacSuperChangedPosition() ;
3021 node
= node
->GetNext();
3025 void wxWindowMac::MacTopLevelWindowChangedPosition()
3027 // only screen-absolute structures have to be moved i.e. glcanvas
3030 wxWindowList::compatibility_iterator node
= GetChildren().GetFirst();
3033 child
= node
->GetData();
3034 child
->MacTopLevelWindowChangedPosition() ;
3036 node
= node
->GetNext();
3040 long wxWindowMac::MacGetLeftBorderSize() const
3047 if (HasFlag(wxRAISED_BORDER
) || HasFlag( wxSUNKEN_BORDER
) || HasFlag(wxDOUBLE_BORDER
))
3049 // this metric is only the 'outset' outside the simple frame rect
3050 GetThemeMetric( kThemeMetricEditTextFrameOutset
, &border
) ;
3053 else if (HasFlag(wxSIMPLE_BORDER
))
3055 // this metric is only the 'outset' outside the simple frame rect
3056 GetThemeMetric( kThemeMetricListBoxFrameOutset
, &border
) ;
3063 long wxWindowMac::MacGetRightBorderSize() const
3065 // they are all symmetric in mac themes
3066 return MacGetLeftBorderSize() ;
3069 long wxWindowMac::MacGetTopBorderSize() const
3071 // they are all symmetric in mac themes
3072 return MacGetLeftBorderSize() ;
3075 long wxWindowMac::MacGetBottomBorderSize() const
3077 // they are all symmetric in mac themes
3078 return MacGetLeftBorderSize() ;
3081 long wxWindowMac::MacRemoveBordersFromStyle( long style
)
3083 return style
& ~wxBORDER_MASK
;
3086 // Find the wxWindowMac at the current mouse position, returning the mouse
3088 wxWindowMac
* wxFindWindowAtPointer( wxPoint
& pt
)
3090 pt
= wxGetMousePosition();
3091 wxWindowMac
* found
= wxFindWindowAtPoint(pt
);
3096 // Get the current mouse position.
3097 wxPoint
wxGetMousePosition()
3101 wxGetMousePosition( &x
, &y
);
3103 return wxPoint(x
, y
);
3106 void wxWindowMac::OnMouseEvent( wxMouseEvent
&event
)
3108 if ( event
.GetEventType() == wxEVT_RIGHT_DOWN
)
3110 // copied from wxGTK : CS
3111 // VZ: shouldn't we move this to base class then?
3113 // generate a "context menu" event: this is similar to wxEVT_RIGHT_DOWN
3116 // (a) it's a command event and so is propagated to the parent
3117 // (b) under MSW it can be generated from kbd too
3118 // (c) it uses screen coords (because of (a))
3119 wxContextMenuEvent
evtCtx(wxEVT_CONTEXT_MENU
,
3121 this->ClientToScreen(event
.GetPosition()));
3122 evtCtx
.SetEventObject(this);
3123 if ( ! HandleWindowEvent(evtCtx
) )
3132 void wxWindowMac::OnPaint( wxPaintEvent
& WXUNUSED(event
) )
3134 if ( wxTheApp
->MacGetCurrentEvent() != NULL
&& wxTheApp
->MacGetCurrentEventHandlerCallRef() != NULL
3135 && GetBackgroundStyle() != wxBG_STYLE_TRANSPARENT
)
3136 CallNextEventHandler(
3137 (EventHandlerCallRef
)wxTheApp
->MacGetCurrentEventHandlerCallRef() ,
3138 (EventRef
) wxTheApp
->MacGetCurrentEvent() ) ;
3141 void wxWindowMac::MacHandleControlClick(WXWidget
WXUNUSED(control
),
3142 wxInt16
WXUNUSED(controlpart
),
3143 bool WXUNUSED(mouseStillDown
))
3147 Rect
wxMacGetBoundsForControl( wxWindow
* window
, const wxPoint
& pos
, const wxSize
&size
, bool adjustForOrigin
)
3151 window
->MacGetBoundsForControl( pos
, size
, x
, y
, w
, h
, adjustForOrigin
) ;
3152 Rect bounds
= { y
, x
, y
+ h
, x
+ w
};
3157 wxInt32
wxWindowMac::MacControlHit(WXEVENTHANDLERREF
WXUNUSED(handler
) , WXEVENTREF
WXUNUSED(event
) )
3159 return eventNotHandledErr
;
3162 bool wxWindowMac::Reparent(wxWindowBase
*newParentBase
)
3164 wxWindowMac
*newParent
= (wxWindowMac
*)newParentBase
;
3165 if ( !wxWindowBase::Reparent(newParent
) )
3168 // copied from MacPostControlCreate
3169 ControlRef container
= (ControlRef
) GetParent()->GetHandle() ;
3171 wxASSERT_MSG( container
!= NULL
, wxT("No valid mac container control") ) ;
3173 ::EmbedControl( m_peer
->GetControlRef() , container
) ;
3178 bool wxWindowMac::SetTransparent(wxByte alpha
)
3180 SetBackgroundStyle(wxBG_STYLE_TRANSPARENT
);
3182 if ( alpha
!= m_macAlpha
)
3184 m_macAlpha
= alpha
;
3191 bool wxWindowMac::CanSetTransparent()
3196 wxByte
wxWindowMac::GetTransparent() const
3201 bool wxWindowMac::IsShownOnScreen() const
3203 #if TARGET_API_MAC_OSX
3204 if ( m_peer
&& m_peer
->Ok() )
3206 bool peerVis
= m_peer
->IsVisible();
3207 bool wxVis
= wxWindowBase::IsShownOnScreen();
3208 if( peerVis
!= wxVis
)
3210 // CS : put a breakpoint here to investigate differences
3211 // between native an wx visibilities
3212 // the only place where I've encountered them until now
3213 // are the hiding/showing sequences where the vis-changed event is
3214 // first sent to the innermost control, while wx does things
3215 // from the outmost control
3216 wxVis
= wxWindowBase::IsShownOnScreen();
3220 return m_peer
->IsVisible();
3224 return wxWindowBase::IsShownOnScreen();