[Spice-devel] [PATCH spice vdagent] vdagent: use best match for resolution change
Arnon Gilboa
agilboa at redhat.com
Tue Dec 14 06:48:23 PST 2010
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;
--
1.5.5.6
More information about the Spice-devel
mailing list