[Spice-devel] [PATCH spice vdagent] vdagent: use best match for resolution change

Hans de Goede hdegoede at redhat.com
Tue Dec 14 07:06:58 PST 2010


Ack.

On 12/14/2010 03:48 PM, Arnon Gilboa wrote:
> similar handling as linux agent
> ---
>   vdagent/desktop_layout.cpp |   85 ++++++++++++++++++++++++++++----------------
>   vdagent/desktop_layout.h   |    4 ++-
>   2 files changed, 57 insertions(+), 32 deletions(-)
>
> diff --git a/vdagent/desktop_layout.cpp b/vdagent/desktop_layout.cpp
> index 32502bc..7040434 100644
> --- a/vdagent/desktop_layout.cpp
> +++ b/vdagent/desktop_layout.cpp
> @@ -106,25 +106,28 @@ void DesktopLayout::set_displays()
>       dev_info.cb = sizeof(dev_info);
>       ZeroMemory(&dev_mode, sizeof(dev_mode));
>       dev_mode.dmSize = sizeof(dev_mode);
> -    while (EnumDisplayDevices(NULL, dev_id,&dev_info, 0)) {
> -        if (wcsstr(dev_info.DeviceString, L"QXL")) {
> -            if (!get_qxl_device_id(dev_info.DeviceKey,&qxl_id)) {
> -                vd_printf("get_qxl_device_id failed");
> -                break;
> -            }
> -            if (qxl_id>= _displays.size()) {
> -                vd_printf("qxl_id %u out of range, #displays %u", qxl_id, _displays.size());
> -                break;
> -            }
> -            //FIXME: always set pos?
> -            init_dev_mode(&dev_mode, _displays.at(qxl_id), true);
> -            LONG ret = ChangeDisplaySettingsEx(dev_info.DeviceName,&dev_mode, NULL,
> -                                               CDS_UPDATEREGISTRY | CDS_NORESET, NULL);
> -            if (ret == DISP_CHANGE_SUCCESSFUL) {
> -                dev_sets++;
> -            }
> +    while (EnumDisplayDevices(NULL, dev_id++,&dev_info, 0)) {
> +        if (!wcsstr(dev_info.DeviceString, L"QXL")) {
> +            continue;
> +        }
> +        if (!get_qxl_device_id(dev_info.DeviceKey,&qxl_id)) {
> +            vd_printf("get_qxl_device_id failed");
> +            break;
> +        }
> +        if (qxl_id>= _displays.size()) {
> +            vd_printf("qxl_id %u out of range, #displays %u", qxl_id, _displays.size());
> +            break;
> +        }
> +        if (!init_dev_mode(dev_info.DeviceName,&dev_mode, _displays.at(qxl_id), true)) {
> +            vd_printf("No suitable mode found for display %S", dev_info.DeviceName);
> +            break;
> +        }
> +        vd_printf("Set display mode %ux%u", 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) {
> +            dev_sets++;
>           }
> -        dev_id++;
>       }
>       if (dev_sets) {
>           ChangeDisplaySettingsEx(NULL, NULL, NULL, 0, NULL);
> @@ -173,23 +176,43 @@ bool DesktopLayout::get_qxl_device_id(WCHAR* device_key, DWORD* device_id)
>       return key_found;
>   }
>
> -void DesktopLayout::init_dev_mode(DEVMODE* dev_mode, DisplayMode* mode, bool set_pos)
> +bool DesktopLayout::init_dev_mode(LPCTSTR dev_name, DEVMODE* dev_mode, DisplayMode* mode,
> +                                  bool set_pos)
>   {
> +    DWORD closest_diff = -1;
> +    DWORD best = -1;
> +
>       ZeroMemory(dev_mode, sizeof(DEVMODE));
>       dev_mode->dmSize = sizeof(DEVMODE);
> -    if (mode&&  mode->get_attached()) {
> -        dev_mode->dmBitsPerPel = mode->get_depth();
> -        dev_mode->dmPelsWidth = mode->get_width();
> -        dev_mode->dmPelsHeight = mode->get_height();
> -        dev_mode->dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
> -        if (set_pos) {
> -            dev_mode->dmPosition.x = mode->get_pos_x();
> -            dev_mode->dmPosition.y = mode->get_pos_y();
> -            dev_mode->dmFields |= DM_POSITION;
> -        }
> -    } else {
> -        //detach monitor
> +    if (!mode || !mode->_attached) {
> +        //Detach monitor
>           dev_mode->dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_POSITION;
> +        return true;
> +    }
> +    //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 == -1 || !EnumDisplaySettings(dev_name, best, dev_mode)) {
> +        return false;
> +    }
> +    dev_mode->dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
> +    if (set_pos) {
> +        dev_mode->dmPosition.x = mode->_pos_x;
> +        dev_mode->dmPosition.y = mode->_pos_y;
> +        dev_mode->dmFields |= DM_POSITION;
>       }
> +    return true;
>   }
>
> diff --git a/vdagent/desktop_layout.h b/vdagent/desktop_layout.h
> index a43ee49..f3294b5 100644
> --- a/vdagent/desktop_layout.h
> +++ b/vdagent/desktop_layout.h
> @@ -52,6 +52,8 @@ private:
>       DWORD _height;
>       DWORD _depth;
>       bool _attached;
> +
> +    friend class DesktopLayout;
>   };
>
>   typedef std::vector<DisplayMode*>  Displays;
> @@ -73,7 +75,7 @@ private:
>       void clean_displays();
>       static bool is_attached(LPCTSTR dev_name);
>       static bool get_qxl_device_id(WCHAR* device_key, DWORD* device_id);
> -    static void init_dev_mode(DEVMODE* dev_mode, DisplayMode* mode, bool set_pos);
> +    static bool init_dev_mode(LPCTSTR dev_name, DEVMODE* dev_mode, DisplayMode* mode, bool set_pos);
>
>   private:
>       mutex_t _mutex;


More information about the Spice-devel mailing list