]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/osx/window_osx.cpp
Use [DOMRange markupString] to get selection source.
[wxWidgets.git] / src / osx / window_osx.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/osx/window_osx.cpp
3// Purpose: wxWindowMac
4// Author: Stefan Csomor
5// Modified by:
6// Created: 1998-01-01
7// RCS-ID: $Id$
8// Copyright: (c) Stefan Csomor
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12#include "wx/wxprec.h"
13
14#include "wx/window.h"
15
16#ifndef WX_PRECOMP
17 #include "wx/log.h"
18 #include "wx/app.h"
19 #include "wx/utils.h"
20 #include "wx/panel.h"
21 #include "wx/frame.h"
22 #include "wx/dc.h"
23 #include "wx/dcclient.h"
24 #include "wx/button.h"
25 #include "wx/menu.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"
38#endif
39
40#include "wx/tooltip.h"
41#include "wx/spinctrl.h"
42#include "wx/geometry.h"
43
44#if wxUSE_LISTCTRL
45 #include "wx/listctrl.h"
46#endif
47
48#if wxUSE_TREECTRL
49 #include "wx/treectrl.h"
50#endif
51
52#if wxUSE_CARET
53 #include "wx/caret.h"
54#endif
55
56#if wxUSE_POPUPWIN
57 #include "wx/popupwin.h"
58#endif
59
60#if wxUSE_DRAG_AND_DROP
61 #include "wx/dnd.h"
62#endif
63
64#include "wx/graphics.h"
65
66#if wxOSX_USE_CARBON
67 #include "wx/osx/uma.h"
68#else
69 #include "wx/osx/private.h"
70#endif
71
72#define MAC_SCROLLBAR_SIZE 15
73#define MAC_SMALL_SCROLLBAR_SIZE 11
74
75#include <string.h>
76
77#ifdef __WXUNIVERSAL__
78 IMPLEMENT_ABSTRACT_CLASS(wxWindowMac, wxWindowBase)
79#endif
80
81BEGIN_EVENT_TABLE(wxWindowMac, wxWindowBase)
82 EVT_MOUSE_EVENTS(wxWindowMac::OnMouseEvent)
83END_EVENT_TABLE()
84
85#define wxMAC_DEBUG_REDRAW 0
86#ifndef wxMAC_DEBUG_REDRAW
87#define wxMAC_DEBUG_REDRAW 0
88#endif
89
90wxWidgetImplType* kOSXNoWidgetImpl = (wxWidgetImplType*) -1L;
91
92#if wxUSE_HOTKEY && wxOSX_USE_COCOA_OR_CARBON
93
94typedef struct {
95 EventHotKeyRef ref;
96 int keyId;
97 wxWindow* window;
98} wxHotKeyRec;
99
100wxVector<wxHotKeyRec> s_hotkeys;
101
102#endif
103
104// ===========================================================================
105// implementation
106// ===========================================================================
107
108// the grow box has to be implemented as an inactive window, so that nothing can direct
109// the focus to it
110
111class WXDLLIMPEXP_CORE wxBlindPlateWindow : public wxWindow
112{
113public:
114 wxBlindPlateWindow() { Init(); }
115
116 // Old-style constructor (no default values for coordinates to avoid
117 // ambiguity with the new one)
118 wxBlindPlateWindow(wxWindow *parent,
119 int x, int y, int width, int height,
120 long style = wxTAB_TRAVERSAL | wxNO_BORDER,
121 const wxString& name = wxPanelNameStr)
122 {
123 Init();
124
125 Create(parent, wxID_ANY, wxPoint(x, y), wxSize(width, height), style, name);
126 }
127
128 // Constructor
129 wxBlindPlateWindow(wxWindow *parent,
130 wxWindowID winid = wxID_ANY,
131 const wxPoint& pos = wxDefaultPosition,
132 const wxSize& size = wxDefaultSize,
133 long style = wxTAB_TRAVERSAL | wxNO_BORDER,
134 const wxString& name = wxPanelNameStr)
135 {
136 Init();
137
138 Create(parent, winid, pos, size, style, name);
139 }
140
141 // Pseudo ctor
142 bool Create(wxWindow *parent,
143 wxWindowID winid = wxID_ANY,
144 const wxPoint& pos = wxDefaultPosition,
145 const wxSize& size = wxDefaultSize,
146 long style = wxTAB_TRAVERSAL | wxNO_BORDER,
147 const wxString& name = wxPanelNameStr)
148 {
149 if ( !wxWindow::Create(parent, winid, pos, size, style, name) )
150 return false;
151
152 // so that non-solid background renders correctly under GTK+:
153 SetThemeEnabled(true);
154 return true;
155 }
156
157 virtual ~wxBlindPlateWindow();
158
159 virtual bool AcceptsFocus() const
160 {
161 return false;
162 }
163
164protected:
165 // common part of all ctors
166 void Init()
167 {
168 }
169
170 DECLARE_DYNAMIC_CLASS_NO_COPY(wxBlindPlateWindow)
171 DECLARE_EVENT_TABLE()
172};
173
174wxBlindPlateWindow::~wxBlindPlateWindow()
175{
176}
177
178IMPLEMENT_DYNAMIC_CLASS(wxBlindPlateWindow, wxWindow)
179
180BEGIN_EVENT_TABLE(wxBlindPlateWindow, wxWindow)
181END_EVENT_TABLE()
182
183
184// ----------------------------------------------------------------------------
185 // constructors and such
186// ----------------------------------------------------------------------------
187
188wxWindowMac::wxWindowMac()
189{
190 Init();
191}
192
193wxWindowMac::wxWindowMac(wxWindowMac *parent,
194 wxWindowID id,
195 const wxPoint& pos ,
196 const wxSize& size ,
197 long style ,
198 const wxString& name )
199{
200 Init();
201 Create(parent, id, pos, size, style, name);
202}
203
204void wxWindowMac::Init()
205{
206 m_peer = NULL ;
207 m_macAlpha = 255 ;
208 m_cgContextRef = NULL ;
209
210 // as all windows are created with WS_VISIBLE style...
211 m_isShown = true;
212
213 m_hScrollBar = NULL ;
214 m_vScrollBar = NULL ;
215 m_hScrollBarAlwaysShown = false;
216 m_vScrollBarAlwaysShown = false;
217 m_growBox = NULL ;
218
219 m_clipChildren = false ;
220 m_cachedClippedRectValid = false ;
221 m_isNativeWindowWrapper = false;
222}
223
224wxWindowMac::~wxWindowMac()
225{
226 SendDestroyEvent();
227
228#if wxUSE_HOTKEY && wxOSX_USE_COCOA_OR_CARBON
229 for ( int i = s_hotkeys.size()-1; i>=0; -- i )
230 {
231 if ( s_hotkeys[i].window == this )
232 {
233 EventHotKeyRef ref = s_hotkeys[i].ref;
234 s_hotkeys.erase(s_hotkeys.begin() + i);
235 if ( UnregisterEventHotKey(ref) != noErr )
236 {
237 wxLogLastError(wxT("UnregisterHotKey"));
238 }
239 }
240 }
241#endif
242
243 MacInvalidateBorders() ;
244
245#ifndef __WXUNIVERSAL__
246 // VS: make sure there's no wxFrame with last focus set to us:
247 for ( wxWindow *win = GetParent(); win; win = win->GetParent() )
248 {
249 wxFrame *frame = wxDynamicCast(win, wxFrame);
250 if ( frame )
251 {
252 if ( frame->GetLastFocus() == this )
253 frame->SetLastFocus(NULL);
254 break;
255 }
256 }
257#endif
258
259 // destroy children before destroying this window itself
260 DestroyChildren();
261
262 // wxRemoveMacControlAssociation( this ) ;
263 // If we delete an item, we should initialize the parent panel,
264 // because it could now be invalid.
265 wxTopLevelWindow *tlw = wxDynamicCast(wxGetTopLevelParent((wxWindow*)this), wxTopLevelWindow);
266 if ( tlw )
267 {
268 if ( tlw->GetDefaultItem() == (wxButton*) this)
269 tlw->SetDefaultItem(NULL);
270 }
271
272 if ( g_MacLastWindow == this )
273 g_MacLastWindow = NULL ;
274
275#ifndef __WXUNIVERSAL__
276 wxFrame* frame = wxDynamicCast( wxGetTopLevelParent( (wxWindow*)this ) , wxFrame ) ;
277 if ( frame )
278 {
279 if ( frame->GetLastFocus() == this )
280 frame->SetLastFocus( NULL ) ;
281 }
282#endif
283
284 // delete our drop target if we've got one
285#if wxUSE_DRAG_AND_DROP
286 wxDELETE(m_dropTarget);
287#endif
288
289 delete GetPeer() ;
290}
291
292WXWidget wxWindowMac::GetHandle() const
293{
294 if ( GetPeer() )
295 return (WXWidget) GetPeer()->GetWXWidget() ;
296 return NULL;
297}
298
299wxOSXWidgetImpl* wxWindowMac::GetPeer() const
300{
301 return m_peer == kOSXNoWidgetImpl ? NULL : m_peer ;
302}
303
304bool wxWindowMac::ShouldCreatePeer() const
305{
306 return m_peer != kOSXNoWidgetImpl;
307}
308
309void wxWindowMac::DontCreatePeer()
310{
311 m_peer = kOSXNoWidgetImpl;
312}
313
314void wxWindowMac::SetWrappingPeer(wxOSXWidgetImpl* wrapper)
315{
316 wxOSXWidgetImpl* inner = GetPeer();
317 wxASSERT_MSG( inner != NULL && inner->IsOk(), "missing or incomplete inner peer" );
318 wxASSERT_MSG( wrapper != NULL && wrapper->IsOk(), "missing or incomplete wrapper" );
319
320 if ( !(inner != NULL && inner->IsOk() && wrapper != NULL && wrapper->IsOk()) )
321 return;
322
323 inner->RemoveFromParent();
324 wrapper->InstallEventHandler();
325 wrapper->Embed(inner);
326 m_peer = wrapper;
327}
328
329void wxWindowMac::SetPeer(wxOSXWidgetImpl* peer)
330{
331 if ( GetPeer() )
332 {
333 if ( !GetPeer()->IsRootControl() )
334 GetPeer()->RemoveFromParent();
335 wxDELETE(m_peer);
336 }
337
338 m_peer = peer;
339
340 if ( GetPeer() && !GetPeer()->IsRootControl())
341 {
342 wxASSERT_MSG( GetPeer()->IsOk() , wxT("The native control must exist already") ) ;
343
344 if (!GetParent()->GetChildren().Find((wxWindow*)this))
345 GetParent()->AddChild( this );
346
347 GetPeer()->InstallEventHandler();
348 GetPeer()->Embed(GetParent()->GetPeer());
349
350 GetParent()->MacChildAdded() ;
351
352 // adjust font, controlsize etc
353 GetPeer()->SetControlSize( m_windowVariant );
354 InheritAttributes();
355 // in case nothing has been set, use the variant default fonts
356 if ( !m_hasFont )
357 DoSetWindowVariant( m_windowVariant );
358
359 GetPeer()->SetLabel( wxStripMenuCodes(m_label, wxStrip_Mnemonics), GetFont().GetEncoding() ) ;
360
361 // for controls we want to use best size for wxDefaultSize params )
362 if ( !GetPeer()->IsUserPane() )
363 SetInitialSize(GetMinSize());
364
365 SetCursor( *wxSTANDARD_CURSOR ) ;
366 }
367}
368
369#if WXWIN_COMPATIBILITY_2_8
370
371bool wxWindowMac::MacIsUserPane()
372{
373 return GetPeer() == NULL || GetPeer()->IsUserPane();
374}
375
376#endif
377
378bool wxWindowMac::MacIsUserPane() const
379{
380 return GetPeer() == NULL || GetPeer()->IsUserPane();
381}
382
383// ---------------------------------------------------------------------------
384// Utility Routines to move between different coordinate systems
385// ---------------------------------------------------------------------------
386
387/*
388 * Right now we have the following setup :
389 * a border that is not part of the native control is always outside the
390 * control's border (otherwise we lose all native intelligence, future ways
391 * may be to have a second embedding control responsible for drawing borders
392 * and backgrounds eventually)
393 * so all this border calculations have to be taken into account when calling
394 * native methods or getting native oriented data
395 * so we have three coordinate systems here
396 * wx client coordinates
397 * wx window coordinates (including window frames)
398 * native coordinates
399 */
400
401//
402//
403
404// Constructor
405bool wxWindowMac::Create(wxWindowMac *parent,
406 wxWindowID id,
407 const wxPoint& pos,
408 const wxSize& size,
409 long style,
410 const wxString& name)
411{
412 wxCHECK_MSG( parent, false, wxT("can't create wxWindowMac without parent") );
413
414 if ( !CreateBase(parent, id, pos, size, style, wxDefaultValidator, name) )
415 return false;
416
417 m_windowVariant = parent->GetWindowVariant() ;
418
419 if ( m_peer != kOSXNoWidgetImpl )
420 {
421 SetPeer(wxWidgetImpl::CreateUserPane( this, parent, id, pos, size , style, GetExtraStyle() ));
422 MacPostControlCreate(pos, size) ;
423 }
424
425#ifndef __WXUNIVERSAL__
426 // Don't give scrollbars to wxControls unless they ask for them
427 if ( (! IsKindOf(CLASSINFO(wxControl))
428#if wxUSE_STATUSBAR
429 && ! IsKindOf(CLASSINFO(wxStatusBar))
430#endif
431 )
432 || (IsKindOf(CLASSINFO(wxControl)) && ((style & wxHSCROLL) || (style & wxVSCROLL))))
433 {
434 MacCreateScrollBars( style ) ;
435 }
436#endif
437
438 wxWindowCreateEvent event((wxWindow*)this);
439 GetEventHandler()->AddPendingEvent(event);
440
441 return true;
442}
443
444void wxWindowMac::MacChildAdded()
445{
446#if wxUSE_SCROLLBAR
447 if ( m_vScrollBar )
448 m_vScrollBar->Raise() ;
449 if ( m_hScrollBar )
450 m_hScrollBar->Raise() ;
451 if ( m_growBox )
452 m_growBox->Raise() ;
453#endif
454}
455
456void wxWindowMac::MacPostControlCreate(const wxPoint& WXUNUSED(pos),
457 const wxSize& WXUNUSED(size))
458{
459 // todo remove if refactoring works correctly
460#if 0
461 wxASSERT_MSG( GetPeer() != NULL && GetPeer()->IsOk() , wxT("No valid mac control") ) ;
462
463 if (!GetParent()->GetChildren().Find((wxWindow*)this))
464 GetParent()->AddChild( this );
465
466 GetPeer()->InstallEventHandler();
467 GetPeer()->Embed(GetParent()->GetPeer());
468
469 GetParent()->MacChildAdded() ;
470
471 // adjust font, controlsize etc
472 DoSetWindowVariant( m_windowVariant ) ;
473
474 GetPeer()->SetLabel( wxStripMenuCodes(m_label, wxStrip_Mnemonics), GetFont().GetEncoding() ) ;
475
476 // for controls we want to use best size for wxDefaultSize params )
477 if ( !GetPeer()->IsUserPane() )
478 SetInitialSize(size);
479
480 SetCursor( *wxSTANDARD_CURSOR ) ;
481#endif
482}
483
484void wxWindowMac::DoSetWindowVariant( wxWindowVariant variant )
485{
486 // Don't assert, in case we set the window variant before
487 // the window is created
488 // wxASSERT( GetPeer()->IsOk() ) ;
489
490 m_windowVariant = variant ;
491
492 if (GetPeer() == NULL || !GetPeer()->IsOk())
493 return;
494
495 GetPeer()->SetControlSize( variant );
496
497 switch ( variant )
498 {
499 case wxWINDOW_VARIANT_NORMAL :
500 static wxFont sysNormal(wxOSX_SYSTEM_FONT_NORMAL);
501 SetFont(sysNormal) ;
502 break ;
503
504 case wxWINDOW_VARIANT_SMALL :
505 static wxFont sysSmall(wxOSX_SYSTEM_FONT_SMALL);
506 SetFont(sysSmall) ;
507 break ;
508
509 case wxWINDOW_VARIANT_MINI :
510 static wxFont sysMini(wxOSX_SYSTEM_FONT_MINI);
511 SetFont(sysMini) ;
512 break ;
513
514 case wxWINDOW_VARIANT_LARGE :
515 static wxFont sysLarge(wxOSX_SYSTEM_FONT_NORMAL);
516 SetFont(sysLarge) ;
517 break ;
518
519 default:
520 wxFAIL_MSG(wxT("unexpected window variant"));
521 break ;
522 }
523}
524
525void wxWindowMac::MacUpdateControlFont()
526{
527 if ( GetPeer() )
528 GetPeer()->SetFont( GetFont() , GetForegroundColour() , GetWindowStyle() ) ;
529
530 // do not trigger refreshes upon invisible and possible partly created objects
531 if ( IsShownOnScreen() )
532 Refresh() ;
533}
534
535bool wxWindowMac::SetFont(const wxFont& font)
536{
537 bool retval = wxWindowBase::SetFont( font );
538
539 MacUpdateControlFont() ;
540
541 return retval;
542}
543
544bool wxWindowMac::SetForegroundColour(const wxColour& col )
545{
546 bool retval = wxWindowBase::SetForegroundColour( col );
547
548 if (retval)
549 MacUpdateControlFont();
550
551 return retval;
552}
553
554bool wxWindowMac::SetBackgroundStyle(wxBackgroundStyle style)
555{
556 if ( !wxWindowBase::SetBackgroundStyle(style) )
557 return false;
558
559 if ( GetPeer() )
560 GetPeer()->SetBackgroundStyle(style);
561 return true;
562}
563
564bool wxWindowMac::SetBackgroundColour(const wxColour& col )
565{
566 if (m_growBox)
567 {
568 if ( m_backgroundColour.IsOk() )
569 m_growBox->SetBackgroundColour(m_backgroundColour);
570 else
571 m_growBox->SetBackgroundColour(*wxWHITE);
572 }
573
574 if ( !wxWindowBase::SetBackgroundColour(col) && m_hasBgCol )
575 return false ;
576
577 if ( GetPeer() )
578 GetPeer()->SetBackgroundColour( col ) ;
579
580 return true ;
581}
582
583static bool wxIsWindowOrParentDisabled(wxWindow* w)
584{
585 while (w && !w->IsTopLevel())
586 {
587 if (!w->IsEnabled())
588 return true;
589 w = w->GetParent();
590 }
591 return false;
592}
593
594void wxWindowMac::SetFocus()
595{
596 if ( !AcceptsFocus() )
597 return ;
598
599 if (wxIsWindowOrParentDisabled((wxWindow*) this))
600 return;
601
602 wxWindow* former = FindFocus() ;
603 if ( former == this )
604 return ;
605
606 GetPeer()->SetFocus() ;
607}
608
609void wxWindowMac::OSXSimulateFocusEvents()
610{
611 wxWindow* former = FindFocus() ;
612 if ( former != NULL && former != this )
613 {
614 {
615 wxFocusEvent event( wxEVT_KILL_FOCUS, former->GetId());
616 event.SetEventObject(former);
617 event.SetWindow(this);
618 former->HandleWindowEvent(event) ;
619 }
620
621 {
622 wxFocusEvent event(wxEVT_SET_FOCUS, former->GetId());
623 event.SetEventObject(former);
624 event.SetWindow(this);
625 former->HandleWindowEvent(event);
626 }
627 }
628}
629
630void wxWindowMac::DoCaptureMouse()
631{
632 wxApp::s_captureWindow = (wxWindow*) this ;
633 GetPeer()->CaptureMouse() ;
634}
635
636wxWindow * wxWindowBase::GetCapture()
637{
638 return wxApp::s_captureWindow ;
639}
640
641void wxWindowMac::DoReleaseMouse()
642{
643 wxApp::s_captureWindow = NULL ;
644
645 GetPeer()->ReleaseMouse() ;
646}
647
648#if wxUSE_DRAG_AND_DROP
649
650void wxWindowMac::SetDropTarget(wxDropTarget *pDropTarget)
651{
652 delete m_dropTarget;
653
654 m_dropTarget = pDropTarget;
655
656 GetPeer()->SetDropTarget(m_dropTarget) ;
657}
658
659#endif
660
661// Old-style File Manager Drag & Drop
662void wxWindowMac::DragAcceptFiles(bool WXUNUSED(accept))
663{
664 // TODO:
665}
666
667// From a wx position / size calculate the appropriate size of the native control
668
669bool wxWindowMac::MacGetBoundsForControl(
670 const wxPoint& pos,
671 const wxSize& size,
672 int& x, int& y,
673 int& w, int& h , bool adjustOrigin ) const
674{
675 // the desired size, minus the border pixels gives the correct size of the control
676 x = (int)pos.x;
677 y = (int)pos.y;
678
679 w = WidthDefault( size.x );
680 h = HeightDefault( size.y );
681
682 x += MacGetLeftBorderSize() ;
683 y += MacGetTopBorderSize() ;
684 w -= MacGetLeftBorderSize() + MacGetRightBorderSize() ;
685 h -= MacGetTopBorderSize() + MacGetBottomBorderSize() ;
686
687 if ( adjustOrigin )
688 AdjustForParentClientOrigin( x , y ) ;
689
690 // this is in window relative coordinate, as this parent may have a border, its physical position is offset by this border
691 if ( GetParent() && !GetParent()->IsTopLevel() )
692 {
693 x -= GetParent()->MacGetLeftBorderSize() ;
694 y -= GetParent()->MacGetTopBorderSize() ;
695 }
696
697 return true ;
698}
699
700// Get window size (not client size)
701void wxWindowMac::DoGetSize(int *x, int *y) const
702{
703 int width, height;
704 GetPeer()->GetSize( width, height );
705
706 if (x)
707 *x = width + MacGetLeftBorderSize() + MacGetRightBorderSize() ;
708 if (y)
709 *y = height + MacGetTopBorderSize() + MacGetBottomBorderSize() ;
710}
711
712// get the position of the bounds of this window in client coordinates of its parent
713void wxWindowMac::DoGetPosition(int *x, int *y) const
714{
715 int x1, y1;
716
717 GetPeer()->GetPosition( x1, y1 ) ;
718
719 // get the wx window position from the native one
720 x1 -= MacGetLeftBorderSize() ;
721 y1 -= MacGetTopBorderSize() ;
722
723 if ( !IsTopLevel() )
724 {
725 wxWindow *parent = GetParent();
726 if ( parent )
727 {
728 // we must first adjust it to be in window coordinates of the parent,
729 // as otherwise it gets lost by the ClientAreaOrigin fix
730 x1 += parent->MacGetLeftBorderSize() ;
731 y1 += parent->MacGetTopBorderSize() ;
732
733 // and now to client coordinates
734 wxPoint pt(parent->GetClientAreaOrigin());
735 x1 -= pt.x ;
736 y1 -= pt.y ;
737 }
738 }
739
740 if (x)
741 *x = x1 ;
742 if (y)
743 *y = y1 ;
744}
745
746void wxWindowMac::DoScreenToClient(int *x, int *y) const
747{
748 wxNonOwnedWindow* tlw = MacGetTopLevelWindow() ;
749 wxCHECK_RET( tlw , wxT("TopLevel Window missing") ) ;
750 tlw->GetNonOwnedPeer()->ScreenToWindow( x, y);
751 MacRootWindowToWindow( x , y ) ;
752
753 wxPoint origin = GetClientAreaOrigin() ;
754 if (x)
755 *x -= origin.x ;
756 if (y)
757 *y -= origin.y ;
758}
759
760void wxWindowMac::DoClientToScreen(int *x, int *y) const
761{
762 wxNonOwnedWindow* tlw = MacGetTopLevelWindow() ;
763 wxCHECK_RET( tlw , wxT("TopLevel window missing") ) ;
764
765 wxPoint origin = GetClientAreaOrigin() ;
766 if (x)
767 *x += origin.x ;
768 if (y)
769 *y += origin.y ;
770
771 MacWindowToRootWindow( x , y ) ;
772 tlw->GetNonOwnedPeer()->WindowToScreen( x , y );
773}
774
775void wxWindowMac::MacClientToRootWindow( int *x , int *y ) const
776{
777 wxPoint origin = GetClientAreaOrigin() ;
778 if (x)
779 *x += origin.x ;
780 if (y)
781 *y += origin.y ;
782
783 MacWindowToRootWindow( x , y ) ;
784}
785
786void wxWindowMac::MacWindowToRootWindow( int *x , int *y ) const
787{
788 wxPoint pt ;
789
790 if (x)
791 pt.x = *x ;
792 if (y)
793 pt.y = *y ;
794
795 if ( !IsTopLevel() )
796 {
797 wxNonOwnedWindow* top = MacGetTopLevelWindow();
798 if (top)
799 {
800 pt.x -= MacGetLeftBorderSize() ;
801 pt.y -= MacGetTopBorderSize() ;
802 wxWidgetImpl::Convert( &pt , GetPeer() , top->GetPeer() ) ;
803 }
804 }
805
806 if (x)
807 *x = (int) pt.x ;
808 if (y)
809 *y = (int) pt.y ;
810}
811
812void wxWindowMac::MacRootWindowToWindow( int *x , int *y ) const
813{
814 wxPoint pt ;
815
816 if (x)
817 pt.x = *x ;
818 if (y)
819 pt.y = *y ;
820
821 if ( !IsTopLevel() )
822 {
823 wxNonOwnedWindow* top = MacGetTopLevelWindow();
824 if (top)
825 {
826 wxWidgetImpl::Convert( &pt , top->GetPeer() , GetPeer() ) ;
827 pt.x += MacGetLeftBorderSize() ;
828 pt.y += MacGetTopBorderSize() ;
829 }
830 }
831
832 if (x)
833 *x = (int) pt.x ;
834 if (y)
835 *y = (int) pt.y ;
836}
837
838wxSize wxWindowMac::DoGetSizeFromClientSize( const wxSize & size ) const
839{
840 wxSize sizeTotal = size;
841
842 int innerwidth, innerheight;
843 int left, top;
844 int outerwidth, outerheight;
845
846 GetPeer()->GetContentArea( left, top, innerwidth, innerheight );
847 GetPeer()->GetSize( outerwidth, outerheight );
848
849 sizeTotal.x += outerwidth-innerwidth;
850 sizeTotal.y += outerheight-innerheight;
851
852 sizeTotal.x += MacGetLeftBorderSize() + MacGetRightBorderSize() ;
853 sizeTotal.y += MacGetTopBorderSize() + MacGetBottomBorderSize() ;
854
855 return sizeTotal;
856}
857
858// Get size *available for subwindows* i.e. excluding menu bar etc.
859void wxWindowMac::DoGetClientSize( int *x, int *y ) const
860{
861 int ww, hh;
862
863 int left, top;
864
865 GetPeer()->GetContentArea( left, top, ww, hh );
866#if wxUSE_SCROLLBAR
867 if (m_hScrollBar && m_hScrollBar->IsShown() )
868 hh -= m_hScrollBar->GetSize().y ;
869
870 if (m_vScrollBar && m_vScrollBar->IsShown() )
871 ww -= m_vScrollBar->GetSize().x ;
872
873#endif
874 if (x)
875 {
876 // we shouldn't return invalid width
877 if ( ww < 0 )
878 ww = 0;
879
880 *x = ww;
881 }
882
883 if (y)
884 {
885 // we shouldn't return invalid height
886 if ( hh < 0 )
887 hh = 0;
888
889 *y = hh;
890 }
891}
892
893bool wxWindowMac::SetCursor(const wxCursor& cursor)
894{
895 if (m_cursor.IsSameAs(cursor))
896 return false;
897
898 if (!cursor.IsOk())
899 {
900 if ( ! wxWindowBase::SetCursor( *wxSTANDARD_CURSOR ) )
901 return false ;
902 }
903 else
904 {
905 if ( ! wxWindowBase::SetCursor( cursor ) )
906 return false ;
907 }
908
909 wxASSERT_MSG( m_cursor.IsOk(),
910 wxT("cursor must be valid after call to the base version"));
911
912 if ( GetPeer() != NULL )
913 GetPeer()->SetCursor( m_cursor );
914
915 return true ;
916}
917
918#if wxUSE_MENUS
919bool wxWindowMac::DoPopupMenu(wxMenu *menu, int x, int y)
920{
921#ifndef __WXUNIVERSAL__
922 menu->UpdateUI();
923
924 if ( x == wxDefaultCoord && y == wxDefaultCoord )
925 {
926 wxPoint mouse = wxGetMousePosition();
927 x = mouse.x;
928 y = mouse.y;
929 }
930 else
931 {
932 ClientToScreen( &x , &y ) ;
933 }
934 menu->GetPeer()->PopUp(this, x, y);
935 return true;
936#else
937 // actually this shouldn't be called, because universal is having its own implementation
938 return false;
939#endif
940}
941#endif
942
943// ----------------------------------------------------------------------------
944// tooltips
945// ----------------------------------------------------------------------------
946
947#if wxUSE_TOOLTIPS
948
949void wxWindowMac::DoSetToolTip(wxToolTip *tooltip)
950{
951 wxWindowBase::DoSetToolTip(tooltip);
952
953 if ( m_tooltip )
954 m_tooltip->SetWindow(this);
955
956 if (GetPeer())
957 GetPeer()->SetToolTip(tooltip);
958}
959
960#endif
961
962void wxWindowMac::MacInvalidateBorders()
963{
964 if ( GetPeer() == NULL )
965 return ;
966
967 bool vis = IsShownOnScreen() ;
968 if ( !vis )
969 return ;
970
971 int outerBorder = MacGetLeftBorderSize() ;
972
973 if ( GetPeer()->NeedsFocusRect() )
974 outerBorder += 4 ;
975
976 if ( outerBorder == 0 )
977 return ;
978
979 // now we know that we have something to do at all
980
981 int tx,ty,tw,th;
982
983 GetPeer()->GetSize( tw, th );
984 GetPeer()->GetPosition( tx, ty );
985
986 wxRect leftupdate( tx-outerBorder,ty,outerBorder,th );
987 wxRect rightupdate( tx+tw, ty, outerBorder, th );
988 wxRect topupdate( tx-outerBorder, ty-outerBorder, tw + 2 * outerBorder, outerBorder );
989 wxRect bottomupdate( tx-outerBorder, ty + th, tw + 2 * outerBorder, outerBorder );
990
991 if (GetParent()) {
992 GetParent()->GetPeer()->SetNeedsDisplay(&leftupdate);
993 GetParent()->GetPeer()->SetNeedsDisplay(&rightupdate);
994 GetParent()->GetPeer()->SetNeedsDisplay(&topupdate);
995 GetParent()->GetPeer()->SetNeedsDisplay(&bottomupdate);
996 }
997}
998
999void wxWindowMac::DoMoveWindow(int x, int y, int width, int height)
1000{
1001 // this is never called for a toplevel window, so we know we have a parent
1002 int former_x , former_y , former_w, former_h ;
1003
1004 // Get true coordinates of former position
1005 DoGetPosition( &former_x , &former_y ) ;
1006 DoGetSize( &former_w , &former_h ) ;
1007
1008 wxWindow *parent = GetParent();
1009 if ( parent )
1010 {
1011 wxPoint pt(parent->GetClientAreaOrigin());
1012 former_x += pt.x ;
1013 former_y += pt.y ;
1014 }
1015
1016 int actualWidth = width ;
1017 int actualHeight = height ;
1018 int actualX = x;
1019 int actualY = y;
1020
1021#if 0
1022 // min and max sizes are only for sizers, not for explicit size setting
1023 if ((m_minWidth != -1) && (actualWidth < m_minWidth))
1024 actualWidth = m_minWidth;
1025 if ((m_minHeight != -1) && (actualHeight < m_minHeight))
1026 actualHeight = m_minHeight;
1027 if ((m_maxWidth != -1) && (actualWidth > m_maxWidth))
1028 actualWidth = m_maxWidth;
1029 if ((m_maxHeight != -1) && (actualHeight > m_maxHeight))
1030 actualHeight = m_maxHeight;
1031#endif
1032
1033 bool doMove = false, doResize = false ;
1034
1035 if ( actualX != former_x || actualY != former_y )
1036 doMove = true ;
1037
1038 if ( actualWidth != former_w || actualHeight != former_h )
1039 doResize = true ;
1040
1041 if ( doMove || doResize )
1042 {
1043 // as the borders are drawn outside the native control, we adjust now
1044
1045 wxRect bounds( wxPoint( actualX + MacGetLeftBorderSize() ,actualY + MacGetTopBorderSize() ),
1046 wxSize( actualWidth - (MacGetLeftBorderSize() + MacGetRightBorderSize()) ,
1047 actualHeight - (MacGetTopBorderSize() + MacGetBottomBorderSize()) ) ) ;
1048
1049 if ( parent && !parent->IsTopLevel() )
1050 {
1051 bounds.Offset( -parent->MacGetLeftBorderSize(), -parent->MacGetTopBorderSize() );
1052 }
1053
1054 MacInvalidateBorders() ;
1055
1056 m_cachedClippedRectValid = false ;
1057
1058 GetPeer()->Move( bounds.x, bounds.y, bounds.width, bounds.height);
1059
1060 wxWindowMac::MacSuperChangedPosition() ; // like this only children will be notified
1061
1062 MacInvalidateBorders() ;
1063
1064 MacRepositionScrollBars() ;
1065 if ( doMove )
1066 {
1067 wxPoint point(actualX, actualY);
1068 wxMoveEvent event(point, m_windowId);
1069 event.SetEventObject(this);
1070 HandleWindowEvent(event) ;
1071 }
1072
1073 if ( doResize )
1074 {
1075 MacRepositionScrollBars() ;
1076 SendSizeEvent();
1077 }
1078 }
1079}
1080
1081wxSize wxWindowMac::DoGetBestSize() const
1082{
1083 if ( GetPeer() == NULL || GetPeer()->IsUserPane() || IsTopLevel() )
1084 {
1085 return wxWindowBase::DoGetBestSize() ;
1086 }
1087 else
1088 {
1089 wxRect r ;
1090
1091 GetPeer()->GetBestRect(&r);
1092
1093 if ( r.GetWidth() == 0 && r.GetHeight() == 0 )
1094 {
1095 r.x =
1096 r.y = 0 ;
1097 r.width =
1098 r.height = 16 ;
1099
1100#if wxUSE_SCROLLBAR
1101 if ( IsKindOf( CLASSINFO( wxScrollBar ) ) )
1102 {
1103 r.height = 16 ;
1104 }
1105 else
1106#endif
1107#if wxUSE_SPINBTN
1108 if ( IsKindOf( CLASSINFO( wxSpinButton ) ) )
1109 {
1110 r.height = 24 ;
1111 }
1112 else
1113#endif
1114 {
1115 // return wxWindowBase::DoGetBestSize() ;
1116 }
1117 }
1118
1119 int bestWidth = r.width + MacGetLeftBorderSize() +
1120 MacGetRightBorderSize();
1121 int bestHeight = r.height + MacGetTopBorderSize() +
1122 MacGetBottomBorderSize();
1123 if ( bestHeight < 10 )
1124 bestHeight = 13 ;
1125
1126 return wxSize(bestWidth, bestHeight);
1127 }
1128}
1129
1130void wxWindowMac::SendSizeEvent(int flags)
1131{
1132 MacOnInternalSize();
1133 wxWindowBase::SendSizeEvent(flags);
1134}
1135
1136// set the size of the window: if the dimensions are positive, just use them,
1137// but if any of them is equal to -1, it means that we must find the value for
1138// it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in
1139// which case -1 is a valid value for x and y)
1140//
1141// If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate
1142// the width/height to best suit our contents, otherwise we reuse the current
1143// width/height
1144void wxWindowMac::DoSetSize(int x, int y, int width, int height, int sizeFlags)
1145{
1146 // get the current size and position...
1147 int currentX, currentY;
1148 int currentW, currentH;
1149
1150 GetPosition(&currentX, &currentY);
1151 GetSize(&currentW, &currentH);
1152
1153 // ... and don't do anything (avoiding flicker) if it's already ok
1154 if ( x == currentX && y == currentY &&
1155 width == currentW && height == currentH && ( height != -1 && width != -1 ) )
1156 {
1157 // TODO: REMOVE
1158 MacRepositionScrollBars() ; // we might have a real position shift
1159
1160 if (sizeFlags & wxSIZE_FORCE_EVENT)
1161 {
1162 SendSizeEvent();
1163 }
1164
1165 return;
1166 }
1167
1168 if ( !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) )
1169 {
1170 if ( x == wxDefaultCoord )
1171 x = currentX;
1172 if ( y == wxDefaultCoord )
1173 y = currentY;
1174 }
1175
1176 AdjustForParentClientOrigin( x, y, sizeFlags );
1177
1178 wxSize size = wxDefaultSize;
1179 if ( width == wxDefaultCoord )
1180 {
1181 if ( sizeFlags & wxSIZE_AUTO_WIDTH )
1182 {
1183 size = DoGetBestSize();
1184 width = size.x;
1185 }
1186 else
1187 {
1188 // just take the current one
1189 width = currentW;
1190 }
1191 }
1192
1193 if ( height == wxDefaultCoord )
1194 {
1195 if ( sizeFlags & wxSIZE_AUTO_HEIGHT )
1196 {
1197 if ( size.x == wxDefaultCoord )
1198 size = DoGetBestSize();
1199 // else: already called DoGetBestSize() above
1200
1201 height = size.y;
1202 }
1203 else
1204 {
1205 // just take the current one
1206 height = currentH;
1207 }
1208 }
1209
1210 DoMoveWindow( x, y, width, height );
1211}
1212
1213wxPoint wxWindowMac::GetClientAreaOrigin() const
1214{
1215 int left,top,width,height;
1216 GetPeer()->GetContentArea( left , top , width , height);
1217 return wxPoint( left + MacGetLeftBorderSize() , top + MacGetTopBorderSize() );
1218}
1219
1220void wxWindowMac::DoSetClientSize(int clientwidth, int clientheight)
1221{
1222 if ( clientwidth != wxDefaultCoord || clientheight != wxDefaultCoord )
1223 {
1224 int currentclientwidth , currentclientheight ;
1225 int currentwidth , currentheight ;
1226
1227 GetClientSize( &currentclientwidth , &currentclientheight ) ;
1228 GetSize( &currentwidth , &currentheight ) ;
1229
1230 DoSetSize( wxDefaultCoord , wxDefaultCoord , currentwidth + clientwidth - currentclientwidth ,
1231 currentheight + clientheight - currentclientheight , wxSIZE_USE_EXISTING ) ;
1232 }
1233}
1234
1235double wxWindowMac::GetContentScaleFactor() const
1236{
1237 return GetPeer()->GetContentScaleFactor();
1238}
1239
1240void wxWindowMac::SetLabel(const wxString& title)
1241{
1242 if ( title == m_label )
1243 return;
1244
1245 m_label = title ;
1246
1247 InvalidateBestSize();
1248
1249 if ( GetPeer() && GetPeer()->IsOk() )
1250 GetPeer()->SetLabel( wxStripMenuCodes(m_label, wxStrip_Mnemonics), GetFont().GetEncoding() ) ;
1251
1252 // do not trigger refreshes upon invisible and possible partly created objects
1253 if ( IsShownOnScreen() )
1254 Refresh() ;
1255}
1256
1257wxString wxWindowMac::GetLabel() const
1258{
1259 return m_label ;
1260}
1261
1262bool wxWindowMac::Show(bool show)
1263{
1264 if ( !show )
1265 MacInvalidateBorders();
1266
1267 if ( !wxWindowBase::Show(show) )
1268 return false;
1269
1270 if ( GetPeer() )
1271 GetPeer()->SetVisibility( show ) ;
1272
1273 if ( show )
1274 MacInvalidateBorders();
1275
1276#ifdef __WXOSX_IPHONE__
1277 // only when there's no native event support
1278 if ( !IsTopLevel() )
1279#endif
1280 {
1281 wxShowEvent eventShow(GetId(), show);
1282 eventShow.SetEventObject(this);
1283
1284 HandleWindowEvent(eventShow);
1285 }
1286
1287 return true;
1288}
1289
1290bool wxWindowMac::OSXShowWithEffect(bool show,
1291 wxShowEffect effect,
1292 unsigned timeout)
1293{
1294 if ( effect == wxSHOW_EFFECT_NONE ||
1295 !GetPeer() || !GetPeer()->ShowWithEffect(show, effect, timeout) )
1296 return Show(show);
1297
1298 return true;
1299}
1300
1301void wxWindowMac::DoEnable(bool enable)
1302{
1303 GetPeer()->Enable( enable ) ;
1304 MacInvalidateBorders();
1305}
1306
1307//
1308// status change notifications
1309//
1310
1311void wxWindowMac::MacVisibilityChanged()
1312{
1313}
1314
1315void wxWindowMac::MacHiliteChanged()
1316{
1317}
1318
1319void wxWindowMac::MacEnabledStateChanged()
1320{
1321}
1322
1323//
1324// status queries on the inherited window's state
1325//
1326
1327bool wxWindowMac::MacIsReallyEnabled()
1328{
1329 return GetPeer()->IsEnabled() ;
1330}
1331
1332bool wxWindowMac::MacIsReallyHilited()
1333{
1334#if wxOSX_USE_CARBON
1335 return GetPeer()->IsActive();
1336#else
1337 return true; // TODO
1338#endif
1339}
1340
1341int wxWindowMac::GetCharHeight() const
1342{
1343 wxCoord height;
1344 GetTextExtent( wxT("g") , NULL , &height , NULL , NULL , NULL );
1345
1346 return height;
1347}
1348
1349int wxWindowMac::GetCharWidth() const
1350{
1351 wxCoord width;
1352 GetTextExtent( wxT("g") , &width , NULL , NULL , NULL , NULL );
1353
1354 return width;
1355}
1356
1357void wxWindowMac::DoGetTextExtent(const wxString& str,
1358 int *x, int *y,
1359 int *descent,
1360 int *externalLeading,
1361 const wxFont *theFont) const
1362{
1363 const wxFont *fontToUse = theFont;
1364 wxFont tempFont;
1365 if ( !fontToUse )
1366 {
1367 tempFont = GetFont();
1368 fontToUse = &tempFont;
1369 }
1370
1371 wxGraphicsContext* ctx = wxGraphicsContext::Create();
1372 ctx->SetFont( *fontToUse, *wxBLACK );
1373
1374 wxDouble h , d , e , w;
1375 ctx->GetTextExtent( str, &w, &h, &d, &e );
1376
1377 delete ctx;
1378
1379 if ( externalLeading )
1380 *externalLeading = (wxCoord)(e+0.5);
1381 if ( descent )
1382 *descent = (wxCoord)(d+0.5);
1383 if ( x )
1384 *x = (wxCoord)(w+0.5);
1385 if ( y )
1386 *y = (wxCoord)(h+0.5);
1387}
1388
1389/*
1390 * Rect is given in client coordinates, for further reading, read wxTopLevelWindowMac::InvalidateRect
1391 * we always intersect with the entire window, not only with the client area
1392 */
1393
1394void wxWindowMac::Refresh(bool WXUNUSED(eraseBack), const wxRect *rect)
1395{
1396 if ( GetPeer() == NULL )
1397 return ;
1398
1399 if ( !IsShownOnScreen() )
1400 return ;
1401
1402 if ( IsFrozen() )
1403 return;
1404
1405 GetPeer()->SetNeedsDisplay( rect ) ;
1406}
1407
1408void wxWindowMac::DoFreeze()
1409{
1410 if ( GetPeer() && GetPeer()->IsOk() )
1411 GetPeer()->SetDrawingEnabled( false ) ;
1412}
1413
1414void wxWindowMac::DoThaw()
1415{
1416 if ( GetPeer() && GetPeer()->IsOk() )
1417 GetPeer()->SetDrawingEnabled( true ) ;
1418}
1419
1420wxWindow *wxGetActiveWindow()
1421{
1422 // actually this is a windows-only concept
1423 return NULL;
1424}
1425
1426// Coordinates relative to the window
1427void wxWindowMac::WarpPointer(int x_pos, int y_pos)
1428{
1429#if wxOSX_USE_COCOA_OR_CARBON
1430 int x = x_pos;
1431 int y = y_pos;
1432 DoClientToScreen(&x, &y);
1433 CGPoint cgpoint = CGPointMake( x, y );
1434 CGWarpMouseCursorPosition( cgpoint );
1435
1436 // At least GTK sends a mouse moved event after WarpMouse
1437 wxMouseEvent event(wxEVT_MOTION);
1438 event.m_x = x_pos;
1439 event.m_y = y_pos;
1440 wxMouseState mState = ::wxGetMouseState();
1441
1442 event.m_altDown = mState.AltDown();
1443 event.m_controlDown = mState.ControlDown();
1444 event.m_leftDown = mState.LeftIsDown();
1445 event.m_middleDown = mState.MiddleIsDown();
1446 event.m_rightDown = mState.RightIsDown();
1447 event.m_metaDown = mState.MetaDown();
1448 event.m_shiftDown = mState.ShiftDown();
1449 event.SetId(GetId());
1450 event.SetEventObject(this);
1451 GetEventHandler()->ProcessEvent(event);
1452#endif
1453}
1454
1455int wxWindowMac::GetScrollPos(int orient) const
1456{
1457#if wxUSE_SCROLLBAR
1458 if ( orient == wxHORIZONTAL )
1459 {
1460 if ( m_hScrollBar )
1461 return m_hScrollBar->GetThumbPosition() ;
1462 }
1463 else
1464 {
1465 if ( m_vScrollBar )
1466 return m_vScrollBar->GetThumbPosition() ;
1467 }
1468#endif
1469 return 0;
1470}
1471
1472// This now returns the whole range, not just the number
1473// of positions that we can scroll.
1474int wxWindowMac::GetScrollRange(int orient) const
1475{
1476#if wxUSE_SCROLLBAR
1477 if ( orient == wxHORIZONTAL )
1478 {
1479 if ( m_hScrollBar )
1480 return m_hScrollBar->GetRange() ;
1481 }
1482 else
1483 {
1484 if ( m_vScrollBar )
1485 return m_vScrollBar->GetRange() ;
1486 }
1487#endif
1488 return 0;
1489}
1490
1491int wxWindowMac::GetScrollThumb(int orient) const
1492{
1493#if wxUSE_SCROLLBAR
1494 if ( orient == wxHORIZONTAL )
1495 {
1496 if ( m_hScrollBar )
1497 return m_hScrollBar->GetThumbSize() ;
1498 }
1499 else
1500 {
1501 if ( m_vScrollBar )
1502 return m_vScrollBar->GetThumbSize() ;
1503 }
1504#endif
1505 return 0;
1506}
1507
1508void wxWindowMac::SetScrollPos(int orient, int pos, bool WXUNUSED(refresh))
1509{
1510#if wxUSE_SCROLLBAR
1511 if ( orient == wxHORIZONTAL )
1512 {
1513 if ( m_hScrollBar )
1514 m_hScrollBar->SetThumbPosition( pos ) ;
1515 }
1516 else
1517 {
1518 if ( m_vScrollBar )
1519 m_vScrollBar->SetThumbPosition( pos ) ;
1520 }
1521#endif
1522}
1523
1524void
1525wxWindowMac::AlwaysShowScrollbars(bool hflag, bool vflag)
1526{
1527 bool needVisibilityUpdate = false;
1528
1529 if ( m_hScrollBarAlwaysShown != hflag )
1530 {
1531 m_hScrollBarAlwaysShown = hflag;
1532 needVisibilityUpdate = true;
1533 }
1534
1535 if ( m_vScrollBarAlwaysShown != vflag )
1536 {
1537 m_vScrollBarAlwaysShown = vflag;
1538 needVisibilityUpdate = true;
1539 }
1540
1541 if ( needVisibilityUpdate )
1542 DoUpdateScrollbarVisibility();
1543}
1544
1545//
1546// we draw borders and grow boxes, are already set up and clipped in the current port / cgContextRef
1547// our own window origin is at leftOrigin/rightOrigin
1548//
1549
1550void wxWindowMac::MacPaintGrowBox()
1551{
1552 if ( IsTopLevel() )
1553 return ;
1554
1555#if wxUSE_SCROLLBAR
1556 if ( MacHasScrollBarCorner() )
1557 {
1558#if 0
1559 CGContextRef cgContext = (CGContextRef) MacGetCGContextRef() ;
1560 wxASSERT( cgContext ) ;
1561
1562 int tx,ty,tw,th;
1563
1564 GetPeer()->GetSize( tw, th );
1565 GetPeer()->GetPosition( tx, ty );
1566
1567 Rect rect = { ty,tx, ty+th, tx+tw };
1568
1569
1570 int size = m_hScrollBar ? m_hScrollBar->GetSize().y : ( m_vScrollBar ? m_vScrollBar->GetSize().x : MAC_SCROLLBAR_SIZE ) ;
1571 CGRect cgrect = CGRectMake( rect.right - size , rect.bottom - size , size , size ) ;
1572 CGContextSaveGState( cgContext );
1573
1574 if ( m_backgroundColour.IsOk() )
1575 {
1576 CGContextSetFillColorWithColor( cgContext, m_backgroundColour.GetCGColor() );
1577 }
1578 else
1579 {
1580 CGContextSetRGBFillColor( cgContext, (CGFloat) 1.0, (CGFloat)1.0 ,(CGFloat) 1.0 , (CGFloat)1.0 );
1581 }
1582 CGContextFillRect( cgContext, cgrect );
1583 CGContextRestoreGState( cgContext );
1584#else
1585 if (m_growBox)
1586 {
1587 if ( m_backgroundColour.IsOk() )
1588 m_growBox->SetBackgroundColour(m_backgroundColour);
1589 else
1590 m_growBox->SetBackgroundColour(*wxWHITE);
1591 }
1592#endif
1593 }
1594
1595#endif
1596}
1597
1598void wxWindowMac::MacPaintBorders( int WXUNUSED(leftOrigin) , int WXUNUSED(rightOrigin) )
1599{
1600 if ( IsTopLevel() )
1601 return ;
1602
1603 bool hasFocus = GetPeer()->NeedsFocusRect() && HasFocus();
1604
1605 // back to the surrounding frame rectangle
1606 int tx,ty,tw,th;
1607
1608 GetPeer()->GetSize( tw, th );
1609 GetPeer()->GetPosition( tx, ty );
1610
1611#if wxOSX_USE_COCOA_OR_CARBON
1612
1613 {
1614 CGRect cgrect = CGRectMake( tx-1 , ty-1 , tw+2 ,
1615 th+2 ) ;
1616
1617 CGContextRef cgContext = (CGContextRef) GetParent()->MacGetCGContextRef() ;
1618 wxASSERT( cgContext ) ;
1619
1620 if ( GetPeer()->NeedsFrame() )
1621 {
1622 HIThemeFrameDrawInfo info ;
1623 memset( &info, 0 , sizeof(info) ) ;
1624
1625 info.version = 0 ;
1626 info.kind = 0 ;
1627 info.state = IsEnabled() ? kThemeStateActive : kThemeStateInactive ;
1628 info.isFocused = hasFocus ;
1629
1630 if ( HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER) || HasFlag(wxDOUBLE_BORDER) )
1631 {
1632 info.kind = kHIThemeFrameTextFieldSquare ;
1633 HIThemeDrawFrame( &cgrect , &info , cgContext , kHIThemeOrientationNormal ) ;
1634 }
1635 else if ( HasFlag(wxSIMPLE_BORDER) )
1636 {
1637 info.kind = kHIThemeFrameListBox ;
1638 HIThemeDrawFrame( &cgrect , &info , cgContext , kHIThemeOrientationNormal ) ;
1639 }
1640 }
1641
1642 if ( hasFocus )
1643 {
1644 HIThemeDrawFocusRect( &cgrect , true , cgContext , kHIThemeOrientationNormal ) ;
1645 }
1646 }
1647#endif // wxOSX_USE_COCOA_OR_CARBON
1648}
1649
1650void wxWindowMac::RemoveChild( wxWindowBase *child )
1651{
1652#if wxUSE_SCROLLBAR
1653 if ( child == m_hScrollBar )
1654 m_hScrollBar = NULL ;
1655 if ( child == m_vScrollBar )
1656 m_vScrollBar = NULL ;
1657 if ( child == m_growBox )
1658 m_growBox = NULL ;
1659#endif
1660 wxWindowBase::RemoveChild( child ) ;
1661}
1662
1663void wxWindowMac::DoUpdateScrollbarVisibility()
1664{
1665#if wxUSE_SCROLLBAR
1666 bool triggerSizeEvent = false;
1667
1668 if ( m_hScrollBar )
1669 {
1670 bool showHScrollBar = m_hScrollBarAlwaysShown || m_hScrollBar->IsNeeded();
1671
1672 if ( m_hScrollBar->IsShown() != showHScrollBar )
1673 {
1674 m_hScrollBar->Show( showHScrollBar );
1675 triggerSizeEvent = true;
1676 }
1677 }
1678
1679 if ( m_vScrollBar)
1680 {
1681 bool showVScrollBar = m_vScrollBarAlwaysShown || m_vScrollBar->IsNeeded();
1682
1683 if ( m_vScrollBar->IsShown() != showVScrollBar )
1684 {
1685 m_vScrollBar->Show( showVScrollBar ) ;
1686 triggerSizeEvent = true;
1687 }
1688 }
1689
1690 MacRepositionScrollBars() ;
1691 if ( triggerSizeEvent )
1692 {
1693 SendSizeEvent();
1694 }
1695#endif
1696}
1697
1698// New function that will replace some of the above.
1699void wxWindowMac::SetScrollbar(int orient, int pos, int thumb,
1700 int range, bool refresh)
1701{
1702#if wxUSE_SCROLLBAR
1703 // Updating scrollbars when window is being deleted is useless and
1704 // currently results in asserts in client-to-screen coordinates conversion
1705 // code which is used by DoUpdateScrollbarVisibility() so just skip it.
1706 if ( m_isBeingDeleted )
1707 return;
1708
1709 if ( orient == wxHORIZONTAL && m_hScrollBar )
1710 m_hScrollBar->SetScrollbar(pos, thumb, range, thumb, refresh);
1711 else if ( orient == wxVERTICAL && m_vScrollBar )
1712 m_vScrollBar->SetScrollbar(pos, thumb, range, thumb, refresh);
1713
1714 DoUpdateScrollbarVisibility();
1715#endif
1716}
1717
1718// Does a physical scroll
1719void wxWindowMac::ScrollWindow(int dx, int dy, const wxRect *rect)
1720{
1721 if ( dx == 0 && dy == 0 )
1722 return ;
1723
1724 int width , height ;
1725 GetClientSize( &width , &height ) ;
1726
1727 {
1728 wxRect scrollrect( MacGetLeftBorderSize() , MacGetTopBorderSize() , width , height ) ;
1729 if ( rect )
1730 scrollrect.Intersect( *rect ) ;
1731 // as the native control might be not a 0/0 wx window coordinates, we have to offset
1732 scrollrect.Offset( -MacGetLeftBorderSize() , -MacGetTopBorderSize() ) ;
1733
1734 GetPeer()->ScrollRect( &scrollrect, dx, dy );
1735 }
1736
1737 wxWindowMac *child;
1738 int x, y, w, h;
1739 for (wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); node; node = node->GetNext())
1740 {
1741 child = node->GetData();
1742 if (child == NULL)
1743 continue;
1744
1745 if (child->IsTopLevel())
1746 continue;
1747
1748 if ( !IsClientAreaChild(child) )
1749 continue;
1750
1751 child->GetPosition( &x, &y );
1752 child->GetSize( &w, &h );
1753 if (rect)
1754 {
1755 wxRect rc( x, y, w, h );
1756 if (rect->Intersects( rc ))
1757 child->SetSize( x + dx, y + dy, w, h, wxSIZE_AUTO|wxSIZE_ALLOW_MINUS_ONE );
1758 }
1759 else
1760 {
1761 child->SetSize( x + dx, y + dy, w, h, wxSIZE_AUTO|wxSIZE_ALLOW_MINUS_ONE );
1762 }
1763 }
1764}
1765
1766void wxWindowMac::MacOnScroll( wxScrollEvent &event )
1767{
1768#if wxUSE_SCROLLBAR
1769 if ( event.GetEventObject() == m_vScrollBar || event.GetEventObject() == m_hScrollBar )
1770 {
1771 wxScrollWinEvent wevent;
1772 wevent.SetPosition(event.GetPosition());
1773 wevent.SetOrientation(event.GetOrientation());
1774 wevent.SetEventObject(this);
1775
1776 if (event.GetEventType() == wxEVT_SCROLL_TOP)
1777 wevent.SetEventType( wxEVT_SCROLLWIN_TOP );
1778 else if (event.GetEventType() == wxEVT_SCROLL_BOTTOM)
1779 wevent.SetEventType( wxEVT_SCROLLWIN_BOTTOM );
1780 else if (event.GetEventType() == wxEVT_SCROLL_LINEUP)
1781 wevent.SetEventType( wxEVT_SCROLLWIN_LINEUP );
1782 else if (event.GetEventType() == wxEVT_SCROLL_LINEDOWN)
1783 wevent.SetEventType( wxEVT_SCROLLWIN_LINEDOWN );
1784 else if (event.GetEventType() == wxEVT_SCROLL_PAGEUP)
1785 wevent.SetEventType( wxEVT_SCROLLWIN_PAGEUP );
1786 else if (event.GetEventType() == wxEVT_SCROLL_PAGEDOWN)
1787 wevent.SetEventType( wxEVT_SCROLLWIN_PAGEDOWN );
1788 else if (event.GetEventType() == wxEVT_SCROLL_THUMBTRACK)
1789 wevent.SetEventType( wxEVT_SCROLLWIN_THUMBTRACK );
1790 else if (event.GetEventType() == wxEVT_SCROLL_THUMBRELEASE)
1791 wevent.SetEventType( wxEVT_SCROLLWIN_THUMBRELEASE );
1792
1793 HandleWindowEvent(wevent);
1794 }
1795#endif
1796}
1797
1798wxWindow *wxWindowBase::DoFindFocus()
1799{
1800 return wxFindWindowFromWXWidget(wxWidgetImpl::FindFocus());
1801}
1802
1803// Raise the window to the top of the Z order
1804void wxWindowMac::Raise()
1805{
1806 GetPeer()->Raise();
1807}
1808
1809// Lower the window to the bottom of the Z order
1810void wxWindowMac::Lower()
1811{
1812 GetPeer()->Lower();
1813}
1814
1815// static wxWindow *gs_lastWhich = NULL;
1816
1817bool wxWindowMac::MacSetupCursor( const wxPoint& pt )
1818{
1819 // first trigger a set cursor event
1820
1821 wxPoint clientorigin = GetClientAreaOrigin() ;
1822 wxSize clientsize = GetClientSize() ;
1823 wxCursor cursor ;
1824 if ( wxRect2DInt( clientorigin.x , clientorigin.y , clientsize.x , clientsize.y ).Contains( wxPoint2DInt( pt ) ) )
1825 {
1826 wxSetCursorEvent event( pt.x , pt.y );
1827 event.SetId(GetId());
1828 event.SetEventObject(this);
1829
1830 bool processedEvtSetCursor = HandleWindowEvent(event);
1831 if ( processedEvtSetCursor && event.HasCursor() )
1832 {
1833 cursor = event.GetCursor() ;
1834 }
1835 else
1836 {
1837 // the test for processedEvtSetCursor is here to prevent using m_cursor
1838 // if the user code caught EVT_SET_CURSOR() and returned nothing from
1839 // it - this is a way to say that our cursor shouldn't be used for this
1840 // point
1841 if ( !processedEvtSetCursor && m_cursor.IsOk() )
1842 cursor = m_cursor ;
1843
1844 if ( !wxIsBusy() && !GetParent() )
1845 cursor = *wxSTANDARD_CURSOR ;
1846 }
1847
1848 if ( cursor.IsOk() )
1849 cursor.MacInstall() ;
1850 }
1851
1852 return cursor.IsOk() ;
1853}
1854
1855wxString wxWindowMac::MacGetToolTipString( wxPoint &WXUNUSED(pt) )
1856{
1857#if wxUSE_TOOLTIPS
1858 if ( m_tooltip )
1859 return m_tooltip->GetTip() ;
1860#endif
1861
1862 return wxEmptyString ;
1863}
1864
1865void wxWindowMac::ClearBackground()
1866{
1867 Refresh() ;
1868 Update() ;
1869}
1870
1871void wxWindowMac::Update()
1872{
1873 wxNonOwnedWindow* top = MacGetTopLevelWindow();
1874 if (top)
1875 top->Update() ;
1876}
1877
1878wxNonOwnedWindow* wxWindowMac::MacGetTopLevelWindow() const
1879{
1880 wxWindowMac *iter = (wxWindowMac*)this ;
1881
1882 while ( iter )
1883 {
1884 if ( iter->IsTopLevel() )
1885 {
1886 wxTopLevelWindow* toplevel = wxDynamicCast(iter,wxTopLevelWindow);
1887 if ( toplevel )
1888 return toplevel;
1889#if wxUSE_POPUPWIN
1890 wxPopupWindow* popupwin = wxDynamicCast(iter,wxPopupWindow);
1891 if ( popupwin )
1892 return popupwin;
1893#endif
1894 }
1895 iter = iter->GetParent() ;
1896 }
1897
1898 return NULL ;
1899}
1900
1901const wxRect& wxWindowMac::MacGetClippedClientRect() const
1902{
1903 MacUpdateClippedRects() ;
1904
1905 return m_cachedClippedClientRect ;
1906}
1907
1908const wxRect& wxWindowMac::MacGetClippedRect() const
1909{
1910 MacUpdateClippedRects() ;
1911
1912 return m_cachedClippedRect ;
1913}
1914
1915const wxRect&wxWindowMac:: MacGetClippedRectWithOuterStructure() const
1916{
1917 MacUpdateClippedRects() ;
1918
1919 return m_cachedClippedRectWithOuterStructure ;
1920}
1921
1922const wxRegion& wxWindowMac::MacGetVisibleRegion( bool includeOuterStructures )
1923{
1924 static wxRegion emptyrgn ;
1925
1926 if ( !m_isBeingDeleted && IsShownOnScreen() )
1927 {
1928 MacUpdateClippedRects() ;
1929 if ( includeOuterStructures )
1930 return m_cachedClippedRegionWithOuterStructure ;
1931 else
1932 return m_cachedClippedRegion ;
1933 }
1934 else
1935 {
1936 return emptyrgn ;
1937 }
1938}
1939
1940void wxWindowMac::MacUpdateClippedRects() const
1941{
1942#if wxOSX_USE_CARBON
1943 if ( m_cachedClippedRectValid )
1944 return ;
1945
1946 // includeOuterStructures is true if we try to draw somthing like a focus ring etc.
1947 // also a window dc uses this, in this case we only clip in the hierarchy for hard
1948 // borders like a scrollwindow, splitter etc otherwise we end up in a paranoia having
1949 // to add focus borders everywhere
1950
1951 Rect rIncludingOuterStructures ;
1952
1953 int tx,ty,tw,th;
1954
1955 GetPeer()->GetSize( tw, th );
1956 GetPeer()->GetPosition( tx, ty );
1957
1958 Rect r = { ty,tx, ty+th, tx+tw };
1959
1960 r.left -= MacGetLeftBorderSize() ;
1961 r.top -= MacGetTopBorderSize() ;
1962 r.bottom += MacGetBottomBorderSize() ;
1963 r.right += MacGetRightBorderSize() ;
1964
1965 r.right -= r.left ;
1966 r.bottom -= r.top ;
1967 r.left = 0 ;
1968 r.top = 0 ;
1969
1970 rIncludingOuterStructures = r ;
1971 InsetRect( &rIncludingOuterStructures , -4 , -4 ) ;
1972
1973 wxRect cl = GetClientRect() ;
1974 Rect rClient = { cl.y , cl.x , cl.y + cl.height , cl.x + cl.width } ;
1975
1976 int x , y ;
1977 wxSize size ;
1978 const wxWindow* child = (wxWindow*) this ;
1979 const wxWindow* parent = NULL ;
1980
1981 while ( !child->IsTopLevel() && ( parent = child->GetParent() ) != NULL )
1982 {
1983 if ( parent->MacIsChildOfClientArea(child) )
1984 {
1985 size = parent->GetClientSize() ;
1986 wxPoint origin = parent->GetClientAreaOrigin() ;
1987 x = origin.x ;
1988 y = origin.y ;
1989 }
1990 else
1991 {
1992 // this will be true for scrollbars, toolbars etc.
1993 size = parent->GetSize() ;
1994 y = parent->MacGetTopBorderSize() ;
1995 x = parent->MacGetLeftBorderSize() ;
1996 size.x -= parent->MacGetLeftBorderSize() + parent->MacGetRightBorderSize() ;
1997 size.y -= parent->MacGetTopBorderSize() + parent->MacGetBottomBorderSize() ;
1998 }
1999
2000 parent->MacWindowToRootWindow( &x, &y ) ;
2001 MacRootWindowToWindow( &x , &y ) ;
2002
2003 Rect rparent = { y , x , y + size.y , x + size.x } ;
2004
2005 // the wxwindow and client rects will always be clipped
2006 SectRect( &r , &rparent , &r ) ;
2007 SectRect( &rClient , &rparent , &rClient ) ;
2008
2009 // the structure only at 'hard' borders
2010 if ( parent->MacClipChildren() ||
2011 ( parent->GetParent() && parent->GetParent()->MacClipGrandChildren() ) )
2012 {
2013 SectRect( &rIncludingOuterStructures , &rparent , &rIncludingOuterStructures ) ;
2014 }
2015
2016 child = parent ;
2017 }
2018
2019 m_cachedClippedRect = wxRect( r.left , r.top , r.right - r.left , r.bottom - r.top ) ;
2020 m_cachedClippedClientRect = wxRect( rClient.left , rClient.top ,
2021 rClient.right - rClient.left , rClient.bottom - rClient.top ) ;
2022 m_cachedClippedRectWithOuterStructure = wxRect(
2023 rIncludingOuterStructures.left , rIncludingOuterStructures.top ,
2024 rIncludingOuterStructures.right - rIncludingOuterStructures.left ,
2025 rIncludingOuterStructures.bottom - rIncludingOuterStructures.top ) ;
2026
2027 m_cachedClippedRegionWithOuterStructure = wxRegion( m_cachedClippedRectWithOuterStructure ) ;
2028 m_cachedClippedRegion = wxRegion( m_cachedClippedRect ) ;
2029 m_cachedClippedClientRegion = wxRegion( m_cachedClippedClientRect ) ;
2030
2031 m_cachedClippedRectValid = true ;
2032#endif
2033}
2034
2035/*
2036 This function must not change the updatergn !
2037 */
2038bool wxWindowMac::MacDoRedraw( long time )
2039{
2040 bool handled = false ;
2041
2042 wxRegion formerUpdateRgn = m_updateRegion;
2043 wxRegion clientUpdateRgn = formerUpdateRgn;
2044
2045 const wxRect clientRect = GetClientRect();
2046
2047 clientUpdateRgn.Intersect(clientRect);
2048
2049 // first send an erase event to the entire update area
2050 const wxBackgroundStyle bgStyle = GetBackgroundStyle();
2051 switch ( bgStyle )
2052 {
2053 case wxBG_STYLE_ERASE:
2054 case wxBG_STYLE_SYSTEM:
2055 case wxBG_STYLE_COLOUR:
2056 {
2057 // for the toplevel window this really is the entire area for
2058 // all the others only their client area, otherwise they might
2059 // be drawing with full alpha and eg put blue into the grow-box
2060 // area of a scrolled window (scroll sample)
2061 wxWindowDC dc(this);
2062 if ( IsTopLevel() )
2063 dc.SetDeviceClippingRegion(formerUpdateRgn);
2064 else
2065 dc.SetDeviceClippingRegion(clientUpdateRgn);
2066
2067 if ( bgStyle == wxBG_STYLE_ERASE )
2068 {
2069 wxEraseEvent eevent( GetId(), &dc );
2070 eevent.SetEventObject( this );
2071 if ( ProcessWindowEvent( eevent ) )
2072 break;
2073 }
2074
2075 if ( UseBgCol() )
2076 {
2077 dc.SetBackground(GetBackgroundColour());
2078 dc.Clear();
2079 }
2080 }
2081 break;
2082
2083 case wxBG_STYLE_PAINT:
2084 case wxBG_STYLE_TRANSPARENT:
2085 // nothing to do, user-defined EVT_PAINT handler will overwrite the
2086 // entire window client area
2087 break;
2088
2089 default:
2090 wxFAIL_MSG( "unsupported background style" );
2091 }
2092
2093 // as this is a full window, shouldn't be necessary anymore
2094 // MacPaintGrowBox();
2095
2096 // calculate a client-origin version of the update rgn and set
2097 // m_updateRegion to that
2098 clientUpdateRgn.Offset(-clientRect.GetPosition());
2099 m_updateRegion = clientUpdateRgn ;
2100
2101 if ( !m_updateRegion.Empty() )
2102 {
2103 // paint the window itself
2104
2105 wxPaintEvent event(GetId());
2106 event.SetTimestamp(time);
2107 event.SetEventObject(this);
2108 handled = HandleWindowEvent(event);
2109 }
2110
2111 m_updateRegion = formerUpdateRgn;
2112
2113 wxNonOwnedWindow* top = MacGetTopLevelWindow();
2114 if (top)
2115 top->WindowWasPainted() ;
2116
2117 return handled;
2118}
2119
2120void wxWindowMac::MacPaintChildrenBorders()
2121{
2122 // now we cannot rely on having its borders drawn by a window itself, as it does not
2123 // get the updateRgn wide enough to always do so, so we do it from the parent
2124 // this would also be the place to draw any custom backgrounds for native controls
2125 // in Composited windowing
2126 wxPoint clientOrigin = GetClientAreaOrigin() ;
2127
2128 wxWindowMac *child;
2129 int x, y, w, h;
2130 for (wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); node; node = node->GetNext())
2131 {
2132 child = node->GetData();
2133 if (child == NULL)
2134 continue;
2135#if wxUSE_SCROLLBAR
2136 if (child == m_vScrollBar)
2137 continue;
2138 if (child == m_hScrollBar)
2139 continue;
2140 if (child == m_growBox)
2141 continue;
2142#endif
2143 if (child->IsTopLevel())
2144 continue;
2145 if (!child->IsShown())
2146 continue;
2147
2148 // only draw those in the update region (add a safety margin of 10 pixels for shadow effects
2149
2150 child->GetPosition( &x, &y );
2151 child->GetSize( &w, &h );
2152
2153 if ( m_updateRegion.Contains(clientOrigin.x+x-10, clientOrigin.y+y-10, w+20, h+20) )
2154 {
2155 // paint custom borders
2156 wxNcPaintEvent eventNc( child->GetId() );
2157 eventNc.SetEventObject( child );
2158 if ( !child->HandleWindowEvent( eventNc ) )
2159 {
2160 child->MacPaintBorders(0, 0) ;
2161 }
2162 }
2163 }
2164}
2165
2166
2167WXWindow wxWindowMac::MacGetTopLevelWindowRef() const
2168{
2169 wxNonOwnedWindow* tlw = MacGetTopLevelWindow();
2170 return tlw ? tlw->GetWXWindow() : NULL ;
2171}
2172
2173bool wxWindowMac::MacHasScrollBarCorner() const
2174{
2175#if wxUSE_SCROLLBAR
2176 /* Returns whether the scroll bars in a wxScrolledWindow should be
2177 * shortened. Scroll bars should be shortened if either:
2178 *
2179 * - both scroll bars are visible, or
2180 *
2181 * - there is a resize box in the parent frame's corner and this
2182 * window shares the bottom and right edge with the parent
2183 * frame.
2184 */
2185
2186 if ( m_hScrollBar == NULL && m_vScrollBar == NULL )
2187 return false;
2188
2189 if ( ( m_hScrollBar && m_hScrollBar->IsShown() )
2190 && ( m_vScrollBar && m_vScrollBar->IsShown() ) )
2191 {
2192 // Both scroll bars visible
2193 return true;
2194 }
2195 else
2196 {
2197 wxPoint thisWindowBottomRight = GetScreenRect().GetBottomRight();
2198
2199 for ( const wxWindow *win = (wxWindow*)this; win; win = win->GetParent() )
2200 {
2201 const wxFrame *frame = wxDynamicCast( win, wxFrame ) ;
2202 if ( frame )
2203 {
2204 // starting from 10.7 there are no resize indicators anymore
2205 if ( (frame->GetWindowStyleFlag() & wxRESIZE_BORDER) && UMAGetSystemVersion() < 0x1070)
2206 {
2207 // Parent frame has resize handle
2208 wxPoint frameBottomRight = frame->GetScreenRect().GetBottomRight();
2209
2210 // Note: allow for some wiggle room here as wxMac's
2211 // window rect calculations seem to be imprecise
2212 if ( abs( thisWindowBottomRight.x - frameBottomRight.x ) <= 2
2213 && abs( thisWindowBottomRight.y - frameBottomRight.y ) <= 2 )
2214 {
2215 // Parent frame has resize handle and shares
2216 // right bottom corner
2217 return true ;
2218 }
2219 else
2220 {
2221 // Parent frame has resize handle but doesn't
2222 // share right bottom corner
2223 return false ;
2224 }
2225 }
2226 else
2227 {
2228 // Parent frame doesn't have resize handle
2229 return false ;
2230 }
2231 }
2232 }
2233
2234 // No parent frame found
2235 return false ;
2236 }
2237#else
2238 return false;
2239#endif
2240}
2241
2242void wxWindowMac::MacCreateScrollBars( long style )
2243{
2244#if wxUSE_SCROLLBAR
2245 wxASSERT_MSG( m_vScrollBar == NULL && m_hScrollBar == NULL , wxT("attempt to create window twice") ) ;
2246
2247 if ( style & ( wxVSCROLL | wxHSCROLL ) )
2248 {
2249 int scrlsize = MAC_SCROLLBAR_SIZE ;
2250 if ( GetWindowVariant() == wxWINDOW_VARIANT_SMALL || GetWindowVariant() == wxWINDOW_VARIANT_MINI )
2251 {
2252 scrlsize = MAC_SMALL_SCROLLBAR_SIZE ;
2253 }
2254
2255 int adjust = MacHasScrollBarCorner() ? scrlsize - 1: 0 ;
2256 int width, height ;
2257 GetClientSize( &width , &height ) ;
2258
2259 wxPoint vPoint(width - scrlsize, 0) ;
2260 wxSize vSize(scrlsize, height - adjust) ;
2261 wxPoint hPoint(0, height - scrlsize) ;
2262 wxSize hSize(width - adjust, scrlsize) ;
2263
2264 // we have to set the min size to a smaller value, otherwise they cannot get smaller (InitialSize sets MinSize)
2265 if ( style & wxVSCROLL )
2266 {
2267 m_vScrollBar = new wxScrollBar((wxWindow*)this, wxID_ANY, vPoint, vSize , wxVERTICAL);
2268 m_vScrollBar->SetMinSize( wxDefaultSize );
2269 }
2270
2271 if ( style & wxHSCROLL )
2272 {
2273 m_hScrollBar = new wxScrollBar((wxWindow*)this, wxID_ANY, hPoint, hSize , wxHORIZONTAL);
2274 m_hScrollBar->SetMinSize( wxDefaultSize );
2275 }
2276
2277 wxPoint gPoint(width - scrlsize, height - scrlsize);
2278 wxSize gSize(scrlsize, scrlsize);
2279 m_growBox = new wxBlindPlateWindow((wxWindow *)this, wxID_ANY, gPoint, gSize, 0);
2280 }
2281
2282 // because the create does not take into account the client area origin
2283 // we might have a real position shift
2284 MacRepositionScrollBars() ;
2285#endif
2286}
2287
2288bool wxWindowMac::MacIsChildOfClientArea( const wxWindow* child ) const
2289{
2290 bool result = ((child == NULL)
2291#if wxUSE_SCROLLBAR
2292 || ((child != m_hScrollBar) && (child != m_vScrollBar) && (child != m_growBox))
2293#endif
2294 );
2295
2296 return result ;
2297}
2298
2299void wxWindowMac::MacRepositionScrollBars()
2300{
2301#if wxUSE_SCROLLBAR
2302 if ( !m_hScrollBar && !m_vScrollBar )
2303 return ;
2304
2305 int scrlsize = m_hScrollBar ? m_hScrollBar->GetSize().y : ( m_vScrollBar ? m_vScrollBar->GetSize().x : MAC_SCROLLBAR_SIZE ) ;
2306 int adjust = MacHasScrollBarCorner() ? scrlsize - 1 : 0 ;
2307
2308 // get real client area
2309 int width, height ;
2310 GetSize( &width , &height );
2311
2312 width -= MacGetLeftBorderSize() + MacGetRightBorderSize();
2313 height -= MacGetTopBorderSize() + MacGetBottomBorderSize();
2314
2315 wxPoint vPoint( width - scrlsize, 0 ) ;
2316 wxSize vSize( scrlsize, height - adjust ) ;
2317 wxPoint hPoint( 0 , height - scrlsize ) ;
2318 wxSize hSize( width - adjust, scrlsize ) ;
2319
2320 if ( m_vScrollBar )
2321 m_vScrollBar->SetSize( vPoint.x , vPoint.y, vSize.x, vSize.y , wxSIZE_ALLOW_MINUS_ONE );
2322 if ( m_hScrollBar )
2323 m_hScrollBar->SetSize( hPoint.x , hPoint.y, hSize.x, hSize.y, wxSIZE_ALLOW_MINUS_ONE );
2324 if ( m_growBox )
2325 {
2326 if ( MacHasScrollBarCorner() )
2327 {
2328 m_growBox->SetSize( width - scrlsize, height - scrlsize, wxDefaultCoord, wxDefaultCoord, wxSIZE_USE_EXISTING );
2329 if ( !m_growBox->IsShown() )
2330 m_growBox->Show();
2331 }
2332 else
2333 {
2334 if ( m_growBox->IsShown() )
2335 m_growBox->Hide();
2336 }
2337 }
2338#endif
2339}
2340
2341bool wxWindowMac::AcceptsFocus() const
2342{
2343 if ( GetPeer() == NULL || GetPeer()->IsUserPane() )
2344 return wxWindowBase::AcceptsFocus();
2345 else
2346 return GetPeer()->CanFocus();
2347}
2348
2349void wxWindowMac::MacSuperChangedPosition()
2350{
2351 // only window-absolute structures have to be moved i.e. controls
2352
2353 m_cachedClippedRectValid = false ;
2354
2355 wxWindowMac *child;
2356 wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
2357 while ( node )
2358 {
2359 child = node->GetData();
2360 child->MacSuperChangedPosition() ;
2361
2362 node = node->GetNext();
2363 }
2364}
2365
2366void wxWindowMac::MacTopLevelWindowChangedPosition()
2367{
2368 // only screen-absolute structures have to be moved i.e. glcanvas
2369
2370 wxWindowMac *child;
2371 wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
2372 while ( node )
2373 {
2374 child = node->GetData();
2375 child->MacTopLevelWindowChangedPosition() ;
2376
2377 node = node->GetNext();
2378 }
2379}
2380
2381long wxWindowMac::MacGetWXBorderSize() const
2382{
2383 if ( IsTopLevel() )
2384 return 0 ;
2385
2386 SInt32 border = 0 ;
2387
2388 if ( GetPeer() && GetPeer()->NeedsFrame() )
2389 {
2390 if (HasFlag(wxRAISED_BORDER) || HasFlag( wxSUNKEN_BORDER) || HasFlag(wxDOUBLE_BORDER))
2391 {
2392#if wxOSX_USE_COCOA_OR_CARBON
2393 // this metric is only the 'outset' outside the simple frame rect
2394 GetThemeMetric( kThemeMetricEditTextFrameOutset , &border ) ;
2395 border += 1;
2396#else
2397 border += 2;
2398#endif
2399 }
2400 else if (HasFlag(wxSIMPLE_BORDER))
2401 {
2402#if wxOSX_USE_COCOA_OR_CARBON
2403 // this metric is only the 'outset' outside the simple frame rect
2404 GetThemeMetric( kThemeMetricListBoxFrameOutset , &border ) ;
2405 border += 1;
2406#else
2407 border += 1;
2408#endif
2409 }
2410 }
2411
2412 return border ;
2413}
2414
2415long wxWindowMac::MacGetLeftBorderSize() const
2416{
2417 // the wx borders are all symmetric in mac themes
2418 long border = MacGetWXBorderSize() ;
2419
2420 if ( GetPeer() )
2421 {
2422 int left, top, right, bottom;
2423 GetPeer()->GetLayoutInset( left, top, right, bottom );
2424 border -= left;
2425 }
2426
2427 return border;
2428}
2429
2430
2431long wxWindowMac::MacGetRightBorderSize() const
2432{
2433 // the wx borders are all symmetric in mac themes
2434 long border = MacGetWXBorderSize() ;
2435
2436 if ( GetPeer() )
2437 {
2438 int left, top, right, bottom;
2439 GetPeer()->GetLayoutInset( left, top, right, bottom );
2440 border -= right;
2441 }
2442
2443 return border;
2444}
2445
2446long wxWindowMac::MacGetTopBorderSize() const
2447{
2448 // the wx borders are all symmetric in mac themes
2449 long border = MacGetWXBorderSize() ;
2450
2451 if ( GetPeer() )
2452 {
2453 int left, top, right, bottom;
2454 GetPeer()->GetLayoutInset( left, top, right, bottom );
2455 border -= top;
2456 }
2457
2458 return border;
2459}
2460
2461long wxWindowMac::MacGetBottomBorderSize() const
2462{
2463 // the wx borders are all symmetric in mac themes
2464 long border = MacGetWXBorderSize() ;
2465
2466 if ( GetPeer() )
2467 {
2468 int left, top, right, bottom;
2469 GetPeer()->GetLayoutInset( left, top, right, bottom );
2470 border -= bottom;
2471 }
2472
2473 return border;
2474}
2475
2476long wxWindowMac::MacRemoveBordersFromStyle( long style )
2477{
2478 return style & ~wxBORDER_MASK ;
2479}
2480
2481// Find the wxWindowMac at the current mouse position, returning the mouse
2482// position.
2483wxWindow * wxFindWindowAtPointer( wxPoint& pt )
2484{
2485 pt = wxGetMousePosition();
2486 wxWindowMac* found = wxFindWindowAtPoint(pt);
2487
2488 return (wxWindow*) found;
2489}
2490
2491// Get the current mouse position.
2492wxPoint wxGetMousePosition()
2493{
2494 int x, y;
2495
2496 wxGetMousePosition( &x, &y );
2497
2498 return wxPoint(x, y);
2499}
2500
2501void wxWindowMac::OnMouseEvent( wxMouseEvent &event )
2502{
2503 if ( event.GetEventType() == wxEVT_RIGHT_DOWN )
2504 {
2505 // copied from wxGTK : CS
2506 // VZ: shouldn't we move this to base class then?
2507
2508 // generate a "context menu" event: this is similar to wxEVT_RIGHT_DOWN
2509 // except that:
2510 //
2511 // (a) it's a command event and so is propagated to the parent
2512 // (b) under MSW it can be generated from kbd too
2513 // (c) it uses screen coords (because of (a))
2514 wxContextMenuEvent evtCtx(wxEVT_CONTEXT_MENU,
2515 this->GetId(),
2516 this->ClientToScreen(event.GetPosition()));
2517 evtCtx.SetEventObject(this);
2518 if ( ! HandleWindowEvent(evtCtx) )
2519 event.Skip() ;
2520 }
2521 else
2522 {
2523 event.Skip() ;
2524 }
2525}
2526
2527void wxWindowMac::TriggerScrollEvent( wxEventType WXUNUSED(scrollEvent) )
2528{
2529}
2530
2531Rect wxMacGetBoundsForControl( wxWindowMac* window , const wxPoint& pos , const wxSize &size , bool adjustForOrigin )
2532{
2533 int x, y, w, h ;
2534
2535 window->MacGetBoundsForControl( pos , size , x , y, w, h , adjustForOrigin ) ;
2536 Rect bounds = { static_cast<short>(y), static_cast<short>(x), static_cast<short>(y + h), static_cast<short>(x + w) };
2537
2538 return bounds ;
2539}
2540
2541bool wxWindowMac::OSXHandleClicked( double WXUNUSED(timestampsec) )
2542{
2543 return false;
2544}
2545
2546wxInt32 wxWindowMac::MacControlHit(WXEVENTHANDLERREF WXUNUSED(handler) , WXEVENTREF event )
2547{
2548#if wxOSX_USE_COCOA_OR_CARBON
2549 if ( OSXHandleClicked( GetEventTime((EventRef)event) ) )
2550 return noErr;
2551
2552 return eventNotHandledErr ;
2553#else
2554 return 0;
2555#endif
2556}
2557
2558bool wxWindowMac::Reparent(wxWindowBase *newParentBase)
2559{
2560 wxWindowMac *newParent = (wxWindowMac *)newParentBase;
2561 if ( !wxWindowBase::Reparent(newParent) )
2562 return false;
2563
2564 GetPeer()->RemoveFromParent();
2565 GetPeer()->Embed( GetParent()->GetPeer() );
2566
2567 MacChildAdded();
2568 return true;
2569}
2570
2571bool wxWindowMac::SetTransparent(wxByte alpha)
2572{
2573 SetBackgroundStyle(wxBG_STYLE_TRANSPARENT);
2574
2575 if ( alpha != m_macAlpha )
2576 {
2577 m_macAlpha = alpha ;
2578 Refresh() ;
2579 }
2580 return true ;
2581}
2582
2583
2584bool wxWindowMac::CanSetTransparent()
2585{
2586 return true ;
2587}
2588
2589wxByte wxWindowMac::GetTransparent() const
2590{
2591 return m_macAlpha ;
2592}
2593
2594bool wxWindowMac::IsShownOnScreen() const
2595{
2596 if ( GetPeer() && GetPeer()->IsOk() )
2597 {
2598 bool peerVis = GetPeer()->IsVisible();
2599 bool wxVis = wxWindowBase::IsShownOnScreen();
2600 if( peerVis != wxVis )
2601 {
2602 // CS : put a breakpoint here to investigate differences
2603 // between native an wx visibilities
2604 // the only place where I've encountered them until now
2605 // are the hiding/showing sequences where the vis-changed event is
2606 // first sent to the innermost control, while wx does things
2607 // from the outmost control
2608 wxVis = wxWindowBase::IsShownOnScreen();
2609 return wxVis;
2610 }
2611
2612 return GetPeer()->IsVisible();
2613 }
2614 return wxWindowBase::IsShownOnScreen();
2615}
2616
2617#if wxUSE_HOTKEY && wxOSX_USE_COCOA_OR_CARBON
2618
2619OSStatus
2620wxHotKeyHandler(EventHandlerCallRef WXUNUSED(nextHandler),
2621 EventRef event,
2622 void* WXUNUSED(userData))
2623{
2624 EventHotKeyID hotKeyId;
2625
2626 GetEventParameter( event, kEventParamDirectObject, typeEventHotKeyID, NULL, sizeof(hotKeyId), NULL, &hotKeyId);
2627
2628 for ( unsigned i = 0; i < s_hotkeys.size(); ++i )
2629 {
2630 if ( s_hotkeys[i].keyId == static_cast<int>(hotKeyId.id) )
2631 {
2632 unsigned char charCode ;
2633 UInt32 keyCode ;
2634 UInt32 modifiers ;
2635 UInt32 when = EventTimeToTicks( GetEventTime( event ) ) ;
2636
2637 GetEventParameter( event, kEventParamKeyMacCharCodes, typeChar, NULL, 1, NULL, &charCode );
2638 GetEventParameter( event, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode );
2639 GetEventParameter( event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers );
2640
2641 UInt32 keymessage = (keyCode << 8) + charCode;
2642
2643 wxKeyEvent wxevent(wxEVT_HOTKEY);
2644 wxevent.SetId(hotKeyId.id);
2645 wxTheApp->MacCreateKeyEvent( wxevent, s_hotkeys[i].window , keymessage ,
2646 modifiers , when , 0 ) ;
2647
2648 s_hotkeys[i].window->HandleWindowEvent(wxevent);
2649 }
2650 }
2651
2652 return noErr;
2653}
2654
2655bool wxWindowMac::RegisterHotKey(int hotkeyId, int modifiers, int keycode)
2656{
2657 for ( unsigned i = 0; i < s_hotkeys.size(); ++i )
2658 {
2659 if ( s_hotkeys[i].keyId == hotkeyId )
2660 {
2661 wxLogLastError(wxT("hotkeyId already registered"));
2662
2663 return false;
2664 }
2665 }
2666
2667 static bool installed = false;
2668 if ( !installed )
2669 {
2670 EventTypeSpec eventType;
2671 eventType.eventClass=kEventClassKeyboard;
2672 eventType.eventKind=kEventHotKeyPressed;
2673
2674 InstallApplicationEventHandler(&wxHotKeyHandler, 1, &eventType, NULL, NULL);
2675 installed = true;
2676 }
2677
2678 UInt32 mac_modifiers=0;
2679 if ( modifiers & wxMOD_ALT )
2680 mac_modifiers |= optionKey;
2681 if ( modifiers & wxMOD_SHIFT )
2682 mac_modifiers |= shiftKey;
2683 if ( modifiers & wxMOD_RAW_CONTROL )
2684 mac_modifiers |= controlKey;
2685 if ( modifiers & wxMOD_CONTROL )
2686 mac_modifiers |= cmdKey;
2687
2688 EventHotKeyRef hotKeyRef;
2689 EventHotKeyID hotKeyIDmac;
2690
2691 hotKeyIDmac.signature = 'WXMC';
2692 hotKeyIDmac.id = hotkeyId;
2693
2694 if ( RegisterEventHotKey(wxCharCodeWXToOSX((wxKeyCode)keycode), mac_modifiers, hotKeyIDmac,
2695 GetApplicationEventTarget(), 0, &hotKeyRef) != noErr )
2696 {
2697 wxLogLastError(wxT("RegisterHotKey"));
2698
2699 return false;
2700 }
2701 else
2702 {
2703 wxHotKeyRec v;
2704 v.ref = hotKeyRef;
2705 v.keyId = hotkeyId;
2706 v.window = this;
2707
2708 s_hotkeys.push_back(v);
2709 }
2710
2711 return true;
2712}
2713
2714bool wxWindowMac::UnregisterHotKey(int hotkeyId)
2715{
2716 for ( int i = ((int)s_hotkeys.size())-1; i>=0; -- i )
2717 {
2718 if ( s_hotkeys[i].keyId == hotkeyId )
2719 {
2720 EventHotKeyRef ref = s_hotkeys[i].ref;
2721 s_hotkeys.erase(s_hotkeys.begin() + i);
2722 if ( UnregisterEventHotKey(ref) != noErr )
2723 {
2724 wxLogLastError(wxT("UnregisterHotKey"));
2725
2726 return false;
2727 }
2728 else
2729 return true;
2730 }
2731 }
2732
2733 return false;
2734}
2735
2736#endif // wxUSE_HOTKEY
2737
2738bool wxWindowMac::OSXHandleKeyEvent( wxKeyEvent& event )
2739{
2740 bool handled = false;
2741
2742 // moved the ordinary key event sending AFTER the accel evaluation
2743
2744#if wxUSE_ACCEL
2745 if ( !handled && event.GetEventType() == wxEVT_KEY_DOWN)
2746 {
2747 wxWindow *ancestor = this;
2748 while (ancestor)
2749 {
2750 int command = ancestor->GetAcceleratorTable()->GetCommand( event );
2751 if (command != -1)
2752 {
2753 wxEvtHandler * const handler = ancestor->GetEventHandler();
2754
2755 wxCommandEvent command_event( wxEVT_MENU, command );
2756 handled = handler->ProcessEvent( command_event );
2757
2758 if ( !handled )
2759 {
2760 // accelerators can also be used with buttons, try them too
2761 command_event.SetEventType(wxEVT_BUTTON);
2762 handled = handler->ProcessEvent( command_event );
2763 }
2764
2765 break;
2766 }
2767
2768 if (ancestor->IsTopLevel())
2769 break;
2770
2771 ancestor = ancestor->GetParent();
2772 }
2773 }
2774#endif // wxUSE_ACCEL
2775
2776 if ( !handled )
2777 {
2778 handled = HandleWindowEvent( event ) ;
2779 if ( handled && event.GetSkipped() )
2780 handled = false ;
2781 }
2782
2783 return handled ;
2784}
2785
2786//
2787// wxWidgetImpl
2788//
2789
2790// we are maintaining a n:1 map from native controls (ControlRef / NSView*) to their wxWidgetImpl
2791// n:1 because we might have an embedded view eg within a scrollview, both being part of the same impl
2792// the impl is calling Associate with its newly created native control(s), e.g. in InstallHandler
2793
2794WX_DECLARE_HASH_MAP(WXWidget, wxWidgetImpl*, wxPointerHash, wxPointerEqual, MacControlMap);
2795
2796static MacControlMap wxWinMacControlList;
2797
2798wxWindowMac *wxFindWindowFromWXWidget(WXWidget inControl )
2799{
2800 wxWidgetImpl* impl = wxWidgetImpl::FindFromWXWidget( inControl );
2801 if ( impl )
2802 return impl->GetWXPeer();
2803
2804 return NULL;
2805}
2806
2807wxWidgetImpl *wxWidgetImpl::FindFromWXWidget(WXWidget inControl )
2808{
2809 MacControlMap::iterator node = wxWinMacControlList.find(inControl);
2810
2811 return (node == wxWinMacControlList.end()) ? NULL : node->second;
2812}
2813
2814void wxWidgetImpl::Associate(WXWidget inControl, wxWidgetImpl *impl)
2815{
2816 // adding NULL ControlRef is (first) surely a result of an error and
2817 // (secondly) breaks native event processing
2818 wxCHECK_RET( inControl != (WXWidget) NULL, wxT("attempt to add a NULL WXWidget to control map") );
2819
2820 wxWinMacControlList[inControl] = impl;
2821}
2822
2823void wxWidgetImpl::RemoveAssociations(wxWidgetImpl* impl)
2824{
2825 // iterate over all the elements in the class
2826 // is the iterator stable ? as we might have two associations pointing to the same wxWindow
2827 // we should go on...
2828
2829 bool found = true ;
2830 while ( found )
2831 {
2832 found = false ;
2833 MacControlMap::iterator it;
2834 for ( it = wxWinMacControlList.begin(); it != wxWinMacControlList.end(); ++it )
2835 {
2836 if ( it->second == impl )
2837 {
2838 wxWinMacControlList.erase(it);
2839 found = true ;
2840 break;
2841 }
2842 }
2843 }
2844}
2845
2846IMPLEMENT_ABSTRACT_CLASS( wxWidgetImpl , wxObject )
2847
2848wxWidgetImpl::wxWidgetImpl( wxWindowMac* peer , bool isRootControl, bool isUserPane )
2849{
2850 Init();
2851 m_isRootControl = isRootControl;
2852 m_isUserPane = isUserPane;
2853 m_wxPeer = peer;
2854 m_shouldSendEvents = true;
2855}
2856
2857wxWidgetImpl::wxWidgetImpl()
2858{
2859 Init();
2860}
2861
2862wxWidgetImpl::~wxWidgetImpl()
2863{
2864}
2865
2866void wxWidgetImpl::Init()
2867{
2868 m_isRootControl = false;
2869 m_wxPeer = NULL;
2870 m_needsFocusRect = false;
2871 m_needsFrame = true;
2872}
2873
2874void wxWidgetImpl::SetNeedsFocusRect( bool needs )
2875{
2876 m_needsFocusRect = needs;
2877}
2878
2879bool wxWidgetImpl::NeedsFocusRect() const
2880{
2881 return m_needsFocusRect;
2882}
2883
2884void wxWidgetImpl::SetNeedsFrame( bool needs )
2885{
2886 m_needsFrame = needs;
2887}
2888
2889bool wxWidgetImpl::NeedsFrame() const
2890{
2891 return m_needsFrame;
2892}
2893
2894void wxWidgetImpl::SetDrawingEnabled(bool WXUNUSED(enabled))
2895{
2896}