]> git.saurik.com Git - wxWidgets.git/blame - src/osx/carbon/window.cpp
clang compat.
[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
9a9fa616 588WXDLLEXPORT pascal 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;
b2680ced
SC
613 // the resulting string will never have more chars than the utf16 version, so this is safe
614 wxMBConvUTF16 converter ;
615 numChars = converter.MB2WC( uniChars , (const char*)charBuf , numChars ) ;
b2680ced
SC
616 }
617
618 switch ( GetEventKind( event ) )
619 {
620 case kEventTextInputUpdateActiveInputArea :
621 {
622 // An IME input event may return several characters, but we need to send one char at a time to
623 // EVT_CHAR
624 for (int pos=0 ; pos < numChars ; pos++)
625 {
626 WXEVENTREF formerEvent = wxTheApp->MacGetCurrentEvent() ;
627 WXEVENTHANDLERCALLREF formerHandler = wxTheApp->MacGetCurrentEventHandlerCallRef() ;
628 wxTheApp->MacSetCurrentEvent( event , handler ) ;
629
630 UInt32 message = uniChars[pos] < 128 ? (char)uniChars[pos] : '?';
631/*
632 NB: faking a charcode here is problematic. The kEventTextInputUpdateActiveInputArea event is sent
633 multiple times to update the active range during inline input, so this handler will often receive
634 uncommited text, which should usually not trigger side effects. It might be a good idea to check the
635 kEventParamTextInputSendFixLen parameter and verify if input is being confirmed (see CarbonEvents.h).
636 On the other hand, it can be useful for some applications to react to uncommitted text (for example,
637 to update a status display), as long as it does not disrupt the inline input session. Ideally, wx
638 should add new event types to support advanced text input. For now, I would keep things as they are.
639
640 However, the code that was being used caused additional problems:
641 UInt32 message = (0 << 8) + ((char)uniChars[pos] );
642 Since it simply truncated the unichar to the last byte, it ended up causing weird bugs with inline
643 input, such as switching to another field when one attempted to insert the character U+4E09 (the kanji
644 for "three"), because it was truncated to 09 (kTabCharCode), which was later "converted" to WXK_TAB
645 (still 09) in wxMacTranslateKey; or triggering the default button when one attempted to insert U+840D
646 (the kanji for "name"), which got truncated to 0D and interpreted as a carriage return keypress.
647 Note that even single-byte characters could have been misinterpreted, since MacRoman charcodes only
648 overlap with Unicode within the (7-bit) ASCII range.
649 But simply passing a NUL charcode would disable text updated events, because wxTextCtrl::OnChar checks
650 for codes within a specific range. Therefore I went for the solution seen above, which keeps ASCII
651 characters as they are and replaces the rest with '?', ensuring that update events are triggered.
652 It would be better to change wxTextCtrl::OnChar to look at the actual unicode character instead, but
653 I don't have time to look into that right now.
654 -- CL
655*/
656 if ( wxTheApp->MacSendCharEvent(
657 focus , message , 0 , when , 0 , 0 , uniChars[pos] ) )
658 {
659 result = noErr ;
660 }
661
662 wxTheApp->MacSetCurrentEvent( formerEvent , formerHandler ) ;
663 }
664 }
665 break ;
666 case kEventTextInputUnicodeForKeyEvent :
667 {
668 UInt32 keyCode, modifiers ;
669 Point point ;
670 EventRef rawEvent ;
671 unsigned char charCode ;
672
673 GetEventParameter( event, kEventParamTextInputSendKeyboardEvent, typeEventRef, NULL, sizeof(rawEvent), NULL, &rawEvent ) ;
674 GetEventParameter( rawEvent, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &charCode );
675 GetEventParameter( rawEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode );
676 GetEventParameter( rawEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers );
677 GetEventParameter( rawEvent, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &point );
678
679 UInt32 message = (keyCode << 8) + charCode;
489468fe 680
b2680ced
SC
681 // An IME input event may return several characters, but we need to send one char at a time to
682 // EVT_CHAR
683 for (int pos=0 ; pos < numChars ; pos++)
684 {
685 WXEVENTREF formerEvent = wxTheApp->MacGetCurrentEvent() ;
686 WXEVENTHANDLERCALLREF formerHandler = wxTheApp->MacGetCurrentEventHandlerCallRef() ;
687 wxTheApp->MacSetCurrentEvent( event , handler ) ;
688
689 if ( wxTheApp->MacSendCharEvent(
690 focus , message , modifiers , when , point.h , point.v , uniChars[pos] ) )
691 {
692 result = noErr ;
693 }
694
695 wxTheApp->MacSetCurrentEvent( formerEvent , formerHandler ) ;
696 }
697 }
698 break;
699 default:
700 break ;
489468fe 701 }
489468fe 702
b2680ced
SC
703 delete [] uniChars ;
704 if ( charBuf != buf )
705 delete [] charBuf ;
489468fe 706
b2680ced 707 return result ;
489468fe
SC
708}
709
b2680ced
SC
710static pascal OSStatus
711wxMacWindowCommandEventHandler(EventHandlerCallRef WXUNUSED(handler),
712 EventRef event,
713 void *data)
489468fe 714{
b2680ced
SC
715 OSStatus result = eventNotHandledErr ;
716 wxWindowMac* focus = (wxWindowMac*) data ;
489468fe 717
b2680ced 718 HICommand command ;
489468fe 719
b2680ced
SC
720 wxMacCarbonEvent cEvent( event ) ;
721 cEvent.GetParameter<HICommand>(kEventParamDirectObject,typeHICommand,&command) ;
489468fe 722
b2680ced
SC
723 wxMenuItem* item = NULL ;
724 wxMenu* itemMenu = wxFindMenuFromMacCommand( command , item ) ;
489468fe 725
b2680ced 726 if ( item )
489468fe 727 {
b2680ced 728 wxASSERT( itemMenu != NULL ) ;
489468fe 729
b2680ced 730 switch ( cEvent.GetKind() )
489468fe 731 {
b2680ced 732 case kEventProcessCommand :
524c47aa
SC
733 if ( itemMenu->HandleCommandProcess( item, focus ) )
734 result = noErr;
b2680ced 735 break ;
489468fe 736
b2680ced 737 case kEventCommandUpdateStatus:
524c47aa
SC
738 if ( itemMenu->HandleCommandUpdateStatus( item, focus ) )
739 result = noErr;
b2680ced 740 break ;
489468fe 741
b2680ced
SC
742 default :
743 break ;
744 }
489468fe 745 }
b2680ced 746 return result ;
489468fe
SC
747}
748
b2680ced 749pascal OSStatus wxMacWindowEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
489468fe 750{
b2680ced
SC
751 EventRef formerEvent = (EventRef) wxTheApp->MacGetCurrentEvent() ;
752 EventHandlerCallRef formerEventHandlerCallRef = (EventHandlerCallRef) wxTheApp->MacGetCurrentEventHandlerCallRef() ;
753 wxTheApp->MacSetCurrentEvent( event , handler ) ;
754 OSStatus result = eventNotHandledErr ;
489468fe 755
b2680ced
SC
756 switch ( GetEventClass( event ) )
757 {
758 case kEventClassCommand :
759 result = wxMacWindowCommandEventHandler( handler , event , data ) ;
760 break ;
489468fe 761
b2680ced
SC
762 case kEventClassControl :
763 result = wxMacWindowControlEventHandler( handler, event, data ) ;
764 break ;
489468fe 765
b2680ced
SC
766 case kEventClassService :
767 result = wxMacWindowServiceEventHandler( handler, event , data ) ;
768 break ;
489468fe 769
b2680ced
SC
770 case kEventClassTextInput :
771 result = wxMacUnicodeTextEventHandler( handler , event , data ) ;
772 break ;
489468fe 773
b2680ced
SC
774 default :
775 break ;
776 }
489468fe 777
b2680ced 778 wxTheApp->MacSetCurrentEvent( formerEvent, formerEventHandlerCallRef ) ;
489468fe 779
b2680ced 780 return result ;
489468fe
SC
781}
782
b2680ced 783DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacWindowEventHandler )
489468fe 784
b2680ced
SC
785// ---------------------------------------------------------------------------
786// Scrollbar Tracking for all
787// ---------------------------------------------------------------------------
489468fe 788
b2680ced
SC
789pascal void wxMacLiveScrollbarActionProc( ControlRef control , ControlPartCode partCode ) ;
790pascal void wxMacLiveScrollbarActionProc( ControlRef control , ControlPartCode partCode )
489468fe 791{
b2680ced 792 if ( partCode != 0)
489468fe 793 {
b2680ced
SC
794 wxWindow* wx = wxFindWindowFromWXWidget( (WXWidget) control ) ;
795 if ( wx )
8f2a8de6 796 {
19c7ac3d
SC
797 wxEventType scrollEvent = wxEVT_NULL;
798 switch ( partCode )
799 {
800 case kControlUpButtonPart:
801 scrollEvent = wxEVT_SCROLL_LINEUP;
802 break;
803
804 case kControlDownButtonPart:
805 scrollEvent = wxEVT_SCROLL_LINEDOWN;
806 break;
807
808 case kControlPageUpPart:
809 scrollEvent = wxEVT_SCROLL_PAGEUP;
810 break;
811
812 case kControlPageDownPart:
813 scrollEvent = wxEVT_SCROLL_PAGEDOWN;
814 break;
815
816 case kControlIndicatorPart:
817 scrollEvent = wxEVT_SCROLL_THUMBTRACK;
818 // when this is called as a live proc, mouse is always still down
819 // so no need for thumbrelease
820 // scrollEvent = wxEVT_SCROLL_THUMBRELEASE;
821 break;
822 }
823 wx->TriggerScrollEvent(scrollEvent) ;
824 }
489468fe
SC
825 }
826}
b2680ced 827wxMAC_DEFINE_PROC_GETTER( ControlActionUPP , wxMacLiveScrollbarActionProc ) ;
489468fe 828
8f2a8de6
VZ
829wxWidgetImplType* wxWidgetImpl::CreateUserPane( wxWindowMac* wxpeer,
830 wxWindowMac* WXUNUSED(parent),
831 wxWindowID WXUNUSED(id),
832 const wxPoint& pos,
a4fec5b4 833 const wxSize& size,
8f2a8de6 834 long WXUNUSED(style),
a4fec5b4 835 long WXUNUSED(extraStyle))
489468fe 836{
b2680ced
SC
837 OSStatus err = noErr;
838 Rect bounds = wxMacGetBoundsForControl( wxpeer , pos , size ) ;
d15694e8 839 wxMacControl* c = new wxMacControl(wxpeer, false, true) ;
b2680ced
SC
840 UInt32 features = 0
841 | kControlSupportsEmbedding
842 | kControlSupportsLiveFeedback
843 | kControlGetsFocusOnClick
844// | kControlHasSpecialBackground
845// | kControlSupportsCalcBestRect
846 | kControlHandlesTracking
847 | kControlSupportsFocus
848 | kControlWantsActivate
849 | kControlWantsIdle ;
489468fe 850
b2680ced
SC
851 err =::CreateUserPaneControl( MAC_WXHWND(wxpeer->GetParent()->MacGetTopLevelWindowRef()) , &bounds, features , c->GetControlRefAddr() );
852 verify_noerr( err );
853 return c;
854}
489468fe 855
489468fe 856
f55d9f74 857void wxMacControl::InstallEventHandler( WXWidget control )
b2680ced 858{
f55d9f74
SC
859 wxWidgetImpl::Associate( control ? control : (WXWidget) m_controlRef , this ) ;
860 ::InstallControlEventHandler( control ? (ControlRef) control : m_controlRef , GetwxMacWindowEventHandlerUPP(),
861 GetEventTypeCount(eventList), eventList, GetWXPeer(), NULL);
489468fe
SC
862}
863
b2680ced
SC
864IMPLEMENT_DYNAMIC_CLASS( wxMacControl , wxWidgetImpl )
865
866wxMacControl::wxMacControl()
489468fe 867{
b2680ced
SC
868 Init();
869}
489468fe 870
415f4a01
SC
871wxMacControl::wxMacControl(wxWindowMac* peer , bool isRootControl, bool isUserPane ) :
872 wxWidgetImpl( peer, isRootControl, isUserPane )
b2680ced
SC
873{
874 Init();
875}
489468fe 876
b2680ced
SC
877wxMacControl::~wxMacControl()
878{
524c47aa
SC
879 if ( m_controlRef && !IsRootControl() )
880 {
881 wxASSERT_MSG( m_controlRef != NULL , wxT("Control Handle already NULL, Dispose called twice ?") );
882 wxASSERT_MSG( IsValidControlHandle(m_controlRef) , wxT("Invalid Control Handle (maybe already released) in Dispose") );
489468fe 883
f55d9f74 884 wxWidgetImpl::RemoveAssociations( this ) ;
524c47aa
SC
885 // we cannot check the ref count here anymore, as autorelease objects might delete their refs later
886 // we can have situations when being embedded, where the control gets deleted behind our back, so only
887 // CFRelease if we are safe
888 if ( IsValidControlHandle(m_controlRef) )
889 CFRelease(m_controlRef);
890 }
b2680ced 891 m_controlRef = NULL;
b2680ced 892}
489468fe 893
524c47aa 894void wxMacControl::Init()
b2680ced 895{
b2680ced 896 m_controlRef = NULL;
524c47aa 897 m_macControlEventHandler = NULL;
b2680ced 898}
489468fe 899
b2680ced
SC
900void wxMacControl::RemoveFromParent()
901{
902 // nothing to do here for carbon
c4825ef7 903 HIViewRemoveFromSuperview(m_controlRef);
b2680ced 904}
489468fe 905
b2680ced
SC
906void wxMacControl::Embed( wxWidgetImpl *parent )
907{
bd412bc6 908 HIViewAddSubview((ControlRef)parent->GetWXWidget(), m_controlRef);
b2680ced 909}
489468fe 910
b2680ced
SC
911void wxMacControl::SetNeedsDisplay( const wxRect* rect )
912{
913 if ( !IsVisible() )
914 return;
489468fe 915
b2680ced
SC
916 if ( rect != NULL )
917 {
918 HIRect updatearea = CGRectMake( rect->x , rect->y , rect->width , rect->height);
919 HIViewSetNeedsDisplayInRect( m_controlRef, &updatearea, true );
920 }
921 else
922 HIViewSetNeedsDisplay( m_controlRef , true );
923}
489468fe 924
b2680ced
SC
925void wxMacControl::Raise()
926{
927 verify_noerr( HIViewSetZOrder( m_controlRef, kHIViewZOrderAbove, NULL ) );
928}
8f2a8de6 929
b2680ced
SC
930void wxMacControl::Lower()
931{
932 verify_noerr( HIViewSetZOrder( m_controlRef, kHIViewZOrderBelow, NULL ) );
933}
489468fe 934
b2680ced
SC
935void wxMacControl::GetContentArea(int &left , int &top , int &width , int &height) const
936{
f215225d 937 HIShapeRef rgn = NULL;
8f2a8de6 938 Rect content ;
f215225d
SC
939
940 if ( HIViewCopyShape(m_controlRef, kHIViewContentMetaPart, &rgn) == noErr)
941 {
942 CGRect cgrect;
943 HIShapeGetBounds(rgn, &cgrect);
8f2a8de6
VZ
944 content = (Rect){ (short)cgrect.origin.y,
945 (short)cgrect.origin.x,
946 (short)(cgrect.origin.y+cgrect.size.height),
947 (short)(cgrect.origin.x+cgrect.size.width) };
f215225d
SC
948 CFRelease(rgn);
949 }
b2680ced 950 else
524c47aa 951 {
f215225d 952 GetControlBounds(m_controlRef, &content);
524c47aa
SC
953 content.right -= content.left;
954 content.left = 0;
955 content.bottom -= content.top;
956 content.top = 0;
957 }
489468fe 958
b2680ced
SC
959 left = content.left;
960 top = content.top;
489468fe 961
b2680ced
SC
962 width = content.right - content.left ;
963 height = content.bottom - content.top ;
964}
965
966void wxMacControl::Move(int x, int y, int width, int height)
967{
bc5c09a3
SC
968 UInt32 attr = 0 ;
969 GetWindowAttributes( GetControlOwner(m_controlRef) , &attr ) ;
970
b2680ced 971 HIRect hir = CGRectMake(x,y,width,height);
bc5c09a3
SC
972 if ( !(attr & kWindowCompositingAttribute) )
973 {
974 HIRect parent;
975 HIViewGetFrame( HIViewGetSuperview(m_controlRef), &parent );
976 hir.origin.x += parent.origin.x;
977 hir.origin.y += parent.origin.y;
978 }
b2680ced 979 HIViewSetFrame ( m_controlRef , &hir );
489468fe
SC
980}
981
b2680ced
SC
982void wxMacControl::GetPosition( int &x, int &y ) const
983{
984 Rect r;
985 GetControlBounds( m_controlRef , &r );
986 x = r.left;
987 y = r.top;
bc5c09a3
SC
988
989 UInt32 attr = 0 ;
990 GetWindowAttributes( GetControlOwner(m_controlRef) , &attr ) ;
991
992 if ( !(attr & kWindowCompositingAttribute) )
993 {
994 HIRect parent;
995 HIViewGetFrame( HIViewGetSuperview(m_controlRef), &parent );
4a49fa24
VZ
996 x -= (int)parent.origin.x;
997 y -= (int)parent.origin.y;
bc5c09a3 998 }
ce00f59b 999
b2680ced 1000}
489468fe 1001
b2680ced 1002void wxMacControl::GetSize( int &width, int &height ) const
489468fe 1003{
b2680ced
SC
1004 Rect r;
1005 GetControlBounds( m_controlRef , &r );
1006 width = r.right - r.left;
1007 height = r.bottom - r.top;
1008}
489468fe 1009
8f2a8de6 1010void wxMacControl::SetControlSize( wxWindowVariant variant )
524c47aa
SC
1011{
1012 ControlSize size ;
1013 switch ( variant )
1014 {
1015 case wxWINDOW_VARIANT_NORMAL :
1016 size = kControlSizeNormal;
1017 break ;
1018
1019 case wxWINDOW_VARIANT_SMALL :
1020 size = kControlSizeSmall;
1021 break ;
1022
1023 case wxWINDOW_VARIANT_MINI :
1024 // not always defined in the headers
1025 size = 3 ;
1026 break ;
1027
1028 case wxWINDOW_VARIANT_LARGE :
1029 size = kControlSizeLarge;
1030 break ;
1031
1032 default:
9a83f860 1033 wxFAIL_MSG(wxT("unexpected window variant"));
524c47aa
SC
1034 break ;
1035 }
1036
1037 SetData<ControlSize>(kControlEntireControl, kControlSizeTag, &size ) ;
1038}
1039
b2680ced
SC
1040void wxMacControl::ScrollRect( const wxRect *rect, int dx, int dy )
1041{
1042 if (GetNeedsDisplay() )
489468fe 1043 {
b2680ced
SC
1044 // because HIViewScrollRect does not scroll the already invalidated area we have two options:
1045 // in case there is already a pending redraw on that area
1046 // either immediate redraw or full invalidate
1047#if 1
1048 // is the better overall solution, as it does not slow down scrolling
1049 SetNeedsDisplay() ;
1050#else
1051 // this would be the preferred version for fast drawing controls
1052 HIViewRender(GetControlRef()) ;
489468fe 1053#endif
489468fe
SC
1054 }
1055
b2680ced
SC
1056 // note there currently is a bug in OSX (10.3 +?) which makes inefficient refreshes in case an entire control
1057 // area is scrolled, this does not occur if width and height are 2 pixels less,
1058 // TODO: write optimal workaround
1059
1060 HIRect scrollarea = CGRectMake( rect->x , rect->y , rect->width , rect->height);
1061 HIViewScrollRect ( m_controlRef , &scrollarea , dx ,dy );
1062
1063#if 0
1064 // this would be the preferred version for fast drawing controls
1065 HIViewRender(GetControlRef()) ;
1066#endif
489468fe
SC
1067}
1068
b2680ced 1069bool wxMacControl::CanFocus() const
489468fe 1070{
b2680ced
SC
1071 // TODO : evaluate performance hits by looking up this value, eventually cache the results for a 1 sec or so
1072 // CAUTION : the value returned currently is 0 or 2, I've also found values of 1 having the same meaning,
1073 // but the value range is nowhere documented
1074 Boolean keyExistsAndHasValidFormat ;
1075 CFIndex fullKeyboardAccess = CFPreferencesGetAppIntegerValue( CFSTR("AppleKeyboardUIMode" ) ,
1076 kCFPreferencesCurrentApplication, &keyExistsAndHasValidFormat );
489468fe 1077
b2680ced 1078 if ( keyExistsAndHasValidFormat && fullKeyboardAccess > 0 )
489468fe 1079 {
b2680ced 1080 return true ;
489468fe
SC
1081 }
1082 else
1083 {
b2680ced
SC
1084 UInt32 features = 0 ;
1085 GetControlFeatures( m_controlRef, &features ) ;
489468fe 1086
b2680ced 1087 return features & ( kControlSupportsFocus | kControlGetsFocusOnClick ) ;
489468fe
SC
1088 }
1089}
1090
b2680ced 1091bool wxMacControl::GetNeedsDisplay() const
489468fe 1092{
b2680ced
SC
1093 return HIViewGetNeedsDisplay( m_controlRef );
1094}
489468fe 1095
b2680ced
SC
1096void wxWidgetImpl::Convert( wxPoint *pt , wxWidgetImpl *from , wxWidgetImpl *to )
1097{
1098 HIPoint hiPoint;
489468fe 1099
b2680ced
SC
1100 hiPoint.x = pt->x;
1101 hiPoint.y = pt->y;
1102 HIViewConvertPoint( &hiPoint , (ControlRef) from->GetWXWidget() , (ControlRef) to->GetWXWidget() );
1103 pt->x = (int)hiPoint.x;
1104 pt->y = (int)hiPoint.y;
1105}
489468fe 1106
b2680ced
SC
1107bool wxMacControl::SetFocus()
1108{
1109 // as we cannot rely on the control features to find out whether we are in full keyboard mode,
1110 // we can only leave in case of an error
489468fe 1111
b2680ced
SC
1112 OSStatus err = SetKeyboardFocus( GetControlOwner( m_controlRef ), m_controlRef, kControlFocusNextPart );
1113 if ( err == errCouldntSetFocus )
1114 return false ;
1115 SetUserFocusWindow(GetControlOwner( m_controlRef ) );
8f2a8de6 1116
b2680ced 1117 return true;
489468fe
SC
1118}
1119
b2680ced 1120bool wxMacControl::HasFocus() const
489468fe 1121{
b2680ced
SC
1122 ControlRef control;
1123 GetKeyboardFocus( GetUserFocusWindow() , &control );
1124 return control == m_controlRef;
1125}
489468fe 1126
54f11060
SC
1127void wxMacControl::SetCursor(const wxCursor& cursor)
1128{
1129 wxWindowMac *mouseWin = 0 ;
1130 WindowRef window = GetControlOwner( m_controlRef ) ;
1131
1132 wxNonOwnedWindow* tlwwx = wxNonOwnedWindow::GetFromWXWindow( (WXWindow) window ) ;
1133 if ( tlwwx != NULL )
1134 {
1135 ControlPartCode part ;
1136 ControlRef control ;
1137 Point pt ;
1138#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
1139 HIPoint hiPoint ;
1140 HIGetMousePosition(kHICoordSpaceWindow, window, &hiPoint);
1141 pt.h = hiPoint.x;
1142 pt.v = hiPoint.y;
1143#else
1144 GetGlobalMouse( &pt );
1145 int x = pt.h;
1146 int y = pt.v;
1147 tlwwx->ScreenToClient(&x, &y);
1148 pt.h = x;
1149 pt.v = y;
1150#endif
1151 control = FindControlUnderMouse( pt , window , &part ) ;
1152 if ( control )
1153 mouseWin = wxFindWindowFromWXWidget( (WXWidget) control ) ;
1154 }
1155
1156 if ( mouseWin == tlwwx && !wxIsBusy() )
1157 cursor.MacInstall() ;
1158}
1159
1160void wxMacControl::CaptureMouse()
1161{
1162}
1163
1164void wxMacControl::ReleaseMouse()
1165{
1166}
1167
b2680ced
SC
1168//
1169// subclass specifics
1170//
1171
1172OSStatus wxMacControl::GetData(ControlPartCode inPartCode , ResType inTag , Size inBufferSize , void * inOutBuffer , Size * outActualSize ) const
1173{
1174 return ::GetControlData( m_controlRef , inPartCode , inTag , inBufferSize , inOutBuffer , outActualSize );
489468fe
SC
1175}
1176
b2680ced 1177OSStatus wxMacControl::GetDataSize(ControlPartCode inPartCode , ResType inTag , Size * outActualSize ) const
489468fe 1178{
b2680ced
SC
1179 return ::GetControlDataSize( m_controlRef , inPartCode , inTag , outActualSize );
1180}
489468fe 1181
b2680ced
SC
1182OSStatus wxMacControl::SetData(ControlPartCode inPartCode , ResType inTag , Size inSize , const void * inData)
1183{
1184 return ::SetControlData( m_controlRef , inPartCode , inTag , inSize , inData );
1185}
489468fe 1186
b2680ced
SC
1187OSStatus wxMacControl::SendEvent( EventRef event , OptionBits inOptions )
1188{
1189 return SendEventToEventTargetWithOptions( event,
1190 HIObjectGetEventTarget( (HIObjectRef) m_controlRef ), inOptions );
1191}
489468fe 1192
b2680ced
SC
1193OSStatus wxMacControl::SendHICommand( HICommand &command , OptionBits inOptions )
1194{
1195 wxMacCarbonEvent event( kEventClassCommand , kEventCommandProcess );
489468fe 1196
b2680ced 1197 event.SetParameter<HICommand>(kEventParamDirectObject,command);
489468fe 1198
b2680ced
SC
1199 return SendEvent( event , inOptions );
1200}
489468fe 1201
b2680ced
SC
1202OSStatus wxMacControl::SendHICommand( UInt32 commandID , OptionBits inOptions )
1203{
1204 HICommand command;
489468fe 1205
b2680ced
SC
1206 memset( &command, 0 , sizeof(command) );
1207 command.commandID = commandID;
1208 return SendHICommand( command , inOptions );
1209}
489468fe 1210
524c47aa 1211void wxMacControl::PerformClick()
b2680ced 1212{
524c47aa 1213 HIViewSimulateClick (m_controlRef, kControlButtonPart, 0, NULL );
b2680ced 1214}
489468fe 1215
524c47aa 1216wxInt32 wxMacControl::GetValue() const
b2680ced
SC
1217{
1218 return ::GetControl32BitValue( m_controlRef );
1219}
489468fe 1220
19c7ac3d 1221wxInt32 wxMacControl::GetMaximum() const
b2680ced
SC
1222{
1223 return ::GetControl32BitMaximum( m_controlRef );
1224}
489468fe 1225
524c47aa 1226wxInt32 wxMacControl::GetMinimum() const
b2680ced
SC
1227{
1228 return ::GetControl32BitMinimum( m_controlRef );
489468fe
SC
1229}
1230
524c47aa 1231void wxMacControl::SetValue( wxInt32 v )
489468fe 1232{
b2680ced 1233 ::SetControl32BitValue( m_controlRef , v );
489468fe
SC
1234}
1235
524c47aa 1236void wxMacControl::SetMinimum( wxInt32 v )
489468fe 1237{
b2680ced
SC
1238 ::SetControl32BitMinimum( m_controlRef , v );
1239}
489468fe 1240
524c47aa 1241void wxMacControl::SetMaximum( wxInt32 v )
b2680ced
SC
1242{
1243 ::SetControl32BitMaximum( m_controlRef , v );
1244}
489468fe 1245
b2680ced
SC
1246void wxMacControl::SetValueAndRange( SInt32 value , SInt32 minimum , SInt32 maximum )
1247{
1248 ::SetControl32BitMinimum( m_controlRef , minimum );
1249 ::SetControl32BitMaximum( m_controlRef , maximum );
1250 ::SetControl32BitValue( m_controlRef , value );
1251}
489468fe 1252
b2680ced
SC
1253void wxMacControl::VisibilityChanged(bool WXUNUSED(shown))
1254{
489468fe
SC
1255}
1256
b2680ced 1257void wxMacControl::SuperChangedPosition()
489468fe 1258{
b2680ced 1259}
489468fe 1260
1e181c7a 1261void wxMacControl::SetFont( const wxFont & font , const wxColour& foreground , long windowStyle, bool ignoreBlack )
b2680ced
SC
1262{
1263 m_font = font;
292e5e1f 1264#if wxOSX_USE_CORE_TEXT
b2680ced 1265 if ( UMAGetSystemVersion() >= 0x1050 )
489468fe 1266 {
b2680ced
SC
1267 HIViewPartCode part = 0;
1268 HIThemeTextHorizontalFlush flush = kHIThemeTextHorizontalFlushDefault;
1269 if ( ( windowStyle & wxALIGN_MASK ) & wxALIGN_CENTER_HORIZONTAL )
1270 flush = kHIThemeTextHorizontalFlushCenter;
1271 else if ( ( windowStyle & wxALIGN_MASK ) & wxALIGN_RIGHT )
1272 flush = kHIThemeTextHorizontalFlushRight;
aa6208d9 1273 HIViewSetTextFont( m_controlRef , part , (CTFontRef) font.OSXGetCTFont() );
b2680ced 1274 HIViewSetTextHorizontalFlush( m_controlRef, part, flush );
489468fe 1275
1e181c7a 1276 if ( foreground != *wxBLACK || ignoreBlack == false )
b2680ced
SC
1277 {
1278 ControlFontStyleRec fontStyle;
1279 foreground.GetRGBColor( &fontStyle.foreColor );
1280 fontStyle.flags = kControlUseForeColorMask;
1281 ::SetControlFontStyle( m_controlRef , &fontStyle );
1282 }
489468fe 1283 }
b2680ced 1284#endif
292e5e1f 1285#if wxOSX_USE_ATSU_TEXT
b2680ced
SC
1286 ControlFontStyleRec fontStyle;
1287 if ( font.MacGetThemeFontID() != kThemeCurrentPortFont )
1288 {
1289 switch ( font.MacGetThemeFontID() )
1290 {
1291 case kThemeSmallSystemFont :
1292 fontStyle.font = kControlFontSmallSystemFont;
1293 break;
489468fe 1294
b2680ced
SC
1295 case 109 : // mini font
1296 fontStyle.font = -5;
1297 break;
489468fe 1298
b2680ced
SC
1299 case kThemeSystemFont :
1300 fontStyle.font = kControlFontBigSystemFont;
1301 break;
489468fe 1302
b2680ced
SC
1303 default :
1304 fontStyle.font = kControlFontBigSystemFont;
1305 break;
1306 }
1307
1308 fontStyle.flags = kControlUseFontMask;
1309 }
1310 else
489468fe 1311 {
b2680ced
SC
1312 fontStyle.font = font.MacGetFontNum();
1313 fontStyle.style = font.MacGetFontStyle();
f1c40652 1314 fontStyle.size = font.GetPointSize();
b2680ced 1315 fontStyle.flags = kControlUseFontMask | kControlUseFaceMask | kControlUseSizeMask;
489468fe 1316 }
b2680ced
SC
1317
1318 fontStyle.just = teJustLeft;
1319 fontStyle.flags |= kControlUseJustMask;
1320 if ( ( windowStyle & wxALIGN_MASK ) & wxALIGN_CENTER_HORIZONTAL )
1321 fontStyle.just = teJustCenter;
1322 else if ( ( windowStyle & wxALIGN_MASK ) & wxALIGN_RIGHT )
1323 fontStyle.just = teJustRight;
1324
1325
1326 // we only should do this in case of a non-standard color, as otherwise 'disabled' controls
1327 // won't get grayed out by the system anymore
1328
1e181c7a 1329 if ( foreground != *wxBLACK || ignoreBlack == false )
489468fe 1330 {
b2680ced
SC
1331 foreground.GetRGBColor( &fontStyle.foreColor );
1332 fontStyle.flags |= kControlUseForeColorMask;
489468fe
SC
1333 }
1334
b2680ced
SC
1335 ::SetControlFontStyle( m_controlRef , &fontStyle );
1336#endif
489468fe
SC
1337}
1338
b2680ced 1339void wxMacControl::SetBackgroundColour( const wxColour &WXUNUSED(col) )
489468fe 1340{
b2680ced 1341// HITextViewSetBackgroundColor( m_textView , color );
489468fe
SC
1342}
1343
bc5c09a3
SC
1344bool wxMacControl::SetBackgroundStyle(wxBackgroundStyle style)
1345{
1346 if ( style != wxBG_STYLE_PAINT )
1347 {
1348 OSStatus err = HIViewChangeFeatures(m_controlRef , 0 , kHIViewIsOpaque);
1349 verify_noerr( err );
1350 }
1351 else
1352 {
1353 OSStatus err = HIViewChangeFeatures(m_controlRef , kHIViewIsOpaque , 0);
1354 verify_noerr( err );
1355 }
ce00f59b 1356
bc5c09a3
SC
1357 return true ;
1358}
1359
b2680ced 1360void wxMacControl::SetRange( SInt32 minimum , SInt32 maximum )
489468fe 1361{
b2680ced
SC
1362 ::SetControl32BitMinimum( m_controlRef , minimum );
1363 ::SetControl32BitMaximum( m_controlRef , maximum );
489468fe
SC
1364}
1365
b2680ced 1366short wxMacControl::HandleKey( SInt16 keyCode, SInt16 charCode, EventModifiers modifiers )
489468fe 1367{
b2680ced 1368 return HandleControlKey( m_controlRef , keyCode , charCode , modifiers );
489468fe
SC
1369}
1370
b2680ced 1371void wxMacControl::SetActionProc( ControlActionUPP actionProc )
489468fe 1372{
b2680ced 1373 SetControlAction( m_controlRef , actionProc );
489468fe
SC
1374}
1375
b2680ced
SC
1376SInt32 wxMacControl::GetViewSize() const
1377{
1378 return GetControlViewSize( m_controlRef );
489468fe
SC
1379}
1380
b2680ced 1381bool wxMacControl::IsVisible() const
489468fe 1382{
b2680ced
SC
1383 return IsControlVisible( m_controlRef );
1384}
489468fe 1385
b2680ced
SC
1386void wxMacControl::SetVisibility( bool visible )
1387{
1388 SetControlVisibility( m_controlRef , visible, true );
1389}
489468fe 1390
b2680ced
SC
1391bool wxMacControl::IsEnabled() const
1392{
1393 return IsControlEnabled( m_controlRef );
489468fe
SC
1394}
1395
b2680ced 1396bool wxMacControl::IsActive() const
489468fe 1397{
b2680ced
SC
1398 return IsControlActive( m_controlRef );
1399}
489468fe 1400
b2680ced
SC
1401void wxMacControl::Enable( bool enable )
1402{
1403 if ( enable )
1404 EnableControl( m_controlRef );
489468fe 1405 else
b2680ced 1406 DisableControl( m_controlRef );
489468fe
SC
1407}
1408
b2680ced 1409void wxMacControl::SetDrawingEnabled( bool enable )
489468fe 1410{
b2680ced
SC
1411 HIViewSetDrawingEnabled( m_controlRef , enable );
1412}
1413
1414void wxMacControl::GetRectInWindowCoords( Rect *r )
1415{
1416 GetControlBounds( m_controlRef , r ) ;
1417
1418 WindowRef tlwref = GetControlOwner( m_controlRef ) ;
1419
1420 wxNonOwnedWindow* tlwwx = wxNonOwnedWindow::GetFromWXWindow( (WXWindow) tlwref ) ;
1421 if ( tlwwx != NULL )
489468fe 1422 {
b2680ced
SC
1423 ControlRef rootControl = tlwwx->GetPeer()->GetControlRef() ;
1424 HIPoint hiPoint = CGPointMake( 0 , 0 ) ;
1425 HIViewConvertPoint( &hiPoint , HIViewGetSuperview(m_controlRef) , rootControl ) ;
1426 OffsetRect( r , (short) hiPoint.x , (short) hiPoint.y ) ;
489468fe
SC
1427 }
1428}
ce00f59b 1429
524c47aa 1430void wxMacControl::GetBestRect( wxRect *rect ) const
489468fe 1431{
b2680ced 1432 short baselineoffset;
524c47aa 1433 Rect r = {0,0,0,0};
b2680ced 1434
524c47aa
SC
1435 GetBestControlRect( m_controlRef , &r , &baselineoffset );
1436 *rect = wxRect( r.left, r.top, r.right - r.left, r.bottom-r.top );
489468fe
SC
1437}
1438
524c47aa 1439void wxMacControl::GetBestRect( Rect *r ) const
489468fe 1440{
524c47aa
SC
1441 short baselineoffset;
1442 GetBestControlRect( m_controlRef , r , &baselineoffset );
1443}
489468fe 1444
524c47aa
SC
1445void wxMacControl::SetLabel( const wxString &title , wxFontEncoding encoding)
1446{
b2680ced 1447 SetControlTitleWithCFString( m_controlRef , wxCFStringRef( title , encoding ) );
489468fe
SC
1448}
1449
b2680ced 1450void wxMacControl::GetFeatures( UInt32 * features )
489468fe 1451{
b2680ced 1452 GetControlFeatures( m_controlRef , features );
489468fe
SC
1453}
1454
524c47aa
SC
1455void wxMacControl::PulseGauge()
1456{
1457}
1458
b2680ced
SC
1459// SetNeedsDisplay would not invalidate the children
1460static void InvalidateControlAndChildren( HIViewRef control )
1461{
1462 HIViewSetNeedsDisplay( control , true );
1463 UInt16 childrenCount = 0;
1464 OSStatus err = CountSubControls( control , &childrenCount );
1465 if ( err == errControlIsNotEmbedder )
1466 return;
489468fe 1467
b2680ced 1468 wxASSERT_MSG( err == noErr , wxT("Unexpected error when accessing subcontrols") );
489468fe 1469
b2680ced
SC
1470 for ( UInt16 i = childrenCount; i >=1; --i )
1471 {
1472 HIViewRef child;
489468fe 1473
b2680ced
SC
1474 err = GetIndexedSubControl( control , i , & child );
1475 if ( err == errControlIsNotEmbedder )
1476 return;
1477
1478 InvalidateControlAndChildren( child );
1479 }
489468fe
SC
1480}
1481
b2680ced 1482void wxMacControl::InvalidateWithChildren()
489468fe 1483{
b2680ced
SC
1484 InvalidateControlAndChildren( m_controlRef );
1485}
489468fe 1486
b2680ced
SC
1487OSType wxMacCreator = 'WXMC';
1488OSType wxMacControlProperty = 'MCCT';
1489
1490void wxMacControl::SetReferenceInNativeControl()
1491{
1492 void * data = this;
1493 verify_noerr( SetControlProperty ( m_controlRef ,
1494 wxMacCreator,wxMacControlProperty, sizeof(data), &data ) );
1495}
1496
1497wxMacControl* wxMacControl::GetReferenceFromNativeControl(ControlRef control)
1498{
1499 wxMacControl* ctl = NULL;
1500 ByteCount actualSize;
1501 if ( GetControlProperty( control ,wxMacCreator,wxMacControlProperty, sizeof(ctl) ,
1502 &actualSize , &ctl ) == noErr )
489468fe 1503 {
b2680ced 1504 return ctl;
489468fe 1505 }
b2680ced 1506 return NULL;
489468fe
SC
1507}
1508
e5d05b90
VZ
1509wxBitmap wxMacControl::GetBitmap() const
1510{
1511 return wxNullBitmap;
1512}
1513
524c47aa
SC
1514void wxMacControl::SetBitmap( const wxBitmap& WXUNUSED(bmp) )
1515{
1516 // implemented in the respective subclasses
1517}
1518
e5d05b90
VZ
1519void wxMacControl::SetBitmapPosition( wxDirection WXUNUSED(dir) )
1520{
1521 // implemented in the same subclasses that implement SetBitmap()
1522}
1523
524c47aa
SC
1524void wxMacControl::SetScrollThumb( wxInt32 WXUNUSED(pos), wxInt32 WXUNUSED(viewsize) )
1525{
1526 // implemented in respective subclass
1527}
489468fe 1528
b2680ced
SC
1529//
1530// Tab Control
1531//
489468fe 1532
b2680ced 1533OSStatus wxMacControl::SetTabEnabled( SInt16 tabNo , bool enable )
489468fe 1534{
b2680ced 1535 return ::SetTabEnabled( m_controlRef , tabNo , enable );
489468fe
SC
1536}
1537
b2680ced
SC
1538
1539
1540// Control Factory
1541
8f2a8de6 1542wxWidgetImplType* wxWidgetImpl::CreateContentView( wxNonOwnedWindow* now )
489468fe 1543{
b2680ced
SC
1544 // There is a bug in 10.2.X for ::GetRootControl returning the window view instead of
1545 // the content view, so we have to retrieve it explicitly
8f2a8de6 1546
b2680ced
SC
1547 wxMacControl* contentview = new wxMacControl(now , true /*isRootControl*/);
1548 HIViewFindByID( HIViewGetRoot( (WindowRef) now->GetWXWindow() ) , kHIViewWindowContentID ,
1549 contentview->GetControlRefAddr() ) ;
1550 if ( !contentview->IsOk() )
489468fe 1551 {
b2680ced
SC
1552 // compatibility mode fallback
1553 GetRootControl( (WindowRef) now->GetWXWindow() , contentview->GetControlRefAddr() ) ;
489468fe 1554 }
489468fe 1555
b2680ced 1556 // the root control level handler
17e2694c
SC
1557 if ( !now->IsNativeWindowWrapper() )
1558 contentview->InstallEventHandler() ;
ce00f59b 1559
b2680ced 1560 return contentview;
489468fe 1561}