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