]> git.tdb.fi Git - libs/gui.git/blob - source/graphics/windows/display.cpp
Expose a lot more information through the Monitor struct
[libs/gui.git] / source / graphics / windows / display.cpp
1 #include <windows.h>
2 #include "display.h"
3 #include "display_private.h"
4
5 using namespace std;
6
7 namespace Msp {
8 namespace Graphics {
9
10 Display::Display(const string &):
11         primary_monitor(0),
12         priv(new Private)
13 {
14         for(unsigned i=0;; ++i)
15         {
16                 DISPLAY_DEVICE adapter_dev;
17                 adapter_dev.cb = sizeof(adapter_dev);
18                 if(!EnumDisplayDevices(0, i, &adapter_dev, 0))
19                         break;
20
21                 if(adapter_dev.StateFlags&DISPLAY_DEVICE_MIRRORING_DRIVER)
22                         continue;
23
24                 monitors.push_back(Monitor());
25                 Monitor &monitor = monitors.back();
26                 monitor.index = monitors.size()-1;
27                 priv->monitors.push_back(adapter_dev.DeviceName);
28
29                 if(adapter_dev.StateFlags&DISPLAY_DEVICE_PRIMARY_DEVICE)
30                         primary_monitor = &monitor;
31
32                 DEVMODE current;
33                 bool have_current = EnumDisplaySettings(adapter_dev.DeviceName, ENUM_CURRENT_SETTINGS, &current);
34
35                 for(unsigned j=0;; ++j)
36                 {
37                         DEVMODE info;
38                         if(!EnumDisplaySettings(adapter_dev.DeviceName, j, &info))
39                                 break;
40
41                         VideoMode mode(info.dmPelsWidth, info.dmPelsHeight);
42                         mode.index = modes.size();
43                         mode.monitor = &monitor;
44                         mode.rate = info.dmDisplayFrequency;
45                         if(find_matching_mode(mode))
46                                 continue;
47
48                         modes.push_back(mode);
49                         monitor.video_modes.push_back(&modes.back());
50
51                         if(have_current && info.dmPelsWidth==current.dmPelsWidth && info.dmPelsHeight==current.dmPelsHeight && info.dmDisplayFrequency==current.dmDisplayFrequency)
52                                 monitor.desktop_mode = &modes.back();
53                 }
54         }
55 }
56
57 Display::~Display()
58 {
59 }
60
61 void Display::set_mode(const VideoMode &requested_mode, bool)
62 {
63         const VideoMode *mode = find_matching_mode(requested_mode);
64         if(!mode)
65                 throw unsupported_video_mode(requested_mode);
66
67         DEVMODE info;
68         info.dmSize = sizeof(DEVMODE);
69         info.dmFields = DM_PELSWIDTH|DM_PELSHEIGHT;
70         info.dmPelsWidth = mode->width;
71         info.dmPelsHeight = mode->height;
72         if(requested_mode.rate)
73         {
74                 info.dmFields |= DM_DISPLAYFREQUENCY;
75                 info.dmDisplayFrequency = mode->rate;
76         }
77
78         LONG ret = ChangeDisplaySettingsEx(priv->monitors[mode->monitor->index].c_str(), &info, NULL, CDS_FULLSCREEN, NULL);
79         if(ret!=DISP_CHANGE_SUCCESSFUL)
80                 throw unsupported_video_mode(requested_mode);
81
82         for(list<Monitor>::iterator i=monitors.begin(); i!=monitors.end(); ++i)
83                 if(&*i==mode->monitor)
84                         i->current_mode = mode;
85 }
86
87 bool Display::process_events()
88 {
89         MSG msg;
90         if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
91         {
92                 DispatchMessage(&msg);
93                 return true;
94         }
95         else
96                 return false;
97 }
98
99 void Display::check_error()
100 {
101 }
102
103 } // namespace Msp
104 } // namespace Graphics