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