]> git.saurik.com Git - wxWidgets.git/blame - src/osx/carbon/window.cpp
avoiding warning because of missing define
[wxWidgets.git] / src / osx / carbon / window.cpp
CommitLineData
489468fe
SC
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/mac/carbon/window.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
b2680ced 64#if wxOSX_USE_CARBON
1f0c8f31 65#include "wx/osx/uma.h"
b2680ced
SC
66#else
67#include "wx/osx/private.h"
68#endif
489468fe
SC
69
70#define MAC_SCROLLBAR_SIZE 15
71#define MAC_SMALL_SCROLLBAR_SIZE 11
72
73#include <string.h>
74
75#ifdef __WXUNIVERSAL__
76 IMPLEMENT_ABSTRACT_CLASS(wxWindowMac, wxWindowBase)
77#else
78 IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowBase)
79#endif
80
81BEGIN_EVENT_TABLE(wxWindowMac, wxWindowBase)
82 EVT_NC_PAINT(wxWindowMac::OnNcPaint)
83 EVT_ERASE_BACKGROUND(wxWindowMac::OnEraseBackground)
84 EVT_PAINT(wxWindowMac::OnPaint)
85 EVT_MOUSE_EVENTS(wxWindowMac::OnMouseEvent)
86END_EVENT_TABLE()
87
88#define wxMAC_DEBUG_REDRAW 0
89#ifndef wxMAC_DEBUG_REDRAW
90#define wxMAC_DEBUG_REDRAW 0
91#endif
92
b2680ced
SC
93//
94// TODO BEGIN move to window_osx.cpp
95//
96// ===========================================================================
97// implementation
98// ===========================================================================
99
100WX_DECLARE_HASH_MAP(WXWidget, wxWindow*, wxPointerHash, wxPointerEqual, MacControlMap);
101
102static MacControlMap wxWinMacControlList;
103
104wxWindowMac *wxFindWindowFromWXWidget(WXWidget inControl )
105{
106 MacControlMap::iterator node = wxWinMacControlList.find(inControl);
107
108 return (node == wxWinMacControlList.end()) ? NULL : node->second;
109}
110
111void wxAssociateWindowWithWXWidget(WXWidget inControl, wxWindow *control)
112{
113 // adding NULL ControlRef is (first) surely a result of an error and
114 // (secondly) breaks native event processing
115 wxCHECK_RET( inControl != (WXWidget) NULL, wxT("attempt to add a NULL WindowRef to window list") );
116
117 wxWinMacControlList[inControl] = control;
118}
119
120void wxRemoveWXWidgetAssociation(wxWindow *control)
121{
122 // iterate over all the elements in the class
123 // is the iterator stable ? as we might have two associations pointing to the same wxWindow
124 // we should go on...
125
126 bool found = true ;
127 while ( found )
128 {
129 found = false ;
130 MacControlMap::iterator it;
131 for ( it = wxWinMacControlList.begin(); it != wxWinMacControlList.end(); ++it )
132 {
133 if ( it->second == control )
134 {
135 wxWinMacControlList.erase(it);
136 found = true ;
137 break;
138 }
139 }
140 }
141}
142
143// ----------------------------------------------------------------------------
144 // constructors and such
145// ----------------------------------------------------------------------------
146
147wxWindowMac::wxWindowMac()
148{
149 Init();
150}
151
152wxWindowMac::wxWindowMac(wxWindowMac *parent,
153 wxWindowID id,
154 const wxPoint& pos ,
155 const wxSize& size ,
156 long style ,
157 const wxString& name )
158{
159 Init();
160 Create(parent, id, pos, size, style, name);
161}
162
163void wxWindowMac::Init()
164{
165 m_peer = NULL ;
166 m_macAlpha = 255 ;
167 m_cgContextRef = NULL ;
168
169 // as all windows are created with WS_VISIBLE style...
170 m_isShown = true;
171
172 m_hScrollBar = NULL ;
173 m_vScrollBar = NULL ;
174 m_hScrollBarAlwaysShown = false;
175 m_vScrollBarAlwaysShown = false;
176
177 m_macIsUserPane = true;
178 m_clipChildren = false ;
179 m_cachedClippedRectValid = false ;
180}
181
182wxWindowMac::~wxWindowMac()
183{
184 SendDestroyEvent();
185
186 m_isBeingDeleted = true;
187
188 MacInvalidateBorders() ;
189
190#ifndef __WXUNIVERSAL__
191 // VS: make sure there's no wxFrame with last focus set to us:
192 for ( wxWindow *win = GetParent(); win; win = win->GetParent() )
193 {
194 wxFrame *frame = wxDynamicCast(win, wxFrame);
195 if ( frame )
196 {
197 if ( frame->GetLastFocus() == this )
198 frame->SetLastFocus((wxWindow*)NULL);
199 break;
200 }
201 }
202#endif
203
204 // destroy children before destroying this window itself
205 DestroyChildren();
206
207 // wxRemoveMacControlAssociation( this ) ;
208 // If we delete an item, we should initialize the parent panel,
209 // because it could now be invalid.
210 wxTopLevelWindow *tlw = wxDynamicCast(wxGetTopLevelParent((wxWindow*)this), wxTopLevelWindow);
211 if ( tlw )
212 {
213 if ( tlw->GetDefaultItem() == (wxButton*) this)
214 tlw->SetDefaultItem(NULL);
215 }
216
217 if ( m_peer && m_peer->IsOk() )
218 {
219 m_peer->Destroy() ;
220 }
221
222 if ( g_MacLastWindow == this )
223 g_MacLastWindow = NULL ;
224
225#ifndef __WXUNIVERSAL__
226 wxFrame* frame = wxDynamicCast( wxGetTopLevelParent( (wxWindow*)this ) , wxFrame ) ;
227 if ( frame )
228 {
229 if ( frame->GetLastFocus() == this )
230 frame->SetLastFocus( NULL ) ;
231 }
232#endif
233
234 // delete our drop target if we've got one
235#if wxUSE_DRAG_AND_DROP
236 if ( m_dropTarget != NULL )
237 {
238 delete m_dropTarget;
239 m_dropTarget = NULL;
240 }
241#endif
242
243 delete m_peer ;
244}
245
246WXWidget wxWindowMac::GetHandle() const
247{
248 return (WXWidget) m_peer->GetWXWidget() ;
249}
250
251//
252// TODO END move to window_osx.cpp
253//
254
489468fe
SC
255// ---------------------------------------------------------------------------
256// Utility Routines to move between different coordinate systems
257// ---------------------------------------------------------------------------
258
259/*
260 * Right now we have the following setup :
261 * a border that is not part of the native control is always outside the
262 * control's border (otherwise we loose all native intelligence, future ways
263 * may be to have a second embedding control responsible for drawing borders
264 * and backgrounds eventually)
265 * so all this border calculations have to be taken into account when calling
266 * native methods or getting native oriented data
267 * so we have three coordinate systems here
268 * wx client coordinates
269 * wx window coordinates (including window frames)
270 * native coordinates
271 */
272
273//
489468fe
SC
274//
275
b2680ced
SC
276// Constructor
277bool wxWindowMac::Create(wxWindowMac *parent,
278 wxWindowID id,
279 const wxPoint& pos,
280 const wxSize& size,
281 long style,
282 const wxString& name)
489468fe 283{
b2680ced 284 wxCHECK_MSG( parent, false, wxT("can't create wxWindowMac without parent") );
489468fe 285
b2680ced
SC
286 if ( !CreateBase(parent, id, pos, size, style, wxDefaultValidator, name) )
287 return false;
489468fe 288
b2680ced 289 m_windowVariant = parent->GetWindowVariant() ;
489468fe 290
b2680ced
SC
291 if ( m_macIsUserPane )
292 {
293#if wxOSX_USE_CARBON
294 m_peer = (wxMacControl*) wxWidgetImpl::CreateUserPane( this, pos, size , style, GetExtraStyle() , name );
295#else
296 m_peer = wxWidgetImpl::CreateUserPane( this, pos, size , style, GetExtraStyle() , name );
297#endif
298 MacPostControlCreate(pos, size) ;
299 }
300
301#ifndef __WXUNIVERSAL__
302 // Don't give scrollbars to wxControls unless they ask for them
303 if ( (! IsKindOf(CLASSINFO(wxControl)) && ! IsKindOf(CLASSINFO(wxStatusBar)))
304 || (IsKindOf(CLASSINFO(wxControl)) && ((style & wxHSCROLL) || (style & wxVSCROLL))))
305 {
306 MacCreateScrollBars( style ) ;
307 }
308#endif
309
310 wxWindowCreateEvent event((wxWindow*)this);
311 GetEventHandler()->AddPendingEvent(event);
312
313 return true;
489468fe
SC
314}
315
b2680ced 316void wxWindowMac::MacChildAdded()
489468fe 317{
b2680ced
SC
318 if ( m_vScrollBar )
319 m_vScrollBar->Raise() ;
320 if ( m_hScrollBar )
321 m_hScrollBar->Raise() ;
489468fe
SC
322}
323
b2680ced 324void wxWindowMac::MacPostControlCreate(const wxPoint& WXUNUSED(pos), const wxSize& size)
489468fe 325{
b2680ced 326 wxASSERT_MSG( m_peer != NULL && m_peer->IsOk() , wxT("No valid mac control") ) ;
489468fe 327
b2680ced
SC
328#if wxOSX_USE_CARBON
329 m_peer->SetReference( (URefCon) this ) ;
330#endif
489468fe 331
b2680ced 332 GetParent()->AddChild( this );
489468fe 333
b2680ced
SC
334#if wxOSX_USE_CARBON
335 m_peer->InstallEventHandler();
489468fe 336
b2680ced
SC
337 ControlRef container = (ControlRef) GetParent()->GetHandle() ;
338 wxASSERT_MSG( container != NULL , wxT("No valid mac container control") ) ;
339 ::EmbedControl( m_peer->GetControlRef() , container ) ;
340#endif
341 GetParent()->MacChildAdded() ;
489468fe 342
b2680ced
SC
343 // adjust font, controlsize etc
344 DoSetWindowVariant( m_windowVariant ) ;
345#if wxOSX_USE_CARBON
346 m_peer->SetLabel( wxStripMenuCodes(m_label, wxStrip_Mnemonics) ) ;
347#endif
348 if (!m_macIsUserPane)
349 SetInitialSize(size);
489468fe 350
b2680ced
SC
351 SetCursor( *wxSTANDARD_CURSOR ) ;
352}
489468fe 353
b2680ced 354void wxWindowMac::DoSetWindowVariant( wxWindowVariant variant )
489468fe 355{
b2680ced
SC
356 // Don't assert, in case we set the window variant before
357 // the window is created
358 // wxASSERT( m_peer->Ok() ) ;
489468fe 359
b2680ced 360 m_windowVariant = variant ;
489468fe 361
b2680ced
SC
362 if (m_peer == NULL || !m_peer->IsOk())
363 return;
489468fe 364
b2680ced 365#if wxOSX_USE_COCOA_OR_CARBON
489468fe 366
b2680ced
SC
367 ControlSize size ;
368 ThemeFontID themeFont = kThemeSystemFont ;
489468fe 369
b2680ced
SC
370 // we will get that from the settings later
371 // and make this NORMAL later, but first
372 // we have a few calculations that we must fix
489468fe 373
b2680ced
SC
374 switch ( variant )
375 {
376 case wxWINDOW_VARIANT_NORMAL :
377 size = kControlSizeNormal;
378 themeFont = kThemeSystemFont ;
379 break ;
489468fe 380
b2680ced
SC
381 case wxWINDOW_VARIANT_SMALL :
382 size = kControlSizeSmall;
383 themeFont = kThemeSmallSystemFont ;
384 break ;
489468fe 385
b2680ced
SC
386 case wxWINDOW_VARIANT_MINI :
387 // not always defined in the headers
388 size = 3 ;
389 themeFont = 109 ;
390 break ;
489468fe 391
b2680ced
SC
392 case wxWINDOW_VARIANT_LARGE :
393 size = kControlSizeLarge;
394 themeFont = kThemeSystemFont ;
395 break ;
489468fe 396
b2680ced
SC
397 default:
398 wxFAIL_MSG(_T("unexpected window variant"));
399 break ;
400 }
489468fe 401
b2680ced
SC
402#if wxOSX_USE_CARBON
403 m_peer->SetData<ControlSize>(kControlEntireControl, kControlSizeTag, &size ) ;
404#endif
489468fe 405
b2680ced
SC
406 wxFont font ;
407 font.MacCreateFromThemeFont( themeFont ) ;
408 SetFont( font ) ;
409#endif
410}
489468fe 411
b2680ced
SC
412void wxWindowMac::MacUpdateControlFont()
413{
414#if wxOSX_USE_CARBON
415 m_peer->SetFont( GetFont() , GetForegroundColour() , GetWindowStyle() ) ;
416#endif
417 // do not trigger refreshes upon invisible and possible partly created objects
418 if ( IsShownOnScreen() )
419 Refresh() ;
420}
489468fe 421
b2680ced
SC
422bool wxWindowMac::SetFont(const wxFont& font)
423{
424 bool retval = wxWindowBase::SetFont( font );
489468fe 425
b2680ced 426 MacUpdateControlFont() ;
489468fe 427
b2680ced
SC
428 return retval;
429}
489468fe 430
b2680ced
SC
431bool wxWindowMac::SetForegroundColour(const wxColour& col )
432{
433 bool retval = wxWindowBase::SetForegroundColour( col );
489468fe 434
b2680ced
SC
435 if (retval)
436 MacUpdateControlFont();
489468fe 437
b2680ced
SC
438 return retval;
439}
489468fe 440
b2680ced
SC
441bool wxWindowMac::SetBackgroundColour(const wxColour& col )
442{
443 if ( !wxWindowBase::SetBackgroundColour(col) && m_hasBgCol )
444 return false ;
489468fe 445
b2680ced
SC
446 if ( m_peer )
447 m_peer->SetBackgroundColour( col ) ;
489468fe 448
b2680ced
SC
449 return true ;
450}
489468fe 451
b2680ced
SC
452void wxWindowMac::SetFocus()
453{
454 if ( !AcceptsFocus() )
455 return ;
489468fe 456
b2680ced
SC
457 wxWindow* former = FindFocus() ;
458 if ( former == this )
459 return ;
489468fe 460
b2680ced
SC
461 m_peer->SetFocus() ;
462}
489468fe 463
b2680ced
SC
464void wxWindowMac::DoCaptureMouse()
465{
466 wxApp::s_captureWindow = (wxWindow*) this ;
467}
489468fe 468
b2680ced
SC
469wxWindow * wxWindowBase::GetCapture()
470{
471 return wxApp::s_captureWindow ;
472}
489468fe 473
b2680ced
SC
474void wxWindowMac::DoReleaseMouse()
475{
476 wxApp::s_captureWindow = NULL ;
477}
489468fe 478
b2680ced
SC
479#if wxUSE_DRAG_AND_DROP
480
481void wxWindowMac::SetDropTarget(wxDropTarget *pDropTarget)
482{
483 if ( m_dropTarget != NULL )
484 delete m_dropTarget;
485
486 m_dropTarget = pDropTarget;
487 if ( m_dropTarget != NULL )
488 {
489 // TODO:
490 }
491}
489468fe 492
489468fe
SC
493#endif
494
b2680ced
SC
495// Old-style File Manager Drag & Drop
496void wxWindowMac::DragAcceptFiles(bool WXUNUSED(accept))
497{
498 // TODO:
499}
489468fe 500
b2680ced 501// From a wx position / size calculate the appropriate size of the native control
489468fe 502
b2680ced
SC
503bool wxWindowMac::MacGetBoundsForControl(
504 const wxPoint& pos,
505 const wxSize& size,
506 int& x, int& y,
507 int& w, int& h , bool adjustOrigin ) const
508{
509 // the desired size, minus the border pixels gives the correct size of the control
510 x = (int)pos.x;
511 y = (int)pos.y;
489468fe 512
b2680ced
SC
513 // TODO: the default calls may be used as soon as PostCreateControl Is moved here
514 w = wxMax(size.x, 0) ; // WidthDefault( size.x );
515 h = wxMax(size.y, 0) ; // HeightDefault( size.y ) ;
489468fe 516
b2680ced
SC
517 x += MacGetLeftBorderSize() ;
518 y += MacGetTopBorderSize() ;
519 w -= MacGetLeftBorderSize() + MacGetRightBorderSize() ;
520 h -= MacGetTopBorderSize() + MacGetBottomBorderSize() ;
489468fe 521
b2680ced
SC
522 if ( adjustOrigin )
523 AdjustForParentClientOrigin( x , y ) ;
489468fe 524
b2680ced
SC
525 // this is in window relative coordinate, as this parent may have a border, its physical position is offset by this border
526 if ( !GetParent()->IsTopLevel() )
527 {
528 x -= GetParent()->MacGetLeftBorderSize() ;
529 y -= GetParent()->MacGetTopBorderSize() ;
530 }
489468fe 531
b2680ced
SC
532 return true ;
533}
489468fe 534
b2680ced
SC
535// Get window size (not client size)
536void wxWindowMac::DoGetSize(int *x, int *y) const
537{
538 int width, height;
539 m_peer->GetSize( width, height );
489468fe 540
b2680ced
SC
541 if (x)
542 *x = width + MacGetLeftBorderSize() + MacGetRightBorderSize() ;
543 if (y)
544 *y = height + MacGetTopBorderSize() + MacGetBottomBorderSize() ;
545}
489468fe 546
b2680ced
SC
547// get the position of the bounds of this window in client coordinates of its parent
548void wxWindowMac::DoGetPosition(int *x, int *y) const
549{
550 int x1, y1;
551
552 m_peer->GetPosition( x1, y1 ) ;
489468fe 553
b2680ced
SC
554 // get the wx window position from the native one
555 x1 -= MacGetLeftBorderSize() ;
556 y1 -= MacGetTopBorderSize() ;
489468fe 557
b2680ced
SC
558 if ( !IsTopLevel() )
559 {
560 wxWindow *parent = GetParent();
561 if ( parent )
562 {
563 // we must first adjust it to be in window coordinates of the parent,
564 // as otherwise it gets lost by the ClientAreaOrigin fix
565 x1 += parent->MacGetLeftBorderSize() ;
566 y1 += parent->MacGetTopBorderSize() ;
567
568 // and now to client coordinates
569 wxPoint pt(parent->GetClientAreaOrigin());
570 x1 -= pt.x ;
571 y1 -= pt.y ;
572 }
489468fe
SC
573 }
574
b2680ced
SC
575 if (x)
576 *x = x1 ;
577 if (y)
578 *y = y1 ;
489468fe
SC
579}
580
b2680ced 581void wxWindowMac::DoScreenToClient(int *x, int *y) const
489468fe 582{
b2680ced
SC
583 wxNonOwnedWindow* tlw = MacGetTopLevelWindow() ;
584 wxCHECK_RET( tlw , wxT("TopLevel Window missing") ) ;
585 tlw->GetNonOwnedPeer()->ScreenToWindow( x, y);
586 MacRootWindowToWindow( x , y ) ;
489468fe 587
b2680ced
SC
588 wxPoint origin = GetClientAreaOrigin() ;
589 if (x)
590 *x -= origin.x ;
591 if (y)
592 *y -= origin.y ;
593}
489468fe 594
b2680ced
SC
595void wxWindowMac::DoClientToScreen(int *x, int *y) const
596{
597 wxNonOwnedWindow* tlw = MacGetTopLevelWindow() ;
598 wxCHECK_RET( tlw , wxT("TopLevel window missing") ) ;
489468fe 599
b2680ced
SC
600 wxPoint origin = GetClientAreaOrigin() ;
601 if (x)
602 *x += origin.x ;
603 if (y)
604 *y += origin.y ;
489468fe 605
b2680ced
SC
606 MacWindowToRootWindow( x , y ) ;
607 tlw->GetNonOwnedPeer()->WindowToScreen( x , y );
608}
489468fe 609
b2680ced
SC
610void wxWindowMac::MacClientToRootWindow( int *x , int *y ) const
611{
612 wxPoint origin = GetClientAreaOrigin() ;
613 if (x)
614 *x += origin.x ;
615 if (y)
616 *y += origin.y ;
489468fe 617
b2680ced
SC
618 MacWindowToRootWindow( x , y ) ;
619}
489468fe 620
b2680ced
SC
621void wxWindowMac::MacWindowToRootWindow( int *x , int *y ) const
622{
623 wxPoint pt ;
489468fe 624
b2680ced
SC
625 if (x)
626 pt.x = *x ;
627 if (y)
628 pt.y = *y ;
489468fe 629
b2680ced
SC
630 if ( !IsTopLevel() )
631 {
632 wxNonOwnedWindow* top = MacGetTopLevelWindow();
633 if (top)
634 {
635 pt.x -= MacGetLeftBorderSize() ;
636 pt.y -= MacGetTopBorderSize() ;
637 wxWidgetImpl::Convert( &pt , m_peer , top->m_peer ) ;
638 }
639 }
489468fe 640
b2680ced
SC
641 if (x)
642 *x = (int) pt.x ;
643 if (y)
644 *y = (int) pt.y ;
645}
489468fe 646
b2680ced
SC
647void wxWindowMac::MacRootWindowToWindow( int *x , int *y ) const
648{
649 wxPoint pt ;
489468fe 650
b2680ced
SC
651 if (x)
652 pt.x = *x ;
653 if (y)
654 pt.y = *y ;
655
656 if ( !IsTopLevel() )
657 {
658 wxNonOwnedWindow* top = MacGetTopLevelWindow();
659 if (top)
660 {
661 wxWidgetImpl::Convert( &pt , top->m_peer , m_peer ) ;
662 pt.x += MacGetLeftBorderSize() ;
663 pt.y += MacGetTopBorderSize() ;
664 }
489468fe
SC
665 }
666
b2680ced
SC
667 if (x)
668 *x = (int) pt.x ;
669 if (y)
670 *y = (int) pt.y ;
489468fe
SC
671}
672
b2680ced 673wxSize wxWindowMac::DoGetSizeFromClientSize( const wxSize & size ) const
489468fe 674{
b2680ced 675 wxSize sizeTotal = size;
489468fe 676
b2680ced
SC
677 int innerwidth, innerheight;
678 int left, top;
679 int outerwidth, outerheight;
680
681 m_peer->GetContentArea( left, top, innerwidth, innerheight );
682 m_peer->GetSize( outerwidth, outerheight );
683
684 sizeTotal.x += left + (outerwidth-innerwidth);
685 sizeTotal.y += top + (outerheight-innerheight);
686
687 sizeTotal.x += MacGetLeftBorderSize() + MacGetRightBorderSize() ;
688 sizeTotal.y += MacGetTopBorderSize() + MacGetBottomBorderSize() ;
489468fe 689
b2680ced
SC
690 return sizeTotal;
691}
489468fe 692
b2680ced
SC
693// Get size *available for subwindows* i.e. excluding menu bar etc.
694void wxWindowMac::DoGetClientSize( int *x, int *y ) const
695{
696 int ww, hh;
489468fe 697
b2680ced
SC
698 int left, top;
699
700 m_peer->GetContentArea( left, top, ww, hh );
489468fe 701
b2680ced
SC
702 if (m_hScrollBar && m_hScrollBar->IsShown() )
703 hh -= m_hScrollBar->GetSize().y ;
489468fe 704
b2680ced
SC
705 if (m_vScrollBar && m_vScrollBar->IsShown() )
706 ww -= m_vScrollBar->GetSize().x ;
489468fe 707
b2680ced
SC
708 if (x)
709 *x = ww;
710 if (y)
711 *y = hh;
712}
489468fe 713
b2680ced
SC
714bool wxWindowMac::SetCursor(const wxCursor& cursor)
715{
716 if (m_cursor.IsSameAs(cursor))
717 return false;
489468fe 718
b2680ced
SC
719 if (!cursor.IsOk())
720 {
721 if ( ! wxWindowBase::SetCursor( *wxSTANDARD_CURSOR ) )
722 return false ;
723 }
724 else
725 {
726 if ( ! wxWindowBase::SetCursor( cursor ) )
727 return false ;
728 }
489468fe 729
b2680ced
SC
730 wxASSERT_MSG( m_cursor.Ok(),
731 wxT("cursor must be valid after call to the base version"));
489468fe 732
b2680ced
SC
733 wxWindowMac *mouseWin = 0 ;
734#if wxOSX_USE_CARBON
735 {
736 wxNonOwnedWindow *tlw = MacGetTopLevelWindow() ;
737 WindowRef window = (WindowRef) ( tlw ? tlw->GetWXWindow() : 0 ) ;
489468fe 738
b2680ced
SC
739 ControlPartCode part ;
740 ControlRef control ;
741 Point pt ;
742 #if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
743 HIPoint hiPoint ;
744 HIGetMousePosition(kHICoordSpaceWindow, window, &hiPoint);
745 pt.h = hiPoint.x;
746 pt.v = hiPoint.y;
747 #else
748 GetGlobalMouse( &pt );
749 int x = pt.h;
750 int y = pt.v;
751 ScreenToClient(&x, &y);
752 pt.h = x;
753 pt.v = y;
754#endif
755 control = FindControlUnderMouse( pt , window , &part ) ;
756 if ( control )
757 mouseWin = wxFindWindowFromWXWidget( (WXWidget) control ) ;
489468fe 758
489468fe 759 }
b2680ced 760#endif
489468fe 761
b2680ced
SC
762 if ( mouseWin == this && !wxIsBusy() )
763 m_cursor.MacInstall() ;
489468fe 764
b2680ced 765 return true ;
489468fe
SC
766}
767
b2680ced
SC
768#if wxUSE_MENUS
769bool wxWindowMac::DoPopupMenu(wxMenu *menu, int x, int y)
489468fe 770{
b2680ced
SC
771#ifndef __WXUNIVERSAL__
772 menu->SetInvokingWindow((wxWindow*)this);
773 menu->UpdateUI();
489468fe 774
b2680ced 775 if ( x == wxDefaultCoord && y == wxDefaultCoord )
489468fe 776 {
b2680ced
SC
777 wxPoint mouse = wxGetMousePosition();
778 x = mouse.x;
779 y = mouse.y;
780 }
781 else
782 {
783 ClientToScreen( &x , &y ) ;
784 }
489468fe 785
b2680ced
SC
786 menu->MacBeforeDisplay( true ) ;
787 long menuResult = ::PopUpMenuSelect((MenuHandle) menu->GetHMenu() , y, x, 0) ;
788 if ( HiWord(menuResult) != 0 )
789 {
790 MenuCommand macid;
791 GetMenuItemCommandID( GetMenuHandle(HiWord(menuResult)) , LoWord(menuResult) , &macid );
792 int id = wxMacCommandToId( macid );
793 wxMenuItem* item = NULL ;
794 wxMenu* realmenu ;
795 item = menu->FindItem( id, &realmenu ) ;
796 if ( item )
489468fe 797 {
b2680ced
SC
798 if (item->IsCheckable())
799 item->Check( !item->IsChecked() ) ;
489468fe 800
b2680ced 801 menu->SendEvent( id , item->IsCheckable() ? item->IsChecked() : -1 ) ;
489468fe
SC
802 }
803 }
489468fe 804
b2680ced
SC
805 menu->MacAfterDisplay( true ) ;
806 menu->SetInvokingWindow( NULL );
489468fe 807
b2680ced
SC
808 return true;
809#else
810 // actually this shouldn't be called, because universal is having its own implementation
811 return false;
812#endif
813}
814#endif
489468fe 815
b2680ced
SC
816// ----------------------------------------------------------------------------
817// tooltips
818// ----------------------------------------------------------------------------
489468fe 819
b2680ced 820#if wxUSE_TOOLTIPS
489468fe 821
b2680ced
SC
822void wxWindowMac::DoSetToolTip(wxToolTip *tooltip)
823{
824 wxWindowBase::DoSetToolTip(tooltip);
489468fe 825
b2680ced
SC
826 if ( m_tooltip )
827 m_tooltip->SetWindow(this);
489468fe
SC
828}
829
b2680ced 830#endif
489468fe 831
b2680ced 832void wxWindowMac::MacInvalidateBorders()
489468fe 833{
b2680ced
SC
834 if ( m_peer == NULL )
835 return ;
489468fe 836
b2680ced
SC
837 bool vis = IsShownOnScreen() ;
838 if ( !vis )
839 return ;
489468fe 840
b2680ced
SC
841 int outerBorder = MacGetLeftBorderSize() ;
842#if wxOSX_USE_CARBON
843 if ( m_peer->NeedsFocusRect() /* && m_peer->HasFocus() */ )
844 outerBorder += 4 ;
845#endif
489468fe 846
b2680ced
SC
847 if ( outerBorder == 0 )
848 return ;
489468fe 849
b2680ced
SC
850 // now we know that we have something to do at all
851
489468fe 852
b2680ced
SC
853 int tx,ty,tw,th;
854
855 m_peer->GetSize( tw, th );
856 m_peer->GetPosition( tx, ty );
489468fe 857
b2680ced
SC
858 wxRect leftupdate( tx-outerBorder,ty,outerBorder,th );
859 wxRect rightupdate( tx+tw, ty, outerBorder, th );
860 wxRect topupdate( tx-outerBorder, ty-outerBorder, tw + 2 * outerBorder, outerBorder );
861 wxRect bottomupdate( tx-outerBorder, ty + th, tw + 2 * outerBorder, outerBorder );
862
863 GetParent()->m_peer->SetNeedsDisplay(&leftupdate);
864 GetParent()->m_peer->SetNeedsDisplay(&rightupdate);
865 GetParent()->m_peer->SetNeedsDisplay(&topupdate);
866 GetParent()->m_peer->SetNeedsDisplay(&bottomupdate);
489468fe
SC
867}
868
b2680ced 869void wxWindowMac::DoMoveWindow(int x, int y, int width, int height)
489468fe 870{
b2680ced
SC
871 // this is never called for a toplevel window, so we know we have a parent
872 int former_x , former_y , former_w, former_h ;
489468fe 873
b2680ced
SC
874 // Get true coordinates of former position
875 DoGetPosition( &former_x , &former_y ) ;
876 DoGetSize( &former_w , &former_h ) ;
877
878 wxWindow *parent = GetParent();
879 if ( parent )
489468fe 880 {
b2680ced
SC
881 wxPoint pt(parent->GetClientAreaOrigin());
882 former_x += pt.x ;
883 former_y += pt.y ;
489468fe 884 }
489468fe 885
b2680ced
SC
886 int actualWidth = width ;
887 int actualHeight = height ;
888 int actualX = x;
889 int actualY = y;
489468fe 890
b2680ced
SC
891 if ((m_minWidth != -1) && (actualWidth < m_minWidth))
892 actualWidth = m_minWidth;
893 if ((m_minHeight != -1) && (actualHeight < m_minHeight))
894 actualHeight = m_minHeight;
895 if ((m_maxWidth != -1) && (actualWidth > m_maxWidth))
896 actualWidth = m_maxWidth;
897 if ((m_maxHeight != -1) && (actualHeight > m_maxHeight))
898 actualHeight = m_maxHeight;
489468fe 899
b2680ced 900 bool doMove = false, doResize = false ;
489468fe 901
b2680ced
SC
902 if ( actualX != former_x || actualY != former_y )
903 doMove = true ;
489468fe 904
b2680ced
SC
905 if ( actualWidth != former_w || actualHeight != former_h )
906 doResize = true ;
489468fe 907
b2680ced
SC
908 if ( doMove || doResize )
909 {
910 // as the borders are drawn outside the native control, we adjust now
489468fe 911
b2680ced
SC
912 wxRect bounds( wxPoint( actualX + MacGetLeftBorderSize() ,actualY + MacGetTopBorderSize() ),
913 wxSize( actualWidth - (MacGetLeftBorderSize() + MacGetRightBorderSize()) ,
914 actualHeight - (MacGetTopBorderSize() + MacGetBottomBorderSize()) ) ) ;
489468fe 915
b2680ced 916 if ( !GetParent()->IsTopLevel() )
489468fe 917 {
b2680ced 918 bounds.Offset( -GetParent()->MacGetLeftBorderSize(), -GetParent()->MacGetTopBorderSize() );
489468fe 919 }
489468fe 920
b2680ced 921 MacInvalidateBorders() ;
489468fe 922
b2680ced
SC
923 m_cachedClippedRectValid = false ;
924
925 m_peer->Move( bounds.x, bounds.y, bounds.width, bounds.height);
489468fe 926
b2680ced 927 wxWindowMac::MacSuperChangedPosition() ; // like this only children will be notified
489468fe 928
b2680ced 929 MacInvalidateBorders() ;
489468fe 930
b2680ced
SC
931 MacRepositionScrollBars() ;
932 if ( doMove )
933 {
934 wxPoint point(actualX, actualY);
935 wxMoveEvent event(point, m_windowId);
936 event.SetEventObject(this);
937 HandleWindowEvent(event) ;
938 }
939
940 if ( doResize )
941 {
942 MacRepositionScrollBars() ;
943 wxSize size(actualWidth, actualHeight);
944 wxSizeEvent event(size, m_windowId);
945 event.SetEventObject(this);
946 HandleWindowEvent(event);
947 }
489468fe 948 }
b2680ced 949}
489468fe 950
b2680ced
SC
951wxSize wxWindowMac::DoGetBestSize() const
952{
953 if ( m_macIsUserPane || IsTopLevel() )
489468fe 954 {
b2680ced 955 return wxWindowBase::DoGetBestSize() ;
489468fe 956 }
b2680ced
SC
957 else
958 {
959
960 Rect bestsize = { 0 , 0 , 0 , 0 } ;
961 int bestWidth, bestHeight ;
962
963#if wxOSX_USE_COCOA_OR_CARBON
964#if wxOSX_USE_CARBON
965 m_peer->GetBestRect( &bestsize ) ;
489468fe 966#endif
b2680ced
SC
967 if ( EmptyRect( &bestsize ) )
968 {
969 bestsize.left =
970 bestsize.top = 0 ;
971 bestsize.right =
972 bestsize.bottom = 16 ;
489468fe 973
b2680ced
SC
974 if ( IsKindOf( CLASSINFO( wxScrollBar ) ) )
975 {
976 bestsize.bottom = 16 ;
977 }
978 #if wxUSE_SPINBTN
979 else if ( IsKindOf( CLASSINFO( wxSpinButton ) ) )
980 {
981 bestsize.bottom = 24 ;
982 }
983 #endif
984 else
985 {
986 // return wxWindowBase::DoGetBestSize() ;
987 }
988 }
989#endif
990 bestWidth = bestsize.right - bestsize.left + MacGetLeftBorderSize() +
991 MacGetRightBorderSize();
992 bestHeight = bestsize.bottom - bestsize.top + MacGetTopBorderSize() +
993 MacGetBottomBorderSize();
994 if ( bestHeight < 10 )
995 bestHeight = 13 ;
489468fe 996
b2680ced
SC
997 return wxSize(bestWidth, bestHeight);
998 }
489468fe
SC
999}
1000
b2680ced
SC
1001// set the size of the window: if the dimensions are positive, just use them,
1002// but if any of them is equal to -1, it means that we must find the value for
1003// it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in
1004// which case -1 is a valid value for x and y)
1005//
1006// If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate
1007// the width/height to best suit our contents, otherwise we reuse the current
1008// width/height
1009void wxWindowMac::DoSetSize(int x, int y, int width, int height, int sizeFlags)
489468fe 1010{
b2680ced
SC
1011 // get the current size and position...
1012 int currentX, currentY;
1013 int currentW, currentH;
489468fe 1014
b2680ced
SC
1015 GetPosition(&currentX, &currentY);
1016 GetSize(&currentW, &currentH);
489468fe 1017
b2680ced
SC
1018 // ... and don't do anything (avoiding flicker) if it's already ok
1019 if ( x == currentX && y == currentY &&
1020 width == currentW && height == currentH && ( height != -1 && width != -1 ) )
1021 {
1022 // TODO: REMOVE
1023 MacRepositionScrollBars() ; // we might have a real position shift
489468fe 1024
b2680ced
SC
1025 return;
1026 }
489468fe 1027
b2680ced 1028 if ( !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) )
489468fe 1029 {
b2680ced
SC
1030 if ( x == wxDefaultCoord )
1031 x = currentX;
1032 if ( y == wxDefaultCoord )
1033 y = currentY;
1034 }
489468fe 1035
b2680ced
SC
1036 AdjustForParentClientOrigin( x, y, sizeFlags );
1037
1038 wxSize size = wxDefaultSize;
1039 if ( width == wxDefaultCoord )
1040 {
1041 if ( sizeFlags & wxSIZE_AUTO_WIDTH )
1042 {
1043 size = DoGetBestSize();
1044 width = size.x;
1045 }
1046 else
1047 {
1048 // just take the current one
1049 width = currentW;
1050 }
1051 }
489468fe 1052
b2680ced
SC
1053 if ( height == wxDefaultCoord )
1054 {
1055 if ( sizeFlags & wxSIZE_AUTO_HEIGHT )
1056 {
1057 if ( size.x == wxDefaultCoord )
1058 size = DoGetBestSize();
1059 // else: already called DoGetBestSize() above
489468fe 1060
b2680ced
SC
1061 height = size.y;
1062 }
1063 else
1064 {
1065 // just take the current one
1066 height = currentH;
1067 }
489468fe
SC
1068 }
1069
b2680ced
SC
1070 DoMoveWindow( x, y, width, height );
1071}
1072
1073wxPoint wxWindowMac::GetClientAreaOrigin() const
1074{
1075#if wxOSX_USE_CARBON
1076 RgnHandle rgn = NewRgn() ;
1077 Rect content ;
1078 if ( m_peer->GetRegion( kControlContentMetaPart , rgn ) == noErr )
489468fe 1079 {
b2680ced
SC
1080 GetRegionBounds( rgn , &content ) ;
1081 }
1082 else
1083 {
1084 content.left =
1085 content.top = 0 ;
489468fe 1086 }
489468fe 1087
b2680ced 1088 DisposeRgn( rgn ) ;
489468fe 1089
b2680ced
SC
1090 return wxPoint( content.left + MacGetLeftBorderSize() , content.top + MacGetTopBorderSize() );
1091#else
1092 return wxPoint(0,0);
1093#endif
489468fe
SC
1094}
1095
b2680ced 1096void wxWindowMac::DoSetClientSize(int clientwidth, int clientheight)
489468fe 1097{
b2680ced
SC
1098 if ( clientwidth != wxDefaultCoord || clientheight != wxDefaultCoord )
1099 {
1100 int currentclientwidth , currentclientheight ;
1101 int currentwidth , currentheight ;
1102
1103 GetClientSize( &currentclientwidth , &currentclientheight ) ;
1104 GetSize( &currentwidth , &currentheight ) ;
1105
1106 DoSetSize( wxDefaultCoord , wxDefaultCoord , currentwidth + clientwidth - currentclientwidth ,
1107 currentheight + clientheight - currentclientheight , wxSIZE_USE_EXISTING ) ;
1108 }
489468fe
SC
1109}
1110
b2680ced 1111void wxWindowMac::SetLabel(const wxString& title)
489468fe 1112{
b2680ced 1113 m_label = title ;
489468fe 1114
b2680ced
SC
1115#if wxOSX_USE_CARBON
1116 if ( m_peer && m_peer->IsOk() )
1117 m_peer->SetLabel( wxStripMenuCodes(m_label, wxStrip_Mnemonics) ) ;
1118#endif
489468fe 1119
b2680ced
SC
1120 // do not trigger refreshes upon invisible and possible partly created objects
1121 if ( IsShownOnScreen() )
1122 Refresh() ;
1123}
489468fe 1124
b2680ced
SC
1125wxString wxWindowMac::GetLabel() const
1126{
1127 return m_label ;
1128}
489468fe 1129
b2680ced
SC
1130bool wxWindowMac::Show(bool show)
1131{
1132 if ( !wxWindowBase::Show(show) )
1133 return false;
489468fe 1134
b2680ced
SC
1135 if ( m_peer )
1136 m_peer->SetVisibility( show ) ;
489468fe 1137
b2680ced 1138 return true;
489468fe
SC
1139}
1140
b2680ced 1141void wxWindowMac::DoEnable(bool enable)
489468fe 1142{
b2680ced
SC
1143#if wxOSX_USE_CARBON
1144 m_peer->Enable( enable ) ;
1145#endif
1146}
489468fe 1147
b2680ced
SC
1148//
1149// status change notifications
1150//
489468fe 1151
b2680ced
SC
1152void wxWindowMac::MacVisibilityChanged()
1153{
1154}
489468fe 1155
b2680ced
SC
1156void wxWindowMac::MacHiliteChanged()
1157{
1158}
489468fe 1159
b2680ced
SC
1160void wxWindowMac::MacEnabledStateChanged()
1161{
1162#if wxOSX_USE_CARBON
1163 OnEnabled( m_peer->IsEnabled() );
1164#endif
1165}
489468fe 1166
b2680ced
SC
1167//
1168// status queries on the inherited window's state
1169//
489468fe 1170
b2680ced 1171bool wxWindowMac::MacIsReallyEnabled()
489468fe 1172{
b2680ced
SC
1173#if wxOSX_USE_CARBON
1174 return m_peer->IsEnabled() ;
1175#endif
489468fe
SC
1176}
1177
b2680ced 1178bool wxWindowMac::MacIsReallyHilited()
489468fe 1179{
b2680ced
SC
1180#if wxOSX_USE_CARBON
1181 return m_peer->IsActive();
1182#endif
489468fe
SC
1183}
1184
b2680ced 1185int wxWindowMac::GetCharHeight() const
489468fe 1186{
b2680ced 1187 wxClientDC dc( (wxWindow*)this ) ;
489468fe 1188
b2680ced 1189 return dc.GetCharHeight() ;
489468fe
SC
1190}
1191
b2680ced 1192int wxWindowMac::GetCharWidth() const
489468fe 1193{
b2680ced 1194 wxClientDC dc( (wxWindow*)this ) ;
489468fe 1195
b2680ced 1196 return dc.GetCharWidth() ;
489468fe
SC
1197}
1198
b2680ced
SC
1199void wxWindowMac::GetTextExtent(const wxString& string, int *x, int *y,
1200 int *descent, int *externalLeading, const wxFont *theFont ) const
489468fe 1201{
b2680ced
SC
1202 const wxFont *fontToUse = theFont;
1203 wxFont tempFont;
1204 if ( !fontToUse )
489468fe 1205 {
b2680ced
SC
1206 tempFont = GetFont();
1207 fontToUse = &tempFont;
489468fe 1208 }
489468fe 1209
b2680ced
SC
1210 wxClientDC dc( (wxWindow*) this ) ;
1211 wxCoord lx,ly,ld,le ;
1212 dc.GetTextExtent( string , &lx , &ly , &ld, &le, (wxFont *)fontToUse ) ;
1213 if ( externalLeading )
1214 *externalLeading = le ;
1215 if ( descent )
1216 *descent = ld ;
1217 if ( x )
1218 *x = lx ;
1219 if ( y )
1220 *y = ly ;
489468fe
SC
1221}
1222
b2680ced
SC
1223/*
1224 * Rect is given in client coordinates, for further reading, read wxTopLevelWindowMac::InvalidateRect
1225 * we always intersect with the entire window, not only with the client area
1226 */
489468fe 1227
b2680ced
SC
1228void wxWindowMac::Refresh(bool WXUNUSED(eraseBack), const wxRect *rect)
1229{
1230 if ( m_peer == NULL )
489468fe
SC
1231 return ;
1232
b2680ced 1233 if ( !IsShownOnScreen() )
489468fe 1234 return ;
b2680ced
SC
1235
1236 m_peer->SetNeedsDisplay( rect ) ;
489468fe
SC
1237}
1238
b2680ced 1239void wxWindowMac::DoFreeze()
489468fe 1240{
b2680ced
SC
1241#if wxOSX_USE_CARBON
1242 if ( m_peer && m_peer->IsOk() )
1243 m_peer->SetDrawingEnabled( false ) ;
1244#endif
489468fe
SC
1245}
1246
b2680ced 1247void wxWindowMac::DoThaw()
489468fe 1248{
b2680ced
SC
1249#if wxOSX_USE_CARBON
1250 if ( m_peer && m_peer->IsOk() )
1251 {
1252 m_peer->SetDrawingEnabled( true ) ;
1253 m_peer->InvalidateWithChildren() ;
1254 }
1255#endif
489468fe
SC
1256}
1257
b2680ced 1258wxWindow *wxGetActiveWindow()
489468fe 1259{
b2680ced
SC
1260 // actually this is a windows-only concept
1261 return NULL;
489468fe
SC
1262}
1263
b2680ced
SC
1264// Coordinates relative to the window
1265void wxWindowMac::WarpPointer(int WXUNUSED(x_pos), int WXUNUSED(y_pos))
489468fe 1266{
b2680ced
SC
1267 // We really don't move the mouse programmatically under Mac.
1268}
489468fe 1269
b2680ced
SC
1270void wxWindowMac::OnEraseBackground(wxEraseEvent& event)
1271{
1272 if ( MacGetTopLevelWindow() == NULL )
1273 return ;
1274/*
1275#if TARGET_API_MAC_OSX
1276 if ( !m_backgroundColour.Ok() || GetBackgroundStyle() == wxBG_STYLE_TRANSPARENT )
489468fe 1277 {
489468fe 1278 }
b2680ced 1279 else
489468fe 1280#endif
b2680ced
SC
1281*/
1282 if ( GetBackgroundStyle() == wxBG_STYLE_COLOUR )
1283 {
1284 event.GetDC()->Clear() ;
1285 }
1286 else if ( GetBackgroundStyle() == wxBG_STYLE_CUSTOM )
1287 {
1288 // don't skip the event here, custom background means that the app
1289 // is drawing it itself in its OnPaint(), so don't draw it at all
1290 // now to avoid flicker
1291 }
1292 else
1293 {
1294 event.Skip() ;
1295 }
489468fe
SC
1296}
1297
b2680ced 1298void wxWindowMac::OnNcPaint( wxNcPaintEvent& event )
489468fe 1299{
b2680ced 1300 event.Skip() ;
489468fe
SC
1301}
1302
b2680ced 1303int wxWindowMac::GetScrollPos(int orient) const
489468fe 1304{
b2680ced 1305 if ( orient == wxHORIZONTAL )
489468fe 1306 {
b2680ced
SC
1307 if ( m_hScrollBar )
1308 return m_hScrollBar->GetThumbPosition() ;
1309 }
1310 else
1311 {
1312 if ( m_vScrollBar )
1313 return m_vScrollBar->GetThumbPosition() ;
489468fe
SC
1314 }
1315
b2680ced 1316 return 0;
489468fe
SC
1317}
1318
b2680ced
SC
1319// This now returns the whole range, not just the number
1320// of positions that we can scroll.
1321int wxWindowMac::GetScrollRange(int orient) const
489468fe 1322{
b2680ced
SC
1323 if ( orient == wxHORIZONTAL )
1324 {
1325 if ( m_hScrollBar )
1326 return m_hScrollBar->GetRange() ;
1327 }
1328 else
1329 {
1330 if ( m_vScrollBar )
1331 return m_vScrollBar->GetRange() ;
1332 }
489468fe 1333
b2680ced 1334 return 0;
489468fe
SC
1335}
1336
b2680ced 1337int wxWindowMac::GetScrollThumb(int orient) const
489468fe 1338{
b2680ced
SC
1339 if ( orient == wxHORIZONTAL )
1340 {
1341 if ( m_hScrollBar )
1342 return m_hScrollBar->GetThumbSize() ;
1343 }
1344 else
1345 {
1346 if ( m_vScrollBar )
1347 return m_vScrollBar->GetThumbSize() ;
1348 }
489468fe 1349
b2680ced
SC
1350 return 0;
1351}
489468fe 1352
b2680ced
SC
1353void wxWindowMac::SetScrollPos(int orient, int pos, bool WXUNUSED(refresh))
1354{
1355 if ( orient == wxHORIZONTAL )
489468fe 1356 {
b2680ced
SC
1357 if ( m_hScrollBar )
1358 m_hScrollBar->SetThumbPosition( pos ) ;
1359 }
1360 else
1361 {
1362 if ( m_vScrollBar )
1363 m_vScrollBar->SetThumbPosition( pos ) ;
489468fe 1364 }
489468fe
SC
1365}
1366
b2680ced
SC
1367void
1368wxWindowMac::AlwaysShowScrollbars(bool hflag, bool vflag)
489468fe 1369{
b2680ced 1370 bool needVisibilityUpdate = false;
489468fe 1371
b2680ced
SC
1372 if ( m_hScrollBarAlwaysShown != hflag )
1373 {
1374 m_hScrollBarAlwaysShown = hflag;
1375 needVisibilityUpdate = true;
1376 }
489468fe 1377
b2680ced
SC
1378 if ( m_vScrollBarAlwaysShown != vflag )
1379 {
1380 m_vScrollBarAlwaysShown = vflag;
1381 needVisibilityUpdate = true;
1382 }
489468fe 1383
b2680ced
SC
1384 if ( needVisibilityUpdate )
1385 DoUpdateScrollbarVisibility();
489468fe
SC
1386}
1387
b2680ced
SC
1388//
1389// we draw borders and grow boxes, are already set up and clipped in the current port / cgContextRef
1390// our own window origin is at leftOrigin/rightOrigin
1391//
1392
1393void wxWindowMac::MacPaintGrowBox()
489468fe 1394{
b2680ced
SC
1395 if ( IsTopLevel() )
1396 return ;
489468fe 1397
b2680ced
SC
1398 if ( MacHasScrollBarCorner() )
1399 {
1400 CGContextRef cgContext = (CGContextRef) MacGetCGContextRef() ;
1401 wxASSERT( cgContext ) ;
489468fe 1402
b2680ced
SC
1403 int tx,ty,tw,th;
1404
1405 m_peer->GetSize( tw, th );
1406 m_peer->GetPosition( tx, ty );
489468fe 1407
b2680ced 1408 Rect rect = { ty,tx, ty+th, tx+tw };
489468fe 1409
489468fe 1410
b2680ced
SC
1411 int size = m_hScrollBar ? m_hScrollBar->GetSize().y : ( m_vScrollBar ? m_vScrollBar->GetSize().x : MAC_SCROLLBAR_SIZE ) ;
1412 CGRect cgrect = CGRectMake( rect.right - size , rect.bottom - size , size , size ) ;
1413 CGPoint cgpoint = CGPointMake( rect.right - size , rect.bottom - size ) ;
1414 CGContextSaveGState( cgContext );
1415
1416 if ( m_backgroundColour.Ok() )
1417 {
1418 CGContextSetFillColorWithColor( cgContext, m_backgroundColour.GetCGColor() );
1419 }
1420 else
1421 {
1422 CGContextSetRGBFillColor( cgContext, (CGFloat) 1.0, (CGFloat)1.0 ,(CGFloat) 1.0 , (CGFloat)1.0 );
1423 }
1424 CGContextFillRect( cgContext, cgrect );
1425 CGContextRestoreGState( cgContext );
1426 }
489468fe
SC
1427}
1428
b2680ced 1429void wxWindowMac::MacPaintBorders( int WXUNUSED(leftOrigin) , int WXUNUSED(rightOrigin) )
489468fe 1430{
b2680ced
SC
1431 if ( IsTopLevel() )
1432 return ;
489468fe 1433
b2680ced 1434 bool hasFocus = m_peer->NeedsFocusRect() && m_peer->HasFocus() ;
489468fe 1435
b2680ced
SC
1436 // back to the surrounding frame rectangle
1437 int tx,ty,tw,th;
1438
1439 m_peer->GetSize( tw, th );
1440 m_peer->GetPosition( tx, ty );
489468fe 1441
b2680ced 1442 Rect rect = { ty,tx, ty+th, tx+tw };
489468fe 1443
b2680ced 1444#if wxOSX_USE_COCOA_OR_CARBON
489468fe 1445
b2680ced 1446 InsetRect( &rect, -1 , -1 ) ;
489468fe 1447
489468fe 1448 {
b2680ced
SC
1449 CGRect cgrect = CGRectMake( rect.left , rect.top , rect.right - rect.left ,
1450 rect.bottom - rect.top ) ;
1451
1452 HIThemeFrameDrawInfo info ;
1453 memset( &info, 0 , sizeof(info) ) ;
1454
1455 info.version = 0 ;
1456 info.kind = 0 ;
1457 info.state = IsEnabled() ? kThemeStateActive : kThemeStateInactive ;
1458 info.isFocused = hasFocus ;
1459
1460 CGContextRef cgContext = (CGContextRef) GetParent()->MacGetCGContextRef() ;
1461 wxASSERT( cgContext ) ;
1462
1463 if ( HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER) || HasFlag(wxDOUBLE_BORDER) )
489468fe 1464 {
b2680ced
SC
1465 info.kind = kHIThemeFrameTextFieldSquare ;
1466 HIThemeDrawFrame( &cgrect , &info , cgContext , kHIThemeOrientationNormal ) ;
1467 }
1468 else if ( HasFlag(wxSIMPLE_BORDER) )
1469 {
1470 info.kind = kHIThemeFrameListBox ;
1471 HIThemeDrawFrame( &cgrect , &info , cgContext , kHIThemeOrientationNormal ) ;
1472 }
1473 else if ( hasFocus )
1474 {
1475 HIThemeDrawFocusRect( &cgrect , true , cgContext , kHIThemeOrientationNormal ) ;
1476 }
1477#if 0 // TODO REMOVE now done in a separate call earlier in drawing the window itself
1478 m_peer->GetRect( &rect ) ;
1479 if ( MacHasScrollBarCorner() )
1480 {
1481 int variant = (m_hScrollBar == NULL ? m_vScrollBar : m_hScrollBar ) ->GetWindowVariant();
1482 int size = m_hScrollBar ? m_hScrollBar->GetSize().y : ( m_vScrollBar ? m_vScrollBar->GetSize().x : MAC_SCROLLBAR_SIZE ) ;
1483 CGRect cgrect = CGRectMake( rect.right - size , rect.bottom - size , size , size ) ;
1484 CGPoint cgpoint = CGPointMake( rect.right - size , rect.bottom - size ) ;
1485 HIThemeGrowBoxDrawInfo info ;
1486 memset( &info, 0, sizeof(info) ) ;
1487 info.version = 0 ;
1488 info.state = IsEnabled() ? kThemeStateActive : kThemeStateInactive ;
1489 info.kind = kHIThemeGrowBoxKindNone ;
1490 // contrary to the docs ...SizeSmall does not work
1491 info.size = kHIThemeGrowBoxSizeNormal ;
1492 info.direction = 0 ;
1493 HIThemeDrawGrowBox( &cgpoint , &info , cgContext , kHIThemeOrientationNormal ) ;
489468fe 1494 }
b2680ced 1495#endif
489468fe 1496 }
b2680ced 1497#endif // wxOSX_USE_COCOA_OR_CARBON
489468fe
SC
1498}
1499
b2680ced 1500void wxWindowMac::RemoveChild( wxWindowBase *child )
489468fe 1501{
b2680ced
SC
1502 if ( child == m_hScrollBar )
1503 m_hScrollBar = NULL ;
1504 if ( child == m_vScrollBar )
1505 m_vScrollBar = NULL ;
489468fe 1506
b2680ced 1507 wxWindowBase::RemoveChild( child ) ;
489468fe
SC
1508}
1509
b2680ced 1510void wxWindowMac::DoUpdateScrollbarVisibility()
489468fe 1511{
b2680ced 1512 bool triggerSizeEvent = false;
489468fe 1513
b2680ced
SC
1514 if ( m_hScrollBar )
1515 {
1516 bool showHScrollBar = m_hScrollBarAlwaysShown || m_hScrollBar->IsNeeded();
489468fe 1517
b2680ced
SC
1518 if ( m_hScrollBar->IsShown() != showHScrollBar )
1519 {
1520 m_hScrollBar->Show( showHScrollBar );
1521 triggerSizeEvent = true;
1522 }
1523 }
1524
1525 if ( m_vScrollBar)
489468fe 1526 {
b2680ced
SC
1527 bool showVScrollBar = m_vScrollBarAlwaysShown || m_vScrollBar->IsNeeded();
1528
1529 if ( m_vScrollBar->IsShown() != showVScrollBar )
489468fe 1530 {
b2680ced
SC
1531 m_vScrollBar->Show( showVScrollBar ) ;
1532 triggerSizeEvent = true;
489468fe
SC
1533 }
1534 }
1535
b2680ced
SC
1536 MacRepositionScrollBars() ;
1537 if ( triggerSizeEvent )
1538 {
1539 wxSizeEvent event(GetSize(), m_windowId);
1540 event.SetEventObject(this);
1541 HandleWindowEvent(event);
1542 }
489468fe
SC
1543}
1544
b2680ced
SC
1545// New function that will replace some of the above.
1546void wxWindowMac::SetScrollbar(int orient, int pos, int thumb,
1547 int range, bool refresh)
489468fe 1548{
b2680ced
SC
1549 if ( orient == wxHORIZONTAL && m_hScrollBar )
1550 m_hScrollBar->SetScrollbar(pos, thumb, range, thumb, refresh);
1551 else if ( orient == wxVERTICAL && m_vScrollBar )
1552 m_vScrollBar->SetScrollbar(pos, thumb, range, thumb, refresh);
489468fe 1553
b2680ced 1554 DoUpdateScrollbarVisibility();
489468fe
SC
1555}
1556
b2680ced
SC
1557// Does a physical scroll
1558void wxWindowMac::ScrollWindow(int dx, int dy, const wxRect *rect)
489468fe 1559{
b2680ced
SC
1560 if ( dx == 0 && dy == 0 )
1561 return ;
489468fe 1562
b2680ced
SC
1563 int width , height ;
1564 GetClientSize( &width , &height ) ;
489468fe 1565
b2680ced
SC
1566 {
1567 wxRect scrollrect( MacGetLeftBorderSize() , MacGetTopBorderSize() , width , height ) ;
1568 if ( rect )
1569 scrollrect.Intersect( *rect ) ;
1570 // as the native control might be not a 0/0 wx window coordinates, we have to offset
1571 scrollrect.Offset( -MacGetLeftBorderSize() , -MacGetTopBorderSize() ) ;
489468fe 1572
b2680ced 1573 m_peer->ScrollRect( &scrollrect, dx, dy );
489468fe 1574 }
b2680ced
SC
1575
1576 wxWindowMac *child;
1577 int x, y, w, h;
1578 for (wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); node; node = node->GetNext())
489468fe 1579 {
b2680ced
SC
1580 child = node->GetData();
1581 if (child == NULL)
1582 continue;
1583 if (child == m_vScrollBar)
1584 continue;
1585 if (child == m_hScrollBar)
1586 continue;
1587 if (child->IsTopLevel())
1588 continue;
489468fe 1589
b2680ced
SC
1590 child->GetPosition( &x, &y );
1591 child->GetSize( &w, &h );
1592 if (rect)
1593 {
1594 wxRect rc( x, y, w, h );
1595 if (rect->Intersects( rc ))
1596 child->SetSize( x + dx, y + dy, w, h, wxSIZE_AUTO|wxSIZE_ALLOW_MINUS_ONE );
1597 }
1598 else
1599 {
1600 child->SetSize( x + dx, y + dy, w, h, wxSIZE_AUTO|wxSIZE_ALLOW_MINUS_ONE );
1601 }
1602 }
489468fe
SC
1603}
1604
b2680ced 1605void wxWindowMac::MacOnScroll( wxScrollEvent &event )
489468fe 1606{
b2680ced 1607 if ( event.GetEventObject() == m_vScrollBar || event.GetEventObject() == m_hScrollBar )
489468fe 1608 {
b2680ced
SC
1609 wxScrollWinEvent wevent;
1610 wevent.SetPosition(event.GetPosition());
1611 wevent.SetOrientation(event.GetOrientation());
1612 wevent.SetEventObject(this);
489468fe 1613
b2680ced
SC
1614 if (event.GetEventType() == wxEVT_SCROLL_TOP)
1615 wevent.SetEventType( wxEVT_SCROLLWIN_TOP );
1616 else if (event.GetEventType() == wxEVT_SCROLL_BOTTOM)
1617 wevent.SetEventType( wxEVT_SCROLLWIN_BOTTOM );
1618 else if (event.GetEventType() == wxEVT_SCROLL_LINEUP)
1619 wevent.SetEventType( wxEVT_SCROLLWIN_LINEUP );
1620 else if (event.GetEventType() == wxEVT_SCROLL_LINEDOWN)
1621 wevent.SetEventType( wxEVT_SCROLLWIN_LINEDOWN );
1622 else if (event.GetEventType() == wxEVT_SCROLL_PAGEUP)
1623 wevent.SetEventType( wxEVT_SCROLLWIN_PAGEUP );
1624 else if (event.GetEventType() == wxEVT_SCROLL_PAGEDOWN)
1625 wevent.SetEventType( wxEVT_SCROLLWIN_PAGEDOWN );
1626 else if (event.GetEventType() == wxEVT_SCROLL_THUMBTRACK)
1627 wevent.SetEventType( wxEVT_SCROLLWIN_THUMBTRACK );
1628 else if (event.GetEventType() == wxEVT_SCROLL_THUMBRELEASE)
1629 wevent.SetEventType( wxEVT_SCROLLWIN_THUMBRELEASE );
489468fe 1630
b2680ced 1631 HandleWindowEvent(wevent);
489468fe 1632 }
b2680ced 1633}
489468fe 1634
b2680ced
SC
1635// Get the window with the focus
1636wxWindow *wxWindowBase::DoFindFocus()
1637{
1638#if wxOSX_USE_CARBON
1639 ControlRef control ;
1640 GetKeyboardFocus( GetUserFocusWindow() , &control ) ;
1641 return wxFindWindowFromWXWidget( (WXWidget) control ) ;
1642#else
1643 return NULL;
1644#endif
1645}
489468fe 1646
b2680ced
SC
1647void wxWindowMac::OnInternalIdle()
1648{
1649 // This calls the UI-update mechanism (querying windows for
1650 // menu/toolbar/control state information)
1651 if (wxUpdateUIEvent::CanUpdate(this) && IsShownOnScreen())
1652 UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
1653}
489468fe 1654
b2680ced
SC
1655// Raise the window to the top of the Z order
1656void wxWindowMac::Raise()
1657{
1658 m_peer->Raise();
489468fe
SC
1659}
1660
b2680ced
SC
1661// Lower the window to the bottom of the Z order
1662void wxWindowMac::Lower()
489468fe 1663{
b2680ced
SC
1664 m_peer->Lower();
1665}
489468fe 1666
b2680ced 1667// static wxWindow *gs_lastWhich = NULL;
489468fe 1668
b2680ced
SC
1669bool wxWindowMac::MacSetupCursor( const wxPoint& pt )
1670{
1671 // first trigger a set cursor event
489468fe 1672
b2680ced
SC
1673 wxPoint clientorigin = GetClientAreaOrigin() ;
1674 wxSize clientsize = GetClientSize() ;
1675 wxCursor cursor ;
1676 if ( wxRect2DInt( clientorigin.x , clientorigin.y , clientsize.x , clientsize.y ).Contains( wxPoint2DInt( pt ) ) )
1677 {
1678 wxSetCursorEvent event( pt.x , pt.y );
489468fe 1679
b2680ced
SC
1680 bool processedEvtSetCursor = HandleWindowEvent(event);
1681 if ( processedEvtSetCursor && event.HasCursor() )
1682 {
1683 cursor = event.GetCursor() ;
1684 }
1685 else
1686 {
1687 // the test for processedEvtSetCursor is here to prevent using m_cursor
1688 // if the user code caught EVT_SET_CURSOR() and returned nothing from
1689 // it - this is a way to say that our cursor shouldn't be used for this
1690 // point
1691 if ( !processedEvtSetCursor && m_cursor.Ok() )
1692 cursor = m_cursor ;
489468fe 1693
b2680ced
SC
1694 if ( !wxIsBusy() && !GetParent() )
1695 cursor = *wxSTANDARD_CURSOR ;
1696 }
1697
1698 if ( cursor.Ok() )
1699 cursor.MacInstall() ;
1700 }
1701
1702 return cursor.Ok() ;
489468fe
SC
1703}
1704
b2680ced 1705wxString wxWindowMac::MacGetToolTipString( wxPoint &WXUNUSED(pt) )
489468fe 1706{
b2680ced
SC
1707#if wxUSE_TOOLTIPS
1708 if ( m_tooltip )
1709 return m_tooltip->GetTip() ;
1710#endif
489468fe 1711
b2680ced
SC
1712 return wxEmptyString ;
1713}
1714
1715void wxWindowMac::ClearBackground()
1716{
1717 Refresh() ;
1718 Update() ;
1719}
1720
1721void wxWindowMac::Update()
1722{
1723 wxNonOwnedWindow* top = MacGetTopLevelWindow();
1724 if (top)
1725 top->Update() ;
1726}
1727
1728wxNonOwnedWindow* wxWindowMac::MacGetTopLevelWindow() const
1729{
1730 wxWindowMac *iter = (wxWindowMac*)this ;
1731
1732 while ( iter )
489468fe 1733 {
b2680ced
SC
1734 if ( iter->IsTopLevel() )
1735 {
1736 wxTopLevelWindow* toplevel = wxDynamicCast(iter,wxTopLevelWindow);
1737 if ( toplevel )
1738 return toplevel;
1739#if wxUSE_POPUPWIN
1740 wxPopupWindow* popupwin = wxDynamicCast(iter,wxPopupWindow);
1741 if ( popupwin )
1742 return popupwin;
1743#endif
1744 }
1745 iter = iter->GetParent() ;
489468fe
SC
1746 }
1747
b2680ced
SC
1748 return NULL ;
1749}
489468fe 1750
b2680ced
SC
1751const wxRect& wxWindowMac::MacGetClippedClientRect() const
1752{
1753 MacUpdateClippedRects() ;
489468fe 1754
b2680ced
SC
1755 return m_cachedClippedClientRect ;
1756}
489468fe 1757
b2680ced
SC
1758const wxRect& wxWindowMac::MacGetClippedRect() const
1759{
1760 MacUpdateClippedRects() ;
489468fe 1761
b2680ced
SC
1762 return m_cachedClippedRect ;
1763}
489468fe 1764
b2680ced
SC
1765const wxRect&wxWindowMac:: MacGetClippedRectWithOuterStructure() const
1766{
1767 MacUpdateClippedRects() ;
1768
1769 return m_cachedClippedRectWithOuterStructure ;
489468fe
SC
1770}
1771
b2680ced 1772const wxRegion& wxWindowMac::MacGetVisibleRegion( bool includeOuterStructures )
489468fe 1773{
b2680ced 1774 static wxRegion emptyrgn ;
489468fe 1775
b2680ced 1776 if ( !m_isBeingDeleted && IsShownOnScreen() )
489468fe 1777 {
b2680ced
SC
1778 MacUpdateClippedRects() ;
1779 if ( includeOuterStructures )
1780 return m_cachedClippedRegionWithOuterStructure ;
1781 else
1782 return m_cachedClippedRegion ;
489468fe
SC
1783 }
1784 else
1785 {
b2680ced 1786 return emptyrgn ;
489468fe 1787 }
b2680ced 1788}
489468fe 1789
b2680ced
SC
1790void wxWindowMac::MacUpdateClippedRects() const
1791{
1792#if wxOSX_USE_CARBON
1793 if ( m_cachedClippedRectValid )
1794 return ;
489468fe 1795
b2680ced
SC
1796 // includeOuterStructures is true if we try to draw somthing like a focus ring etc.
1797 // also a window dc uses this, in this case we only clip in the hierarchy for hard
1798 // borders like a scrollwindow, splitter etc otherwise we end up in a paranoia having
1799 // to add focus borders everywhere
489468fe 1800
b2680ced 1801 Rect rIncludingOuterStructures ;
489468fe 1802
b2680ced
SC
1803 int tx,ty,tw,th;
1804
1805 m_peer->GetSize( tw, th );
1806 m_peer->GetPosition( tx, ty );
489468fe 1807
b2680ced 1808 Rect r = { ty,tx, ty+th, tx+tw };
489468fe 1809
b2680ced
SC
1810 r.left -= MacGetLeftBorderSize() ;
1811 r.top -= MacGetTopBorderSize() ;
1812 r.bottom += MacGetBottomBorderSize() ;
1813 r.right += MacGetRightBorderSize() ;
489468fe 1814
b2680ced
SC
1815 r.right -= r.left ;
1816 r.bottom -= r.top ;
1817 r.left = 0 ;
1818 r.top = 0 ;
489468fe 1819
b2680ced
SC
1820 rIncludingOuterStructures = r ;
1821 InsetRect( &rIncludingOuterStructures , -4 , -4 ) ;
489468fe 1822
b2680ced
SC
1823 wxRect cl = GetClientRect() ;
1824 Rect rClient = { cl.y , cl.x , cl.y + cl.height , cl.x + cl.width } ;
489468fe 1825
b2680ced
SC
1826 int x , y ;
1827 wxSize size ;
1828 const wxWindow* child = (wxWindow*) this ;
1829 const wxWindow* parent = NULL ;
489468fe 1830
b2680ced
SC
1831 while ( !child->IsTopLevel() && ( parent = child->GetParent() ) != NULL )
1832 {
1833 if ( parent->MacIsChildOfClientArea(child) )
1834 {
1835 size = parent->GetClientSize() ;
1836 wxPoint origin = parent->GetClientAreaOrigin() ;
1837 x = origin.x ;
1838 y = origin.y ;
1839 }
1840 else
1841 {
1842 // this will be true for scrollbars, toolbars etc.
1843 size = parent->GetSize() ;
1844 y = parent->MacGetTopBorderSize() ;
1845 x = parent->MacGetLeftBorderSize() ;
1846 size.x -= parent->MacGetLeftBorderSize() + parent->MacGetRightBorderSize() ;
1847 size.y -= parent->MacGetTopBorderSize() + parent->MacGetBottomBorderSize() ;
1848 }
489468fe 1849
b2680ced
SC
1850 parent->MacWindowToRootWindow( &x, &y ) ;
1851 MacRootWindowToWindow( &x , &y ) ;
489468fe 1852
b2680ced 1853 Rect rparent = { y , x , y + size.y , x + size.x } ;
489468fe 1854
b2680ced
SC
1855 // the wxwindow and client rects will always be clipped
1856 SectRect( &r , &rparent , &r ) ;
1857 SectRect( &rClient , &rparent , &rClient ) ;
489468fe 1858
b2680ced
SC
1859 // the structure only at 'hard' borders
1860 if ( parent->MacClipChildren() ||
1861 ( parent->GetParent() && parent->GetParent()->MacClipGrandChildren() ) )
1862 {
1863 SectRect( &rIncludingOuterStructures , &rparent , &rIncludingOuterStructures ) ;
1864 }
489468fe 1865
b2680ced
SC
1866 child = parent ;
1867 }
489468fe 1868
b2680ced
SC
1869 m_cachedClippedRect = wxRect( r.left , r.top , r.right - r.left , r.bottom - r.top ) ;
1870 m_cachedClippedClientRect = wxRect( rClient.left , rClient.top ,
1871 rClient.right - rClient.left , rClient.bottom - rClient.top ) ;
1872 m_cachedClippedRectWithOuterStructure = wxRect(
1873 rIncludingOuterStructures.left , rIncludingOuterStructures.top ,
1874 rIncludingOuterStructures.right - rIncludingOuterStructures.left ,
1875 rIncludingOuterStructures.bottom - rIncludingOuterStructures.top ) ;
489468fe 1876
b2680ced
SC
1877 m_cachedClippedRegionWithOuterStructure = wxRegion( m_cachedClippedRectWithOuterStructure ) ;
1878 m_cachedClippedRegion = wxRegion( m_cachedClippedRect ) ;
1879 m_cachedClippedClientRegion = wxRegion( m_cachedClippedClientRect ) ;
489468fe 1880
b2680ced
SC
1881 m_cachedClippedRectValid = true ;
1882#endif
489468fe
SC
1883}
1884
b2680ced
SC
1885/*
1886 This function must not change the updatergn !
1887 */
1888bool wxWindowMac::MacDoRedraw( void* updatergnr , long time )
489468fe 1889{
b2680ced
SC
1890 bool handled = false ;
1891#if wxOSX_USE_CARBON
1892 Rect updatebounds ;
1893 RgnHandle updatergn = (RgnHandle) updatergnr ;
1894 GetRegionBounds( updatergn , &updatebounds ) ;
489468fe 1895
b2680ced 1896 // wxLogDebug(wxT("update for %s bounds %d, %d, %d, %d"), wxString(GetClassInfo()->GetClassName()).c_str(), updatebounds.left, updatebounds.top , updatebounds.right , updatebounds.bottom ) ;
489468fe 1897
b2680ced 1898 if ( !EmptyRgn(updatergn) )
489468fe 1899 {
b2680ced
SC
1900 RgnHandle newupdate = NewRgn() ;
1901 wxSize point = GetClientSize() ;
1902 wxPoint origin = GetClientAreaOrigin() ;
1903 SetRectRgn( newupdate , origin.x , origin.y , origin.x + point.x , origin.y + point.y ) ;
1904 SectRgn( newupdate , updatergn , newupdate ) ;
489468fe 1905
b2680ced
SC
1906 // first send an erase event to the entire update area
1907 {
1908 // for the toplevel window this really is the entire area
1909 // for all the others only their client area, otherwise they
1910 // might be drawing with full alpha and eg put blue into
1911 // the grow-box area of a scrolled window (scroll sample)
1912 wxDC* dc = new wxWindowDC(this);
1913 if ( IsTopLevel() )
1914 dc->SetClippingRegion(wxRegion(HIShapeCreateWithQDRgn(updatergn)));
1915 else
1916 dc->SetClippingRegion(wxRegion(HIShapeCreateWithQDRgn(newupdate)));
489468fe 1917
b2680ced
SC
1918 wxEraseEvent eevent( GetId(), dc );
1919 eevent.SetEventObject( this );
1920 HandleWindowEvent( eevent );
1921 delete dc ;
1922 }
489468fe 1923
b2680ced 1924 MacPaintGrowBox();
489468fe 1925
b2680ced
SC
1926 // calculate a client-origin version of the update rgn and set m_updateRegion to that
1927 OffsetRgn( newupdate , -origin.x , -origin.y ) ;
1928 m_updateRegion = wxRegion(HIShapeCreateWithQDRgn(newupdate)) ;
1929 DisposeRgn( newupdate ) ;
489468fe 1930
b2680ced
SC
1931 if ( !m_updateRegion.Empty() )
1932 {
1933 // paint the window itself
489468fe 1934
b2680ced
SC
1935 wxPaintEvent event;
1936 event.SetTimestamp(time);
1937 event.SetEventObject(this);
1938 HandleWindowEvent(event);
1939 handled = true ;
1940 }
489468fe 1941
b2680ced
SC
1942 // now we cannot rely on having its borders drawn by a window itself, as it does not
1943 // get the updateRgn wide enough to always do so, so we do it from the parent
1944 // this would also be the place to draw any custom backgrounds for native controls
1945 // in Composited windowing
1946 wxPoint clientOrigin = GetClientAreaOrigin() ;
489468fe 1947
b2680ced
SC
1948 wxWindowMac *child;
1949 int x, y, w, h;
1950 for (wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); node; node = node->GetNext())
1951 {
1952 child = node->GetData();
1953 if (child == NULL)
1954 continue;
1955 if (child == m_vScrollBar)
1956 continue;
1957 if (child == m_hScrollBar)
1958 continue;
1959 if (child->IsTopLevel())
1960 continue;
1961 if (!child->IsShown())
1962 continue;
489468fe 1963
b2680ced 1964 // only draw those in the update region (add a safety margin of 10 pixels for shadow effects
489468fe 1965
b2680ced
SC
1966 child->GetPosition( &x, &y );
1967 child->GetSize( &w, &h );
1968 Rect childRect = { y , x , y + h , x + w } ;
1969 OffsetRect( &childRect , clientOrigin.x , clientOrigin.y ) ;
1970 InsetRect( &childRect , -10 , -10) ;
489468fe 1971
b2680ced
SC
1972 if ( RectInRgn( &childRect , updatergn ) )
1973 {
1974 // paint custom borders
1975 wxNcPaintEvent eventNc( child->GetId() );
1976 eventNc.SetEventObject( child );
1977 if ( !child->HandleWindowEvent( eventNc ) )
1978 {
1979 child->MacPaintBorders(0, 0) ;
1980 }
1981 }
489468fe
SC
1982 }
1983 }
b2680ced
SC
1984#endif
1985 return handled ;
489468fe
SC
1986}
1987
b2680ced
SC
1988
1989WXWindow wxWindowMac::MacGetTopLevelWindowRef() const
489468fe 1990{
b2680ced
SC
1991 wxNonOwnedWindow* tlw = MacGetTopLevelWindow();
1992 return tlw ? tlw->GetWXWindow() : NULL ;
1993}
1994
1995bool wxWindowMac::MacHasScrollBarCorner() const
1996{
1997 /* Returns whether the scroll bars in a wxScrolledWindow should be
1998 * shortened. Scroll bars should be shortened if either:
1999 *
2000 * - both scroll bars are visible, or
2001 *
2002 * - there is a resize box in the parent frame's corner and this
2003 * window shares the bottom and right edge with the parent
2004 * frame.
2005 */
2006
2007 if ( m_hScrollBar == NULL && m_vScrollBar == NULL )
2008 return false;
2009
2010 if ( ( m_hScrollBar && m_hScrollBar->IsShown() )
2011 && ( m_vScrollBar && m_vScrollBar->IsShown() ) )
489468fe 2012 {
b2680ced
SC
2013 // Both scroll bars visible
2014 return true;
489468fe
SC
2015 }
2016 else
2017 {
b2680ced 2018 wxPoint thisWindowBottomRight = GetScreenRect().GetBottomRight();
489468fe 2019
b2680ced 2020 for ( const wxWindow *win = (wxWindow*)this; win; win = win->GetParent() )
489468fe 2021 {
b2680ced
SC
2022 const wxFrame *frame = wxDynamicCast( win, wxFrame ) ;
2023 if ( frame )
489468fe 2024 {
b2680ced
SC
2025 if ( frame->GetWindowStyleFlag() & wxRESIZE_BORDER )
2026 {
2027 // Parent frame has resize handle
2028 wxPoint frameBottomRight = frame->GetScreenRect().GetBottomRight();
2029
2030 // Note: allow for some wiggle room here as wxMac's
2031 // window rect calculations seem to be imprecise
2032 if ( abs( thisWindowBottomRight.x - frameBottomRight.x ) <= 2
2033 && abs( thisWindowBottomRight.y - frameBottomRight.y ) <= 2 )
2034 {
2035 // Parent frame has resize handle and shares
2036 // right bottom corner
2037 return true ;
2038 }
2039 else
2040 {
2041 // Parent frame has resize handle but doesn't
2042 // share right bottom corner
2043 return false ;
2044 }
2045 }
2046 else
2047 {
2048 // Parent frame doesn't have resize handle
2049 return false ;
2050 }
489468fe
SC
2051 }
2052 }
2053
b2680ced
SC
2054 // No parent frame found
2055 return false ;
489468fe
SC
2056 }
2057}
2058
b2680ced 2059void wxWindowMac::MacCreateScrollBars( long style )
489468fe 2060{
b2680ced 2061 wxASSERT_MSG( m_vScrollBar == NULL && m_hScrollBar == NULL , wxT("attempt to create window twice") ) ;
489468fe 2062
b2680ced 2063 if ( style & ( wxVSCROLL | wxHSCROLL ) )
489468fe 2064 {
b2680ced
SC
2065 int scrlsize = MAC_SCROLLBAR_SIZE ;
2066 if ( GetWindowVariant() == wxWINDOW_VARIANT_SMALL || GetWindowVariant() == wxWINDOW_VARIANT_MINI )
2067 {
2068 scrlsize = MAC_SMALL_SCROLLBAR_SIZE ;
2069 }
489468fe 2070
b2680ced
SC
2071 int adjust = MacHasScrollBarCorner() ? scrlsize - 1: 0 ;
2072 int width, height ;
2073 GetClientSize( &width , &height ) ;
489468fe 2074
b2680ced
SC
2075 wxPoint vPoint(width - scrlsize, 0) ;
2076 wxSize vSize(scrlsize, height - adjust) ;
2077 wxPoint hPoint(0, height - scrlsize) ;
2078 wxSize hSize(width - adjust, scrlsize) ;
489468fe 2079
b2680ced
SC
2080 // we have to set the min size to a smaller value, otherwise they cannot get smaller (InitialSize sets MinSize)
2081 if ( style & wxVSCROLL )
489468fe 2082 {
b2680ced
SC
2083 m_vScrollBar = new wxScrollBar((wxWindow*)this, wxID_ANY, vPoint, vSize , wxVERTICAL);
2084 m_vScrollBar->SetMinSize( wxDefaultSize );
489468fe 2085 }
489468fe 2086
b2680ced 2087 if ( style & wxHSCROLL )
489468fe 2088 {
b2680ced
SC
2089 m_hScrollBar = new wxScrollBar((wxWindow*)this, wxID_ANY, hPoint, hSize , wxHORIZONTAL);
2090 m_hScrollBar->SetMinSize( wxDefaultSize );
489468fe
SC
2091 }
2092 }
2093
b2680ced
SC
2094 // because the create does not take into account the client area origin
2095 // we might have a real position shift
2096 MacRepositionScrollBars() ;
489468fe
SC
2097}
2098
b2680ced 2099bool wxWindowMac::MacIsChildOfClientArea( const wxWindow* child ) const
489468fe 2100{
b2680ced 2101 bool result = ((child == NULL) || ((child != m_hScrollBar) && (child != m_vScrollBar)));
489468fe 2102
b2680ced 2103 return result ;
489468fe
SC
2104}
2105
b2680ced 2106void wxWindowMac::MacRepositionScrollBars()
489468fe 2107{
b2680ced
SC
2108 if ( !m_hScrollBar && !m_vScrollBar )
2109 return ;
489468fe 2110
b2680ced
SC
2111 int scrlsize = m_hScrollBar ? m_hScrollBar->GetSize().y : ( m_vScrollBar ? m_vScrollBar->GetSize().x : MAC_SCROLLBAR_SIZE ) ;
2112 int adjust = MacHasScrollBarCorner() ? scrlsize - 1 : 0 ;
489468fe 2113
b2680ced
SC
2114 // get real client area
2115 int width, height ;
2116 GetSize( &width , &height );
489468fe 2117
b2680ced
SC
2118 width -= MacGetLeftBorderSize() + MacGetRightBorderSize();
2119 height -= MacGetTopBorderSize() + MacGetBottomBorderSize();
489468fe 2120
b2680ced
SC
2121 wxPoint vPoint( width - scrlsize, 0 ) ;
2122 wxSize vSize( scrlsize, height - adjust ) ;
2123 wxPoint hPoint( 0 , height - scrlsize ) ;
2124 wxSize hSize( width - adjust, scrlsize ) ;
489468fe 2125
b2680ced
SC
2126 if ( m_vScrollBar )
2127 m_vScrollBar->SetSize( vPoint.x , vPoint.y, vSize.x, vSize.y , wxSIZE_ALLOW_MINUS_ONE );
2128 if ( m_hScrollBar )
2129 m_hScrollBar->SetSize( hPoint.x , hPoint.y, hSize.x, hSize.y, wxSIZE_ALLOW_MINUS_ONE );
489468fe
SC
2130}
2131
b2680ced 2132bool wxWindowMac::AcceptsFocus() const
489468fe 2133{
b2680ced 2134 return m_peer->CanFocus() && wxWindowBase::AcceptsFocus();
489468fe
SC
2135}
2136
b2680ced 2137void wxWindowMac::MacSuperChangedPosition()
489468fe 2138{
b2680ced 2139 // only window-absolute structures have to be moved i.e. controls
489468fe 2140
b2680ced 2141 m_cachedClippedRectValid = false ;
489468fe 2142
b2680ced
SC
2143 wxWindowMac *child;
2144 wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
2145 while ( node )
2146 {
2147 child = node->GetData();
2148 child->MacSuperChangedPosition() ;
2149
2150 node = node->GetNext();
2151 }
489468fe
SC
2152}
2153
b2680ced 2154void wxWindowMac::MacTopLevelWindowChangedPosition()
489468fe 2155{
b2680ced 2156 // only screen-absolute structures have to be moved i.e. glcanvas
489468fe 2157
b2680ced
SC
2158 wxWindowMac *child;
2159 wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
2160 while ( node )
2161 {
2162 child = node->GetData();
2163 child->MacTopLevelWindowChangedPosition() ;
489468fe 2164
b2680ced
SC
2165 node = node->GetNext();
2166 }
489468fe
SC
2167}
2168
b2680ced 2169long wxWindowMac::MacGetLeftBorderSize() const
489468fe 2170{
b2680ced
SC
2171 if ( IsTopLevel() )
2172 return 0 ;
489468fe 2173
b2680ced 2174 SInt32 border = 0 ;
489468fe 2175
b2680ced
SC
2176 if (HasFlag(wxRAISED_BORDER) || HasFlag( wxSUNKEN_BORDER) || HasFlag(wxDOUBLE_BORDER))
2177 {
2178#if wxOSX_USE_COCOA_OR_CARBON
2179 // this metric is only the 'outset' outside the simple frame rect
2180 GetThemeMetric( kThemeMetricEditTextFrameOutset , &border ) ;
2181 border += 1;
2182#else
2183 border += 2;
2184#endif
2185 }
2186 else if (HasFlag(wxSIMPLE_BORDER))
2187 {
2188#if wxOSX_USE_COCOA_OR_CARBON
2189 // this metric is only the 'outset' outside the simple frame rect
2190 GetThemeMetric( kThemeMetricListBoxFrameOutset , &border ) ;
2191 border += 1;
2192#else
2193 border += 1;
2194#endif
2195 }
489468fe 2196
b2680ced 2197 return border ;
489468fe
SC
2198}
2199
b2680ced 2200long wxWindowMac::MacGetRightBorderSize() const
489468fe 2201{
b2680ced
SC
2202 // they are all symmetric in mac themes
2203 return MacGetLeftBorderSize() ;
489468fe
SC
2204}
2205
b2680ced 2206long wxWindowMac::MacGetTopBorderSize() const
489468fe 2207{
b2680ced
SC
2208 // they are all symmetric in mac themes
2209 return MacGetLeftBorderSize() ;
489468fe
SC
2210}
2211
b2680ced 2212long wxWindowMac::MacGetBottomBorderSize() const
489468fe 2213{
b2680ced
SC
2214 // they are all symmetric in mac themes
2215 return MacGetLeftBorderSize() ;
489468fe
SC
2216}
2217
b2680ced 2218long wxWindowMac::MacRemoveBordersFromStyle( long style )
489468fe 2219{
b2680ced 2220 return style & ~wxBORDER_MASK ;
489468fe
SC
2221}
2222
b2680ced
SC
2223// Find the wxWindowMac at the current mouse position, returning the mouse
2224// position.
2225wxWindow * wxFindWindowAtPointer( wxPoint& pt )
489468fe 2226{
b2680ced
SC
2227 pt = wxGetMousePosition();
2228 wxWindowMac* found = wxFindWindowAtPoint(pt);
489468fe 2229
b2680ced 2230 return (wxWindow*) found;
489468fe
SC
2231}
2232
b2680ced
SC
2233// Get the current mouse position.
2234wxPoint wxGetMousePosition()
489468fe 2235{
b2680ced 2236 int x, y;
489468fe 2237
b2680ced
SC
2238 wxGetMousePosition( &x, &y );
2239
2240 return wxPoint(x, y);
2241}
489468fe 2242
b2680ced
SC
2243void wxWindowMac::OnMouseEvent( wxMouseEvent &event )
2244{
2245 if ( event.GetEventType() == wxEVT_RIGHT_DOWN )
489468fe 2246 {
b2680ced
SC
2247 // copied from wxGTK : CS
2248 // VZ: shouldn't we move this to base class then?
489468fe 2249
b2680ced
SC
2250 // generate a "context menu" event: this is similar to wxEVT_RIGHT_DOWN
2251 // except that:
2252 //
2253 // (a) it's a command event and so is propagated to the parent
2254 // (b) under MSW it can be generated from kbd too
2255 // (c) it uses screen coords (because of (a))
2256 wxContextMenuEvent evtCtx(wxEVT_CONTEXT_MENU,
2257 this->GetId(),
2258 this->ClientToScreen(event.GetPosition()));
2259 evtCtx.SetEventObject(this);
2260 if ( ! HandleWindowEvent(evtCtx) )
2261 event.Skip() ;
489468fe
SC
2262 }
2263 else
2264 {
b2680ced 2265 event.Skip() ;
489468fe
SC
2266 }
2267}
2268
b2680ced 2269void wxWindowMac::OnPaint( wxPaintEvent & WXUNUSED(event) )
489468fe 2270{
b2680ced
SC
2271#if wxOSX_USE_COCOA_OR_CARBON
2272 // for native controls: call their native paint method
2273 if ( !MacIsUserPane() || ( IsTopLevel() && GetBackgroundStyle() == wxBG_STYLE_SYSTEM ) )
489468fe 2274 {
b2680ced
SC
2275 if ( wxTheApp->MacGetCurrentEvent() != NULL && wxTheApp->MacGetCurrentEventHandlerCallRef() != NULL
2276 && GetBackgroundStyle() != wxBG_STYLE_TRANSPARENT )
2277 CallNextEventHandler(
2278 (EventHandlerCallRef)wxTheApp->MacGetCurrentEventHandlerCallRef() ,
2279 (EventRef) wxTheApp->MacGetCurrentEvent() ) ;
489468fe
SC
2280 }
2281#endif
2282}
2283
b2680ced
SC
2284void wxWindowMac::MacHandleControlClick(WXWidget WXUNUSED(control),
2285 wxInt16 WXUNUSED(controlpart),
2286 bool WXUNUSED(mouseStillDown))
489468fe 2287{
489468fe
SC
2288}
2289
b2680ced 2290Rect wxMacGetBoundsForControl( wxWindowMac* window , const wxPoint& pos , const wxSize &size , bool adjustForOrigin )
489468fe 2291{
b2680ced
SC
2292 int x, y, w, h ;
2293
2294 window->MacGetBoundsForControl( pos , size , x , y, w, h , adjustForOrigin ) ;
2295 Rect bounds = { y, x, y + h, x + w };
2296
2297 return bounds ;
489468fe
SC
2298}
2299
b2680ced 2300wxInt32 wxWindowMac::MacControlHit(WXEVENTHANDLERREF WXUNUSED(handler) , WXEVENTREF WXUNUSED(event) )
489468fe 2301{
b2680ced
SC
2302#if wxOSX_USE_COCOA_OR_CARBON
2303 return eventNotHandledErr ;
2304#else
2305 return 0;
489468fe 2306#endif
489468fe
SC
2307}
2308
b2680ced 2309bool wxWindowMac::Reparent(wxWindowBase *newParentBase)
489468fe 2310{
b2680ced
SC
2311 wxWindowMac *newParent = (wxWindowMac *)newParentBase;
2312 if ( !wxWindowBase::Reparent(newParent) )
2313 return false;
2314
2315 m_peer->RemoveFromParent();
2316 m_peer->Embed( GetParent()->GetPeer() );
2317 return true;
489468fe
SC
2318}
2319
b2680ced 2320bool wxWindowMac::SetTransparent(wxByte alpha)
489468fe 2321{
b2680ced
SC
2322 SetBackgroundStyle(wxBG_STYLE_TRANSPARENT);
2323
2324 if ( alpha != m_macAlpha )
489468fe 2325 {
b2680ced
SC
2326 m_macAlpha = alpha ;
2327 Refresh() ;
489468fe 2328 }
b2680ced 2329 return true ;
489468fe
SC
2330}
2331
489468fe 2332
b2680ced
SC
2333bool wxWindowMac::CanSetTransparent()
2334{
2335 return true ;
489468fe
SC
2336}
2337
b2680ced 2338wxByte wxWindowMac::GetTransparent() const
489468fe 2339{
b2680ced 2340 return m_macAlpha ;
489468fe
SC
2341}
2342
b2680ced 2343bool wxWindowMac::IsShownOnScreen() const
489468fe 2344{
b2680ced 2345 if ( m_peer && m_peer->IsOk() )
489468fe 2346 {
b2680ced
SC
2347 bool peerVis = m_peer->IsVisible();
2348 bool wxVis = wxWindowBase::IsShownOnScreen();
2349 if( peerVis != wxVis )
2350 {
2351 // CS : put a breakpoint here to investigate differences
2352 // between native an wx visibilities
2353 // the only place where I've encountered them until now
2354 // are the hiding/showing sequences where the vis-changed event is
2355 // first sent to the innermost control, while wx does things
2356 // from the outmost control
2357 wxVis = wxWindowBase::IsShownOnScreen();
2358 return wxVis;
2359 }
2360
2361 return m_peer->IsVisible();
489468fe 2362 }
b2680ced 2363 return wxWindowBase::IsShownOnScreen();
489468fe
SC
2364}
2365
b2680ced
SC
2366#if wxOSX_USE_CARBON
2367//
2368// impl
2369//
489468fe 2370
489468fe 2371
b2680ced
SC
2372// ---------------------------------------------------------------------------
2373// Carbon Events
2374// ---------------------------------------------------------------------------
489468fe 2375
b2680ced
SC
2376static const EventTypeSpec eventList[] =
2377{
2378 { kEventClassCommand, kEventProcessCommand } ,
2379 { kEventClassCommand, kEventCommandUpdateStatus } ,
489468fe 2380
b2680ced
SC
2381 { kEventClassControl , kEventControlGetClickActivation } ,
2382 { kEventClassControl , kEventControlHit } ,
489468fe 2383
b2680ced
SC
2384 { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent } ,
2385 { kEventClassTextInput, kEventTextInputUpdateActiveInputArea } ,
489468fe 2386
b2680ced 2387 { kEventClassControl , kEventControlDraw } ,
489468fe 2388
b2680ced
SC
2389 { kEventClassControl , kEventControlVisibilityChanged } ,
2390 { kEventClassControl , kEventControlEnabledStateChanged } ,
2391 { kEventClassControl , kEventControlHiliteChanged } ,
489468fe 2392
b2680ced
SC
2393 { kEventClassControl , kEventControlActivate } ,
2394 { kEventClassControl , kEventControlDeactivate } ,
489468fe 2395
b2680ced
SC
2396 { kEventClassControl , kEventControlSetFocusPart } ,
2397 { kEventClassControl , kEventControlFocusPartChanged } ,
489468fe 2398
b2680ced
SC
2399 { kEventClassService , kEventServiceGetTypes },
2400 { kEventClassService , kEventServiceCopy },
2401 { kEventClassService , kEventServicePaste },
489468fe 2402
b2680ced
SC
2403// { kEventClassControl , kEventControlInvalidateForSizeChange } , // 10.3 only
2404// { kEventClassControl , kEventControlBoundsChanged } ,
2405} ;
2406
2407static pascal OSStatus wxMacWindowControlEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
489468fe 2408{
b2680ced
SC
2409 OSStatus result = eventNotHandledErr ;
2410 static wxWindowMac* targetFocusWindow = NULL;
2411 static wxWindowMac* formerFocusWindow = NULL;
489468fe 2412
b2680ced 2413 wxMacCarbonEvent cEvent( event ) ;
489468fe 2414
b2680ced
SC
2415 ControlRef controlRef ;
2416 wxWindowMac* thisWindow = (wxWindowMac*) data ;
2417
2418 cEvent.GetParameter( kEventParamDirectObject , &controlRef ) ;
489468fe 2419
b2680ced 2420 switch ( GetEventKind( event ) )
489468fe 2421 {
b2680ced
SC
2422 case kEventControlDraw :
2423 {
2424 RgnHandle updateRgn = NULL ;
2425 RgnHandle allocatedRgn = NULL ;
2426 wxRegion visRegion = thisWindow->MacGetVisibleRegion() ;
489468fe 2427
b2680ced
SC
2428 if ( cEvent.GetParameter<RgnHandle>(kEventParamRgnHandle, &updateRgn) != noErr )
2429 {
2430 HIShapeGetAsQDRgn( visRegion.GetWXHRGN(), updateRgn );
2431 }
2432 else
2433 {
2434 if ( thisWindow->MacGetLeftBorderSize() != 0 || thisWindow->MacGetTopBorderSize() != 0 )
2435 {
2436 // as this update region is in native window locals we must adapt it to wx window local
2437 allocatedRgn = NewRgn() ;
2438 CopyRgn( updateRgn , allocatedRgn ) ;
489468fe 2439
b2680ced
SC
2440 // hide the given region by the new region that must be shifted
2441 OffsetRgn( allocatedRgn , thisWindow->MacGetLeftBorderSize() , thisWindow->MacGetTopBorderSize() ) ;
2442 updateRgn = allocatedRgn ;
2443 }
2444 }
489468fe 2445
b2680ced
SC
2446#if wxMAC_DEBUG_REDRAW
2447 if ( thisWindow->MacIsUserPane() )
2448 {
2449 static float color = 0.5 ;
2450 static int channel = 0 ;
2451 HIRect bounds;
2452 CGContextRef cgContext = cEvent.GetParameter<CGContextRef>(kEventParamCGContextRef) ;
489468fe 2453
b2680ced
SC
2454 HIViewGetBounds( controlRef, &bounds );
2455 CGContextSetRGBFillColor( cgContext, channel == 0 ? color : 0.5 ,
2456 channel == 1 ? color : 0.5 , channel == 2 ? color : 0.5 , 1 );
2457 CGContextFillRect( cgContext, bounds );
2458 color += 0.1 ;
2459 if ( color > 0.9 )
2460 {
2461 color = 0.5 ;
2462 channel++ ;
2463 if ( channel == 3 )
2464 channel = 0 ;
2465 }
2466 }
489468fe 2467#endif
489468fe 2468
b2680ced
SC
2469 {
2470 bool created = false ;
2471 CGContextRef cgContext = NULL ;
2472 OSStatus err = cEvent.GetParameter<CGContextRef>(kEventParamCGContextRef, &cgContext) ;
2473 if ( err != noErr )
2474 {
2475 wxFAIL_MSG("Unable to retrieve CGContextRef");
2476 }
489468fe 2477
b2680ced 2478 thisWindow->MacSetCGContextRef( cgContext ) ;
489468fe 2479
b2680ced
SC
2480 {
2481 wxMacCGContextStateSaver sg( cgContext ) ;
2482 CGFloat alpha = (CGFloat)1.0 ;
2483 {
2484 wxWindow* iter = thisWindow ;
2485 while ( iter )
2486 {
2487 alpha *= (CGFloat)( iter->GetTransparent()/255.0 ) ;
2488 if ( iter->IsTopLevel() )
2489 iter = NULL ;
2490 else
2491 iter = iter->GetParent() ;
2492 }
2493 }
2494 CGContextSetAlpha( cgContext , alpha ) ;
489468fe 2495
b2680ced
SC
2496 if ( thisWindow->GetBackgroundStyle() == wxBG_STYLE_TRANSPARENT )
2497 {
2498 HIRect bounds;
2499 HIViewGetBounds( controlRef, &bounds );
2500 CGContextClearRect( cgContext, bounds );
2501 }
489468fe 2502
489468fe 2503
489468fe 2504
b2680ced
SC
2505 if ( thisWindow->MacDoRedraw( updateRgn , cEvent.GetTicks() ) )
2506 result = noErr ;
489468fe 2507
b2680ced
SC
2508 thisWindow->MacSetCGContextRef( NULL ) ;
2509 }
489468fe 2510
b2680ced
SC
2511 if ( created )
2512 CGContextRelease( cgContext ) ;
2513 }
489468fe 2514
b2680ced
SC
2515 if ( allocatedRgn )
2516 DisposeRgn( allocatedRgn ) ;
2517 }
2518 break ;
489468fe 2519
b2680ced
SC
2520 case kEventControlVisibilityChanged :
2521 // we might have two native controls attributed to the same wxWindow instance
2522 // eg a scrollview and an embedded textview, make sure we only fire for the 'outer'
2523 // control, as otherwise native and wx visibility are different
2524 if ( thisWindow->GetPeer() != NULL && thisWindow->GetPeer()->GetControlRef() == controlRef )
2525 {
2526 thisWindow->MacVisibilityChanged() ;
2527 }
2528 break ;
489468fe 2529
b2680ced
SC
2530 case kEventControlEnabledStateChanged :
2531 thisWindow->MacEnabledStateChanged();
2532 break ;
489468fe 2533
b2680ced
SC
2534 case kEventControlHiliteChanged :
2535 thisWindow->MacHiliteChanged() ;
2536 break ;
489468fe 2537
b2680ced
SC
2538 case kEventControlActivate :
2539 case kEventControlDeactivate :
2540 // FIXME: we should have a virtual function for this!
2541#if wxUSE_TREECTRL
2542 if ( thisWindow->IsKindOf( CLASSINFO( wxTreeCtrl ) ) )
2543 thisWindow->Refresh();
2544#endif
2545#if wxUSE_LISTCTRL
2546 if ( thisWindow->IsKindOf( CLASSINFO( wxListCtrl ) ) )
2547 thisWindow->Refresh();
2548#endif
2549 break ;
2550
2551 //
2552 // focus handling
2553 // different handling on OS X
2554 //
2555
2556 case kEventControlFocusPartChanged :
2557 // the event is emulated by wxmac for systems lower than 10.5
2558 {
2559 if ( UMAGetSystemVersion() < 0x1050 )
2560 {
2561 // as it is synthesized here, we have to manually avoid propagation
2562 result = noErr;
2563 }
2564 ControlPartCode previousControlPart = cEvent.GetParameter<ControlPartCode>(kEventParamControlPreviousPart , typeControlPartCode );
2565 ControlPartCode currentControlPart = cEvent.GetParameter<ControlPartCode>(kEventParamControlCurrentPart , typeControlPartCode );
2566
2567 if ( thisWindow->MacGetTopLevelWindow() && thisWindow->GetPeer()->NeedsFocusRect() )
2568 {
2569 thisWindow->MacInvalidateBorders();
2570 }
2571
2572 if ( currentControlPart == 0 )
2573 {
2574 // kill focus
2575#if wxUSE_CARET
2576 if ( thisWindow->GetCaret() )
2577 thisWindow->GetCaret()->OnKillFocus();
2578#endif
2579
2580 wxLogTrace(_T("Focus"), _T("focus lost(%p)"), wx_static_cast(void*, thisWindow));
2581
2582 // remove this as soon as posting the synthesized event works properly
2583 static bool inKillFocusEvent = false ;
2584
2585 if ( !inKillFocusEvent )
2586 {
2587 inKillFocusEvent = true ;
2588 wxFocusEvent event( wxEVT_KILL_FOCUS, thisWindow->GetId());
2589 event.SetEventObject(thisWindow);
2590 event.SetWindow(targetFocusWindow);
2591 thisWindow->HandleWindowEvent(event) ;
2592 inKillFocusEvent = false ;
2593 targetFocusWindow = NULL;
2594 }
2595 }
2596 else if ( previousControlPart == 0 )
2597 {
2598 // set focus
2599 // panel wants to track the window which was the last to have focus in it
2600 wxLogTrace(_T("Focus"), _T("focus set(%p)"), wx_static_cast(void*, thisWindow));
2601 wxChildFocusEvent eventFocus((wxWindow*)thisWindow);
2602 thisWindow->HandleWindowEvent(eventFocus);
2603
2604#if wxUSE_CARET
2605 if ( thisWindow->GetCaret() )
2606 thisWindow->GetCaret()->OnSetFocus();
2607#endif
2608
2609 wxFocusEvent event(wxEVT_SET_FOCUS, thisWindow->GetId());
2610 event.SetEventObject(thisWindow);
2611 event.SetWindow(formerFocusWindow);
2612 thisWindow->HandleWindowEvent(event) ;
2613 formerFocusWindow = NULL;
2614 }
2615 }
2616 break;
2617 case kEventControlSetFocusPart :
2618 {
2619 Boolean focusEverything = false ;
2620 if ( cEvent.GetParameter<Boolean>(kEventParamControlFocusEverything , &focusEverything ) == noErr )
2621 {
2622 // put a breakpoint here to catch focus everything events
2623 }
2624 ControlPartCode controlPart = cEvent.GetParameter<ControlPartCode>(kEventParamControlPart , typeControlPartCode );
2625 if ( controlPart != kControlFocusNoPart )
2626 {
2627 targetFocusWindow = thisWindow;
2628 wxLogTrace(_T("Focus"), _T("focus to be set(%p)"), wx_static_cast(void*, thisWindow));
2629 }
2630 else
2631 {
2632 formerFocusWindow = thisWindow;
2633 wxLogTrace(_T("Focus"), _T("focus to be lost(%p)"), wx_static_cast(void*, thisWindow));
2634 }
2635
2636 ControlPartCode previousControlPart = 0;
2637 verify_noerr( HIViewGetFocusPart(controlRef, &previousControlPart));
2638
2639 if ( thisWindow->MacIsUserPane() )
2640 {
2641 if ( controlPart != kControlFocusNoPart )
2642 cEvent.SetParameter<ControlPartCode>( kEventParamControlPart, typeControlPartCode, 1 ) ;
2643 result = noErr ;
2644 }
2645 else
2646 result = CallNextEventHandler(handler, event);
2647
2648 if ( UMAGetSystemVersion() < 0x1050 )
2649 {
2650// set back to 0 if problems arise
2651#if 1
2652 if ( result == noErr )
2653 {
2654 ControlPartCode currentControlPart = cEvent.GetParameter<ControlPartCode>(kEventParamControlPart , typeControlPartCode );
2655 // synthesize the event focus changed event
2656 EventRef evRef = NULL ;
2657
2658 OSStatus err = MacCreateEvent(
2659 NULL , kEventClassControl , kEventControlFocusPartChanged , TicksToEventTime( TickCount() ) ,
2660 kEventAttributeUserEvent , &evRef );
2661 verify_noerr( err );
2662
2663 wxMacCarbonEvent iEvent( evRef ) ;
2664 iEvent.SetParameter<ControlRef>( kEventParamDirectObject , controlRef );
2665 iEvent.SetParameter<EventTargetRef>( kEventParamPostTarget, typeEventTargetRef, GetControlEventTarget( controlRef ) );
2666 iEvent.SetParameter<ControlPartCode>( kEventParamControlPreviousPart, typeControlPartCode, previousControlPart );
2667 iEvent.SetParameter<ControlPartCode>( kEventParamControlCurrentPart, typeControlPartCode, currentControlPart );
2668
489468fe 2669#if 1
b2680ced
SC
2670 // TODO test this first, avoid double posts etc...
2671 PostEventToQueue( GetMainEventQueue(), evRef , kEventPriorityHigh );
489468fe 2672#else
b2680ced
SC
2673 wxMacWindowControlEventHandler( NULL , evRef , data ) ;
2674#endif
2675 ReleaseEvent( evRef ) ;
2676 }
2677#else
2678 // old implementation, to be removed if the new one works
2679 if ( controlPart == kControlFocusNoPart )
2680 {
2681#if wxUSE_CARET
2682 if ( thisWindow->GetCaret() )
2683 thisWindow->GetCaret()->OnKillFocus();
489468fe 2684#endif
489468fe 2685
b2680ced 2686 wxLogTrace(_T("Focus"), _T("focus lost(%p)"), wx_static_cast(void*, thisWindow));
489468fe 2687
b2680ced
SC
2688 static bool inKillFocusEvent = false ;
2689
2690 if ( !inKillFocusEvent )
2691 {
2692 inKillFocusEvent = true ;
2693 wxFocusEvent event( wxEVT_KILL_FOCUS, thisWindow->GetId());
2694 event.SetEventObject(thisWindow);
2695 thisWindow->HandleWindowEvent(event) ;
2696 inKillFocusEvent = false ;
2697 }
2698 }
2699 else
2700 {
2701 // panel wants to track the window which was the last to have focus in it
2702 wxLogTrace(_T("Focus"), _T("focus set(%p)"), wx_static_cast(void*, thisWindow));
2703 wxChildFocusEvent eventFocus((wxWindow*)thisWindow);
2704 thisWindow->HandleWindowEvent(eventFocus);
2705
2706 #if wxUSE_CARET
2707 if ( thisWindow->GetCaret() )
2708 thisWindow->GetCaret()->OnSetFocus();
2709 #endif
2710
2711 wxFocusEvent event(wxEVT_SET_FOCUS, thisWindow->GetId());
2712 event.SetEventObject(thisWindow);
2713 thisWindow->HandleWindowEvent(event) ;
2714 }
489468fe 2715#endif
b2680ced
SC
2716 }
2717 }
2718 break ;
2719
2720 case kEventControlHit :
2721 result = thisWindow->MacControlHit( handler , event ) ;
2722 break ;
2723
2724 case kEventControlGetClickActivation :
2725 {
2726 // fix to always have a proper activation for DataBrowser controls (stay in bkgnd otherwise)
2727 WindowRef owner = cEvent.GetParameter<WindowRef>(kEventParamWindowRef);
2728 if ( !IsWindowActive(owner) )
2729 {
2730 cEvent.SetParameter(kEventParamClickActivation,(UInt32) kActivateAndIgnoreClick) ;
2731 result = noErr ;
2732 }
2733 }
2734 break ;
2735
2736 default :
2737 break ;
489468fe
SC
2738 }
2739
b2680ced
SC
2740 return result ;
2741}
2742
2743static pascal OSStatus
2744wxMacWindowServiceEventHandler(EventHandlerCallRef WXUNUSED(handler),
2745 EventRef event,
2746 void *data)
2747{
2748 OSStatus result = eventNotHandledErr ;
2749
2750 wxMacCarbonEvent cEvent( event ) ;
2751
2752 ControlRef controlRef ;
2753 wxWindowMac* thisWindow = (wxWindowMac*) data ;
2754 wxTextCtrl* textCtrl = wxDynamicCast( thisWindow , wxTextCtrl ) ;
2755 cEvent.GetParameter( kEventParamDirectObject , &controlRef ) ;
2756
2757 switch ( GetEventKind( event ) )
489468fe 2758 {
b2680ced
SC
2759 case kEventServiceGetTypes :
2760 if ( textCtrl )
2761 {
2762 long from, to ;
2763 textCtrl->GetSelection( &from , &to ) ;
489468fe 2764
b2680ced
SC
2765 CFMutableArrayRef copyTypes = 0 , pasteTypes = 0;
2766 if ( from != to )
2767 copyTypes = cEvent.GetParameter< CFMutableArrayRef >( kEventParamServiceCopyTypes , typeCFMutableArrayRef ) ;
2768 if ( textCtrl->IsEditable() )
2769 pasteTypes = cEvent.GetParameter< CFMutableArrayRef >( kEventParamServicePasteTypes , typeCFMutableArrayRef ) ;
2770
2771 static const OSType textDataTypes[] = { kTXNTextData /* , 'utxt', 'PICT', 'MooV', 'AIFF' */ };
2772 for ( size_t i = 0 ; i < WXSIZEOF(textDataTypes) ; ++i )
2773 {
2774 CFStringRef typestring = CreateTypeStringWithOSType(textDataTypes[i]);
2775 if ( typestring )
2776 {
2777 if ( copyTypes )
2778 CFArrayAppendValue(copyTypes, typestring) ;
2779 if ( pasteTypes )
2780 CFArrayAppendValue(pasteTypes, typestring) ;
2781
2782 CFRelease( typestring ) ;
2783 }
2784 }
2785
2786 result = noErr ;
2787 }
2788 break ;
2789
2790 case kEventServiceCopy :
2791 if ( textCtrl )
2792 {
2793 long from, to ;
2794
2795 textCtrl->GetSelection( &from , &to ) ;
2796 wxString val = textCtrl->GetValue() ;
2797 val = val.Mid( from , to - from ) ;
2798 PasteboardRef pasteboard = cEvent.GetParameter<PasteboardRef>( kEventParamPasteboardRef, typePasteboardRef );
2799 verify_noerr( PasteboardClear( pasteboard ) ) ;
2800 PasteboardSynchronize( pasteboard );
2801 // TODO add proper conversion
2802 CFDataRef data = CFDataCreate( kCFAllocatorDefault, (const UInt8*)val.c_str(), val.length() );
2803 PasteboardPutItemFlavor( pasteboard, (PasteboardItemID) 1, CFSTR("com.apple.traditional-mac-plain-text"), data, 0);
2804 CFRelease( data );
2805 result = noErr ;
2806 }
2807 break ;
2808
2809 case kEventServicePaste :
2810 if ( textCtrl )
2811 {
2812 PasteboardRef pasteboard = cEvent.GetParameter<PasteboardRef>( kEventParamPasteboardRef, typePasteboardRef );
2813 PasteboardSynchronize( pasteboard );
2814 ItemCount itemCount;
2815 verify_noerr( PasteboardGetItemCount( pasteboard, &itemCount ) );
2816 for( UInt32 itemIndex = 1; itemIndex <= itemCount; itemIndex++ )
2817 {
2818 PasteboardItemID itemID;
2819 if ( PasteboardGetItemIdentifier( pasteboard, itemIndex, &itemID ) == noErr )
2820 {
2821 CFDataRef flavorData = NULL;
2822 if ( PasteboardCopyItemFlavorData( pasteboard, itemID, CFSTR("com.apple.traditional-mac-plain-text"), &flavorData ) == noErr )
2823 {
2824 CFIndex flavorDataSize = CFDataGetLength( flavorData );
2825 char *content = new char[flavorDataSize+1] ;
2826 memcpy( content, CFDataGetBytePtr( flavorData ), flavorDataSize );
2827 content[flavorDataSize]=0;
2828 CFRelease( flavorData );
2829#if wxUSE_UNICODE
2830 textCtrl->WriteText( wxString( content , wxConvLocal ) );
2831#else
2832 textCtrl->WriteText( wxString( content ) ) ;
2833#endif
2834
2835 delete[] content ;
2836 result = noErr ;
2837 }
2838 }
2839 }
2840 }
2841 break ;
2842
2843 default:
2844 break ;
489468fe 2845 }
b2680ced
SC
2846
2847 return result ;
489468fe
SC
2848}
2849
b2680ced 2850pascal OSStatus wxMacUnicodeTextEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
489468fe 2851{
b2680ced
SC
2852 OSStatus result = eventNotHandledErr ;
2853 wxWindowMac* focus = (wxWindowMac*) data ;
2854
2855 wchar_t* uniChars = NULL ;
2856 UInt32 when = EventTimeToTicks( GetEventTime( event ) ) ;
2857
2858 UniChar* charBuf = NULL;
2859 ByteCount dataSize = 0 ;
2860 int numChars = 0 ;
2861 UniChar buf[2] ;
2862 if ( GetEventParameter( event, kEventParamTextInputSendText, typeUnicodeText, NULL, 0 , &dataSize, NULL ) == noErr )
489468fe 2863 {
b2680ced
SC
2864 numChars = dataSize / sizeof( UniChar) + 1;
2865 charBuf = buf ;
489468fe 2866
b2680ced
SC
2867 if ( (size_t) numChars * 2 > sizeof(buf) )
2868 charBuf = new UniChar[ numChars ] ;
2869 else
2870 charBuf = buf ;
2871
2872 uniChars = new wchar_t[ numChars ] ;
2873 GetEventParameter( event, kEventParamTextInputSendText, typeUnicodeText, NULL, dataSize , NULL , charBuf ) ;
2874 charBuf[ numChars - 1 ] = 0;
2875#if SIZEOF_WCHAR_T == 2
2876 uniChars = (wchar_t*) charBuf ;
2877/* memcpy( uniChars , charBuf , numChars * 2 ) ;*/ // is there any point in copying charBuf over itself? (in fact, memcpy isn't even guaranteed to work correctly if the source and destination ranges overlap...)
2878#else
2879 // the resulting string will never have more chars than the utf16 version, so this is safe
2880 wxMBConvUTF16 converter ;
2881 numChars = converter.MB2WC( uniChars , (const char*)charBuf , numChars ) ;
2882#endif
2883 }
2884
2885 switch ( GetEventKind( event ) )
2886 {
2887 case kEventTextInputUpdateActiveInputArea :
2888 {
2889 // An IME input event may return several characters, but we need to send one char at a time to
2890 // EVT_CHAR
2891 for (int pos=0 ; pos < numChars ; pos++)
2892 {
2893 WXEVENTREF formerEvent = wxTheApp->MacGetCurrentEvent() ;
2894 WXEVENTHANDLERCALLREF formerHandler = wxTheApp->MacGetCurrentEventHandlerCallRef() ;
2895 wxTheApp->MacSetCurrentEvent( event , handler ) ;
2896
2897 UInt32 message = uniChars[pos] < 128 ? (char)uniChars[pos] : '?';
2898/*
2899 NB: faking a charcode here is problematic. The kEventTextInputUpdateActiveInputArea event is sent
2900 multiple times to update the active range during inline input, so this handler will often receive
2901 uncommited text, which should usually not trigger side effects. It might be a good idea to check the
2902 kEventParamTextInputSendFixLen parameter and verify if input is being confirmed (see CarbonEvents.h).
2903 On the other hand, it can be useful for some applications to react to uncommitted text (for example,
2904 to update a status display), as long as it does not disrupt the inline input session. Ideally, wx
2905 should add new event types to support advanced text input. For now, I would keep things as they are.
2906
2907 However, the code that was being used caused additional problems:
2908 UInt32 message = (0 << 8) + ((char)uniChars[pos] );
2909 Since it simply truncated the unichar to the last byte, it ended up causing weird bugs with inline
2910 input, such as switching to another field when one attempted to insert the character U+4E09 (the kanji
2911 for "three"), because it was truncated to 09 (kTabCharCode), which was later "converted" to WXK_TAB
2912 (still 09) in wxMacTranslateKey; or triggering the default button when one attempted to insert U+840D
2913 (the kanji for "name"), which got truncated to 0D and interpreted as a carriage return keypress.
2914 Note that even single-byte characters could have been misinterpreted, since MacRoman charcodes only
2915 overlap with Unicode within the (7-bit) ASCII range.
2916 But simply passing a NUL charcode would disable text updated events, because wxTextCtrl::OnChar checks
2917 for codes within a specific range. Therefore I went for the solution seen above, which keeps ASCII
2918 characters as they are and replaces the rest with '?', ensuring that update events are triggered.
2919 It would be better to change wxTextCtrl::OnChar to look at the actual unicode character instead, but
2920 I don't have time to look into that right now.
2921 -- CL
2922*/
2923 if ( wxTheApp->MacSendCharEvent(
2924 focus , message , 0 , when , 0 , 0 , uniChars[pos] ) )
2925 {
2926 result = noErr ;
2927 }
2928
2929 wxTheApp->MacSetCurrentEvent( formerEvent , formerHandler ) ;
2930 }
2931 }
2932 break ;
2933 case kEventTextInputUnicodeForKeyEvent :
2934 {
2935 UInt32 keyCode, modifiers ;
2936 Point point ;
2937 EventRef rawEvent ;
2938 unsigned char charCode ;
2939
2940 GetEventParameter( event, kEventParamTextInputSendKeyboardEvent, typeEventRef, NULL, sizeof(rawEvent), NULL, &rawEvent ) ;
2941 GetEventParameter( rawEvent, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &charCode );
2942 GetEventParameter( rawEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode );
2943 GetEventParameter( rawEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers );
2944 GetEventParameter( rawEvent, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &point );
2945
2946 UInt32 message = (keyCode << 8) + charCode;
489468fe 2947
b2680ced
SC
2948 // An IME input event may return several characters, but we need to send one char at a time to
2949 // EVT_CHAR
2950 for (int pos=0 ; pos < numChars ; pos++)
2951 {
2952 WXEVENTREF formerEvent = wxTheApp->MacGetCurrentEvent() ;
2953 WXEVENTHANDLERCALLREF formerHandler = wxTheApp->MacGetCurrentEventHandlerCallRef() ;
2954 wxTheApp->MacSetCurrentEvent( event , handler ) ;
2955
2956 if ( wxTheApp->MacSendCharEvent(
2957 focus , message , modifiers , when , point.h , point.v , uniChars[pos] ) )
2958 {
2959 result = noErr ;
2960 }
2961
2962 wxTheApp->MacSetCurrentEvent( formerEvent , formerHandler ) ;
2963 }
2964 }
2965 break;
2966 default:
2967 break ;
489468fe 2968 }
489468fe 2969
b2680ced
SC
2970 delete [] uniChars ;
2971 if ( charBuf != buf )
2972 delete [] charBuf ;
489468fe 2973
b2680ced 2974 return result ;
489468fe
SC
2975}
2976
b2680ced
SC
2977static pascal OSStatus
2978wxMacWindowCommandEventHandler(EventHandlerCallRef WXUNUSED(handler),
2979 EventRef event,
2980 void *data)
489468fe 2981{
b2680ced
SC
2982 OSStatus result = eventNotHandledErr ;
2983 wxWindowMac* focus = (wxWindowMac*) data ;
489468fe 2984
b2680ced 2985 HICommand command ;
489468fe 2986
b2680ced
SC
2987 wxMacCarbonEvent cEvent( event ) ;
2988 cEvent.GetParameter<HICommand>(kEventParamDirectObject,typeHICommand,&command) ;
489468fe 2989
b2680ced
SC
2990 wxMenuItem* item = NULL ;
2991 wxMenu* itemMenu = wxFindMenuFromMacCommand( command , item ) ;
2992 int id = wxMacCommandToId( command.commandID ) ;
489468fe 2993
b2680ced 2994 if ( item )
489468fe 2995 {
b2680ced 2996 wxASSERT( itemMenu != NULL ) ;
489468fe 2997
b2680ced 2998 switch ( cEvent.GetKind() )
489468fe 2999 {
b2680ced
SC
3000 case kEventProcessCommand :
3001 result = itemMenu->MacHandleCommandProcess( item, id, focus );
3002 break ;
489468fe 3003
b2680ced
SC
3004 case kEventCommandUpdateStatus:
3005 result = itemMenu->MacHandleCommandUpdateStatus( item, id, focus );
3006 break ;
489468fe 3007
b2680ced
SC
3008 default :
3009 break ;
3010 }
489468fe 3011 }
b2680ced 3012 return result ;
489468fe
SC
3013}
3014
b2680ced 3015pascal OSStatus wxMacWindowEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
489468fe 3016{
b2680ced
SC
3017 EventRef formerEvent = (EventRef) wxTheApp->MacGetCurrentEvent() ;
3018 EventHandlerCallRef formerEventHandlerCallRef = (EventHandlerCallRef) wxTheApp->MacGetCurrentEventHandlerCallRef() ;
3019 wxTheApp->MacSetCurrentEvent( event , handler ) ;
3020 OSStatus result = eventNotHandledErr ;
489468fe 3021
b2680ced
SC
3022 switch ( GetEventClass( event ) )
3023 {
3024 case kEventClassCommand :
3025 result = wxMacWindowCommandEventHandler( handler , event , data ) ;
3026 break ;
489468fe 3027
b2680ced
SC
3028 case kEventClassControl :
3029 result = wxMacWindowControlEventHandler( handler, event, data ) ;
3030 break ;
489468fe 3031
b2680ced
SC
3032 case kEventClassService :
3033 result = wxMacWindowServiceEventHandler( handler, event , data ) ;
3034 break ;
489468fe 3035
b2680ced
SC
3036 case kEventClassTextInput :
3037 result = wxMacUnicodeTextEventHandler( handler , event , data ) ;
3038 break ;
489468fe 3039
b2680ced
SC
3040 default :
3041 break ;
3042 }
489468fe 3043
b2680ced 3044 wxTheApp->MacSetCurrentEvent( formerEvent, formerEventHandlerCallRef ) ;
489468fe 3045
b2680ced 3046 return result ;
489468fe
SC
3047}
3048
b2680ced 3049DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacWindowEventHandler )
489468fe 3050
b2680ced
SC
3051// ---------------------------------------------------------------------------
3052// Scrollbar Tracking for all
3053// ---------------------------------------------------------------------------
489468fe 3054
b2680ced
SC
3055pascal void wxMacLiveScrollbarActionProc( ControlRef control , ControlPartCode partCode ) ;
3056pascal void wxMacLiveScrollbarActionProc( ControlRef control , ControlPartCode partCode )
489468fe 3057{
b2680ced 3058 if ( partCode != 0)
489468fe 3059 {
b2680ced
SC
3060 wxWindow* wx = wxFindWindowFromWXWidget( (WXWidget) control ) ;
3061 if ( wx )
3062 wx->MacHandleControlClick( (WXWidget) control , partCode , true /* stillDown */ ) ;
489468fe
SC
3063 }
3064}
b2680ced 3065wxMAC_DEFINE_PROC_GETTER( ControlActionUPP , wxMacLiveScrollbarActionProc ) ;
489468fe 3066
b2680ced
SC
3067wxWidgetImpl* wxWidgetImpl::CreateUserPane( wxWindowMac* wxpeer, const wxPoint& pos, const wxSize& size,
3068 long style, long extraStyle, const wxString& name)
489468fe 3069{
b2680ced
SC
3070 OSStatus err = noErr;
3071 Rect bounds = wxMacGetBoundsForControl( wxpeer , pos , size ) ;
3072 wxMacControl* c = new wxMacControl(wxpeer) ;
3073 UInt32 features = 0
3074 | kControlSupportsEmbedding
3075 | kControlSupportsLiveFeedback
3076 | kControlGetsFocusOnClick
3077// | kControlHasSpecialBackground
3078// | kControlSupportsCalcBestRect
3079 | kControlHandlesTracking
3080 | kControlSupportsFocus
3081 | kControlWantsActivate
3082 | kControlWantsIdle ;
489468fe 3083
b2680ced
SC
3084 err =::CreateUserPaneControl( MAC_WXHWND(wxpeer->GetParent()->MacGetTopLevelWindowRef()) , &bounds, features , c->GetControlRefAddr() );
3085 verify_noerr( err );
3086 return c;
3087}
489468fe 3088
489468fe 3089
b2680ced
SC
3090void wxMacControl::MacInstallEventHandler( ControlRef control, wxWindowMac* wxPeer )
3091{
3092 wxAssociateWindowWithWXWidget( (WXWidget) control , wxPeer ) ;
3093 ::InstallControlEventHandler( control , GetwxMacWindowEventHandlerUPP(),
3094 GetEventTypeCount(eventList), eventList, wxPeer, NULL);
489468fe
SC
3095}
3096
b2680ced
SC
3097IMPLEMENT_DYNAMIC_CLASS( wxMacControl , wxWidgetImpl )
3098
3099wxMacControl::wxMacControl()
489468fe 3100{
b2680ced
SC
3101 Init();
3102}
489468fe 3103
b2680ced
SC
3104wxMacControl::wxMacControl(wxWindowMac* peer , bool isRootControl ) :
3105 wxWidgetImpl( peer, isRootControl )
3106{
3107 Init();
3108}
489468fe 3109
b2680ced
SC
3110wxMacControl::~wxMacControl()
3111{
3112}
489468fe 3113
b2680ced
SC
3114void wxMacControl::Init()
3115{
3116 m_controlRef = NULL;
3117 m_macControlEventHandler = NULL;
3118}
489468fe 3119
b2680ced
SC
3120void wxMacControl::Destroy()
3121{
3122 wxASSERT_MSG( m_controlRef != NULL , wxT("Control Handle already NULL, Dispose called twice ?") );
3123 wxASSERT_MSG( IsValidControlHandle(m_controlRef) , wxT("Invalid Control Handle (maybe already released) in Dispose") );
489468fe 3124
b2680ced
SC
3125 wxRemoveWXWidgetAssociation( m_wxPeer) ;
3126 // we cannot check the ref count here anymore, as autorelease objects might delete their refs later
3127 // we can have situations when being embedded, where the control gets deleted behind our back, so only
3128 // CFRelease if we are safe
3129 if ( IsValidControlHandle(m_controlRef) )
3130 CFRelease(m_controlRef);
3131 m_controlRef = NULL;
3132}
489468fe 3133
b2680ced
SC
3134void wxMacControl::SetReference( URefCon data )
3135{
3136 SetControlReference( m_controlRef , data );
3137}
489468fe 3138
b2680ced
SC
3139void wxMacControl::RemoveFromParent()
3140{
3141 // nothing to do here for carbon
3142}
489468fe 3143
b2680ced
SC
3144void wxMacControl::Embed( wxWidgetImpl *parent )
3145{
3146 // copied from MacPostControlCreate
3147 ControlRef container = (ControlRef) parent->GetWXWidget() ;
3148 wxASSERT_MSG( container != NULL , wxT("No valid mac container control") ) ;
3149 ::EmbedControl( m_controlRef , container ) ;
3150}
489468fe 3151
b2680ced
SC
3152void wxMacControl::SetNeedsDisplay( const wxRect* rect )
3153{
3154 if ( !IsVisible() )
3155 return;
489468fe 3156
b2680ced
SC
3157 if ( rect != NULL )
3158 {
3159 HIRect updatearea = CGRectMake( rect->x , rect->y , rect->width , rect->height);
3160 HIViewSetNeedsDisplayInRect( m_controlRef, &updatearea, true );
3161 }
3162 else
3163 HIViewSetNeedsDisplay( m_controlRef , true );
3164}
489468fe 3165
b2680ced
SC
3166void wxMacControl::Raise()
3167{
3168 verify_noerr( HIViewSetZOrder( m_controlRef, kHIViewZOrderAbove, NULL ) );
3169}
3170
3171void wxMacControl::Lower()
3172{
3173 verify_noerr( HIViewSetZOrder( m_controlRef, kHIViewZOrderBelow, NULL ) );
3174}
489468fe 3175
b2680ced
SC
3176void wxMacControl::GetContentArea(int &left , int &top , int &width , int &height) const
3177{
3178 RgnHandle rgn = NewRgn() ;
3179 Rect content ;
3180 if ( GetControlRegion( m_controlRef, kControlContentMetaPart , rgn ) == noErr )
3181 GetRegionBounds( rgn , &content ) ;
3182 else
3183 GetControlBounds( m_controlRef , &content );
3184 DisposeRgn( rgn ) ;
489468fe 3185
b2680ced
SC
3186 left = content.left;
3187 top = content.top;
489468fe 3188
b2680ced
SC
3189 width = content.right - content.left ;
3190 height = content.bottom - content.top ;
3191}
3192
3193void wxMacControl::Move(int x, int y, int width, int height)
3194{
3195 HIRect hir = CGRectMake(x,y,width,height);
3196 HIViewSetFrame ( m_controlRef , &hir );
489468fe
SC
3197}
3198
b2680ced
SC
3199void wxMacControl::GetPosition( int &x, int &y ) const
3200{
3201 Rect r;
3202 GetControlBounds( m_controlRef , &r );
3203 x = r.left;
3204 y = r.top;
3205}
489468fe 3206
b2680ced 3207void wxMacControl::GetSize( int &width, int &height ) const
489468fe 3208{
b2680ced
SC
3209 Rect r;
3210 GetControlBounds( m_controlRef , &r );
3211 width = r.right - r.left;
3212 height = r.bottom - r.top;
3213}
489468fe 3214
b2680ced
SC
3215void wxMacControl::ScrollRect( const wxRect *rect, int dx, int dy )
3216{
3217 if (GetNeedsDisplay() )
489468fe 3218 {
b2680ced
SC
3219 // because HIViewScrollRect does not scroll the already invalidated area we have two options:
3220 // in case there is already a pending redraw on that area
3221 // either immediate redraw or full invalidate
3222#if 1
3223 // is the better overall solution, as it does not slow down scrolling
3224 SetNeedsDisplay() ;
3225#else
3226 // this would be the preferred version for fast drawing controls
3227 HIViewRender(GetControlRef()) ;
489468fe 3228#endif
489468fe
SC
3229 }
3230
b2680ced
SC
3231 // note there currently is a bug in OSX (10.3 +?) which makes inefficient refreshes in case an entire control
3232 // area is scrolled, this does not occur if width and height are 2 pixels less,
3233 // TODO: write optimal workaround
3234
3235 HIRect scrollarea = CGRectMake( rect->x , rect->y , rect->width , rect->height);
3236 HIViewScrollRect ( m_controlRef , &scrollarea , dx ,dy );
3237
3238#if 0
3239 // this would be the preferred version for fast drawing controls
3240 HIViewRender(GetControlRef()) ;
3241#endif
489468fe
SC
3242}
3243
b2680ced 3244bool wxMacControl::CanFocus() const
489468fe 3245{
b2680ced
SC
3246 // TODO : evaluate performance hits by looking up this value, eventually cache the results for a 1 sec or so
3247 // CAUTION : the value returned currently is 0 or 2, I've also found values of 1 having the same meaning,
3248 // but the value range is nowhere documented
3249 Boolean keyExistsAndHasValidFormat ;
3250 CFIndex fullKeyboardAccess = CFPreferencesGetAppIntegerValue( CFSTR("AppleKeyboardUIMode" ) ,
3251 kCFPreferencesCurrentApplication, &keyExistsAndHasValidFormat );
489468fe 3252
b2680ced 3253 if ( keyExistsAndHasValidFormat && fullKeyboardAccess > 0 )
489468fe 3254 {
b2680ced 3255 return true ;
489468fe
SC
3256 }
3257 else
3258 {
b2680ced
SC
3259 UInt32 features = 0 ;
3260 GetControlFeatures( m_controlRef, &features ) ;
489468fe 3261
b2680ced 3262 return features & ( kControlSupportsFocus | kControlGetsFocusOnClick ) ;
489468fe
SC
3263 }
3264}
3265
b2680ced 3266bool wxMacControl::GetNeedsDisplay() const
489468fe 3267{
b2680ced
SC
3268 return HIViewGetNeedsDisplay( m_controlRef );
3269}
489468fe 3270
b2680ced
SC
3271void wxWidgetImpl::Convert( wxPoint *pt , wxWidgetImpl *from , wxWidgetImpl *to )
3272{
3273 HIPoint hiPoint;
489468fe 3274
b2680ced
SC
3275 hiPoint.x = pt->x;
3276 hiPoint.y = pt->y;
3277 HIViewConvertPoint( &hiPoint , (ControlRef) from->GetWXWidget() , (ControlRef) to->GetWXWidget() );
3278 pt->x = (int)hiPoint.x;
3279 pt->y = (int)hiPoint.y;
3280}
489468fe 3281
b2680ced
SC
3282bool wxMacControl::SetFocus()
3283{
3284 // as we cannot rely on the control features to find out whether we are in full keyboard mode,
3285 // we can only leave in case of an error
489468fe 3286
b2680ced
SC
3287 OSStatus err = SetKeyboardFocus( GetControlOwner( m_controlRef ), m_controlRef, kControlFocusNextPart );
3288 if ( err == errCouldntSetFocus )
3289 return false ;
3290 SetUserFocusWindow(GetControlOwner( m_controlRef ) );
3291
3292 return true;
489468fe
SC
3293}
3294
b2680ced 3295bool wxMacControl::HasFocus() const
489468fe 3296{
b2680ced
SC
3297 ControlRef control;
3298 GetKeyboardFocus( GetUserFocusWindow() , &control );
3299 return control == m_controlRef;
3300}
489468fe 3301
b2680ced
SC
3302//
3303// subclass specifics
3304//
3305
3306OSStatus wxMacControl::GetData(ControlPartCode inPartCode , ResType inTag , Size inBufferSize , void * inOutBuffer , Size * outActualSize ) const
3307{
3308 return ::GetControlData( m_controlRef , inPartCode , inTag , inBufferSize , inOutBuffer , outActualSize );
489468fe
SC
3309}
3310
b2680ced 3311OSStatus wxMacControl::GetDataSize(ControlPartCode inPartCode , ResType inTag , Size * outActualSize ) const
489468fe 3312{
b2680ced
SC
3313 return ::GetControlDataSize( m_controlRef , inPartCode , inTag , outActualSize );
3314}
489468fe 3315
b2680ced
SC
3316OSStatus wxMacControl::SetData(ControlPartCode inPartCode , ResType inTag , Size inSize , const void * inData)
3317{
3318 return ::SetControlData( m_controlRef , inPartCode , inTag , inSize , inData );
3319}
489468fe 3320
b2680ced
SC
3321OSStatus wxMacControl::SendEvent( EventRef event , OptionBits inOptions )
3322{
3323 return SendEventToEventTargetWithOptions( event,
3324 HIObjectGetEventTarget( (HIObjectRef) m_controlRef ), inOptions );
3325}
489468fe 3326
b2680ced
SC
3327OSStatus wxMacControl::SendHICommand( HICommand &command , OptionBits inOptions )
3328{
3329 wxMacCarbonEvent event( kEventClassCommand , kEventCommandProcess );
489468fe 3330
b2680ced 3331 event.SetParameter<HICommand>(kEventParamDirectObject,command);
489468fe 3332
b2680ced
SC
3333 return SendEvent( event , inOptions );
3334}
489468fe 3335
b2680ced
SC
3336OSStatus wxMacControl::SendHICommand( UInt32 commandID , OptionBits inOptions )
3337{
3338 HICommand command;
489468fe 3339
b2680ced
SC
3340 memset( &command, 0 , sizeof(command) );
3341 command.commandID = commandID;
3342 return SendHICommand( command , inOptions );
3343}
489468fe 3344
b2680ced
SC
3345void wxMacControl::Flash( ControlPartCode part , UInt32 ticks )
3346{
3347 unsigned long finalTicks;
489468fe 3348
b2680ced
SC
3349 HiliteControl( m_controlRef , part );
3350 Delay( ticks , &finalTicks );
3351 HiliteControl( m_controlRef , kControlNoPart );
3352}
489468fe 3353
b2680ced
SC
3354SInt32 wxMacControl::GetValue() const
3355{
3356 return ::GetControl32BitValue( m_controlRef );
3357}
489468fe 3358
b2680ced
SC
3359SInt32 wxMacControl::GetMaximum() const
3360{
3361 return ::GetControl32BitMaximum( m_controlRef );
3362}
489468fe 3363
b2680ced
SC
3364SInt32 wxMacControl::GetMinimum() const
3365{
3366 return ::GetControl32BitMinimum( m_controlRef );
489468fe
SC
3367}
3368
b2680ced 3369void wxMacControl::SetValue( SInt32 v )
489468fe 3370{
b2680ced 3371 ::SetControl32BitValue( m_controlRef , v );
489468fe
SC
3372}
3373
b2680ced 3374void wxMacControl::SetMinimum( SInt32 v )
489468fe 3375{
b2680ced
SC
3376 ::SetControl32BitMinimum( m_controlRef , v );
3377}
489468fe 3378
b2680ced
SC
3379void wxMacControl::SetMaximum( SInt32 v )
3380{
3381 ::SetControl32BitMaximum( m_controlRef , v );
3382}
489468fe 3383
b2680ced
SC
3384void wxMacControl::SetValueAndRange( SInt32 value , SInt32 minimum , SInt32 maximum )
3385{
3386 ::SetControl32BitMinimum( m_controlRef , minimum );
3387 ::SetControl32BitMaximum( m_controlRef , maximum );
3388 ::SetControl32BitValue( m_controlRef , value );
3389}
489468fe 3390
b2680ced
SC
3391void wxMacControl::VisibilityChanged(bool WXUNUSED(shown))
3392{
489468fe
SC
3393}
3394
b2680ced 3395void wxMacControl::SuperChangedPosition()
489468fe 3396{
b2680ced 3397}
489468fe 3398
b2680ced
SC
3399void wxMacControl::SetFont( const wxFont & font , const wxColour& foreground , long windowStyle )
3400{
3401 m_font = font;
3402#if wxMAC_USE_CORE_TEXT
3403 if ( UMAGetSystemVersion() >= 0x1050 )
489468fe 3404 {
b2680ced
SC
3405 HIViewPartCode part = 0;
3406 HIThemeTextHorizontalFlush flush = kHIThemeTextHorizontalFlushDefault;
3407 if ( ( windowStyle & wxALIGN_MASK ) & wxALIGN_CENTER_HORIZONTAL )
3408 flush = kHIThemeTextHorizontalFlushCenter;
3409 else if ( ( windowStyle & wxALIGN_MASK ) & wxALIGN_RIGHT )
3410 flush = kHIThemeTextHorizontalFlushRight;
3411 HIViewSetTextFont( m_controlRef , part , (CTFontRef) font.MacGetCTFont() );
3412 HIViewSetTextHorizontalFlush( m_controlRef, part, flush );
489468fe 3413
b2680ced
SC
3414 if ( foreground != *wxBLACK )
3415 {
3416 ControlFontStyleRec fontStyle;
3417 foreground.GetRGBColor( &fontStyle.foreColor );
3418 fontStyle.flags = kControlUseForeColorMask;
3419 ::SetControlFontStyle( m_controlRef , &fontStyle );
3420 }
489468fe 3421 }
b2680ced
SC
3422#endif
3423#if wxMAC_USE_ATSU_TEXT
3424 ControlFontStyleRec fontStyle;
3425 if ( font.MacGetThemeFontID() != kThemeCurrentPortFont )
3426 {
3427 switch ( font.MacGetThemeFontID() )
3428 {
3429 case kThemeSmallSystemFont :
3430 fontStyle.font = kControlFontSmallSystemFont;
3431 break;
489468fe 3432
b2680ced
SC
3433 case 109 : // mini font
3434 fontStyle.font = -5;
3435 break;
489468fe 3436
b2680ced
SC
3437 case kThemeSystemFont :
3438 fontStyle.font = kControlFontBigSystemFont;
3439 break;
489468fe 3440
b2680ced
SC
3441 default :
3442 fontStyle.font = kControlFontBigSystemFont;
3443 break;
3444 }
3445
3446 fontStyle.flags = kControlUseFontMask;
3447 }
3448 else
489468fe 3449 {
b2680ced
SC
3450 fontStyle.font = font.MacGetFontNum();
3451 fontStyle.style = font.MacGetFontStyle();
3452 fontStyle.size = font.MacGetFontSize();
3453 fontStyle.flags = kControlUseFontMask | kControlUseFaceMask | kControlUseSizeMask;
489468fe 3454 }
b2680ced
SC
3455
3456 fontStyle.just = teJustLeft;
3457 fontStyle.flags |= kControlUseJustMask;
3458 if ( ( windowStyle & wxALIGN_MASK ) & wxALIGN_CENTER_HORIZONTAL )
3459 fontStyle.just = teJustCenter;
3460 else if ( ( windowStyle & wxALIGN_MASK ) & wxALIGN_RIGHT )
3461 fontStyle.just = teJustRight;
3462
3463
3464 // we only should do this in case of a non-standard color, as otherwise 'disabled' controls
3465 // won't get grayed out by the system anymore
3466
3467 if ( foreground != *wxBLACK )
489468fe 3468 {
b2680ced
SC
3469 foreground.GetRGBColor( &fontStyle.foreColor );
3470 fontStyle.flags |= kControlUseForeColorMask;
489468fe
SC
3471 }
3472
b2680ced
SC
3473 ::SetControlFontStyle( m_controlRef , &fontStyle );
3474#endif
489468fe
SC
3475}
3476
b2680ced 3477void wxMacControl::SetBackgroundColour( const wxColour &WXUNUSED(col) )
489468fe 3478{
b2680ced 3479// HITextViewSetBackgroundColor( m_textView , color );
489468fe
SC
3480}
3481
b2680ced 3482void wxMacControl::SetRange( SInt32 minimum , SInt32 maximum )
489468fe 3483{
b2680ced
SC
3484 ::SetControl32BitMinimum( m_controlRef , minimum );
3485 ::SetControl32BitMaximum( m_controlRef , maximum );
489468fe
SC
3486}
3487
b2680ced 3488short wxMacControl::HandleKey( SInt16 keyCode, SInt16 charCode, EventModifiers modifiers )
489468fe 3489{
b2680ced 3490 return HandleControlKey( m_controlRef , keyCode , charCode , modifiers );
489468fe
SC
3491}
3492
b2680ced 3493void wxMacControl::SetActionProc( ControlActionUPP actionProc )
489468fe 3494{
b2680ced 3495 SetControlAction( m_controlRef , actionProc );
489468fe
SC
3496}
3497
b2680ced 3498void wxMacControl::SetViewSize( SInt32 viewSize )
489468fe 3499{
b2680ced
SC
3500 SetControlViewSize(m_controlRef , viewSize );
3501}
489468fe 3502
b2680ced
SC
3503SInt32 wxMacControl::GetViewSize() const
3504{
3505 return GetControlViewSize( m_controlRef );
489468fe
SC
3506}
3507
b2680ced 3508bool wxMacControl::IsVisible() const
489468fe 3509{
b2680ced
SC
3510 return IsControlVisible( m_controlRef );
3511}
489468fe 3512
b2680ced
SC
3513void wxMacControl::SetVisibility( bool visible )
3514{
3515 SetControlVisibility( m_controlRef , visible, true );
3516}
489468fe 3517
b2680ced
SC
3518bool wxMacControl::IsEnabled() const
3519{
3520 return IsControlEnabled( m_controlRef );
489468fe
SC
3521}
3522
b2680ced 3523bool wxMacControl::IsActive() const
489468fe 3524{
b2680ced
SC
3525 return IsControlActive( m_controlRef );
3526}
489468fe 3527
b2680ced
SC
3528void wxMacControl::Enable( bool enable )
3529{
3530 if ( enable )
3531 EnableControl( m_controlRef );
489468fe 3532 else
b2680ced 3533 DisableControl( m_controlRef );
489468fe
SC
3534}
3535
b2680ced 3536void wxMacControl::SetDrawingEnabled( bool enable )
489468fe 3537{
b2680ced
SC
3538 HIViewSetDrawingEnabled( m_controlRef , enable );
3539}
3540
3541void wxMacControl::GetRectInWindowCoords( Rect *r )
3542{
3543 GetControlBounds( m_controlRef , r ) ;
3544
3545 WindowRef tlwref = GetControlOwner( m_controlRef ) ;
3546
3547 wxNonOwnedWindow* tlwwx = wxNonOwnedWindow::GetFromWXWindow( (WXWindow) tlwref ) ;
3548 if ( tlwwx != NULL )
489468fe 3549 {
b2680ced
SC
3550 ControlRef rootControl = tlwwx->GetPeer()->GetControlRef() ;
3551 HIPoint hiPoint = CGPointMake( 0 , 0 ) ;
3552 HIViewConvertPoint( &hiPoint , HIViewGetSuperview(m_controlRef) , rootControl ) ;
3553 OffsetRect( r , (short) hiPoint.x , (short) hiPoint.y ) ;
489468fe
SC
3554 }
3555}
3556
b2680ced 3557void wxMacControl::GetBestRect( Rect *r )
489468fe 3558{
b2680ced
SC
3559 short baselineoffset;
3560
3561 GetBestControlRect( m_controlRef , r , &baselineoffset );
489468fe
SC
3562}
3563
b2680ced 3564void wxMacControl::SetLabel( const wxString &title )
489468fe 3565{
b2680ced 3566 wxFontEncoding encoding;
489468fe 3567
b2680ced
SC
3568 if ( m_font.Ok() )
3569 encoding = m_font.GetEncoding();
3570 else
3571 encoding = wxFont::GetDefaultEncoding();
489468fe 3572
b2680ced 3573 SetControlTitleWithCFString( m_controlRef , wxCFStringRef( title , encoding ) );
489468fe
SC
3574}
3575
b2680ced 3576void wxMacControl::GetFeatures( UInt32 * features )
489468fe 3577{
b2680ced 3578 GetControlFeatures( m_controlRef , features );
489468fe
SC
3579}
3580
b2680ced 3581OSStatus wxMacControl::GetRegion( ControlPartCode partCode , RgnHandle region )
489468fe 3582{
b2680ced
SC
3583 OSStatus err = GetControlRegion( m_controlRef , partCode , region );
3584 return err;
3585}
489468fe 3586
b2680ced
SC
3587// SetNeedsDisplay would not invalidate the children
3588static void InvalidateControlAndChildren( HIViewRef control )
3589{
3590 HIViewSetNeedsDisplay( control , true );
3591 UInt16 childrenCount = 0;
3592 OSStatus err = CountSubControls( control , &childrenCount );
3593 if ( err == errControlIsNotEmbedder )
3594 return;
489468fe 3595
b2680ced 3596 wxASSERT_MSG( err == noErr , wxT("Unexpected error when accessing subcontrols") );
489468fe 3597
b2680ced
SC
3598 for ( UInt16 i = childrenCount; i >=1; --i )
3599 {
3600 HIViewRef child;
489468fe 3601
b2680ced
SC
3602 err = GetIndexedSubControl( control , i , & child );
3603 if ( err == errControlIsNotEmbedder )
3604 return;
3605
3606 InvalidateControlAndChildren( child );
3607 }
489468fe
SC
3608}
3609
b2680ced 3610void wxMacControl::InvalidateWithChildren()
489468fe 3611{
b2680ced
SC
3612 InvalidateControlAndChildren( m_controlRef );
3613}
489468fe 3614
b2680ced
SC
3615OSType wxMacCreator = 'WXMC';
3616OSType wxMacControlProperty = 'MCCT';
3617
3618void wxMacControl::SetReferenceInNativeControl()
3619{
3620 void * data = this;
3621 verify_noerr( SetControlProperty ( m_controlRef ,
3622 wxMacCreator,wxMacControlProperty, sizeof(data), &data ) );
3623}
3624
3625wxMacControl* wxMacControl::GetReferenceFromNativeControl(ControlRef control)
3626{
3627 wxMacControl* ctl = NULL;
3628 ByteCount actualSize;
3629 if ( GetControlProperty( control ,wxMacCreator,wxMacControlProperty, sizeof(ctl) ,
3630 &actualSize , &ctl ) == noErr )
489468fe 3631 {
b2680ced 3632 return ctl;
489468fe 3633 }
b2680ced 3634 return NULL;
489468fe
SC
3635}
3636
3637
b2680ced
SC
3638//
3639// Tab Control
3640//
489468fe 3641
b2680ced 3642OSStatus wxMacControl::SetTabEnabled( SInt16 tabNo , bool enable )
489468fe 3643{
b2680ced 3644 return ::SetTabEnabled( m_controlRef , tabNo , enable );
489468fe
SC
3645}
3646
b2680ced
SC
3647
3648
3649// Control Factory
3650
3651wxWidgetImpl* wxWidgetImpl::CreateContentView( wxNonOwnedWindow* now )
489468fe 3652{
b2680ced
SC
3653 // There is a bug in 10.2.X for ::GetRootControl returning the window view instead of
3654 // the content view, so we have to retrieve it explicitly
3655
3656 wxMacControl* contentview = new wxMacControl(now , true /*isRootControl*/);
3657 HIViewFindByID( HIViewGetRoot( (WindowRef) now->GetWXWindow() ) , kHIViewWindowContentID ,
3658 contentview->GetControlRefAddr() ) ;
3659 if ( !contentview->IsOk() )
489468fe 3660 {
b2680ced
SC
3661 // compatibility mode fallback
3662 GetRootControl( (WindowRef) now->GetWXWindow() , contentview->GetControlRefAddr() ) ;
489468fe 3663 }
489468fe 3664
b2680ced
SC
3665 // the root control level handler
3666 contentview->InstallEventHandler() ;
3667 return contentview;
489468fe 3668}
b2680ced
SC
3669
3670#endif // wxOSX_USE_CARBON