[Spice-devel] [PATCH win-vdagent v6 2/3] Encapsulating XPDM implementation

Frediano Ziglio fziglio at redhat.com
Mon Aug 15 07:57:58 UTC 2016


This adjust come issues updating the coordinates for primary display.
Should be merged into the other
- if a primary is already present don't adjust positions
- handle cases where the leftmost monitor have x > 0
- handle cases where more monitors are leftmost

diff --git a/vdagent/display_configuration.cpp b/vdagent/display_configuration.cpp
index 4db093f..bfea113 100755
--- a/vdagent/display_configuration.cpp
+++ b/vdagent/display_configuration.cpp
@@ -907,10 +907,11 @@ bool CCD::is_device_path(LPCTSTR device_name, DISPLAYCONFIG_PATH_INFO* path)
 
 // If we have detached the primary monitor, then we need to reset the positions of the remaining
 // monitors to insure that at least one is positioned at (0,0)
+// Windows specify that there must be such a monitor which is considered the primary one
 void CCD::verify_primary_position()
 {
-    LONG leftmost_x(0);
-    LONG leftmost_y(0);
+    LONG leftmost_x(LONG_MAX);
+    LONG leftmost_y(LONG_MAX);
     if (!_primary_detached) {
         return;
     }
@@ -921,28 +922,30 @@ void CCD::verify_primary_position()
         if (!is_active_path(path_info))
             continue;
 
-        DISPLAYCONFIG_MODE_INFO* mode = &_pModeInfo[path_info->sourceInfo.modeInfoIdx];
-        if (leftmost_x > mode->sourceMode.position.x) {
-            leftmost_x = mode->sourceMode.position.x;
-            leftmost_y = mode->sourceMode.position.y;
+        const POINTL& position(_pModeInfo[path_info->sourceInfo.modeInfoIdx].sourceMode.position);
+        // we already have a primary monitor so we have nothing to do
+        if (position.x == 0 && position.y == 0)
+            return;
+        if (leftmost_x > position.x) {
+            leftmost_x = position.x;
+            leftmost_y = position.y;
         }
+        // in case there are more monitors on the left most chooise the top one
+        if (leftmost_x == position.x && leftmost_y > position.y)
+            leftmost_y = position.y;
     }
 
-    if (leftmost_x == 0) {
-        return;
-    }
-
+    // update all active monitors adjusting the choosen monitor to (0,0)
     for (UINT32 i = 0; i < _numPathElements; i++) {
         DISPLAYCONFIG_PATH_INFO* path_info = &_pPathInfo[i];
         if (!is_active_path(path_info))
             continue;
-        DISPLAYCONFIG_MODE_INFO* mode = &_pModeInfo[path_info->sourceInfo.modeInfoIdx];
-        vd_printf("%s: setting mode x to %lu", __FUNCTION__, mode->sourceMode.position.x);
-        mode->sourceMode.position.x -= leftmost_x;
-        mode->sourceMode.position.y -= leftmost_y;
+        POINTL& position(_pModeInfo[path_info->sourceInfo.modeInfoIdx].sourceMode.position);
+        vd_printf("%s: setting mode x to %lu", __FUNCTION__, position.x);
+        position.x -= leftmost_x;
+        position.y -= leftmost_y;
     }
     _path_state = PATH_UPDATED;
-    return;
 }
 
 bool CCD::update_mode_position(LPCTSTR device_name, DEVMODE* dev_mode)


Frediano

