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