]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/utils.cpp
cleanup - reformatting
[wxWidgets.git] / src / mac / carbon / utils.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/mac/carbon/utils.cpp
3 // Purpose: Various utilities
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/utils.h"
15 #include "wx/app.h"
16 #include "wx/apptrait.h"
17
18 #if wxUSE_GUI
19 #include "wx/mac/uma.h"
20 #include "wx/font.h"
21 #include "wx/toplevel.h"
22 #else
23 #include "wx/intl.h"
24 #endif
25
26 #include <ctype.h>
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <stdarg.h>
32
33 #include "MoreFilesX.h"
34
35 #ifndef __DARWIN__
36 #include <Threads.h>
37 #include <Sound.h>
38 #endif
39
40 #if wxUSE_GUI
41 #if TARGET_API_MAC_OSX
42 #include <CoreServices/CoreServices.h>
43 #else
44 #include <DriverServices.h>
45 #include <Multiprocessing.h>
46 #endif
47
48 #ifdef __DARWIN__
49 #include <Carbon/Carbon.h>
50 #else
51 #include <ATSUnicode.h>
52 #include <TextCommon.h>
53 #include <TextEncodingConverter.h>
54 #endif
55 #endif // wxUSE_GUI
56
57 #include "wx/mac/private.h"
58
59 #if defined(__MWERKS__) && wxUSE_UNICODE
60 #include <wtime.h>
61 #endif
62
63 // ---------------------------------------------------------------------------
64 // code used in both base and GUI compilation
65 // ---------------------------------------------------------------------------
66
67 // our OS version is the same in non GUI and GUI cases
68 static int DoGetOSVersion(int *majorVsn, int *minorVsn)
69 {
70 long theSystem ;
71
72 // are there x-platform conventions ?
73
74 Gestalt(gestaltSystemVersion, &theSystem) ;
75 if (minorVsn != NULL)
76 *minorVsn = (theSystem & 0xFF) ;
77
78 if (majorVsn != NULL)
79 *majorVsn = (theSystem >> 8) ;
80
81 #ifdef __DARWIN__
82 return wxMAC_DARWIN;
83 #else
84 return wxMAC;
85 #endif
86 }
87
88
89 #if wxUSE_BASE
90
91 // ----------------------------------------------------------------------------
92 // debugging support
93 // ----------------------------------------------------------------------------
94
95 #if defined(__WXDEBUG__) && defined(__WXMAC__) && !defined(__DARWIN__) && defined(__MWERKS__) && (__MWERKS__ >= 0x2400)
96
97 // MetroNub stuff doesn't seem to work in CodeWarrior 5.3 Carbon builds...
98
99 #ifndef __MetroNubUtils__
100 #include "MetroNubUtils.h"
101 #endif
102
103 #ifndef __GESTALT__
104 #include <Gestalt.h>
105 #endif
106
107 #if TARGET_API_MAC_CARBON
108
109 #include <CodeFragments.h>
110
111 extern "C" long CallUniversalProc(UniversalProcPtr theProcPtr, ProcInfoType procInfo, ...);
112
113 ProcPtr gCallUniversalProc_Proc = NULL;
114
115 #endif
116
117 static MetroNubUserEntryBlock* gMetroNubEntry = NULL;
118
119 static long fRunOnce = false;
120
121
122 Boolean IsMetroNubInstalled()
123 {
124 if (!fRunOnce)
125 {
126 long result, value;
127
128 fRunOnce = true;
129 gMetroNubEntry = NULL;
130
131 if (Gestalt(gestaltSystemVersion, &value) == noErr && value < 0x1000)
132 {
133 // look for MetroNub's Gestalt selector
134 if (Gestalt(kMetroNubUserSignature, &result) == noErr)
135 {
136 #if TARGET_API_MAC_CARBON
137 if (gCallUniversalProc_Proc == NULL)
138 {
139 CFragConnectionID connectionID;
140 Ptr mainAddress;
141 Str255 errorString;
142 ProcPtr symbolAddress;
143 OSErr err;
144 CFragSymbolClass symbolClass;
145
146 symbolAddress = NULL;
147 err = GetSharedLibrary("\pInterfaceLib", kPowerPCCFragArch, kFindCFrag,
148 &connectionID, &mainAddress, errorString);
149
150 if (err != noErr)
151 {
152 gCallUniversalProc_Proc = NULL;
153 goto end;
154 }
155
156 err = FindSymbol(connectionID, "\pCallUniversalProc",
157 (Ptr *) &gCallUniversalProc_Proc, &symbolClass);
158
159 if (err != noErr)
160 {
161 gCallUniversalProc_Proc = NULL;
162 goto end;
163 }
164 }
165 #endif
166
167 {
168 MetroNubUserEntryBlock* block = (MetroNubUserEntryBlock *)result;
169
170 // make sure the version of the API is compatible
171 if (block->apiLowVersion <= kMetroNubUserAPIVersion &&
172 kMetroNubUserAPIVersion <= block->apiHiVersion)
173 {
174 // success!
175 gMetroNubEntry = block;
176 }
177 }
178 }
179 }
180 }
181
182 end:
183
184 #if TARGET_API_MAC_CARBON
185 return (gMetroNubEntry != NULL && gCallUniversalProc_Proc != NULL);
186 #else
187 return (gMetroNubEntry != NULL);
188 #endif
189 }
190
191 Boolean IsMWDebuggerRunning()
192 {
193 if (IsMetroNubInstalled())
194 return CallIsDebuggerRunningProc(gMetroNubEntry->isDebuggerRunning);
195
196 return false;
197 }
198
199 Boolean AmIBeingMWDebugged()
200 {
201 if (IsMetroNubInstalled())
202 return CallAmIBeingDebuggedProc(gMetroNubEntry->amIBeingDebugged);
203
204 return false;
205 }
206
207 extern bool WXDLLEXPORT wxIsDebuggerRunning()
208 {
209 return IsMWDebuggerRunning() && AmIBeingMWDebugged();
210 }
211
212 #else
213
214 extern bool WXDLLEXPORT wxIsDebuggerRunning()
215 {
216 return false;
217 }
218
219 #endif // defined(__WXMAC__) && !defined(__DARWIN__) && (__MWERKS__ >= 0x2400)
220
221
222 #ifndef __DARWIN__
223 // defined in unix/utilsunx.cpp for Mac OS X
224
225 // get full hostname (with domain name if possible)
226 bool wxGetFullHostName(wxChar *buf, int maxSize)
227 {
228 return wxGetHostName(buf, maxSize);
229 }
230
231 // Get user ID e.g. jacs
232 bool wxGetUserId(wxChar *buf, int maxSize)
233 {
234 return wxGetUserName( buf , maxSize ) ;
235 }
236
237 const wxChar* wxGetHomeDir(wxString *pstr)
238 {
239 *pstr = wxMacFindFolder( (short) kOnSystemDisk, kPreferencesFolderType, kDontCreateFolder ) ;
240 return pstr->c_str() ;
241 }
242
243 // Get hostname only (without domain name)
244 bool wxGetHostName(wxChar *buf, int maxSize)
245 {
246 // Gets Chooser name of user by examining a System resource.
247 buf[0] = 0 ;
248
249 const short kComputerNameID = -16413;
250
251 short oldResFile = CurResFile() ;
252 UseResFile(0);
253 StringHandle chooserName = (StringHandle)::GetString(kComputerNameID);
254 UseResFile(oldResFile);
255
256 if (chooserName && *chooserName)
257 {
258 HLock( (Handle) chooserName ) ;
259 wxString name = wxMacMakeStringFromPascal( *chooserName ) ;
260 HUnlock( (Handle) chooserName ) ;
261 ReleaseResource( (Handle) chooserName ) ;
262 wxStrncpy( buf , name , maxSize - 1 ) ;
263 }
264
265 return true;
266 }
267
268 // Get user name e.g. Stefan Csomor
269 bool wxGetUserName(wxChar *buf, int maxSize)
270 {
271 // Gets Chooser name of user by examining a System resource.
272 buf[0] = 0 ;
273
274 const short kChooserNameID = -16096;
275
276 short oldResFile = CurResFile() ;
277 UseResFile(0);
278 StringHandle chooserName = (StringHandle)::GetString(kChooserNameID);
279 UseResFile(oldResFile);
280
281 if (chooserName && *chooserName)
282 {
283 HLock( (Handle) chooserName ) ;
284 wxString name = wxMacMakeStringFromPascal( *chooserName ) ;
285 HUnlock( (Handle) chooserName ) ;
286 ReleaseResource( (Handle) chooserName ) ;
287 wxStrncpy( buf , name , maxSize - 1 ) ;
288 }
289
290 return true;
291 }
292
293 int wxKill(long pid, wxSignal sig , wxKillError *rc, int flags)
294 {
295 // TODO
296 return 0;
297 }
298
299 WXDLLEXPORT bool wxGetEnv(const wxString& var, wxString *value)
300 {
301 // TODO : under classic there is no environement support, under X yes
302 return false ;
303 }
304
305 // set the env var name to the given value, return true on success
306 WXDLLEXPORT bool wxSetEnv(const wxString& var, const wxChar *value)
307 {
308 // TODO : under classic there is no environement support, under X yes
309 return false ;
310 }
311
312 // Execute a program in an Interactive Shell
313 bool wxShell(const wxString& command)
314 {
315 // TODO
316 return false;
317 }
318
319 // Shutdown or reboot the PC
320 bool wxShutdown(wxShutdownFlags wFlags)
321 {
322 // TODO
323 return false;
324 }
325
326 wxPowerType wxGetPowerType()
327 {
328 // TODO
329 return wxPOWER_UNKNOWN;
330 }
331
332 wxBatteryState wxGetBatteryState()
333 {
334 // TODO
335 return wxBATTERY_UNKNOWN_STATE;
336 }
337
338 // Get free memory in bytes, or -1 if cannot determine amount (e.g. on UNIX)
339 wxMemorySize wxGetFreeMemory()
340 {
341 return (wxMemorySize)FreeMem() ;
342 }
343
344 #ifndef __DARWIN__
345
346 void wxMicroSleep(unsigned long microseconds)
347 {
348 AbsoluteTime wakeup = AddDurationToAbsolute( microseconds * durationMicrosecond , UpTime());
349 MPDelayUntil( & wakeup);
350 }
351
352 void wxMilliSleep(unsigned long milliseconds)
353 {
354 AbsoluteTime wakeup = AddDurationToAbsolute( milliseconds, UpTime());
355 MPDelayUntil( & wakeup);
356 }
357
358 void wxSleep(int nSecs)
359 {
360 wxMilliSleep(1000*nSecs);
361 }
362
363 #endif
364
365 // Consume all events until no more left
366 void wxFlushEvents()
367 {
368 }
369
370 #endif // !__DARWIN__
371
372 // Emit a beeeeeep
373 void wxBell()
374 {
375 SysBeep(30);
376 }
377
378 wxToolkitInfo& wxConsoleAppTraits::GetToolkitInfo()
379 {
380 static wxToolkitInfo info;
381
382 info.os = DoGetOSVersion(&info.versionMajor, &info.versionMinor);
383 info.name = _T("wxBase");
384
385 return info;
386 }
387
388 #endif // wxUSE_BASE
389
390 #if wxUSE_GUI
391
392 wxToolkitInfo& wxGUIAppTraits::GetToolkitInfo()
393 {
394 static wxToolkitInfo info;
395
396 info.os = DoGetOSVersion(&info.versionMajor, &info.versionMinor);
397 info.shortName = _T("mac");
398 info.name = _T("wxMac");
399
400 #ifdef __WXUNIVERSAL__
401 info.shortName << _T("univ");
402 info.name << _T("/wxUniversal");
403 #endif
404
405 return info;
406 }
407
408 // Reading and writing resources (eg WIN.INI, .Xdefaults)
409 #if wxUSE_RESOURCES
410 bool wxWriteResource(const wxString& section, const wxString& entry, const wxString& value, const wxString& file)
411 {
412 // TODO
413 return false;
414 }
415
416 bool wxWriteResource(const wxString& section, const wxString& entry, float value, const wxString& file)
417 {
418 wxString buf;
419 buf.Printf(wxT("%.4f"), value);
420
421 return wxWriteResource(section, entry, buf, file);
422 }
423
424 bool wxWriteResource(const wxString& section, const wxString& entry, long value, const wxString& file)
425 {
426 wxString buf;
427 buf.Printf(wxT("%ld"), value);
428
429 return wxWriteResource(section, entry, buf, file);
430 }
431
432 bool wxWriteResource(const wxString& section, const wxString& entry, int value, const wxString& file)
433 {
434 wxString buf;
435 buf.Printf(wxT("%d"), value);
436
437 return wxWriteResource(section, entry, buf, file);
438 }
439
440 bool wxGetResource(const wxString& section, const wxString& entry, char **value, const wxString& file)
441 {
442 // TODO
443 return false;
444 }
445
446 bool wxGetResource(const wxString& section, const wxString& entry, float *value, const wxString& file)
447 {
448 char *s = NULL;
449 bool succ = wxGetResource(section, entry, (char **)&s, file);
450 if (succ)
451 {
452 *value = (float)strtod(s, NULL);
453 delete[] s;
454 }
455
456 return succ;
457 }
458
459 bool wxGetResource(const wxString& section, const wxString& entry, long *value, const wxString& file)
460 {
461 char *s = NULL;
462 bool succ = wxGetResource(section, entry, (char **)&s, file);
463 if (succ)
464 {
465 *value = strtol(s, NULL, 10);
466 delete[] s;
467 }
468
469 return succ;
470 }
471
472 bool wxGetResource(const wxString& section, const wxString& entry, int *value, const wxString& file)
473 {
474 char *s = NULL;
475 bool succ = wxGetResource(section, entry, (char **)&s, file);
476 if (succ)
477 {
478 *value = (int)strtol(s, NULL, 10);
479 delete[] s;
480 }
481
482 return succ;
483 }
484 #endif // wxUSE_RESOURCES
485
486 int gs_wxBusyCursorCount = 0;
487 extern wxCursor gMacCurrentCursor ;
488 wxCursor gMacStoredActiveCursor ;
489
490 // Set the cursor to the busy cursor for all windows
491 void wxBeginBusyCursor(wxCursor *cursor)
492 {
493 if (gs_wxBusyCursorCount++ == 0)
494 {
495 gMacStoredActiveCursor = gMacCurrentCursor ;
496 cursor->MacInstall() ;
497 }
498 //else: nothing to do, already set
499 }
500
501 // Restore cursor to normal
502 void wxEndBusyCursor()
503 {
504 wxCHECK_RET( gs_wxBusyCursorCount > 0,
505 wxT("no matching wxBeginBusyCursor() for wxEndBusyCursor()") );
506
507 if (--gs_wxBusyCursorCount == 0)
508 {
509 gMacStoredActiveCursor.MacInstall() ;
510 gMacStoredActiveCursor = wxNullCursor ;
511 }
512 }
513
514 // true if we're between the above two calls
515 bool wxIsBusy()
516 {
517 return (gs_wxBusyCursorCount > 0);
518 }
519
520 #endif // wxUSE_GUI
521
522 #if wxUSE_BASE
523
524 wxString wxMacFindFolder( short vol,
525 OSType folderType,
526 Boolean createFolder)
527 {
528 FSRef fsRef ;
529 wxString strDir ;
530
531 if ( FSFindFolder( vol, folderType, createFolder, &fsRef) == noErr)
532 strDir = wxMacFSRefToPath( &fsRef ) + wxFILE_SEP_PATH ;
533
534 return strDir ;
535 }
536
537 #endif // wxUSE_BASE
538
539 #if wxUSE_GUI
540
541 // Check whether this window wants to process messages, e.g. Stop button
542 // in long calculations.
543 bool wxCheckForInterrupt(wxWindow *wnd)
544 {
545 // TODO
546 return false;
547 }
548
549 void wxGetMousePosition( int* x, int* y )
550 {
551 Point pt ;
552
553 GetMouse( &pt ) ;
554 LocalToGlobal( &pt ) ;
555 *x = pt.h ;
556 *y = pt.v ;
557 };
558
559 // Return true if we have a colour display
560 bool wxColourDisplay()
561 {
562 return true;
563 }
564
565 // Returns depth of screen
566 int wxDisplayDepth()
567 {
568 Rect globRect ;
569 SetRect(&globRect, -32760, -32760, 32760, 32760);
570 GDHandle theMaxDevice;
571
572 int theDepth = 8;
573 theMaxDevice = GetMaxDevice(&globRect);
574 if (theMaxDevice != NULL)
575 theDepth = (**(**theMaxDevice).gdPMap).pixelSize;
576
577 return theDepth ;
578 }
579
580 // Get size of display
581 void wxDisplaySize(int *width, int *height)
582 {
583 BitMap screenBits;
584 GetQDGlobalsScreenBits( &screenBits );
585
586 if (width != NULL)
587 *width = screenBits.bounds.right - screenBits.bounds.left ;
588
589 if (height != NULL)
590 *height = screenBits.bounds.bottom - screenBits.bounds.top ;
591 }
592
593 void wxDisplaySizeMM(int *width, int *height)
594 {
595 wxDisplaySize(width, height);
596 // on mac 72 is fixed (at least now ;-)
597 float cvPt2Mm = 25.4 / 72;
598
599 if (width != NULL)
600 *width = int( *width * cvPt2Mm );
601
602 if (height != NULL)
603 *height = int( *height * cvPt2Mm );
604 }
605
606 void wxClientDisplayRect(int *x, int *y, int *width, int *height)
607 {
608 Rect r ;
609
610 GetAvailableWindowPositioningBounds( GetMainDevice() , &r ) ;
611 if ( x )
612 *x = r.left ;
613 if ( y )
614 *y = r.top ;
615 if ( width )
616 *width = r.right - r.left ;
617 if ( height )
618 *height = r.bottom - r.top ;
619 }
620
621 wxWindow* wxFindWindowAtPoint(const wxPoint& pt)
622 {
623 return wxGenericFindWindowAtPoint(pt);
624 }
625
626 #endif // wxUSE_GUI
627
628 #if wxUSE_BASE
629
630 wxString wxGetOsDescription()
631 {
632 #ifdef WXWIN_OS_DESCRIPTION
633 // use configure generated description if available
634 return wxString(wxT("MacOS (")) + wxT(WXWIN_OS_DESCRIPTION) + wxString(wxT(")"));
635 #else
636 return wxT("MacOS") ; //TODO:define further
637 #endif
638 }
639
640 #ifndef __DARWIN__
641 wxChar *wxGetUserHome (const wxString& user)
642 {
643 // TODO
644 return NULL;
645 }
646
647 bool wxGetDiskSpace(const wxString& path, wxDiskspaceSize_t *pTotal, wxDiskspaceSize_t *pFree)
648 {
649 if ( path.empty() )
650 return false;
651
652 wxString p = path ;
653 if (p[0u] == ':' )
654 p = wxGetCwd() + p ;
655
656 int pos = p.Find(':') ;
657 if ( pos != wxNOT_FOUND )
658 p = p.Mid(1,pos) ;
659
660 p = p + wxT(":") ;
661
662 OSErr err = noErr ;
663
664 FSRef fsRef ;
665 err = wxMacPathToFSRef( p , &fsRef ) ;
666 if ( noErr == err )
667 {
668 FSVolumeRefNum vRefNum ;
669 err = FSGetVRefNum( &fsRef , &vRefNum ) ;
670 if ( noErr == err )
671 {
672 UInt64 freeBytes , totalBytes ;
673 err = FSGetVInfo( vRefNum , NULL , &freeBytes , &totalBytes ) ;
674 if ( noErr == err )
675 {
676 if ( pTotal )
677 *pTotal = wxDiskspaceSize_t( totalBytes ) ;
678 if ( pFree )
679 *pFree = wxDiskspaceSize_t( freeBytes ) ;
680 }
681 }
682 }
683
684 return err == noErr ;
685 }
686 #endif // !__DARWIN__
687
688 //---------------------------------------------------------------------------
689 // wxMac Specific utility functions
690 //---------------------------------------------------------------------------
691
692 void wxMacStringToPascal( const wxString&from , StringPtr to )
693 {
694 wxCharBuffer buf = from.mb_str( wxConvLocal ) ;
695 int len = strlen(buf) ;
696
697 if ( len > 255 )
698 len = 255 ;
699 to[0] = len ;
700 memcpy( (char*) &to[1] , buf , len ) ;
701 }
702
703 wxString wxMacMakeStringFromPascal( ConstStringPtr from )
704 {
705 return wxString( (char*) &from[1] , wxConvLocal , from[0] ) ;
706 }
707
708 // ----------------------------------------------------------------------------
709 // Common Event Support
710 // ----------------------------------------------------------------------------
711
712 extern ProcessSerialNumber gAppProcess ;
713
714 void wxMacWakeUp()
715 {
716 ProcessSerialNumber psn ;
717 Boolean isSame ;
718 psn.highLongOfPSN = 0 ;
719 psn.lowLongOfPSN = kCurrentProcess ;
720 SameProcess( &gAppProcess , &psn , &isSame ) ;
721 if ( isSame )
722 {
723 #if TARGET_CARBON
724 OSStatus err = noErr ;
725
726 #if 0
727 // lead sometimes to race conditions, although all calls used should be thread safe ...
728 static wxMacCarbonEvent s_wakeupEvent ;
729 if ( !s_wakeupEvent.IsValid() )
730 {
731 err = s_wakeupEvent.Create( 'WXMC', 'WXMC', GetCurrentEventTime(),
732 kEventAttributeNone ) ;
733 }
734 if ( err == noErr )
735 {
736
737 if ( IsEventInQueue( GetMainEventQueue() , s_wakeupEvent ) )
738 return ;
739 s_wakeupEvent.SetCurrentTime() ;
740 err = PostEventToQueue(GetMainEventQueue(), s_wakeupEvent,
741 kEventPriorityHigh );
742 }
743 #else
744 wxMacCarbonEvent wakeupEvent ;
745 wakeupEvent.Create( 'WXMC', 'WXMC', GetCurrentEventTime(),
746 kEventAttributeNone ) ;
747 err = PostEventToQueue(GetMainEventQueue(), wakeupEvent,
748 kEventPriorityHigh );
749 #endif
750 #else
751 PostEvent( nullEvent , 0 ) ;
752 #endif
753 }
754 else
755 {
756 WakeUpProcess( &gAppProcess ) ;
757 }
758 }
759
760 #endif // wxUSE_BASE
761
762 #if wxUSE_GUI
763
764 // ----------------------------------------------------------------------------
765 // Native Struct Conversions
766 // ----------------------------------------------------------------------------
767
768 void wxMacRectToNative( const wxRect *wx , Rect *n )
769 {
770 n->left = wx->x ;
771 n->top = wx->y ;
772 n->right = wx->x + wx->width ;
773 n->bottom = wx->y + wx->height ;
774 }
775
776 void wxMacNativeToRect( const Rect *n , wxRect* wx )
777 {
778 wx->x = n->left ;
779 wx->y = n->top ;
780 wx->width = n->right - n->left ;
781 wx->height = n->bottom - n->top ;
782 }
783
784 void wxMacPointToNative( const wxPoint* wx , Point *n )
785 {
786 n->h = wx->x ;
787 n->v = wx->y ;
788 }
789
790 void wxMacNativeToPoint( const Point *n , wxPoint* wx )
791 {
792 wx->x = n->h ;
793 wx->y = n->v ;
794 }
795
796 // ----------------------------------------------------------------------------
797 // Carbon Event Support
798 // ----------------------------------------------------------------------------
799
800 OSStatus wxMacCarbonEvent::GetParameter(EventParamName inName, EventParamType inDesiredType, UInt32 inBufferSize, void * outData)
801 {
802 return ::GetEventParameter( m_eventRef , inName , inDesiredType , NULL , inBufferSize , NULL , outData ) ;
803 }
804
805 OSStatus wxMacCarbonEvent::SetParameter(EventParamName inName, EventParamType inType, UInt32 inBufferSize, const void * inData)
806 {
807 return ::SetEventParameter( m_eventRef , inName , inType , inBufferSize , inData ) ;
808 }
809
810 // ----------------------------------------------------------------------------
811 // Control Access Support
812 // ----------------------------------------------------------------------------
813
814 wxMacControl::wxMacControl(wxWindow* peer , bool isRootControl )
815 {
816 Init() ;
817 m_peer = peer ;
818 m_isRootControl = isRootControl ;
819 m_isCompositing = peer->MacGetTopLevelWindow()->MacUsesCompositing() ;
820 }
821
822 wxMacControl::wxMacControl( wxWindow* peer , ControlRef control )
823 {
824 Init() ;
825 m_peer = peer ;
826 m_isCompositing = peer->MacGetTopLevelWindow()->MacUsesCompositing() ;
827 m_controlRef = control ;
828 }
829
830 wxMacControl::wxMacControl( wxWindow* peer , WXWidget control )
831 {
832 Init() ;
833 m_peer = peer ;
834 m_isCompositing = peer->MacGetTopLevelWindow()->MacUsesCompositing() ;
835 m_controlRef = (ControlRef) control ;
836 }
837
838 wxMacControl::~wxMacControl()
839 {
840 }
841
842 void wxMacControl::Init()
843 {
844 m_peer = NULL ;
845 m_controlRef = NULL ;
846 m_needsFocusRect = false ;
847 m_isCompositing = false ;
848 m_isRootControl = false ;
849 }
850
851 void wxMacControl::Dispose()
852 {
853 ::DisposeControl( m_controlRef ) ;
854 m_controlRef = NULL ;
855 }
856
857 void wxMacControl::SetReference( SInt32 data )
858 {
859 SetControlReference( m_controlRef , data ) ;
860 }
861
862 OSStatus wxMacControl::GetData(ControlPartCode inPartCode , ResType inTag , Size inBufferSize , void * inOutBuffer , Size * outActualSize ) const
863 {
864 return ::GetControlData( m_controlRef , inPartCode , inTag , inBufferSize , inOutBuffer , outActualSize ) ;
865 }
866
867 OSStatus wxMacControl::GetDataSize(ControlPartCode inPartCode , ResType inTag , Size * outActualSize ) const
868 {
869 return ::GetControlDataSize( m_controlRef , inPartCode , inTag , outActualSize ) ;
870 }
871
872 OSStatus wxMacControl::SetData(ControlPartCode inPartCode , ResType inTag , Size inSize , const void * inData)
873 {
874 return ::SetControlData( m_controlRef , inPartCode , inTag , inSize , inData ) ;
875 }
876
877 OSStatus wxMacControl::SendEvent( EventRef event , OptionBits inOptions )
878 {
879 #if TARGET_API_MAC_OSX
880 return SendEventToEventTargetWithOptions( event,
881 HIObjectGetEventTarget( (HIObjectRef) m_controlRef ), inOptions );
882 #else
883 #pragma unused(inOptions)
884 return SendEventToEventTarget(event,GetControlEventTarget( m_controlRef ) ) ;
885 #endif
886 }
887
888 OSStatus wxMacControl::SendHICommand( HICommand &command , OptionBits inOptions )
889 {
890 wxMacCarbonEvent event( kEventClassCommand , kEventCommandProcess ) ;
891
892 event.SetParameter<HICommand>(kEventParamDirectObject,command) ;
893
894 return SendEvent( event , inOptions ) ;
895 }
896
897 OSStatus wxMacControl::SendHICommand( UInt32 commandID , OptionBits inOptions )
898 {
899 HICommand command ;
900
901 memset( &command, 0 , sizeof(command) ) ;
902 command.commandID = commandID ;
903 return SendHICommand( command , inOptions ) ;
904 }
905
906 void wxMacControl::Flash( ControlPartCode part , UInt32 ticks )
907 {
908 unsigned long finalTicks ;
909
910 HiliteControl( m_controlRef , part ) ;
911 Delay( ticks , &finalTicks ) ;
912 HiliteControl( m_controlRef , kControlNoPart ) ;
913 }
914
915 SInt32 wxMacControl::GetValue() const
916 {
917 return ::GetControl32BitValue( m_controlRef ) ;
918 }
919
920 SInt32 wxMacControl::GetMaximum() const
921 {
922 return ::GetControl32BitMaximum( m_controlRef ) ;
923 }
924
925 SInt32 wxMacControl::GetMinimum() const
926 {
927 return ::GetControl32BitMinimum( m_controlRef ) ;
928 }
929
930 void wxMacControl::SetValue( SInt32 v )
931 {
932 ::SetControl32BitValue( m_controlRef , v ) ;
933 }
934
935 void wxMacControl::SetMinimum( SInt32 v )
936 {
937 ::SetControl32BitMinimum( m_controlRef , v ) ;
938 }
939
940 void wxMacControl::SetMaximum( SInt32 v )
941 {
942 ::SetControl32BitMaximum( m_controlRef , v ) ;
943 }
944
945 void wxMacControl::SetValueAndRange( SInt32 value , SInt32 minimum , SInt32 maximum )
946 {
947 ::SetControl32BitMinimum( m_controlRef , minimum ) ;
948 ::SetControl32BitMaximum( m_controlRef , maximum ) ;
949 ::SetControl32BitValue( m_controlRef , value ) ;
950 }
951
952 OSStatus wxMacControl::SetFocus( ControlFocusPart focusPart )
953 {
954 return SetKeyboardFocus( GetControlOwner( m_controlRef ), m_controlRef, focusPart ) ;
955 }
956
957 bool wxMacControl::HasFocus() const
958 {
959 ControlRef control ;
960 GetKeyboardFocus( GetUserFocusWindow() , &control ) ;
961 return control == m_controlRef ;
962 }
963
964 void wxMacControl::SetNeedsFocusRect( bool needs )
965 {
966 m_needsFocusRect = needs ;
967 }
968
969 bool wxMacControl::NeedsFocusRect() const
970 {
971 return m_needsFocusRect ;
972 }
973
974 void wxMacControl::VisibilityChanged(bool shown)
975 {
976 }
977
978 void wxMacControl::SuperChangedPosition()
979 {
980 }
981
982 void wxMacControl::SetFont( const wxFont & font , const wxColour& foreground , long windowStyle )
983 {
984 m_font = font ;
985 ControlFontStyleRec fontStyle;
986 if ( font.MacGetThemeFontID() != kThemeCurrentPortFont )
987 {
988 switch ( font.MacGetThemeFontID() )
989 {
990 case kThemeSmallSystemFont :
991 fontStyle.font = kControlFontSmallSystemFont ;
992 break ;
993
994 case 109 : // mini font
995 fontStyle.font = -5 ;
996 break ;
997
998 case kThemeSystemFont :
999 fontStyle.font = kControlFontBigSystemFont ;
1000 break ;
1001
1002 default :
1003 fontStyle.font = kControlFontBigSystemFont ;
1004 break ;
1005 }
1006
1007 fontStyle.flags = kControlUseFontMask ;
1008 }
1009 else
1010 {
1011 fontStyle.font = font.MacGetFontNum() ;
1012 fontStyle.style = font.MacGetFontStyle() ;
1013 fontStyle.size = font.MacGetFontSize() ;
1014 fontStyle.flags = kControlUseFontMask | kControlUseFaceMask | kControlUseSizeMask ;
1015 }
1016
1017 fontStyle.just = teJustLeft ;
1018 fontStyle.flags |= kControlUseJustMask ;
1019 if ( ( windowStyle & wxALIGN_MASK ) & wxALIGN_CENTER_HORIZONTAL )
1020 fontStyle.just = teJustCenter ;
1021 else if ( ( windowStyle & wxALIGN_MASK ) & wxALIGN_RIGHT )
1022 fontStyle.just = teJustRight ;
1023
1024
1025 // we only should do this in case of a non-standard color, as otherwise 'disabled' controls
1026 // won't get grayed out by the system anymore
1027
1028 if ( foreground != *wxBLACK )
1029 {
1030 fontStyle.foreColor = MAC_WXCOLORREF( foreground.GetPixel() ) ;
1031 fontStyle.flags |= kControlUseForeColorMask ;
1032 }
1033
1034 ::SetControlFontStyle( m_controlRef , &fontStyle );
1035 }
1036
1037 void wxMacControl::SetBackground( const wxBrush &WXUNUSED(brush) )
1038 {
1039 // TODO
1040 // setting up a color proc is not recommended anymore
1041 }
1042
1043 void wxMacControl::SetRange( SInt32 minimum , SInt32 maximum )
1044 {
1045 ::SetControl32BitMinimum( m_controlRef , minimum ) ;
1046 ::SetControl32BitMaximum( m_controlRef , maximum ) ;
1047 }
1048
1049 short wxMacControl::HandleKey( SInt16 keyCode, SInt16 charCode, EventModifiers modifiers )
1050 {
1051 return HandleControlKey( m_controlRef , keyCode , charCode , modifiers ) ;
1052 }
1053
1054 void wxMacControl::SetActionProc( ControlActionUPP actionProc )
1055 {
1056 SetControlAction( m_controlRef , actionProc ) ;
1057 }
1058
1059 void wxMacControl::SetViewSize( SInt32 viewSize )
1060 {
1061 SetControlViewSize(m_controlRef , viewSize ) ;
1062 }
1063
1064 SInt32 wxMacControl::GetViewSize() const
1065 {
1066 return GetControlViewSize( m_controlRef ) ;
1067 }
1068
1069 bool wxMacControl::IsVisible() const
1070 {
1071 return IsControlVisible( m_controlRef ) ;
1072 }
1073
1074 void wxMacControl::SetVisibility( bool visible , bool redraw )
1075 {
1076 SetControlVisibility( m_controlRef , visible , redraw ) ;
1077 }
1078
1079 bool wxMacControl::IsEnabled() const
1080 {
1081 #if TARGET_API_MAC_OSX
1082 return IsControlEnabled( m_controlRef ) ;
1083 #else
1084 return IsControlActive( m_controlRef ) ;
1085 #endif
1086 }
1087
1088 bool wxMacControl::IsActive() const
1089 {
1090 return IsControlActive( m_controlRef ) ;
1091 }
1092
1093 void wxMacControl::Enable( bool enable )
1094 {
1095 #if TARGET_API_MAC_OSX
1096 if ( enable )
1097 EnableControl( m_controlRef ) ;
1098 else
1099 DisableControl( m_controlRef ) ;
1100 #else
1101 if ( enable )
1102 ActivateControl( m_controlRef ) ;
1103 else
1104 DeactivateControl( m_controlRef ) ;
1105 #endif
1106 }
1107
1108 void wxMacControl::SetDrawingEnabled( bool enable )
1109 {
1110 #if TARGET_API_MAC_OSX
1111 HIViewSetDrawingEnabled( m_controlRef , enable ) ;
1112 #endif
1113 }
1114
1115 #if TARGET_API_MAC_OSX
1116 bool wxMacControl::GetNeedsDisplay() const
1117 {
1118 #if TARGET_API_MAC_OSX
1119 if ( m_isCompositing )
1120 {
1121 return HIViewGetNeedsDisplay( m_controlRef ) ;
1122 }
1123 else
1124 #endif
1125 {
1126 if ( !IsVisible() )
1127 return false ;
1128
1129 Rect controlBounds ;
1130 GetControlBounds( m_controlRef, &controlBounds ) ;
1131 RgnHandle rgn = NewRgn() ;
1132 GetWindowRegion ( GetControlOwner( m_controlRef ) , kWindowUpdateRgn , rgn ) ;
1133 Boolean intersect = RectInRgn ( &controlBounds , rgn ) ;
1134 DisposeRgn( rgn ) ;
1135
1136 return intersect ;
1137 }
1138 }
1139 #endif
1140
1141 void wxMacControl::SetNeedsDisplay( RgnHandle where )
1142 {
1143 if ( !IsVisible() )
1144 return ;
1145
1146 #if TARGET_API_MAC_OSX
1147 if ( m_isCompositing )
1148 {
1149 HIViewSetNeedsDisplayInRegion( m_controlRef , where , true ) ;
1150 }
1151 else
1152 #endif
1153 {
1154 Rect controlBounds ;
1155 GetControlBounds( m_controlRef, &controlBounds ) ;
1156 RgnHandle update = NewRgn() ;
1157 CopyRgn( where , update ) ;
1158 OffsetRgn( update , controlBounds.left , controlBounds.top ) ;
1159 InvalWindowRgn( GetControlOwner( m_controlRef) , update ) ;
1160 }
1161 }
1162
1163 void wxMacControl::SetNeedsDisplay( Rect* where )
1164 {
1165 if ( !IsVisible() )
1166 return ;
1167
1168 #if TARGET_API_MAC_OSX
1169 if ( m_isCompositing )
1170 {
1171 if ( where != NULL )
1172 {
1173 RgnHandle update = NewRgn() ;
1174 RectRgn( update , where ) ;
1175 HIViewSetNeedsDisplayInRegion( m_controlRef , update , true ) ;
1176 DisposeRgn( update ) ;
1177 }
1178 else
1179 HIViewSetNeedsDisplay( m_controlRef , true ) ;
1180 }
1181 else
1182 #endif
1183 {
1184 Rect controlBounds ;
1185
1186 GetControlBounds( m_controlRef, &controlBounds ) ;
1187 if ( where )
1188 {
1189 Rect whereLocal = *where ;
1190 OffsetRect( &whereLocal , controlBounds.left , controlBounds.top ) ;
1191 SectRect( &controlBounds , &whereLocal, &controlBounds ) ;
1192 }
1193
1194 InvalWindowRect( GetControlOwner( m_controlRef) , &controlBounds ) ;
1195 }
1196 }
1197
1198 void wxMacControl::Convert( wxPoint *pt , wxMacControl *from , wxMacControl *to )
1199 {
1200 #if TARGET_API_MAC_OSX
1201 if ( from->m_peer->MacGetTopLevelWindow()->MacUsesCompositing() )
1202 {
1203 HIPoint hiPoint ;
1204
1205 hiPoint.x = pt->x ;
1206 hiPoint.y = pt->y ;
1207 HIViewConvertPoint( &hiPoint , from->m_controlRef , to->m_controlRef ) ;
1208 pt->x = (int)hiPoint.x ;
1209 pt->y = (int)hiPoint.y ;
1210 }
1211 else
1212 #endif
1213 {
1214 Rect fromRect, toRect ;
1215
1216 GetControlBounds( from->m_controlRef , &fromRect ) ;
1217 GetControlBounds( to->m_controlRef , &toRect ) ;
1218 if ( from->m_isRootControl )
1219 fromRect.left = fromRect.top = 0 ;
1220 if ( to->m_isRootControl )
1221 toRect.left = toRect.top = 0 ;
1222
1223 pt->x = pt->x + fromRect.left - toRect.left ;
1224 pt->y = pt->y + fromRect.top - toRect.top ;
1225 }
1226 }
1227
1228 void wxMacControl::SetRect( Rect *r )
1229 {
1230 #if TARGET_API_MAC_OSX
1231 if ( m_isCompositing )
1232 {
1233 //A HIRect is actually a CGRect on OSX - which consists of two structures -
1234 //CGPoint and CGSize, which have two floats each
1235 HIRect hir = { { r->left , r->top }, { r->right - r->left , r->bottom - r->top } } ;
1236 HIViewSetFrame ( m_controlRef , &hir ) ;
1237 // eventuall we might have to do a SetVisibility( false , true ) ;
1238 // before and a SetVisibility( true , true ) ; after
1239 }
1240 else
1241 #endif
1242 {
1243 bool vis = IsVisible() ;
1244 if ( vis )
1245 {
1246 Rect former ;
1247 GetControlBounds( m_controlRef , &former ) ;
1248 InvalWindowRect( GetControlOwner( m_controlRef ) , &former ) ;
1249 }
1250
1251 Rect controlBounds = *r ;
1252
1253 // since the rect passed in is always (even in non-compositing) relative
1254 // to the (native) parent, we have to adjust to window relative here
1255 wxMacControl* parent = m_peer->GetParent()->GetPeer() ;
1256 if ( !parent->m_isRootControl )
1257 {
1258 Rect superRect ;
1259 GetControlBounds( parent->m_controlRef , &superRect ) ;
1260 OffsetRect( &controlBounds , superRect.left , superRect.top ) ;
1261 }
1262
1263 SetControlBounds( m_controlRef , &controlBounds ) ;
1264 if ( vis )
1265 InvalWindowRect( GetControlOwner( m_controlRef ) , &controlBounds ) ;
1266 }
1267 }
1268
1269 void wxMacControl::GetRect( Rect *r )
1270 {
1271 GetControlBounds( m_controlRef , r ) ;
1272 if ( !m_isCompositing )
1273 {
1274 // correct the case of the root control
1275 if ( m_isRootControl )
1276 {
1277 WindowRef wr = GetControlOwner( m_controlRef ) ;
1278 GetWindowBounds( wr , kWindowContentRgn , r ) ;
1279 r->right -= r->left ;
1280 r->bottom -= r->top ;
1281 r->left = 0 ;
1282 r->top = 0 ;
1283 }
1284 else
1285 {
1286 wxMacControl* parent = m_peer->GetParent()->GetPeer() ;
1287 if ( !parent->m_isRootControl )
1288 {
1289 Rect superRect ;
1290 GetControlBounds( parent->m_controlRef , &superRect ) ;
1291 OffsetRect( r , -superRect.left , -superRect.top ) ;
1292 }
1293 }
1294 }
1295 }
1296
1297 void wxMacControl::GetRectInWindowCoords( Rect *r )
1298 {
1299 UMAGetControlBoundsInWindowCoords( m_controlRef , r ) ;
1300 }
1301
1302 void wxMacControl::GetBestRect( Rect *r )
1303 {
1304 short baselineoffset ;
1305
1306 GetBestControlRect( m_controlRef , r , &baselineoffset ) ;
1307 }
1308
1309 void wxMacControl::SetLabel( const wxString &title )
1310 {
1311 wxFontEncoding encoding;
1312
1313 if ( m_font.Ok() )
1314 encoding = m_font.GetEncoding();
1315 else
1316 encoding = wxFont::GetDefaultEncoding();
1317
1318 UMASetControlTitle( m_controlRef , title , encoding ) ;
1319 }
1320
1321 void wxMacControl::GetFeatures( UInt32 * features )
1322 {
1323 GetControlFeatures( m_controlRef , features ) ;
1324 }
1325
1326 OSStatus wxMacControl::GetRegion( ControlPartCode partCode , RgnHandle region )
1327 {
1328 OSStatus err = GetControlRegion( m_controlRef , partCode , region ) ;
1329 if ( !m_isCompositing )
1330 {
1331 if ( !m_isRootControl )
1332 {
1333 Rect r ;
1334
1335 GetControlBounds(m_controlRef, &r ) ;
1336 if ( !EmptyRgn( region ) )
1337 OffsetRgn( region , -r.left , -r.top ) ;
1338 }
1339 }
1340
1341 return err ;
1342 }
1343
1344 OSStatus wxMacControl::SetZOrder( bool above , wxMacControl* other )
1345 {
1346 #if TARGET_API_MAC_OSX
1347 return HIViewSetZOrder( m_controlRef,above ? kHIViewZOrderAbove : kHIViewZOrderBelow,
1348 (other != NULL) ? other->m_controlRef : NULL) ;
1349 #else
1350 return 0 ;
1351 #endif
1352 }
1353
1354 #if TARGET_API_MAC_OSX
1355 // SetNeedsDisplay would not invalidate the children
1356 static void InvalidateControlAndChildren( HIViewRef control )
1357 {
1358 HIViewSetNeedsDisplay( control , true ) ;
1359 UInt16 childrenCount = 0 ;
1360 OSStatus err = CountSubControls( control , &childrenCount ) ;
1361 if ( err == errControlIsNotEmbedder )
1362 return ;
1363
1364 wxASSERT_MSG( err == noErr , wxT("Unexpected error when accessing subcontrols") ) ;
1365
1366 for ( UInt16 i = childrenCount ; i >=1 ; --i )
1367 {
1368 HIViewRef child ;
1369
1370 err = GetIndexedSubControl( control , i , & child ) ;
1371 if ( err == errControlIsNotEmbedder )
1372 return ;
1373
1374 InvalidateControlAndChildren( child ) ;
1375 }
1376 }
1377 #endif
1378
1379 void wxMacControl::InvalidateWithChildren()
1380 {
1381 #if TARGET_API_MAC_OSX
1382 InvalidateControlAndChildren( m_controlRef ) ;
1383 #endif
1384 }
1385
1386 void wxMacControl::ScrollRect( wxRect *r , int dx , int dy )
1387 {
1388 wxASSERT( r != NULL ) ;
1389
1390 #if TARGET_API_MAC_OSX
1391 if ( m_isCompositing )
1392 {
1393 HIRect scrollarea = CGRectMake( r->x , r->y , r->width , r->height) ;
1394 HIViewScrollRect ( m_controlRef , &scrollarea , dx ,dy ) ;
1395 }
1396 else
1397 #endif
1398 {
1399 Rect bounds ;
1400
1401 GetControlBounds( m_controlRef , &bounds ) ;
1402 bounds.left += r->x ;
1403 bounds.top += r->y ;
1404 bounds.bottom = bounds.top + r->height ;
1405 bounds.right = bounds.left + r->width ;
1406 wxMacWindowClipper clip( m_peer ) ;
1407 RgnHandle updateRgn = NewRgn() ;
1408 ::ScrollRect( &bounds , dx , dy , updateRgn ) ;
1409 InvalWindowRgn( GetControlOwner( m_controlRef ) , updateRgn ) ;
1410 DisposeRgn( updateRgn );
1411 }
1412 }
1413
1414 //
1415 // Tab Control
1416 //
1417
1418 OSStatus wxMacControl::SetTabEnabled( SInt16 tabNo , bool enable )
1419 {
1420 return ::SetTabEnabled( m_controlRef , tabNo , enable ) ;
1421 }
1422
1423 //
1424 // Quartz Support
1425 //
1426
1427 #ifdef __WXMAC_OSX__
1428 // snippets from Sketch Sample from Apple :
1429
1430 #define kGenericRGBProfilePathStr "/System/Library/ColorSync/Profiles/Generic RGB Profile.icc"
1431
1432 /*
1433 This function locates, opens, and returns the profile reference for the calibrated
1434 Generic RGB color space. It is up to the caller to call CMCloseProfile when done
1435 with the profile reference this function returns.
1436 */
1437 CMProfileRef wxMacOpenGenericProfile()
1438 {
1439 static CMProfileRef cachedRGBProfileRef = NULL;
1440
1441 // we only create the profile reference once
1442 if (cachedRGBProfileRef == NULL)
1443 {
1444 CMProfileLocation loc;
1445
1446 loc.locType = cmPathBasedProfile;
1447 strcpy(loc.u.pathLoc.path, kGenericRGBProfilePathStr);
1448
1449 verify_noerr( CMOpenProfile(&cachedRGBProfileRef, &loc) );
1450 }
1451
1452 // clone the profile reference so that the caller has their own reference, not our cached one
1453 if (cachedRGBProfileRef)
1454 CMCloneProfileRef(cachedRGBProfileRef);
1455
1456 return cachedRGBProfileRef;
1457 }
1458
1459 /*
1460 Return the generic RGB color space. This is a 'get' function and the caller should
1461 not release the returned value unless the caller retains it first. Usually callers
1462 of this routine will immediately use the returned colorspace with CoreGraphics
1463 so they typically do not need to retain it themselves.
1464
1465 This function creates the generic RGB color space once and hangs onto it so it can
1466 return it whenever this function is called.
1467 */
1468
1469 CGColorSpaceRef wxMacGetGenericRGBColorSpace()
1470 {
1471 static wxMacCFRefHolder<CGColorSpaceRef> genericRGBColorSpace ;
1472
1473 if (genericRGBColorSpace == NULL)
1474 {
1475 if ( UMAGetSystemVersion() >= 0x1040 )
1476 {
1477 genericRGBColorSpace.Set( CGColorSpaceCreateWithName( CFSTR("kCGColorSpaceGenericRGB") ) ) ;
1478 }
1479 else
1480 {
1481 CMProfileRef genericRGBProfile = wxMacOpenGenericProfile();
1482
1483 if (genericRGBProfile)
1484 {
1485 genericRGBColorSpace.Set( CGColorSpaceCreateWithPlatformColorSpace(genericRGBProfile) ) ;
1486
1487 wxASSERT_MSG( genericRGBColorSpace != NULL, wxT("couldn't create the generic RGB color space") ) ;
1488
1489 // we opened the profile so it is up to us to close it
1490 CMCloseProfile(genericRGBProfile);
1491 }
1492 }
1493 }
1494
1495 return genericRGBColorSpace;
1496 }
1497 #endif
1498
1499 wxMacPortSaver::wxMacPortSaver( GrafPtr port )
1500 {
1501 ::GetPort( &m_port ) ;
1502 ::SetPort( port ) ;
1503 }
1504
1505 wxMacPortSaver::~wxMacPortSaver()
1506 {
1507 ::SetPort( m_port ) ;
1508 }
1509
1510 #endif // wxUSE_GUI