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