]> git.saurik.com Git - wxWidgets.git/blame - src/mac/classic/display.cpp
create stock GDI objects on demand; use const with GDI objects appropriately (patch...
[wxWidgets.git] / src / mac / classic / display.cpp
CommitLineData
2646f485 1/////////////////////////////////////////////////////////////////////////////
ef1717a9 2// Name: src/mac/classic/display.cpp
2646f485
SC
3// Purpose: Mac implementation of wxDisplay class
4// Author: Brian Victor
ef1717a9 5// Modified by: Royce Mitchell III & Ryan Norton, Vadim Zeitlin
2646f485
SC
6// Created: 06/21/02
7// RCS-ID: $Id$
77ffb593 8// Copyright: (c) wxWidgets team
65571936 9// Licence: wxWindows licence
2646f485
SC
10/////////////////////////////////////////////////////////////////////////////
11
ef1717a9
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
2646f485
SC
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
24 #pragma hdrstop
25#endif
26
27#if wxUSE_DISPLAY
28
29#ifndef WX_PRECOMP
30 #include "wx/dynarray.h"
31 #include "wx/log.h"
2646f485
SC
32#endif
33
34#ifdef __DARWIN__
35 #include <Carbon/Carbon.h>
36#else
37 #include <Gestalt.h>
38 #include <Displays.h>
39 #include <Quickdraw.h>
40 #include <Video.h> //for VDSwitchInfoRec
41 #include <FixMath.h>
42#endif
43
44#include "wx/display.h"
ef1717a9 45#include "wx/display_impl.h"
2646f485
SC
46#include "wx/gdicmn.h"
47#include "wx/string.h"
48
49// ----------------------------------------------------------------------------
ef1717a9 50// display implementation classes
2646f485
SC
51// ----------------------------------------------------------------------------
52
ef1717a9 53class wxDisplayImplMac : public wxDisplayImpl
2646f485
SC
54{
55public:
f37c35d7
VZ
56 wxDisplayImplMac(size_t n, GDHandle hndl)
57 : wxDisplayImpl(n),
58 m_hndl(hndl)
59 {
60 }
ef1717a9
VZ
61
62 virtual wxRect GetGeometry() const;
63 virtual wxString GetName() const { return wxString(); }
64
65 virtual wxArrayVideoModes GetModes(const wxVideoMode& mode) const;
66 virtual wxVideoMode GetCurrentMode() const;
67 virtual bool ChangeMode(const wxVideoMode& mode);
68
69private:
2646f485 70 GDHandle m_hndl;
ef1717a9
VZ
71
72 DECLARE_NO_COPY_CLASS(wxDisplayImplMac)
2646f485
SC
73};
74
ef1717a9
VZ
75class wxDisplayFactoryMac : public wxDisplayFactory
76{
77public:
78 wxDisplayFactoryMac();
79
80 virtual wxDisplayImpl *CreateDisplay(size_t n);
81 virtual size_t GetCount();
82 virtual int GetFromPoint(const wxPoint& pt);
83
84protected:
85 DECLARE_NO_COPY_CLASS(wxDisplayFactoryMac)
86};
87
88// ============================================================================
89// wxDisplayFactoryMac implementation
90// ============================================================================
91
92size_t wxDisplayFactoryMac::GetCount()
2646f485 93{
2646f485 94 size_t num = 0;
ef1717a9 95 GDHandle hndl = DMGetFirstScreenDevice(true);
2646f485
SC
96 while(hndl)
97 {
98 num++;
99 hndl = DMGetNextScreenDevice(hndl, true);
100 }
101 return num;
102}
103
ef1717a9 104int wxDisplayFactoryMac::GetFromPoint(const wxPoint &p)
2646f485 105{
2646f485 106 size_t num = 0;
ef1717a9 107 GDHandle hndl = DMGetFirstScreenDevice(true);
2646f485
SC
108 while(hndl)
109 {
110 Rect screenrect = (*hndl)->gdRect;
111 if (p.x >= screenrect.left &&
112 p.x <= screenrect.right &&
113 p.y >= screenrect.top &&
114 p.y <= screenrect.bottom)
115 {
116 return num;
117 }
118 num++;
119 hndl = DMGetNextScreenDevice(hndl, true);
120 }
ef1717a9
VZ
121
122 return wxNOT_FOUND;
2646f485
SC
123}
124
ef1717a9 125wxDisplayImpl *wxDisplayFactoryMac::CreateDisplay(size_t n)
2646f485 126{
f37c35d7
VZ
127 size_t nOrig = n;
128
ef1717a9 129 GDHandle hndl = DMGetFirstScreenDevice(true);
2646f485
SC
130 while(hndl)
131 {
ef1717a9 132 if (n == 0)
2646f485 133 {
f37c35d7 134 return new wxDisplayImplMac(nOrig, hndl);
2646f485 135 }
ef1717a9 136 n--;
2646f485
SC
137 hndl = DMGetNextScreenDevice(hndl, true);
138 }
2646f485 139
ef1717a9 140 return NULL;
2646f485
SC
141}
142
ef1717a9
VZ
143// ============================================================================
144// wxDisplayImplMac implementation
145// ============================================================================
2646f485 146
ef1717a9 147wxRect wxDisplayImplMac::GetGeometry() const
2646f485 148{
ef1717a9
VZ
149 Rect screenrect = (*m_hndl)->gdRect;
150 return wxRect(screenrect.left, screenrect.top,
151 screenrect.right - screenrect.left,
152 screenrect.bottom - screenrect.top);
2646f485
SC
153}
154
155struct DMModeIteratorRec
156{
ef1717a9
VZ
157 wxArrayVideoModes* pModes;
158 const wxVideoMode* pMatchMode;
2646f485
SC
159};
160
ef1717a9
VZ
161pascal void DMModeListIteratorProc ( void* pData,
162 DMListIndexType nIndex,
163 DMDisplayModeListEntryPtr pInfo)
2646f485
SC
164{
165 DMModeIteratorRec* pInfoData = (DMModeIteratorRec*) pData;
166
ef1717a9 167 //Note that in testing the refresh rate is always 0 on my ibook - RN
2646f485
SC
168 int refresh = (int) Fix2Long(pInfo->displayModeResolutionInfo->csRefreshRate);
169
ef1717a9
VZ
170 for(unsigned long i = 0; i < pInfo->displayModeDepthBlockInfo->depthBlockCount; ++i)
171 {
2646f485
SC
172#define pDBI pInfo->displayModeDepthBlockInfo->depthVPBlock[i].depthVPBlock
173
ef1717a9
VZ
174 if (wxVideoMode((int) pInfo->displayModeResolutionInfo->csHorizontalPixels,
175 (int) pInfo->displayModeResolutionInfo->csVerticalLines,
176 (int) pDBI->vpPixelSize,
177 refresh).Matches(*pInfoData->pMatchMode) )
178 {
179 pInfoData->pModes->Add(wxVideoMode((int) pInfo->displayModeResolutionInfo->csHorizontalPixels,
180 (int) pInfo->displayModeResolutionInfo->csVerticalLines,
181 (int) pDBI->vpPixelSize,
182 refresh));
183 }
2646f485 184#undef pDBI
ef1717a9 185 }
2646f485
SC
186}
187
188struct DMModeInfoRec
189{
ef1717a9
VZ
190 const wxVideoMode* pMode;
191 VDSwitchInfoRec sMode;
192 bool bMatched;
2646f485
SC
193};
194
ef1717a9
VZ
195pascal void DMModeInfoProc ( void* pData,
196 DMListIndexType nIndex,
197 DMDisplayModeListEntryPtr pInfo)
2646f485 198{
ef1717a9
VZ
199 DMModeInfoRec* pInfoData = (DMModeInfoRec*) pData;
200 Fixed refresh = Long2Fix(pInfoData->pMode->refresh);
2646f485 201
ef1717a9
VZ
202 for(unsigned long i = 0; i < pInfo->displayModeDepthBlockInfo->depthBlockCount; ++i)
203 {
2646f485 204#define pDBI pInfo->displayModeDepthBlockInfo->depthVPBlock[i].depthVPBlock
ef1717a9
VZ
205 if (pInfoData->pMode->w == (int&) pInfo->displayModeResolutionInfo->csHorizontalPixels &&
206 pInfoData->pMode->h == (int&) pInfo->displayModeResolutionInfo->csVerticalLines &&
207 pInfoData->pMode->bpp == (int) pDBI->vpPixelSize &&
208 refresh == pInfo->displayModeResolutionInfo->csRefreshRate)
209 {
210 memcpy(&pInfoData->sMode, pInfo->displayModeDepthBlockInfo->depthVPBlock[i].depthSwitchInfo,
211 sizeof(VDSwitchInfoRec));
212 pInfoData->sMode.csMode = pDBI->vpPixelSize;
213 pInfoData->bMatched = true;
214 break;
215 }
2646f485 216#undef pDBI
ef1717a9 217 }
2646f485
SC
218}
219
220struct DMModeTransRec
221{
ef1717a9
VZ
222 wxVideoMode Mode;
223 const VDSwitchInfoRec* psMode;
224 bool bMatched;
2646f485
SC
225};
226
ef1717a9
VZ
227pascal void DMModeTransProc ( void* pData,
228 DMListIndexType nIndex,
229 DMDisplayModeListEntryPtr pInfo)
2646f485 230{
ef1717a9 231 DMModeTransRec* pInfoData = (DMModeTransRec*) pData;
2646f485 232
ef1717a9
VZ
233 for(unsigned long i = 0; i < pInfo->displayModeDepthBlockInfo->depthBlockCount; ++i)
234 {
2646f485 235#define pDBI pInfo->displayModeDepthBlockInfo->depthVPBlock[i].depthVPBlock
ef1717a9
VZ
236 if (pInfoData->psMode->csData == pInfo->displayModeDepthBlockInfo->depthVPBlock[i].depthSwitchInfo->csData)
237 {
238 pInfoData->Mode = wxVideoMode((int) pInfo->displayModeResolutionInfo->csHorizontalPixels,
239 (int) pInfo->displayModeResolutionInfo->csVerticalLines,
240 (int) pDBI->vpPixelSize,
241 (int) Fix2Long(pInfo->displayModeResolutionInfo->csRefreshRate) );
242 pInfoData->bMatched = true;
243 break;
244 }
2646f485 245#undef pDBI
ef1717a9 246 }
2646f485
SC
247}
248
ef1717a9 249wxArrayVideoModes wxDisplayImplMac::GetModes(const wxVideoMode& mode) const
2646f485 250{
2646f485
SC
251 wxArrayVideoModes Modes;
252
253 unsigned long dwDMVer;
254 Gestalt(gestaltDisplayMgrVers, (long*) &dwDMVer);
255
256 //Check DM version (for backward compatibility only - 7.5.3+ use 2.0)
257 if (dwDMVer >= 0x020000) //version 2?
258 {
259
ef1717a9
VZ
260 DMListIndexType nNumModes;
261 DMListType pModes;
262 DMDisplayModeListIteratorUPP uppMLI;
263 DisplayIDType nDisplayID;
264
265 wxASSERT(DMGetDisplayIDByGDevice(m_hndl, &nDisplayID, false) == noErr);
266 //Create a new list...
267 wxASSERT_MSG(DMNewDisplayModeList(nDisplayID, NULL, NULL, &nNumModes, &pModes) == noErr, wxT("Could not create a new display mode list") );
268
269 uppMLI = NewDMDisplayModeListIteratorUPP(DMModeListIteratorProc);
270 wxASSERT(uppMLI);
271
272 DMModeIteratorRec sModeInfo;
273 sModeInfo.pModes = &Modes;
274 sModeInfo.pMatchMode = &mode;
275 for (DMListIndexType i = 0; i < nNumModes; ++i)
276 {
277 wxASSERT(DMGetIndexedDisplayModeFromList(pModes, i, NULL,
278 uppMLI, &sModeInfo) == noErr);
279 }
280 DisposeDMDisplayModeListIteratorUPP(uppMLI);
281 wxASSERT(DMDisposeList(pModes) == noErr);
2646f485
SC
282 }
283 else //DM 1.0, 1.2, 1.x
284 {
ef1717a9
VZ
285 wxLogSysError(wxString::Format(wxT("Display Manager Version %u Not Supported! Present? %s"),
286 (unsigned int) dwDMVer / 0x10000,
287 (dwDMVer & (1 << gestaltDisplayMgrPresent) ? wxT("Yes") : wxT("No")) )
288 );
2646f485
SC
289 }
290
291 return Modes;
292}
293
ef1717a9 294wxVideoMode wxDisplayImplMac::GetCurrentMode() const
2646f485
SC
295{
296 unsigned long dwDMVer;
297 wxVideoMode RetMode;
ef1717a9
VZ
298
299 Gestalt(gestaltDisplayMgrVers, (long*) &dwDMVer);
2646f485
SC
300 //Check DM version (for backward compatibility only - 7.5.3+ use 2.0)
301 if (dwDMVer >= 0x020000) //version 2?
302 {
ef1717a9
VZ
303 VDSwitchInfoRec sMode; //Note - csMode member also contains the bit depth
304 if (DMGetDisplayMode(m_hndl, &sMode) == noErr)
305 {
306 DMListIndexType nNumModes;
307 DMListType pModes;
308 DMDisplayModeListIteratorUPP uppMLI;
309 DisplayIDType nDisplayID;
310
311 wxASSERT(DMGetDisplayIDByGDevice(m_hndl, &nDisplayID, false) == noErr);
312 //Create a new list...
313 wxASSERT_MSG(DMNewDisplayModeList(nDisplayID, NULL, NULL, &nNumModes, &pModes) == noErr,
314 wxT("Could not create a new display mode list") );
315
316 uppMLI = NewDMDisplayModeListIteratorUPP(DMModeTransProc);
317 wxASSERT(uppMLI);
318
319 DMModeTransRec sModeInfo;
320 sModeInfo.bMatched = false;
321 sModeInfo.psMode = &sMode;
322 for (DMListIndexType i = 0; i < nNumModes; ++i)
323 {
324 wxASSERT(DMGetIndexedDisplayModeFromList(pModes, i, NULL,
325 uppMLI, &sModeInfo) == noErr);
326
327 if ( sModeInfo.bMatched == true )
328 {
329 RetMode = sModeInfo.Mode;
330 break;
331 }
332 }
333
334 DisposeDMDisplayModeListIteratorUPP(uppMLI);
335 wxASSERT(DMDisposeList(pModes) == noErr);
336 }
337 else //Can't get current mode?
338 {
339 wxLogSysError(wxString::Format(wxT("Couldn't obtain current display mode!!!\ndwDMVer:%u"),
340 (unsigned int) dwDMVer));
341 }
2646f485
SC
342 }
343 else //DM ver 1
344 {
ef1717a9
VZ
345 wxLogSysError(wxString::Format(wxT("Display Manager Version %u Not Supported! Present? %s"),
346 (unsigned int) dwDMVer / 0x10000,
347 (dwDMVer & (1 << gestaltDisplayMgrPresent) ? wxT("Yes") : wxT("No")) )
348 );
2646f485 349 }
ef1717a9 350
2646f485
SC
351 return RetMode;
352}
353
ef1717a9 354bool wxDisplayImplMac::ChangeMode(const wxVideoMode& mode)
2646f485
SC
355{
356 unsigned long dwDMVer;
357 Gestalt(gestaltDisplayMgrVers, (long*)&dwDMVer);
358 if (GetCount() == 1 || dwDMVer >= 0x020000)
359 {
ef1717a9
VZ
360 if (mode == wxDefaultVideoMode)
361 {
2646f485 362//#ifndef __DARWIN__
ef1717a9
VZ
363// Handle hDisplayState;
364// if (DMBeginConfigureDisplays(&hDisplayState) != noErr)
365// {
366// wxLogSysError(wxT("Could not lock display for display mode changing!"));
367// return false;
368// }
369// wxASSERT( DMUseScreenPrefs(true, hDisplayState) == noErr);
370// DMEndConfigureDisplays(hDisplayState);
371// return true;
2646f485 372//#else
ef1717a9
VZ
373 //hmmmmm....
374 return true;
2646f485 375//#endif
ef1717a9
VZ
376 }
377
378 //0 & NULL for params 2 & 3 of DMSetVideoMode signal it to use defaults (current mode)
379 //DM 2.0+ doesn't use params 2 & 3 of DMSetDisplayMode
380 //so we have to use this icky structure
381 VDSwitchInfoRec sMode;
382 memset(&sMode, 0, sizeof(VDSwitchInfoRec) );
383
384 DMListIndexType nNumModes;
385 DMListType pModes;
386 DMDisplayModeListIteratorUPP uppMLI;
387 DisplayIDType nDisplayID;
388
389 wxASSERT(DMGetDisplayIDByGDevice(m_hndl, &nDisplayID, false) == noErr);
390 //Create a new list...
391 wxASSERT_MSG(DMNewDisplayModeList(nDisplayID, NULL, NULL, &nNumModes, &pModes) == noErr,
392 wxT("Could not create a new display mode list") );
393
394 uppMLI = NewDMDisplayModeListIteratorUPP(DMModeInfoProc);
395 wxASSERT(uppMLI);
396
397 DMModeInfoRec sModeInfo;
398 sModeInfo.bMatched = false;
399 sModeInfo.pMode = &mode;
400 unsigned int i;
401 for(i = 0; i < nNumModes; ++i)
402 {
403 wxASSERT(DMGetIndexedDisplayModeFromList(pModes, i, NULL,
404 uppMLI, &sModeInfo) == noErr);
405 if (sModeInfo.bMatched == true)
406 {
407 sMode = sModeInfo.sMode;
408 break;
409 }
410 }
411 if(i == nNumModes)
2646f485 412 return false;
ef1717a9
VZ
413
414 DisposeDMDisplayModeListIteratorUPP(uppMLI);
415 wxASSERT(DMDisposeList(pModes) == noErr);
416
417 // For the really paranoid -
418 // unsigned long flags;
419 // Boolean bok;
420 // wxASSERT(noErr == DMCheckDisplayMode(m_hndl, sMode.csData,
421 // sMode.csMode, &flags, NULL, &bok));
422 // wxASSERT(bok);
423
424 Handle hDisplayState;
425 if (DMBeginConfigureDisplays(&hDisplayState) != noErr)
426 {
427 wxLogSysError(wxT("Could not lock display for display mode changing!"));
428 return false;
429 }
430
431 unsigned long dwBPP = (unsigned long) mode.bpp;
432 if (DMSetDisplayMode(m_hndl, sMode.csData,
433 (unsigned long*) &(dwBPP), NULL
434 //(unsigned long) &sMode
435 , hDisplayState
436 ) != noErr)
437 {
438 DMEndConfigureDisplays(hDisplayState);
439 wxLogError(wxT("Could not set the display mode"));
440 return false;
441 }
442 DMEndConfigureDisplays(hDisplayState);
2646f485
SC
443 }
444 else //DM 1.0, 1.2, 1.x
445 {
ef1717a9
VZ
446 wxLogSysError(wxString::Format(wxT("Monitor gravitation not supported yet. dwDMVer:%u"),
447 (unsigned int) dwDMVer));
448 return false;
2646f485 449 }
ef1717a9 450
2646f485
SC
451 return true;
452}
453
ef1717a9
VZ
454// ============================================================================
455// wxDisplay::CreateFactory()
456// ============================================================================
457
458/* static */ wxDisplayFactory *wxDisplay::CreateFactory()
2646f485 459{
ef1717a9 460 return new wxDisplayFactoryMac;
2646f485
SC
461}
462
463#endif // wxUSE_DISPLAY