> The Direct3D 9 API operates on either the Windows XP display driver
> model (XPDM) or the Windows Vista display driver model (WDDM), depending
> on the operating system installed.
> 
> This patch encapsulates the current XPDM interface implementation into
> XPDMInterface class which inherits DisplayConfig class. This patch
> makes it easier to introduce WDDM interface to Vdagent in future
> patches.
> 
> Based on a patch by Sandy Stutsman <sstutsma at redhat.com>
> 
> Signed-off-by: Dmitry Fleytman <dfleytma at redhat.com>
> Signed-off-by: Sameeh Jubran <sameeh at daynix.com>
> ---
>  vdagent/desktop_layout.cpp        | 148 +++++++-------------------------
>  vdagent/desktop_layout.h          |   9 +-
>  vdagent/display_configuration.cpp | 174
>  ++++++++++++++++++++++++++++++++++++++
>  vdagent/display_configuration.h   |  36 ++++++++
>  4 files changed, 245 insertions(+), 122 deletions(-)
> 
> diff --git a/vdagent/desktop_layout.cpp b/vdagent/desktop_layout.cpp
> index a7666ca..9c3e873 100644
> --- a/vdagent/desktop_layout.cpp
> +++ b/vdagent/desktop_layout.cpp
> @@ -18,6 +18,7 @@
>  #include <spice/qxl_windows.h>
>  #include <spice/qxl_dev.h>
>  #include "desktop_layout.h"
> +#include "display_configuration.h"
>  #include "vdlog.h"
>  
>  #ifdef __MINGW32__
> @@ -35,15 +36,17 @@ void DisplayMode::set_res(DWORD width, DWORD height,
> DWORD depth)
>  DesktopLayout::DesktopLayout()
>      : _total_width (0)
>      , _total_height (0)
> -    , _send_monitors_position(false)
> +    , _display_config (NULL)
>  {
>      MUTEX_INIT(_mutex);
> +    _display_config = DisplayConfig::create_config();
>      get_displays();
>  }
>  
>  DesktopLayout::~DesktopLayout()
>  {
>      clean_displays();
> +    delete _display_config;
>  }
>  
>  void DesktopLayout::get_displays()
> @@ -59,6 +62,7 @@ void DesktopLayout::get_displays()
>          unlock();
>          return;
>      }
> +    _display_config->update_config_path();
>      clean_displays();
>      ZeroMemory(&dev_info, sizeof(dev_info));
>      dev_info.cb = sizeof(dev_info);
> @@ -82,12 +86,13 @@ void DesktopLayout::get_displays()
>                  _displays[i] = NULL;
>              }
>          }
> -        attached = !!(dev_info.StateFlags &
> DISPLAY_DEVICE_ATTACHED_TO_DESKTOP);
> +        attached = _display_config->is_attached(&dev_info);
> +
>          EnumDisplaySettings(dev_info.DeviceName, ENUM_CURRENT_SETTINGS,
>          &mode);
>          _displays[display_id] = new DisplayMode(mode.dmPosition.x,
>          mode.dmPosition.y,
>                                                  mode.dmPelsWidth,
>                                                  mode.dmPelsHeight,
>                                                  mode.dmBitsPerPel,
>                                                  attached);
> -        update_monitor_config(dev_info.DeviceName, _displays[display_id]);
> +        _display_config->update_monitor_config(dev_info.DeviceName,
> _displays[display_id], &mode);
>      }
>      normalize_displays_pos();
>      unlock();
> @@ -121,6 +126,7 @@ void DesktopLayout::set_displays()
>          unlock();
>          return;
>      }
> +    _display_config->update_config_path();
>      ZeroMemory(&dev_info, sizeof(dev_info));
>      dev_info.cb = sizeof(dev_info);
>      ZeroMemory(&dev_mode, sizeof(dev_mode));
> @@ -146,28 +152,32 @@ void DesktopLayout::set_displays()
>              break;
>          }
>          DisplayMode * mode(_displays.at(display_id));
> -        if (!init_dev_mode(dev_info.DeviceName, &dev_mode, mode, normal_x,
> normal_y, true)) {
> +        if (!init_dev_mode(dev_info.DeviceName, &dev_mode, mode)) {
>              vd_printf("No suitable mode found for display %S",
>              dev_info.DeviceName);
>              break;
>          }
>          vd_printf("Set display mode %lux%lu", dev_mode.dmPelsWidth,
>          dev_mode.dmPelsHeight);
> -        LONG ret = ChangeDisplaySettingsEx(dev_info.DeviceName, &dev_mode,
> NULL,
> -                                           CDS_UPDATEREGISTRY | CDS_NORESET,
> NULL);
> -        if (ret == DISP_CHANGE_SUCCESSFUL) {
> +        if (_display_config->update_dev_mode_position(dev_info.DeviceName,
> &dev_mode,
> +                                                     mode->_pos_x -
> normal_x,
> +                                                     mode->_pos_y -
> normal_y)) {
>              dev_sets++;
> -            update_monitor_config(dev_info.DeviceName, mode);
> +            _display_config->update_monitor_config(dev_info.DeviceName,
> mode, &dev_mode);
>          }
>          if (!is_qxl) {
>              display_id++;
>          }
>      }
>      if (dev_sets) {
> -        ChangeDisplaySettingsEx(NULL, NULL, NULL, 0, NULL);
> +        _display_config->update_display_settings();
>          normalize_displays_pos();
>      }
>      unlock();
>  }
>  
> +void DesktopLayout::set_position_configurable(bool flag) {
> +    _display_config->set_monitors_config(flag);
> +}
> +
>  // Normalize all display positions to non-negative coordinates and update
>  total width and height of
>  // the virtual desktop. Caller is responsible to lock() & unlock().
>  void DesktopLayout::normalize_displays_pos()
> @@ -265,125 +275,29 @@ bool DesktopLayout::get_qxl_device_id(WCHAR*
> device_key, DWORD* device_id)
>      return key_found;
>  }
>  
> -bool DesktopLayout::init_dev_mode(LPCTSTR dev_name, DEVMODE* dev_mode,
> DisplayMode* mode,
> -                                  LONG normal_x, LONG normal_y, bool
> set_pos)
> +bool DesktopLayout::init_dev_mode(LPCTSTR dev_name, DEVMODE* dev_mode,
> DisplayMode* mode)
>  {
> -    DWORD closest_diff = -1;
> -    DWORD best = -1;
> -    QXLEscapeSetCustomDisplay custom;
> -    HDC hdc = NULL;
> -    LONG ret;
> -
>      ZeroMemory(dev_mode, sizeof(DEVMODE));
>      dev_mode->dmSize = sizeof(DEVMODE);
> -    if (!mode || !mode->_attached) {
> -        //Detach monitor
> -        dev_mode->dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_POSITION;
> -        return true;
> -    }
> -
> -    hdc = CreateDC(dev_name, NULL, NULL, NULL);
> -    if (!hdc) {
> -        // for some reason, windows want those 3 flags to enable monitor
> -        dev_mode->dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_POSITION;
> -        dev_mode->dmPelsWidth = mode->_width;
> -        dev_mode->dmPelsHeight = mode->_height;
> -        ret = ChangeDisplaySettingsEx(dev_name, dev_mode, NULL,
> CDS_UPDATEREGISTRY, NULL);
> -        if (ret == DISP_CHANGE_BADMODE) {
> -            // custom resolution might not be set yet, use known resolution
> -            // FIXME: this causes client temporary resize... a
> -            // solution would involve passing custom resolution before
> -            // driver initialization, perhaps through registry
> -            dev_mode->dmPelsWidth = 640;
> -            dev_mode->dmPelsHeight = 480;
> -            ret = ChangeDisplaySettingsEx(dev_name, dev_mode, NULL,
> CDS_UPDATEREGISTRY, NULL);
> -        }
>  
> -        vd_printf("attach %ld", ret);
> -        hdc = CreateDC(dev_name, NULL, NULL, NULL);
> +    //Update monitor state
> +    MONITOR_STATE monitor_state = (!mode || !mode->_attached)?
> MONITOR_DETACHED : MONITOR_ATTACHED;
> +    _display_config->set_monitor_state(dev_name, dev_mode, monitor_state);
> +    if (monitor_state == MONITOR_DETACHED) {
> +        return true;
>      }
>  
> -    if (!hdc) {
> -        vd_printf("failed to create DC");
> +    // Update custom resolution
> +    dev_mode->dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_POSITION;
> +    dev_mode->dmPelsWidth = mode->_width;
> +    dev_mode->dmPelsHeight = mode->_height;
> +    dev_mode->dmBitsPerPel = mode->_depth;
> +    if (!_display_config->custom_display_escape(dev_name, dev_mode))
>          return false;
> -    } else {
> -        // Update custom resolution
> -        custom.xres = mode->_width;
> -        custom.yres = mode->_height;
> -        custom.bpp = mode->_depth;
> -
> -        int err = ExtEscape(hdc, QXL_ESCAPE_SET_CUSTOM_DISPLAY,
> -                            sizeof(QXLEscapeSetCustomDisplay),
> (LPCSTR)&custom, 0, NULL);
> -        if (err <= 0) {
> -            vd_printf("can't set custom display, perhaps an old driver");
> -        }
> -        DeleteDC(hdc);
> -    }
> -
> -    // force refresh mode table
> -    DEVMODE tempDevMode;
> -    ZeroMemory(&tempDevMode, sizeof (tempDevMode));
> -    tempDevMode.dmSize = sizeof(DEVMODE);
> -    EnumDisplaySettings(dev_name, 0xffffff, &tempDevMode);
> -
> -    //Find the closest size which will fit within the monitor
> -    for (DWORD i = 0; EnumDisplaySettings(dev_name, i, dev_mode); i++) {
> -        if (dev_mode->dmPelsWidth > mode->_width ||
> -            dev_mode->dmPelsHeight > mode->_height ||
> -            dev_mode->dmBitsPerPel != mode->_depth) {
> -            continue;
> -        }
> -        DWORD wdiff = mode->_width - dev_mode->dmPelsWidth;
> -        DWORD hdiff = mode->_height - dev_mode->dmPelsHeight;
> -        DWORD diff = wdiff * wdiff + hdiff * hdiff;
> -        if (diff < closest_diff) {
> -            closest_diff = diff;
> -            best = i;
> -        }
> -    }
> -    if (best == (DWORD)-1 || !EnumDisplaySettings(dev_name, best, dev_mode))
> {
> -        return false;
> -    }
> -    dev_mode->dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
> -    if (set_pos) {
> -        //Convert the position so that the primary is always at (0,0)
> -        dev_mode->dmPosition.x = mode->_pos_x - normal_x;
> -        dev_mode->dmPosition.y = mode->_pos_y - normal_y;
> -        dev_mode->dmFields |= DM_POSITION;
> -    }
>  
>      // update current DisplayMode (so mouse scaling works properly)
>      mode->_width = dev_mode->dmPelsWidth;
>      mode->_height = dev_mode->dmPelsHeight;
> -
>      return true;
> -}
> -
> -bool DesktopLayout::update_monitor_config(LPCTSTR dev_name, DisplayMode*
> mode)
> -{
> -    QXLHead monitor_config;
> -
> -    if (!mode || !mode->get_attached())
> -        return false;
> -
> -    //Don't configure monitors unless the client supports it
> -    if(!_send_monitors_position) return FALSE;
> -
> -    HDC hdc = CreateDC(dev_name, NULL, NULL, NULL);
> -
> -    memset(&monitor_config, 0, sizeof(monitor_config));
> -    monitor_config.x = mode->_pos_x;
> -    monitor_config.y = mode->_pos_y;
> -    monitor_config.width = mode->_width;
> -    monitor_config.height = mode->_height;
> -
> -    int err = ExtEscape(hdc, QXL_ESCAPE_MONITOR_CONFIG,
> -        sizeof(QXLHead), (LPCSTR) &monitor_config, 0, NULL);
> -
> -    if (err < 0){
> -        vd_printf("can't update monitor config, may have an older driver");
> -    }
>  
> -    DeleteDC(hdc);
> -    return (err >= 0);
>  }
> diff --git a/vdagent/desktop_layout.h b/vdagent/desktop_layout.h
> index ece3946..fd6af76 100644
> --- a/vdagent/desktop_layout.h
> +++ b/vdagent/desktop_layout.h
> @@ -60,6 +60,7 @@ private:
>  };
>  
>  typedef std::vector<DisplayMode*> Displays;
> +class DisplayConfig;
>  
>  class DesktopLayout {
>  public:
> @@ -73,23 +74,21 @@ public:
>      size_t get_display_count() { return _displays.size();}
>      DWORD get_total_width() { return _total_width;}
>      DWORD get_total_height() { return _total_height;}
> -    void set_position_configurable(bool flag) { _send_monitors_position =
> flag; }
> +    void set_position_configurable(bool flag);
>  private:
>      void clean_displays();
>      void normalize_displays_pos();
>      DisplayMode * get_primary_display();
> -    bool update_monitor_config(LPCTSTR dev_name, DisplayMode* mode);
> +    bool init_dev_mode(LPCTSTR dev_name, DEVMODE* dev_mode, DisplayMode*
> mode);
>      static bool consistent_displays();
>      static bool is_attached(LPCTSTR dev_name);
>      static bool get_qxl_device_id(WCHAR* device_key, DWORD* device_id);
> -    static bool init_dev_mode(LPCTSTR dev_name, DEVMODE* dev_mode,
> DisplayMode* mode,
> -                              LONG normal_x, LONG normal_y, bool set_pos);
>  private:
>      mutex_t _mutex;
>      Displays _displays;
>      DWORD _total_width;
>      DWORD _total_height;
> -    bool _send_monitors_position;
> +    DisplayConfig* _display_config;
>  };
>  
>  #endif
> diff --git a/vdagent/display_configuration.cpp
> b/vdagent/display_configuration.cpp
> index a7aa0d7..5e40d05 100755
> --- a/vdagent/display_configuration.cpp
> +++ b/vdagent/display_configuration.cpp
> @@ -152,6 +152,180 @@ struct DISPLAYCONFIG_PATH_INFO {
>      UINT32 flags;
>  };
>  
> +struct QXLMonitorEscape {
> +    QXLMonitorEscape(DEVMODE* dev_mode)
> +    {
> +        ZeroMemory(&_head, sizeof(_head));
> +        _head.x = dev_mode->dmPosition.x;
> +        _head.y = dev_mode->dmPosition.y;
> +        _head.width = dev_mode->dmPelsWidth;
> +        _head.height = dev_mode->dmPelsHeight;
> +    }
> +    QXLHead _head;
> +};
> +
> +struct QxlCustomEscapeObj : public QXLEscapeSetCustomDisplay {
> +    QxlCustomEscapeObj(uint32_t bitsPerPel, uint32_t width, uint32_t height)
> +    {
> +        xres = width;
> +        yres = height;
> +        bpp = bitsPerPel;
> +    }
> +    QxlCustomEscapeObj() {};
> +};
> +
> +DisplayConfig* DisplayConfig::create_config()
> +{
> +    DisplayConfig* new_interface;
> +    new_interface = new XPDMInterface();
> +    return new_interface;
> +}
> +
> +DisplayConfig::DisplayConfig()
> +    : _send_monitors_config(false)
> +{}
> +
> +bool XPDMInterface::is_attached(DISPLAY_DEVICE* dev_info)
> +{
> +    return !!(dev_info->StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP);
> +}
> +
> +bool XPDMInterface::set_monitor_state(LPCTSTR device_name, DEVMODE*
> dev_mode, MONITOR_STATE state)
> +{
> +    dev_mode->dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_POSITION;
> +    if (state == MONITOR_ATTACHED) {
> +        return true;
> +    }
> +
> +    LONG status = ChangeDisplaySettingsEx(device_name, dev_mode, NULL,
> CDS_UPDATEREGISTRY, NULL);
> +    return (status == DISP_CHANGE_SUCCESSFUL);
> +}
> +
> +LONG XPDMInterface::update_display_settings()
> +{
> +    return ChangeDisplaySettingsEx(NULL, NULL, NULL, 0, NULL);
> +}
> +
> +bool XPDMInterface::update_dev_mode_position(LPCTSTR device_name,
> +                                             DEVMODE* dev_mode, LONG x, LONG
> y)
> +{
> +    //Convert the position so that the primary is always at (0,0)
> +    dev_mode->dmPosition.x = x;
> +    dev_mode->dmPosition.y = y;
> +    dev_mode->dmFields |= DM_POSITION;
> +    vd_printf("%s: setting %S at (%lu, %lu)", __FUNCTION__, device_name,
> dev_mode->dmPosition.x,
> +        dev_mode->dmPosition.y);
> +
> +    LONG status = ChangeDisplaySettingsEx(device_name, dev_mode, NULL,
> +                                          CDS_UPDATEREGISTRY | CDS_NORESET,
> NULL);
> +    return (status == DISP_CHANGE_SUCCESSFUL);
> +}
> +
> +bool XPDMInterface::custom_display_escape(LPCTSTR device_name, DEVMODE*
> dev_mode)
> +{
> +    LONG        ret;
> +    NTSTATUS    Status (ERROR_SUCCESS);
> +    HDC         hdc = CreateDC(device_name, NULL, NULL, NULL);
> +
> +    if (!hdc) {
> +        ret = ChangeDisplaySettingsEx(device_name, dev_mode, NULL,
> CDS_UPDATEREGISTRY, NULL);
> +        if (ret == DISP_CHANGE_BADMODE) {
> +            // custom resolution might not be set yet, use known resolution
> +            // FIXME: this causes client temporary resize... a
> +            // solution would involve passing custom resolution before
> +            // driver initialization, perhaps through registry
> +            dev_mode->dmPelsWidth = 640;
> +            dev_mode->dmPelsHeight = 480;
> +            ret = ChangeDisplaySettingsEx(device_name, dev_mode, NULL,
> CDS_UPDATEREGISTRY, NULL);
> +        }
> +
> +        vd_printf("attach %ld", ret);
> +        if (!(hdc = CreateDC(device_name, NULL, NULL, NULL))) {
> +            vd_printf("%s: failed to create DC", __FUNCTION__);
> +            return false;
> +        }
> +    }
> +
> +    QxlCustomEscapeObj custom_escape(dev_mode->dmBitsPerPel,
> +                                            dev_mode->dmPelsWidth,
> dev_mode->dmPelsHeight);
> +
> +    int err = ExtEscape(hdc, QXL_ESCAPE_SET_CUSTOM_DISPLAY,
> +              sizeof(QXLEscapeSetCustomDisplay), (LPCSTR) &custom_escape, 0,
> NULL);
> +    if (err <= 0) {
> +        vd_printf("%s: Can't set custom display, perhaps running with an
> older driver?",
> +            __FUNCTION__);
> +    }
> +
> +    if (!find_best_mode(device_name, dev_mode)) {
> +        Status = E_FAIL;
> +    }
> +
> +    DeleteDC(hdc);
> +    return NT_SUCCESS(Status);
> +}
> +
> +bool XPDMInterface::update_monitor_config(LPCTSTR device_name, DisplayMode*
> mode,
> +                                           DEVMODE* dev_mode)
> +{
> +    if (!mode || !mode->get_attached()) {
> +        return false;
> +    }
> +
> +    QXLMonitorEscape monitor_config(dev_mode);
> +    HDC hdc(CreateDC(device_name, NULL, NULL, NULL));
> +    int err(0);
> +
> +    if (!hdc || !_send_monitors_config) {
> +        return false;
> +    }
> +
> +    err = ExtEscape(hdc, QXL_ESCAPE_MONITOR_CONFIG, sizeof(QXLHead),
> +                    (LPCSTR) &monitor_config, 0, NULL);
> +    if (err < 0) {
> +        vd_printf("%s: %S can't update monitor config, may have old, old
> driver",
> +                 __FUNCTION__, device_name);
> +    }
> +    DeleteDC(hdc);
> +    return (err >= 0);
> +}
> +
> +bool XPDMInterface::find_best_mode(LPCTSTR Device, DEVMODE* dev_mode)
> +{
> +    DWORD closest_diff = -1;
> +    DWORD best = -1;
> +
> +    // force refresh mode table
> +    DEVMODE test_dev_mode;
> +    ZeroMemory(&test_dev_mode, sizeof(test_dev_mode));
> +    test_dev_mode.dmSize = sizeof(DEVMODE);
> +    EnumDisplaySettings(Device, 0xffffff, &test_dev_mode);
> +
> +    //Find the closest size which will fit within the monitor
> +    for (DWORD i = 0; EnumDisplaySettings(Device, i, &test_dev_mode); i++) {
> +        if (dev_mode->dmPelsWidth > test_dev_mode.dmPelsWidth ||
> +            dev_mode->dmPelsHeight > test_dev_mode.dmPelsHeight ||
> +            dev_mode->dmBitsPerPel != test_dev_mode.dmBitsPerPel) {
> +            continue;
> +        }
> +        DWORD wdiff = dev_mode->dmPelsWidth - test_dev_mode.dmPelsWidth;
> +        DWORD hdiff = dev_mode->dmPelsHeight - test_dev_mode.dmPelsHeight;
> +        DWORD diff = wdiff * wdiff + hdiff * hdiff;
> +        if (diff < closest_diff) {
> +            closest_diff = diff;
> +            best = i;
> +        }
> +    }
> +    vd_printf("%s: closest_diff at %lu best %lu", __FUNCTION__,
> closest_diff, best);
> +    if (best == (DWORD) -1 || !EnumDisplaySettings(Device, best, dev_mode))
> {
> +        return false;
> +    }
> +
> +    //Change to the best fit
> +    LONG status = ChangeDisplaySettingsEx(Device, dev_mode, NULL,
> +                                          CDS_UPDATEREGISTRY | CDS_NORESET,
> NULL);
> +    return NT_SUCCESS(status);
> +}
> +
>  CCD::CCD()
>      :_numPathElements(0)
>      ,_numModeElements(0)
> diff --git a/vdagent/display_configuration.h
> b/vdagent/display_configuration.h
> index 94e52e4..05b35f4 100755
> --- a/vdagent/display_configuration.h
> +++ b/vdagent/display_configuration.h
> @@ -89,4 +89,40 @@ private:
>      PATH_STATE _path_state;
>  };
>  
> +class DisplayMode;
> +
> +//Class provides interface to get/set display configurations
> +class DisplayConfig {
> +public:
> +    static DisplayConfig* create_config();
> +    DisplayConfig();
> +    virtual ~DisplayConfig() {};
> +    virtual bool is_attached(DISPLAY_DEVICE* dev_info) = 0;
> +    virtual bool custom_display_escape(LPCTSTR device, DEVMODE* mode) = 0;
> +    virtual bool update_monitor_config(LPCTSTR device, DisplayMode* mode,
> DEVMODE* dev_mode) = 0;
> +    virtual bool set_monitor_state(LPCTSTR device_name, DEVMODE* dev_mode,
> MONITOR_STATE state) = 0;
> +    virtual LONG update_display_settings() = 0;
> +    virtual bool update_dev_mode_position(LPCTSTR dev_name, DEVMODE*
> dev_mode, LONG x, LONG y) = 0;
> +    void set_monitors_config(bool flag) { _send_monitors_config = flag; }
> +    virtual void update_config_path() {};
> +
> +protected:
> +    bool _send_monitors_config;
> +};
> +
> +//DisplayConfig implementation for guest with XPDM graphics drivers
> +class XPDMInterface : public DisplayConfig {
> +public:
> +    XPDMInterface() :DisplayConfig() {};
> +    bool is_attached(DISPLAY_DEVICE* dev_info);
> +    bool custom_display_escape(LPCTSTR device_name, DEVMODE* dev_mode);
> +    bool update_monitor_config(LPCTSTR device_name, DisplayMode* mode,
> DEVMODE* dev_mode);
> +    bool set_monitor_state(LPCTSTR device_name, DEVMODE* dev_mode,
> MONITOR_STATE state);
> +    LONG update_display_settings();
> +    bool update_dev_mode_position(LPCTSTR device_name, DEVMODE * dev_mode,
> LONG x, LONG y);
> +
> +private:
> +    bool find_best_mode(LPCTSTR Device, DEVMODE* dev_mode);
> +};
> +
>  #endif
> \ No newline at end of file
> --
> 2.7.4
> 
> 


More information about the Spice-devel mailing list