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