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