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
)
2053 event
.GetDC()->Clear() ;
2057 void wxWindowMac::OnNcPaint( wxNcPaintEvent
& event
)
2062 int wxWindowMac::GetScrollPos(int orient
) const
2064 if ( orient
== wxHORIZONTAL
)
2067 return m_hScrollBar
->GetThumbPosition() ;
2072 return m_vScrollBar
->GetThumbPosition() ;
2078 // This now returns the whole range, not just the number
2079 // of positions that we can scroll.
2080 int wxWindowMac::GetScrollRange(int orient
) const
2082 if ( orient
== wxHORIZONTAL
)
2085 return m_hScrollBar
->GetRange() ;
2090 return m_vScrollBar
->GetRange() ;
2096 int wxWindowMac::GetScrollThumb(int orient
) const
2098 if ( orient
== wxHORIZONTAL
)
2101 return m_hScrollBar
->GetThumbSize() ;
2106 return m_vScrollBar
->GetThumbSize() ;
2112 void wxWindowMac::SetScrollPos(int orient
, int pos
, bool WXUNUSED(refresh
))
2114 if ( orient
== wxHORIZONTAL
)
2117 m_hScrollBar
->SetThumbPosition( pos
) ;
2122 m_vScrollBar
->SetThumbPosition( pos
) ;
2127 wxWindowMac::AlwaysShowScrollbars(bool hflag
, bool vflag
)
2129 bool needVisibilityUpdate
= false;
2131 if ( m_hScrollBarAlwaysShown
!= hflag
)
2133 m_hScrollBarAlwaysShown
= hflag
;
2134 needVisibilityUpdate
= true;
2137 if ( m_vScrollBarAlwaysShown
!= vflag
)
2139 m_vScrollBarAlwaysShown
= vflag
;
2140 needVisibilityUpdate
= true;
2143 if ( needVisibilityUpdate
)
2144 DoUpdateScrollbarVisibility();
2148 // we draw borders and grow boxes, are already set up and clipped in the current port / cgContextRef
2149 // our own window origin is at leftOrigin/rightOrigin
2152 void wxWindowMac::MacPaintGrowBox()
2157 if ( MacHasScrollBarCorner() )
2161 CGContextRef cgContext
= (CGContextRef
) MacGetCGContextRef() ;
2162 wxASSERT( cgContext
) ;
2164 m_peer
->GetRect( &rect
) ;
2166 int size
= m_hScrollBar
? m_hScrollBar
->GetSize().y
: ( m_vScrollBar
? m_vScrollBar
->GetSize().x
: MAC_SCROLLBAR_SIZE
) ;
2167 CGRect cgrect
= CGRectMake( rect
.right
- size
, rect
.bottom
- size
, size
, size
) ;
2168 CGPoint cgpoint
= CGPointMake( rect
.right
- size
, rect
.bottom
- size
) ;
2169 CGContextSaveGState( cgContext
);
2171 if ( m_backgroundColour
.Ok() )
2173 CGContextSetFillColorWithColor( cgContext
, m_backgroundColour
.GetCGColor() );
2177 CGContextSetRGBFillColor( cgContext
, 1.0, 1.0 , 1.0 , 1.0 );
2179 CGContextFillRect( cgContext
, cgrect
);
2180 CGContextRestoreGState( cgContext
);
2184 void wxWindowMac::MacPaintBorders( int WXUNUSED(leftOrigin
) , int WXUNUSED(rightOrigin
) )
2190 bool hasFocus
= m_peer
->NeedsFocusRect() && m_peer
->HasFocus() ;
2192 // back to the surrounding frame rectangle
2193 m_peer
->GetRect( &rect
) ;
2194 InsetRect( &rect
, -1 , -1 ) ;
2197 CGRect cgrect
= CGRectMake( rect
.left
, rect
.top
, rect
.right
- rect
.left
,
2198 rect
.bottom
- rect
.top
) ;
2200 HIThemeFrameDrawInfo info
;
2201 memset( &info
, 0 , sizeof(info
) ) ;
2205 info
.state
= IsEnabled() ? kThemeStateActive
: kThemeStateInactive
;
2206 info
.isFocused
= hasFocus
;
2208 CGContextRef cgContext
= (CGContextRef
) GetParent()->MacGetCGContextRef() ;
2209 wxASSERT( cgContext
) ;
2211 if ( HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
) || HasFlag(wxDOUBLE_BORDER
) )
2213 info
.kind
= kHIThemeFrameTextFieldSquare
;
2214 HIThemeDrawFrame( &cgrect
, &info
, cgContext
, kHIThemeOrientationNormal
) ;
2216 else if ( HasFlag(wxSIMPLE_BORDER
) )
2218 info
.kind
= kHIThemeFrameListBox
;
2219 HIThemeDrawFrame( &cgrect
, &info
, cgContext
, kHIThemeOrientationNormal
) ;
2221 else if ( hasFocus
)
2223 HIThemeDrawFocusRect( &cgrect
, true , cgContext
, kHIThemeOrientationNormal
) ;
2225 #if 0 // TODO REMOVE now done in a separate call earlier in drawing the window itself
2226 m_peer
->GetRect( &rect
) ;
2227 if ( MacHasScrollBarCorner() )
2229 int variant
= (m_hScrollBar
== NULL
? m_vScrollBar
: m_hScrollBar
) ->GetWindowVariant();
2230 int size
= m_hScrollBar
? m_hScrollBar
->GetSize().y
: ( m_vScrollBar
? m_vScrollBar
->GetSize().x
: MAC_SCROLLBAR_SIZE
) ;
2231 CGRect cgrect
= CGRectMake( rect
.right
- size
, rect
.bottom
- size
, size
, size
) ;
2232 CGPoint cgpoint
= CGPointMake( rect
.right
- size
, rect
.bottom
- size
) ;
2233 HIThemeGrowBoxDrawInfo info
;
2234 memset( &info
, 0, sizeof(info
) ) ;
2236 info
.state
= IsEnabled() ? kThemeStateActive
: kThemeStateInactive
;
2237 info
.kind
= kHIThemeGrowBoxKindNone
;
2238 // contrary to the docs ...SizeSmall does not work
2239 info
.size
= kHIThemeGrowBoxSizeNormal
;
2240 info
.direction
= 0 ;
2241 HIThemeDrawGrowBox( &cgpoint
, &info
, cgContext
, kHIThemeOrientationNormal
) ;
2247 void wxWindowMac::RemoveChild( wxWindowBase
*child
)
2249 if ( child
== m_hScrollBar
)
2250 m_hScrollBar
= NULL
;
2251 if ( child
== m_vScrollBar
)
2252 m_vScrollBar
= NULL
;
2254 wxWindowBase::RemoveChild( child
) ;
2257 void wxWindowMac::DoUpdateScrollbarVisibility()
2259 bool triggerSizeEvent
= false;
2263 bool showHScrollBar
= m_hScrollBarAlwaysShown
|| m_hScrollBar
->IsNeeded();
2265 if ( m_hScrollBar
->IsShown() != showHScrollBar
)
2267 m_hScrollBar
->Show( showHScrollBar
);
2268 triggerSizeEvent
= true;
2274 bool showVScrollBar
= m_vScrollBarAlwaysShown
|| m_vScrollBar
->IsNeeded();
2276 if ( m_vScrollBar
->IsShown() != showVScrollBar
)
2278 m_vScrollBar
->Show( showVScrollBar
) ;
2279 triggerSizeEvent
= true;
2283 MacRepositionScrollBars() ;
2284 if ( triggerSizeEvent
)
2286 wxSizeEvent
event(GetSize(), m_windowId
);
2287 event
.SetEventObject(this);
2288 GetEventHandler()->ProcessEvent(event
);
2292 // New function that will replace some of the above.
2293 void wxWindowMac::SetScrollbar(int orient
, int pos
, int thumb
,
2294 int range
, bool refresh
)
2296 if ( orient
== wxHORIZONTAL
&& m_hScrollBar
)
2297 m_hScrollBar
->SetScrollbar(pos
, thumb
, range
, thumb
, refresh
);
2298 else if ( orient
== wxVERTICAL
&& m_vScrollBar
)
2299 m_vScrollBar
->SetScrollbar(pos
, thumb
, range
, thumb
, refresh
);
2301 DoUpdateScrollbarVisibility();
2304 // Does a physical scroll
2305 void wxWindowMac::ScrollWindow(int dx
, int dy
, const wxRect
*rect
)
2307 if ( dx
== 0 && dy
== 0 )
2310 int width
, height
;
2311 GetClientSize( &width
, &height
) ;
2314 // note there currently is a bug in OSX which makes inefficient refreshes in case an entire control
2315 // area is scrolled, this does not occur if width and height are 2 pixels less,
2316 // TODO: write optimal workaround
2317 wxRect
scrollrect( MacGetLeftBorderSize() , MacGetTopBorderSize() , width
, height
) ;
2319 scrollrect
.Intersect( *rect
) ;
2321 if ( m_peer
->GetNeedsDisplay() )
2323 // because HIViewScrollRect does not scroll the already invalidated area we have two options:
2324 // in case there is already a pending redraw on that area
2325 // either immediate redraw or full invalidate
2327 // is the better overall solution, as it does not slow down scrolling
2328 m_peer
->SetNeedsDisplay() ;
2330 // this would be the preferred version for fast drawing controls
2331 HIViewRender(m_peer
->GetControlRef()) ;
2335 // as the native control might be not a 0/0 wx window coordinates, we have to offset
2336 scrollrect
.Offset( -MacGetLeftBorderSize() , -MacGetTopBorderSize() ) ;
2337 m_peer
->ScrollRect( &scrollrect
, dx
, dy
) ;
2340 // this would be the preferred version for fast drawing controls
2341 HIViewRender(m_peer
->GetControlRef()) ;
2347 for (wxWindowList::compatibility_iterator node
= GetChildren().GetFirst(); node
; node
= node
->GetNext())
2349 child
= node
->GetData();
2352 if (child
== m_vScrollBar
)
2354 if (child
== m_hScrollBar
)
2356 if (child
->IsTopLevel())
2359 child
->GetPosition( &x
, &y
);
2360 child
->GetSize( &w
, &h
);
2363 wxRect
rc( x
, y
, w
, h
);
2364 if (rect
->Intersects( rc
))
2365 child
->SetSize( x
+ dx
, y
+ dy
, w
, h
, wxSIZE_AUTO
|wxSIZE_ALLOW_MINUS_ONE
);
2369 child
->SetSize( x
+ dx
, y
+ dy
, w
, h
, wxSIZE_AUTO
|wxSIZE_ALLOW_MINUS_ONE
);
2374 void wxWindowMac::MacOnScroll( wxScrollEvent
&event
)
2376 if ( event
.GetEventObject() == m_vScrollBar
|| event
.GetEventObject() == m_hScrollBar
)
2378 wxScrollWinEvent wevent
;
2379 wevent
.SetPosition(event
.GetPosition());
2380 wevent
.SetOrientation(event
.GetOrientation());
2381 wevent
.SetEventObject(this);
2383 if (event
.GetEventType() == wxEVT_SCROLL_TOP
)
2384 wevent
.SetEventType( wxEVT_SCROLLWIN_TOP
);
2385 else if (event
.GetEventType() == wxEVT_SCROLL_BOTTOM
)
2386 wevent
.SetEventType( wxEVT_SCROLLWIN_BOTTOM
);
2387 else if (event
.GetEventType() == wxEVT_SCROLL_LINEUP
)
2388 wevent
.SetEventType( wxEVT_SCROLLWIN_LINEUP
);
2389 else if (event
.GetEventType() == wxEVT_SCROLL_LINEDOWN
)
2390 wevent
.SetEventType( wxEVT_SCROLLWIN_LINEDOWN
);
2391 else if (event
.GetEventType() == wxEVT_SCROLL_PAGEUP
)
2392 wevent
.SetEventType( wxEVT_SCROLLWIN_PAGEUP
);
2393 else if (event
.GetEventType() == wxEVT_SCROLL_PAGEDOWN
)
2394 wevent
.SetEventType( wxEVT_SCROLLWIN_PAGEDOWN
);
2395 else if (event
.GetEventType() == wxEVT_SCROLL_THUMBTRACK
)
2396 wevent
.SetEventType( wxEVT_SCROLLWIN_THUMBTRACK
);
2397 else if (event
.GetEventType() == wxEVT_SCROLL_THUMBRELEASE
)
2398 wevent
.SetEventType( wxEVT_SCROLLWIN_THUMBRELEASE
);
2400 GetEventHandler()->ProcessEvent(wevent
);
2404 // Get the window with the focus
2405 wxWindowMac
*wxWindowBase::DoFindFocus()
2407 ControlRef control
;
2408 GetKeyboardFocus( GetUserFocusWindow() , &control
) ;
2409 return wxFindControlFromMacControl( control
) ;
2412 void wxWindowMac::OnSetFocus( wxFocusEvent
& event
)
2414 // panel wants to track the window which was the last to have focus in it,
2415 // so we want to set ourselves as the window which last had focus
2417 // notice that it's also important to do it upwards the tree because
2418 // otherwise when the top level panel gets focus, it won't set it back to
2419 // us, but to some other sibling
2421 // CS: don't know if this is still needed:
2422 //wxChildFocusEvent eventFocus(this);
2423 //(void)GetEventHandler()->ProcessEvent(eventFocus);
2425 if ( MacGetTopLevelWindow() && m_peer
->NeedsFocusRect() )
2427 GetParent()->Refresh() ;
2428 wxMacWindowStateSaver
sv( this ) ;
2431 m_peer
->GetRect( &rect
) ;
2432 // auf den umgebenden Rahmen zurチᅡ゚ck
2433 InsetRect( &rect
, -1 , -1 ) ;
2435 wxTopLevelWindowMac
* top
= MacGetTopLevelWindow();
2439 wxMacControl::Convert( &pt
, GetParent()->m_peer
, top
->m_peer
) ;
2441 rect
.right
+= pt
.x
;
2443 rect
.bottom
+= pt
.y
;
2446 bool bIsFocusEvent
= (event
.GetEventType() == wxEVT_SET_FOCUS
);
2447 DrawThemeFocusRect( &rect
, bIsFocusEvent
) ;
2448 if ( !bIsFocusEvent
)
2450 // as this erases part of the frame we have to redraw borders
2451 // and because our z-ordering is not always correct (staticboxes)
2452 // we have to invalidate things, we cannot simple redraw
2453 MacInvalidateBorders() ;
2460 void wxWindowMac::OnInternalIdle()
2462 // This calls the UI-update mechanism (querying windows for
2463 // menu/toolbar/control state information)
2464 if (wxUpdateUIEvent::CanUpdate(this) && IsShown())
2465 UpdateWindowUI(wxUPDATE_UI_FROMIDLE
);
2468 // Raise the window to the top of the Z order
2469 void wxWindowMac::Raise()
2471 m_peer
->SetZOrder( true , NULL
) ;
2474 // Lower the window to the bottom of the Z order
2475 void wxWindowMac::Lower()
2477 m_peer
->SetZOrder( false , NULL
) ;
2480 // static wxWindow *gs_lastWhich = NULL;
2482 bool wxWindowMac::MacSetupCursor( const wxPoint
& pt
)
2484 // first trigger a set cursor event
2486 wxPoint clientorigin
= GetClientAreaOrigin() ;
2487 wxSize clientsize
= GetClientSize() ;
2489 if ( wxRect2DInt( clientorigin
.x
, clientorigin
.y
, clientsize
.x
, clientsize
.y
).Contains( wxPoint2DInt( pt
) ) )
2491 wxSetCursorEvent
event( pt
.x
, pt
.y
);
2493 bool processedEvtSetCursor
= GetEventHandler()->ProcessEvent(event
);
2494 if ( processedEvtSetCursor
&& event
.HasCursor() )
2496 cursor
= event
.GetCursor() ;
2500 // the test for processedEvtSetCursor is here to prevent using m_cursor
2501 // if the user code caught EVT_SET_CURSOR() and returned nothing from
2502 // it - this is a way to say that our cursor shouldn't be used for this
2504 if ( !processedEvtSetCursor
&& m_cursor
.Ok() )
2507 if ( !wxIsBusy() && !GetParent() )
2508 cursor
= *wxSTANDARD_CURSOR
;
2512 cursor
.MacInstall() ;
2515 return cursor
.Ok() ;
2518 wxString
wxWindowMac::MacGetToolTipString( wxPoint
&WXUNUSED(pt
) )
2522 return m_tooltip
->GetTip() ;
2525 return wxEmptyString
;
2528 void wxWindowMac::ClearBackground()
2534 void wxWindowMac::Update()
2536 wxTopLevelWindowMac
* top
= MacGetTopLevelWindow();
2538 top
->MacPerformUpdates() ;
2541 wxTopLevelWindowMac
* wxWindowMac::MacGetTopLevelWindow() const
2543 wxTopLevelWindowMac
* win
= NULL
;
2544 WindowRef window
= (WindowRef
) MacGetTopLevelWindowRef() ;
2546 win
= wxFindWinFromMacWindow( window
) ;
2551 const wxRect
& wxWindowMac::MacGetClippedClientRect() const
2553 MacUpdateClippedRects() ;
2555 return m_cachedClippedClientRect
;
2558 const wxRect
& wxWindowMac::MacGetClippedRect() const
2560 MacUpdateClippedRects() ;
2562 return m_cachedClippedRect
;
2565 const wxRect
&wxWindowMac:: MacGetClippedRectWithOuterStructure() const
2567 MacUpdateClippedRects() ;
2569 return m_cachedClippedRectWithOuterStructure
;
2572 const wxRegion
& wxWindowMac::MacGetVisibleRegion( bool includeOuterStructures
)
2574 static wxRegion emptyrgn
;
2576 if ( !m_isBeingDeleted
&& MacIsReallyShown() /*m_peer->IsVisible() */ )
2578 MacUpdateClippedRects() ;
2579 if ( includeOuterStructures
)
2580 return m_cachedClippedRegionWithOuterStructure
;
2582 return m_cachedClippedRegion
;
2590 void wxWindowMac::MacUpdateClippedRects() const
2592 if ( m_cachedClippedRectValid
)
2595 // includeOuterStructures is true if we try to draw somthing like a focus ring etc.
2596 // also a window dc uses this, in this case we only clip in the hierarchy for hard
2597 // borders like a scrollwindow, splitter etc otherwise we end up in a paranoia having
2598 // to add focus borders everywhere
2600 Rect r
, rIncludingOuterStructures
;
2602 m_peer
->GetRect( &r
) ;
2603 r
.left
-= MacGetLeftBorderSize() ;
2604 r
.top
-= MacGetTopBorderSize() ;
2605 r
.bottom
+= MacGetBottomBorderSize() ;
2606 r
.right
+= MacGetRightBorderSize() ;
2613 rIncludingOuterStructures
= r
;
2614 InsetRect( &rIncludingOuterStructures
, -4 , -4 ) ;
2616 wxRect cl
= GetClientRect() ;
2617 Rect rClient
= { cl
.y
, cl
.x
, cl
.y
+ cl
.height
, cl
.x
+ cl
.width
} ;
2621 const wxWindow
* child
= this ;
2622 const wxWindow
* parent
= NULL
;
2624 while ( !child
->IsTopLevel() && ( parent
= child
->GetParent() ) != NULL
)
2626 if ( parent
->MacIsChildOfClientArea(child
) )
2628 size
= parent
->GetClientSize() ;
2629 wxPoint origin
= parent
->GetClientAreaOrigin() ;
2635 // this will be true for scrollbars, toolbars etc.
2636 size
= parent
->GetSize() ;
2637 y
= parent
->MacGetTopBorderSize() ;
2638 x
= parent
->MacGetLeftBorderSize() ;
2639 size
.x
-= parent
->MacGetLeftBorderSize() + parent
->MacGetRightBorderSize() ;
2640 size
.y
-= parent
->MacGetTopBorderSize() + parent
->MacGetBottomBorderSize() ;
2643 parent
->MacWindowToRootWindow( &x
, &y
) ;
2644 MacRootWindowToWindow( &x
, &y
) ;
2646 Rect rparent
= { y
, x
, y
+ size
.y
, x
+ size
.x
} ;
2648 // the wxwindow and client rects will always be clipped
2649 SectRect( &r
, &rparent
, &r
) ;
2650 SectRect( &rClient
, &rparent
, &rClient
) ;
2652 // the structure only at 'hard' borders
2653 if ( parent
->MacClipChildren() ||
2654 ( parent
->GetParent() && parent
->GetParent()->MacClipGrandChildren() ) )
2656 SectRect( &rIncludingOuterStructures
, &rparent
, &rIncludingOuterStructures
) ;
2662 m_cachedClippedRect
= wxRect( r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
) ;
2663 m_cachedClippedClientRect
= wxRect( rClient
.left
, rClient
.top
,
2664 rClient
.right
- rClient
.left
, rClient
.bottom
- rClient
.top
) ;
2665 m_cachedClippedRectWithOuterStructure
= wxRect(
2666 rIncludingOuterStructures
.left
, rIncludingOuterStructures
.top
,
2667 rIncludingOuterStructures
.right
- rIncludingOuterStructures
.left
,
2668 rIncludingOuterStructures
.bottom
- rIncludingOuterStructures
.top
) ;
2670 m_cachedClippedRegionWithOuterStructure
= wxRegion( m_cachedClippedRectWithOuterStructure
) ;
2671 m_cachedClippedRegion
= wxRegion( m_cachedClippedRect
) ;
2672 m_cachedClippedClientRegion
= wxRegion( m_cachedClippedClientRect
) ;
2674 m_cachedClippedRectValid
= true ;
2678 This function must not change the updatergn !
2680 bool wxWindowMac::MacDoRedraw( void* updatergnr
, long time
)
2682 bool handled
= false ;
2684 RgnHandle updatergn
= (RgnHandle
) updatergnr
;
2685 GetRegionBounds( updatergn
, &updatebounds
) ;
2687 // wxLogDebug(wxT("update for %s bounds %d, %d, %d, %d"), wxString(GetClassInfo()->GetClassName()).c_str(), updatebounds.left, updatebounds.top , updatebounds.right , updatebounds.bottom ) ;
2689 if ( !EmptyRgn(updatergn
) )
2691 RgnHandle newupdate
= NewRgn() ;
2692 wxSize point
= GetClientSize() ;
2693 wxPoint origin
= GetClientAreaOrigin() ;
2694 SetRectRgn( newupdate
, origin
.x
, origin
.y
, origin
.x
+ point
.x
, origin
.y
+ point
.y
) ;
2695 SectRgn( newupdate
, updatergn
, newupdate
) ;
2697 // first send an erase event to the entire update area
2699 // for the toplevel window this really is the entire area
2700 // for all the others only their client area, otherwise they
2701 // might be drawing with full alpha and eg put blue into
2702 // the grow-box area of a scrolled window (scroll sample)
2703 wxDC
* dc
= new wxWindowDC(this);
2705 dc
->SetClippingRegion(wxRegion(HIShapeCreateWithQDRgn(updatergn
)));
2707 dc
->SetClippingRegion(wxRegion(HIShapeCreateWithQDRgn(newupdate
)));
2709 wxEraseEvent
eevent( GetId(), dc
);
2710 eevent
.SetEventObject( this );
2711 GetEventHandler()->ProcessEvent( eevent
);
2717 // calculate a client-origin version of the update rgn and set m_updateRegion to that
2718 OffsetRgn( newupdate
, -origin
.x
, -origin
.y
) ;
2719 m_updateRegion
= wxRegion(HIShapeCreateWithQDRgn(newupdate
)) ;
2720 DisposeRgn( newupdate
) ;
2722 if ( !m_updateRegion
.Empty() )
2724 // paint the window itself
2727 event
.SetTimestamp(time
);
2728 event
.SetEventObject(this);
2729 GetEventHandler()->ProcessEvent(event
);
2733 // now we cannot rely on having its borders drawn by a window itself, as it does not
2734 // get the updateRgn wide enough to always do so, so we do it from the parent
2735 // this would also be the place to draw any custom backgrounds for native controls
2736 // in Composited windowing
2737 wxPoint clientOrigin
= GetClientAreaOrigin() ;
2741 for (wxWindowList::compatibility_iterator node
= GetChildren().GetFirst(); node
; node
= node
->GetNext())
2743 child
= node
->GetData();
2746 if (child
== m_vScrollBar
)
2748 if (child
== m_hScrollBar
)
2750 if (child
->IsTopLevel())
2752 if (!child
->IsShown())
2755 // only draw those in the update region (add a safety margin of 10 pixels for shadow effects
2757 child
->GetPosition( &x
, &y
);
2758 child
->GetSize( &w
, &h
);
2759 Rect childRect
= { y
, x
, y
+ h
, x
+ w
} ;
2760 OffsetRect( &childRect
, clientOrigin
.x
, clientOrigin
.y
) ;
2761 InsetRect( &childRect
, -10 , -10) ;
2763 if ( RectInRgn( &childRect
, updatergn
) )
2765 // paint custom borders
2766 wxNcPaintEvent
eventNc( child
->GetId() );
2767 eventNc
.SetEventObject( child
);
2768 if ( !child
->GetEventHandler()->ProcessEvent( eventNc
) )
2770 child
->MacPaintBorders(0, 0) ;
2780 WXWindow
wxWindowMac::MacGetTopLevelWindowRef() const
2782 wxWindowMac
*iter
= (wxWindowMac
*)this ;
2786 if ( iter
->IsTopLevel() )
2788 wxTopLevelWindow
* toplevel
= wxDynamicCast(iter
,wxTopLevelWindow
);
2790 return toplevel
->MacGetWindowRef();
2792 wxPopupWindow
* popupwin
= wxDynamicCast(iter
,wxPopupWindow
);
2794 return popupwin
->MacGetPopupWindowRef();
2797 iter
= iter
->GetParent() ;
2803 bool wxWindowMac::MacHasScrollBarCorner() const
2805 /* Returns whether the scroll bars in a wxScrolledWindow should be
2806 * shortened. Scroll bars should be shortened if either:
2808 * - both scroll bars are visible, or
2810 * - there is a resize box in the parent frame's corner and this
2811 * window shares the bottom and right edge with the parent
2815 if ( m_hScrollBar
== NULL
&& m_vScrollBar
== NULL
)
2818 if ( ( m_hScrollBar
&& m_hScrollBar
->IsShown() )
2819 && ( m_vScrollBar
&& m_vScrollBar
->IsShown() ) )
2821 // Both scroll bars visible
2826 wxPoint thisWindowBottomRight
= GetScreenRect().GetBottomRight();
2828 for ( const wxWindow
*win
= this; win
; win
= win
->GetParent() )
2830 const wxFrame
*frame
= wxDynamicCast( win
, wxFrame
) ;
2833 if ( frame
->GetWindowStyleFlag() & wxRESIZE_BORDER
)
2835 // Parent frame has resize handle
2836 wxPoint frameBottomRight
= frame
->GetScreenRect().GetBottomRight();
2838 // Note: allow for some wiggle room here as wxMac's
2839 // window rect calculations seem to be imprecise
2840 if ( abs( thisWindowBottomRight
.x
- frameBottomRight
.x
) <= 2
2841 && abs( thisWindowBottomRight
.y
- frameBottomRight
.y
) <= 2 )
2843 // Parent frame has resize handle and shares
2844 // right bottom corner
2849 // Parent frame has resize handle but doesn't
2850 // share right bottom corner
2856 // Parent frame doesn't have resize handle
2862 // No parent frame found
2867 void wxWindowMac::MacCreateScrollBars( long style
)
2869 wxASSERT_MSG( m_vScrollBar
== NULL
&& m_hScrollBar
== NULL
, wxT("attempt to create window twice") ) ;
2871 if ( style
& ( wxVSCROLL
| wxHSCROLL
) )
2873 int scrlsize
= MAC_SCROLLBAR_SIZE
;
2874 if ( GetWindowVariant() == wxWINDOW_VARIANT_SMALL
|| GetWindowVariant() == wxWINDOW_VARIANT_MINI
)
2876 scrlsize
= MAC_SMALL_SCROLLBAR_SIZE
;
2879 int adjust
= MacHasScrollBarCorner() ? scrlsize
- 1: 0 ;
2881 GetClientSize( &width
, &height
) ;
2883 wxPoint
vPoint(width
- scrlsize
, 0) ;
2884 wxSize
vSize(scrlsize
, height
- adjust
) ;
2885 wxPoint
hPoint(0, height
- scrlsize
) ;
2886 wxSize
hSize(width
- adjust
, scrlsize
) ;
2888 // we have to set the min size to a smaller value, otherwise they cannot get smaller (InitialSize sets MinSize)
2889 if ( style
& wxVSCROLL
)
2891 m_vScrollBar
= new wxScrollBar((wxWindow
*)this, wxID_ANY
, vPoint
, vSize
, wxVERTICAL
);
2892 m_vScrollBar
->SetMinSize( wxDefaultSize
);
2895 if ( style
& wxHSCROLL
)
2897 m_hScrollBar
= new wxScrollBar((wxWindow
*)this, wxID_ANY
, hPoint
, hSize
, wxHORIZONTAL
);
2898 m_hScrollBar
->SetMinSize( wxDefaultSize
);
2902 // because the create does not take into account the client area origin
2903 // we might have a real position shift
2904 MacRepositionScrollBars() ;
2907 bool wxWindowMac::MacIsChildOfClientArea( const wxWindow
* child
) const
2909 bool result
= ((child
== NULL
) || ((child
!= m_hScrollBar
) && (child
!= m_vScrollBar
)));
2914 void wxWindowMac::MacRepositionScrollBars()
2916 if ( !m_hScrollBar
&& !m_vScrollBar
)
2919 int scrlsize
= m_hScrollBar
? m_hScrollBar
->GetSize().y
: ( m_vScrollBar
? m_vScrollBar
->GetSize().x
: MAC_SCROLLBAR_SIZE
) ;
2920 int adjust
= MacHasScrollBarCorner() ? scrlsize
- 1 : 0 ;
2922 // get real client area
2924 GetSize( &width
, &height
);
2926 width
-= MacGetLeftBorderSize() + MacGetRightBorderSize();
2927 height
-= MacGetTopBorderSize() + MacGetBottomBorderSize();
2929 wxPoint
vPoint( width
- scrlsize
, 0 ) ;
2930 wxSize
vSize( scrlsize
, height
- adjust
) ;
2931 wxPoint
hPoint( 0 , height
- scrlsize
) ;
2932 wxSize
hSize( width
- adjust
, scrlsize
) ;
2935 int x
= 0, y
= 0, w
, h
;
2936 GetSize( &w
, &h
) ;
2938 MacClientToRootWindow( &x
, &y
) ;
2939 MacClientToRootWindow( &w
, &h
) ;
2941 wxWindowMac
*iter
= (wxWindowMac
*)this ;
2943 int totW
= 10000 , totH
= 10000;
2946 if ( iter
->IsTopLevel() )
2948 iter
->GetSize( &totW
, &totH
) ;
2952 iter
= iter
->GetParent() ;
2966 if ( w
- x
>= totW
)
2971 if ( h
- y
>= totH
)
2979 m_vScrollBar
->SetSize( vPoint
.x
, vPoint
.y
, vSize
.x
, vSize
.y
, wxSIZE_ALLOW_MINUS_ONE
);
2981 m_hScrollBar
->SetSize( hPoint
.x
, hPoint
.y
, hSize
.x
, hSize
.y
, wxSIZE_ALLOW_MINUS_ONE
);
2984 bool wxWindowMac::AcceptsFocus() const
2986 return MacCanFocus() && wxWindowBase::AcceptsFocus();
2989 void wxWindowMac::MacSuperChangedPosition()
2991 // only window-absolute structures have to be moved i.e. controls
2993 m_cachedClippedRectValid
= false ;
2996 wxWindowList::compatibility_iterator node
= GetChildren().GetFirst();
2999 child
= node
->GetData();
3000 child
->MacSuperChangedPosition() ;
3002 node
= node
->GetNext();
3006 void wxWindowMac::MacTopLevelWindowChangedPosition()
3008 // only screen-absolute structures have to be moved i.e. glcanvas
3011 wxWindowList::compatibility_iterator node
= GetChildren().GetFirst();
3014 child
= node
->GetData();
3015 child
->MacTopLevelWindowChangedPosition() ;
3017 node
= node
->GetNext();
3021 long wxWindowMac::MacGetLeftBorderSize() const
3028 if (HasFlag(wxRAISED_BORDER
) || HasFlag( wxSUNKEN_BORDER
) || HasFlag(wxDOUBLE_BORDER
))
3030 // this metric is only the 'outset' outside the simple frame rect
3031 GetThemeMetric( kThemeMetricEditTextFrameOutset
, &border
) ;
3034 else if (HasFlag(wxSIMPLE_BORDER
))
3036 // this metric is only the 'outset' outside the simple frame rect
3037 GetThemeMetric( kThemeMetricListBoxFrameOutset
, &border
) ;
3044 long wxWindowMac::MacGetRightBorderSize() const
3046 // they are all symmetric in mac themes
3047 return MacGetLeftBorderSize() ;
3050 long wxWindowMac::MacGetTopBorderSize() const
3052 // they are all symmetric in mac themes
3053 return MacGetLeftBorderSize() ;
3056 long wxWindowMac::MacGetBottomBorderSize() const
3058 // they are all symmetric in mac themes
3059 return MacGetLeftBorderSize() ;
3062 long wxWindowMac::MacRemoveBordersFromStyle( long style
)
3064 return style
& ~wxBORDER_MASK
;
3067 // Find the wxWindowMac at the current mouse position, returning the mouse
3069 wxWindowMac
* wxFindWindowAtPointer( wxPoint
& pt
)
3071 pt
= wxGetMousePosition();
3072 wxWindowMac
* found
= wxFindWindowAtPoint(pt
);
3077 // Get the current mouse position.
3078 wxPoint
wxGetMousePosition()
3082 wxGetMousePosition( &x
, &y
);
3084 return wxPoint(x
, y
);
3087 void wxWindowMac::OnMouseEvent( wxMouseEvent
&event
)
3089 if ( event
.GetEventType() == wxEVT_RIGHT_DOWN
)
3091 // copied from wxGTK : CS
3092 // VZ: shouldn't we move this to base class then?
3094 // generate a "context menu" event: this is similar to wxEVT_RIGHT_DOWN
3097 // (a) it's a command event and so is propagated to the parent
3098 // (b) under MSW it can be generated from kbd too
3099 // (c) it uses screen coords (because of (a))
3100 wxContextMenuEvent
evtCtx(wxEVT_CONTEXT_MENU
,
3102 this->ClientToScreen(event
.GetPosition()));
3103 if ( ! GetEventHandler()->ProcessEvent(evtCtx
) )
3112 void wxWindowMac::OnPaint( wxPaintEvent
& WXUNUSED(event
) )
3114 if ( wxTheApp
->MacGetCurrentEvent() != NULL
&& wxTheApp
->MacGetCurrentEventHandlerCallRef() != NULL
3115 && GetBackgroundStyle() != wxBG_STYLE_TRANSPARENT
)
3116 CallNextEventHandler(
3117 (EventHandlerCallRef
)wxTheApp
->MacGetCurrentEventHandlerCallRef() ,
3118 (EventRef
) wxTheApp
->MacGetCurrentEvent() ) ;
3121 void wxWindowMac::MacHandleControlClick(WXWidget
WXUNUSED(control
),
3122 wxInt16
WXUNUSED(controlpart
),
3123 bool WXUNUSED(mouseStillDown
))
3127 Rect
wxMacGetBoundsForControl( wxWindow
* window
, const wxPoint
& pos
, const wxSize
&size
, bool adjustForOrigin
)
3131 window
->MacGetBoundsForControl( pos
, size
, x
, y
, w
, h
, adjustForOrigin
) ;
3132 Rect bounds
= { y
, x
, y
+ h
, x
+ w
};
3137 wxInt32
wxWindowMac::MacControlHit(WXEVENTHANDLERREF
WXUNUSED(handler
) , WXEVENTREF
WXUNUSED(event
) )
3139 return eventNotHandledErr
;
3142 bool wxWindowMac::Reparent(wxWindowBase
*newParentBase
)
3144 wxWindowMac
*newParent
= (wxWindowMac
*)newParentBase
;
3145 if ( !wxWindowBase::Reparent(newParent
) )
3148 // copied from MacPostControlCreate
3149 ControlRef container
= (ControlRef
) GetParent()->GetHandle() ;
3151 wxASSERT_MSG( container
!= NULL
, wxT("No valid mac container control") ) ;
3153 ::EmbedControl( m_peer
->GetControlRef() , container
) ;
3158 bool wxWindowMac::SetTransparent(wxByte alpha
)
3160 SetBackgroundStyle(wxBG_STYLE_TRANSPARENT
);
3162 if ( alpha
!= m_macAlpha
)
3164 m_macAlpha
= alpha
;
3171 bool wxWindowMac::CanSetTransparent()
3176 wxByte
wxWindowMac::GetTransparent() const