]> git.tdb.fi Git - libs/gui.git/blobdiff - source/graphics/windows/display.cpp
Retrieve correct names for monitors on Windows
[libs/gui.git] / source / graphics / windows / display.cpp
index 5cc04c1674f6707ac3c3f3fa50a53220943572ad..359df9e39b7f16023022e0f662edc002b62c191b 100644 (file)
-#include <windows.h>
 #include "display.h"
+#include "display_private.h"
+#include <algorithm>
+#include <windows.h>
 
 using namespace std;
 
 namespace Msp {
 namespace Graphics {
 
-Display::Display(const string &)
+Display::Display(const string &):
+       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)
        {
-               DEVMODE info;
-               if(!EnumDisplaySettings(0, i, &info))
+               DISPLAY_DEVICE adapter_dev;
+               adapter_dev.cb = sizeof(adapter_dev);
+               if(!EnumDisplayDevices(nullptr, i, &adapter_dev, 0))
                        break;
 
-               VideoMode mode(info.dmPelsWidth, info.dmPelsHeight);
-               mode.rate = info.dmDisplayFrequency;
-               modes.push_back(mode);
+               if(adapter_dev.StateFlags&DISPLAY_DEVICE_MIRRORING_DRIVER)
+                       continue;
+
+               monitors.push_back(Monitor());
+               Monitor &monitor = monitors.back();
+               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_index = i;
+
+               DEVMODE current;
+               bool have_current = EnumDisplaySettings(adapter_dev.DeviceName, ENUM_CURRENT_SETTINGS, &current);
+
+               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.rate = info.dmDisplayFrequency;
+
+                       modes.push_back(mode);
+                       mode_monitor_indices.push_back(monitor.index);
+
+                       if(have_current && info.dmPelsWidth==current.dmPelsWidth && info.dmPelsHeight==current.dmPelsHeight && info.dmDisplayFrequency==current.dmDisplayFrequency)
+                               desktop_mode_index = mode.index;
+               }
+               desktop_mode_indices.push_back(desktop_mode_index);
        }
-       
-       DEVMODE info;
-       if(EnumDisplaySettings(0, ENUM_CURRENT_SETTINGS, &info))
+
+       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)
        {
-               orig_mode = VideoMode(info.dmPelsWidth, info.dmPelsHeight);
-               orig_mode.rate = info.dmDisplayFrequency;
+               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 &mode)
+void Display::set_mode(const VideoMode &requested_mode, bool)
 {
+       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;
-       if(mode.rate)
+       info.dmPelsWidth = mode->width;
+       info.dmPelsHeight = mode->height;
+       if(requested_mode.rate)
        {
                info.dmFields |= DM_DISPLAYFREQUENCY;
-               info.dmDisplayFrequency = mode.rate;
+               info.dmDisplayFrequency = mode->rate;
        }
 
-       LONG ret = ChangeDisplaySettings(&info, CDS_FULLSCREEN);
+       LONG ret = ChangeDisplaySettingsEx(priv->monitors[mode->monitor->index].c_str(), &info, NULL, CDS_FULLSCREEN, NULL);
        if(ret!=DISP_CHANGE_SUCCESSFUL)
-               throw unsupported_video_mode(mode);
+               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;
        }