]> git.saurik.com Git - wxWidgets.git/blob - src/osx/core/display.cpp
b1961bc92e3a69248e4b9f477122425948e291a4
[wxWidgets.git] / src / osx / core / display.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/osx/core/display.cpp
3 // Purpose: Mac implementation of wxDisplay class
4 // Author: Ryan Norton & Brian Victor
5 // Modified by: Royce Mitchell III, Vadim Zeitlin
6 // Created: 06/21/02
7 // Copyright: (c) wxWidgets team
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11 // ============================================================================
12 // declarations
13 // ============================================================================
14
15 // ----------------------------------------------------------------------------
16 // headers
17 // ----------------------------------------------------------------------------
18
19 #include "wx/wxprec.h"
20
21 #ifdef __BORLANDC__
22 #pragma hdrstop
23 #endif
24
25 #if wxUSE_DISPLAY
26
27 #include "wx/display.h"
28
29 #ifndef WX_PRECOMP
30 #include "wx/dynarray.h"
31 #include "wx/log.h"
32 #include "wx/string.h"
33 #include "wx/gdicmn.h"
34 #endif
35
36 #include "wx/display_impl.h"
37 #include "wx/osx/private.h"
38
39 #if wxOSX_USE_COCOA_OR_CARBON
40
41 // ----------------------------------------------------------------------------
42 // display classes implementation
43 // ----------------------------------------------------------------------------
44
45 class wxDisplayImplMacOSX : public wxDisplayImpl
46 {
47 public:
48 wxDisplayImplMacOSX(unsigned n, CGDirectDisplayID id)
49 : wxDisplayImpl(n),
50 m_id(id)
51 {
52 }
53
54 virtual wxRect GetGeometry() const;
55 virtual wxRect GetClientArea() const;
56 virtual wxString GetName() const { return wxString(); }
57
58 virtual wxArrayVideoModes GetModes(const wxVideoMode& mode) const;
59 virtual wxVideoMode GetCurrentMode() const;
60 virtual bool ChangeMode(const wxVideoMode& mode);
61
62 virtual bool IsPrimary() const;
63
64 private:
65 CGDirectDisplayID m_id;
66
67 wxDECLARE_NO_COPY_CLASS(wxDisplayImplMacOSX);
68 };
69
70 class wxDisplayFactoryMacOSX : public wxDisplayFactory
71 {
72 public:
73 wxDisplayFactoryMacOSX() {}
74
75 virtual wxDisplayImpl *CreateDisplay(unsigned n);
76 virtual unsigned GetCount();
77 virtual int GetFromPoint(const wxPoint& pt);
78
79 protected:
80 wxDECLARE_NO_COPY_CLASS(wxDisplayFactoryMacOSX);
81 };
82
83 // ============================================================================
84 // wxDisplayFactoryMacOSX implementation
85 // ============================================================================
86
87 // gets all displays that are not mirror displays
88
89 static CGDisplayErr wxOSXGetDisplayList(CGDisplayCount maxDisplays,
90 CGDirectDisplayID *displays,
91 CGDisplayCount *displayCount)
92 {
93 CGDisplayErr error = kCGErrorSuccess;
94 CGDisplayCount onlineCount;
95
96 error = CGGetOnlineDisplayList(0,NULL,&onlineCount);
97 if ( error == kCGErrorSuccess )
98 {
99 *displayCount = 0;
100 if ( onlineCount > 0 )
101 {
102 CGDirectDisplayID *onlineDisplays = new CGDirectDisplayID[onlineCount];
103 error = CGGetOnlineDisplayList(onlineCount,onlineDisplays,&onlineCount);
104 if ( error == kCGErrorSuccess )
105 {
106 for ( CGDisplayCount i = 0; i < onlineCount; ++i )
107 {
108 if ( CGDisplayMirrorsDisplay(onlineDisplays[i]) != kCGNullDirectDisplay )
109 continue;
110
111 if ( displays == NULL )
112 *displayCount += 1;
113 else
114 {
115 if ( *displayCount < maxDisplays )
116 {
117 displays[*displayCount] = onlineDisplays[i];
118 *displayCount += 1;
119 }
120 }
121 }
122 }
123 delete[] onlineDisplays;
124 }
125
126 }
127 return error;
128 }
129
130 unsigned wxDisplayFactoryMacOSX::GetCount()
131 {
132 CGDisplayCount count;
133 CGDisplayErr err = wxOSXGetDisplayList(0, NULL, &count);
134
135 wxCHECK_MSG( err == CGDisplayNoErr, 0, "wxOSXGetDisplayList() failed" );
136
137 return count;
138 }
139
140 int wxDisplayFactoryMacOSX::GetFromPoint(const wxPoint& p)
141 {
142 CGPoint thePoint = {(float)p.x, (float)p.y};
143 CGDirectDisplayID theID;
144 CGDisplayCount theCount;
145 CGDisplayErr err = CGGetDisplaysWithPoint(thePoint, 1, &theID, &theCount);
146 wxASSERT(err == CGDisplayNoErr);
147
148 int nWhich = wxNOT_FOUND;
149
150 if (theCount)
151 {
152 theCount = GetCount();
153 CGDirectDisplayID* theIDs = new CGDirectDisplayID[theCount];
154 err = wxOSXGetDisplayList(theCount, theIDs, &theCount);
155 wxASSERT(err == CGDisplayNoErr);
156
157 for (nWhich = 0; nWhich < (int) theCount; ++nWhich)
158 {
159 if (theIDs[nWhich] == theID)
160 break;
161 }
162
163 delete [] theIDs;
164
165 if (nWhich == (int) theCount)
166 {
167 wxFAIL_MSG(wxT("Failed to find display in display list"));
168 nWhich = wxNOT_FOUND;
169 }
170 }
171
172 return nWhich;
173 }
174
175 wxDisplayImpl *wxDisplayFactoryMacOSX::CreateDisplay(unsigned n)
176 {
177 CGDisplayCount theCount = GetCount();
178 CGDirectDisplayID* theIDs = new CGDirectDisplayID[theCount];
179
180 CGDisplayErr err = wxOSXGetDisplayList(theCount, theIDs, &theCount);
181 wxCHECK_MSG( err == CGDisplayNoErr, NULL, "wxOSXGetDisplayList() failed" );
182
183 wxASSERT( n < theCount );
184
185 wxDisplayImplMacOSX *display = new wxDisplayImplMacOSX(n, theIDs[n]);
186
187 delete [] theIDs;
188
189 return display;
190 }
191
192 // ============================================================================
193 // wxDisplayImplMacOSX implementation
194 // ============================================================================
195
196 bool wxDisplayImplMacOSX::IsPrimary() const
197 {
198 return CGDisplayIsMain(m_id);
199 }
200
201 wxRect wxDisplayImplMacOSX::GetGeometry() const
202 {
203 CGRect theRect = CGDisplayBounds(m_id);
204 return wxRect( (int)theRect.origin.x,
205 (int)theRect.origin.y,
206 (int)theRect.size.width,
207 (int)theRect.size.height ); //floats
208 }
209
210 wxRect wxDisplayImplMacOSX::GetClientArea() const
211 {
212 // VZ: I don't know how to get client area for arbitrary display but
213 // wxGetClientDisplayRect() does work correctly for at least the main
214 // one (TODO: do it correctly for the other displays too)
215 if ( IsPrimary() )
216 return wxGetClientDisplayRect();
217
218 return wxDisplayImpl::GetClientArea();
219 }
220
221 static int wxCFDictKeyToInt( CFDictionaryRef desc, CFStringRef key )
222 {
223 CFNumberRef value = (CFNumberRef) CFDictionaryGetValue( desc, key );
224 if (value == NULL)
225 return 0;
226
227 int num = 0;
228 CFNumberGetValue( value, kCFNumberIntType, &num );
229
230 return num;
231 }
232
233 wxArrayVideoModes wxDisplayImplMacOSX::GetModes(const wxVideoMode& mode) const
234 {
235 wxArrayVideoModes resultModes;
236
237 CFArrayRef theArray = CGDisplayAvailableModes( m_id );
238
239 for (CFIndex i = 0; i < CFArrayGetCount(theArray); ++i)
240 {
241 CFDictionaryRef theValue = (CFDictionaryRef) CFArrayGetValueAtIndex( theArray, i );
242
243 wxVideoMode theMode(
244 wxCFDictKeyToInt( theValue, kCGDisplayWidth ),
245 wxCFDictKeyToInt( theValue, kCGDisplayHeight ),
246 wxCFDictKeyToInt( theValue, kCGDisplayBitsPerPixel ),
247 wxCFDictKeyToInt( theValue, kCGDisplayRefreshRate ));
248
249 if (theMode.Matches( mode ))
250 resultModes.Add( theMode );
251 }
252
253 return resultModes;
254 }
255
256 wxVideoMode wxDisplayImplMacOSX::GetCurrentMode() const
257 {
258 CFDictionaryRef theValue = CGDisplayCurrentMode( m_id );
259
260 return wxVideoMode(
261 wxCFDictKeyToInt( theValue, kCGDisplayWidth ),
262 wxCFDictKeyToInt( theValue, kCGDisplayHeight ),
263 wxCFDictKeyToInt( theValue, kCGDisplayBitsPerPixel ),
264 wxCFDictKeyToInt( theValue, kCGDisplayRefreshRate ));
265 }
266
267 bool wxDisplayImplMacOSX::ChangeMode( const wxVideoMode& mode )
268 {
269 #ifndef __WXOSX_IPHONE__
270 if (mode == wxDefaultVideoMode)
271 {
272 CGRestorePermanentDisplayConfiguration();
273 return true;
274 }
275 #endif
276
277 boolean_t bExactMatch;
278 CFDictionaryRef theCGMode = CGDisplayBestModeForParametersAndRefreshRate(
279 m_id,
280 (size_t)mode.GetDepth(),
281 (size_t)mode.GetWidth(),
282 (size_t)mode.GetHeight(),
283 (double)mode.GetRefresh(),
284 &bExactMatch );
285
286 bool bOK = bExactMatch;
287
288 if (bOK)
289 bOK = CGDisplaySwitchToMode( m_id, theCGMode ) == CGDisplayNoErr;
290
291 return bOK;
292 }
293
294 // ============================================================================
295 // wxDisplay::CreateFactory()
296 // ============================================================================
297
298 /* static */ wxDisplayFactory *wxDisplay::CreateFactory()
299 {
300 return new wxDisplayFactoryMacOSX;
301 }
302
303 #else
304
305 /* static */ wxDisplayFactory *wxDisplay::CreateFactory()
306 {
307 return new wxDisplayFactorySingle;
308 }
309
310 #endif
311
312 #endif // wxUSE_DISPLAY