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