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