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