This source file includes following definitions.
- GetCurrentResolution
- GetSupportedResolutions
- SetResolution
- RestoreResolution
- IsResizeSupported
- GetPrimaryDisplayMode
- IsModeValid
- GetModeResolution
- Create
#include "remoting/host/desktop_resizer.h"
#include <map>
#include <windows.h>
#include "base/logging.h"
namespace {
const int kDefaultDPI = 96;
}
namespace remoting {
static inline bool operator <(const ScreenResolution& a,
const ScreenResolution& b) {
if (a.dimensions().width() != b.dimensions().width())
return a.dimensions().width() < b.dimensions().width();
if (a.dimensions().height() != b.dimensions().height())
return a.dimensions().height() < b.dimensions().height();
if (a.dpi().x() != b.dpi().x())
return a.dpi().x() < b.dpi().x();
return a.dpi().y() < b.dpi().y();
}
class DesktopResizerWin : public DesktopResizer {
public:
DesktopResizerWin();
virtual ~DesktopResizerWin();
virtual ScreenResolution GetCurrentResolution() OVERRIDE;
virtual std::list<ScreenResolution> GetSupportedResolutions(
const ScreenResolution& preferred) OVERRIDE;
virtual void SetResolution(const ScreenResolution& resolution) OVERRIDE;
virtual void RestoreResolution(const ScreenResolution& original) OVERRIDE;
private:
static bool IsResizeSupported();
static bool GetPrimaryDisplayMode(
DWORD mode_number, DWORD flags, DEVMODE* mode);
static bool IsModeValid(const DEVMODE& mode);
static ScreenResolution GetModeResolution(const DEVMODE& mode);
std::map<ScreenResolution, DEVMODE> best_mode_for_resolution_;
DISALLOW_COPY_AND_ASSIGN(DesktopResizerWin);
};
DesktopResizerWin::DesktopResizerWin() {
}
DesktopResizerWin::~DesktopResizerWin() {
}
ScreenResolution DesktopResizerWin::GetCurrentResolution() {
DEVMODE current_mode;
if (GetPrimaryDisplayMode(ENUM_CURRENT_SETTINGS, 0, ¤t_mode) &&
IsModeValid(current_mode))
return GetModeResolution(current_mode);
return ScreenResolution();
}
std::list<ScreenResolution> DesktopResizerWin::GetSupportedResolutions(
const ScreenResolution& preferred) {
if (!IsResizeSupported())
return std::list<ScreenResolution>();
DEVMODE current_mode;
if (!GetPrimaryDisplayMode(ENUM_CURRENT_SETTINGS, 0, ¤t_mode) ||
!IsModeValid(current_mode))
return std::list<ScreenResolution>();
std::list<ScreenResolution> resolutions;
best_mode_for_resolution_.clear();
for (DWORD i = 0; ; ++i) {
DEVMODE candidate_mode;
if (!GetPrimaryDisplayMode(i, EDS_ROTATEDMODE, &candidate_mode))
break;
if (!IsModeValid(candidate_mode))
continue;
if (candidate_mode.dmBitsPerPel != current_mode.dmBitsPerPel)
continue;
ScreenResolution candidate_resolution = GetModeResolution(candidate_mode);
if (best_mode_for_resolution_.count(candidate_resolution) != 0) {
DEVMODE best_mode = best_mode_for_resolution_[candidate_resolution];
if ((candidate_mode.dmDisplayOrientation !=
current_mode.dmDisplayOrientation) &&
(best_mode.dmDisplayOrientation ==
current_mode.dmDisplayOrientation)) {
continue;
}
if ((candidate_mode.dmDisplayFrequency !=
current_mode.dmDisplayFrequency) &&
(best_mode.dmDisplayFrequency >=
candidate_mode.dmDisplayFrequency)) {
continue;
}
} else {
resolutions.push_back(candidate_resolution);
}
best_mode_for_resolution_[candidate_resolution] = candidate_mode;
}
return resolutions;
}
void DesktopResizerWin::SetResolution(const ScreenResolution& resolution) {
if (best_mode_for_resolution_.count(resolution) == 0)
return;
DEVMODE new_mode = best_mode_for_resolution_[resolution];
DWORD result = ChangeDisplaySettings(&new_mode, CDS_FULLSCREEN);
if (result != DISP_CHANGE_SUCCESSFUL)
LOG(ERROR) << "SetResolution failed: " << result;
}
void DesktopResizerWin::RestoreResolution(const ScreenResolution& original) {
DWORD result = ChangeDisplaySettings(NULL, 0);
if (result != DISP_CHANGE_SUCCESSFUL)
LOG(ERROR) << "RestoreResolution failed: " << result;
}
bool DesktopResizerWin::IsResizeSupported() {
return GetSystemMetrics(SM_CMONITORS) == 1;
}
bool DesktopResizerWin::GetPrimaryDisplayMode(
DWORD mode_number, DWORD flags, DEVMODE* mode) {
memset(mode, 0, sizeof(DEVMODE));
mode->dmSize = sizeof(DEVMODE);
if (!EnumDisplaySettingsEx(NULL, mode_number, mode, flags))
return false;
return true;
}
bool DesktopResizerWin::IsModeValid(const DEVMODE& mode) {
const DWORD kRequiredFields =
DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL |
DM_DISPLAYFREQUENCY | DM_DISPLAYORIENTATION;
return (mode.dmFields & kRequiredFields) == kRequiredFields;
}
ScreenResolution DesktopResizerWin::GetModeResolution(const DEVMODE& mode) {
DCHECK(IsModeValid(mode));
return ScreenResolution(
webrtc::DesktopSize(mode.dmPelsWidth, mode.dmPelsHeight),
webrtc::DesktopVector(kDefaultDPI, kDefaultDPI));
}
scoped_ptr<DesktopResizer> DesktopResizer::Create() {
return scoped_ptr<DesktopResizer>(new DesktopResizerWin);
}
}