ClangFormat: apply to source, most of intern
[blender.git] / intern / ghost / intern / GHOST_DisplayManagerWin32.cpp
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup GHOST
22  */
23
24 #include "GHOST_DisplayManagerWin32.h"
25 #include "GHOST_Debug.h"
26
27 #undef _WIN32_WINNT
28 #define _WIN32_WINNT 0x501  // require Windows XP or newer
29 #define WIN32_LEAN_AND_MEAN
30 #include <windows.h>
31
32 // We do not support multiple monitors at the moment
33 #define COMPILE_MULTIMON_STUBS
34 #include <multimon.h>
35
36 GHOST_DisplayManagerWin32::GHOST_DisplayManagerWin32(void)
37 {
38 }
39
40 GHOST_TSuccess GHOST_DisplayManagerWin32::getNumDisplays(GHOST_TUns8 &numDisplays) const
41 {
42   numDisplays = ::GetSystemMetrics(SM_CMONITORS);
43   return numDisplays > 0 ? GHOST_kSuccess : GHOST_kFailure;
44 }
45
46 static BOOL get_dd(DWORD d, DISPLAY_DEVICE *dd)
47 {
48   dd->cb = sizeof(DISPLAY_DEVICE);
49   return ::EnumDisplayDevices(NULL, d, dd, 0);
50 }
51
52 /*
53  * When you call EnumDisplaySettings with iModeNum set to zero, the operating system
54  * initializes and caches information about the display device. When you call
55  * EnumDisplaySettings with iModeNum set to a non-zero value, the function returns
56  * the information that was cached the last time the function was called with iModeNum
57  * set to zero.
58  */
59 GHOST_TSuccess GHOST_DisplayManagerWin32::getNumDisplaySettings(GHOST_TUns8 display,
60                                                                 GHOST_TInt32 &numSettings) const
61 {
62   DISPLAY_DEVICE display_device;
63   if (!get_dd(display, &display_device))
64     return GHOST_kFailure;
65
66   numSettings = 0;
67   DEVMODE dm;
68   while (::EnumDisplaySettings(display_device.DeviceName, numSettings, &dm)) {
69     numSettings++;
70   }
71   return GHOST_kSuccess;
72 }
73
74 GHOST_TSuccess GHOST_DisplayManagerWin32::getDisplaySetting(GHOST_TUns8 display,
75                                                             GHOST_TInt32 index,
76                                                             GHOST_DisplaySetting &setting) const
77 {
78   DISPLAY_DEVICE display_device;
79   if (!get_dd(display, &display_device))
80     return GHOST_kFailure;
81
82   GHOST_TSuccess success;
83   DEVMODE dm;
84   if (::EnumDisplaySettings(display_device.DeviceName, index, &dm)) {
85 #ifdef GHOST_DEBUG
86     printf("display mode: width=%d, height=%d, bpp=%d, frequency=%d\n",
87            dm.dmPelsWidth,
88            dm.dmPelsHeight,
89            dm.dmBitsPerPel,
90            dm.dmDisplayFrequency);
91 #endif  // GHOST_DEBUG
92     setting.xPixels = dm.dmPelsWidth;
93     setting.yPixels = dm.dmPelsHeight;
94     setting.bpp = dm.dmBitsPerPel;
95     /* When you call the EnumDisplaySettings function, the dmDisplayFrequency member
96      * may return with the value 0 or 1. These values represent the display hardware's
97      * default refresh rate. This default rate is typically set by switches on a display
98      * card or computer motherboard, or by a configuration program that does not use
99      * Win32 display functions such as ChangeDisplaySettings.
100      */
101     /* First, we tried to explicitly set the frequency to 60 if EnumDisplaySettings
102      * returned 0 or 1 but this doesn't work since later on an exact match will
103      * be searched. And this will never happen if we change it to 60. Now we rely
104      * on the default h/w setting.
105      */
106     setting.frequency = dm.dmDisplayFrequency;
107     success = GHOST_kSuccess;
108   }
109   else {
110     success = GHOST_kFailure;
111   }
112   return success;
113 }
114
115 GHOST_TSuccess GHOST_DisplayManagerWin32::getCurrentDisplaySetting(
116     GHOST_TUns8 display, GHOST_DisplaySetting &setting) const
117 {
118   return getDisplaySetting(display, ENUM_CURRENT_SETTINGS, setting);
119 }
120
121 GHOST_TSuccess GHOST_DisplayManagerWin32::setCurrentDisplaySetting(
122     GHOST_TUns8 display, const GHOST_DisplaySetting &setting)
123 {
124   DISPLAY_DEVICE display_device;
125   if (!get_dd(display, &display_device))
126     return GHOST_kFailure;
127
128   GHOST_DisplaySetting match;
129   findMatch(display, setting, match);
130   DEVMODE dm;
131   int i = 0;
132   while (::EnumDisplaySettings(display_device.DeviceName, i++, &dm)) {
133     if ((dm.dmBitsPerPel == match.bpp) && (dm.dmPelsWidth == match.xPixels) &&
134         (dm.dmPelsHeight == match.yPixels) && (dm.dmDisplayFrequency == match.frequency)) {
135       break;
136     }
137   }
138   /*
139    * dm.dmBitsPerPel = match.bpp;
140    * dm.dmPelsWidth = match.xPixels;
141    * dm.dmPelsHeight = match.yPixels;
142    * dm.dmDisplayFrequency = match.frequency;
143    * dm.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY;
144    * dm.dmSize = sizeof(DEVMODE);
145    * dm.dmDriverExtra = 0;
146    */
147 #ifdef GHOST_DEBUG
148   printf("display change: Requested settings:\n");
149   printf("  dmBitsPerPel=%d\n", dm.dmBitsPerPel);
150   printf("  dmPelsWidth=%d\n", dm.dmPelsWidth);
151   printf("  dmPelsHeight=%d\n", dm.dmPelsHeight);
152   printf("  dmDisplayFrequency=%d\n", dm.dmDisplayFrequency);
153 #endif  // GHOST_DEBUG
154
155   LONG status = ::ChangeDisplaySettings(&dm, CDS_FULLSCREEN);
156 #ifdef GHOST_DEBUG
157   switch (status) {
158     case DISP_CHANGE_SUCCESSFUL:
159       printf("display change: The settings change was successful.\n");
160       break;
161     case DISP_CHANGE_RESTART:
162       printf(
163           "display change: The computer must be restarted in order for the graphics mode to "
164           "work.\n");
165       break;
166     case DISP_CHANGE_BADFLAGS:
167       printf("display change: An invalid set of flags was passed in.\n");
168       break;
169     case DISP_CHANGE_BADPARAM:
170       printf(
171           "display change: An invalid parameter was passed in. "
172           "This can include an invalid flag or combination of flags.\n");
173       break;
174     case DISP_CHANGE_FAILED:
175       printf("display change: The display driver failed the specified graphics mode.\n");
176       break;
177     case DISP_CHANGE_BADMODE:
178       printf("display change: The graphics mode is not supported.\n");
179       break;
180     case DISP_CHANGE_NOTUPDATED:
181       printf("display change: Windows NT: Unable to write settings to the registry.\n");
182       break;
183     default:
184       printf("display change: Return value invalid\n");
185       break;
186   }
187 #endif  // GHOST_DEBUG
188   return status == DISP_CHANGE_SUCCESSFUL ? GHOST_kSuccess : GHOST_kFailure;
189 }