This source file includes following definitions.
- resolution
- client_scale_factor
- aspect_ratio_goodness
- area
- IsBetterThan
- weak_factory_
- SetScreenResolution
- SetNowFunctionForTesting
#include "remoting/host/resizing_host_observer.h"
#include <list>
#include "base/bind.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "remoting/host/desktop_resizer.h"
#include "remoting/host/screen_resolution.h"
namespace remoting {
namespace {
const int kMinimumResizeIntervalMs = 1000;
class CandidateResolution {
public:
CandidateResolution(const ScreenResolution& candidate,
const ScreenResolution& preferred)
: resolution_(candidate) {
CHECK(!candidate.IsEmpty());
DCHECK(!preferred.IsEmpty());
if ((candidate.dimensions().width() > preferred.dimensions().width()) ||
(candidate.dimensions().height() > preferred.dimensions().height())) {
const float width_ratio =
static_cast<float>(preferred.dimensions().width()) /
candidate.dimensions().width();
const float height_ratio =
static_cast<float>(preferred.dimensions().height()) /
candidate.dimensions().height();
client_scale_factor_ = std::min(width_ratio, height_ratio);
} else {
client_scale_factor_ = 1.0;
}
float candidate_aspect_ratio =
static_cast<float>(candidate.dimensions().width()) /
candidate.dimensions().height();
float preferred_aspect_ratio =
static_cast<float>(preferred.dimensions().width()) /
preferred.dimensions().height();
if (candidate_aspect_ratio > preferred_aspect_ratio) {
aspect_ratio_goodness_ = preferred_aspect_ratio / candidate_aspect_ratio;
} else {
aspect_ratio_goodness_ = candidate_aspect_ratio / preferred_aspect_ratio;
}
}
const ScreenResolution& resolution() const { return resolution_; }
float client_scale_factor() const { return client_scale_factor_; }
float aspect_ratio_goodness() const { return aspect_ratio_goodness_; }
int64 area() const {
return static_cast<int64>(resolution_.dimensions().width()) *
resolution_.dimensions().height();
}
bool IsBetterThan(const CandidateResolution& other) const {
if (client_scale_factor() < other.client_scale_factor()) {
return false;
} else if (client_scale_factor() > other.client_scale_factor()) {
return true;
}
if (area() < other.area()) {
return false;
} else if (area() > other.area()) {
return true;
}
if (aspect_ratio_goodness() < other.aspect_ratio_goodness()) {
return false;
} else if (aspect_ratio_goodness() > other.aspect_ratio_goodness()) {
return true;
}
return resolution().dimensions().width() >
other.resolution().dimensions().width();
}
private:
float client_scale_factor_;
float aspect_ratio_goodness_;
ScreenResolution resolution_;
};
}
ResizingHostObserver::ResizingHostObserver(
scoped_ptr<DesktopResizer> desktop_resizer)
: desktop_resizer_(desktop_resizer.Pass()),
now_function_(base::Bind(base::Time::Now)),
weak_factory_(this) {
}
ResizingHostObserver::~ResizingHostObserver() {
if (!original_resolution_.IsEmpty())
desktop_resizer_->RestoreResolution(original_resolution_);
}
void ResizingHostObserver::SetScreenResolution(
const ScreenResolution& resolution) {
base::Time now = now_function_.Run();
if (resolution.IsEmpty())
return;
base::TimeDelta minimum_resize_interval =
base::TimeDelta::FromMilliseconds(kMinimumResizeIntervalMs);
base::Time next_allowed_resize =
previous_resize_time_ + minimum_resize_interval;
if (now < next_allowed_resize) {
deferred_resize_timer_.Start(
FROM_HERE,
next_allowed_resize - now,
base::Bind(&ResizingHostObserver::SetScreenResolution,
weak_factory_.GetWeakPtr(), resolution));
return;
}
std::list<ScreenResolution> resolutions =
desktop_resizer_->GetSupportedResolutions(resolution);
if (resolutions.empty())
return;
CandidateResolution best_candidate(resolutions.front(), resolution);
for (std::list<ScreenResolution>::const_iterator i = ++resolutions.begin();
i != resolutions.end(); ++i) {
CandidateResolution candidate(*i, resolution);
if (candidate.IsBetterThan(best_candidate)) {
best_candidate = candidate;
}
}
ScreenResolution current_resolution =
desktop_resizer_->GetCurrentResolution();
if (!best_candidate.resolution().Equals(current_resolution)) {
if (original_resolution_.IsEmpty())
original_resolution_ = current_resolution;
desktop_resizer_->SetResolution(best_candidate.resolution());
}
previous_resize_time_ = now;
}
void ResizingHostObserver::SetNowFunctionForTesting(
const base::Callback<base::Time(void)>& now_function) {
now_function_ = now_function;
}
}