first round of debug/release merge: introduce wxDEBUG_LEVEL, for now defined as 1...
[wxWidgets.git] / src / cocoa / display.mm
1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/cocoa/display.mm
3 // Purpose:     Cocoa implementation of wxDisplay class
4 // Author:      Ryan Norton
5 // Modified by:
6 // Created:     2004-10-03
7 // RCS-ID:      $Id$
8 // Copyright:   (c) Ryan Norton
9 // Licence:     wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #ifdef __BORLANDC__
16     #pragma hdrstop
17 #endif
18
19 #if wxUSE_DISPLAY
20
21 #include "wx/display.h"
22
23 #ifndef WX_PRECOMP
24     #include "wx/dynarray.h"
25     #include "wx/string.h"
26     #include "wx/gdicmn.h"
27 #endif
28
29 #include "wx/display_impl.h"
30
31 #import <Foundation/Foundation.h>
32
33 // ----------------------------------------------------------------------------
34 // display classes implementation
35 // ----------------------------------------------------------------------------
36
37 class wxDisplayImplMacOSX : public wxDisplayImpl
38 {
39 public:
40     wxDisplayImplMacOSX(unsigned n, CGDirectDisplayID id_)
41         : wxDisplayImpl(n),
42           m_id(id_)
43     {
44     }
45
46     virtual wxRect GetGeometry() const;
47     virtual wxString GetName() const { return wxString(); }
48
49     virtual wxArrayVideoModes GetModes(const wxVideoMode& mode) const;
50     virtual wxVideoMode GetCurrentMode() const;
51     virtual bool ChangeMode(const wxVideoMode& mode);
52
53 private:
54     CGDirectDisplayID m_id;
55
56     wxDECLARE_NO_COPY_CLASS(wxDisplayImplMacOSX);
57 };
58
59 class wxDisplayFactoryMacOSX : public wxDisplayFactory
60 {
61 public:
62     wxDisplayFactoryMacOSX() { }
63
64     virtual wxDisplayImpl *CreateDisplay(unsigned n);
65     virtual unsigned GetCount();
66     virtual int GetFromPoint(const wxPoint& pt);
67
68 protected:
69     wxDECLARE_NO_COPY_CLASS(wxDisplayFactoryMacOSX);
70 };
71
72 // ============================================================================
73 // wxDisplayFactoryMacOSX implementation
74 // ============================================================================
75
76 unsigned wxDisplayFactoryMacOSX::GetCount()
77 {
78     CGDisplayCount count;
79 #ifdef __WXDEBUG__
80     CGDisplayErr err =
81 #endif
82     CGGetActiveDisplayList(0, NULL, &count);
83
84     wxASSERT(err == CGDisplayNoErr);
85
86     return count;
87 }
88
89 int wxDisplayFactoryMacOSX::GetFromPoint(const wxPoint& p)
90 {
91     CGPoint thePoint = {(float)p.x, (float)p.y};
92     CGDirectDisplayID theID;
93     CGDisplayCount theCount;
94     CGDisplayErr err = CGGetDisplaysWithPoint(thePoint, 1, &theID, &theCount);
95     wxASSERT(err == CGDisplayNoErr);
96
97     int nWhich = wxNOT_FOUND;
98
99     if (theCount)
100     {
101         theCount = GetCount();
102         CGDirectDisplayID* theIDs = new CGDirectDisplayID[theCount];
103         err = CGGetActiveDisplayList(theCount, theIDs, &theCount);
104         wxASSERT(err == CGDisplayNoErr);
105
106         for (nWhich = 0; nWhich < (int) theCount; ++nWhich)
107         {
108             if (theIDs[nWhich] == theID)
109                 break;
110         }
111
112         delete [] theIDs;
113
114         if (nWhich == (int) theCount)
115         {
116             wxFAIL_MSG(wxT("Failed to find display in display list"));
117             nWhich = wxNOT_FOUND;
118         }
119     }
120
121     return nWhich;
122 }
123
124 wxDisplayImpl *wxDisplayFactoryMacOSX::CreateDisplay(unsigned n)
125 {
126     CGDisplayCount theCount = GetCount();
127     CGDirectDisplayID* theIDs = new CGDirectDisplayID[theCount];
128
129 #ifdef __WXDEBUG__
130     CGDisplayErr err =
131 #endif
132     CGGetActiveDisplayList(theCount, theIDs, &theCount);
133
134     wxASSERT( err == CGDisplayNoErr );
135     wxASSERT( n < theCount );
136
137     wxDisplayImplMacOSX *display = new wxDisplayImplMacOSX(n, theIDs[n]);
138
139     delete [] theIDs;
140
141     return display;
142 }
143
144
145 wxRect wxDisplayImplMacOSX::GetGeometry() const
146 {
147     CGRect theRect = CGDisplayBounds(m_id);
148     return wxRect(  (int)theRect.origin.x,
149                     (int)theRect.origin.y,
150                     (int)theRect.size.width,
151                     (int)theRect.size.height  ); //floats
152 }
153
154 static int wxCFDictKeyToInt( CFDictionaryRef desc, CFStringRef key )
155 {
156     CFNumberRef value;
157     int num = 0;
158
159     if ( (value = (CFNumberRef) CFDictionaryGetValue(desc, key)) == NULL )
160         return 0;
161     CFNumberGetValue(value, kCFNumberIntType, &num);
162     return num;
163 }
164
165 wxArrayVideoModes wxDisplayImplMacOSX::GetModes(const wxVideoMode& mode) const
166 {
167     wxArrayVideoModes Modes;
168
169     CFArrayRef theArray = CGDisplayAvailableModes(m_id);
170
171     for(CFIndex i = 0; i < CFArrayGetCount(theArray); ++i)
172     {
173         CFDictionaryRef theValue = (CFDictionaryRef) CFArrayGetValueAtIndex(theArray, i);
174
175         wxVideoMode theMode(wxCFDictKeyToInt(theValue, kCGDisplayWidth),
176                             wxCFDictKeyToInt(theValue, kCGDisplayHeight),
177                             wxCFDictKeyToInt(theValue, kCGDisplayBitsPerPixel),
178                             wxCFDictKeyToInt(theValue, kCGDisplayRefreshRate));
179
180         if (theMode.Matches(mode))
181             Modes.Add(theMode);
182     }
183
184     return Modes;
185 }
186
187 wxVideoMode wxDisplayImplMacOSX::GetCurrentMode() const
188 {
189     CFDictionaryRef theValue = CGDisplayCurrentMode (m_id);
190
191     return wxVideoMode(wxCFDictKeyToInt(theValue, kCGDisplayWidth),
192                             wxCFDictKeyToInt(theValue, kCGDisplayHeight),
193                             wxCFDictKeyToInt(theValue, kCGDisplayBitsPerPixel),
194                             wxCFDictKeyToInt(theValue, kCGDisplayRefreshRate));
195 }
196
197 bool wxDisplayImplMacOSX::ChangeMode(const wxVideoMode& mode)
198 {
199     //Changing to default mode (wxDefualtVideoMode) doesn't
200     //work because we don't have access to the system's 'scrn'
201     //resource which holds the user's mode which the system
202     //will return to after this app is done
203     boolean_t bExactMatch;
204     CFDictionaryRef theCGMode = CGDisplayBestModeForParametersAndRefreshRate (
205                                         m_id,
206                                         (size_t)mode.bpp,
207                                         (size_t)mode.w,
208                                         (size_t)mode.h,
209                                         (double)mode.refresh,
210                                         &bExactMatch);
211
212     bool bOK = bExactMatch;
213
214     if(bOK)
215         bOK = CGDisplaySwitchToMode(m_id, theCGMode) == CGDisplayNoErr;
216
217     return bOK;
218 }
219
220 // ============================================================================
221 // wxDisplay::CreateFactory()
222 // ============================================================================
223
224 /* static */ wxDisplayFactory *wxDisplay::CreateFactory()
225 {
226     return new wxDisplayFactoryMacOSX;
227 }
228
229 #endif // wxUSE_DISPLAY