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