Index: remoting/webapp/crd/js/client_session.js |
diff --git a/remoting/webapp/crd/js/client_session.js b/remoting/webapp/crd/js/client_session.js |
index 9a2cab2ed4aadf3befb689e96256de4948a8d60b..2600da39eb401c05ab4ff0551b680d7b803b86e9 100644 |
--- a/remoting/webapp/crd/js/client_session.js |
+++ b/remoting/webapp/crd/js/client_session.js |
@@ -1255,36 +1255,62 @@ remoting.ClientSession.prototype.updateDimensions = function() { |
var desktopWidth = this.plugin_.getDesktopWidth(); |
var desktopHeight = this.plugin_.getDesktopHeight(); |
- // When configured to display a host at its original size, we aim to display |
- // it as close to its physical size as possible, without losing data: |
- // - If client and host have matching DPI, render the host pixel-for-pixel. |
- // - If the host has higher DPI then still render pixel-for-pixel. |
- // - If the host has lower DPI then let Chrome up-scale it to natural size. |
- |
- // We specify the plugin dimensions in Density-Independent Pixels, so to |
- // render pixel-for-pixel we need to down-scale the host dimensions by the |
- // devicePixelRatio of the client. To match the host pixel density, we choose |
- // an initial scale factor based on the client devicePixelRatio and host DPI. |
- |
- // Determine the effective device pixel ratio of the host, based on DPI. |
+ // We have the following goals in sizing the desktop display at the client: |
+ // 1. Avoid losing detail by down-scaling beyond 1:1 host:device pixels. |
+ // 2. Avoid up-scaling if that will cause the client to need scrollbars. |
+ // 3. Avoid introducing blurriness with non-integer up-scaling factors. |
+ // 4. Avoid having huge "letterboxes" around the desktop, if it's really |
+ // small. |
+ // |
+ // To determine the ideal size we follow a four-stage process: |
+ // 1. Determine the "natural" size at which to display the desktop. |
+ // a. Initially assume 1:1 mapping of desktop to client device pixels. |
+ // b. If host DPI is less than the client's then up-scale accordingly. |
Jamie
2015/01/09 22:23:47
Does this overrule constraint 3, above?
|
+ // c. If desktopScale is configured for the host then allow that to |
+ // cancel-out some or all of the up-scaling from (b). |
Jamie
2015/01/09 22:23:47
It's not clear what "some or all" means here. Can
|
+ // 2. If the natural size of the desktop is smaller than the client device |
+ // then apply up-scaling by an integer scale factor to avoid excessive |
+ // letterboxing. |
Jamie
2015/01/09 22:23:47
Does "avoid excessive letterboxing" imply that we'
|
+ // 3. If shrink-to-fit is configured, and the natural size exceeds the |
+ // client size then apply down-scaling by an arbitrary scale factor. |
+ // 4. If the overall scale factor is fractionally over an integer factor |
+ // then reduce it to that integer factor, to avoid blurring. |
Jamie
2015/01/09 22:23:47
By "fractionally", do mean "only just"? Given that
|
+ |
+ // All calculations are performed in device pixels. |
+ var clientWidth = clientArea.width * window.devicePixelRatio; |
+ var clientHeight = clientArea.height * window.devicePixelRatio; |
+ |
+ // 1. Determine a "natural" size at which to display the desktop. |
+ var scale = 1.0; |
+ |
+ // Determine the effective host device pixel ratio. |
var hostPixelRatioX = Math.ceil(this.plugin_.getDesktopXDpi() / 96); |
var hostPixelRatioY = Math.ceil(this.plugin_.getDesktopYDpi() / 96); |
var hostPixelRatio = Math.min(hostPixelRatioX, hostPixelRatioY); |
- // Include the desktopScale in the hostPixelRatio before comparing it with |
- // the client devicePixelRatio to determine the "natural" scale to use. |
- hostPixelRatio *= this.desktopScale_; |
+ // Allow up-scaling to account for DPI. |
+ scale = Math.max(scale, window.devicePixelRatio / hostPixelRatio); |
- // Down-scale by the smaller of the client and host ratios. |
- var scale = 1.0 / Math.min(window.devicePixelRatio, hostPixelRatio); |
+ // Allow some or all of the up-scaling to be cancelled by the desktopScale. |
+ if (this.desktopScale_ > 1.0) { |
+ scale = Math.max(1.0, scale / this.desktopScale_); |
+ } |
+ |
+ // 2. Up-scale to avoid excessive letterboxing, if necessary. |
+ if (desktopWidth * scale <= clientWidth && |
+ desktopHeight * scale <= clientHeight) { |
+ var scaleX = Math.floor(clientWidth / desktopWidth); |
+ var scaleY = Math.floor(clientHeight / desktopHeight); |
+ scale = Math.min(scaleX, scaleY); |
+ } |
+ // 3. Apply shrink-to-fit, if configured. |
if (this.shrinkToFit_) { |
- // Reduce the scale, if necessary, to fit the whole desktop in the window. |
- var scaleFitWidth = Math.min(scale, 1.0 * clientArea.width / desktopWidth); |
- var scaleFitHeight = |
- Math.min(scale, 1.0 * clientArea.height / desktopHeight); |
+ var scaleFitWidth = Math.min(scale, 1.0 * clientWidth / desktopWidth); |
+ var scaleFitHeight = Math.min(scale, 1.0 * clientHeight / desktopHeight); |
scale = Math.min(scaleFitHeight, scaleFitWidth); |
+ // TODO(wez): Fix multi-monitor and wide/tall desktop handling. |
// If we're running full-screen then try to handle common side-by-side |
// multi-monitor combinations more intelligently. |
if (remoting.fullscreen.isActive()) { |
@@ -1305,6 +1331,16 @@ remoting.ClientSession.prototype.updateDimensions = function() { |
} |
} |
+ // 4. Avoid blurring for close-to-integer up-scaling factors. |
+ if (scale > 1.0) { |
+ var scaleBlurriness = scale / Math.floor(scale); |
+ if (scaleBlurriness < 1.1) { |
+ scale = Math.floor(scale); |
+ } |
+ } |
+ |
+ // Determine the necessary plugin dimensions in DIPs. |
+ scale = scale / window.devicePixelRatio; |
var pluginWidth = Math.round(desktopWidth * scale); |
var pluginHeight = Math.round(desktopHeight * scale); |