moving focus rect overlap problems to the vis region of a window
[wxWidgets.git] / src / mac / carbon / window.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: windows.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 #ifdef __GNUG__
13 #pragma implementation "window.h"
14 #endif
15
16 #include "wx/setup.h"
17 #include "wx/menu.h"
18 #include "wx/window.h"
19 #include "wx/dc.h"
20 #include "wx/dcclient.h"
21 #include "wx/utils.h"
22 #include "wx/app.h"
23 #include "wx/panel.h"
24 #include "wx/layout.h"
25 #include "wx/dialog.h"
26 #include "wx/scrolbar.h"
27 #include "wx/statbox.h"
28 #include "wx/button.h"
29 #include "wx/settings.h"
30 #include "wx/msgdlg.h"
31 #include "wx/frame.h"
32 #include "wx/tooltip.h"
33 #include "wx/statusbr.h"
34 #include "wx/menuitem.h"
35 #include "wx/spinctrl.h"
36 #include "wx/log.h"
37 #include "wx/geometry.h"
38 #include "wx/textctrl.h"
39 #include "wx/laywin.h"
40 #include "wx/splitter.h"
41
42 #include "wx/toolbar.h"
43 #include "wx/dc.h"
44
45 #if wxUSE_CARET
46 #include "wx/caret.h"
47 #endif // wxUSE_CARET
48
49 #define wxWINDOW_HSCROLL 5998
50 #define wxWINDOW_VSCROLL 5997
51
52 #define MAC_SCROLLBAR_SIZE 15
53 #define MAC_SMALL_SCROLLBAR_SIZE 11
54
55 #include "wx/mac/uma.h"
56 #ifndef __DARWIN__
57 #include <Windows.h>
58 #include <ToolUtils.h>
59 #include <Scrap.h>
60 #include <MacTextEditor.h>
61 #endif
62
63 #if TARGET_API_MAC_OSX
64 #ifndef __HIVIEW__
65 #include <HIToolbox/HIView.h>
66 #endif
67 #endif
68
69 #if wxUSE_DRAG_AND_DROP
70 #include "wx/dnd.h"
71 #endif
72
73 #include <string.h>
74
75 extern wxList wxPendingDelete;
76
77 #ifdef __WXUNIVERSAL__
78 IMPLEMENT_ABSTRACT_CLASS(wxWindowMac, wxWindowBase)
79 #else // __WXMAC__
80 IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowBase)
81 #endif // __WXUNIVERSAL__/__WXMAC__
82
83 #if !USE_SHARED_LIBRARY
84
85 BEGIN_EVENT_TABLE(wxWindowMac, wxWindowBase)
86 EVT_NC_PAINT(wxWindowMac::OnNcPaint)
87 EVT_ERASE_BACKGROUND(wxWindowMac::OnEraseBackground)
88 // TODO EVT_PAINT(wxWindowMac::OnPaint)
89 EVT_SET_FOCUS(wxWindowMac::OnSetFocus)
90 EVT_KILL_FOCUS(wxWindowMac::OnSetFocus)
91 EVT_MOUSE_EVENTS(wxWindowMac::OnMouseEvent)
92 END_EVENT_TABLE()
93
94 #endif
95
96 #define wxMAC_DEBUG_REDRAW 0
97 #ifndef wxMAC_DEBUG_REDRAW
98 #define wxMAC_DEBUG_REDRAW 0
99 #endif
100
101 #define wxMAC_USE_THEME_BORDER 1
102
103 // ---------------------------------------------------------------------------
104 // Utility Routines to move between different coordinate systems
105 // ---------------------------------------------------------------------------
106
107 /*
108 * Right now we have the following setup :
109 * a border that is not part of the native control is always outside the
110 * control's border (otherwise we loose all native intelligence, future ways
111 * may be to have a second embedding control responsible for drawing borders
112 * and backgrounds eventually)
113 * so all this border calculations have to be taken into account when calling
114 * native methods or getting native oriented data
115 * so we have three coordinate systems here
116 * wx client coordinates
117 * wx window coordinates (including window frames)
118 * native coordinates
119 */
120
121 //
122 // originating from native control
123 //
124
125
126 void wxMacNativeToWindow( const wxWindow* window , RgnHandle handle )
127 {
128 OffsetRgn( handle , window->MacGetLeftBorderSize() , window->MacGetTopBorderSize() ) ;
129 }
130
131 void wxMacNativeToWindow( const wxWindow* window , Rect *rect )
132 {
133 OffsetRect( rect , window->MacGetLeftBorderSize() , window->MacGetTopBorderSize() ) ;
134 }
135
136 //
137 // directed towards native control
138 //
139
140 void wxMacWindowToNative( const wxWindow* window , RgnHandle handle )
141 {
142 OffsetRgn( handle , -window->MacGetLeftBorderSize() , -window->MacGetTopBorderSize() );
143 }
144
145 void wxMacWindowToNative( const wxWindow* window , Rect *rect )
146 {
147 OffsetRect( rect , -window->MacGetLeftBorderSize() , -window->MacGetTopBorderSize() ) ;
148 }
149
150
151 // ---------------------------------------------------------------------------
152 // Carbon Events
153 // ---------------------------------------------------------------------------
154
155 extern long wxMacTranslateKey(unsigned char key, unsigned char code) ;
156 pascal OSStatus wxMacSetupControlBackground( ControlRef iControl , SInt16 iMessage , SInt16 iDepth , Boolean iIsColor ) ;
157
158 #if TARGET_API_MAC_OSX
159
160 #if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_3
161 enum {
162 kEventControlVisibilityChanged = 157
163 };
164 #endif
165
166 #endif
167
168 static const EventTypeSpec eventList[] =
169 {
170 { kEventClassControl , kEventControlHit } ,
171 #if TARGET_API_MAC_OSX
172 { kEventClassControl , kEventControlDraw } ,
173 { kEventClassControl , kEventControlVisibilityChanged } ,
174 { kEventClassControl , kEventControlEnabledStateChanged } ,
175 { kEventClassControl , kEventControlHiliteChanged } ,
176 { kEventClassControl , kEventControlSetFocusPart } ,
177
178 { kEventClassService , kEventServiceGetTypes },
179 { kEventClassService , kEventServiceCopy },
180 { kEventClassService , kEventServicePaste },
181
182 // { kEventClassControl , kEventControlInvalidateForSizeChange } , // 10.3 only
183 // { kEventClassControl , kEventControlBoundsChanged } ,
184 #endif
185 } ;
186
187 static pascal OSStatus wxMacWindowControlEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
188 {
189 OSStatus result = eventNotHandledErr ;
190
191 wxMacCarbonEvent cEvent( event ) ;
192
193 ControlRef controlRef ;
194 wxWindowMac* thisWindow = (wxWindowMac*) data ;
195
196 cEvent.GetParameter( kEventParamDirectObject , &controlRef ) ;
197
198 switch( GetEventKind( event ) )
199 {
200 #if TARGET_API_MAC_OSX
201 case kEventControlDraw :
202 {
203 RgnHandle updateRgn = NULL ;
204 RgnHandle allocatedRgn = NULL ;
205 wxRegion visRegion = thisWindow->MacGetVisibleRegion() ;
206 if ( cEvent.GetParameter<RgnHandle>(kEventParamRgnHandle, &updateRgn) != noErr )
207 {
208 updateRgn = (RgnHandle) visRegion.GetWXHRGN() ;
209 }
210 else
211 {
212 if ( thisWindow->MacGetLeftBorderSize() != 0 || thisWindow->MacGetTopBorderSize() != 0 )
213 {
214 allocatedRgn = NewRgn() ;
215 CopyRgn( updateRgn , allocatedRgn ) ;
216 // hide the given region by the new region that must be shifted
217 wxMacNativeToWindow( thisWindow , allocatedRgn ) ;
218 updateRgn = allocatedRgn ;
219 }
220 }
221
222 #if 0
223 // in case we would need a coregraphics compliant background erase first
224 // now usable to track redraws
225 CGContextRef cgContext = cEvent.GetParameter<CGContextRef>(kEventParamCGContextRef) ;
226 if ( thisWindow->MacIsUserPane() )
227 {
228 static float color = 0.5 ;
229 static channel = 0 ;
230 HIRect bounds;
231 HIViewGetBounds( controlRef, &bounds );
232 CGContextSetRGBFillColor( cgContext, channel == 0 ? color : 0.5 ,
233 channel == 1 ? color : 0.5 , channel == 2 ? color : 0.5 , 1 );
234 CGContextFillRect( cgContext, bounds );
235 color += 0.1 ;
236 if ( color > 0.9 )
237 {
238 color = 0.5 ;
239 channel++ ;
240 if ( channel == 3 )
241 channel = 0 ;
242 }
243 }
244 #endif
245 if ( thisWindow->MacDoRedraw( updateRgn , cEvent.GetTicks() ) )
246 result = noErr ;
247 if ( allocatedRgn )
248 DisposeRgn( allocatedRgn ) ;
249 }
250 break ;
251 case kEventControlVisibilityChanged :
252 thisWindow->MacVisibilityChanged() ;
253 break ;
254 case kEventControlEnabledStateChanged :
255 thisWindow->MacEnabledStateChanged() ;
256 break ;
257 case kEventControlHiliteChanged :
258 thisWindow->MacHiliteChanged() ;
259 break ;
260 case kEventControlSetFocusPart :
261 {
262 Boolean focusEverything = false ;
263 ControlPartCode controlPart = cEvent.GetParameter<ControlPartCode>(kEventParamControlPart , typeControlPartCode );
264 if ( cEvent.GetParameter<Boolean>(kEventParamControlFocusEverything , &focusEverything ) == noErr )
265 {
266 }
267 if ( controlPart == kControlFocusNoPart )
268 {
269 #if wxUSE_CARET
270 if ( thisWindow->GetCaret() )
271 {
272 thisWindow->GetCaret()->OnKillFocus();
273 }
274 #endif // wxUSE_CARET
275 wxFocusEvent event( wxEVT_KILL_FOCUS, thisWindow->GetId());
276 event.SetEventObject(thisWindow);
277 thisWindow->GetEventHandler()->ProcessEvent(event) ;
278 }
279 else
280 {
281 // panel wants to track the window which was the last to have focus in it
282 wxChildFocusEvent eventFocus(thisWindow);
283 thisWindow->GetEventHandler()->ProcessEvent(eventFocus);
284
285 #if wxUSE_CARET
286 if ( thisWindow->GetCaret() )
287 {
288 thisWindow->GetCaret()->OnSetFocus();
289 }
290 #endif // wxUSE_CARET
291
292 wxFocusEvent event(wxEVT_SET_FOCUS, thisWindow->GetId());
293 event.SetEventObject(thisWindow);
294 thisWindow->GetEventHandler()->ProcessEvent(event) ;
295 }
296 if ( thisWindow->MacIsUserPane() )
297 result = noErr ;
298 }
299 break ;
300 #endif
301 case kEventControlHit :
302 {
303 result = thisWindow->MacControlHit( handler , event ) ;
304 }
305 break ;
306 default :
307 break ;
308 }
309 return result ;
310 }
311
312 static pascal OSStatus wxMacWindowServiceEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
313 {
314 OSStatus result = eventNotHandledErr ;
315
316 wxMacCarbonEvent cEvent( event ) ;
317
318 ControlRef controlRef ;
319 wxWindowMac* thisWindow = (wxWindowMac*) data ;
320 wxTextCtrl* textCtrl = wxDynamicCast( thisWindow , wxTextCtrl ) ;
321 cEvent.GetParameter( kEventParamDirectObject , &controlRef ) ;
322
323 switch( GetEventKind( event ) )
324 {
325 case kEventServiceGetTypes :
326 if( textCtrl )
327 {
328 long from, to ;
329 textCtrl->GetSelection( &from , &to ) ;
330
331 CFMutableArrayRef copyTypes = 0 , pasteTypes = 0;
332 if( from != to )
333 copyTypes = cEvent.GetParameter< CFMutableArrayRef >( kEventParamServiceCopyTypes , typeCFMutableArrayRef ) ;
334 if ( textCtrl->IsEditable() )
335 pasteTypes = cEvent.GetParameter< CFMutableArrayRef >( kEventParamServicePasteTypes , typeCFMutableArrayRef ) ;
336
337 static const OSType textDataTypes[] = { kTXNTextData /* , 'utxt' , 'PICT', 'MooV', 'AIFF' */ };
338 for ( size_t i = 0 ; i < WXSIZEOF(textDataTypes) ; ++i )
339 {
340 CFStringRef typestring = CreateTypeStringWithOSType(textDataTypes[i]);
341 if ( typestring )
342 {
343 if ( copyTypes )
344 CFArrayAppendValue (copyTypes, typestring) ;
345 if ( pasteTypes )
346 CFArrayAppendValue (pasteTypes, typestring) ;
347 CFRelease( typestring ) ;
348 }
349 }
350 result = noErr ;
351 }
352 break ;
353 case kEventServiceCopy :
354 if ( textCtrl )
355 {
356 long from, to ;
357 textCtrl->GetSelection( &from , &to ) ;
358 wxString val = textCtrl->GetValue() ;
359 val = val.Mid( from , to - from ) ;
360 ScrapRef scrapRef = cEvent.GetParameter< ScrapRef > ( kEventParamScrapRef , typeScrapRef ) ;
361 verify_noerr( ClearScrap( &scrapRef ) ) ;
362 verify_noerr( PutScrapFlavor( scrapRef , kTXNTextData , 0 , val.Length() , val.c_str() ) ) ;
363 result = noErr ;
364 }
365 break ;
366 case kEventServicePaste :
367 if ( textCtrl )
368 {
369 ScrapRef scrapRef = cEvent.GetParameter< ScrapRef > ( kEventParamScrapRef , typeScrapRef ) ;
370 Size textSize, pastedSize ;
371 verify_noerr( GetScrapFlavorSize (scrapRef, kTXNTextData, &textSize) ) ;
372 textSize++ ;
373 char *content = new char[textSize] ;
374 GetScrapFlavorData (scrapRef, kTXNTextData, &pastedSize, content );
375 content[textSize-1] = 0 ;
376 #if wxUSE_UNICODE
377 textCtrl->WriteText( wxString( content , wxConvLocal ) );
378 #else
379 textCtrl->WriteText( wxString( content ) ) ;
380 #endif
381 delete[] content ;
382 result = noErr ;
383 }
384 break ;
385 }
386
387 return result ;
388 }
389
390 pascal OSStatus wxMacWindowEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
391 {
392 EventRef formerEvent = (EventRef) wxTheApp->MacGetCurrentEvent() ;
393 EventHandlerCallRef formerEventHandlerCallRef = (EventHandlerCallRef) wxTheApp->MacGetCurrentEventHandlerCallRef() ;
394 wxTheApp->MacSetCurrentEvent( event , handler ) ;
395 OSStatus result = eventNotHandledErr ;
396
397 switch ( GetEventClass( event ) )
398 {
399 case kEventClassControl :
400 result = wxMacWindowControlEventHandler( handler, event, data ) ;
401 break ;
402 case kEventClassService :
403 result = wxMacWindowServiceEventHandler( handler, event , data ) ;
404 default :
405 break ;
406 }
407 wxTheApp->MacSetCurrentEvent( formerEvent, formerEventHandlerCallRef ) ;
408 return result ;
409 }
410
411 DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacWindowEventHandler )
412
413 // ---------------------------------------------------------------------------
414 // UserPane events for non OSX builds
415 // ---------------------------------------------------------------------------
416
417 static pascal void wxMacControlUserPaneDrawProc(ControlRef control, SInt16 part)
418 {
419 wxWindow * win = wxFindControlFromMacControl(control) ;
420 wxCHECK_RET( win , wxT("Callback from unkown control") ) ;
421 win->MacControlUserPaneDrawProc(part) ;
422 }
423
424 static pascal ControlPartCode wxMacControlUserPaneHitTestProc(ControlRef control, Point where)
425 {
426 wxWindow * win = wxFindControlFromMacControl(control) ;
427 wxCHECK_MSG( win , kControlNoPart , wxT("Callback from unkown control") ) ;
428 return win->MacControlUserPaneHitTestProc(where.h , where.v) ;
429 }
430
431 static pascal ControlPartCode wxMacControlUserPaneTrackingProc(ControlRef control, Point startPt, ControlActionUPP actionProc)
432 {
433 wxWindow * win = wxFindControlFromMacControl(control) ;
434 wxCHECK_MSG( win , kControlNoPart , wxT("Callback from unkown control") ) ;
435 return win->MacControlUserPaneTrackingProc( startPt.h , startPt.v , (void*) actionProc) ;
436 }
437
438 static pascal void wxMacControlUserPaneIdleProc(ControlRef control)
439 {
440 wxWindow * win = wxFindControlFromMacControl(control) ;
441 wxCHECK_RET( win , wxT("Callback from unkown control") ) ;
442 win->MacControlUserPaneIdleProc() ;
443 }
444
445 static pascal ControlPartCode wxMacControlUserPaneKeyDownProc(ControlRef control, SInt16 keyCode, SInt16 charCode, SInt16 modifiers)
446 {
447 wxWindow * win = wxFindControlFromMacControl(control) ;
448 wxCHECK_MSG( win , kControlNoPart , wxT("Callback from unkown control") ) ;
449 return win->MacControlUserPaneKeyDownProc(keyCode,charCode,modifiers) ;
450 }
451
452 static pascal void wxMacControlUserPaneActivateProc(ControlRef control, Boolean activating)
453 {
454 wxWindow * win = wxFindControlFromMacControl(control) ;
455 wxCHECK_RET( win , wxT("Callback from unkown control") ) ;
456 win->MacControlUserPaneActivateProc(activating) ;
457 }
458
459 static pascal ControlPartCode wxMacControlUserPaneFocusProc(ControlRef control, ControlFocusPart action)
460 {
461 wxWindow * win = wxFindControlFromMacControl(control) ;
462 wxCHECK_MSG( win , kControlNoPart , wxT("Callback from unkown control") ) ;
463 return win->MacControlUserPaneFocusProc(action) ;
464 }
465
466 static pascal void wxMacControlUserPaneBackgroundProc(ControlRef control, ControlBackgroundPtr info)
467 {
468 wxWindow * win = wxFindControlFromMacControl(control) ;
469 wxCHECK_RET( win , wxT("Callback from unkown control") ) ;
470 win->MacControlUserPaneBackgroundProc(info) ;
471 }
472
473 void wxWindowMac::MacControlUserPaneDrawProc(wxInt16 part)
474 {
475 RgnHandle rgn = NewRgn() ;
476 GetClip( rgn ) ;
477 wxMacWindowStateSaver sv( this ) ;
478 SectRgn( rgn , (RgnHandle) MacGetVisibleRegion().GetWXHRGN() , rgn ) ;
479 MacDoRedraw( rgn , 0 ) ;
480 DisposeRgn( rgn ) ;
481 }
482
483 wxInt16 wxWindowMac::MacControlUserPaneHitTestProc(wxInt16 x, wxInt16 y)
484 {
485 return kControlNoPart ;
486 }
487
488 wxInt16 wxWindowMac::MacControlUserPaneTrackingProc(wxInt16 x, wxInt16 y, void* actionProc)
489 {
490 return kControlNoPart ;
491 }
492
493 void wxWindowMac::MacControlUserPaneIdleProc()
494 {
495 }
496
497 wxInt16 wxWindowMac::MacControlUserPaneKeyDownProc(wxInt16 keyCode, wxInt16 charCode, wxInt16 modifiers)
498 {
499 return kControlNoPart ;
500 }
501
502 void wxWindowMac::MacControlUserPaneActivateProc(bool activating)
503 {
504 }
505
506 wxInt16 wxWindowMac::MacControlUserPaneFocusProc(wxInt16 action)
507 {
508 return kControlNoPart ;
509 }
510
511 void wxWindowMac::MacControlUserPaneBackgroundProc(void* info)
512 {
513 }
514
515 ControlUserPaneDrawUPP gControlUserPaneDrawUPP = NULL ;
516 ControlUserPaneHitTestUPP gControlUserPaneHitTestUPP = NULL ;
517 ControlUserPaneTrackingUPP gControlUserPaneTrackingUPP = NULL ;
518 ControlUserPaneIdleUPP gControlUserPaneIdleUPP = NULL ;
519 ControlUserPaneKeyDownUPP gControlUserPaneKeyDownUPP = NULL ;
520 ControlUserPaneActivateUPP gControlUserPaneActivateUPP = NULL ;
521 ControlUserPaneFocusUPP gControlUserPaneFocusUPP = NULL ;
522 ControlUserPaneBackgroundUPP gControlUserPaneBackgroundUPP = NULL ;
523
524 // ===========================================================================
525 // implementation
526 // ===========================================================================
527
528 wxList wxWinMacControlList(wxKEY_INTEGER);
529
530 wxWindow *wxFindControlFromMacControl(ControlRef inControl )
531 {
532 wxNode *node = wxWinMacControlList.Find((long)inControl);
533 if (!node)
534 return NULL;
535 return (wxControl *)node->GetData();
536 }
537
538 void wxAssociateControlWithMacControl(ControlRef inControl, wxWindow *control)
539 {
540 // adding NULL ControlRef is (first) surely a result of an error and
541 // (secondly) breaks native event processing
542 wxCHECK_RET( inControl != (ControlRef) NULL, wxT("attempt to add a NULL WindowRef to window list") );
543
544 if ( !wxWinMacControlList.Find((long)inControl) )
545 wxWinMacControlList.Append((long)inControl, control);
546 }
547
548 void wxRemoveMacControlAssociation(wxWindow *control)
549 {
550 wxWinMacControlList.DeleteObject(control);
551 }
552
553 // UPP functions
554 ControlActionUPP wxMacLiveScrollbarActionUPP = NULL ;
555
556 ControlColorUPP wxMacSetupControlBackgroundUPP = NULL ;
557
558 // we have to setup the brush in the current port and return noErr
559 // or return an error code so that the control manager walks further up the
560 // hierarchy to find a correct background
561
562 pascal OSStatus wxMacSetupControlBackground( ControlRef iControl , SInt16 iMessage , SInt16 iDepth , Boolean iIsColor )
563 {
564 OSStatus status = paramErr ;
565 switch( iMessage )
566 {
567 case kControlMsgApplyTextColor :
568 break ;
569 case kControlMsgSetUpBackground :
570 {
571 wxWindow* wx = (wxWindow*) wxFindControlFromMacControl( iControl ) ;
572 if ( wx != NULL )
573 {
574 /*
575 const wxBrush &brush = wx->MacGetBackgroundBrush() ;
576 if ( brush.Ok() )
577 {
578 wxDC::MacSetupBackgroundForCurrentPort( brush ) ;
579 */
580 // this clipping is only needed for non HIView
581
582 RgnHandle clip = NewRgn() ;
583 int x = 0 , y = 0;
584
585 wx->MacWindowToRootWindow( &x,&y ) ;
586 CopyRgn( (RgnHandle) wx->MacGetVisibleRegion().GetWXHRGN() , clip ) ;
587 OffsetRgn( clip , x , y ) ;
588 SetClip( clip ) ;
589 DisposeRgn( clip ) ;
590
591 status = noErr ;
592 /*
593 }
594 else if ( wx->MacIsUserPane() )
595 {
596 // if we don't have a valid brush for such a control, we have to call the
597 // setup of our parent ourselves
598 status = SetUpControlBackground( (ControlRef) wx->GetParent()->GetHandle() , iDepth , iIsColor ) ;
599 }
600 */
601 }
602 }
603 break ;
604 default :
605 break ;
606 }
607 return status ;
608 }
609
610
611 pascal void wxMacLiveScrollbarActionProc( ControlRef control , ControlPartCode partCode ) ;
612 pascal void wxMacLiveScrollbarActionProc( ControlRef control , ControlPartCode partCode )
613 {
614 if ( partCode != 0)
615 {
616 wxWindow* wx = wxFindControlFromMacControl( control ) ;
617 if ( wx )
618 {
619 wx->MacHandleControlClick( (WXWidget) control , partCode , true /* stillDown */ ) ;
620 }
621 }
622 }
623
624 // ----------------------------------------------------------------------------
625 // constructors and such
626 // ----------------------------------------------------------------------------
627
628 wxWindowMac::wxWindowMac()
629 {
630 Init();
631 }
632
633 wxWindowMac::wxWindowMac(wxWindowMac *parent,
634 wxWindowID id,
635 const wxPoint& pos ,
636 const wxSize& size ,
637 long style ,
638 const wxString& name )
639 {
640 Init();
641 Create(parent, id, pos, size, style, name);
642 }
643
644 void wxWindowMac::Init()
645 {
646 m_peer = NULL ;
647 m_frozenness = 0 ;
648 #if WXWIN_COMPATIBILITY_2_4
649 m_backgroundTransparent = FALSE;
650 #endif
651
652 // as all windows are created with WS_VISIBLE style...
653 m_isShown = TRUE;
654
655 m_hScrollBar = NULL ;
656 m_vScrollBar = NULL ;
657 m_macBackgroundBrush = wxNullBrush ;
658
659 m_macIsUserPane = TRUE;
660
661 // make sure all proc ptrs are available
662
663 if ( gControlUserPaneDrawUPP == NULL )
664 {
665 gControlUserPaneDrawUPP = NewControlUserPaneDrawUPP( wxMacControlUserPaneDrawProc ) ;
666 gControlUserPaneHitTestUPP = NewControlUserPaneHitTestUPP( wxMacControlUserPaneHitTestProc ) ;
667 gControlUserPaneTrackingUPP = NewControlUserPaneTrackingUPP( wxMacControlUserPaneTrackingProc ) ;
668 gControlUserPaneIdleUPP = NewControlUserPaneIdleUPP( wxMacControlUserPaneIdleProc ) ;
669 gControlUserPaneKeyDownUPP = NewControlUserPaneKeyDownUPP( wxMacControlUserPaneKeyDownProc ) ;
670 gControlUserPaneActivateUPP = NewControlUserPaneActivateUPP( wxMacControlUserPaneActivateProc ) ;
671 gControlUserPaneFocusUPP = NewControlUserPaneFocusUPP( wxMacControlUserPaneFocusProc ) ;
672 gControlUserPaneBackgroundUPP = NewControlUserPaneBackgroundUPP( wxMacControlUserPaneBackgroundProc ) ;
673 }
674 if ( wxMacLiveScrollbarActionUPP == NULL )
675 {
676 wxMacLiveScrollbarActionUPP = NewControlActionUPP( wxMacLiveScrollbarActionProc );
677 }
678
679 if ( wxMacSetupControlBackgroundUPP == NULL )
680 {
681 wxMacSetupControlBackgroundUPP = NewControlColorUPP( wxMacSetupControlBackground ) ;
682 }
683
684 // we need a valid font for the encodings
685 wxWindowBase::SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
686 }
687
688 // Destructor
689 wxWindowMac::~wxWindowMac()
690 {
691 SendDestroyEvent();
692
693 m_isBeingDeleted = TRUE;
694
695 #ifndef __WXUNIVERSAL__
696 // VS: make sure there's no wxFrame with last focus set to us:
697 for ( wxWindow *win = GetParent(); win; win = win->GetParent() )
698 {
699 wxFrame *frame = wxDynamicCast(win, wxFrame);
700 if ( frame )
701 {
702 if ( frame->GetLastFocus() == this )
703 {
704 frame->SetLastFocus((wxWindow*)NULL);
705 }
706 break;
707 }
708 }
709 #endif // __WXUNIVERSAL__
710
711 // wxRemoveMacControlAssociation( this ) ;
712 // If we delete an item, we should initialize the parent panel,
713 // because it could now be invalid.
714 wxWindow *parent = GetParent() ;
715 if ( parent )
716 {
717 if (parent->GetDefaultItem() == (wxButton*) this)
718 parent->SetDefaultItem(NULL);
719 }
720 if ( m_peer && m_peer->Ok() )
721 {
722 // in case the callback might be called during destruction
723 wxRemoveMacControlAssociation( this) ;
724 // we currently are not using this hook
725 // ::SetControlColorProc( *m_peer , NULL ) ;
726 m_peer->Dispose() ;
727 }
728
729 if ( g_MacLastWindow == this )
730 {
731 g_MacLastWindow = NULL ;
732 }
733
734 wxFrame* frame = wxDynamicCast( wxGetTopLevelParent( this ) , wxFrame ) ;
735 if ( frame )
736 {
737 if ( frame->GetLastFocus() == this )
738 frame->SetLastFocus( NULL ) ;
739 }
740
741 DestroyChildren();
742
743 // delete our drop target if we've got one
744 #if wxUSE_DRAG_AND_DROP
745 if ( m_dropTarget != NULL )
746 {
747 delete m_dropTarget;
748 m_dropTarget = NULL;
749 }
750 #endif // wxUSE_DRAG_AND_DROP
751 delete m_peer ;
752 }
753
754 WXWidget wxWindowMac::GetHandle() const
755 {
756 return (WXWidget) m_peer->GetControlRef() ;
757 }
758
759
760 void wxWindowMac::MacInstallEventHandler( WXWidget control )
761 {
762 wxAssociateControlWithMacControl( (ControlRef) control , this ) ;
763 InstallControlEventHandler( (ControlRef) control , GetwxMacWindowEventHandlerUPP(),
764 GetEventTypeCount(eventList), eventList, this,
765 (EventHandlerRef *)&m_macControlEventHandler);
766
767 }
768
769 // Constructor
770 bool wxWindowMac::Create(wxWindowMac *parent, wxWindowID id,
771 const wxPoint& pos,
772 const wxSize& size,
773 long style,
774 const wxString& name)
775 {
776 wxCHECK_MSG( parent, FALSE, wxT("can't create wxWindowMac without parent") );
777
778 if ( !CreateBase(parent, id, pos, size, style, wxDefaultValidator, name) )
779 return FALSE;
780
781 parent->AddChild(this);
782
783 m_windowVariant = parent->GetWindowVariant() ;
784
785 if ( m_macIsUserPane )
786 {
787 Rect bounds = wxMacGetBoundsForControl( this , pos , size ) ;
788
789 UInt32 features = 0
790 | kControlSupportsEmbedding
791 // | kControlSupportsLiveFeedback
792 // | kControlHasSpecialBackground
793 // | kControlSupportsCalcBestRect
794 // | kControlHandlesTracking
795 | kControlSupportsFocus
796 // | kControlWantsActivate
797 // | kControlWantsIdle
798 ;
799
800 m_peer = new wxMacControl() ;
801 ::CreateUserPaneControl( MAC_WXHWND(GetParent()->MacGetTopLevelWindowRef()) , &bounds, features , m_peer->GetControlRefAddr() );
802
803
804 MacPostControlCreate(pos,size) ;
805 #if !TARGET_API_MAC_OSX
806 m_peer->SetData<ControlUserPaneDrawUPP>(kControlEntireControl,kControlUserPaneDrawProcTag,&gControlUserPaneDrawUPP) ;
807 m_peer->SetData<ControlUserPaneHitTestUPP>(kControlEntireControl,kControlUserPaneHitTestProcTag,&gControlUserPaneHitTestUPP) ;
808 m_peer->SetData<ControlUserPaneTrackingUPP>(kControlEntireControl,kControlUserPaneTrackingProcTag,&gControlUserPaneTrackingUPP) ;
809 m_peer->SetData<ControlUserPaneIdleUPP>(kControlEntireControl,kControlUserPaneIdleProcTag,&gControlUserPaneIdleUPP) ;
810 m_peer->SetData<ControlUserPaneKeyDownUPP>(kControlEntireControl,kControlUserPaneKeyDownProcTag,&gControlUserPaneKeyDownUPP) ;
811 m_peer->SetData<ControlUserPaneActivateUPP>(kControlEntireControl,kControlUserPaneActivateProcTag,&gControlUserPaneActivateUPP) ;
812 m_peer->SetData<ControlUserPaneFocusUPP>(kControlEntireControl,kControlUserPaneFocusProcTag,&gControlUserPaneFocusUPP) ;
813 m_peer->SetData<ControlUserPaneBackgroundUPP>(kControlEntireControl,kControlUserPaneBackgroundProcTag,&gControlUserPaneBackgroundUPP) ;
814 #endif
815 }
816 #ifndef __WXUNIVERSAL__
817 // Don't give scrollbars to wxControls unless they ask for them
818 if ( (! IsKindOf(CLASSINFO(wxControl)) && ! IsKindOf(CLASSINFO(wxStatusBar))) ||
819 (IsKindOf(CLASSINFO(wxControl)) && ( style & wxHSCROLL || style & wxVSCROLL)))
820 {
821 MacCreateScrollBars( style ) ;
822 }
823 #endif
824
825 wxWindowCreateEvent event(this);
826 GetEventHandler()->AddPendingEvent(event);
827
828 return TRUE;
829 }
830
831 void wxWindowMac::MacPostControlCreate(const wxPoint& pos, const wxSize& size)
832 {
833 wxASSERT_MSG( m_peer != NULL && m_peer->Ok() , wxT("No valid mac control") ) ;
834
835 m_peer->SetReference( (long) this ) ;
836
837 MacInstallEventHandler( (WXWidget) m_peer->GetControlRef() );
838
839 ControlRef container = (ControlRef) GetParent()->GetHandle() ;
840 wxASSERT_MSG( container != NULL , wxT("No valid mac container control") ) ;
841 ::EmbedControl( m_peer->GetControlRef() , container ) ;
842
843 // adjust font, controlsize etc
844 DoSetWindowVariant( m_windowVariant ) ;
845
846 #if !TARGET_API_MAC_OSX
847 // eventually we can fix some clipping issues be reactivating this hook
848 //if ( m_macIsUserPane )
849 // SetControlColorProc( m_peer->GetControlRef() , wxMacSetupControlBackgroundUPP ) ;
850 #endif
851 m_peer->SetTitle( wxStripMenuCodes(m_label) ) ;
852
853 if (!m_macIsUserPane)
854 {
855 SetInitialBestSize(size);
856 }
857
858 SetCursor( *wxSTANDARD_CURSOR ) ;
859 }
860
861 void wxWindowMac::DoSetWindowVariant( wxWindowVariant variant )
862 {
863 // Don't assert, in case we set the window variant before
864 // the window is created
865 // wxASSERT( m_peer->Ok() ) ;
866
867 m_windowVariant = variant ;
868
869 if (m_peer == NULL || !m_peer->Ok())
870 return;
871
872 ControlSize size ;
873 ThemeFontID themeFont = kThemeSystemFont ;
874
875 // we will get that from the settings later
876 // and make this NORMAL later, but first
877 // we have a few calculations that we must fix
878
879 switch ( variant )
880 {
881 case wxWINDOW_VARIANT_NORMAL :
882 size = kControlSizeNormal;
883 themeFont = kThemeSystemFont ;
884 break ;
885 case wxWINDOW_VARIANT_SMALL :
886 size = kControlSizeSmall;
887 themeFont = kThemeSmallSystemFont ;
888 break ;
889 case wxWINDOW_VARIANT_MINI :
890 if (UMAGetSystemVersion() >= 0x1030 )
891 {
892 // not always defined in the headers
893 size = 3 ;
894 themeFont = 109 ;
895 }
896 else
897 {
898 size = kControlSizeSmall;
899 themeFont = kThemeSmallSystemFont ;
900 }
901 break ;
902 case wxWINDOW_VARIANT_LARGE :
903 size = kControlSizeLarge;
904 themeFont = kThemeSystemFont ;
905 break ;
906 default:
907 wxFAIL_MSG(_T("unexpected window variant"));
908 break ;
909 }
910 m_peer->SetData<ControlSize>(kControlEntireControl, kControlSizeTag,&size ) ;
911
912 wxFont font ;
913 font.MacCreateThemeFont( themeFont ) ;
914 SetFont( font ) ;
915 }
916
917 void wxWindowMac::MacUpdateControlFont()
918 {
919 m_peer->SetFont( GetFont() , GetForegroundColour() , GetWindowStyle() ) ;
920 Refresh() ;
921 }
922
923 bool wxWindowMac::SetFont(const wxFont& font)
924 {
925 bool retval = !wxWindowBase::SetFont( font ) ;
926
927 MacUpdateControlFont() ;
928
929 return retval;
930 }
931
932 bool wxWindowMac::SetForegroundColour(const wxColour& col )
933 {
934 if ( !wxWindowBase::SetForegroundColour(col) )
935 return false ;
936
937 MacUpdateControlFont() ;
938
939 return true ;
940 }
941
942 bool wxWindowMac::SetBackgroundColour(const wxColour& col )
943 {
944 if ( !wxWindowBase::SetBackgroundColour(col) && m_hasBgCol )
945 return false ;
946
947 wxBrush brush ;
948 wxColour newCol(GetBackgroundColour());
949 if ( newCol == wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE) )
950 {
951 brush.MacSetTheme( kThemeBrushDocumentWindowBackground ) ;
952 }
953 else if ( newCol == wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE ) )
954 {
955 brush.MacSetTheme( kThemeBrushDialogBackgroundActive ) ;
956 }
957 else
958 {
959 brush.SetColour( newCol ) ;
960 }
961 MacSetBackgroundBrush( brush ) ;
962
963 MacUpdateControlFont() ;
964
965 return true ;
966 }
967
968 void wxWindowMac::MacSetBackgroundBrush( const wxBrush &brush )
969 {
970 m_macBackgroundBrush = brush ;
971 m_peer->SetBackground( brush ) ;
972 }
973
974 bool wxWindowMac::MacCanFocus() const
975 {
976 // there is currently no way to determine whether the window is running in full keyboard
977 // access mode, therefore we cannot rely on these features, yet the only other way would be
978 // to issue a SetKeyboardFocus event and verify after whether it succeeded, this would risk problems
979 // in event handlers...
980 UInt32 features = 0 ;
981 m_peer->GetFeatures( & features ) ;
982 return features & ( kControlSupportsFocus | kControlGetsFocusOnClick ) ;
983 }
984
985
986 void wxWindowMac::SetFocus()
987 {
988 if ( AcceptsFocus() )
989 {
990 #if !TARGET_API_MAC_OSX
991 wxWindow* former = FindFocus() ;
992 #endif
993 OSStatus err = m_peer->SetFocus( kControlFocusNextPart ) ;
994 // as we cannot rely on the control features to find out whether we are in full keyboard mode, we can only
995 // leave in case of an error
996 if ( err == errCouldntSetFocus )
997 return ;
998
999 #if !TARGET_API_MAC_OSX
1000 // emulate carbon events when running under carbonlib where they are not natively available
1001 if ( former )
1002 {
1003 EventRef evRef = NULL ;
1004 verify_noerr( MacCreateEvent( NULL , kEventClassControl , kEventControlSetFocusPart , TicksToEventTime( TickCount() ) , kEventAttributeUserEvent ,
1005 &evRef ) );
1006
1007 wxMacCarbonEvent cEvent( evRef ) ;
1008 cEvent.SetParameter<ControlRef>( kEventParamDirectObject , (ControlRef) former->GetHandle() ) ;
1009 cEvent.SetParameter<ControlPartCode>(kEventParamControlPart , typeControlPartCode , kControlFocusNoPart ) ;
1010
1011 wxMacWindowEventHandler( NULL , evRef , former ) ;
1012 ReleaseEvent(evRef) ;
1013 }
1014 // send new focus event
1015 {
1016 EventRef evRef = NULL ;
1017 verify_noerr( MacCreateEvent( NULL , kEventClassControl , kEventControlSetFocusPart , TicksToEventTime( TickCount() ) , kEventAttributeUserEvent ,
1018 &evRef ) );
1019
1020 wxMacCarbonEvent cEvent( evRef ) ;
1021 cEvent.SetParameter<ControlRef>( kEventParamDirectObject , (ControlRef) GetHandle() ) ;
1022 cEvent.SetParameter<ControlPartCode>(kEventParamControlPart , typeControlPartCode , kControlFocusNextPart ) ;
1023
1024 wxMacWindowEventHandler( NULL , evRef , this ) ;
1025 ReleaseEvent(evRef) ;
1026 }
1027 #endif
1028 }
1029 }
1030
1031
1032 void wxWindowMac::DoCaptureMouse()
1033 {
1034 wxTheApp->s_captureWindow = this ;
1035 }
1036
1037 wxWindow* wxWindowBase::GetCapture()
1038 {
1039 return wxTheApp->s_captureWindow ;
1040 }
1041
1042 void wxWindowMac::DoReleaseMouse()
1043 {
1044 wxTheApp->s_captureWindow = NULL ;
1045 }
1046
1047 #if wxUSE_DRAG_AND_DROP
1048
1049 void wxWindowMac::SetDropTarget(wxDropTarget *pDropTarget)
1050 {
1051 if ( m_dropTarget != 0 ) {
1052 delete m_dropTarget;
1053 }
1054
1055 m_dropTarget = pDropTarget;
1056 if ( m_dropTarget != 0 )
1057 {
1058 // TODO
1059 }
1060 }
1061
1062 #endif
1063
1064 // Old style file-manager drag&drop
1065 void wxWindowMac::DragAcceptFiles(bool accept)
1066 {
1067 // TODO
1068 }
1069
1070 // Returns the size of the native control. In the case of the toplevel window
1071 // this is the content area root control
1072
1073 void wxWindowMac::MacGetPositionAndSizeFromControl(int& x, int& y,
1074 int& w, int& h) const
1075 {
1076 Rect bounds ;
1077 m_peer->GetRect( &bounds ) ;
1078
1079
1080 x = bounds.left ;
1081 y = bounds.top ;
1082 w = bounds.right - bounds.left ;
1083 h = bounds.bottom - bounds.top ;
1084 }
1085
1086 // From a wx position / size calculate the appropriate size of the native control
1087
1088 bool wxWindowMac::MacGetBoundsForControl(const wxPoint& pos,
1089 const wxSize& size,
1090 int& x, int& y,
1091 int& w, int& h , bool adjustOrigin ) const
1092 {
1093 // the desired size, minus the border pixels gives the correct size of the control
1094
1095 x = (int)pos.x;
1096 y = (int)pos.y;
1097 // todo the default calls may be used as soon as PostCreateControl Is moved here
1098 w = size.x ; // WidthDefault( size.x );
1099 h = size.y ; // HeightDefault( size.y ) ;
1100 #if !TARGET_API_MAC_OSX
1101 GetParent()->MacWindowToRootWindow( &x , &y ) ;
1102 #endif
1103
1104 x += MacGetLeftBorderSize() ;
1105 y += MacGetTopBorderSize() ;
1106 w -= MacGetLeftBorderSize() + MacGetRightBorderSize() ;
1107 h -= MacGetTopBorderSize() + MacGetBottomBorderSize() ;
1108
1109 if ( adjustOrigin )
1110 AdjustForParentClientOrigin( x , y ) ;
1111 return true ;
1112 }
1113
1114 // Get window size (not client size)
1115 void wxWindowMac::DoGetSize(int *x, int *y) const
1116 {
1117 // take the size of the control and add the borders that have to be drawn outside
1118 int x1 , y1 , w1 , h1 ;
1119
1120 MacGetPositionAndSizeFromControl( x1 , y1, w1 ,h1 ) ;
1121
1122 w1 += MacGetLeftBorderSize() + MacGetRightBorderSize() ;
1123 h1 += MacGetTopBorderSize() + MacGetBottomBorderSize() ;
1124
1125 if(x) *x = w1 ;
1126 if(y) *y = h1 ;
1127 }
1128
1129 // get the position of the bounds of this window in client coordinates of its parent
1130 void wxWindowMac::DoGetPosition(int *x, int *y) const
1131 {
1132 int x1 , y1 , w1 ,h1 ;
1133 MacGetPositionAndSizeFromControl( x1 , y1, w1 ,h1 ) ;
1134 x1 -= MacGetLeftBorderSize() ;
1135 y1 -= MacGetTopBorderSize() ;
1136 // to non-client
1137 #if !TARGET_API_MAC_OSX
1138 if ( !GetParent()->IsTopLevel() )
1139 {
1140 Rect bounds ;
1141 GetControlBounds( (ControlRef) GetParent()->GetHandle() , &bounds ) ;
1142 x1 -= bounds.left ;
1143 y1 -= bounds.top ;
1144 }
1145 #endif
1146 if ( !IsTopLevel() )
1147 {
1148 wxWindow *parent = GetParent();
1149 if ( parent )
1150 {
1151 // we must first adjust it to be in window coordinates of the parent, as otherwise it gets lost by the clientareaorigin fix
1152 x1 += parent->MacGetLeftBorderSize() ;
1153 y1 += parent->MacGetTopBorderSize() ;
1154 // and now to client coordinates
1155 wxPoint pt(parent->GetClientAreaOrigin());
1156 x1 -= pt.x ;
1157 y1 -= pt.y ;
1158 }
1159 }
1160 if(x) *x = x1 ;
1161 if(y) *y = y1 ;
1162 }
1163
1164 void wxWindowMac::DoScreenToClient(int *x, int *y) const
1165 {
1166 WindowRef window = (WindowRef) MacGetTopLevelWindowRef() ;
1167
1168 wxCHECK_RET( window , wxT("TopLevel Window Missing") ) ;
1169
1170 {
1171 Point localwhere = {0,0} ;
1172
1173 if(x) localwhere.h = * x ;
1174 if(y) localwhere.v = * y ;
1175
1176 QDGlobalToLocalPoint( GetWindowPort( window ) , &localwhere ) ;
1177 if(x) *x = localwhere.h ;
1178 if(y) *y = localwhere.v ;
1179
1180 }
1181 MacRootWindowToWindow( x , y ) ;
1182
1183 wxPoint origin = GetClientAreaOrigin() ;
1184 if(x) *x -= origin.x ;
1185 if(y) *y -= origin.y ;
1186 }
1187
1188 void wxWindowMac::DoClientToScreen(int *x, int *y) const
1189 {
1190 WindowRef window = (WindowRef) MacGetTopLevelWindowRef() ;
1191 wxCHECK_RET( window , wxT("TopLevel Window Missing") ) ;
1192
1193 wxPoint origin = GetClientAreaOrigin() ;
1194 if(x) *x += origin.x ;
1195 if(y) *y += origin.y ;
1196
1197 MacWindowToRootWindow( x , y ) ;
1198
1199 {
1200 Point localwhere = { 0,0 };
1201 if(x) localwhere.h = * x ;
1202 if(y) localwhere.v = * y ;
1203 QDLocalToGlobalPoint( GetWindowPort( window ) , &localwhere ) ;
1204 if(x) *x = localwhere.h ;
1205 if(y) *y = localwhere.v ;
1206 }
1207 }
1208
1209 void wxWindowMac::MacClientToRootWindow( int *x , int *y ) const
1210 {
1211 wxPoint origin = GetClientAreaOrigin() ;
1212 if(x) *x += origin.x ;
1213 if(y) *y += origin.y ;
1214
1215 MacWindowToRootWindow( x , y ) ;
1216 }
1217
1218 void wxWindowMac::MacRootWindowToClient( int *x , int *y ) const
1219 {
1220 MacRootWindowToWindow( x , y ) ;
1221
1222 wxPoint origin = GetClientAreaOrigin() ;
1223 if(x) *x -= origin.x ;
1224 if(y) *y -= origin.y ;
1225 }
1226
1227 void wxWindowMac::MacWindowToRootWindow( int *x , int *y ) const
1228 {
1229 #if TARGET_API_MAC_OSX
1230 wxPoint pt ;
1231 if ( x ) pt.x = *x ;
1232 if ( y ) pt.y = *y ;
1233
1234 if ( !IsTopLevel() )
1235 {
1236 wxTopLevelWindowMac* top = MacGetTopLevelWindow();
1237 if (top)
1238 {
1239 pt.x -= MacGetLeftBorderSize() ;
1240 pt.y -= MacGetTopBorderSize() ;
1241 wxMacControl::Convert( &pt , m_peer , top->m_peer ) ;
1242 }
1243 }
1244
1245 if ( x ) *x = (int) pt.x ;
1246 if ( y ) *y = (int) pt.y ;
1247 #else
1248 if ( !IsTopLevel() )
1249 {
1250 Rect bounds ;
1251 m_peer->GetRect( &bounds ) ;
1252 if(x) *x += bounds.left - MacGetLeftBorderSize() ;
1253 if(y) *y += bounds.top - MacGetTopBorderSize() ;
1254 }
1255 #endif
1256 }
1257
1258 void wxWindowMac::MacWindowToRootWindow( short *x , short *y ) const
1259 {
1260 int x1 , y1 ;
1261 if ( x ) x1 = *x ;
1262 if ( y ) y1 = *y ;
1263 MacWindowToRootWindow( &x1 , &y1 ) ;
1264 if ( x ) *x = x1 ;
1265 if ( y ) *y = y1 ;
1266 }
1267
1268 void wxWindowMac::MacRootWindowToWindow( int *x , int *y ) const
1269 {
1270 #if TARGET_API_MAC_OSX
1271 wxPoint pt ;
1272 if ( x ) pt.x = *x ;
1273 if ( y ) pt.y = *y ;
1274
1275 if ( !IsTopLevel() )
1276 {
1277 wxMacControl::Convert( &pt , MacGetTopLevelWindow()->m_peer , m_peer ) ;
1278 pt.x += MacGetLeftBorderSize() ;
1279 pt.y += MacGetTopBorderSize() ;
1280 }
1281
1282 if ( x ) *x = (int) pt.x ;
1283 if ( y ) *y = (int) pt.y ;
1284 #else
1285 if ( !IsTopLevel() )
1286 {
1287 Rect bounds ;
1288 m_peer->GetRect( &bounds ) ;
1289 if(x) *x -= bounds.left + MacGetLeftBorderSize() ;
1290 if(y) *y -= bounds.top + MacGetTopBorderSize() ;
1291 }
1292 #endif
1293 }
1294
1295 void wxWindowMac::MacRootWindowToWindow( short *x , short *y ) const
1296 {
1297 int x1 , y1 ;
1298 if ( x ) x1 = *x ;
1299 if ( y ) y1 = *y ;
1300 MacRootWindowToWindow( &x1 , &y1 ) ;
1301 if ( x ) *x = x1 ;
1302 if ( y ) *y = y1 ;
1303 }
1304
1305 void wxWindowMac::MacGetContentAreaInset( int &left , int &top , int &right , int &bottom )
1306 {
1307 RgnHandle rgn = NewRgn() ;
1308 Rect content ;
1309 if ( m_peer->GetRegion( kControlContentMetaPart , rgn ) == noErr )
1310 {
1311 GetRegionBounds( rgn , &content ) ;
1312 DisposeRgn( rgn ) ;
1313 }
1314 else
1315 {
1316 m_peer->GetRect( &content ) ;
1317 }
1318 Rect structure ;
1319 m_peer->GetRect( &structure ) ;
1320 #if !TARGET_API_MAC_OSX
1321 OffsetRect( &content , -structure.left , -structure.top ) ;
1322 #endif
1323 left = content.left - structure.left ;
1324 top = content.top - structure.top ;
1325 right = structure.right - content.right ;
1326 bottom = structure.bottom - content.bottom ;
1327 }
1328
1329 wxSize wxWindowMac::DoGetSizeFromClientSize( const wxSize & size ) const
1330 {
1331 wxSize sizeTotal = size;
1332
1333 RgnHandle rgn = NewRgn() ;
1334
1335 Rect content ;
1336
1337 if ( m_peer->GetRegion( kControlContentMetaPart , rgn ) == noErr )
1338 {
1339 GetRegionBounds( rgn , &content ) ;
1340 DisposeRgn( rgn ) ;
1341 }
1342 else
1343 {
1344 m_peer->GetRect( &content ) ;
1345 }
1346 Rect structure ;
1347 m_peer->GetRect( &structure ) ;
1348 #if !TARGET_API_MAC_OSX
1349 OffsetRect( &content , -structure.left , -structure.top ) ;
1350 #endif
1351
1352 sizeTotal.x += (structure.right - structure.left) - (content.right - content.left) ;
1353 sizeTotal.y += (structure.bottom - structure.top) - (content.bottom - content.top ) ;
1354
1355 sizeTotal.x += MacGetLeftBorderSize( ) + MacGetRightBorderSize( ) ;
1356 sizeTotal.y += MacGetTopBorderSize( ) + MacGetBottomBorderSize( ) ;
1357
1358 return sizeTotal;
1359 }
1360
1361
1362 // Get size *available for subwindows* i.e. excluding menu bar etc.
1363 void wxWindowMac::DoGetClientSize(int *x, int *y) const
1364 {
1365 int ww, hh;
1366
1367 RgnHandle rgn = NewRgn() ;
1368 Rect content ;
1369 if ( m_peer->GetRegion( kControlContentMetaPart , rgn ) == noErr )
1370 {
1371 GetRegionBounds( rgn , &content ) ;
1372 DisposeRgn( rgn ) ;
1373 }
1374 else
1375 {
1376 m_peer->GetRect( &content ) ;
1377 }
1378 #if !TARGET_API_MAC_OSX
1379 Rect structure ;
1380 m_peer->GetRect( &structure ) ;
1381 OffsetRect( &content , -structure.left , -structure.top ) ;
1382 #endif
1383 ww = content.right - content.left ;
1384 hh = content.bottom - content.top ;
1385 /*
1386 ww -= MacGetLeftBorderSize( ) + MacGetRightBorderSize( ) ;
1387 hh -= MacGetTopBorderSize( ) + MacGetBottomBorderSize( );
1388 */
1389 /*
1390 if ( (m_vScrollBar && m_vScrollBar->IsShown()) || (m_hScrollBar && m_hScrollBar->IsShown()) )
1391 {
1392 int x1 = 0 ;
1393 int y1 = 0 ;
1394 int w ;
1395 int h ;
1396 GetSize( &w , &h ) ;
1397
1398 MacClientToRootWindow( &x1 , &y1 ) ;
1399 MacClientToRootWindow( &w , &h ) ;
1400
1401 wxWindowMac *iter = (wxWindowMac*)this ;
1402
1403 int totW = 10000 , totH = 10000;
1404 while( iter )
1405 {
1406 if ( iter->IsTopLevel() )
1407 {
1408 iter->GetSize( &totW , &totH ) ;
1409 break ;
1410 }
1411
1412 iter = iter->GetParent() ;
1413 }
1414
1415 if (m_hScrollBar && m_hScrollBar->IsShown() )
1416 {
1417 hh -= m_hScrollBar->GetSize().y ; // MAC_SCROLLBAR_SIZE ;
1418 if ( h-y1 >= totH )
1419 {
1420 hh += 1 ;
1421 }
1422 }
1423 if (m_vScrollBar && m_vScrollBar->IsShown() )
1424 {
1425 ww -= m_vScrollBar->GetSize().x ; // MAC_SCROLLBAR_SIZE;
1426 if ( w-x1 >= totW )
1427 {
1428 ww += 1 ;
1429 }
1430 }
1431 }
1432 */
1433 if (m_hScrollBar && m_hScrollBar->IsShown() )
1434 {
1435 hh -= m_hScrollBar->GetSize().y ; // MAC_SCROLLBAR_SIZE ;
1436 }
1437 if (m_vScrollBar && m_vScrollBar->IsShown() )
1438 {
1439 ww -= m_vScrollBar->GetSize().x ; // MAC_SCROLLBAR_SIZE;
1440 }
1441 if(x) *x = ww;
1442 if(y) *y = hh;
1443
1444 }
1445
1446 bool wxWindowMac::SetCursor(const wxCursor& cursor)
1447 {
1448 if (m_cursor == cursor)
1449 return FALSE;
1450
1451 if (wxNullCursor == cursor)
1452 {
1453 if ( ! wxWindowBase::SetCursor( *wxSTANDARD_CURSOR ) )
1454 return FALSE ;
1455 }
1456 else
1457 {
1458 if ( ! wxWindowBase::SetCursor( cursor ) )
1459 return FALSE ;
1460 }
1461
1462 wxASSERT_MSG( m_cursor.Ok(),
1463 wxT("cursor must be valid after call to the base version"));
1464
1465
1466 wxWindowMac *mouseWin = 0 ;
1467 {
1468 WindowRef window = (WindowRef) MacGetTopLevelWindowRef() ;
1469 CGrafPtr savePort ;
1470 Boolean swapped = QDSwapPort( GetWindowPort( window ) , &savePort ) ;
1471
1472 // TODO If we ever get a GetCurrentEvent.. replacement for the mouse
1473 // position, use it...
1474
1475 Point pt ;
1476 GetMouse( &pt ) ;
1477 ControlPartCode part ;
1478 ControlRef control ;
1479 control = wxMacFindControlUnderMouse( pt , window , &part ) ;
1480 if ( control )
1481 mouseWin = wxFindControlFromMacControl( control ) ;
1482
1483 if ( swapped )
1484 QDSwapPort( savePort , NULL ) ;
1485 }
1486
1487 if ( mouseWin == this && !wxIsBusy() )
1488 {
1489 m_cursor.MacInstall() ;
1490 }
1491
1492 return TRUE ;
1493 }
1494
1495 #if wxUSE_MENUS
1496 bool wxWindowMac::DoPopupMenu(wxMenu *menu, int x, int y)
1497 {
1498 menu->SetInvokingWindow(this);
1499 menu->UpdateUI();
1500
1501 if ( x == -1 && y == -1 )
1502 {
1503 wxPoint mouse = wxGetMousePosition();
1504 x = mouse.x; y = mouse.y;
1505 }
1506 else
1507 {
1508 ClientToScreen( &x , &y ) ;
1509 }
1510
1511 menu->MacBeforeDisplay( true ) ;
1512 long menuResult = ::PopUpMenuSelect((MenuHandle) menu->GetHMenu() ,y,x, 0) ;
1513 if ( HiWord(menuResult) != 0 )
1514 {
1515 MenuCommand id ;
1516 GetMenuItemCommandID( GetMenuHandle(HiWord(menuResult)) , LoWord(menuResult) , &id ) ;
1517 wxMenuItem* item = NULL ;
1518 wxMenu* realmenu ;
1519 item = menu->FindItem(id, &realmenu) ;
1520 if (item->IsCheckable())
1521 {
1522 item->Check( !item->IsChecked() ) ;
1523 }
1524 menu->SendEvent( id , item->IsCheckable() ? item->IsChecked() : -1 ) ;
1525 }
1526 menu->MacAfterDisplay( true ) ;
1527
1528 menu->SetInvokingWindow(NULL);
1529
1530 return TRUE;
1531 }
1532 #endif
1533
1534 // ----------------------------------------------------------------------------
1535 // tooltips
1536 // ----------------------------------------------------------------------------
1537
1538 #if wxUSE_TOOLTIPS
1539
1540 void wxWindowMac::DoSetToolTip(wxToolTip *tooltip)
1541 {
1542 wxWindowBase::DoSetToolTip(tooltip);
1543
1544 if ( m_tooltip )
1545 m_tooltip->SetWindow(this);
1546 }
1547
1548 #endif // wxUSE_TOOLTIPS
1549
1550 void wxWindowMac::DoMoveWindow(int x, int y, int width, int height)
1551 {
1552 // this is never called for a toplevel window, so we know we have a parent
1553 int former_x , former_y , former_w, former_h ;
1554
1555 // Get true coordinates of former position
1556 DoGetPosition( &former_x , &former_y ) ;
1557 DoGetSize( &former_w , &former_h ) ;
1558
1559 wxWindow *parent = GetParent();
1560 if ( parent )
1561 {
1562 wxPoint pt(parent->GetClientAreaOrigin());
1563 former_x += pt.x ;
1564 former_y += pt.y ;
1565 }
1566
1567 int actualWidth = width;
1568 int actualHeight = height;
1569 int actualX = x;
1570 int actualY = y;
1571
1572 if ((m_minWidth != -1) && (actualWidth < m_minWidth))
1573 actualWidth = m_minWidth;
1574 if ((m_minHeight != -1) && (actualHeight < m_minHeight))
1575 actualHeight = m_minHeight;
1576 if ((m_maxWidth != -1) && (actualWidth > m_maxWidth))
1577 actualWidth = m_maxWidth;
1578 if ((m_maxHeight != -1) && (actualHeight > m_maxHeight))
1579 actualHeight = m_maxHeight;
1580
1581 bool doMove = false ;
1582 bool doResize = false ;
1583
1584 if ( actualX != former_x || actualY != former_y )
1585 {
1586 doMove = true ;
1587 }
1588 if ( actualWidth != former_w || actualHeight != former_h )
1589 {
1590 doResize = true ;
1591 }
1592
1593 if ( doMove || doResize )
1594 {
1595 // we don't adjust twice for the origin
1596 Rect r = wxMacGetBoundsForControl(this , wxPoint( actualX,actualY), wxSize( actualWidth, actualHeight ) , false ) ;
1597 #if TARGET_API_MAC_OSX
1598 // this is in window relative coordinate, as this parent may have a border, its physical position is offset by this border
1599 if ( ! GetParent()->IsTopLevel() )
1600 {
1601 r.left -= GetParent()->MacGetLeftBorderSize() ;
1602 r.top -= GetParent()->MacGetTopBorderSize() ;
1603 r.right -= GetParent()->MacGetLeftBorderSize() ;
1604 r.bottom -= GetParent()->MacGetTopBorderSize() ;
1605 }
1606 #endif
1607 bool vis = m_peer->IsVisible();
1608
1609 // the HIViewSetFrame call itself should invalidate the areas, but when testing with the UnicodeTextCtrl it does not !
1610 if ( vis )
1611 m_peer->SetVisibility( false , true ) ;
1612 m_peer->SetRect( &r ) ;
1613 if ( vis )
1614 m_peer->SetVisibility( true , true ) ;
1615
1616 MacRepositionScrollBars() ;
1617 if ( doMove )
1618 {
1619 wxPoint point(actualX,actualY);
1620 wxMoveEvent event(point, m_windowId);
1621 event.SetEventObject(this);
1622 GetEventHandler()->ProcessEvent(event) ;
1623 }
1624 if ( doResize )
1625 {
1626 MacRepositionScrollBars() ;
1627 wxSize size(actualWidth, actualHeight);
1628 wxSizeEvent event(size, m_windowId);
1629 event.SetEventObject(this);
1630 GetEventHandler()->ProcessEvent(event);
1631 }
1632 }
1633
1634 }
1635
1636 wxSize wxWindowMac::DoGetBestSize() const
1637 {
1638 if ( m_macIsUserPane || IsTopLevel() )
1639 return wxWindowBase::DoGetBestSize() ;
1640
1641 Rect bestsize = { 0 , 0 , 0 , 0 } ;
1642 int bestWidth, bestHeight ;
1643 m_peer->GetBestRect( &bestsize ) ;
1644
1645 if ( EmptyRect( &bestsize ) )
1646 {
1647 bestsize.left = bestsize.top = 0 ;
1648 bestsize.right = 16 ;
1649 bestsize.bottom = 16 ;
1650 if ( IsKindOf( CLASSINFO( wxScrollBar ) ) )
1651 {
1652 bestsize.bottom = 16 ;
1653 }
1654 else if ( IsKindOf( CLASSINFO( wxSpinButton ) ) )
1655 {
1656 bestsize.bottom = 24 ;
1657 }
1658 else
1659 {
1660 // return wxWindowBase::DoGetBestSize() ;
1661 }
1662 }
1663
1664 bestWidth = bestsize.right - bestsize.left ;
1665 bestHeight = bestsize.bottom - bestsize.top ;
1666 if ( bestHeight < 10 )
1667 bestHeight = 13 ;
1668
1669 return wxSize(bestWidth, bestHeight);
1670 }
1671
1672
1673 // set the size of the window: if the dimensions are positive, just use them,
1674 // but if any of them is equal to -1, it means that we must find the value for
1675 // it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in
1676 // which case -1 is a valid value for x and y)
1677 //
1678 // If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate
1679 // the width/height to best suit our contents, otherwise we reuse the current
1680 // width/height
1681 void wxWindowMac::DoSetSize(int x, int y, int width, int height, int sizeFlags)
1682 {
1683 // get the current size and position...
1684 int currentX, currentY;
1685 GetPosition(&currentX, &currentY);
1686
1687 int currentW,currentH;
1688 GetSize(&currentW, &currentH);
1689
1690 // ... and don't do anything (avoiding flicker) if it's already ok
1691 if ( x == currentX && y == currentY &&
1692 width == currentW && height == currentH && ( height != -1 && width != -1 ) )
1693 {
1694 // TODO REMOVE
1695 MacRepositionScrollBars() ; // we might have a real position shift
1696 return;
1697 }
1698
1699 if ( x == -1 && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) )
1700 x = currentX;
1701 if ( y == -1 && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) )
1702 y = currentY;
1703
1704 AdjustForParentClientOrigin(x, y, sizeFlags);
1705
1706 wxSize size(-1, -1);
1707 if ( width == -1 )
1708 {
1709 if ( sizeFlags & wxSIZE_AUTO_WIDTH )
1710 {
1711 size = DoGetBestSize();
1712 width = size.x;
1713 }
1714 else
1715 {
1716 // just take the current one
1717 width = currentW;
1718 }
1719 }
1720
1721 if ( height == -1 )
1722 {
1723 if ( sizeFlags & wxSIZE_AUTO_HEIGHT )
1724 {
1725 if ( size.x == -1 )
1726 {
1727 size = DoGetBestSize();
1728 }
1729 //else: already called DoGetBestSize() above
1730
1731 height = size.y;
1732 }
1733 else
1734 {
1735 // just take the current one
1736 height = currentH;
1737 }
1738 }
1739
1740 DoMoveWindow(x, y, width, height);
1741
1742 }
1743
1744 wxPoint wxWindowMac::GetClientAreaOrigin() const
1745 {
1746 RgnHandle rgn = NewRgn() ;
1747 Rect content ;
1748 m_peer->GetRegion( kControlContentMetaPart , rgn ) ;
1749 GetRegionBounds( rgn , &content ) ;
1750 DisposeRgn( rgn ) ;
1751 #if !TARGET_API_MAC_OSX
1752 // if the content rgn is empty / not supported
1753 // don't attempt to correct the coordinates to wxWindow relative ones
1754 if (!::EmptyRect( &content ) )
1755 {
1756 Rect structure ;
1757 m_peer->GetRect( &structure ) ;
1758 OffsetRect( &content , -structure.left , -structure.top ) ;
1759 }
1760 #endif
1761
1762 return wxPoint( content.left + MacGetLeftBorderSize( ) , content.top + MacGetTopBorderSize( ) );
1763 }
1764
1765 void wxWindowMac::DoSetClientSize(int clientwidth, int clientheight)
1766 {
1767 if ( clientheight != -1 || clientheight != -1 )
1768 {
1769 int currentclientwidth , currentclientheight ;
1770 int currentwidth , currentheight ;
1771
1772 GetClientSize( &currentclientwidth , &currentclientheight ) ;
1773 GetSize( &currentwidth , &currentheight ) ;
1774
1775 DoSetSize( -1 , -1 , currentwidth + clientwidth - currentclientwidth ,
1776 currentheight + clientheight - currentclientheight , wxSIZE_USE_EXISTING ) ;
1777 }
1778 }
1779
1780 void wxWindowMac::SetTitle(const wxString& title)
1781 {
1782 m_label = wxStripMenuCodes(title) ;
1783
1784 if ( m_peer && m_peer->Ok() )
1785 {
1786 m_peer->SetTitle( m_label ) ;
1787 }
1788 Refresh() ;
1789 }
1790
1791 wxString wxWindowMac::GetTitle() const
1792 {
1793 return m_label ;
1794 }
1795
1796 bool wxWindowMac::Show(bool show)
1797 {
1798 if ( !wxWindowBase::Show(show) )
1799 return FALSE;
1800
1801 // TODO use visibilityChanged Carbon Event for OSX
1802 bool former = MacIsReallyShown() ;
1803
1804 m_peer->SetVisibility( show , true ) ;
1805 if ( former != MacIsReallyShown() )
1806 MacPropagateVisibilityChanged() ;
1807 return TRUE;
1808 }
1809
1810 bool wxWindowMac::Enable(bool enable)
1811 {
1812 wxASSERT( m_peer->Ok() ) ;
1813 if ( !wxWindowBase::Enable(enable) )
1814 return FALSE;
1815
1816 bool former = MacIsReallyEnabled() ;
1817 m_peer->Enable( enable ) ;
1818
1819 if ( former != MacIsReallyEnabled() )
1820 MacPropagateEnabledStateChanged() ;
1821 return TRUE;
1822 }
1823
1824 //
1825 // status change propagations (will be not necessary for OSX later )
1826 //
1827
1828 void wxWindowMac::MacPropagateVisibilityChanged()
1829 {
1830 #if !TARGET_API_MAC_OSX
1831 MacVisibilityChanged() ;
1832
1833 wxWindowListNode *node = GetChildren().GetFirst();
1834 while ( node )
1835 {
1836 wxWindowMac *child = node->GetData();
1837 if ( child->IsShown() )
1838 child->MacPropagateVisibilityChanged( ) ;
1839 node = node->GetNext();
1840 }
1841 #endif
1842 }
1843
1844 void wxWindowMac::MacPropagateEnabledStateChanged( )
1845 {
1846 #if !TARGET_API_MAC_OSX
1847 MacEnabledStateChanged() ;
1848
1849 wxWindowListNode *node = GetChildren().GetFirst();
1850 while ( node )
1851 {
1852 wxWindowMac *child = node->GetData();
1853 if ( child->IsEnabled() )
1854 child->MacPropagateEnabledStateChanged() ;
1855 node = node->GetNext();
1856 }
1857 #endif
1858 }
1859
1860 void wxWindowMac::MacPropagateHiliteChanged( )
1861 {
1862 #if !TARGET_API_MAC_OSX
1863 MacHiliteChanged() ;
1864
1865 wxWindowListNode *node = GetChildren().GetFirst();
1866 while ( node )
1867 {
1868 wxWindowMac *child = node->GetData();
1869 // if ( child->IsEnabled() )
1870 child->MacPropagateHiliteChanged() ;
1871 node = node->GetNext();
1872 }
1873 #endif
1874 }
1875
1876 //
1877 // status change notifications
1878 //
1879
1880 void wxWindowMac::MacVisibilityChanged()
1881 {
1882 }
1883
1884 void wxWindowMac::MacHiliteChanged()
1885 {
1886 }
1887
1888 void wxWindowMac::MacEnabledStateChanged()
1889 {
1890 }
1891
1892 //
1893 // status queries on the inherited window's state
1894 //
1895
1896 bool wxWindowMac::MacIsReallyShown()
1897 {
1898 // only under OSX the visibility of the TLW is taken into account
1899 #if TARGET_API_MAC_OSX
1900 if ( m_peer && m_peer->Ok() )
1901 return m_peer->IsVisible();
1902 #endif
1903 wxWindow* win = this ;
1904 while( win->IsShown() )
1905 {
1906 if ( win->IsTopLevel() )
1907 return true ;
1908
1909 win = win->GetParent() ;
1910 if ( win == NULL )
1911 return true ;
1912
1913 } ;
1914 return false ;
1915 }
1916
1917 bool wxWindowMac::MacIsReallyEnabled()
1918 {
1919 return m_peer->IsEnabled() ;
1920 }
1921
1922 bool wxWindowMac::MacIsReallyHilited()
1923 {
1924 return m_peer->IsActive();
1925 }
1926
1927 void wxWindowMac::MacFlashInvalidAreas()
1928 {
1929 #if TARGET_API_MAC_OSX
1930 HIViewFlashDirtyArea( (WindowRef) MacGetTopLevelWindowRef() ) ;
1931 #endif
1932 }
1933
1934 //
1935 //
1936 //
1937
1938 int wxWindowMac::GetCharHeight() const
1939 {
1940 wxClientDC dc ( (wxWindowMac*)this ) ;
1941 return dc.GetCharHeight() ;
1942 }
1943
1944 int wxWindowMac::GetCharWidth() const
1945 {
1946 wxClientDC dc ( (wxWindowMac*)this ) ;
1947 return dc.GetCharWidth() ;
1948 }
1949
1950 void wxWindowMac::GetTextExtent(const wxString& string, int *x, int *y,
1951 int *descent, int *externalLeading, const wxFont *theFont ) const
1952 {
1953 const wxFont *fontToUse = theFont;
1954 if ( !fontToUse )
1955 fontToUse = &m_font;
1956
1957 wxClientDC dc( (wxWindowMac*) this ) ;
1958 long lx,ly,ld,le ;
1959 dc.GetTextExtent( string , &lx , &ly , &ld, &le, (wxFont *)fontToUse ) ;
1960 if ( externalLeading )
1961 *externalLeading = le ;
1962 if ( descent )
1963 *descent = ld ;
1964 if ( x )
1965 *x = lx ;
1966 if ( y )
1967 *y = ly ;
1968 }
1969
1970 /*
1971 * Rect is given in client coordinates, for further reading, read wxTopLevelWindowMac::InvalidateRect
1972 * we always intersect with the entire window, not only with the client area
1973 */
1974
1975 void wxWindowMac::Refresh(bool eraseBack, const wxRect *rect)
1976 {
1977 if ( m_peer == NULL )
1978 return ;
1979
1980 #if TARGET_API_MAC_OSX
1981 if ( rect == NULL )
1982 m_peer->SetNeedsDisplay( true ) ;
1983 else
1984 {
1985 RgnHandle update = NewRgn() ;
1986 SetRectRgn( update , rect->x , rect->y , rect->x + rect->width , rect->y + rect->height ) ;
1987 SectRgn( (RgnHandle) MacGetVisibleRegion().GetWXHRGN() , update , update ) ;
1988 wxPoint origin = GetClientAreaOrigin() ;
1989 OffsetRgn( update, origin.x , origin.y ) ;
1990 // right now this is wx' window coordinates, as our native peer does not have borders, this is
1991 // inset
1992 OffsetRgn( update , -MacGetLeftBorderSize() , -MacGetTopBorderSize() ) ;
1993 m_peer->SetNeedsDisplay( true , update) ;
1994 DisposeRgn( update ) ;
1995 }
1996 #else
1997 /*
1998 RgnHandle updateRgn = NewRgn() ;
1999 if ( rect == NULL )
2000 {
2001 CopyRgn( (RgnHandle) MacGetVisibleRegion().GetWXHRGN() , updateRgn ) ;
2002 }
2003 else
2004 {
2005 SetRectRgn( updateRgn , rect->x , rect->y , rect->x + rect->width , rect->y + rect->height ) ;
2006 SectRgn( (RgnHandle) MacGetVisibleRegion().GetWXHRGN() , updateRgn , updateRgn ) ;
2007 }
2008 InvalWindowRgn( (WindowRef) MacGetTopLevelWindowRef() , updateRgn ) ;
2009 DisposeRgn(updateRgn) ;
2010 */
2011 if ( m_peer->IsVisible())
2012 {
2013 m_peer->SetVisibility( false , false ) ;
2014 m_peer->SetVisibility( true , true ) ;
2015 }
2016 /*
2017 if ( MacGetTopLevelWindow() == NULL )
2018 return ;
2019
2020 if ( !m_peer->IsVisible())
2021 return ;
2022
2023 wxPoint client = GetClientAreaOrigin();
2024 int x1 = -client.x;
2025 int y1 = -client.y;
2026 int x2 = m_width - client.x;
2027 int y2 = m_height - client.y;
2028
2029 if (IsKindOf( CLASSINFO(wxButton)))
2030 {
2031 // buttons have an "aura"
2032 y1 -= 5;
2033 x1 -= 5;
2034 y2 += 5;
2035 x2 += 5;
2036 }
2037
2038 Rect clientrect = { y1, x1, y2, x2 };
2039
2040 if ( rect )
2041 {
2042 Rect r = { rect->y , rect->x , rect->y + rect->height , rect->x + rect->width } ;
2043 SectRect( &clientrect , &r , &clientrect ) ;
2044 }
2045
2046 if ( !EmptyRect( &clientrect ) )
2047 {
2048 int top = 0 , left = 0 ;
2049
2050 MacClientToRootWindow( &left , &top ) ;
2051 OffsetRect( &clientrect , left , top ) ;
2052
2053 MacGetTopLevelWindow()->MacInvalidate( &clientrect , eraseBack ) ;
2054 }
2055 */
2056 #endif
2057 }
2058
2059 void wxWindowMac::Freeze()
2060 {
2061 #if TARGET_API_MAC_OSX
2062 if ( !m_frozenness++ )
2063 {
2064 m_peer->SetDrawingEnabled( false ) ;
2065 }
2066 #endif
2067 }
2068
2069
2070 void wxWindowMac::Thaw()
2071 {
2072 #if TARGET_API_MAC_OSX
2073 wxASSERT_MSG( m_frozenness > 0, _T("Thaw() without matching Freeze()") );
2074
2075 if ( !--m_frozenness )
2076 {
2077 m_peer->SetDrawingEnabled( true ) ;
2078 m_peer->InvalidateWithChildren() ;
2079 }
2080 #endif
2081 }
2082
2083 void wxWindowMac::MacRedrawControl()
2084 {
2085 /*
2086 if ( *m_peer && MacGetTopLevelWindowRef() && m_peer->IsVisible())
2087 {
2088 #if TARGET_API_MAC_CARBON
2089 Update() ;
2090 #else
2091 wxClientDC dc(this) ;
2092 wxMacPortSetter helper(&dc) ;
2093 wxMacWindowClipper clipper(this) ;
2094 wxDC::MacSetupBackgroundForCurrentPort( MacGetBackgroundBrush() ) ;
2095 UMADrawControl( *m_peer ) ;
2096 #endif
2097 }
2098 */
2099 }
2100
2101 /* TODO
2102 void wxWindowMac::OnPaint(wxPaintEvent& event)
2103 {
2104 // why don't we skip that here ?
2105 }
2106 */
2107
2108 wxWindowMac *wxGetActiveWindow()
2109 {
2110 // actually this is a windows-only concept
2111 return NULL;
2112 }
2113
2114 // Coordinates relative to the window
2115 void wxWindowMac::WarpPointer (int x_pos, int y_pos)
2116 {
2117 // We really don't move the mouse programmatically under Mac.
2118 }
2119
2120 void wxWindowMac::OnEraseBackground(wxEraseEvent& event)
2121 {
2122 #if TARGET_API_MAC_OSX
2123 if ( m_macBackgroundBrush.Ok() == false || m_macBackgroundBrush.GetStyle() == wxTRANSPARENT )
2124 {
2125 event.Skip() ;
2126 }
2127 else
2128 #endif
2129 event.GetDC()->Clear() ;
2130 }
2131
2132 void wxWindowMac::OnNcPaint( wxNcPaintEvent& event )
2133 {
2134 event.Skip() ;
2135 }
2136
2137 int wxWindowMac::GetScrollPos(int orient) const
2138 {
2139 if ( orient == wxHORIZONTAL )
2140 {
2141 if ( m_hScrollBar )
2142 return m_hScrollBar->GetThumbPosition() ;
2143 }
2144 else
2145 {
2146 if ( m_vScrollBar )
2147 return m_vScrollBar->GetThumbPosition() ;
2148 }
2149 return 0;
2150 }
2151
2152 // This now returns the whole range, not just the number
2153 // of positions that we can scroll.
2154 int wxWindowMac::GetScrollRange(int orient) const
2155 {
2156 if ( orient == wxHORIZONTAL )
2157 {
2158 if ( m_hScrollBar )
2159 return m_hScrollBar->GetRange() ;
2160 }
2161 else
2162 {
2163 if ( m_vScrollBar )
2164 return m_vScrollBar->GetRange() ;
2165 }
2166 return 0;
2167 }
2168
2169 int wxWindowMac::GetScrollThumb(int orient) const
2170 {
2171 if ( orient == wxHORIZONTAL )
2172 {
2173 if ( m_hScrollBar )
2174 return m_hScrollBar->GetThumbSize() ;
2175 }
2176 else
2177 {
2178 if ( m_vScrollBar )
2179 return m_vScrollBar->GetThumbSize() ;
2180 }
2181 return 0;
2182 }
2183
2184 void wxWindowMac::SetScrollPos(int orient, int pos, bool refresh)
2185 {
2186 if ( orient == wxHORIZONTAL )
2187 {
2188 if ( m_hScrollBar )
2189 m_hScrollBar->SetThumbPosition( pos ) ;
2190 }
2191 else
2192 {
2193 if ( m_vScrollBar )
2194 m_vScrollBar->SetThumbPosition( pos ) ;
2195 }
2196 }
2197
2198 void wxWindowMac::MacPaintBorders( int left , int top )
2199 {
2200 if( IsTopLevel() )
2201 return ;
2202
2203 Rect rect ;
2204 m_peer->GetRect( &rect ) ;
2205 InsetRect( &rect, -MacGetLeftBorderSize() , -MacGetTopBorderSize() ) ;
2206
2207 if ( !IsTopLevel() )
2208 {
2209 wxTopLevelWindowMac* top = MacGetTopLevelWindow();
2210 if (top)
2211 {
2212 wxPoint pt(0,0) ;
2213 wxMacControl::Convert( &pt , GetParent()->m_peer , top->m_peer ) ;
2214 rect.left += pt.x ;
2215 rect.right += pt.x ;
2216 rect.top += pt.y ;
2217 rect.bottom += pt.y ;
2218 }
2219 }
2220
2221 if (HasFlag(wxRAISED_BORDER) || HasFlag( wxSUNKEN_BORDER) || HasFlag(wxDOUBLE_BORDER) )
2222 {
2223 Rect srect = rect ;
2224 SInt32 border = 0 ;
2225 GetThemeMetric( kThemeMetricEditTextFrameOutset , &border ) ;
2226 InsetRect( &srect , border , border );
2227 DrawThemeEditTextFrame(&srect,IsEnabled() ? kThemeStateActive : kThemeStateInactive) ;
2228 }
2229 else if (HasFlag(wxSIMPLE_BORDER))
2230 {
2231 Rect srect = rect ;
2232 SInt32 border = 0 ;
2233 GetThemeMetric( kThemeMetricListBoxFrameOutset , &border ) ;
2234 InsetRect( &srect , border , border );
2235 DrawThemeListBoxFrame(&rect,IsEnabled() ? kThemeStateActive : kThemeStateInactive) ;
2236 }
2237 }
2238
2239 void wxWindowMac::RemoveChild( wxWindowBase *child )
2240 {
2241 if ( child == m_hScrollBar )
2242 m_hScrollBar = NULL ;
2243 if ( child == m_vScrollBar )
2244 m_vScrollBar = NULL ;
2245
2246 wxWindowBase::RemoveChild( child ) ;
2247 }
2248
2249 // New function that will replace some of the above.
2250 void wxWindowMac::SetScrollbar(int orient, int pos, int thumbVisible,
2251 int range, bool refresh)
2252 {
2253 if ( orient == wxHORIZONTAL )
2254 {
2255 if ( m_hScrollBar )
2256 {
2257 if ( range == 0 || thumbVisible >= range )
2258 {
2259 if ( m_hScrollBar->IsShown() )
2260 m_hScrollBar->Show(false) ;
2261 }
2262 else
2263 {
2264 if ( !m_hScrollBar->IsShown() )
2265 m_hScrollBar->Show(true) ;
2266 m_hScrollBar->SetScrollbar( pos , thumbVisible , range , thumbVisible , refresh ) ;
2267 }
2268 }
2269 }
2270 else
2271 {
2272 if ( m_vScrollBar )
2273 {
2274 if ( range == 0 || thumbVisible >= range )
2275 {
2276 if ( m_vScrollBar->IsShown() )
2277 m_vScrollBar->Show(false) ;
2278 }
2279 else
2280 {
2281 if ( !m_vScrollBar->IsShown() )
2282 m_vScrollBar->Show(true) ;
2283 m_vScrollBar->SetScrollbar( pos , thumbVisible , range , thumbVisible , refresh ) ;
2284 }
2285 }
2286 }
2287 MacRepositionScrollBars() ;
2288 }
2289
2290 // Does a physical scroll
2291 void wxWindowMac::ScrollWindow(int dx, int dy, const wxRect *rect)
2292 {
2293 if( dx == 0 && dy ==0 )
2294 return ;
2295
2296
2297 {
2298
2299 int width , height ;
2300 GetClientSize( &width , &height ) ;
2301 #if TARGET_API_MAC_OSX
2302 // note there currently is a bug in OSX which makes inefficient refreshes in case an entire control
2303 // area is scrolled, this does not occur if width and height are 2 pixels less,
2304 // TODO write optimal workaround
2305 wxRect scrollrect( MacGetLeftBorderSize() , MacGetTopBorderSize() , width , height ) ;
2306 if ( rect )
2307 {
2308 scrollrect.Intersect( *rect ) ;
2309 }
2310 if ( m_peer->GetNeedsDisplay() )
2311 {
2312 // becuase HIViewScrollRect does not scroll the already invalidated area we have two options
2313 // either immediate redraw or full invalidate
2314 #if 1
2315 // is the better overall solution, as it does not slow down scrolling
2316 m_peer->SetNeedsDisplay( true ) ;
2317 #else
2318 // this would be the preferred version for fast drawing controls
2319 if( UMAGetSystemVersion() < 0x1030 )
2320 Update() ;
2321 else
2322 HIViewRender(m_peer->GetControlRef()) ;
2323 #endif
2324 }
2325 // as the native control might be not a 0/0 wx window coordinates, we have to offset
2326 scrollrect.Offset( -MacGetLeftBorderSize() , -MacGetTopBorderSize() ) ;
2327 m_peer->ScrollRect( scrollrect , dx , dy ) ;
2328 #else
2329
2330 wxPoint pos;
2331 pos.x = pos.y = 0;
2332
2333 Rect scrollrect;
2334 RgnHandle updateRgn = NewRgn() ;
2335
2336 {
2337 wxClientDC dc(this) ;
2338 wxMacPortSetter helper(&dc) ;
2339
2340 m_peer->GetRect( &scrollrect ) ;
2341 scrollrect.top += MacGetTopBorderSize() ;
2342 scrollrect.left += MacGetLeftBorderSize() ;
2343 scrollrect.bottom = scrollrect.top + height ;
2344 scrollrect.right = scrollrect.left + width ;
2345
2346 if ( rect )
2347 {
2348 Rect r = { dc.YLOG2DEVMAC(rect->y) , dc.XLOG2DEVMAC(rect->x) , dc.YLOG2DEVMAC(rect->y + rect->height) ,
2349 dc.XLOG2DEVMAC(rect->x + rect->width) } ;
2350 SectRect( &scrollrect , &r , &scrollrect ) ;
2351 }
2352 ScrollRect( &scrollrect , dx , dy , updateRgn ) ;
2353 }
2354 // ScrollWindowRect( (WindowRef) MacGetTopLevelWindowRef() , &scrollrect , dx , dy , kScrollWindowInvalidate, updateRgn ) ;
2355 #endif
2356 }
2357
2358 for (wxWindowListNode *node = GetChildren().GetFirst(); node; node = node->GetNext())
2359 {
2360 wxWindowMac *child = node->GetData();
2361 if (child == m_vScrollBar) continue;
2362 if (child == m_hScrollBar) continue;
2363 if (child->IsTopLevel()) continue;
2364
2365 int x,y;
2366 child->GetPosition( &x, &y );
2367 int w,h;
2368 child->GetSize( &w, &h );
2369 if (rect)
2370 {
2371 wxRect rc(x,y,w,h);
2372 if (rect->Intersects(rc))
2373 child->SetSize( x+dx, y+dy, w, h );
2374 }
2375 else
2376 {
2377 child->SetSize( x+dx, y+dy, w, h );
2378 }
2379 }
2380 }
2381
2382 void wxWindowMac::MacOnScroll(wxScrollEvent &event )
2383 {
2384 if ( event.m_eventObject == m_vScrollBar || event.m_eventObject == m_hScrollBar )
2385 {
2386 wxScrollWinEvent wevent;
2387 wevent.SetPosition(event.GetPosition());
2388 wevent.SetOrientation(event.GetOrientation());
2389 wevent.m_eventObject = this;
2390
2391 if (event.m_eventType == wxEVT_SCROLL_TOP)
2392 wevent.m_eventType = wxEVT_SCROLLWIN_TOP;
2393 else if (event.m_eventType == wxEVT_SCROLL_BOTTOM)
2394 wevent.m_eventType = wxEVT_SCROLLWIN_BOTTOM;
2395 else if (event.m_eventType == wxEVT_SCROLL_LINEUP)
2396 wevent.m_eventType = wxEVT_SCROLLWIN_LINEUP;
2397 else if (event.m_eventType == wxEVT_SCROLL_LINEDOWN)
2398 wevent.m_eventType = wxEVT_SCROLLWIN_LINEDOWN;
2399 else if (event.m_eventType == wxEVT_SCROLL_PAGEUP)
2400 wevent.m_eventType = wxEVT_SCROLLWIN_PAGEUP;
2401 else if (event.m_eventType == wxEVT_SCROLL_PAGEDOWN)
2402 wevent.m_eventType = wxEVT_SCROLLWIN_PAGEDOWN;
2403 else if (event.m_eventType == wxEVT_SCROLL_THUMBTRACK)
2404 wevent.m_eventType = wxEVT_SCROLLWIN_THUMBTRACK;
2405 else if (event.m_eventType == wxEVT_SCROLL_THUMBRELEASE)
2406 wevent.m_eventType = wxEVT_SCROLLWIN_THUMBRELEASE;
2407
2408 GetEventHandler()->ProcessEvent(wevent);
2409 }
2410 }
2411
2412 // Get the window with the focus
2413 wxWindowMac *wxWindowBase::FindFocus()
2414 {
2415 ControlRef control ;
2416 GetKeyboardFocus( GetUserFocusWindow() , &control ) ;
2417 return wxFindControlFromMacControl( control ) ;
2418 }
2419
2420 void wxWindowMac::OnSetFocus(wxFocusEvent& event)
2421 {
2422 // panel wants to track the window which was the last to have focus in it,
2423 // so we want to set ourselves as the window which last had focus
2424 //
2425 // notice that it's also important to do it upwards the tree becaus
2426 // otherwise when the top level panel gets focus, it won't set it back to
2427 // us, but to some other sibling
2428
2429 // CS:don't know if this is still needed:
2430 //wxChildFocusEvent eventFocus(this);
2431 //(void)GetEventHandler()->ProcessEvent(eventFocus);
2432
2433 if ( MacGetTopLevelWindow() && m_peer->NeedsFocusRect() )
2434 {
2435 wxMacWindowStateSaver sv( this ) ;
2436
2437 int w , h ;
2438 int x , y ;
2439 x = y = 0 ;
2440 MacWindowToRootWindow( &x , &y ) ;
2441 GetSize( &w , &h ) ;
2442 Rect rect = {y , x , h + y , w + x } ;
2443
2444 if ( event.GetEventType() == wxEVT_SET_FOCUS )
2445 DrawThemeFocusRect( &rect , true ) ;
2446 else
2447 {
2448 DrawThemeFocusRect( &rect , false ) ;
2449
2450 // as this erases part of the frame we have to redraw borders
2451 // and because our z-ordering is not always correct (staticboxes)
2452 // we have to invalidate things, we cannot simple redraw
2453 RgnHandle updateInner = NewRgn() , updateOuter = NewRgn() ;
2454 RectRgn( updateInner , &rect ) ;
2455 InsetRect( &rect , -4 , -4 ) ;
2456 RectRgn( updateOuter , &rect ) ;
2457 DiffRgn( updateOuter , updateInner ,updateOuter ) ;
2458 wxPoint parent(0,0);
2459 GetParent()->MacWindowToRootWindow( &parent.x , &parent.y ) ;
2460 parent -= GetParent()->GetClientAreaOrigin() ;
2461 OffsetRgn( updateOuter , -parent.x , -parent.y ) ;
2462 GetParent()->m_peer->SetNeedsDisplay( true , updateOuter ) ;
2463 DisposeRgn(updateOuter) ;
2464 DisposeRgn(updateInner) ;
2465 }
2466 }
2467
2468 event.Skip();
2469 }
2470
2471 void wxWindowMac::OnInternalIdle()
2472 {
2473 // This calls the UI-update mechanism (querying windows for
2474 // menu/toolbar/control state information)
2475 if (wxUpdateUIEvent::CanUpdate(this))
2476 UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
2477 }
2478
2479 // Raise the window to the top of the Z order
2480 void wxWindowMac::Raise()
2481 {
2482 m_peer->SetZOrder( true , NULL ) ;
2483 }
2484
2485 // Lower the window to the bottom of the Z order
2486 void wxWindowMac::Lower()
2487 {
2488 m_peer->SetZOrder( false , NULL ) ;
2489 }
2490
2491
2492 // static wxWindow *gs_lastWhich = NULL;
2493
2494 bool wxWindowMac::MacSetupCursor( const wxPoint& pt)
2495 {
2496 // first trigger a set cursor event
2497
2498 wxPoint clientorigin = GetClientAreaOrigin() ;
2499 wxSize clientsize = GetClientSize() ;
2500 wxCursor cursor ;
2501 if ( wxRect2DInt( clientorigin.x , clientorigin.y , clientsize.x , clientsize.y ).Contains( wxPoint2DInt( pt ) ) )
2502 {
2503 wxSetCursorEvent event( pt.x , pt.y );
2504
2505 bool processedEvtSetCursor = GetEventHandler()->ProcessEvent(event);
2506 if ( processedEvtSetCursor && event.HasCursor() )
2507 {
2508 cursor = event.GetCursor() ;
2509 }
2510 else
2511 {
2512
2513 // the test for processedEvtSetCursor is here to prevent using m_cursor
2514 // if the user code caught EVT_SET_CURSOR() and returned nothing from
2515 // it - this is a way to say that our cursor shouldn't be used for this
2516 // point
2517 if ( !processedEvtSetCursor && m_cursor.Ok() )
2518 {
2519 cursor = m_cursor ;
2520 }
2521 if ( wxIsBusy() )
2522 {
2523 }
2524 else
2525 {
2526 if ( !GetParent() )
2527 cursor = *wxSTANDARD_CURSOR ;
2528 }
2529 }
2530 if ( cursor.Ok() )
2531 cursor.MacInstall() ;
2532 }
2533 return cursor.Ok() ;
2534 }
2535
2536 wxString wxWindowMac::MacGetToolTipString( wxPoint &pt )
2537 {
2538 if ( m_tooltip )
2539 {
2540 return m_tooltip->GetTip() ;
2541 }
2542 return wxEmptyString ;
2543 }
2544
2545 void wxWindowMac::Update()
2546 {
2547 #if TARGET_API_MAC_OSX
2548 WindowRef window = (WindowRef)MacGetTopLevelWindowRef() ;
2549 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3
2550 // for composited windows this also triggers a redraw of all
2551 // invalid views in the window
2552 if( UMAGetSystemVersion() >= 0x1030 )
2553 HIWindowFlush(window) ;
2554 else
2555 #endif
2556 {
2557 // the only way to trigger the redrawing on earlier systems is to call
2558 // ReceiveNextEvent
2559
2560 EventRef currentEvent = (EventRef) wxTheApp->MacGetCurrentEvent() ;
2561 UInt32 currentEventClass = 0 ;
2562 UInt32 currentEventKind = 0 ;
2563 if ( currentEvent != NULL )
2564 {
2565 currentEventClass = ::GetEventClass( currentEvent ) ;
2566 currentEventKind = ::GetEventKind( currentEvent ) ;
2567 }
2568 if ( currentEventClass != kEventClassMenu )
2569 {
2570 // when tracking a menu, strange redraw errors occur if we flush now, so leave..
2571
2572 EventRef theEvent;
2573 OSStatus status = noErr ;
2574 status = ReceiveNextEvent( 0 , NULL , kEventDurationNoWait , false , &theEvent ) ;
2575 }
2576 else
2577 m_peer->SetNeedsDisplay( true ) ;
2578 }
2579 #else
2580 ::Draw1Control( m_peer->GetControlRef() ) ;
2581 #endif
2582 }
2583
2584 wxTopLevelWindowMac* wxWindowMac::MacGetTopLevelWindow() const
2585 {
2586 wxTopLevelWindowMac* win = NULL ;
2587 WindowRef window = (WindowRef) MacGetTopLevelWindowRef() ;
2588 if ( window )
2589 {
2590 win = wxFindWinFromMacWindow( window ) ;
2591 }
2592 return win ;
2593 }
2594 wxRegion wxWindowMac::MacGetVisibleRegion( bool includeOuterStructures )
2595 {
2596 // includeOuterStructures is true if we try to draw somthing like a focus ring etc.
2597 // also a window dc uses this, in this case we only clip in the hierarchy for hard
2598 // borders like a scrollwindow, splitter etc otherwise we end up in a paranoia having
2599 // to add focus borders everywhere
2600
2601 Rect r ;
2602 RgnHandle visRgn = NewRgn() ;
2603 RgnHandle tempRgn = NewRgn() ;
2604 if ( m_peer->IsVisible())
2605 {
2606 m_peer->GetRect( &r ) ;
2607 r.left -= MacGetLeftBorderSize() ;
2608 r.top -= MacGetTopBorderSize() ;
2609 r.bottom += MacGetBottomBorderSize() ;
2610 r.right += MacGetRightBorderSize() ;
2611
2612 if (! MacGetTopLevelWindow()->MacUsesCompositing() )
2613 {
2614 MacRootWindowToWindow( &r.left , & r.top ) ;
2615 MacRootWindowToWindow( &r.right , & r.bottom ) ;
2616 }
2617 else
2618 {
2619 r.right -= r.left ;
2620 r.bottom -= r.top ;
2621 r.left = 0 ;
2622 r.top = 0 ;
2623 }
2624 if ( includeOuterStructures )
2625 InsetRect( &r , -4 , -4 ) ;
2626 RectRgn( visRgn , &r ) ;
2627
2628 if ( !IsTopLevel() )
2629 {
2630 wxWindow* child = this ;
2631 wxWindow* parent = child->GetParent() ;
2632 while( parent )
2633 {
2634 int x , y ;
2635 wxSize size ;
2636 // we have to find a better clipping algorithm here, in order not to clip things
2637 // positioned like status and toolbar
2638 if ( 1 /* parent->IsTopLevel() && child->IsKindOf( CLASSINFO( wxToolBar ) ) */ )
2639 {
2640 size = parent->GetSize() ;
2641 x = y = 0 ;
2642 }
2643 else
2644 {
2645 size = parent->GetClientSize() ;
2646 wxPoint origin = parent->GetClientAreaOrigin() ;
2647 x = origin.x ;
2648 y = origin.y ;
2649 }
2650 parent->MacWindowToRootWindow( &x, &y ) ;
2651 MacRootWindowToWindow( &x , &y ) ;
2652
2653 if ( !includeOuterStructures || (
2654 parent->IsKindOf( CLASSINFO( wxScrolledWindow ) ) ||
2655 parent->IsKindOf( CLASSINFO( wxSashLayoutWindow ) ) ||
2656 ( parent->GetParent() && parent->GetParent()->IsKindOf( CLASSINFO( wxSplitterWindow ) ) )
2657 ) )
2658 {
2659 SetRectRgn( tempRgn ,
2660 x + parent->MacGetLeftBorderSize() , y + parent->MacGetTopBorderSize() ,
2661 x + size.x - parent->MacGetRightBorderSize(),
2662 y + size.y - parent->MacGetBottomBorderSize()) ;
2663
2664 SectRgn( visRgn , tempRgn , visRgn ) ;
2665 }
2666 if ( parent->IsTopLevel() )
2667 break ;
2668 child = parent ;
2669 parent = child->GetParent() ;
2670 }
2671 }
2672 }
2673
2674 wxRegion vis = visRgn ;
2675 DisposeRgn( visRgn ) ;
2676 DisposeRgn( tempRgn ) ;
2677 return vis ;
2678 }
2679
2680 /*
2681 This function must not change the updatergn !
2682 */
2683 bool wxWindowMac::MacDoRedraw( WXHRGN updatergnr , long time )
2684 {
2685 RgnHandle updatergn = (RgnHandle) updatergnr ;
2686 bool handled = false ;
2687 Rect updatebounds ;
2688 GetRegionBounds( updatergn , &updatebounds ) ;
2689 // wxLogDebug("update for %s bounds %d , %d , %d , %d",typeid(*this).name() , updatebounds.left , updatebounds.top , updatebounds.right , updatebounds.bottom ) ;
2690 if ( !EmptyRgn(updatergn) )
2691 {
2692 RgnHandle newupdate = NewRgn() ;
2693 wxSize point = GetClientSize() ;
2694 wxPoint origin = GetClientAreaOrigin() ;
2695 SetRectRgn( newupdate , origin.x , origin.y , origin.x + point.x , origin.y+point.y ) ;
2696 SectRgn( newupdate , updatergn , newupdate ) ;
2697
2698 // first send an erase event to the entire update area
2699 {
2700 wxWindowDC dc(this);
2701 dc.SetClippingRegion(wxRegion(updatergn));
2702 wxEraseEvent eevent( GetId(), &dc );
2703 eevent.SetEventObject( this );
2704 GetEventHandler()->ProcessEvent( eevent );
2705 }
2706
2707 // calculate a client-origin version of the update rgn and set m_updateRegion to that
2708 OffsetRgn( newupdate , -origin.x , -origin.y ) ;
2709 m_updateRegion = newupdate ;
2710 DisposeRgn( newupdate ) ;
2711
2712 if ( !m_updateRegion.Empty() )
2713 {
2714 // paint the window itself
2715 wxPaintEvent event;
2716 event.m_timeStamp = time ;
2717 event.SetEventObject(this);
2718 handled = GetEventHandler()->ProcessEvent(event);
2719
2720 // we have to call the default built-in handler, as otherwise our frames will be drawn and immediately erased afterwards
2721 if ( !handled )
2722 {
2723 if ( wxTheApp->MacGetCurrentEvent() != NULL && wxTheApp->MacGetCurrentEventHandlerCallRef() != NULL )
2724 {
2725 CallNextEventHandler((EventHandlerCallRef)wxTheApp->MacGetCurrentEventHandlerCallRef() , (EventRef) wxTheApp->MacGetCurrentEvent() ) ;
2726 handled = true ;
2727 }
2728 }
2729
2730 }
2731
2732 // now we cannot rely on having its borders drawn by a window itself, as it does not
2733 // get the updateRgn wide enough to always do so, so we do it from the parent
2734 // this would also be the place to draw any custom backgrounds for native controls
2735 // in Composited windowing
2736 wxPoint clientOrigin = GetClientAreaOrigin() ;
2737
2738 for (wxWindowListNode *node = GetChildren().GetFirst(); node; node = node->GetNext())
2739 {
2740 wxWindowMac *child = node->GetData();
2741 if (child == m_vScrollBar) continue;
2742 if (child == m_hScrollBar) continue;
2743 if (child->IsTopLevel()) continue;
2744 if (!child->IsShown()) continue;
2745
2746 int x,y;
2747 child->GetPosition( &x, &y );
2748 int w,h;
2749 child->GetSize( &w, &h );
2750 Rect childRect = { y , x , y + h , x + w } ;
2751 OffsetRect( &childRect , clientOrigin.x , clientOrigin.y ) ;
2752 if ( child->MacGetTopBorderSize() )
2753 {
2754 if ( RectInRgn( &childRect , updatergn ) )
2755 {
2756 // paint custom borders
2757 wxNcPaintEvent eventNc( child->GetId() );
2758 eventNc.SetEventObject( child );
2759 if ( !child->GetEventHandler()->ProcessEvent( eventNc ) )
2760 {
2761 wxWindowDC dc(this) ;
2762 dc.SetClippingRegion(wxRegion(updatergn));
2763 wxMacPortSetter helper(&dc) ;
2764 child->MacPaintBorders( dc.m_macLocalOrigin.x + childRect.left , dc.m_macLocalOrigin.y + childRect.top) ;
2765 }
2766 }
2767 }
2768 if ( child->m_peer->NeedsFocusRect() && child->m_peer->HasFocus() )
2769 {
2770 wxWindowDC dc(this) ;
2771 dc.SetClippingRegion(wxRegion(updatergn));
2772 wxMacPortSetter helper(&dc) ;
2773 OffsetRect( &childRect , dc.m_macLocalOrigin.x , dc.m_macLocalOrigin.y ) ;
2774 DrawThemeFocusRect( &childRect , true ) ;
2775 }
2776 }
2777 }
2778 return handled ;
2779 }
2780
2781 void wxWindowMac::MacRedraw( WXHRGN updatergnr , long time, bool erase)
2782 {
2783 RgnHandle updatergn = (RgnHandle) updatergnr ;
2784 // updatergn is always already clipped to our boundaries
2785 // if we are in compositing mode then it is in relative to the upper left of the control
2786 // if we are in non-compositing, then it is relatvie to the uppder left of the content area
2787 // of the toplevel window
2788 // it is in window coordinates, not in client coordinates
2789
2790 // ownUpdateRgn is the area that this window has to repaint, it is in window coordinates
2791 RgnHandle ownUpdateRgn = NewRgn() ;
2792 CopyRgn( updatergn , ownUpdateRgn ) ;
2793
2794 if ( MacGetTopLevelWindow()->MacUsesCompositing() == false )
2795 {
2796 Rect bounds;
2797 m_peer->GetRectInWindowCoords( &bounds );
2798 RgnHandle controlRgn = NewRgn();
2799 RectRgn( controlRgn, &bounds );
2800 //KO: This sets the ownUpdateRgn to the area of this control that is inside
2801 // the window update region
2802 SectRgn( ownUpdateRgn, controlRgn, ownUpdateRgn );
2803 DisposeRgn( controlRgn );
2804
2805 //KO: convert ownUpdateRgn to local coordinates
2806 OffsetRgn( ownUpdateRgn, -bounds.left, -bounds.top );
2807 }
2808
2809 MacDoRedraw( ownUpdateRgn , time ) ;
2810 DisposeRgn( ownUpdateRgn ) ;
2811
2812 }
2813
2814 WXWindow wxWindowMac::MacGetTopLevelWindowRef() const
2815 {
2816 wxWindowMac *iter = (wxWindowMac*)this ;
2817
2818 while( iter )
2819 {
2820 if ( iter->IsTopLevel() )
2821 return ((wxTopLevelWindow*)iter)->MacGetWindowRef() ;
2822
2823 iter = iter->GetParent() ;
2824 }
2825 wxASSERT_MSG( 1 , wxT("No valid mac root window") ) ;
2826 return NULL ;
2827 }
2828
2829 void wxWindowMac::MacCreateScrollBars( long style )
2830 {
2831 wxASSERT_MSG( m_vScrollBar == NULL && m_hScrollBar == NULL , wxT("attempt to create window twice") ) ;
2832
2833 if ( style & ( wxVSCROLL | wxHSCROLL ) )
2834 {
2835 bool hasBoth = ( style & wxVSCROLL ) && ( style & wxHSCROLL ) ;
2836 int scrlsize = MAC_SCROLLBAR_SIZE ;
2837 wxWindowVariant variant = wxWINDOW_VARIANT_NORMAL ;
2838 if ( GetWindowVariant() == wxWINDOW_VARIANT_SMALL || GetWindowVariant() == wxWINDOW_VARIANT_MINI )
2839 {
2840 scrlsize = MAC_SMALL_SCROLLBAR_SIZE ;
2841 variant = wxWINDOW_VARIANT_SMALL ;
2842 }
2843
2844 int adjust = hasBoth ? scrlsize - 1: 0 ;
2845 int width, height ;
2846 GetClientSize( &width , &height ) ;
2847
2848 wxPoint vPoint(width-scrlsize, 0) ;
2849 wxSize vSize(scrlsize, height - adjust) ;
2850 wxPoint hPoint(0 , height-scrlsize ) ;
2851 wxSize hSize( width - adjust, scrlsize) ;
2852
2853
2854 if ( style & wxVSCROLL )
2855 {
2856 m_vScrollBar = new wxScrollBar(this, wxWINDOW_VSCROLL, vPoint,
2857 vSize , wxVERTICAL);
2858 }
2859
2860 if ( style & wxHSCROLL )
2861 {
2862 m_hScrollBar = new wxScrollBar(this, wxWINDOW_HSCROLL, hPoint,
2863 hSize , wxHORIZONTAL);
2864 }
2865 }
2866
2867
2868 // because the create does not take into account the client area origin
2869 MacRepositionScrollBars() ; // we might have a real position shift
2870 }
2871
2872 void wxWindowMac::MacRepositionScrollBars()
2873 {
2874 if ( !m_hScrollBar && !m_vScrollBar )
2875 return ;
2876
2877 bool hasBoth = ( m_hScrollBar && m_hScrollBar->IsShown()) && ( m_vScrollBar && m_vScrollBar->IsShown()) ;
2878 int scrlsize = m_hScrollBar ? m_hScrollBar->GetSize().y : ( m_vScrollBar ? m_vScrollBar->GetSize().x : MAC_SCROLLBAR_SIZE ) ;
2879 int adjust = hasBoth ? scrlsize - 1 : 0 ;
2880
2881 // get real client area
2882
2883 int width ;
2884 int height ;
2885 GetSize( &width , &height ) ;
2886
2887 width -= MacGetLeftBorderSize() + MacGetRightBorderSize();
2888 height -= MacGetTopBorderSize() + MacGetBottomBorderSize();
2889
2890 wxPoint vPoint(width-MAC_SCROLLBAR_SIZE, 0) ;
2891 wxSize vSize(MAC_SCROLLBAR_SIZE, height - adjust) ;
2892 wxPoint hPoint(0 , height-MAC_SCROLLBAR_SIZE ) ;
2893 wxSize hSize( width - adjust, MAC_SCROLLBAR_SIZE) ;
2894 /*
2895 int x = 0 ;
2896 int y = 0 ;
2897 int w ;
2898 int h ;
2899 GetSize( &w , &h ) ;
2900
2901 MacClientToRootWindow( &x , &y ) ;
2902 MacClientToRootWindow( &w , &h ) ;
2903
2904 wxWindowMac *iter = (wxWindowMac*)this ;
2905
2906 int totW = 10000 , totH = 10000;
2907 while( iter )
2908 {
2909 if ( iter->IsTopLevel() )
2910 {
2911 iter->GetSize( &totW , &totH ) ;
2912 break ;
2913 }
2914
2915 iter = iter->GetParent() ;
2916 }
2917
2918 if ( x == 0 )
2919 {
2920 hPoint.x = -1 ;
2921 hSize.x += 1 ;
2922 }
2923 if ( y == 0 )
2924 {
2925 vPoint.y = -1 ;
2926 vSize.y += 1 ;
2927 }
2928
2929 if ( w-x >= totW )
2930 {
2931 hSize.x += 1 ;
2932 vPoint.x += 1 ;
2933 }
2934
2935 if ( h-y >= totH )
2936 {
2937 vSize.y += 1 ;
2938 hPoint.y += 1 ;
2939 }
2940 */
2941 if ( m_vScrollBar )
2942 {
2943 m_vScrollBar->SetSize( vPoint.x , vPoint.y, vSize.x, vSize.y , wxSIZE_ALLOW_MINUS_ONE);
2944 }
2945 if ( m_hScrollBar )
2946 {
2947 m_hScrollBar->SetSize( hPoint.x , hPoint.y, hSize.x, hSize.y, wxSIZE_ALLOW_MINUS_ONE);
2948 }
2949 }
2950
2951 bool wxWindowMac::AcceptsFocus() const
2952 {
2953 return MacCanFocus() && wxWindowBase::AcceptsFocus();
2954 }
2955
2956 void wxWindowMac::MacSuperChangedPosition()
2957 {
2958 // only window-absolute structures have to be moved i.e. controls
2959
2960 wxWindowListNode *node = GetChildren().GetFirst();
2961 while ( node )
2962 {
2963 wxWindowMac *child = node->GetData();
2964 child->MacSuperChangedPosition() ;
2965 node = node->GetNext();
2966 }
2967 }
2968
2969 void wxWindowMac::MacTopLevelWindowChangedPosition()
2970 {
2971 // only screen-absolute structures have to be moved i.e. glcanvas
2972
2973 wxWindowListNode *node = GetChildren().GetFirst();
2974 while ( node )
2975 {
2976 wxWindowMac *child = node->GetData();
2977 child->MacTopLevelWindowChangedPosition() ;
2978 node = node->GetNext();
2979 }
2980 }
2981
2982 long wxWindowMac::MacGetLeftBorderSize( ) const
2983 {
2984 if( IsTopLevel() )
2985 return 0 ;
2986
2987 if (m_windowStyle & wxRAISED_BORDER || m_windowStyle & wxSUNKEN_BORDER )
2988 {
2989 SInt32 border = 3 ;
2990 return border ;
2991 }
2992 else if ( m_windowStyle &wxDOUBLE_BORDER)
2993 {
2994 SInt32 border = 3 ;
2995 return border ;
2996 }
2997 else if (m_windowStyle &wxSIMPLE_BORDER)
2998 {
2999 return 1 ;
3000 }
3001 return 0 ;
3002 }
3003
3004 long wxWindowMac::MacGetRightBorderSize( ) const
3005 {
3006 // they are all symmetric in mac themes
3007 return MacGetLeftBorderSize() ;
3008 }
3009
3010 long wxWindowMac::MacGetTopBorderSize( ) const
3011 {
3012 // they are all symmetric in mac themes
3013 return MacGetLeftBorderSize() ;
3014 }
3015
3016 long wxWindowMac::MacGetBottomBorderSize( ) const
3017 {
3018 // they are all symmetric in mac themes
3019 return MacGetLeftBorderSize() ;
3020 }
3021
3022 long wxWindowMac::MacRemoveBordersFromStyle( long style )
3023 {
3024 return style & ~wxBORDER_MASK ;
3025 }
3026
3027 // Find the wxWindowMac at the current mouse position, returning the mouse
3028 // position.
3029 wxWindowMac* wxFindWindowAtPointer(wxPoint& pt)
3030 {
3031 pt = wxGetMousePosition();
3032 wxWindowMac* found = wxFindWindowAtPoint(pt);
3033 return found;
3034 }
3035
3036 // Get the current mouse position.
3037 wxPoint wxGetMousePosition()
3038 {
3039 int x, y;
3040 wxGetMousePosition(& x, & y);
3041 return wxPoint(x, y);
3042 }
3043
3044 void wxWindowMac::OnMouseEvent( wxMouseEvent &event )
3045 {
3046 if ( event.GetEventType() == wxEVT_RIGHT_DOWN )
3047 {
3048 // copied from wxGTK : CS
3049 // generate a "context menu" event: this is similar to wxEVT_RIGHT_DOWN
3050 // except that:
3051 //
3052 // (a) it's a command event and so is propagated to the parent
3053 // (b) under MSW it can be generated from kbd too
3054 // (c) it uses screen coords (because of (a))
3055 wxContextMenuEvent evtCtx(wxEVT_CONTEXT_MENU,
3056 this->GetId(),
3057 this->ClientToScreen(event.GetPosition()));
3058 if ( ! GetEventHandler()->ProcessEvent(evtCtx) )
3059 event.Skip() ;
3060 }
3061 else
3062 {
3063 event.Skip() ;
3064 }
3065 }
3066
3067 void wxWindowMac::MacHandleControlClick( WXWidget control , wxInt16 controlpart , bool WXUNUSED( mouseStillDown ) )
3068 {
3069 }
3070
3071 Rect wxMacGetBoundsForControl( wxWindow* window , const wxPoint& pos , const wxSize &size , bool adjustForOrigin )
3072 {
3073 int x ,y , w ,h ;
3074
3075 window->MacGetBoundsForControl( pos , size , x , y, w, h , adjustForOrigin) ;
3076 Rect bounds = { y , x , y+h , x+w };
3077 return bounds ;
3078 }
3079
3080 wxInt32 wxWindowMac::MacControlHit(WXEVENTHANDLERREF WXUNUSED(handler) , WXEVENTREF WXUNUSED(event) )
3081 {
3082 return eventNotHandledErr ;
3083 }
3084
3085