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