-#include <windows.h>
#include "display.h"
#include "display_private.h"
+#include <algorithm>
+#include <windows.h>
using namespace std;
namespace Graphics {
Display::Display(const string &):
- primary_monitor(0),
priv(new Private)
{
+ static ErrorDialog err_dlg(nullptr);
+
+ int primary_index = -1;
+ vector<unsigned> mode_monitor_indices;
+ vector<int> desktop_mode_indices;
for(unsigned i=0;; ++i)
{
DISPLAY_DEVICE adapter_dev;
adapter_dev.cb = sizeof(adapter_dev);
- if(!EnumDisplayDevices(0, i, &adapter_dev, 0))
+ if(!EnumDisplayDevices(nullptr, i, &adapter_dev, 0))
break;
if(adapter_dev.StateFlags&DISPLAY_DEVICE_MIRRORING_DRIVER)
monitor.index = monitors.size()-1;
priv->monitors.push_back(adapter_dev.DeviceName);
+ DISPLAY_DEVICE monitor_dev;
+ monitor_dev.cb = sizeof(monitor_dev);
+ if(EnumDisplayDevices(adapter_dev.DeviceName, 0, &monitor_dev, 0))
+ monitor.name = monitor_dev.DeviceString;
+
if(adapter_dev.StateFlags&DISPLAY_DEVICE_PRIMARY_DEVICE)
- primary_monitor = &monitor;
+ primary_index = i;
DEVMODE current;
bool have_current = EnumDisplaySettings(adapter_dev.DeviceName, ENUM_CURRENT_SETTINGS, ¤t);
+ unsigned first_mode = modes.size();
+ int desktop_mode_index = -1;
for(unsigned j=0;; ++j)
{
DEVMODE info;
if(!EnumDisplaySettings(adapter_dev.DeviceName, j, &info))
break;
+ if(any_of(modes.begin()+first_mode, modes.end(), [&info](const VideoMode &m){
+ return (m.width==info.dmPelsWidth && m.height==info.dmPelsHeight && m.rate==info.dmDisplayFrequency);
+ }))
+ continue;
+
VideoMode mode(info.dmPelsWidth, info.dmPelsHeight);
mode.index = modes.size();
- mode.monitor = &monitor;
mode.rate = info.dmDisplayFrequency;
- if(find_matching_mode(mode))
- continue;
modes.push_back(mode);
- monitor.video_modes.push_back(&modes.back());
+ mode_monitor_indices.push_back(monitor.index);
if(have_current && info.dmPelsWidth==current.dmPelsWidth && info.dmPelsHeight==current.dmPelsHeight && info.dmDisplayFrequency==current.dmDisplayFrequency)
- monitor.desktop_mode = &modes.back();
+ desktop_mode_index = mode.index;
}
+ desktop_mode_indices.push_back(desktop_mode_index);
}
+
+ for(unsigned i=0; i<monitors.size(); ++i)
+ {
+ int j = desktop_mode_indices[i];
+ if(j>=0)
+ monitors[i].desktop_settings.mode = &modes[j];
+ monitors[i].current_settings = monitors[i].desktop_settings;
+ }
+
+ for(unsigned i=0; i<modes.size(); ++i)
+ {
+ Monitor &monitor = monitors[mode_monitor_indices[i]];
+ modes[i].monitor = &monitor;
+ monitor.video_modes.push_back(&modes[i]);
+ }
+
+ if(primary_index>=0)
+ primary_monitor = &monitors[primary_index];
}
Display::~Display()
{
+ delete priv;
}
void Display::set_mode(const VideoMode &requested_mode, bool)
{
- const VideoMode *mode = find_matching_mode(requested_mode);
+ const VideoMode *mode = find_mode(requested_mode);
if(!mode)
throw unsupported_video_mode(requested_mode);
DEVMODE info;
+ info.dmDeviceName[0] = 0;
+ info.dmSpecVersion = DM_SPECVERSION;
+ info.dmDriverVersion = 0;
info.dmSize = sizeof(DEVMODE);
+ info.dmDriverExtra = 0;
info.dmFields = DM_PELSWIDTH|DM_PELSHEIGHT;
info.dmPelsWidth = mode->width;
info.dmPelsHeight = mode->height;
LONG ret = ChangeDisplaySettingsEx(priv->monitors[mode->monitor->index].c_str(), &info, NULL, CDS_FULLSCREEN, NULL);
if(ret!=DISP_CHANGE_SUCCESSFUL)
throw unsupported_video_mode(requested_mode);
+
+ for(Monitor &m: monitors)
+ if(&m==mode->monitor)
+ m.current_settings.mode = mode;
}
bool Display::process_events()
{
MSG msg;
- if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
+ if(PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
{
+ TranslateMessage(&msg);
DispatchMessage(&msg);
return true;
}