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