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