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