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