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