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_SET_FOCUS(wxWindowMac::OnSetFocus
)
82 EVT_KILL_FOCUS(wxWindowMac::OnSetFocus
)
83 EVT_MOUSE_EVENTS(wxWindowMac::OnMouseEvent
)
86 #define wxMAC_DEBUG_REDRAW 0
87 #ifndef wxMAC_DEBUG_REDRAW
88 #define wxMAC_DEBUG_REDRAW 0
91 // ---------------------------------------------------------------------------
92 // Utility Routines to move between different coordinate systems
93 // ---------------------------------------------------------------------------
96 * Right now we have the following setup :
97 * a border that is not part of the native control is always outside the
98 * control's border (otherwise we loose all native intelligence, future ways
99 * may be to have a second embedding control responsible for drawing borders
100 * and backgrounds eventually)
101 * so all this border calculations have to be taken into account when calling
102 * native methods or getting native oriented data
103 * so we have three coordinate systems here
104 * wx client coordinates
105 * wx window coordinates (including window frames)
110 // originating from native control
114 void wxMacNativeToWindow( const wxWindow
* window
, RgnHandle handle
)
116 OffsetRgn( handle
, window
->MacGetLeftBorderSize() , window
->MacGetTopBorderSize() ) ;
119 void wxMacNativeToWindow( const wxWindow
* window
, Rect
*rect
)
121 OffsetRect( rect
, window
->MacGetLeftBorderSize() , window
->MacGetTopBorderSize() ) ;
125 // directed towards native control
128 void wxMacWindowToNative( const wxWindow
* window
, RgnHandle handle
)
130 OffsetRgn( handle
, -window
->MacGetLeftBorderSize() , -window
->MacGetTopBorderSize() );
133 void wxMacWindowToNative( const wxWindow
* window
, Rect
*rect
)
135 OffsetRect( rect
, -window
->MacGetLeftBorderSize() , -window
->MacGetTopBorderSize() ) ;
138 // ---------------------------------------------------------------------------
140 // ---------------------------------------------------------------------------
142 static const EventTypeSpec eventList
[] =
144 { kEventClassCommand
, kEventProcessCommand
} ,
145 { kEventClassCommand
, kEventCommandUpdateStatus
} ,
147 { kEventClassControl
, kEventControlGetClickActivation
} ,
148 { kEventClassControl
, kEventControlHit
} ,
150 { kEventClassTextInput
, kEventTextInputUnicodeForKeyEvent
} ,
151 { kEventClassTextInput
, kEventTextInputUpdateActiveInputArea
} ,
153 { kEventClassControl
, kEventControlDraw
} ,
155 { kEventClassControl
, kEventControlVisibilityChanged
} ,
156 { kEventClassControl
, kEventControlEnabledStateChanged
} ,
157 { kEventClassControl
, kEventControlHiliteChanged
} ,
159 { kEventClassControl
, kEventControlActivate
} ,
160 { kEventClassControl
, kEventControlDeactivate
} ,
162 { kEventClassControl
, kEventControlSetFocusPart
} ,
164 { kEventClassService
, kEventServiceGetTypes
},
165 { kEventClassService
, kEventServiceCopy
},
166 { kEventClassService
, kEventServicePaste
},
168 // { kEventClassControl , kEventControlInvalidateForSizeChange } , // 10.3 only
169 // { kEventClassControl , kEventControlBoundsChanged } ,
172 static pascal OSStatus
wxMacWindowControlEventHandler( EventHandlerCallRef handler
, EventRef event
, void *data
)
174 OSStatus result
= eventNotHandledErr
;
176 wxMacCarbonEvent
cEvent( event
) ;
178 ControlRef controlRef
;
179 wxWindowMac
* thisWindow
= (wxWindowMac
*) data
;
181 cEvent
.GetParameter( kEventParamDirectObject
, &controlRef
) ;
183 switch ( GetEventKind( event
) )
185 case kEventControlDraw
:
187 RgnHandle updateRgn
= NULL
;
188 RgnHandle allocatedRgn
= NULL
;
189 wxRegion visRegion
= thisWindow
->MacGetVisibleRegion() ;
191 if ( cEvent
.GetParameter
<RgnHandle
>(kEventParamRgnHandle
, &updateRgn
) != noErr
)
193 updateRgn
= (RgnHandle
) visRegion
.GetWXHRGN() ;
197 if ( thisWindow
->MacGetLeftBorderSize() != 0 || thisWindow
->MacGetTopBorderSize() != 0 )
199 // as this update region is in native window locals we must adapt it to wx window local
200 allocatedRgn
= NewRgn() ;
201 CopyRgn( updateRgn
, allocatedRgn
) ;
203 // hide the given region by the new region that must be shifted
204 wxMacNativeToWindow( thisWindow
, allocatedRgn
) ;
205 updateRgn
= allocatedRgn
;
209 #if wxMAC_DEBUG_REDRAW
210 if ( thisWindow
->MacIsUserPane() )
212 static float color
= 0.5 ;
215 CGContextRef cgContext
= cEvent
.GetParameter
<CGContextRef
>(kEventParamCGContextRef
) ;
217 HIViewGetBounds( controlRef
, &bounds
);
218 CGContextSetRGBFillColor( cgContext
, channel
== 0 ? color
: 0.5 ,
219 channel
== 1 ? color
: 0.5 , channel
== 2 ? color
: 0.5 , 1 );
220 CGContextFillRect( cgContext
, bounds
);
233 bool created
= false ;
234 CGContextRef cgContext
= NULL
;
235 OSStatus err
= cEvent
.GetParameter
<CGContextRef
>(kEventParamCGContextRef
, &cgContext
) ;
236 wxASSERT_MSG( err
== noErr
, wxT("Unable to retrieve CGContextRef") ) ;
237 thisWindow
->MacSetCGContextRef( cgContext
) ;
240 wxMacCGContextStateSaver
sg( cgContext
) ;
243 wxWindow
* iter
= thisWindow
;
246 alpha
*= (float) iter
->GetTransparent()/255.0 ;
247 if ( iter
->IsTopLevel() )
250 iter
= iter
->GetParent() ;
253 CGContextSetAlpha( cgContext
, alpha
) ;
255 if ( thisWindow
->GetBackgroundStyle() == wxBG_STYLE_TRANSPARENT
)
258 HIViewGetBounds( controlRef
, &bounds
);
259 CGContextClearRect( cgContext
, bounds
);
264 if ( thisWindow
->MacDoRedraw( updateRgn
, cEvent
.GetTicks() ) )
267 thisWindow
->MacSetCGContextRef( NULL
) ;
271 CGContextRelease( cgContext
) ;
275 DisposeRgn( allocatedRgn
) ;
279 case kEventControlVisibilityChanged
:
280 thisWindow
->MacVisibilityChanged() ;
283 case kEventControlEnabledStateChanged
:
284 thisWindow
->MacEnabledStateChanged();
287 case kEventControlHiliteChanged
:
288 thisWindow
->MacHiliteChanged() ;
291 case kEventControlActivate
:
292 case kEventControlDeactivate
:
293 // FIXME: we should have a virtual function for this!
295 if ( thisWindow
->IsKindOf( CLASSINFO( wxTreeCtrl
) ) )
296 thisWindow
->Refresh();
299 if ( thisWindow
->IsKindOf( CLASSINFO( wxListCtrl
) ) )
300 thisWindow
->Refresh();
304 // we emulate this event under Carbon CFM
305 case kEventControlSetFocusPart
:
307 Boolean focusEverything
= false ;
308 ControlPartCode controlPart
= cEvent
.GetParameter
<ControlPartCode
>(kEventParamControlPart
, typeControlPartCode
);
310 if ( cEvent
.GetParameter
<Boolean
>(kEventParamControlFocusEverything
, &focusEverything
) == noErr
)
314 if ( thisWindow
->MacIsUserPane() )
317 if ( controlPart
== kControlFocusNoPart
)
320 if ( thisWindow
->GetCaret() )
321 thisWindow
->GetCaret()->OnKillFocus();
324 static bool inKillFocusEvent
= false ;
326 if ( !inKillFocusEvent
)
328 inKillFocusEvent
= true ;
329 wxFocusEvent
event( wxEVT_KILL_FOCUS
, thisWindow
->GetId());
330 event
.SetEventObject(thisWindow
);
331 thisWindow
->GetEventHandler()->ProcessEvent(event
) ;
332 inKillFocusEvent
= false ;
337 // panel wants to track the window which was the last to have focus in it
338 wxChildFocusEvent
eventFocus(thisWindow
);
339 thisWindow
->GetEventHandler()->ProcessEvent(eventFocus
);
342 if ( thisWindow
->GetCaret() )
343 thisWindow
->GetCaret()->OnSetFocus();
346 wxFocusEvent
event(wxEVT_SET_FOCUS
, thisWindow
->GetId());
347 event
.SetEventObject(thisWindow
);
348 thisWindow
->GetEventHandler()->ProcessEvent(event
) ;
353 case kEventControlHit
:
354 result
= thisWindow
->MacControlHit( handler
, event
) ;
357 case kEventControlGetClickActivation
:
359 // fix to always have a proper activation for DataBrowser controls (stay in bkgnd otherwise)
360 WindowRef owner
= cEvent
.GetParameter
<WindowRef
>(kEventParamWindowRef
);
361 if ( !IsWindowActive(owner
) )
363 cEvent
.SetParameter(kEventParamClickActivation
,(UInt32
) kActivateAndIgnoreClick
) ;
376 static pascal OSStatus
377 wxMacWindowServiceEventHandler(EventHandlerCallRef
WXUNUSED(handler
),
381 OSStatus result
= eventNotHandledErr
;
383 wxMacCarbonEvent
cEvent( event
) ;
385 ControlRef controlRef
;
386 wxWindowMac
* thisWindow
= (wxWindowMac
*) data
;
387 wxTextCtrl
* textCtrl
= wxDynamicCast( thisWindow
, wxTextCtrl
) ;
388 cEvent
.GetParameter( kEventParamDirectObject
, &controlRef
) ;
390 switch ( GetEventKind( event
) )
392 case kEventServiceGetTypes
:
396 textCtrl
->GetSelection( &from
, &to
) ;
398 CFMutableArrayRef copyTypes
= 0 , pasteTypes
= 0;
400 copyTypes
= cEvent
.GetParameter
< CFMutableArrayRef
>( kEventParamServiceCopyTypes
, typeCFMutableArrayRef
) ;
401 if ( textCtrl
->IsEditable() )
402 pasteTypes
= cEvent
.GetParameter
< CFMutableArrayRef
>( kEventParamServicePasteTypes
, typeCFMutableArrayRef
) ;
404 static const OSType textDataTypes
[] = { kTXNTextData
/* , 'utxt', 'PICT', 'MooV', 'AIFF' */ };
405 for ( size_t i
= 0 ; i
< WXSIZEOF(textDataTypes
) ; ++i
)
407 CFStringRef typestring
= CreateTypeStringWithOSType(textDataTypes
[i
]);
411 CFArrayAppendValue(copyTypes
, typestring
) ;
413 CFArrayAppendValue(pasteTypes
, typestring
) ;
415 CFRelease( typestring
) ;
423 case kEventServiceCopy
:
428 textCtrl
->GetSelection( &from
, &to
) ;
429 wxString val
= textCtrl
->GetValue() ;
430 val
= val
.Mid( from
, to
- from
) ;
431 PasteboardRef pasteboard
= cEvent
.GetParameter
<PasteboardRef
>( kEventParamPasteboardRef
, typePasteboardRef
);
432 verify_noerr( PasteboardClear( pasteboard
) ) ;
433 PasteboardSynchronize( pasteboard
);
434 // TODO add proper conversion
435 CFDataRef data
= CFDataCreate( kCFAllocatorDefault
, (const UInt8
*)val
.c_str(), val
.length() );
436 PasteboardPutItemFlavor( pasteboard
, (PasteboardItemID
) 1, CFSTR("com.apple.traditional-mac-plain-text"), data
, 0);
442 case kEventServicePaste
:
445 PasteboardRef pasteboard
= cEvent
.GetParameter
<PasteboardRef
>( kEventParamPasteboardRef
, typePasteboardRef
);
446 PasteboardSynchronize( pasteboard
);
448 verify_noerr( PasteboardGetItemCount( pasteboard
, &itemCount
) );
449 for( UInt32 itemIndex
= 1; itemIndex
<= itemCount
; itemIndex
++ )
451 PasteboardItemID itemID
;
452 if ( PasteboardGetItemIdentifier( pasteboard
, itemIndex
, &itemID
) == noErr
)
454 CFDataRef flavorData
= NULL
;
455 if ( PasteboardCopyItemFlavorData( pasteboard
, itemID
, CFSTR("com.apple.traditional-mac-plain-text"), &flavorData
) == noErr
)
457 CFIndex flavorDataSize
= CFDataGetLength( flavorData
);
458 char *content
= new char[flavorDataSize
+1] ;
459 memcpy( content
, CFDataGetBytePtr( flavorData
), flavorDataSize
);
460 content
[flavorDataSize
]=0;
461 CFRelease( flavorData
);
463 textCtrl
->WriteText( wxString( content
, wxConvLocal
) );
465 textCtrl
->WriteText( wxString( content
) ) ;
483 pascal OSStatus
wxMacUnicodeTextEventHandler( EventHandlerCallRef handler
, EventRef event
, void *data
)
485 OSStatus result
= eventNotHandledErr
;
486 wxWindowMac
* focus
= (wxWindowMac
*) data
;
488 wchar_t* uniChars
= NULL
;
489 UInt32 when
= EventTimeToTicks( GetEventTime( event
) ) ;
491 UniChar
* charBuf
= NULL
;
492 ByteCount dataSize
= 0 ;
495 if ( GetEventParameter( event
, kEventParamTextInputSendText
, typeUnicodeText
, NULL
, 0 , &dataSize
, NULL
) == noErr
)
497 numChars
= dataSize
/ sizeof( UniChar
) + 1;
500 if ( (size_t) numChars
* 2 > sizeof(buf
) )
501 charBuf
= new UniChar
[ numChars
] ;
505 uniChars
= new wchar_t[ numChars
] ;
506 GetEventParameter( event
, kEventParamTextInputSendText
, typeUnicodeText
, NULL
, dataSize
, NULL
, charBuf
) ;
507 charBuf
[ numChars
- 1 ] = 0;
508 #if SIZEOF_WCHAR_T == 2
509 uniChars
= (wchar_t*) charBuf
;
510 /* 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...)
512 // the resulting string will never have more chars than the utf16 version, so this is safe
513 wxMBConvUTF16 converter
;
514 numChars
= converter
.MB2WC( uniChars
, (const char*)charBuf
, numChars
) ;
518 switch ( GetEventKind( event
) )
520 case kEventTextInputUpdateActiveInputArea
:
522 // An IME input event may return several characters, but we need to send one char at a time to
524 for (int pos
=0 ; pos
< numChars
; pos
++)
526 WXEVENTREF formerEvent
= wxTheApp
->MacGetCurrentEvent() ;
527 WXEVENTHANDLERCALLREF formerHandler
= wxTheApp
->MacGetCurrentEventHandlerCallRef() ;
528 wxTheApp
->MacSetCurrentEvent( event
, handler
) ;
530 UInt32 message
= uniChars
[pos
] < 128 ? (char)uniChars
[pos
] : '?';
532 NB: faking a charcode here is problematic. The kEventTextInputUpdateActiveInputArea event is sent
533 multiple times to update the active range during inline input, so this handler will often receive
534 uncommited text, which should usually not trigger side effects. It might be a good idea to check the
535 kEventParamTextInputSendFixLen parameter and verify if input is being confirmed (see CarbonEvents.h).
536 On the other hand, it can be useful for some applications to react to uncommitted text (for example,
537 to update a status display), as long as it does not disrupt the inline input session. Ideally, wx
538 should add new event types to support advanced text input. For now, I would keep things as they are.
540 However, the code that was being used caused additional problems:
541 UInt32 message = (0 << 8) + ((char)uniChars[pos] );
542 Since it simply truncated the unichar to the last byte, it ended up causing weird bugs with inline
543 input, such as switching to another field when one attempted to insert the character U+4E09 (the kanji
544 for "three"), because it was truncated to 09 (kTabCharCode), which was later "converted" to WXK_TAB
545 (still 09) in wxMacTranslateKey; or triggering the default button when one attempted to insert U+840D
546 (the kanji for "name"), which got truncated to 0D and interpreted as a carriage return keypress.
547 Note that even single-byte characters could have been misinterpreted, since MacRoman charcodes only
548 overlap with Unicode within the (7-bit) ASCII range.
549 But simply passing a NUL charcode would disable text updated events, because wxTextCtrl::OnChar checks
550 for codes within a specific range. Therefore I went for the solution seen above, which keeps ASCII
551 characters as they are and replaces the rest with '?', ensuring that update events are triggered.
552 It would be better to change wxTextCtrl::OnChar to look at the actual unicode character instead, but
553 I don't have time to look into that right now.
556 if ( wxTheApp
->MacSendCharEvent(
557 focus
, message
, 0 , when
, 0 , 0 , uniChars
[pos
] ) )
562 wxTheApp
->MacSetCurrentEvent( formerEvent
, formerHandler
) ;
566 case kEventTextInputUnicodeForKeyEvent
:
568 UInt32 keyCode
, modifiers
;
571 unsigned char charCode
;
573 GetEventParameter( event
, kEventParamTextInputSendKeyboardEvent
, typeEventRef
, NULL
, sizeof(rawEvent
), NULL
, &rawEvent
) ;
574 GetEventParameter( rawEvent
, kEventParamKeyMacCharCodes
, typeChar
, NULL
, sizeof(char), NULL
, &charCode
);
575 GetEventParameter( rawEvent
, kEventParamKeyCode
, typeUInt32
, NULL
, sizeof(UInt32
), NULL
, &keyCode
);
576 GetEventParameter( rawEvent
, kEventParamKeyModifiers
, typeUInt32
, NULL
, sizeof(UInt32
), NULL
, &modifiers
);
577 GetEventParameter( rawEvent
, kEventParamMouseLocation
, typeQDPoint
, NULL
, sizeof(Point
), NULL
, &point
);
579 UInt32 message
= (keyCode
<< 8) + charCode
;
581 // An IME input event may return several characters, but we need to send one char at a time to
583 for (int pos
=0 ; pos
< numChars
; pos
++)
585 WXEVENTREF formerEvent
= wxTheApp
->MacGetCurrentEvent() ;
586 WXEVENTHANDLERCALLREF formerHandler
= wxTheApp
->MacGetCurrentEventHandlerCallRef() ;
587 wxTheApp
->MacSetCurrentEvent( event
, handler
) ;
589 if ( wxTheApp
->MacSendCharEvent(
590 focus
, message
, modifiers
, when
, point
.h
, point
.v
, uniChars
[pos
] ) )
595 wxTheApp
->MacSetCurrentEvent( formerEvent
, formerHandler
) ;
604 if ( charBuf
!= buf
)
610 static pascal OSStatus
611 wxMacWindowCommandEventHandler(EventHandlerCallRef
WXUNUSED(handler
),
615 OSStatus result
= eventNotHandledErr
;
616 wxWindowMac
* focus
= (wxWindowMac
*) data
;
620 wxMacCarbonEvent
cEvent( event
) ;
621 cEvent
.GetParameter
<HICommand
>(kEventParamDirectObject
,typeHICommand
,&command
) ;
623 wxMenuItem
* item
= NULL
;
624 wxMenu
* itemMenu
= wxFindMenuFromMacCommand( command
, item
) ;
625 int id
= wxMacCommandToId( command
.commandID
) ;
629 wxASSERT( itemMenu
!= NULL
) ;
631 switch ( cEvent
.GetKind() )
633 case kEventProcessCommand
:
634 result
= itemMenu
->MacHandleCommandProcess( item
, id
, focus
);
637 case kEventCommandUpdateStatus
:
638 result
= itemMenu
->MacHandleCommandUpdateStatus( item
, id
, focus
);
648 pascal OSStatus
wxMacWindowEventHandler( EventHandlerCallRef handler
, EventRef event
, void *data
)
650 EventRef formerEvent
= (EventRef
) wxTheApp
->MacGetCurrentEvent() ;
651 EventHandlerCallRef formerEventHandlerCallRef
= (EventHandlerCallRef
) wxTheApp
->MacGetCurrentEventHandlerCallRef() ;
652 wxTheApp
->MacSetCurrentEvent( event
, handler
) ;
653 OSStatus result
= eventNotHandledErr
;
655 switch ( GetEventClass( event
) )
657 case kEventClassCommand
:
658 result
= wxMacWindowCommandEventHandler( handler
, event
, data
) ;
661 case kEventClassControl
:
662 result
= wxMacWindowControlEventHandler( handler
, event
, data
) ;
665 case kEventClassService
:
666 result
= wxMacWindowServiceEventHandler( handler
, event
, data
) ;
669 case kEventClassTextInput
:
670 result
= wxMacUnicodeTextEventHandler( handler
, event
, data
) ;
677 wxTheApp
->MacSetCurrentEvent( formerEvent
, formerEventHandlerCallRef
) ;
682 DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacWindowEventHandler
)
684 // ---------------------------------------------------------------------------
685 // Scrollbar Tracking for all
686 // ---------------------------------------------------------------------------
688 pascal void wxMacLiveScrollbarActionProc( ControlRef control
, ControlPartCode partCode
) ;
689 pascal void wxMacLiveScrollbarActionProc( ControlRef control
, ControlPartCode partCode
)
693 wxWindow
* wx
= wxFindControlFromMacControl( control
) ;
695 wx
->MacHandleControlClick( (WXWidget
) control
, partCode
, true /* stillDown */ ) ;
698 wxMAC_DEFINE_PROC_GETTER( ControlActionUPP
, wxMacLiveScrollbarActionProc
) ;
700 // ===========================================================================
702 // ===========================================================================
704 WX_DECLARE_HASH_MAP(ControlRef
, wxWindow
*, wxPointerHash
, wxPointerEqual
, MacControlMap
);
706 static MacControlMap wxWinMacControlList
;
708 wxWindow
*wxFindControlFromMacControl(ControlRef inControl
)
710 MacControlMap::iterator node
= wxWinMacControlList
.find(inControl
);
712 return (node
== wxWinMacControlList
.end()) ? NULL
: node
->second
;
715 void wxAssociateControlWithMacControl(ControlRef inControl
, wxWindow
*control
)
717 // adding NULL ControlRef is (first) surely a result of an error and
718 // (secondly) breaks native event processing
719 wxCHECK_RET( inControl
!= (ControlRef
) NULL
, wxT("attempt to add a NULL WindowRef to window list") );
721 wxWinMacControlList
[inControl
] = control
;
724 void wxRemoveMacControlAssociation(wxWindow
*control
)
726 // iterate over all the elements in the class
727 // is the iterator stable ? as we might have two associations pointing to the same wxWindow
728 // we should go on...
734 MacControlMap::iterator it
;
735 for ( it
= wxWinMacControlList
.begin(); it
!= wxWinMacControlList
.end(); ++it
)
737 if ( it
->second
== control
)
739 wxWinMacControlList
.erase(it
);
747 // ----------------------------------------------------------------------------
748 // constructors and such
749 // ----------------------------------------------------------------------------
751 wxWindowMac::wxWindowMac()
756 wxWindowMac::wxWindowMac(wxWindowMac
*parent
,
761 const wxString
& name
)
764 Create(parent
, id
, pos
, size
, style
, name
);
767 void wxWindowMac::Init()
772 m_cgContextRef
= NULL
;
774 // as all windows are created with WS_VISIBLE style...
777 m_hScrollBar
= NULL
;
778 m_vScrollBar
= NULL
;
779 m_hScrollBarAlwaysShown
= false;
780 m_vScrollBarAlwaysShown
= false;
782 m_macIsUserPane
= true;
783 m_clipChildren
= false ;
784 m_cachedClippedRectValid
= false ;
786 // we need a valid font for the encodings
787 wxWindowBase::SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
));
790 wxWindowMac::~wxWindowMac()
794 m_isBeingDeleted
= true;
796 MacInvalidateBorders() ;
798 #ifndef __WXUNIVERSAL__
799 // VS: make sure there's no wxFrame with last focus set to us:
800 for ( wxWindow
*win
= GetParent(); win
; win
= win
->GetParent() )
802 wxFrame
*frame
= wxDynamicCast(win
, wxFrame
);
805 if ( frame
->GetLastFocus() == this )
806 frame
->SetLastFocus((wxWindow
*)NULL
);
812 // destroy children before destroying this window itself
815 // wxRemoveMacControlAssociation( this ) ;
816 // If we delete an item, we should initialize the parent panel,
817 // because it could now be invalid.
818 wxTopLevelWindow
*tlw
= wxDynamicCast(wxGetTopLevelParent(this), wxTopLevelWindow
);
821 if ( tlw
->GetDefaultItem() == (wxButton
*) this)
822 tlw
->SetDefaultItem(NULL
);
825 if ( m_peer
&& m_peer
->Ok() )
827 // in case the callback might be called during destruction
828 wxRemoveMacControlAssociation( this) ;
829 ::RemoveEventHandler( (EventHandlerRef
) m_macControlEventHandler
) ;
830 // we currently are not using this hook
831 // ::SetControlColorProc( *m_peer , NULL ) ;
835 if ( g_MacLastWindow
== this )
836 g_MacLastWindow
= NULL
;
838 #ifndef __WXUNIVERSAL__
839 wxFrame
* frame
= wxDynamicCast( wxGetTopLevelParent( (wxWindow
*)this ) , wxFrame
) ;
842 if ( frame
->GetLastFocus() == this )
843 frame
->SetLastFocus( NULL
) ;
847 // delete our drop target if we've got one
848 #if wxUSE_DRAG_AND_DROP
849 if ( m_dropTarget
!= NULL
)
859 WXWidget
wxWindowMac::GetHandle() const
861 return (WXWidget
) m_peer
->GetControlRef() ;
864 void wxWindowMac::MacInstallEventHandler( WXWidget control
)
866 wxAssociateControlWithMacControl( (ControlRef
) control
, this ) ;
867 InstallControlEventHandler( (ControlRef
)control
, GetwxMacWindowEventHandlerUPP(),
868 GetEventTypeCount(eventList
), eventList
, this,
869 (EventHandlerRef
*)&m_macControlEventHandler
);
873 bool wxWindowMac::Create(wxWindowMac
*parent
,
878 const wxString
& name
)
880 wxCHECK_MSG( parent
, false, wxT("can't create wxWindowMac without parent") );
882 if ( !CreateBase(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
) )
885 m_windowVariant
= parent
->GetWindowVariant() ;
887 if ( m_macIsUserPane
)
889 Rect bounds
= wxMacGetBoundsForControl( this , pos
, size
) ;
892 | kControlSupportsEmbedding
893 | kControlSupportsLiveFeedback
894 | kControlGetsFocusOnClick
895 // | kControlHasSpecialBackground
896 // | kControlSupportsCalcBestRect
897 | kControlHandlesTracking
898 | kControlSupportsFocus
899 | kControlWantsActivate
900 | kControlWantsIdle
;
902 m_peer
= new wxMacControl(this) ;
903 OSStatus err
=::CreateUserPaneControl( MAC_WXHWND(GetParent()->MacGetTopLevelWindowRef()) , &bounds
, features
, m_peer
->GetControlRefAddr() );
906 MacPostControlCreate(pos
, size
) ;
909 #ifndef __WXUNIVERSAL__
910 // Don't give scrollbars to wxControls unless they ask for them
911 if ( (! IsKindOf(CLASSINFO(wxControl
)) && ! IsKindOf(CLASSINFO(wxStatusBar
)))
912 || (IsKindOf(CLASSINFO(wxControl
)) && ((style
& wxHSCROLL
) || (style
& wxVSCROLL
))))
914 MacCreateScrollBars( style
) ;
918 wxWindowCreateEvent
event(this);
919 GetEventHandler()->AddPendingEvent(event
);
924 void wxWindowMac::MacChildAdded()
927 m_vScrollBar
->Raise() ;
929 m_hScrollBar
->Raise() ;
932 void wxWindowMac::MacPostControlCreate(const wxPoint
& WXUNUSED(pos
), const wxSize
& size
)
934 wxASSERT_MSG( m_peer
!= NULL
&& m_peer
->Ok() , wxT("No valid mac control") ) ;
936 m_peer
->SetReference( (URefCon
) this ) ;
937 GetParent()->AddChild( this );
939 MacInstallEventHandler( (WXWidget
) m_peer
->GetControlRef() );
941 ControlRef container
= (ControlRef
) GetParent()->GetHandle() ;
942 wxASSERT_MSG( container
!= NULL
, wxT("No valid mac container control") ) ;
943 ::EmbedControl( m_peer
->GetControlRef() , container
) ;
944 GetParent()->MacChildAdded() ;
946 // adjust font, controlsize etc
947 DoSetWindowVariant( m_windowVariant
) ;
949 m_peer
->SetLabel( wxStripMenuCodes(m_label
, wxStrip_Mnemonics
) ) ;
951 if (!m_macIsUserPane
)
952 SetInitialSize(size
);
954 SetCursor( *wxSTANDARD_CURSOR
) ;
957 void wxWindowMac::DoSetWindowVariant( wxWindowVariant variant
)
959 // Don't assert, in case we set the window variant before
960 // the window is created
961 // wxASSERT( m_peer->Ok() ) ;
963 m_windowVariant
= variant
;
965 if (m_peer
== NULL
|| !m_peer
->Ok())
969 ThemeFontID themeFont
= kThemeSystemFont
;
971 // we will get that from the settings later
972 // and make this NORMAL later, but first
973 // we have a few calculations that we must fix
977 case wxWINDOW_VARIANT_NORMAL
:
978 size
= kControlSizeNormal
;
979 themeFont
= kThemeSystemFont
;
982 case wxWINDOW_VARIANT_SMALL
:
983 size
= kControlSizeSmall
;
984 themeFont
= kThemeSmallSystemFont
;
987 case wxWINDOW_VARIANT_MINI
:
988 // not always defined in the headers
993 case wxWINDOW_VARIANT_LARGE
:
994 size
= kControlSizeLarge
;
995 themeFont
= kThemeSystemFont
;
999 wxFAIL_MSG(_T("unexpected window variant"));
1003 m_peer
->SetData
<ControlSize
>(kControlEntireControl
, kControlSizeTag
, &size
) ;
1006 font
.MacCreateThemeFont( themeFont
) ;
1010 void wxWindowMac::MacUpdateControlFont()
1012 m_peer
->SetFont( GetFont() , GetForegroundColour() , GetWindowStyle() ) ;
1013 // do not trigger refreshes upon invisible and possible partly created objects
1014 if ( MacIsReallyShown() )
1018 bool wxWindowMac::SetFont(const wxFont
& font
)
1020 bool retval
= wxWindowBase::SetFont( font
);
1022 MacUpdateControlFont() ;
1027 bool wxWindowMac::SetForegroundColour(const wxColour
& col
)
1029 bool retval
= wxWindowBase::SetForegroundColour( col
);
1032 MacUpdateControlFont();
1037 bool wxWindowMac::SetBackgroundColour(const wxColour
& col
)
1039 if ( !wxWindowBase::SetBackgroundColour(col
) && m_hasBgCol
)
1042 m_peer
->SetBackgroundColour( col
) ;
1047 bool wxWindowMac::MacCanFocus() const
1049 // TODO : evaluate performance hits by looking up this value, eventually cache the results for a 1 sec or so
1050 // CAUTION : the value returned currently is 0 or 2, I've also found values of 1 having the same meaning,
1051 // but the value range is nowhere documented
1052 Boolean keyExistsAndHasValidFormat
;
1053 CFIndex fullKeyboardAccess
= CFPreferencesGetAppIntegerValue( CFSTR("AppleKeyboardUIMode" ) ,
1054 kCFPreferencesCurrentApplication
, &keyExistsAndHasValidFormat
);
1056 if ( keyExistsAndHasValidFormat
&& fullKeyboardAccess
> 0 )
1062 UInt32 features
= 0 ;
1063 m_peer
->GetFeatures( &features
) ;
1065 return features
& ( kControlSupportsFocus
| kControlGetsFocusOnClick
) ;
1069 void wxWindowMac::SetFocus()
1071 if ( !AcceptsFocus() )
1074 wxWindow
* former
= FindFocus() ;
1075 if ( former
== this )
1078 // as we cannot rely on the control features to find out whether we are in full keyboard mode,
1079 // we can only leave in case of an error
1080 OSStatus err
= m_peer
->SetFocus( kControlFocusNextPart
) ;
1081 if ( err
== errCouldntSetFocus
)
1084 SetUserFocusWindow( (WindowRef
)MacGetTopLevelWindowRef() );
1087 void wxWindowMac::DoCaptureMouse()
1089 wxApp::s_captureWindow
= this ;
1092 wxWindow
* wxWindowBase::GetCapture()
1094 return wxApp::s_captureWindow
;
1097 void wxWindowMac::DoReleaseMouse()
1099 wxApp::s_captureWindow
= NULL
;
1102 #if wxUSE_DRAG_AND_DROP
1104 void wxWindowMac::SetDropTarget(wxDropTarget
*pDropTarget
)
1106 if ( m_dropTarget
!= NULL
)
1107 delete m_dropTarget
;
1109 m_dropTarget
= pDropTarget
;
1110 if ( m_dropTarget
!= NULL
)
1118 // Old-style File Manager Drag & Drop
1119 void wxWindowMac::DragAcceptFiles(bool WXUNUSED(accept
))
1124 // Returns the size of the native control. In the case of the toplevel window
1125 // this is the content area root control
1127 void wxWindowMac::MacGetPositionAndSizeFromControl(int& WXUNUSED(x
),
1130 int& WXUNUSED(h
)) const
1132 wxFAIL_MSG( wxT("Not currently supported") ) ;
1135 // From a wx position / size calculate the appropriate size of the native control
1137 bool wxWindowMac::MacGetBoundsForControl(
1141 int& w
, int& h
, bool adjustOrigin
) const
1143 // the desired size, minus the border pixels gives the correct size of the control
1147 // TODO: the default calls may be used as soon as PostCreateControl Is moved here
1148 w
= wxMax(size
.x
, 0) ; // WidthDefault( size.x );
1149 h
= wxMax(size
.y
, 0) ; // HeightDefault( size.y ) ;
1151 x
+= MacGetLeftBorderSize() ;
1152 y
+= MacGetTopBorderSize() ;
1153 w
-= MacGetLeftBorderSize() + MacGetRightBorderSize() ;
1154 h
-= MacGetTopBorderSize() + MacGetBottomBorderSize() ;
1157 AdjustForParentClientOrigin( x
, y
) ;
1159 // this is in window relative coordinate, as this parent may have a border, its physical position is offset by this border
1160 if ( !GetParent()->IsTopLevel() )
1162 x
-= GetParent()->MacGetLeftBorderSize() ;
1163 y
-= GetParent()->MacGetTopBorderSize() ;
1169 // Get window size (not client size)
1170 void wxWindowMac::DoGetSize(int *x
, int *y
) const
1173 m_peer
->GetRect( &bounds
) ;
1176 *x
= bounds
.right
- bounds
.left
+ MacGetLeftBorderSize() + MacGetRightBorderSize() ;
1178 *y
= bounds
.bottom
- bounds
.top
+ MacGetTopBorderSize() + MacGetBottomBorderSize() ;
1181 // get the position of the bounds of this window in client coordinates of its parent
1182 void wxWindowMac::DoGetPosition(int *x
, int *y
) const
1185 m_peer
->GetRect( &bounds
) ;
1187 int x1
= bounds
.left
;
1188 int y1
= bounds
.top
;
1190 // get the wx window position from the native one
1191 x1
-= MacGetLeftBorderSize() ;
1192 y1
-= MacGetTopBorderSize() ;
1194 if ( !IsTopLevel() )
1196 wxWindow
*parent
= GetParent();
1199 // we must first adjust it to be in window coordinates of the parent,
1200 // as otherwise it gets lost by the ClientAreaOrigin fix
1201 x1
+= parent
->MacGetLeftBorderSize() ;
1202 y1
+= parent
->MacGetTopBorderSize() ;
1204 // and now to client coordinates
1205 wxPoint
pt(parent
->GetClientAreaOrigin());
1217 void wxWindowMac::DoScreenToClient(int *x
, int *y
) const
1219 WindowRef window
= (WindowRef
) MacGetTopLevelWindowRef() ;
1220 wxCHECK_RET( window
, wxT("TopLevel Window missing") ) ;
1222 Point localwhere
= { 0, 0 } ;
1229 wxMacGlobalToLocal( window
, &localwhere
) ;
1236 MacRootWindowToWindow( x
, y
) ;
1238 wxPoint origin
= GetClientAreaOrigin() ;
1245 void wxWindowMac::DoClientToScreen(int *x
, int *y
) const
1247 WindowRef window
= (WindowRef
) MacGetTopLevelWindowRef() ;
1248 wxCHECK_RET( window
, wxT("TopLevel window missing") ) ;
1250 wxPoint origin
= GetClientAreaOrigin() ;
1256 MacWindowToRootWindow( x
, y
) ;
1258 Point localwhere
= { 0, 0 };
1264 wxMacLocalToGlobal( window
, &localwhere
) ;
1272 void wxWindowMac::MacClientToRootWindow( int *x
, int *y
) const
1274 wxPoint origin
= GetClientAreaOrigin() ;
1280 MacWindowToRootWindow( x
, y
) ;
1283 void wxWindowMac::MacRootWindowToClient( int *x
, int *y
) const
1285 MacRootWindowToWindow( x
, y
) ;
1287 wxPoint origin
= GetClientAreaOrigin() ;
1294 void wxWindowMac::MacWindowToRootWindow( int *x
, int *y
) const
1303 if ( !IsTopLevel() )
1305 wxTopLevelWindowMac
* top
= MacGetTopLevelWindow();
1308 pt
.x
-= MacGetLeftBorderSize() ;
1309 pt
.y
-= MacGetTopBorderSize() ;
1310 wxMacControl::Convert( &pt
, m_peer
, top
->m_peer
) ;
1320 void wxWindowMac::MacWindowToRootWindow( short *x
, short *y
) const
1329 MacWindowToRootWindow( &x1
, &y1
) ;
1337 void wxWindowMac::MacRootWindowToWindow( int *x
, int *y
) const
1346 if ( !IsTopLevel() )
1348 wxTopLevelWindowMac
* top
= MacGetTopLevelWindow();
1351 wxMacControl::Convert( &pt
, top
->m_peer
, m_peer
) ;
1352 pt
.x
+= MacGetLeftBorderSize() ;
1353 pt
.y
+= MacGetTopBorderSize() ;
1363 void wxWindowMac::MacRootWindowToWindow( short *x
, short *y
) const
1372 MacRootWindowToWindow( &x1
, &y1
) ;
1380 void wxWindowMac::MacGetContentAreaInset( int &left
, int &top
, int &right
, int &bottom
)
1382 RgnHandle rgn
= NewRgn() ;
1384 if ( m_peer
->GetRegion( kControlContentMetaPart
, rgn
) == noErr
)
1386 Rect structure
, content
;
1388 GetRegionBounds( rgn
, &content
) ;
1389 m_peer
->GetRect( &structure
) ;
1390 OffsetRect( &structure
, -structure
.left
, -structure
.top
) ;
1392 left
= content
.left
- structure
.left
;
1393 top
= content
.top
- structure
.top
;
1394 right
= structure
.right
- content
.right
;
1395 bottom
= structure
.bottom
- content
.bottom
;
1399 left
= top
= right
= bottom
= 0 ;
1405 wxSize
wxWindowMac::DoGetSizeFromClientSize( const wxSize
& size
) const
1407 wxSize sizeTotal
= size
;
1409 RgnHandle rgn
= NewRgn() ;
1410 if ( m_peer
->GetRegion( kControlContentMetaPart
, rgn
) == noErr
)
1412 Rect content
, structure
;
1413 GetRegionBounds( rgn
, &content
) ;
1414 m_peer
->GetRect( &structure
) ;
1416 // structure is in parent coordinates, but we only need width and height, so it's ok
1418 sizeTotal
.x
+= (structure
.right
- structure
.left
) - (content
.right
- content
.left
) ;
1419 sizeTotal
.y
+= (structure
.bottom
- structure
.top
) - (content
.bottom
- content
.top
) ;
1424 sizeTotal
.x
+= MacGetLeftBorderSize() + MacGetRightBorderSize() ;
1425 sizeTotal
.y
+= MacGetTopBorderSize() + MacGetBottomBorderSize() ;
1430 // Get size *available for subwindows* i.e. excluding menu bar etc.
1431 void wxWindowMac::DoGetClientSize( int *x
, int *y
) const
1435 RgnHandle rgn
= NewRgn() ;
1437 if ( m_peer
->GetRegion( kControlContentMetaPart
, rgn
) == noErr
)
1438 GetRegionBounds( rgn
, &content
) ;
1440 m_peer
->GetRect( &content
) ;
1443 ww
= content
.right
- content
.left
;
1444 hh
= content
.bottom
- content
.top
;
1446 if (m_hScrollBar
&& m_hScrollBar
->IsShown() )
1447 hh
-= m_hScrollBar
->GetSize().y
;
1449 if (m_vScrollBar
&& m_vScrollBar
->IsShown() )
1450 ww
-= m_vScrollBar
->GetSize().x
;
1458 bool wxWindowMac::SetCursor(const wxCursor
& cursor
)
1460 if (m_cursor
.IsSameAs(cursor
))
1465 if ( ! wxWindowBase::SetCursor( *wxSTANDARD_CURSOR
) )
1470 if ( ! wxWindowBase::SetCursor( cursor
) )
1474 wxASSERT_MSG( m_cursor
.Ok(),
1475 wxT("cursor must be valid after call to the base version"));
1477 wxWindowMac
*mouseWin
= 0 ;
1479 wxTopLevelWindowMac
*tlw
= MacGetTopLevelWindow() ;
1480 WindowRef window
= (WindowRef
) ( tlw
? tlw
->MacGetWindowRef() : 0 ) ;
1482 ControlPartCode part
;
1483 ControlRef control
;
1485 #if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
1487 HIGetMousePosition(kHICoordSpaceWindow
, window
, &hiPoint
);
1491 GetGlobalMouse( &pt
);
1494 ScreenToClient(&x
, &y
);
1498 control
= FindControlUnderMouse( pt
, window
, &part
) ;
1500 mouseWin
= wxFindControlFromMacControl( control
) ;
1504 if ( mouseWin
== this && !wxIsBusy() )
1505 m_cursor
.MacInstall() ;
1511 bool wxWindowMac::DoPopupMenu(wxMenu
*menu
, int x
, int y
)
1513 #ifndef __WXUNIVERSAL__
1514 menu
->SetInvokingWindow((wxWindow
*)this);
1517 if ( x
== wxDefaultCoord
&& y
== wxDefaultCoord
)
1519 wxPoint mouse
= wxGetMousePosition();
1525 ClientToScreen( &x
, &y
) ;
1528 menu
->MacBeforeDisplay( true ) ;
1529 long menuResult
= ::PopUpMenuSelect((MenuHandle
) menu
->GetHMenu() , y
, x
, 0) ;
1530 if ( HiWord(menuResult
) != 0 )
1533 GetMenuItemCommandID( GetMenuHandle(HiWord(menuResult
)) , LoWord(menuResult
) , &macid
);
1534 int id
= wxMacCommandToId( macid
);
1535 wxMenuItem
* item
= NULL
;
1537 item
= menu
->FindItem( id
, &realmenu
) ;
1540 if (item
->IsCheckable())
1541 item
->Check( !item
->IsChecked() ) ;
1543 menu
->SendEvent( id
, item
->IsCheckable() ? item
->IsChecked() : -1 ) ;
1547 menu
->MacAfterDisplay( true ) ;
1548 menu
->SetInvokingWindow( NULL
);
1552 // actually this shouldn't be called, because universal is having its own implementation
1558 // ----------------------------------------------------------------------------
1560 // ----------------------------------------------------------------------------
1564 void wxWindowMac::DoSetToolTip(wxToolTip
*tooltip
)
1566 wxWindowBase::DoSetToolTip(tooltip
);
1569 m_tooltip
->SetWindow(this);
1574 void wxWindowMac::MacInvalidateBorders()
1576 if ( m_peer
== NULL
)
1579 bool vis
= MacIsReallyShown() ;
1583 int outerBorder
= MacGetLeftBorderSize() ;
1584 if ( m_peer
->NeedsFocusRect() && m_peer
->HasFocus() )
1587 if ( outerBorder
== 0 )
1590 // now we know that we have something to do at all
1592 // as the borders are drawn on the parent we have to properly invalidate all these areas
1593 RgnHandle updateInner
, updateOuter
;
1596 // this rectangle is in HIViewCoordinates under OSX and in Window Coordinates under Carbon
1597 updateInner
= NewRgn() ;
1598 updateOuter
= NewRgn() ;
1600 m_peer
->GetRect( &rect
) ;
1601 RectRgn( updateInner
, &rect
) ;
1602 InsetRect( &rect
, -outerBorder
, -outerBorder
) ;
1603 RectRgn( updateOuter
, &rect
) ;
1604 DiffRgn( updateOuter
, updateInner
, updateOuter
) ;
1606 GetParent()->m_peer
->SetNeedsDisplay( updateOuter
) ;
1608 DisposeRgn( updateOuter
) ;
1609 DisposeRgn( updateInner
) ;
1612 void wxWindowMac::DoMoveWindow(int x
, int y
, int width
, int height
)
1614 // this is never called for a toplevel window, so we know we have a parent
1615 int former_x
, former_y
, former_w
, former_h
;
1617 // Get true coordinates of former position
1618 DoGetPosition( &former_x
, &former_y
) ;
1619 DoGetSize( &former_w
, &former_h
) ;
1621 wxWindow
*parent
= GetParent();
1624 wxPoint
pt(parent
->GetClientAreaOrigin());
1629 int actualWidth
= width
;
1630 int actualHeight
= height
;
1634 if ((m_minWidth
!= -1) && (actualWidth
< m_minWidth
))
1635 actualWidth
= m_minWidth
;
1636 if ((m_minHeight
!= -1) && (actualHeight
< m_minHeight
))
1637 actualHeight
= m_minHeight
;
1638 if ((m_maxWidth
!= -1) && (actualWidth
> m_maxWidth
))
1639 actualWidth
= m_maxWidth
;
1640 if ((m_maxHeight
!= -1) && (actualHeight
> m_maxHeight
))
1641 actualHeight
= m_maxHeight
;
1643 bool doMove
= false, doResize
= false ;
1645 if ( actualX
!= former_x
|| actualY
!= former_y
)
1648 if ( actualWidth
!= former_w
|| actualHeight
!= former_h
)
1651 if ( doMove
|| doResize
)
1653 // as the borders are drawn outside the native control, we adjust now
1655 wxRect
bounds( wxPoint( actualX
+ MacGetLeftBorderSize() ,actualY
+ MacGetTopBorderSize() ),
1656 wxSize( actualWidth
- (MacGetLeftBorderSize() + MacGetRightBorderSize()) ,
1657 actualHeight
- (MacGetTopBorderSize() + MacGetBottomBorderSize()) ) ) ;
1660 wxMacRectToNative( &bounds
, &r
) ;
1662 if ( !GetParent()->IsTopLevel() )
1663 wxMacWindowToNative( GetParent() , &r
) ;
1665 MacInvalidateBorders() ;
1667 m_cachedClippedRectValid
= false ;
1668 m_peer
->SetRect( &r
) ;
1670 wxWindowMac::MacSuperChangedPosition() ; // like this only children will be notified
1672 MacInvalidateBorders() ;
1674 MacRepositionScrollBars() ;
1677 wxPoint
point(actualX
, actualY
);
1678 wxMoveEvent
event(point
, m_windowId
);
1679 event
.SetEventObject(this);
1680 GetEventHandler()->ProcessEvent(event
) ;
1685 MacRepositionScrollBars() ;
1686 wxSize
size(actualWidth
, actualHeight
);
1687 wxSizeEvent
event(size
, m_windowId
);
1688 event
.SetEventObject(this);
1689 GetEventHandler()->ProcessEvent(event
);
1694 wxSize
wxWindowMac::DoGetBestSize() const
1696 if ( m_macIsUserPane
|| IsTopLevel() )
1697 return wxWindowBase::DoGetBestSize() ;
1699 Rect bestsize
= { 0 , 0 , 0 , 0 } ;
1700 int bestWidth
, bestHeight
;
1702 m_peer
->GetBestRect( &bestsize
) ;
1703 if ( EmptyRect( &bestsize
) )
1708 bestsize
.bottom
= 16 ;
1710 if ( IsKindOf( CLASSINFO( wxScrollBar
) ) )
1712 bestsize
.bottom
= 16 ;
1715 else if ( IsKindOf( CLASSINFO( wxSpinButton
) ) )
1717 bestsize
.bottom
= 24 ;
1722 // return wxWindowBase::DoGetBestSize() ;
1726 bestWidth
= bestsize
.right
- bestsize
.left
;
1727 bestHeight
= bestsize
.bottom
- bestsize
.top
;
1728 if ( bestHeight
< 10 )
1731 return wxSize(bestWidth
, bestHeight
);
1734 // set the size of the window: if the dimensions are positive, just use them,
1735 // but if any of them is equal to -1, it means that we must find the value for
1736 // it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in
1737 // which case -1 is a valid value for x and y)
1739 // If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate
1740 // the width/height to best suit our contents, otherwise we reuse the current
1742 void wxWindowMac::DoSetSize(int x
, int y
, int width
, int height
, int sizeFlags
)
1744 // get the current size and position...
1745 int currentX
, currentY
;
1746 int currentW
, currentH
;
1748 GetPosition(¤tX
, ¤tY
);
1749 GetSize(¤tW
, ¤tH
);
1751 // ... and don't do anything (avoiding flicker) if it's already ok
1752 if ( x
== currentX
&& y
== currentY
&&
1753 width
== currentW
&& height
== currentH
&& ( height
!= -1 && width
!= -1 ) )
1756 MacRepositionScrollBars() ; // we might have a real position shift
1761 if ( !(sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) )
1763 if ( x
== wxDefaultCoord
)
1765 if ( y
== wxDefaultCoord
)
1769 AdjustForParentClientOrigin( x
, y
, sizeFlags
);
1771 wxSize size
= wxDefaultSize
;
1772 if ( width
== wxDefaultCoord
)
1774 if ( sizeFlags
& wxSIZE_AUTO_WIDTH
)
1776 size
= DoGetBestSize();
1781 // just take the current one
1786 if ( height
== wxDefaultCoord
)
1788 if ( sizeFlags
& wxSIZE_AUTO_HEIGHT
)
1790 if ( size
.x
== wxDefaultCoord
)
1791 size
= DoGetBestSize();
1792 // else: already called DoGetBestSize() above
1798 // just take the current one
1803 DoMoveWindow( x
, y
, width
, height
);
1806 wxPoint
wxWindowMac::GetClientAreaOrigin() const
1808 RgnHandle rgn
= NewRgn() ;
1810 if ( m_peer
->GetRegion( kControlContentMetaPart
, rgn
) == noErr
)
1812 GetRegionBounds( rgn
, &content
) ;
1822 return wxPoint( content
.left
+ MacGetLeftBorderSize() , content
.top
+ MacGetTopBorderSize() );
1825 void wxWindowMac::DoSetClientSize(int clientwidth
, int clientheight
)
1827 if ( clientwidth
!= wxDefaultCoord
|| clientheight
!= wxDefaultCoord
)
1829 int currentclientwidth
, currentclientheight
;
1830 int currentwidth
, currentheight
;
1832 GetClientSize( ¤tclientwidth
, ¤tclientheight
) ;
1833 GetSize( ¤twidth
, ¤theight
) ;
1835 DoSetSize( wxDefaultCoord
, wxDefaultCoord
, currentwidth
+ clientwidth
- currentclientwidth
,
1836 currentheight
+ clientheight
- currentclientheight
, wxSIZE_USE_EXISTING
) ;
1840 void wxWindowMac::SetLabel(const wxString
& title
)
1844 if ( m_peer
&& m_peer
->Ok() )
1845 m_peer
->SetLabel( wxStripMenuCodes(m_label
, wxStrip_Mnemonics
) ) ;
1847 // do not trigger refreshes upon invisible and possible partly created objects
1848 if ( MacIsReallyShown() )
1852 wxString
wxWindowMac::GetLabel() const
1857 bool wxWindowMac::Show(bool show
)
1859 if ( !wxWindowBase::Show(show
) )
1863 m_peer
->SetVisibility( show
, true ) ;
1868 void wxWindowMac::DoEnable(bool enable
)
1870 m_peer
->Enable( enable
) ;
1874 // status change notifications
1877 void wxWindowMac::MacVisibilityChanged()
1881 void wxWindowMac::MacHiliteChanged()
1885 void wxWindowMac::MacEnabledStateChanged()
1887 OnEnabled( m_peer
->IsEnabled() );
1891 // status queries on the inherited window's state
1894 bool wxWindowMac::MacIsReallyShown()
1896 // only under OSX the visibility of the TLW is taken into account
1897 if ( m_isBeingDeleted
)
1900 #if TARGET_API_MAC_OSX
1901 if ( m_peer
&& m_peer
->Ok() )
1902 return m_peer
->IsVisible();
1905 wxWindow
* win
= this ;
1906 while ( win
->IsShown() )
1908 if ( win
->IsTopLevel() )
1911 win
= win
->GetParent() ;
1919 bool wxWindowMac::MacIsReallyEnabled()
1921 return m_peer
->IsEnabled() ;
1924 bool wxWindowMac::MacIsReallyHilited()
1926 return m_peer
->IsActive();
1929 void wxWindowMac::MacFlashInvalidAreas()
1931 #if TARGET_API_MAC_OSX
1932 HIViewFlashDirtyArea( (WindowRef
) MacGetTopLevelWindowRef() ) ;
1936 int wxWindowMac::GetCharHeight() const
1938 wxClientDC
dc( (wxWindowMac
*)this ) ;
1940 return dc
.GetCharHeight() ;
1943 int wxWindowMac::GetCharWidth() const
1945 wxClientDC
dc( (wxWindowMac
*)this ) ;
1947 return dc
.GetCharWidth() ;
1950 void wxWindowMac::GetTextExtent(const wxString
& string
, int *x
, int *y
,
1951 int *descent
, int *externalLeading
, const wxFont
*theFont
) const
1953 const wxFont
*fontToUse
= theFont
;
1955 fontToUse
= &m_font
;
1957 wxClientDC
dc( (wxWindowMac
*) this ) ;
1958 wxCoord lx
,ly
,ld
,le
;
1959 dc
.GetTextExtent( string
, &lx
, &ly
, &ld
, &le
, (wxFont
*)fontToUse
) ;
1960 if ( externalLeading
)
1961 *externalLeading
= le
;
1971 * Rect is given in client coordinates, for further reading, read wxTopLevelWindowMac::InvalidateRect
1972 * we always intersect with the entire window, not only with the client area
1975 void wxWindowMac::Refresh(bool WXUNUSED(eraseBack
), const wxRect
*rect
)
1977 if ( m_peer
== NULL
)
1980 if ( !MacIsReallyShown() )
1987 wxMacRectToNative( rect
, &r
) ;
1988 m_peer
->SetNeedsDisplay( &r
) ;
1992 m_peer
->SetNeedsDisplay() ;
1996 void wxWindowMac::Freeze()
1998 #if TARGET_API_MAC_OSX
1999 if ( !m_frozenness
++ )
2001 if ( m_peer
&& m_peer
->Ok() )
2002 m_peer
->SetDrawingEnabled( false ) ;
2007 void wxWindowMac::Thaw()
2009 #if TARGET_API_MAC_OSX
2010 wxASSERT_MSG( m_frozenness
> 0, wxT("Thaw() without matching Freeze()") );
2012 if ( !--m_frozenness
)
2014 if ( m_peer
&& m_peer
->Ok() )
2016 m_peer
->SetDrawingEnabled( true ) ;
2017 m_peer
->InvalidateWithChildren() ;
2023 bool wxWindowMac::IsFrozen() const
2025 return m_frozenness
!= 0;
2028 wxWindowMac
*wxGetActiveWindow()
2030 // actually this is a windows-only concept
2034 // Coordinates relative to the window
2035 void wxWindowMac::WarpPointer(int WXUNUSED(x_pos
), int WXUNUSED(y_pos
))
2037 // We really don't move the mouse programmatically under Mac.
2040 void wxWindowMac::OnEraseBackground(wxEraseEvent
& event
)
2042 if ( MacGetTopLevelWindow() == NULL
)
2045 #if TARGET_API_MAC_OSX
2046 if ( !m_backgroundColour.Ok() || GetBackgroundStyle() == wxBG_STYLE_TRANSPARENT )
2052 if ( GetBackgroundStyle() == wxBG_STYLE_COLOUR
)
2054 event
.GetDC()->Clear() ;
2062 void wxWindowMac::OnNcPaint( wxNcPaintEvent
& event
)
2067 int wxWindowMac::GetScrollPos(int orient
) const
2069 if ( orient
== wxHORIZONTAL
)
2072 return m_hScrollBar
->GetThumbPosition() ;
2077 return m_vScrollBar
->GetThumbPosition() ;
2083 // This now returns the whole range, not just the number
2084 // of positions that we can scroll.
2085 int wxWindowMac::GetScrollRange(int orient
) const
2087 if ( orient
== wxHORIZONTAL
)
2090 return m_hScrollBar
->GetRange() ;
2095 return m_vScrollBar
->GetRange() ;
2101 int wxWindowMac::GetScrollThumb(int orient
) const
2103 if ( orient
== wxHORIZONTAL
)
2106 return m_hScrollBar
->GetThumbSize() ;
2111 return m_vScrollBar
->GetThumbSize() ;
2117 void wxWindowMac::SetScrollPos(int orient
, int pos
, bool WXUNUSED(refresh
))
2119 if ( orient
== wxHORIZONTAL
)
2122 m_hScrollBar
->SetThumbPosition( pos
) ;
2127 m_vScrollBar
->SetThumbPosition( pos
) ;
2132 wxWindowMac::AlwaysShowScrollbars(bool hflag
, bool vflag
)
2134 bool needVisibilityUpdate
= false;
2136 if ( m_hScrollBarAlwaysShown
!= hflag
)
2138 m_hScrollBarAlwaysShown
= hflag
;
2139 needVisibilityUpdate
= true;
2142 if ( m_vScrollBarAlwaysShown
!= vflag
)
2144 m_vScrollBarAlwaysShown
= vflag
;
2145 needVisibilityUpdate
= true;
2148 if ( needVisibilityUpdate
)
2149 DoUpdateScrollbarVisibility();
2153 // we draw borders and grow boxes, are already set up and clipped in the current port / cgContextRef
2154 // our own window origin is at leftOrigin/rightOrigin
2157 void wxWindowMac::MacPaintGrowBox()
2162 if ( MacHasScrollBarCorner() )
2166 CGContextRef cgContext
= (CGContextRef
) MacGetCGContextRef() ;
2167 wxASSERT( cgContext
) ;
2169 m_peer
->GetRect( &rect
) ;
2171 int size
= m_hScrollBar
? m_hScrollBar
->GetSize().y
: ( m_vScrollBar
? m_vScrollBar
->GetSize().x
: MAC_SCROLLBAR_SIZE
) ;
2172 CGRect cgrect
= CGRectMake( rect
.right
- size
, rect
.bottom
- size
, size
, size
) ;
2173 CGPoint cgpoint
= CGPointMake( rect
.right
- size
, rect
.bottom
- size
) ;
2174 CGContextSaveGState( cgContext
);
2176 if ( m_backgroundColour
.Ok() )
2178 CGContextSetFillColorWithColor( cgContext
, m_backgroundColour
.GetCGColor() );
2182 CGContextSetRGBFillColor( cgContext
, 1.0, 1.0 , 1.0 , 1.0 );
2184 CGContextFillRect( cgContext
, cgrect
);
2185 CGContextRestoreGState( cgContext
);
2189 void wxWindowMac::MacPaintBorders( int WXUNUSED(leftOrigin
) , int WXUNUSED(rightOrigin
) )
2195 bool hasFocus
= m_peer
->NeedsFocusRect() && m_peer
->HasFocus() ;
2197 // back to the surrounding frame rectangle
2198 m_peer
->GetRect( &rect
) ;
2199 InsetRect( &rect
, -1 , -1 ) ;
2202 CGRect cgrect
= CGRectMake( rect
.left
, rect
.top
, rect
.right
- rect
.left
,
2203 rect
.bottom
- rect
.top
) ;
2205 HIThemeFrameDrawInfo info
;
2206 memset( &info
, 0 , sizeof(info
) ) ;
2210 info
.state
= IsEnabled() ? kThemeStateActive
: kThemeStateInactive
;
2211 info
.isFocused
= hasFocus
;
2213 CGContextRef cgContext
= (CGContextRef
) GetParent()->MacGetCGContextRef() ;
2214 wxASSERT( cgContext
) ;
2216 if ( HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
) || HasFlag(wxDOUBLE_BORDER
) )
2218 info
.kind
= kHIThemeFrameTextFieldSquare
;
2219 HIThemeDrawFrame( &cgrect
, &info
, cgContext
, kHIThemeOrientationNormal
) ;
2221 else if ( HasFlag(wxSIMPLE_BORDER
) )
2223 info
.kind
= kHIThemeFrameListBox
;
2224 HIThemeDrawFrame( &cgrect
, &info
, cgContext
, kHIThemeOrientationNormal
) ;
2226 else if ( hasFocus
)
2228 HIThemeDrawFocusRect( &cgrect
, true , cgContext
, kHIThemeOrientationNormal
) ;
2230 #if 0 // TODO REMOVE now done in a separate call earlier in drawing the window itself
2231 m_peer
->GetRect( &rect
) ;
2232 if ( MacHasScrollBarCorner() )
2234 int variant
= (m_hScrollBar
== NULL
? m_vScrollBar
: m_hScrollBar
) ->GetWindowVariant();
2235 int size
= m_hScrollBar
? m_hScrollBar
->GetSize().y
: ( m_vScrollBar
? m_vScrollBar
->GetSize().x
: MAC_SCROLLBAR_SIZE
) ;
2236 CGRect cgrect
= CGRectMake( rect
.right
- size
, rect
.bottom
- size
, size
, size
) ;
2237 CGPoint cgpoint
= CGPointMake( rect
.right
- size
, rect
.bottom
- size
) ;
2238 HIThemeGrowBoxDrawInfo info
;
2239 memset( &info
, 0, sizeof(info
) ) ;
2241 info
.state
= IsEnabled() ? kThemeStateActive
: kThemeStateInactive
;
2242 info
.kind
= kHIThemeGrowBoxKindNone
;
2243 // contrary to the docs ...SizeSmall does not work
2244 info
.size
= kHIThemeGrowBoxSizeNormal
;
2245 info
.direction
= 0 ;
2246 HIThemeDrawGrowBox( &cgpoint
, &info
, cgContext
, kHIThemeOrientationNormal
) ;
2252 void wxWindowMac::RemoveChild( wxWindowBase
*child
)
2254 if ( child
== m_hScrollBar
)
2255 m_hScrollBar
= NULL
;
2256 if ( child
== m_vScrollBar
)
2257 m_vScrollBar
= NULL
;
2259 wxWindowBase::RemoveChild( child
) ;
2262 void wxWindowMac::DoUpdateScrollbarVisibility()
2264 bool triggerSizeEvent
= false;
2268 bool showHScrollBar
= m_hScrollBarAlwaysShown
|| m_hScrollBar
->IsNeeded();
2270 if ( m_hScrollBar
->IsShown() != showHScrollBar
)
2272 m_hScrollBar
->Show( showHScrollBar
);
2273 triggerSizeEvent
= true;
2279 bool showVScrollBar
= m_vScrollBarAlwaysShown
|| m_vScrollBar
->IsNeeded();
2281 if ( m_vScrollBar
->IsShown() != showVScrollBar
)
2283 m_vScrollBar
->Show( showVScrollBar
) ;
2284 triggerSizeEvent
= true;
2288 MacRepositionScrollBars() ;
2289 if ( triggerSizeEvent
)
2291 wxSizeEvent
event(GetSize(), m_windowId
);
2292 event
.SetEventObject(this);
2293 GetEventHandler()->ProcessEvent(event
);
2297 // New function that will replace some of the above.
2298 void wxWindowMac::SetScrollbar(int orient
, int pos
, int thumb
,
2299 int range
, bool refresh
)
2301 if ( orient
== wxHORIZONTAL
&& m_hScrollBar
)
2302 m_hScrollBar
->SetScrollbar(pos
, thumb
, range
, thumb
, refresh
);
2303 else if ( orient
== wxVERTICAL
&& m_vScrollBar
)
2304 m_vScrollBar
->SetScrollbar(pos
, thumb
, range
, thumb
, refresh
);
2306 DoUpdateScrollbarVisibility();
2309 // Does a physical scroll
2310 void wxWindowMac::ScrollWindow(int dx
, int dy
, const wxRect
*rect
)
2312 if ( dx
== 0 && dy
== 0 )
2315 int width
, height
;
2316 GetClientSize( &width
, &height
) ;
2319 // note there currently is a bug in OSX which makes inefficient refreshes in case an entire control
2320 // area is scrolled, this does not occur if width and height are 2 pixels less,
2321 // TODO: write optimal workaround
2322 wxRect
scrollrect( MacGetLeftBorderSize() , MacGetTopBorderSize() , width
, height
) ;
2324 scrollrect
.Intersect( *rect
) ;
2326 if ( m_peer
->GetNeedsDisplay() )
2328 // because HIViewScrollRect does not scroll the already invalidated area we have two options:
2329 // in case there is already a pending redraw on that area
2330 // either immediate redraw or full invalidate
2332 // is the better overall solution, as it does not slow down scrolling
2333 m_peer
->SetNeedsDisplay() ;
2335 // this would be the preferred version for fast drawing controls
2336 HIViewRender(m_peer
->GetControlRef()) ;
2340 // as the native control might be not a 0/0 wx window coordinates, we have to offset
2341 scrollrect
.Offset( -MacGetLeftBorderSize() , -MacGetTopBorderSize() ) ;
2342 m_peer
->ScrollRect( &scrollrect
, dx
, dy
) ;
2345 // this would be the preferred version for fast drawing controls
2346 HIViewRender(m_peer
->GetControlRef()) ;
2352 for (wxWindowList::compatibility_iterator node
= GetChildren().GetFirst(); node
; node
= node
->GetNext())
2354 child
= node
->GetData();
2357 if (child
== m_vScrollBar
)
2359 if (child
== m_hScrollBar
)
2361 if (child
->IsTopLevel())
2364 child
->GetPosition( &x
, &y
);
2365 child
->GetSize( &w
, &h
);
2368 wxRect
rc( x
, y
, w
, h
);
2369 if (rect
->Intersects( rc
))
2370 child
->SetSize( x
+ dx
, y
+ dy
, w
, h
, wxSIZE_AUTO
|wxSIZE_ALLOW_MINUS_ONE
);
2374 child
->SetSize( x
+ dx
, y
+ dy
, w
, h
, wxSIZE_AUTO
|wxSIZE_ALLOW_MINUS_ONE
);
2379 void wxWindowMac::MacOnScroll( wxScrollEvent
&event
)
2381 if ( event
.GetEventObject() == m_vScrollBar
|| event
.GetEventObject() == m_hScrollBar
)
2383 wxScrollWinEvent wevent
;
2384 wevent
.SetPosition(event
.GetPosition());
2385 wevent
.SetOrientation(event
.GetOrientation());
2386 wevent
.SetEventObject(this);
2388 if (event
.GetEventType() == wxEVT_SCROLL_TOP
)
2389 wevent
.SetEventType( wxEVT_SCROLLWIN_TOP
);
2390 else if (event
.GetEventType() == wxEVT_SCROLL_BOTTOM
)
2391 wevent
.SetEventType( wxEVT_SCROLLWIN_BOTTOM
);
2392 else if (event
.GetEventType() == wxEVT_SCROLL_LINEUP
)
2393 wevent
.SetEventType( wxEVT_SCROLLWIN_LINEUP
);
2394 else if (event
.GetEventType() == wxEVT_SCROLL_LINEDOWN
)
2395 wevent
.SetEventType( wxEVT_SCROLLWIN_LINEDOWN
);
2396 else if (event
.GetEventType() == wxEVT_SCROLL_PAGEUP
)
2397 wevent
.SetEventType( wxEVT_SCROLLWIN_PAGEUP
);
2398 else if (event
.GetEventType() == wxEVT_SCROLL_PAGEDOWN
)
2399 wevent
.SetEventType( wxEVT_SCROLLWIN_PAGEDOWN
);
2400 else if (event
.GetEventType() == wxEVT_SCROLL_THUMBTRACK
)
2401 wevent
.SetEventType( wxEVT_SCROLLWIN_THUMBTRACK
);
2402 else if (event
.GetEventType() == wxEVT_SCROLL_THUMBRELEASE
)
2403 wevent
.SetEventType( wxEVT_SCROLLWIN_THUMBRELEASE
);
2405 GetEventHandler()->ProcessEvent(wevent
);
2409 // Get the window with the focus
2410 wxWindowMac
*wxWindowBase::DoFindFocus()
2412 ControlRef control
;
2413 GetKeyboardFocus( GetUserFocusWindow() , &control
) ;
2414 return wxFindControlFromMacControl( control
) ;
2417 void wxWindowMac::OnSetFocus( wxFocusEvent
& event
)
2419 // panel wants to track the window which was the last to have focus in it,
2420 // so we want to set ourselves as the window which last had focus
2422 // notice that it's also important to do it upwards the tree because
2423 // otherwise when the top level panel gets focus, it won't set it back to
2424 // us, but to some other sibling
2426 // CS: don't know if this is still needed:
2427 //wxChildFocusEvent eventFocus(this);
2428 //(void)GetEventHandler()->ProcessEvent(eventFocus);
2430 if ( MacGetTopLevelWindow() && m_peer
->NeedsFocusRect() )
2432 GetParent()->Refresh() ;
2433 wxMacWindowStateSaver
sv( this ) ;
2436 m_peer
->GetRect( &rect
) ;
2437 // auf den umgebenden Rahmen zurチᅡ゚ck
2438 InsetRect( &rect
, -1 , -1 ) ;
2440 wxTopLevelWindowMac
* top
= MacGetTopLevelWindow();
2444 wxMacControl::Convert( &pt
, GetParent()->m_peer
, top
->m_peer
) ;
2446 rect
.right
+= pt
.x
;
2448 rect
.bottom
+= pt
.y
;
2451 bool bIsFocusEvent
= (event
.GetEventType() == wxEVT_SET_FOCUS
);
2452 DrawThemeFocusRect( &rect
, bIsFocusEvent
) ;
2453 if ( !bIsFocusEvent
)
2455 // as this erases part of the frame we have to redraw borders
2456 // and because our z-ordering is not always correct (staticboxes)
2457 // we have to invalidate things, we cannot simple redraw
2458 MacInvalidateBorders() ;
2465 void wxWindowMac::OnInternalIdle()
2467 // This calls the UI-update mechanism (querying windows for
2468 // menu/toolbar/control state information)
2469 if (wxUpdateUIEvent::CanUpdate(this) && IsShown())
2470 UpdateWindowUI(wxUPDATE_UI_FROMIDLE
);
2473 // Raise the window to the top of the Z order
2474 void wxWindowMac::Raise()
2476 m_peer
->SetZOrder( true , NULL
) ;
2479 // Lower the window to the bottom of the Z order
2480 void wxWindowMac::Lower()
2482 m_peer
->SetZOrder( false , NULL
) ;
2485 // static wxWindow *gs_lastWhich = NULL;
2487 bool wxWindowMac::MacSetupCursor( const wxPoint
& pt
)
2489 // first trigger a set cursor event
2491 wxPoint clientorigin
= GetClientAreaOrigin() ;
2492 wxSize clientsize
= GetClientSize() ;
2494 if ( wxRect2DInt( clientorigin
.x
, clientorigin
.y
, clientsize
.x
, clientsize
.y
).Contains( wxPoint2DInt( pt
) ) )
2496 wxSetCursorEvent
event( pt
.x
, pt
.y
);
2498 bool processedEvtSetCursor
= GetEventHandler()->ProcessEvent(event
);
2499 if ( processedEvtSetCursor
&& event
.HasCursor() )
2501 cursor
= event
.GetCursor() ;
2505 // the test for processedEvtSetCursor is here to prevent using m_cursor
2506 // if the user code caught EVT_SET_CURSOR() and returned nothing from
2507 // it - this is a way to say that our cursor shouldn't be used for this
2509 if ( !processedEvtSetCursor
&& m_cursor
.Ok() )
2512 if ( !wxIsBusy() && !GetParent() )
2513 cursor
= *wxSTANDARD_CURSOR
;
2517 cursor
.MacInstall() ;
2520 return cursor
.Ok() ;
2523 wxString
wxWindowMac::MacGetToolTipString( wxPoint
&WXUNUSED(pt
) )
2527 return m_tooltip
->GetTip() ;
2530 return wxEmptyString
;
2533 void wxWindowMac::ClearBackground()
2539 void wxWindowMac::Update()
2541 wxTopLevelWindowMac
* top
= MacGetTopLevelWindow();
2543 top
->MacPerformUpdates() ;
2546 wxTopLevelWindowMac
* wxWindowMac::MacGetTopLevelWindow() const
2548 wxTopLevelWindowMac
* win
= NULL
;
2549 WindowRef window
= (WindowRef
) MacGetTopLevelWindowRef() ;
2551 win
= wxFindWinFromMacWindow( window
) ;
2556 const wxRect
& wxWindowMac::MacGetClippedClientRect() const
2558 MacUpdateClippedRects() ;
2560 return m_cachedClippedClientRect
;
2563 const wxRect
& wxWindowMac::MacGetClippedRect() const
2565 MacUpdateClippedRects() ;
2567 return m_cachedClippedRect
;
2570 const wxRect
&wxWindowMac:: MacGetClippedRectWithOuterStructure() const
2572 MacUpdateClippedRects() ;
2574 return m_cachedClippedRectWithOuterStructure
;
2577 const wxRegion
& wxWindowMac::MacGetVisibleRegion( bool includeOuterStructures
)
2579 static wxRegion emptyrgn
;
2581 if ( !m_isBeingDeleted
&& MacIsReallyShown() /*m_peer->IsVisible() */ )
2583 MacUpdateClippedRects() ;
2584 if ( includeOuterStructures
)
2585 return m_cachedClippedRegionWithOuterStructure
;
2587 return m_cachedClippedRegion
;
2595 void wxWindowMac::MacUpdateClippedRects() const
2597 if ( m_cachedClippedRectValid
)
2600 // includeOuterStructures is true if we try to draw somthing like a focus ring etc.
2601 // also a window dc uses this, in this case we only clip in the hierarchy for hard
2602 // borders like a scrollwindow, splitter etc otherwise we end up in a paranoia having
2603 // to add focus borders everywhere
2605 Rect r
, rIncludingOuterStructures
;
2607 m_peer
->GetRect( &r
) ;
2608 r
.left
-= MacGetLeftBorderSize() ;
2609 r
.top
-= MacGetTopBorderSize() ;
2610 r
.bottom
+= MacGetBottomBorderSize() ;
2611 r
.right
+= MacGetRightBorderSize() ;
2618 rIncludingOuterStructures
= r
;
2619 InsetRect( &rIncludingOuterStructures
, -4 , -4 ) ;
2621 wxRect cl
= GetClientRect() ;
2622 Rect rClient
= { cl
.y
, cl
.x
, cl
.y
+ cl
.height
, cl
.x
+ cl
.width
} ;
2626 const wxWindow
* child
= this ;
2627 const wxWindow
* parent
= NULL
;
2629 while ( !child
->IsTopLevel() && ( parent
= child
->GetParent() ) != NULL
)
2631 if ( parent
->MacIsChildOfClientArea(child
) )
2633 size
= parent
->GetClientSize() ;
2634 wxPoint origin
= parent
->GetClientAreaOrigin() ;
2640 // this will be true for scrollbars, toolbars etc.
2641 size
= parent
->GetSize() ;
2642 y
= parent
->MacGetTopBorderSize() ;
2643 x
= parent
->MacGetLeftBorderSize() ;
2644 size
.x
-= parent
->MacGetLeftBorderSize() + parent
->MacGetRightBorderSize() ;
2645 size
.y
-= parent
->MacGetTopBorderSize() + parent
->MacGetBottomBorderSize() ;
2648 parent
->MacWindowToRootWindow( &x
, &y
) ;
2649 MacRootWindowToWindow( &x
, &y
) ;
2651 Rect rparent
= { y
, x
, y
+ size
.y
, x
+ size
.x
} ;
2653 // the wxwindow and client rects will always be clipped
2654 SectRect( &r
, &rparent
, &r
) ;
2655 SectRect( &rClient
, &rparent
, &rClient
) ;
2657 // the structure only at 'hard' borders
2658 if ( parent
->MacClipChildren() ||
2659 ( parent
->GetParent() && parent
->GetParent()->MacClipGrandChildren() ) )
2661 SectRect( &rIncludingOuterStructures
, &rparent
, &rIncludingOuterStructures
) ;
2667 m_cachedClippedRect
= wxRect( r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
) ;
2668 m_cachedClippedClientRect
= wxRect( rClient
.left
, rClient
.top
,
2669 rClient
.right
- rClient
.left
, rClient
.bottom
- rClient
.top
) ;
2670 m_cachedClippedRectWithOuterStructure
= wxRect(
2671 rIncludingOuterStructures
.left
, rIncludingOuterStructures
.top
,
2672 rIncludingOuterStructures
.right
- rIncludingOuterStructures
.left
,
2673 rIncludingOuterStructures
.bottom
- rIncludingOuterStructures
.top
) ;
2675 m_cachedClippedRegionWithOuterStructure
= wxRegion( m_cachedClippedRectWithOuterStructure
) ;
2676 m_cachedClippedRegion
= wxRegion( m_cachedClippedRect
) ;
2677 m_cachedClippedClientRegion
= wxRegion( m_cachedClippedClientRect
) ;
2679 m_cachedClippedRectValid
= true ;
2683 This function must not change the updatergn !
2685 bool wxWindowMac::MacDoRedraw( void* updatergnr
, long time
)
2687 bool handled
= false ;
2689 RgnHandle updatergn
= (RgnHandle
) updatergnr
;
2690 GetRegionBounds( updatergn
, &updatebounds
) ;
2692 // wxLogDebug(wxT("update for %s bounds %d, %d, %d, %d"), wxString(GetClassInfo()->GetClassName()).c_str(), updatebounds.left, updatebounds.top , updatebounds.right , updatebounds.bottom ) ;
2694 if ( !EmptyRgn(updatergn
) )
2696 RgnHandle newupdate
= NewRgn() ;
2697 wxSize point
= GetClientSize() ;
2698 wxPoint origin
= GetClientAreaOrigin() ;
2699 SetRectRgn( newupdate
, origin
.x
, origin
.y
, origin
.x
+ point
.x
, origin
.y
+ point
.y
) ;
2700 SectRgn( newupdate
, updatergn
, newupdate
) ;
2702 // first send an erase event to the entire update area
2704 // for the toplevel window this really is the entire area
2705 // for all the others only their client area, otherwise they
2706 // might be drawing with full alpha and eg put blue into
2707 // the grow-box area of a scrolled window (scroll sample)
2708 wxDC
* dc
= new wxWindowDC(this);
2710 dc
->SetClippingRegion(wxRegion(HIShapeCreateWithQDRgn(updatergn
)));
2712 dc
->SetClippingRegion(wxRegion(HIShapeCreateWithQDRgn(newupdate
)));
2714 wxEraseEvent
eevent( GetId(), dc
);
2715 eevent
.SetEventObject( this );
2716 GetEventHandler()->ProcessEvent( eevent
);
2722 // calculate a client-origin version of the update rgn and set m_updateRegion to that
2723 OffsetRgn( newupdate
, -origin
.x
, -origin
.y
) ;
2724 m_updateRegion
= wxRegion(HIShapeCreateWithQDRgn(newupdate
)) ;
2725 DisposeRgn( newupdate
) ;
2727 if ( !m_updateRegion
.Empty() )
2729 // paint the window itself
2732 event
.SetTimestamp(time
);
2733 event
.SetEventObject(this);
2734 GetEventHandler()->ProcessEvent(event
);
2738 // now we cannot rely on having its borders drawn by a window itself, as it does not
2739 // get the updateRgn wide enough to always do so, so we do it from the parent
2740 // this would also be the place to draw any custom backgrounds for native controls
2741 // in Composited windowing
2742 wxPoint clientOrigin
= GetClientAreaOrigin() ;
2746 for (wxWindowList::compatibility_iterator node
= GetChildren().GetFirst(); node
; node
= node
->GetNext())
2748 child
= node
->GetData();
2751 if (child
== m_vScrollBar
)
2753 if (child
== m_hScrollBar
)
2755 if (child
->IsTopLevel())
2757 if (!child
->IsShown())
2760 // only draw those in the update region (add a safety margin of 10 pixels for shadow effects
2762 child
->GetPosition( &x
, &y
);
2763 child
->GetSize( &w
, &h
);
2764 Rect childRect
= { y
, x
, y
+ h
, x
+ w
} ;
2765 OffsetRect( &childRect
, clientOrigin
.x
, clientOrigin
.y
) ;
2766 InsetRect( &childRect
, -10 , -10) ;
2768 if ( RectInRgn( &childRect
, updatergn
) )
2770 // paint custom borders
2771 wxNcPaintEvent
eventNc( child
->GetId() );
2772 eventNc
.SetEventObject( child
);
2773 if ( !child
->GetEventHandler()->ProcessEvent( eventNc
) )
2775 child
->MacPaintBorders(0, 0) ;
2785 WXWindow
wxWindowMac::MacGetTopLevelWindowRef() const
2787 wxWindowMac
*iter
= (wxWindowMac
*)this ;
2791 if ( iter
->IsTopLevel() )
2793 wxTopLevelWindow
* toplevel
= wxDynamicCast(iter
,wxTopLevelWindow
);
2795 return toplevel
->MacGetWindowRef();
2797 wxPopupWindow
* popupwin
= wxDynamicCast(iter
,wxPopupWindow
);
2799 return popupwin
->MacGetPopupWindowRef();
2802 iter
= iter
->GetParent() ;
2808 bool wxWindowMac::MacHasScrollBarCorner() const
2810 /* Returns whether the scroll bars in a wxScrolledWindow should be
2811 * shortened. Scroll bars should be shortened if either:
2813 * - both scroll bars are visible, or
2815 * - there is a resize box in the parent frame's corner and this
2816 * window shares the bottom and right edge with the parent
2820 if ( m_hScrollBar
== NULL
&& m_vScrollBar
== NULL
)
2823 if ( ( m_hScrollBar
&& m_hScrollBar
->IsShown() )
2824 && ( m_vScrollBar
&& m_vScrollBar
->IsShown() ) )
2826 // Both scroll bars visible
2831 wxPoint thisWindowBottomRight
= GetScreenRect().GetBottomRight();
2833 for ( const wxWindow
*win
= this; win
; win
= win
->GetParent() )
2835 const wxFrame
*frame
= wxDynamicCast( win
, wxFrame
) ;
2838 if ( frame
->GetWindowStyleFlag() & wxRESIZE_BORDER
)
2840 // Parent frame has resize handle
2841 wxPoint frameBottomRight
= frame
->GetScreenRect().GetBottomRight();
2843 // Note: allow for some wiggle room here as wxMac's
2844 // window rect calculations seem to be imprecise
2845 if ( abs( thisWindowBottomRight
.x
- frameBottomRight
.x
) <= 2
2846 && abs( thisWindowBottomRight
.y
- frameBottomRight
.y
) <= 2 )
2848 // Parent frame has resize handle and shares
2849 // right bottom corner
2854 // Parent frame has resize handle but doesn't
2855 // share right bottom corner
2861 // Parent frame doesn't have resize handle
2867 // No parent frame found
2872 void wxWindowMac::MacCreateScrollBars( long style
)
2874 wxASSERT_MSG( m_vScrollBar
== NULL
&& m_hScrollBar
== NULL
, wxT("attempt to create window twice") ) ;
2876 if ( style
& ( wxVSCROLL
| wxHSCROLL
) )
2878 int scrlsize
= MAC_SCROLLBAR_SIZE
;
2879 if ( GetWindowVariant() == wxWINDOW_VARIANT_SMALL
|| GetWindowVariant() == wxWINDOW_VARIANT_MINI
)
2881 scrlsize
= MAC_SMALL_SCROLLBAR_SIZE
;
2884 int adjust
= MacHasScrollBarCorner() ? scrlsize
- 1: 0 ;
2886 GetClientSize( &width
, &height
) ;
2888 wxPoint
vPoint(width
- scrlsize
, 0) ;
2889 wxSize
vSize(scrlsize
, height
- adjust
) ;
2890 wxPoint
hPoint(0, height
- scrlsize
) ;
2891 wxSize
hSize(width
- adjust
, scrlsize
) ;
2893 // we have to set the min size to a smaller value, otherwise they cannot get smaller (InitialSize sets MinSize)
2894 if ( style
& wxVSCROLL
)
2896 m_vScrollBar
= new wxScrollBar((wxWindow
*)this, wxID_ANY
, vPoint
, vSize
, wxVERTICAL
);
2897 m_vScrollBar
->SetMinSize( wxDefaultSize
);
2900 if ( style
& wxHSCROLL
)
2902 m_hScrollBar
= new wxScrollBar((wxWindow
*)this, wxID_ANY
, hPoint
, hSize
, wxHORIZONTAL
);
2903 m_hScrollBar
->SetMinSize( wxDefaultSize
);
2907 // because the create does not take into account the client area origin
2908 // we might have a real position shift
2909 MacRepositionScrollBars() ;
2912 bool wxWindowMac::MacIsChildOfClientArea( const wxWindow
* child
) const
2914 bool result
= ((child
== NULL
) || ((child
!= m_hScrollBar
) && (child
!= m_vScrollBar
)));
2919 void wxWindowMac::MacRepositionScrollBars()
2921 if ( !m_hScrollBar
&& !m_vScrollBar
)
2924 int scrlsize
= m_hScrollBar
? m_hScrollBar
->GetSize().y
: ( m_vScrollBar
? m_vScrollBar
->GetSize().x
: MAC_SCROLLBAR_SIZE
) ;
2925 int adjust
= MacHasScrollBarCorner() ? scrlsize
- 1 : 0 ;
2927 // get real client area
2929 GetSize( &width
, &height
);
2931 width
-= MacGetLeftBorderSize() + MacGetRightBorderSize();
2932 height
-= MacGetTopBorderSize() + MacGetBottomBorderSize();
2934 wxPoint
vPoint( width
- scrlsize
, 0 ) ;
2935 wxSize
vSize( scrlsize
, height
- adjust
) ;
2936 wxPoint
hPoint( 0 , height
- scrlsize
) ;
2937 wxSize
hSize( width
- adjust
, scrlsize
) ;
2940 int x
= 0, y
= 0, w
, h
;
2941 GetSize( &w
, &h
) ;
2943 MacClientToRootWindow( &x
, &y
) ;
2944 MacClientToRootWindow( &w
, &h
) ;
2946 wxWindowMac
*iter
= (wxWindowMac
*)this ;
2948 int totW
= 10000 , totH
= 10000;
2951 if ( iter
->IsTopLevel() )
2953 iter
->GetSize( &totW
, &totH
) ;
2957 iter
= iter
->GetParent() ;
2971 if ( w
- x
>= totW
)
2976 if ( h
- y
>= totH
)
2984 m_vScrollBar
->SetSize( vPoint
.x
, vPoint
.y
, vSize
.x
, vSize
.y
, wxSIZE_ALLOW_MINUS_ONE
);
2986 m_hScrollBar
->SetSize( hPoint
.x
, hPoint
.y
, hSize
.x
, hSize
.y
, wxSIZE_ALLOW_MINUS_ONE
);
2989 bool wxWindowMac::AcceptsFocus() const
2991 return MacCanFocus() && wxWindowBase::AcceptsFocus();
2994 void wxWindowMac::MacSuperChangedPosition()
2996 // only window-absolute structures have to be moved i.e. controls
2998 m_cachedClippedRectValid
= false ;
3001 wxWindowList::compatibility_iterator node
= GetChildren().GetFirst();
3004 child
= node
->GetData();
3005 child
->MacSuperChangedPosition() ;
3007 node
= node
->GetNext();
3011 void wxWindowMac::MacTopLevelWindowChangedPosition()
3013 // only screen-absolute structures have to be moved i.e. glcanvas
3016 wxWindowList::compatibility_iterator node
= GetChildren().GetFirst();
3019 child
= node
->GetData();
3020 child
->MacTopLevelWindowChangedPosition() ;
3022 node
= node
->GetNext();
3026 long wxWindowMac::MacGetLeftBorderSize() const
3033 if (HasFlag(wxRAISED_BORDER
) || HasFlag( wxSUNKEN_BORDER
) || HasFlag(wxDOUBLE_BORDER
))
3035 // this metric is only the 'outset' outside the simple frame rect
3036 GetThemeMetric( kThemeMetricEditTextFrameOutset
, &border
) ;
3039 else if (HasFlag(wxSIMPLE_BORDER
))
3041 // this metric is only the 'outset' outside the simple frame rect
3042 GetThemeMetric( kThemeMetricListBoxFrameOutset
, &border
) ;
3049 long wxWindowMac::MacGetRightBorderSize() const
3051 // they are all symmetric in mac themes
3052 return MacGetLeftBorderSize() ;
3055 long wxWindowMac::MacGetTopBorderSize() const
3057 // they are all symmetric in mac themes
3058 return MacGetLeftBorderSize() ;
3061 long wxWindowMac::MacGetBottomBorderSize() const
3063 // they are all symmetric in mac themes
3064 return MacGetLeftBorderSize() ;
3067 long wxWindowMac::MacRemoveBordersFromStyle( long style
)
3069 return style
& ~wxBORDER_MASK
;
3072 // Find the wxWindowMac at the current mouse position, returning the mouse
3074 wxWindowMac
* wxFindWindowAtPointer( wxPoint
& pt
)
3076 pt
= wxGetMousePosition();
3077 wxWindowMac
* found
= wxFindWindowAtPoint(pt
);
3082 // Get the current mouse position.
3083 wxPoint
wxGetMousePosition()
3087 wxGetMousePosition( &x
, &y
);
3089 return wxPoint(x
, y
);
3092 void wxWindowMac::OnMouseEvent( wxMouseEvent
&event
)
3094 if ( event
.GetEventType() == wxEVT_RIGHT_DOWN
)
3096 // copied from wxGTK : CS
3097 // VZ: shouldn't we move this to base class then?
3099 // generate a "context menu" event: this is similar to wxEVT_RIGHT_DOWN
3102 // (a) it's a command event and so is propagated to the parent
3103 // (b) under MSW it can be generated from kbd too
3104 // (c) it uses screen coords (because of (a))
3105 wxContextMenuEvent
evtCtx(wxEVT_CONTEXT_MENU
,
3107 this->ClientToScreen(event
.GetPosition()));
3108 if ( ! GetEventHandler()->ProcessEvent(evtCtx
) )
3117 void wxWindowMac::OnPaint( wxPaintEvent
& WXUNUSED(event
) )
3119 if ( wxTheApp
->MacGetCurrentEvent() != NULL
&& wxTheApp
->MacGetCurrentEventHandlerCallRef() != NULL
3120 && GetBackgroundStyle() != wxBG_STYLE_TRANSPARENT
)
3121 CallNextEventHandler(
3122 (EventHandlerCallRef
)wxTheApp
->MacGetCurrentEventHandlerCallRef() ,
3123 (EventRef
) wxTheApp
->MacGetCurrentEvent() ) ;
3126 void wxWindowMac::MacHandleControlClick(WXWidget
WXUNUSED(control
),
3127 wxInt16
WXUNUSED(controlpart
),
3128 bool WXUNUSED(mouseStillDown
))
3132 Rect
wxMacGetBoundsForControl( wxWindow
* window
, const wxPoint
& pos
, const wxSize
&size
, bool adjustForOrigin
)
3136 window
->MacGetBoundsForControl( pos
, size
, x
, y
, w
, h
, adjustForOrigin
) ;
3137 Rect bounds
= { y
, x
, y
+ h
, x
+ w
};
3142 wxInt32
wxWindowMac::MacControlHit(WXEVENTHANDLERREF
WXUNUSED(handler
) , WXEVENTREF
WXUNUSED(event
) )
3144 return eventNotHandledErr
;
3147 bool wxWindowMac::Reparent(wxWindowBase
*newParentBase
)
3149 wxWindowMac
*newParent
= (wxWindowMac
*)newParentBase
;
3150 if ( !wxWindowBase::Reparent(newParent
) )
3153 // copied from MacPostControlCreate
3154 ControlRef container
= (ControlRef
) GetParent()->GetHandle() ;
3156 wxASSERT_MSG( container
!= NULL
, wxT("No valid mac container control") ) ;
3158 ::EmbedControl( m_peer
->GetControlRef() , container
) ;
3163 bool wxWindowMac::SetTransparent(wxByte alpha
)
3165 SetBackgroundStyle(wxBG_STYLE_TRANSPARENT
);
3167 if ( alpha
!= m_macAlpha
)
3169 m_macAlpha
= alpha
;
3176 bool wxWindowMac::CanSetTransparent()
3181 wxByte
wxWindowMac::GetTransparent() const