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