OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 /** | 5 /** |
6 * @fileoverview | 6 * @fileoverview |
7 * Class handling creation and teardown of a remoting client session. | 7 * Class handling creation and teardown of a remoting client session. |
8 * | 8 * |
9 * The ClientSession class controls lifetime of the client plugin | 9 * The ClientSession class controls lifetime of the client plugin |
10 * object and provides the plugin with the functionality it needs to | 10 * object and provides the plugin with the functionality it needs to |
(...skipping 1237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1248 remoting.ClientSession.prototype.updateDimensions = function() { | 1248 remoting.ClientSession.prototype.updateDimensions = function() { |
1249 if (this.plugin_.getDesktopWidth() == 0 || | 1249 if (this.plugin_.getDesktopWidth() == 0 || |
1250 this.plugin_.getDesktopHeight() == 0) { | 1250 this.plugin_.getDesktopHeight() == 0) { |
1251 return; | 1251 return; |
1252 } | 1252 } |
1253 | 1253 |
1254 var clientArea = this.getClientArea_(); | 1254 var clientArea = this.getClientArea_(); |
1255 var desktopWidth = this.plugin_.getDesktopWidth(); | 1255 var desktopWidth = this.plugin_.getDesktopWidth(); |
1256 var desktopHeight = this.plugin_.getDesktopHeight(); | 1256 var desktopHeight = this.plugin_.getDesktopHeight(); |
1257 | 1257 |
1258 // When configured to display a host at its original size, we aim to display | 1258 // We have the following goals in sizing the desktop display at the client: |
1259 // it as close to its physical size as possible, without losing data: | 1259 // 1. Avoid losing detail by down-scaling beyond 1:1 host:device pixels. |
1260 // - If client and host have matching DPI, render the host pixel-for-pixel. | 1260 // 2. Avoid up-scaling if that will cause the client to need scrollbars. |
1261 // - If the host has higher DPI then still render pixel-for-pixel. | 1261 // 3. Avoid introducing blurriness with non-integer up-scaling factors. |
1262 // - If the host has lower DPI then let Chrome up-scale it to natural size. | 1262 // 4. Avoid having huge "letterboxes" around the desktop, if it's really |
1263 // small. | |
1264 // | |
1265 // To determine the ideal size we follow a four-stage process: | |
1266 // 1. Determine the "natural" size at which to display the desktop. | |
1267 // a. Initially assume 1:1 mapping of desktop to client device pixels. | |
1268 // 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?
| |
1269 // c. If desktopScale is configured for the host then allow that to | |
1270 // 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
| |
1271 // 2. If the natural size of the desktop is smaller than the client device | |
1272 // then apply up-scaling by an integer scale factor to avoid excessive | |
1273 // letterboxing. | |
Jamie
2015/01/09 22:23:47
Does "avoid excessive letterboxing" imply that we'
| |
1274 // 3. If shrink-to-fit is configured, and the natural size exceeds the | |
1275 // client size then apply down-scaling by an arbitrary scale factor. | |
1276 // 4. If the overall scale factor is fractionally over an integer factor | |
1277 // 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
| |
1263 | 1278 |
1264 // We specify the plugin dimensions in Density-Independent Pixels, so to | 1279 // All calculations are performed in device pixels. |
1265 // render pixel-for-pixel we need to down-scale the host dimensions by the | 1280 var clientWidth = clientArea.width * window.devicePixelRatio; |
1266 // devicePixelRatio of the client. To match the host pixel density, we choose | 1281 var clientHeight = clientArea.height * window.devicePixelRatio; |
1267 // an initial scale factor based on the client devicePixelRatio and host DPI. | |
1268 | 1282 |
1269 // Determine the effective device pixel ratio of the host, based on DPI. | 1283 // 1. Determine a "natural" size at which to display the desktop. |
1284 var scale = 1.0; | |
1285 | |
1286 // Determine the effective host device pixel ratio. | |
1270 var hostPixelRatioX = Math.ceil(this.plugin_.getDesktopXDpi() / 96); | 1287 var hostPixelRatioX = Math.ceil(this.plugin_.getDesktopXDpi() / 96); |
1271 var hostPixelRatioY = Math.ceil(this.plugin_.getDesktopYDpi() / 96); | 1288 var hostPixelRatioY = Math.ceil(this.plugin_.getDesktopYDpi() / 96); |
1272 var hostPixelRatio = Math.min(hostPixelRatioX, hostPixelRatioY); | 1289 var hostPixelRatio = Math.min(hostPixelRatioX, hostPixelRatioY); |
1273 | 1290 |
1274 // Include the desktopScale in the hostPixelRatio before comparing it with | 1291 // Allow up-scaling to account for DPI. |
1275 // the client devicePixelRatio to determine the "natural" scale to use. | 1292 scale = Math.max(scale, window.devicePixelRatio / hostPixelRatio); |
1276 hostPixelRatio *= this.desktopScale_; | |
1277 | 1293 |
1278 // Down-scale by the smaller of the client and host ratios. | 1294 // Allow some or all of the up-scaling to be cancelled by the desktopScale. |
1279 var scale = 1.0 / Math.min(window.devicePixelRatio, hostPixelRatio); | 1295 if (this.desktopScale_ > 1.0) { |
1296 scale = Math.max(1.0, scale / this.desktopScale_); | |
1297 } | |
1280 | 1298 |
1299 // 2. Up-scale to avoid excessive letterboxing, if necessary. | |
1300 if (desktopWidth * scale <= clientWidth && | |
1301 desktopHeight * scale <= clientHeight) { | |
1302 var scaleX = Math.floor(clientWidth / desktopWidth); | |
1303 var scaleY = Math.floor(clientHeight / desktopHeight); | |
1304 scale = Math.min(scaleX, scaleY); | |
1305 } | |
1306 | |
1307 // 3. Apply shrink-to-fit, if configured. | |
1281 if (this.shrinkToFit_) { | 1308 if (this.shrinkToFit_) { |
1282 // Reduce the scale, if necessary, to fit the whole desktop in the window. | 1309 var scaleFitWidth = Math.min(scale, 1.0 * clientWidth / desktopWidth); |
1283 var scaleFitWidth = Math.min(scale, 1.0 * clientArea.width / desktopWidth); | 1310 var scaleFitHeight = Math.min(scale, 1.0 * clientHeight / desktopHeight); |
1284 var scaleFitHeight = | |
1285 Math.min(scale, 1.0 * clientArea.height / desktopHeight); | |
1286 scale = Math.min(scaleFitHeight, scaleFitWidth); | 1311 scale = Math.min(scaleFitHeight, scaleFitWidth); |
1287 | 1312 |
1313 // TODO(wez): Fix multi-monitor and wide/tall desktop handling. | |
1288 // If we're running full-screen then try to handle common side-by-side | 1314 // If we're running full-screen then try to handle common side-by-side |
1289 // multi-monitor combinations more intelligently. | 1315 // multi-monitor combinations more intelligently. |
1290 if (remoting.fullscreen.isActive()) { | 1316 if (remoting.fullscreen.isActive()) { |
1291 // If the host has two monitors each the same size as the client then | 1317 // If the host has two monitors each the same size as the client then |
1292 // scale-to-fit will have the desktop occupy only 50% of the client area, | 1318 // scale-to-fit will have the desktop occupy only 50% of the client area, |
1293 // in which case it would be preferable to down-scale less and let the | 1319 // in which case it would be preferable to down-scale less and let the |
1294 // user bump-scroll around ("scale-and-pan"). | 1320 // user bump-scroll around ("scale-and-pan"). |
1295 // Triggering scale-and-pan if less than 65% of the client area would be | 1321 // Triggering scale-and-pan if less than 65% of the client area would be |
1296 // used adds enough fuzz to cope with e.g. 1280x800 client connecting to | 1322 // used adds enough fuzz to cope with e.g. 1280x800 client connecting to |
1297 // a (2x1280)x1024 host nicely. | 1323 // a (2x1280)x1024 host nicely. |
1298 // Note that we don't need to account for scrollbars while fullscreen. | 1324 // Note that we don't need to account for scrollbars while fullscreen. |
1299 if (scale <= scaleFitHeight * 0.65) { | 1325 if (scale <= scaleFitHeight * 0.65) { |
1300 scale = scaleFitHeight; | 1326 scale = scaleFitHeight; |
1301 } | 1327 } |
1302 if (scale <= scaleFitWidth * 0.65) { | 1328 if (scale <= scaleFitWidth * 0.65) { |
1303 scale = scaleFitWidth; | 1329 scale = scaleFitWidth; |
1304 } | 1330 } |
1305 } | 1331 } |
1306 } | 1332 } |
1307 | 1333 |
1334 // 4. Avoid blurring for close-to-integer up-scaling factors. | |
1335 if (scale > 1.0) { | |
1336 var scaleBlurriness = scale / Math.floor(scale); | |
1337 if (scaleBlurriness < 1.1) { | |
1338 scale = Math.floor(scale); | |
1339 } | |
1340 } | |
1341 | |
1342 // Determine the necessary plugin dimensions in DIPs. | |
1343 scale = scale / window.devicePixelRatio; | |
1308 var pluginWidth = Math.round(desktopWidth * scale); | 1344 var pluginWidth = Math.round(desktopWidth * scale); |
1309 var pluginHeight = Math.round(desktopHeight * scale); | 1345 var pluginHeight = Math.round(desktopHeight * scale); |
1310 | 1346 |
1311 // Resize the plugin if necessary. | 1347 // Resize the plugin if necessary. |
1312 // TODO(wez): Handle high-DPI to high-DPI properly (crbug.com/135089). | 1348 // TODO(wez): Handle high-DPI to high-DPI properly (crbug.com/135089). |
1313 this.plugin_.element().style.width = pluginWidth + 'px'; | 1349 this.plugin_.element().style.width = pluginWidth + 'px'; |
1314 this.plugin_.element().style.height = pluginHeight + 'px'; | 1350 this.plugin_.element().style.height = pluginHeight + 'px'; |
1315 | 1351 |
1316 // Position the container. | 1352 // Position the container. |
1317 // Note that clientWidth/Height take into account scrollbars. | 1353 // Note that clientWidth/Height take into account scrollbars. |
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1726 * @param {Object} message The parsed extension message data. | 1762 * @param {Object} message The parsed extension message data. |
1727 * @return {boolean} True if the message was recognized, false otherwise. | 1763 * @return {boolean} True if the message was recognized, false otherwise. |
1728 */ | 1764 */ |
1729 remoting.ClientSession.prototype.handleExtensionMessage = | 1765 remoting.ClientSession.prototype.handleExtensionMessage = |
1730 function(type, message) { | 1766 function(type, message) { |
1731 if (this.videoFrameRecorder_) { | 1767 if (this.videoFrameRecorder_) { |
1732 return this.videoFrameRecorder_.handleMessage(type, message); | 1768 return this.videoFrameRecorder_.handleMessage(type, message); |
1733 } | 1769 } |
1734 return false; | 1770 return false; |
1735 } | 1771 } |
OLD | NEW |