]> git.saurik.com Git - wxWidgets.git/blame - src/osx/carbon/window.cpp
wrong override params
[wxWidgets.git] / src / osx / carbon / window.cpp
CommitLineData
489468fe 1/////////////////////////////////////////////////////////////////////////////
524c47aa 2// Name: src/osx/carbon/window.cpp
489468fe
SC
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
b2680ced 64#if wxOSX_USE_CARBON
1f0c8f31 65#include "wx/osx/uma.h"
b2680ced
SC
66#else
67#include "wx/osx/private.h"
524c47aa
SC
68// bring in themeing
69#include <Carbon/Carbon.h>
b2680ced 70#endif
489468fe
SC
71
72#define MAC_SCROLLBAR_SIZE 15
73#define MAC_SMALL_SCROLLBAR_SIZE 11
74
75#include <string.h>
76
524c47aa
SC
77#define wxMAC_DEBUG_REDRAW 0
78#ifndef wxMAC_DEBUG_REDRAW
79#define wxMAC_DEBUG_REDRAW 0
489468fe 80#endif
b2680ced 81
f06e0fea
SC
82// Get the window with the focus
83WXWidget wxWidgetImpl::FindFocus()
84{
85 ControlRef control = NULL ;
86 GetKeyboardFocus( GetUserFocusWindow() , &control ) ;
87 return control;
88}
89
b2680ced
SC
90// ---------------------------------------------------------------------------
91// Carbon Events
92// ---------------------------------------------------------------------------
489468fe 93
b2680ced
SC
94static const EventTypeSpec eventList[] =
95{
96 { kEventClassCommand, kEventProcessCommand } ,
97 { kEventClassCommand, kEventCommandUpdateStatus } ,
489468fe 98
b2680ced
SC
99 { kEventClassControl , kEventControlGetClickActivation } ,
100 { kEventClassControl , kEventControlHit } ,
489468fe 101
b2680ced
SC
102 { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent } ,
103 { kEventClassTextInput, kEventTextInputUpdateActiveInputArea } ,
489468fe 104
b2680ced 105 { kEventClassControl , kEventControlDraw } ,
489468fe 106
b2680ced
SC
107 { kEventClassControl , kEventControlVisibilityChanged } ,
108 { kEventClassControl , kEventControlEnabledStateChanged } ,
109 { kEventClassControl , kEventControlHiliteChanged } ,
489468fe 110
b2680ced
SC
111 { kEventClassControl , kEventControlActivate } ,
112 { kEventClassControl , kEventControlDeactivate } ,
489468fe 113
b2680ced
SC
114 { kEventClassControl , kEventControlSetFocusPart } ,
115 { kEventClassControl , kEventControlFocusPartChanged } ,
489468fe 116
b2680ced
SC
117 { kEventClassService , kEventServiceGetTypes },
118 { kEventClassService , kEventServiceCopy },
119 { kEventClassService , kEventServicePaste },
489468fe 120
b2680ced
SC
121// { kEventClassControl , kEventControlInvalidateForSizeChange } , // 10.3 only
122// { kEventClassControl , kEventControlBoundsChanged } ,
123} ;
124
125static pascal OSStatus wxMacWindowControlEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
489468fe 126{
b2680ced
SC
127 OSStatus result = eventNotHandledErr ;
128 static wxWindowMac* targetFocusWindow = NULL;
129 static wxWindowMac* formerFocusWindow = NULL;
489468fe 130
b2680ced 131 wxMacCarbonEvent cEvent( event ) ;
489468fe 132
b2680ced
SC
133 ControlRef controlRef ;
134 wxWindowMac* thisWindow = (wxWindowMac*) data ;
135
136 cEvent.GetParameter( kEventParamDirectObject , &controlRef ) ;
489468fe 137
b2680ced 138 switch ( GetEventKind( event ) )
489468fe 139 {
b2680ced
SC
140 case kEventControlDraw :
141 {
5398a2e0
SC
142 HIShapeRef updateRgn = NULL ;
143 HIMutableShapeRef allocatedRgn = NULL ;
b2680ced 144 wxRegion visRegion = thisWindow->MacGetVisibleRegion() ;
489468fe 145
5398a2e0
SC
146 // according to the docs: redraw entire control if param not present
147 if ( cEvent.GetParameter<HIShapeRef>(kEventParamShape, &updateRgn) != noErr )
b2680ced 148 {
5398a2e0 149 updateRgn = visRegion.GetWXHRGN();
b2680ced
SC
150 }
151 else
152 {
153 if ( thisWindow->MacGetLeftBorderSize() != 0 || thisWindow->MacGetTopBorderSize() != 0 )
154 {
155 // as this update region is in native window locals we must adapt it to wx window local
5398a2e0
SC
156 allocatedRgn = HIShapeCreateMutableCopy(updateRgn);
157 HIShapeOffset(allocatedRgn, thisWindow->MacGetLeftBorderSize() , thisWindow->MacGetTopBorderSize());
b2680ced 158 // hide the given region by the new region that must be shifted
b2680ced
SC
159 updateRgn = allocatedRgn ;
160 }
161 }
489468fe 162
b2680ced
SC
163#if wxMAC_DEBUG_REDRAW
164 if ( thisWindow->MacIsUserPane() )
165 {
166 static float color = 0.5 ;
167 static int channel = 0 ;
168 HIRect bounds;
169 CGContextRef cgContext = cEvent.GetParameter<CGContextRef>(kEventParamCGContextRef) ;
489468fe 170
b2680ced
SC
171 HIViewGetBounds( controlRef, &bounds );
172 CGContextSetRGBFillColor( cgContext, channel == 0 ? color : 0.5 ,
173 channel == 1 ? color : 0.5 , channel == 2 ? color : 0.5 , 1 );
174 CGContextFillRect( cgContext, bounds );
175 color += 0.1 ;
176 if ( color > 0.9 )
177 {
178 color = 0.5 ;
179 channel++ ;
180 if ( channel == 3 )
181 channel = 0 ;
182 }
183 }
489468fe 184#endif
489468fe 185
b2680ced
SC
186 {
187 bool created = false ;
188 CGContextRef cgContext = NULL ;
189 OSStatus err = cEvent.GetParameter<CGContextRef>(kEventParamCGContextRef, &cgContext) ;
190 if ( err != noErr )
191 {
192 wxFAIL_MSG("Unable to retrieve CGContextRef");
193 }
489468fe 194
b2680ced 195 thisWindow->MacSetCGContextRef( cgContext ) ;
489468fe 196
b2680ced
SC
197 {
198 wxMacCGContextStateSaver sg( cgContext ) ;
199 CGFloat alpha = (CGFloat)1.0 ;
200 {
201 wxWindow* iter = thisWindow ;
202 while ( iter )
203 {
204 alpha *= (CGFloat)( iter->GetTransparent()/255.0 ) ;
205 if ( iter->IsTopLevel() )
206 iter = NULL ;
207 else
208 iter = iter->GetParent() ;
209 }
210 }
211 CGContextSetAlpha( cgContext , alpha ) ;
489468fe 212
b2680ced
SC
213 if ( thisWindow->GetBackgroundStyle() == wxBG_STYLE_TRANSPARENT )
214 {
215 HIRect bounds;
216 HIViewGetBounds( controlRef, &bounds );
217 CGContextClearRect( cgContext, bounds );
218 }
489468fe 219
5398a2e0
SC
220 if ( !HIShapeIsEmpty(updateRgn) )
221 {
222 // refcount increase because wxRegion constructor takes ownership of the native region
223 CFRetain(updateRgn);
224 thisWindow->GetUpdateRegion() = wxRegion(updateRgn);
225 if ( !thisWindow->MacDoRedraw( cEvent.GetTicks() ) )
226 {
227 // for native controls: call their native paint method
228 if ( !thisWindow->MacIsUserPane() ||
229 ( thisWindow->IsTopLevel() && thisWindow->GetBackgroundStyle() == wxBG_STYLE_SYSTEM ) )
230 {
231 if ( thisWindow->GetBackgroundStyle() != wxBG_STYLE_TRANSPARENT )
232 CallNextEventHandler( handler ,event ) ;
233 }
234 }
235 thisWindow->MacPaintChildrenBorders();
236 }
b2680ced
SC
237 thisWindow->MacSetCGContextRef( NULL ) ;
238 }
489468fe 239
b2680ced
SC
240 if ( created )
241 CGContextRelease( cgContext ) ;
242 }
489468fe 243
b2680ced 244 if ( allocatedRgn )
5398a2e0 245 CFRelease( allocatedRgn ) ;
b2680ced
SC
246 }
247 break ;
489468fe 248
b2680ced
SC
249 case kEventControlVisibilityChanged :
250 // we might have two native controls attributed to the same wxWindow instance
251 // eg a scrollview and an embedded textview, make sure we only fire for the 'outer'
252 // control, as otherwise native and wx visibility are different
253 if ( thisWindow->GetPeer() != NULL && thisWindow->GetPeer()->GetControlRef() == controlRef )
254 {
255 thisWindow->MacVisibilityChanged() ;
256 }
257 break ;
489468fe 258
b2680ced
SC
259 case kEventControlEnabledStateChanged :
260 thisWindow->MacEnabledStateChanged();
261 break ;
489468fe 262
b2680ced
SC
263 case kEventControlHiliteChanged :
264 thisWindow->MacHiliteChanged() ;
265 break ;
489468fe 266
b2680ced
SC
267 case kEventControlActivate :
268 case kEventControlDeactivate :
269 // FIXME: we should have a virtual function for this!
270#if wxUSE_TREECTRL
271 if ( thisWindow->IsKindOf( CLASSINFO( wxTreeCtrl ) ) )
272 thisWindow->Refresh();
273#endif
274#if wxUSE_LISTCTRL
275 if ( thisWindow->IsKindOf( CLASSINFO( wxListCtrl ) ) )
276 thisWindow->Refresh();
277#endif
278 break ;
279
280 //
281 // focus handling
282 // different handling on OS X
283 //
284
285 case kEventControlFocusPartChanged :
286 // the event is emulated by wxmac for systems lower than 10.5
287 {
288 if ( UMAGetSystemVersion() < 0x1050 )
289 {
290 // as it is synthesized here, we have to manually avoid propagation
291 result = noErr;
292 }
293 ControlPartCode previousControlPart = cEvent.GetParameter<ControlPartCode>(kEventParamControlPreviousPart , typeControlPartCode );
294 ControlPartCode currentControlPart = cEvent.GetParameter<ControlPartCode>(kEventParamControlCurrentPart , typeControlPartCode );
295
296 if ( thisWindow->MacGetTopLevelWindow() && thisWindow->GetPeer()->NeedsFocusRect() )
297 {
298 thisWindow->MacInvalidateBorders();
299 }
300
301 if ( currentControlPart == 0 )
302 {
303 // kill focus
304#if wxUSE_CARET
305 if ( thisWindow->GetCaret() )
306 thisWindow->GetCaret()->OnKillFocus();
307#endif
308
5c33522f 309 wxLogTrace(_T("Focus"), _T("focus lost(%p)"), static_cast<void*>(thisWindow));
c016394b 310
b2680ced
SC
311 // remove this as soon as posting the synthesized event works properly
312 static bool inKillFocusEvent = false ;
313
314 if ( !inKillFocusEvent )
315 {
316 inKillFocusEvent = true ;
317 wxFocusEvent event( wxEVT_KILL_FOCUS, thisWindow->GetId());
318 event.SetEventObject(thisWindow);
319 event.SetWindow(targetFocusWindow);
320 thisWindow->HandleWindowEvent(event) ;
321 inKillFocusEvent = false ;
322 targetFocusWindow = NULL;
323 }
324 }
325 else if ( previousControlPart == 0 )
326 {
327 // set focus
328 // panel wants to track the window which was the last to have focus in it
5c33522f 329 wxLogTrace(_T("Focus"), _T("focus set(%p)"), static_cast<void*>(thisWindow));
b2680ced
SC
330 wxChildFocusEvent eventFocus((wxWindow*)thisWindow);
331 thisWindow->HandleWindowEvent(eventFocus);
332
333#if wxUSE_CARET
334 if ( thisWindow->GetCaret() )
335 thisWindow->GetCaret()->OnSetFocus();
336#endif
337
338 wxFocusEvent event(wxEVT_SET_FOCUS, thisWindow->GetId());
339 event.SetEventObject(thisWindow);
340 event.SetWindow(formerFocusWindow);
341 thisWindow->HandleWindowEvent(event) ;
342 formerFocusWindow = NULL;
343 }
344 }
345 break;
346 case kEventControlSetFocusPart :
347 {
348 Boolean focusEverything = false ;
349 if ( cEvent.GetParameter<Boolean>(kEventParamControlFocusEverything , &focusEverything ) == noErr )
350 {
351 // put a breakpoint here to catch focus everything events
352 }
353 ControlPartCode controlPart = cEvent.GetParameter<ControlPartCode>(kEventParamControlPart , typeControlPartCode );
354 if ( controlPart != kControlFocusNoPart )
355 {
356 targetFocusWindow = thisWindow;
5c33522f 357 wxLogTrace(_T("Focus"), _T("focus to be set(%p)"), static_cast<void*>(thisWindow));
b2680ced
SC
358 }
359 else
360 {
361 formerFocusWindow = thisWindow;
5c33522f 362 wxLogTrace(_T("Focus"), _T("focus to be lost(%p)"), static_cast<void*>(thisWindow));
b2680ced
SC
363 }
364
365 ControlPartCode previousControlPart = 0;
366 verify_noerr( HIViewGetFocusPart(controlRef, &previousControlPart));
367
368 if ( thisWindow->MacIsUserPane() )
369 {
370 if ( controlPart != kControlFocusNoPart )
371 cEvent.SetParameter<ControlPartCode>( kEventParamControlPart, typeControlPartCode, 1 ) ;
372 result = noErr ;
373 }
374 else
375 result = CallNextEventHandler(handler, event);
376
377 if ( UMAGetSystemVersion() < 0x1050 )
378 {
379// set back to 0 if problems arise
380#if 1
381 if ( result == noErr )
382 {
383 ControlPartCode currentControlPart = cEvent.GetParameter<ControlPartCode>(kEventParamControlPart , typeControlPartCode );
384 // synthesize the event focus changed event
385 EventRef evRef = NULL ;
386
387 OSStatus err = MacCreateEvent(
388 NULL , kEventClassControl , kEventControlFocusPartChanged , TicksToEventTime( TickCount() ) ,
389 kEventAttributeUserEvent , &evRef );
390 verify_noerr( err );
391
392 wxMacCarbonEvent iEvent( evRef ) ;
393 iEvent.SetParameter<ControlRef>( kEventParamDirectObject , controlRef );
394 iEvent.SetParameter<EventTargetRef>( kEventParamPostTarget, typeEventTargetRef, GetControlEventTarget( controlRef ) );
395 iEvent.SetParameter<ControlPartCode>( kEventParamControlPreviousPart, typeControlPartCode, previousControlPart );
396 iEvent.SetParameter<ControlPartCode>( kEventParamControlCurrentPart, typeControlPartCode, currentControlPart );
397
489468fe 398#if 1
b2680ced
SC
399 // TODO test this first, avoid double posts etc...
400 PostEventToQueue( GetMainEventQueue(), evRef , kEventPriorityHigh );
489468fe 401#else
b2680ced
SC
402 wxMacWindowControlEventHandler( NULL , evRef , data ) ;
403#endif
404 ReleaseEvent( evRef ) ;
405 }
406#else
407 // old implementation, to be removed if the new one works
408 if ( controlPart == kControlFocusNoPart )
409 {
410#if wxUSE_CARET
411 if ( thisWindow->GetCaret() )
412 thisWindow->GetCaret()->OnKillFocus();
489468fe 413#endif
489468fe 414
5c33522f 415 wxLogTrace(_T("Focus"), _T("focus lost(%p)"), static_cast<void*>(thisWindow));
489468fe 416
b2680ced
SC
417 static bool inKillFocusEvent = false ;
418
419 if ( !inKillFocusEvent )
420 {
421 inKillFocusEvent = true ;
422 wxFocusEvent event( wxEVT_KILL_FOCUS, thisWindow->GetId());
423 event.SetEventObject(thisWindow);
424 thisWindow->HandleWindowEvent(event) ;
425 inKillFocusEvent = false ;
426 }
427 }
428 else
429 {
430 // panel wants to track the window which was the last to have focus in it
5c33522f 431 wxLogTrace(_T("Focus"), _T("focus set(%p)"), static_cast<void*>(thisWindow));
b2680ced
SC
432 wxChildFocusEvent eventFocus((wxWindow*)thisWindow);
433 thisWindow->HandleWindowEvent(eventFocus);
434
435 #if wxUSE_CARET
436 if ( thisWindow->GetCaret() )
437 thisWindow->GetCaret()->OnSetFocus();
438 #endif
439
440 wxFocusEvent event(wxEVT_SET_FOCUS, thisWindow->GetId());
441 event.SetEventObject(thisWindow);
442 thisWindow->HandleWindowEvent(event) ;
443 }
489468fe 444#endif
b2680ced
SC
445 }
446 }
447 break ;
448
449 case kEventControlHit :
450 result = thisWindow->MacControlHit( handler , event ) ;
451 break ;
452
453 case kEventControlGetClickActivation :
454 {
455 // fix to always have a proper activation for DataBrowser controls (stay in bkgnd otherwise)
456 WindowRef owner = cEvent.GetParameter<WindowRef>(kEventParamWindowRef);
457 if ( !IsWindowActive(owner) )
458 {
cf1c280f 459 cEvent.SetParameter(kEventParamClickActivation,typeClickActivationResult, (UInt32) kActivateAndIgnoreClick) ;
b2680ced
SC
460 result = noErr ;
461 }
462 }
463 break ;
464
465 default :
466 break ;
489468fe
SC
467 }
468
b2680ced
SC
469 return result ;
470}
471
472static pascal OSStatus
473wxMacWindowServiceEventHandler(EventHandlerCallRef WXUNUSED(handler),
474 EventRef event,
475 void *data)
476{
477 OSStatus result = eventNotHandledErr ;
478
479 wxMacCarbonEvent cEvent( event ) ;
480
481 ControlRef controlRef ;
482 wxWindowMac* thisWindow = (wxWindowMac*) data ;
483 wxTextCtrl* textCtrl = wxDynamicCast( thisWindow , wxTextCtrl ) ;
484 cEvent.GetParameter( kEventParamDirectObject , &controlRef ) ;
485
486 switch ( GetEventKind( event ) )
489468fe 487 {
b2680ced
SC
488 case kEventServiceGetTypes :
489 if ( textCtrl )
490 {
491 long from, to ;
492 textCtrl->GetSelection( &from , &to ) ;
489468fe 493
b2680ced
SC
494 CFMutableArrayRef copyTypes = 0 , pasteTypes = 0;
495 if ( from != to )
496 copyTypes = cEvent.GetParameter< CFMutableArrayRef >( kEventParamServiceCopyTypes , typeCFMutableArrayRef ) ;
497 if ( textCtrl->IsEditable() )
498 pasteTypes = cEvent.GetParameter< CFMutableArrayRef >( kEventParamServicePasteTypes , typeCFMutableArrayRef ) ;
499
500 static const OSType textDataTypes[] = { kTXNTextData /* , 'utxt', 'PICT', 'MooV', 'AIFF' */ };
501 for ( size_t i = 0 ; i < WXSIZEOF(textDataTypes) ; ++i )
502 {
503 CFStringRef typestring = CreateTypeStringWithOSType(textDataTypes[i]);
504 if ( typestring )
505 {
506 if ( copyTypes )
507 CFArrayAppendValue(copyTypes, typestring) ;
508 if ( pasteTypes )
509 CFArrayAppendValue(pasteTypes, typestring) ;
510
511 CFRelease( typestring ) ;
512 }
513 }
514
515 result = noErr ;
516 }
517 break ;
518
519 case kEventServiceCopy :
520 if ( textCtrl )
521 {
522 long from, to ;
523
524 textCtrl->GetSelection( &from , &to ) ;
525 wxString val = textCtrl->GetValue() ;
526 val = val.Mid( from , to - from ) ;
527 PasteboardRef pasteboard = cEvent.GetParameter<PasteboardRef>( kEventParamPasteboardRef, typePasteboardRef );
528 verify_noerr( PasteboardClear( pasteboard ) ) ;
529 PasteboardSynchronize( pasteboard );
530 // TODO add proper conversion
531 CFDataRef data = CFDataCreate( kCFAllocatorDefault, (const UInt8*)val.c_str(), val.length() );
532 PasteboardPutItemFlavor( pasteboard, (PasteboardItemID) 1, CFSTR("com.apple.traditional-mac-plain-text"), data, 0);
533 CFRelease( data );
534 result = noErr ;
535 }
536 break ;
537
538 case kEventServicePaste :
539 if ( textCtrl )
540 {
541 PasteboardRef pasteboard = cEvent.GetParameter<PasteboardRef>( kEventParamPasteboardRef, typePasteboardRef );
542 PasteboardSynchronize( pasteboard );
543 ItemCount itemCount;
544 verify_noerr( PasteboardGetItemCount( pasteboard, &itemCount ) );
545 for( UInt32 itemIndex = 1; itemIndex <= itemCount; itemIndex++ )
546 {
547 PasteboardItemID itemID;
548 if ( PasteboardGetItemIdentifier( pasteboard, itemIndex, &itemID ) == noErr )
549 {
550 CFDataRef flavorData = NULL;
551 if ( PasteboardCopyItemFlavorData( pasteboard, itemID, CFSTR("com.apple.traditional-mac-plain-text"), &flavorData ) == noErr )
552 {
553 CFIndex flavorDataSize = CFDataGetLength( flavorData );
554 char *content = new char[flavorDataSize+1] ;
555 memcpy( content, CFDataGetBytePtr( flavorData ), flavorDataSize );
556 content[flavorDataSize]=0;
557 CFRelease( flavorData );
558#if wxUSE_UNICODE
559 textCtrl->WriteText( wxString( content , wxConvLocal ) );
560#else
561 textCtrl->WriteText( wxString( content ) ) ;
562#endif
563
564 delete[] content ;
565 result = noErr ;
566 }
567 }
568 }
569 }
570 break ;
571
572 default:
573 break ;
489468fe 574 }
b2680ced
SC
575
576 return result ;
489468fe
SC
577}
578
b2680ced 579pascal OSStatus wxMacUnicodeTextEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
489468fe 580{
b2680ced
SC
581 OSStatus result = eventNotHandledErr ;
582 wxWindowMac* focus = (wxWindowMac*) data ;
583
584 wchar_t* uniChars = NULL ;
585 UInt32 when = EventTimeToTicks( GetEventTime( event ) ) ;
586
587 UniChar* charBuf = NULL;
588 ByteCount dataSize = 0 ;
589 int numChars = 0 ;
590 UniChar buf[2] ;
591 if ( GetEventParameter( event, kEventParamTextInputSendText, typeUnicodeText, NULL, 0 , &dataSize, NULL ) == noErr )
489468fe 592 {
b2680ced
SC
593 numChars = dataSize / sizeof( UniChar) + 1;
594 charBuf = buf ;
489468fe 595
b2680ced
SC
596 if ( (size_t) numChars * 2 > sizeof(buf) )
597 charBuf = new UniChar[ numChars ] ;
598 else
599 charBuf = buf ;
600
601 uniChars = new wchar_t[ numChars ] ;
602 GetEventParameter( event, kEventParamTextInputSendText, typeUnicodeText, NULL, dataSize , NULL , charBuf ) ;
603 charBuf[ numChars - 1 ] = 0;
604#if SIZEOF_WCHAR_T == 2
605 uniChars = (wchar_t*) charBuf ;
606/* 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...)
607#else
608 // the resulting string will never have more chars than the utf16 version, so this is safe
609 wxMBConvUTF16 converter ;
610 numChars = converter.MB2WC( uniChars , (const char*)charBuf , numChars ) ;
611#endif
612 }
613
614 switch ( GetEventKind( event ) )
615 {
616 case kEventTextInputUpdateActiveInputArea :
617 {
618 // An IME input event may return several characters, but we need to send one char at a time to
619 // EVT_CHAR
620 for (int pos=0 ; pos < numChars ; pos++)
621 {
622 WXEVENTREF formerEvent = wxTheApp->MacGetCurrentEvent() ;
623 WXEVENTHANDLERCALLREF formerHandler = wxTheApp->MacGetCurrentEventHandlerCallRef() ;
624 wxTheApp->MacSetCurrentEvent( event , handler ) ;
625
626 UInt32 message = uniChars[pos] < 128 ? (char)uniChars[pos] : '?';
627/*
628 NB: faking a charcode here is problematic. The kEventTextInputUpdateActiveInputArea event is sent
629 multiple times to update the active range during inline input, so this handler will often receive
630 uncommited text, which should usually not trigger side effects. It might be a good idea to check the
631 kEventParamTextInputSendFixLen parameter and verify if input is being confirmed (see CarbonEvents.h).
632 On the other hand, it can be useful for some applications to react to uncommitted text (for example,
633 to update a status display), as long as it does not disrupt the inline input session. Ideally, wx
634 should add new event types to support advanced text input. For now, I would keep things as they are.
635
636 However, the code that was being used caused additional problems:
637 UInt32 message = (0 << 8) + ((char)uniChars[pos] );
638 Since it simply truncated the unichar to the last byte, it ended up causing weird bugs with inline
639 input, such as switching to another field when one attempted to insert the character U+4E09 (the kanji
640 for "three"), because it was truncated to 09 (kTabCharCode), which was later "converted" to WXK_TAB
641 (still 09) in wxMacTranslateKey; or triggering the default button when one attempted to insert U+840D
642 (the kanji for "name"), which got truncated to 0D and interpreted as a carriage return keypress.
643 Note that even single-byte characters could have been misinterpreted, since MacRoman charcodes only
644 overlap with Unicode within the (7-bit) ASCII range.
645 But simply passing a NUL charcode would disable text updated events, because wxTextCtrl::OnChar checks
646 for codes within a specific range. Therefore I went for the solution seen above, which keeps ASCII
647 characters as they are and replaces the rest with '?', ensuring that update events are triggered.
648 It would be better to change wxTextCtrl::OnChar to look at the actual unicode character instead, but
649 I don't have time to look into that right now.
650 -- CL
651*/
652 if ( wxTheApp->MacSendCharEvent(
653 focus , message , 0 , when , 0 , 0 , uniChars[pos] ) )
654 {
655 result = noErr ;
656 }
657
658 wxTheApp->MacSetCurrentEvent( formerEvent , formerHandler ) ;
659 }
660 }
661 break ;
662 case kEventTextInputUnicodeForKeyEvent :
663 {
664 UInt32 keyCode, modifiers ;
665 Point point ;
666 EventRef rawEvent ;
667 unsigned char charCode ;
668
669 GetEventParameter( event, kEventParamTextInputSendKeyboardEvent, typeEventRef, NULL, sizeof(rawEvent), NULL, &rawEvent ) ;
670 GetEventParameter( rawEvent, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &charCode );
671 GetEventParameter( rawEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode );
672 GetEventParameter( rawEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers );
673 GetEventParameter( rawEvent, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &point );
674
675 UInt32 message = (keyCode << 8) + charCode;
489468fe 676
b2680ced
SC
677 // An IME input event may return several characters, but we need to send one char at a time to
678 // EVT_CHAR
679 for (int pos=0 ; pos < numChars ; pos++)
680 {
681 WXEVENTREF formerEvent = wxTheApp->MacGetCurrentEvent() ;
682 WXEVENTHANDLERCALLREF formerHandler = wxTheApp->MacGetCurrentEventHandlerCallRef() ;
683 wxTheApp->MacSetCurrentEvent( event , handler ) ;
684
685 if ( wxTheApp->MacSendCharEvent(
686 focus , message , modifiers , when , point.h , point.v , uniChars[pos] ) )
687 {
688 result = noErr ;
689 }
690
691 wxTheApp->MacSetCurrentEvent( formerEvent , formerHandler ) ;
692 }
693 }
694 break;
695 default:
696 break ;
489468fe 697 }
489468fe 698
b2680ced
SC
699 delete [] uniChars ;
700 if ( charBuf != buf )
701 delete [] charBuf ;
489468fe 702
b2680ced 703 return result ;
489468fe
SC
704}
705
b2680ced
SC
706static pascal OSStatus
707wxMacWindowCommandEventHandler(EventHandlerCallRef WXUNUSED(handler),
708 EventRef event,
709 void *data)
489468fe 710{
b2680ced
SC
711 OSStatus result = eventNotHandledErr ;
712 wxWindowMac* focus = (wxWindowMac*) data ;
489468fe 713
b2680ced 714 HICommand command ;
489468fe 715
b2680ced
SC
716 wxMacCarbonEvent cEvent( event ) ;
717 cEvent.GetParameter<HICommand>(kEventParamDirectObject,typeHICommand,&command) ;
489468fe 718
b2680ced
SC
719 wxMenuItem* item = NULL ;
720 wxMenu* itemMenu = wxFindMenuFromMacCommand( command , item ) ;
489468fe 721
b2680ced 722 if ( item )
489468fe 723 {
b2680ced 724 wxASSERT( itemMenu != NULL ) ;
489468fe 725
b2680ced 726 switch ( cEvent.GetKind() )
489468fe 727 {
b2680ced 728 case kEventProcessCommand :
524c47aa
SC
729 if ( itemMenu->HandleCommandProcess( item, focus ) )
730 result = noErr;
b2680ced 731 break ;
489468fe 732
b2680ced 733 case kEventCommandUpdateStatus:
524c47aa
SC
734 if ( itemMenu->HandleCommandUpdateStatus( item, focus ) )
735 result = noErr;
b2680ced 736 break ;
489468fe 737
b2680ced
SC
738 default :
739 break ;
740 }
489468fe 741 }
b2680ced 742 return result ;
489468fe
SC
743}
744
b2680ced 745pascal OSStatus wxMacWindowEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
489468fe 746{
b2680ced
SC
747 EventRef formerEvent = (EventRef) wxTheApp->MacGetCurrentEvent() ;
748 EventHandlerCallRef formerEventHandlerCallRef = (EventHandlerCallRef) wxTheApp->MacGetCurrentEventHandlerCallRef() ;
749 wxTheApp->MacSetCurrentEvent( event , handler ) ;
750 OSStatus result = eventNotHandledErr ;
489468fe 751
b2680ced
SC
752 switch ( GetEventClass( event ) )
753 {
754 case kEventClassCommand :
755 result = wxMacWindowCommandEventHandler( handler , event , data ) ;
756 break ;
489468fe 757
b2680ced
SC
758 case kEventClassControl :
759 result = wxMacWindowControlEventHandler( handler, event, data ) ;
760 break ;
489468fe 761
b2680ced
SC
762 case kEventClassService :
763 result = wxMacWindowServiceEventHandler( handler, event , data ) ;
764 break ;
489468fe 765
b2680ced
SC
766 case kEventClassTextInput :
767 result = wxMacUnicodeTextEventHandler( handler , event , data ) ;
768 break ;
489468fe 769
b2680ced
SC
770 default :
771 break ;
772 }
489468fe 773
b2680ced 774 wxTheApp->MacSetCurrentEvent( formerEvent, formerEventHandlerCallRef ) ;
489468fe 775
b2680ced 776 return result ;
489468fe
SC
777}
778
b2680ced 779DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacWindowEventHandler )
489468fe 780
b2680ced
SC
781// ---------------------------------------------------------------------------
782// Scrollbar Tracking for all
783// ---------------------------------------------------------------------------
489468fe 784
b2680ced
SC
785pascal void wxMacLiveScrollbarActionProc( ControlRef control , ControlPartCode partCode ) ;
786pascal void wxMacLiveScrollbarActionProc( ControlRef control , ControlPartCode partCode )
489468fe 787{
b2680ced 788 if ( partCode != 0)
489468fe 789 {
b2680ced
SC
790 wxWindow* wx = wxFindWindowFromWXWidget( (WXWidget) control ) ;
791 if ( wx )
19c7ac3d
SC
792 {
793 wxEventType scrollEvent = wxEVT_NULL;
794 switch ( partCode )
795 {
796 case kControlUpButtonPart:
797 scrollEvent = wxEVT_SCROLL_LINEUP;
798 break;
799
800 case kControlDownButtonPart:
801 scrollEvent = wxEVT_SCROLL_LINEDOWN;
802 break;
803
804 case kControlPageUpPart:
805 scrollEvent = wxEVT_SCROLL_PAGEUP;
806 break;
807
808 case kControlPageDownPart:
809 scrollEvent = wxEVT_SCROLL_PAGEDOWN;
810 break;
811
812 case kControlIndicatorPart:
813 scrollEvent = wxEVT_SCROLL_THUMBTRACK;
814 // when this is called as a live proc, mouse is always still down
815 // so no need for thumbrelease
816 // scrollEvent = wxEVT_SCROLL_THUMBRELEASE;
817 break;
818 }
819 wx->TriggerScrollEvent(scrollEvent) ;
820 }
489468fe
SC
821 }
822}
b2680ced 823wxMAC_DEFINE_PROC_GETTER( ControlActionUPP , wxMacLiveScrollbarActionProc ) ;
489468fe 824
a4fec5b4
SC
825wxWidgetImplType* wxWidgetImpl::CreateUserPane( wxWindowMac* wxpeer,
826 wxWindowMac* WXUNUSED(parent),
827 wxWindowID WXUNUSED(id),
828 const wxPoint& pos,
829 const wxSize& size,
830 long WXUNUSED(style),
831 long WXUNUSED(extraStyle))
489468fe 832{
b2680ced
SC
833 OSStatus err = noErr;
834 Rect bounds = wxMacGetBoundsForControl( wxpeer , pos , size ) ;
835 wxMacControl* c = new wxMacControl(wxpeer) ;
836 UInt32 features = 0
837 | kControlSupportsEmbedding
838 | kControlSupportsLiveFeedback
839 | kControlGetsFocusOnClick
840// | kControlHasSpecialBackground
841// | kControlSupportsCalcBestRect
842 | kControlHandlesTracking
843 | kControlSupportsFocus
844 | kControlWantsActivate
845 | kControlWantsIdle ;
489468fe 846
b2680ced
SC
847 err =::CreateUserPaneControl( MAC_WXHWND(wxpeer->GetParent()->MacGetTopLevelWindowRef()) , &bounds, features , c->GetControlRefAddr() );
848 verify_noerr( err );
849 return c;
850}
489468fe 851
489468fe 852
f55d9f74 853void wxMacControl::InstallEventHandler( WXWidget control )
b2680ced 854{
f55d9f74
SC
855 wxWidgetImpl::Associate( control ? control : (WXWidget) m_controlRef , this ) ;
856 ::InstallControlEventHandler( control ? (ControlRef) control : m_controlRef , GetwxMacWindowEventHandlerUPP(),
857 GetEventTypeCount(eventList), eventList, GetWXPeer(), NULL);
489468fe
SC
858}
859
b2680ced
SC
860IMPLEMENT_DYNAMIC_CLASS( wxMacControl , wxWidgetImpl )
861
862wxMacControl::wxMacControl()
489468fe 863{
b2680ced
SC
864 Init();
865}
489468fe 866
b2680ced
SC
867wxMacControl::wxMacControl(wxWindowMac* peer , bool isRootControl ) :
868 wxWidgetImpl( peer, isRootControl )
869{
870 Init();
871}
489468fe 872
b2680ced
SC
873wxMacControl::~wxMacControl()
874{
524c47aa
SC
875 if ( m_controlRef && !IsRootControl() )
876 {
877 wxASSERT_MSG( m_controlRef != NULL , wxT("Control Handle already NULL, Dispose called twice ?") );
878 wxASSERT_MSG( IsValidControlHandle(m_controlRef) , wxT("Invalid Control Handle (maybe already released) in Dispose") );
489468fe 879
f55d9f74 880 wxWidgetImpl::RemoveAssociations( this ) ;
524c47aa
SC
881 // we cannot check the ref count here anymore, as autorelease objects might delete their refs later
882 // we can have situations when being embedded, where the control gets deleted behind our back, so only
883 // CFRelease if we are safe
884 if ( IsValidControlHandle(m_controlRef) )
885 CFRelease(m_controlRef);
886 }
b2680ced 887 m_controlRef = NULL;
b2680ced 888}
489468fe 889
524c47aa 890void wxMacControl::Init()
b2680ced 891{
b2680ced 892 m_controlRef = NULL;
524c47aa 893 m_macControlEventHandler = NULL;
b2680ced 894}
489468fe 895
b2680ced
SC
896void wxMacControl::RemoveFromParent()
897{
898 // nothing to do here for carbon
c4825ef7 899 HIViewRemoveFromSuperview(m_controlRef);
b2680ced 900}
489468fe 901
b2680ced
SC
902void wxMacControl::Embed( wxWidgetImpl *parent )
903{
bd412bc6 904 HIViewAddSubview((ControlRef)parent->GetWXWidget(), m_controlRef);
b2680ced 905}
489468fe 906
b2680ced
SC
907void wxMacControl::SetNeedsDisplay( const wxRect* rect )
908{
909 if ( !IsVisible() )
910 return;
489468fe 911
b2680ced
SC
912 if ( rect != NULL )
913 {
914 HIRect updatearea = CGRectMake( rect->x , rect->y , rect->width , rect->height);
915 HIViewSetNeedsDisplayInRect( m_controlRef, &updatearea, true );
916 }
917 else
918 HIViewSetNeedsDisplay( m_controlRef , true );
919}
489468fe 920
b2680ced
SC
921void wxMacControl::Raise()
922{
923 verify_noerr( HIViewSetZOrder( m_controlRef, kHIViewZOrderAbove, NULL ) );
924}
925
926void wxMacControl::Lower()
927{
928 verify_noerr( HIViewSetZOrder( m_controlRef, kHIViewZOrderBelow, NULL ) );
929}
489468fe 930
b2680ced
SC
931void wxMacControl::GetContentArea(int &left , int &top , int &width , int &height) const
932{
f215225d
SC
933 HIShapeRef rgn = NULL;
934 Rect content ;
935
936 if ( HIViewCopyShape(m_controlRef, kHIViewContentMetaPart, &rgn) == noErr)
937 {
938 CGRect cgrect;
939 HIShapeGetBounds(rgn, &cgrect);
940 content = (Rect){ cgrect.origin.y, cgrect.origin.x, cgrect.origin.y+cgrect.size.height, cgrect.origin.x+cgrect.size.width };
941 CFRelease(rgn);
942 }
b2680ced 943 else
524c47aa 944 {
f215225d 945 GetControlBounds(m_controlRef, &content);
524c47aa
SC
946 content.right -= content.left;
947 content.left = 0;
948 content.bottom -= content.top;
949 content.top = 0;
950 }
489468fe 951
b2680ced
SC
952 left = content.left;
953 top = content.top;
489468fe 954
b2680ced
SC
955 width = content.right - content.left ;
956 height = content.bottom - content.top ;
957}
958
959void wxMacControl::Move(int x, int y, int width, int height)
960{
961 HIRect hir = CGRectMake(x,y,width,height);
962 HIViewSetFrame ( m_controlRef , &hir );
489468fe
SC
963}
964
b2680ced
SC
965void wxMacControl::GetPosition( int &x, int &y ) const
966{
967 Rect r;
968 GetControlBounds( m_controlRef , &r );
969 x = r.left;
970 y = r.top;
971}
489468fe 972
b2680ced 973void wxMacControl::GetSize( int &width, int &height ) const
489468fe 974{
b2680ced
SC
975 Rect r;
976 GetControlBounds( m_controlRef , &r );
977 width = r.right - r.left;
978 height = r.bottom - r.top;
979}
489468fe 980
524c47aa
SC
981void wxMacControl::SetControlSize( wxWindowVariant variant )
982{
983 ControlSize size ;
984 switch ( variant )
985 {
986 case wxWINDOW_VARIANT_NORMAL :
987 size = kControlSizeNormal;
988 break ;
989
990 case wxWINDOW_VARIANT_SMALL :
991 size = kControlSizeSmall;
992 break ;
993
994 case wxWINDOW_VARIANT_MINI :
995 // not always defined in the headers
996 size = 3 ;
997 break ;
998
999 case wxWINDOW_VARIANT_LARGE :
1000 size = kControlSizeLarge;
1001 break ;
1002
1003 default:
1004 wxFAIL_MSG(_T("unexpected window variant"));
1005 break ;
1006 }
1007
1008 SetData<ControlSize>(kControlEntireControl, kControlSizeTag, &size ) ;
1009}
1010
b2680ced
SC
1011void wxMacControl::ScrollRect( const wxRect *rect, int dx, int dy )
1012{
1013 if (GetNeedsDisplay() )
489468fe 1014 {
b2680ced
SC
1015 // because HIViewScrollRect does not scroll the already invalidated area we have two options:
1016 // in case there is already a pending redraw on that area
1017 // either immediate redraw or full invalidate
1018#if 1
1019 // is the better overall solution, as it does not slow down scrolling
1020 SetNeedsDisplay() ;
1021#else
1022 // this would be the preferred version for fast drawing controls
1023 HIViewRender(GetControlRef()) ;
489468fe 1024#endif
489468fe
SC
1025 }
1026
b2680ced
SC
1027 // note there currently is a bug in OSX (10.3 +?) which makes inefficient refreshes in case an entire control
1028 // area is scrolled, this does not occur if width and height are 2 pixels less,
1029 // TODO: write optimal workaround
1030
1031 HIRect scrollarea = CGRectMake( rect->x , rect->y , rect->width , rect->height);
1032 HIViewScrollRect ( m_controlRef , &scrollarea , dx ,dy );
1033
1034#if 0
1035 // this would be the preferred version for fast drawing controls
1036 HIViewRender(GetControlRef()) ;
1037#endif
489468fe
SC
1038}
1039
b2680ced 1040bool wxMacControl::CanFocus() const
489468fe 1041{
b2680ced
SC
1042 // TODO : evaluate performance hits by looking up this value, eventually cache the results for a 1 sec or so
1043 // CAUTION : the value returned currently is 0 or 2, I've also found values of 1 having the same meaning,
1044 // but the value range is nowhere documented
1045 Boolean keyExistsAndHasValidFormat ;
1046 CFIndex fullKeyboardAccess = CFPreferencesGetAppIntegerValue( CFSTR("AppleKeyboardUIMode" ) ,
1047 kCFPreferencesCurrentApplication, &keyExistsAndHasValidFormat );
489468fe 1048
b2680ced 1049 if ( keyExistsAndHasValidFormat && fullKeyboardAccess > 0 )
489468fe 1050 {
b2680ced 1051 return true ;
489468fe
SC
1052 }
1053 else
1054 {
b2680ced
SC
1055 UInt32 features = 0 ;
1056 GetControlFeatures( m_controlRef, &features ) ;
489468fe 1057
b2680ced 1058 return features & ( kControlSupportsFocus | kControlGetsFocusOnClick ) ;
489468fe
SC
1059 }
1060}
1061
b2680ced 1062bool wxMacControl::GetNeedsDisplay() const
489468fe 1063{
b2680ced
SC
1064 return HIViewGetNeedsDisplay( m_controlRef );
1065}
489468fe 1066
b2680ced
SC
1067void wxWidgetImpl::Convert( wxPoint *pt , wxWidgetImpl *from , wxWidgetImpl *to )
1068{
1069 HIPoint hiPoint;
489468fe 1070
b2680ced
SC
1071 hiPoint.x = pt->x;
1072 hiPoint.y = pt->y;
1073 HIViewConvertPoint( &hiPoint , (ControlRef) from->GetWXWidget() , (ControlRef) to->GetWXWidget() );
1074 pt->x = (int)hiPoint.x;
1075 pt->y = (int)hiPoint.y;
1076}
489468fe 1077
b2680ced
SC
1078bool wxMacControl::SetFocus()
1079{
1080 // as we cannot rely on the control features to find out whether we are in full keyboard mode,
1081 // we can only leave in case of an error
489468fe 1082
b2680ced
SC
1083 OSStatus err = SetKeyboardFocus( GetControlOwner( m_controlRef ), m_controlRef, kControlFocusNextPart );
1084 if ( err == errCouldntSetFocus )
1085 return false ;
1086 SetUserFocusWindow(GetControlOwner( m_controlRef ) );
1087
1088 return true;
489468fe
SC
1089}
1090
b2680ced 1091bool wxMacControl::HasFocus() const
489468fe 1092{
b2680ced
SC
1093 ControlRef control;
1094 GetKeyboardFocus( GetUserFocusWindow() , &control );
1095 return control == m_controlRef;
1096}
489468fe 1097
54f11060
SC
1098void wxMacControl::SetCursor(const wxCursor& cursor)
1099{
1100 wxWindowMac *mouseWin = 0 ;
1101 WindowRef window = GetControlOwner( m_controlRef ) ;
1102
1103 wxNonOwnedWindow* tlwwx = wxNonOwnedWindow::GetFromWXWindow( (WXWindow) window ) ;
1104 if ( tlwwx != NULL )
1105 {
1106 ControlPartCode part ;
1107 ControlRef control ;
1108 Point pt ;
1109#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
1110 HIPoint hiPoint ;
1111 HIGetMousePosition(kHICoordSpaceWindow, window, &hiPoint);
1112 pt.h = hiPoint.x;
1113 pt.v = hiPoint.y;
1114#else
1115 GetGlobalMouse( &pt );
1116 int x = pt.h;
1117 int y = pt.v;
1118 tlwwx->ScreenToClient(&x, &y);
1119 pt.h = x;
1120 pt.v = y;
1121#endif
1122 control = FindControlUnderMouse( pt , window , &part ) ;
1123 if ( control )
1124 mouseWin = wxFindWindowFromWXWidget( (WXWidget) control ) ;
1125 }
1126
1127 if ( mouseWin == tlwwx && !wxIsBusy() )
1128 cursor.MacInstall() ;
1129}
1130
1131void wxMacControl::CaptureMouse()
1132{
1133}
1134
1135void wxMacControl::ReleaseMouse()
1136{
1137}
1138
b2680ced
SC
1139//
1140// subclass specifics
1141//
1142
1143OSStatus wxMacControl::GetData(ControlPartCode inPartCode , ResType inTag , Size inBufferSize , void * inOutBuffer , Size * outActualSize ) const
1144{
1145 return ::GetControlData( m_controlRef , inPartCode , inTag , inBufferSize , inOutBuffer , outActualSize );
489468fe
SC
1146}
1147
b2680ced 1148OSStatus wxMacControl::GetDataSize(ControlPartCode inPartCode , ResType inTag , Size * outActualSize ) const
489468fe 1149{
b2680ced
SC
1150 return ::GetControlDataSize( m_controlRef , inPartCode , inTag , outActualSize );
1151}
489468fe 1152
b2680ced
SC
1153OSStatus wxMacControl::SetData(ControlPartCode inPartCode , ResType inTag , Size inSize , const void * inData)
1154{
1155 return ::SetControlData( m_controlRef , inPartCode , inTag , inSize , inData );
1156}
489468fe 1157
b2680ced
SC
1158OSStatus wxMacControl::SendEvent( EventRef event , OptionBits inOptions )
1159{
1160 return SendEventToEventTargetWithOptions( event,
1161 HIObjectGetEventTarget( (HIObjectRef) m_controlRef ), inOptions );
1162}
489468fe 1163
b2680ced
SC
1164OSStatus wxMacControl::SendHICommand( HICommand &command , OptionBits inOptions )
1165{
1166 wxMacCarbonEvent event( kEventClassCommand , kEventCommandProcess );
489468fe 1167
b2680ced 1168 event.SetParameter<HICommand>(kEventParamDirectObject,command);
489468fe 1169
b2680ced
SC
1170 return SendEvent( event , inOptions );
1171}
489468fe 1172
b2680ced
SC
1173OSStatus wxMacControl::SendHICommand( UInt32 commandID , OptionBits inOptions )
1174{
1175 HICommand command;
489468fe 1176
b2680ced
SC
1177 memset( &command, 0 , sizeof(command) );
1178 command.commandID = commandID;
1179 return SendHICommand( command , inOptions );
1180}
489468fe 1181
524c47aa 1182void wxMacControl::PerformClick()
b2680ced 1183{
524c47aa 1184 HIViewSimulateClick (m_controlRef, kControlButtonPart, 0, NULL );
b2680ced 1185}
489468fe 1186
524c47aa 1187wxInt32 wxMacControl::GetValue() const
b2680ced
SC
1188{
1189 return ::GetControl32BitValue( m_controlRef );
1190}
489468fe 1191
19c7ac3d 1192wxInt32 wxMacControl::GetMaximum() const
b2680ced
SC
1193{
1194 return ::GetControl32BitMaximum( m_controlRef );
1195}
489468fe 1196
524c47aa 1197wxInt32 wxMacControl::GetMinimum() const
b2680ced
SC
1198{
1199 return ::GetControl32BitMinimum( m_controlRef );
489468fe
SC
1200}
1201
524c47aa 1202void wxMacControl::SetValue( wxInt32 v )
489468fe 1203{
b2680ced 1204 ::SetControl32BitValue( m_controlRef , v );
489468fe
SC
1205}
1206
524c47aa 1207void wxMacControl::SetMinimum( wxInt32 v )
489468fe 1208{
b2680ced
SC
1209 ::SetControl32BitMinimum( m_controlRef , v );
1210}
489468fe 1211
524c47aa 1212void wxMacControl::SetMaximum( wxInt32 v )
b2680ced
SC
1213{
1214 ::SetControl32BitMaximum( m_controlRef , v );
1215}
489468fe 1216
b2680ced
SC
1217void wxMacControl::SetValueAndRange( SInt32 value , SInt32 minimum , SInt32 maximum )
1218{
1219 ::SetControl32BitMinimum( m_controlRef , minimum );
1220 ::SetControl32BitMaximum( m_controlRef , maximum );
1221 ::SetControl32BitValue( m_controlRef , value );
1222}
489468fe 1223
b2680ced
SC
1224void wxMacControl::VisibilityChanged(bool WXUNUSED(shown))
1225{
489468fe
SC
1226}
1227
b2680ced 1228void wxMacControl::SuperChangedPosition()
489468fe 1229{
b2680ced 1230}
489468fe 1231
1e181c7a 1232void wxMacControl::SetFont( const wxFont & font , const wxColour& foreground , long windowStyle, bool ignoreBlack )
b2680ced
SC
1233{
1234 m_font = font;
292e5e1f 1235#if wxOSX_USE_CORE_TEXT
b2680ced 1236 if ( UMAGetSystemVersion() >= 0x1050 )
489468fe 1237 {
b2680ced
SC
1238 HIViewPartCode part = 0;
1239 HIThemeTextHorizontalFlush flush = kHIThemeTextHorizontalFlushDefault;
1240 if ( ( windowStyle & wxALIGN_MASK ) & wxALIGN_CENTER_HORIZONTAL )
1241 flush = kHIThemeTextHorizontalFlushCenter;
1242 else if ( ( windowStyle & wxALIGN_MASK ) & wxALIGN_RIGHT )
1243 flush = kHIThemeTextHorizontalFlushRight;
aa6208d9 1244 HIViewSetTextFont( m_controlRef , part , (CTFontRef) font.OSXGetCTFont() );
b2680ced 1245 HIViewSetTextHorizontalFlush( m_controlRef, part, flush );
489468fe 1246
1e181c7a 1247 if ( foreground != *wxBLACK || ignoreBlack == false )
b2680ced
SC
1248 {
1249 ControlFontStyleRec fontStyle;
1250 foreground.GetRGBColor( &fontStyle.foreColor );
1251 fontStyle.flags = kControlUseForeColorMask;
1252 ::SetControlFontStyle( m_controlRef , &fontStyle );
1253 }
489468fe 1254 }
b2680ced 1255#endif
292e5e1f 1256#if wxOSX_USE_ATSU_TEXT
b2680ced
SC
1257 ControlFontStyleRec fontStyle;
1258 if ( font.MacGetThemeFontID() != kThemeCurrentPortFont )
1259 {
1260 switch ( font.MacGetThemeFontID() )
1261 {
1262 case kThemeSmallSystemFont :
1263 fontStyle.font = kControlFontSmallSystemFont;
1264 break;
489468fe 1265
b2680ced
SC
1266 case 109 : // mini font
1267 fontStyle.font = -5;
1268 break;
489468fe 1269
b2680ced
SC
1270 case kThemeSystemFont :
1271 fontStyle.font = kControlFontBigSystemFont;
1272 break;
489468fe 1273
b2680ced
SC
1274 default :
1275 fontStyle.font = kControlFontBigSystemFont;
1276 break;
1277 }
1278
1279 fontStyle.flags = kControlUseFontMask;
1280 }
1281 else
489468fe 1282 {
b2680ced
SC
1283 fontStyle.font = font.MacGetFontNum();
1284 fontStyle.style = font.MacGetFontStyle();
f1c40652 1285 fontStyle.size = font.GetPointSize();
b2680ced 1286 fontStyle.flags = kControlUseFontMask | kControlUseFaceMask | kControlUseSizeMask;
489468fe 1287 }
b2680ced
SC
1288
1289 fontStyle.just = teJustLeft;
1290 fontStyle.flags |= kControlUseJustMask;
1291 if ( ( windowStyle & wxALIGN_MASK ) & wxALIGN_CENTER_HORIZONTAL )
1292 fontStyle.just = teJustCenter;
1293 else if ( ( windowStyle & wxALIGN_MASK ) & wxALIGN_RIGHT )
1294 fontStyle.just = teJustRight;
1295
1296
1297 // we only should do this in case of a non-standard color, as otherwise 'disabled' controls
1298 // won't get grayed out by the system anymore
1299
1e181c7a 1300 if ( foreground != *wxBLACK || ignoreBlack == false )
489468fe 1301 {
b2680ced
SC
1302 foreground.GetRGBColor( &fontStyle.foreColor );
1303 fontStyle.flags |= kControlUseForeColorMask;
489468fe
SC
1304 }
1305
b2680ced
SC
1306 ::SetControlFontStyle( m_controlRef , &fontStyle );
1307#endif
489468fe
SC
1308}
1309
b2680ced 1310void wxMacControl::SetBackgroundColour( const wxColour &WXUNUSED(col) )
489468fe 1311{
b2680ced 1312// HITextViewSetBackgroundColor( m_textView , color );
489468fe
SC
1313}
1314
b2680ced 1315void wxMacControl::SetRange( SInt32 minimum , SInt32 maximum )
489468fe 1316{
b2680ced
SC
1317 ::SetControl32BitMinimum( m_controlRef , minimum );
1318 ::SetControl32BitMaximum( m_controlRef , maximum );
489468fe
SC
1319}
1320
b2680ced 1321short wxMacControl::HandleKey( SInt16 keyCode, SInt16 charCode, EventModifiers modifiers )
489468fe 1322{
b2680ced 1323 return HandleControlKey( m_controlRef , keyCode , charCode , modifiers );
489468fe
SC
1324}
1325
b2680ced 1326void wxMacControl::SetActionProc( ControlActionUPP actionProc )
489468fe 1327{
b2680ced 1328 SetControlAction( m_controlRef , actionProc );
489468fe
SC
1329}
1330
b2680ced
SC
1331SInt32 wxMacControl::GetViewSize() const
1332{
1333 return GetControlViewSize( m_controlRef );
489468fe
SC
1334}
1335
b2680ced 1336bool wxMacControl::IsVisible() const
489468fe 1337{
b2680ced
SC
1338 return IsControlVisible( m_controlRef );
1339}
489468fe 1340
b2680ced
SC
1341void wxMacControl::SetVisibility( bool visible )
1342{
1343 SetControlVisibility( m_controlRef , visible, true );
1344}
489468fe 1345
b2680ced
SC
1346bool wxMacControl::IsEnabled() const
1347{
1348 return IsControlEnabled( m_controlRef );
489468fe
SC
1349}
1350
b2680ced 1351bool wxMacControl::IsActive() const
489468fe 1352{
b2680ced
SC
1353 return IsControlActive( m_controlRef );
1354}
489468fe 1355
b2680ced
SC
1356void wxMacControl::Enable( bool enable )
1357{
1358 if ( enable )
1359 EnableControl( m_controlRef );
489468fe 1360 else
b2680ced 1361 DisableControl( m_controlRef );
489468fe
SC
1362}
1363
b2680ced 1364void wxMacControl::SetDrawingEnabled( bool enable )
489468fe 1365{
b2680ced
SC
1366 HIViewSetDrawingEnabled( m_controlRef , enable );
1367}
1368
1369void wxMacControl::GetRectInWindowCoords( Rect *r )
1370{
1371 GetControlBounds( m_controlRef , r ) ;
1372
1373 WindowRef tlwref = GetControlOwner( m_controlRef ) ;
1374
1375 wxNonOwnedWindow* tlwwx = wxNonOwnedWindow::GetFromWXWindow( (WXWindow) tlwref ) ;
1376 if ( tlwwx != NULL )
489468fe 1377 {
b2680ced
SC
1378 ControlRef rootControl = tlwwx->GetPeer()->GetControlRef() ;
1379 HIPoint hiPoint = CGPointMake( 0 , 0 ) ;
1380 HIViewConvertPoint( &hiPoint , HIViewGetSuperview(m_controlRef) , rootControl ) ;
1381 OffsetRect( r , (short) hiPoint.x , (short) hiPoint.y ) ;
489468fe
SC
1382 }
1383}
1384
524c47aa 1385void wxMacControl::GetBestRect( wxRect *rect ) const
489468fe 1386{
b2680ced 1387 short baselineoffset;
524c47aa 1388 Rect r = {0,0,0,0};
b2680ced 1389
524c47aa
SC
1390 GetBestControlRect( m_controlRef , &r , &baselineoffset );
1391 *rect = wxRect( r.left, r.top, r.right - r.left, r.bottom-r.top );
489468fe
SC
1392}
1393
524c47aa 1394void wxMacControl::GetBestRect( Rect *r ) const
489468fe 1395{
524c47aa
SC
1396 short baselineoffset;
1397 GetBestControlRect( m_controlRef , r , &baselineoffset );
1398}
489468fe 1399
524c47aa
SC
1400void wxMacControl::SetLabel( const wxString &title , wxFontEncoding encoding)
1401{
b2680ced 1402 SetControlTitleWithCFString( m_controlRef , wxCFStringRef( title , encoding ) );
489468fe
SC
1403}
1404
b2680ced 1405void wxMacControl::GetFeatures( UInt32 * features )
489468fe 1406{
b2680ced 1407 GetControlFeatures( m_controlRef , features );
489468fe
SC
1408}
1409
524c47aa
SC
1410void wxMacControl::PulseGauge()
1411{
1412}
1413
b2680ced
SC
1414// SetNeedsDisplay would not invalidate the children
1415static void InvalidateControlAndChildren( HIViewRef control )
1416{
1417 HIViewSetNeedsDisplay( control , true );
1418 UInt16 childrenCount = 0;
1419 OSStatus err = CountSubControls( control , &childrenCount );
1420 if ( err == errControlIsNotEmbedder )
1421 return;
489468fe 1422
b2680ced 1423 wxASSERT_MSG( err == noErr , wxT("Unexpected error when accessing subcontrols") );
489468fe 1424
b2680ced
SC
1425 for ( UInt16 i = childrenCount; i >=1; --i )
1426 {
1427 HIViewRef child;
489468fe 1428
b2680ced
SC
1429 err = GetIndexedSubControl( control , i , & child );
1430 if ( err == errControlIsNotEmbedder )
1431 return;
1432
1433 InvalidateControlAndChildren( child );
1434 }
489468fe
SC
1435}
1436
b2680ced 1437void wxMacControl::InvalidateWithChildren()
489468fe 1438{
b2680ced
SC
1439 InvalidateControlAndChildren( m_controlRef );
1440}
489468fe 1441
b2680ced
SC
1442OSType wxMacCreator = 'WXMC';
1443OSType wxMacControlProperty = 'MCCT';
1444
1445void wxMacControl::SetReferenceInNativeControl()
1446{
1447 void * data = this;
1448 verify_noerr( SetControlProperty ( m_controlRef ,
1449 wxMacCreator,wxMacControlProperty, sizeof(data), &data ) );
1450}
1451
1452wxMacControl* wxMacControl::GetReferenceFromNativeControl(ControlRef control)
1453{
1454 wxMacControl* ctl = NULL;
1455 ByteCount actualSize;
1456 if ( GetControlProperty( control ,wxMacCreator,wxMacControlProperty, sizeof(ctl) ,
1457 &actualSize , &ctl ) == noErr )
489468fe 1458 {
b2680ced 1459 return ctl;
489468fe 1460 }
b2680ced 1461 return NULL;
489468fe
SC
1462}
1463
524c47aa
SC
1464void wxMacControl::SetBitmap( const wxBitmap& WXUNUSED(bmp) )
1465{
1466 // implemented in the respective subclasses
1467}
1468
1469void wxMacControl::SetScrollThumb( wxInt32 WXUNUSED(pos), wxInt32 WXUNUSED(viewsize) )
1470{
1471 // implemented in respective subclass
1472}
489468fe 1473
b2680ced
SC
1474//
1475// Tab Control
1476//
489468fe 1477
b2680ced 1478OSStatus wxMacControl::SetTabEnabled( SInt16 tabNo , bool enable )
489468fe 1479{
b2680ced 1480 return ::SetTabEnabled( m_controlRef , tabNo , enable );
489468fe
SC
1481}
1482
b2680ced
SC
1483
1484
1485// Control Factory
1486
524c47aa 1487wxWidgetImplType* wxWidgetImpl::CreateContentView( wxNonOwnedWindow* now )
489468fe 1488{
b2680ced
SC
1489 // There is a bug in 10.2.X for ::GetRootControl returning the window view instead of
1490 // the content view, so we have to retrieve it explicitly
1491
1492 wxMacControl* contentview = new wxMacControl(now , true /*isRootControl*/);
1493 HIViewFindByID( HIViewGetRoot( (WindowRef) now->GetWXWindow() ) , kHIViewWindowContentID ,
1494 contentview->GetControlRefAddr() ) ;
1495 if ( !contentview->IsOk() )
489468fe 1496 {
b2680ced
SC
1497 // compatibility mode fallback
1498 GetRootControl( (WindowRef) now->GetWXWindow() , contentview->GetControlRefAddr() ) ;
489468fe 1499 }
489468fe 1500
b2680ced
SC
1501 // the root control level handler
1502 contentview->InstallEventHandler() ;
1503 return contentview;
489468fe 1504}