| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 * Provides view port management utilities below for a desktop remoting session. | 7 * Provides view port management utilities below for a desktop remoting session. |
| 8 * - Enabling bump scrolling | 8 * - Enabling bump scrolling |
| 9 * - Resizing the viewport to fit the host desktop | 9 * - Resizing the viewport to fit the host desktop |
| 10 * - Resizing the host desktop to fit the client viewport. | 10 * - Resizing the host desktop to fit the client viewport. |
| (...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 323 remoting.DesktopViewport.prototype.updateDimensions_ = function() { | 323 remoting.DesktopViewport.prototype.updateDimensions_ = function() { |
| 324 var dimensions = this.hostDesktop_.getDimensions(); | 324 var dimensions = this.hostDesktop_.getDimensions(); |
| 325 if (dimensions.width === 0 || dimensions.height === 0) { | 325 if (dimensions.width === 0 || dimensions.height === 0) { |
| 326 return; | 326 return; |
| 327 } | 327 } |
| 328 | 328 |
| 329 var desktopSize = { width: dimensions.width, | 329 var desktopSize = { width: dimensions.width, |
| 330 height: dimensions.height }; | 330 height: dimensions.height }; |
| 331 var desktopDpi = { x: dimensions.xDpi, | 331 var desktopDpi = { x: dimensions.xDpi, |
| 332 y: dimensions.yDpi }; | 332 y: dimensions.yDpi }; |
| 333 var newSize = remoting.DesktopViewport.choosePluginSize( | 333 var newSize = remoting.Viewport.choosePluginSize( |
| 334 this.getClientArea(), window.devicePixelRatio, | 334 this.getClientArea(), window.devicePixelRatio, |
| 335 desktopSize, desktopDpi, this.hostOptions_.desktopScale, | 335 desktopSize, desktopDpi, this.hostOptions_.desktopScale, |
| 336 remoting.fullscreen.isActive(), this.hostOptions_.shrinkToFit); | 336 remoting.fullscreen.isActive(), this.hostOptions_.shrinkToFit); |
| 337 | 337 |
| 338 // Resize the plugin if necessary. | 338 // Resize the plugin if necessary. |
| 339 console.log('plugin dimensions:' + newSize.width + 'x' + newSize.height); | 339 console.log('plugin dimensions:' + newSize.width + 'x' + newSize.height); |
| 340 this.pluginElement_.style.width = newSize.width + 'px'; | 340 this.pluginElement_.style.width = newSize.width + 'px'; |
| 341 this.pluginElement_.style.height = newSize.height + 'px'; | 341 this.pluginElement_.style.height = newSize.height + 'px'; |
| 342 }; | 342 }; |
| 343 | 343 |
| 344 /** | |
| 345 * Helper function accepting client and host dimensions, and returning a chosen | |
| 346 * size for the plugin element, in DIPs. | |
| 347 * | |
| 348 * @param {{width: number, height: number}} clientSizeDips Available client | |
| 349 * dimensions, in DIPs. | |
| 350 * @param {number} clientPixelRatio Number of physical pixels per client DIP. | |
| 351 * @param {{width: number, height: number}} desktopSize Size of the host desktop | |
| 352 * in physical pixels. | |
| 353 * @param {{x: number, y: number}} desktopDpi DPI of the host desktop in both | |
| 354 * dimensions. | |
| 355 * @param {number} desktopScale The scale factor configured for the host. | |
| 356 * @param {boolean} isFullscreen True if full-screen mode is active. | |
| 357 * @param {boolean} shrinkToFit True if shrink-to-fit should be applied. | |
| 358 * @return {{width: number, height: number}} Chosen plugin dimensions, in DIPs. | |
| 359 */ | |
| 360 remoting.DesktopViewport.choosePluginSize = function( | |
| 361 clientSizeDips, clientPixelRatio, desktopSize, desktopDpi, desktopScale, | |
| 362 isFullscreen, shrinkToFit) { | |
| 363 base.debug.assert(clientSizeDips.width > 0); | |
| 364 base.debug.assert(clientSizeDips.height > 0); | |
| 365 base.debug.assert(clientPixelRatio >= 1.0); | |
| 366 base.debug.assert(desktopSize.width > 0); | |
| 367 base.debug.assert(desktopSize.height > 0); | |
| 368 base.debug.assert(desktopDpi.x > 0); | |
| 369 base.debug.assert(desktopDpi.y > 0); | |
| 370 base.debug.assert(desktopScale > 0); | |
| 371 | |
| 372 // We have the following goals in sizing the desktop display at the client: | |
| 373 // 1. Avoid losing detail by down-scaling beyond 1:1 host:device pixels. | |
| 374 // 2. Avoid up-scaling if that will cause the client to need scrollbars. | |
| 375 // 3. Avoid introducing blurriness with non-integer up-scaling factors. | |
| 376 // 4. Avoid having huge "letterboxes" around the desktop, if it's really | |
| 377 // small. | |
| 378 // 5. Compensate for mismatched DPIs, so that the behaviour of features like | |
| 379 // shrink-to-fit matches their "natural" rather than their pixel size. | |
| 380 // e.g. with shrink-to-fit active a 1024x768 low-DPI host on a 640x480 | |
| 381 // high-DPI client will be up-scaled to 1280x960, rather than displayed | |
| 382 // at 1:1 host:physical client pixels. | |
| 383 // | |
| 384 // To determine the ideal size we follow a four-stage process: | |
| 385 // 1. Determine the "natural" size at which to display the desktop. | |
| 386 // a. Initially assume 1:1 mapping of desktop to client device pixels. | |
| 387 // b. If host DPI is less than the client's then up-scale accordingly. | |
| 388 // c. If desktopScale is configured for the host then allow that to | |
| 389 // reduce the amount of up-scaling from (b). e.g. if the client:host | |
| 390 // DPIs are 2:1 then a desktopScale of 1.5 would reduce the up-scale | |
| 391 // to 4:3, while a desktopScale of 3.0 would result in no up-scaling. | |
| 392 // 2. If the natural size of the desktop is smaller than the client device | |
| 393 // then apply up-scaling by an integer scale factor to avoid excessive | |
| 394 // letterboxing. | |
| 395 // 3. If shrink-to-fit is configured then: | |
| 396 // a. If the natural size exceeds the client size then apply down-scaling | |
| 397 // by an arbitrary scale factor. | |
| 398 // b. If we're in full-screen mode and the client & host aspect-ratios | |
| 399 // are radically different (e.g. the host is actually multi-monitor) | |
| 400 // then shrink-to-fit to the shorter dimension, rather than leaving | |
| 401 // huge letterboxes; the user can then bump-scroll around the desktop. | |
| 402 // 4. If the overall scale factor is fractionally over an integer factor | |
| 403 // then reduce it to that integer factor, to avoid blurring. | |
| 404 | |
| 405 // All calculations are performed in device pixels. | |
| 406 var clientWidth = clientSizeDips.width * clientPixelRatio; | |
| 407 var clientHeight = clientSizeDips.height * clientPixelRatio; | |
| 408 | |
| 409 // 1. Determine a "natural" size at which to display the desktop. | |
| 410 var scale = 1.0; | |
| 411 | |
| 412 // Determine the effective host device pixel ratio. | |
| 413 // Note that we round up or down to the closest integer pixel ratio. | |
| 414 var hostPixelRatioX = Math.round(desktopDpi.x / 96); | |
| 415 var hostPixelRatioY = Math.round(desktopDpi.y / 96); | |
| 416 var hostPixelRatio = Math.min(hostPixelRatioX, hostPixelRatioY); | |
| 417 | |
| 418 // Allow up-scaling to account for DPI. | |
| 419 scale = Math.max(scale, clientPixelRatio / hostPixelRatio); | |
| 420 | |
| 421 // Allow some or all of the up-scaling to be cancelled by the desktopScale. | |
| 422 if (desktopScale > 1.0) { | |
| 423 scale = Math.max(1.0, scale / desktopScale); | |
| 424 } | |
| 425 | |
| 426 // 2. If the host is still much smaller than the client, then up-scale to | |
| 427 // avoid wasting space, but only by an integer factor, to avoid blurring. | |
| 428 if (desktopSize.width * scale <= clientWidth && | |
| 429 desktopSize.height * scale <= clientHeight) { | |
| 430 var scaleX = Math.floor(clientWidth / desktopSize.width); | |
| 431 var scaleY = Math.floor(clientHeight / desktopSize.height); | |
| 432 scale = Math.min(scaleX, scaleY); | |
| 433 base.debug.assert(scale >= 1.0); | |
| 434 } | |
| 435 | |
| 436 // 3. Apply shrink-to-fit, if configured. | |
| 437 if (shrinkToFit) { | |
| 438 var scaleFitWidth = Math.min(scale, clientWidth / desktopSize.width); | |
| 439 var scaleFitHeight = Math.min(scale, clientHeight / desktopSize.height); | |
| 440 scale = Math.min(scaleFitHeight, scaleFitWidth); | |
| 441 | |
| 442 // If we're running full-screen then try to handle common side-by-side | |
| 443 // multi-monitor combinations more intelligently. | |
| 444 if (isFullscreen) { | |
| 445 // If the host has two monitors each the same size as the client then | |
| 446 // scale-to-fit will have the desktop occupy only 50% of the client area, | |
| 447 // in which case it would be preferable to down-scale less and let the | |
| 448 // user bump-scroll around ("scale-and-pan"). | |
| 449 // Triggering scale-and-pan if less than 65% of the client area would be | |
| 450 // used adds enough fuzz to cope with e.g. 1280x800 client connecting to | |
| 451 // a (2x1280)x1024 host nicely. | |
| 452 // Note that we don't need to account for scrollbars while fullscreen. | |
| 453 if (scale <= scaleFitHeight * 0.65) { | |
| 454 scale = scaleFitHeight; | |
| 455 } | |
| 456 if (scale <= scaleFitWidth * 0.65) { | |
| 457 scale = scaleFitWidth; | |
| 458 } | |
| 459 } | |
| 460 } | |
| 461 | |
| 462 // 4. Avoid blurring for close-to-integer up-scaling factors. | |
| 463 if (scale > 1.0) { | |
| 464 var scaleBlurriness = scale / Math.floor(scale); | |
| 465 if (scaleBlurriness < 1.1) { | |
| 466 scale = Math.floor(scale); | |
| 467 } | |
| 468 } | |
| 469 | |
| 470 // Return the necessary plugin dimensions in DIPs. | |
| 471 scale = scale / clientPixelRatio; | |
| 472 var pluginWidth = Math.round(desktopSize.width * scale); | |
| 473 var pluginHeight = Math.round(desktopSize.height * scale); | |
| 474 return { width: pluginWidth, height: pluginHeight }; | |
| 475 }; | |
| 476 | |
| 477 /** @private */ | 344 /** @private */ |
| 478 remoting.DesktopViewport.prototype.resetScroll_ = function() { | 345 remoting.DesktopViewport.prototype.resetScroll_ = function() { |
| 479 this.pluginContainer_.style.marginTop = '0px'; | 346 this.pluginContainer_.style.marginTop = '0px'; |
| 480 this.pluginContainer_.style.marginLeft = '0px'; | 347 this.pluginContainer_.style.marginLeft = '0px'; |
| 481 }; | 348 }; |
| 482 | 349 |
| 483 /** | 350 /** |
| 484 * Sets and stores the scale factor to apply to host sizing requests. | 351 * Sets and stores the scale factor to apply to host sizing requests. |
| 485 * The desktopScale applies to the dimensions reported to the host, not | 352 * The desktopScale applies to the dimensions reported to the host, not |
| 486 * to the client DPI reported to it. | 353 * to the client DPI reported to it. |
| 487 * | 354 * |
| 488 * @param {number} desktopScale Scale factor to apply. | 355 * @param {number} desktopScale Scale factor to apply. |
| 489 */ | 356 */ |
| 490 remoting.DesktopViewport.prototype.setDesktopScale = function(desktopScale) { | 357 remoting.DesktopViewport.prototype.setDesktopScale = function(desktopScale) { |
| 491 this.hostOptions_.desktopScale = desktopScale; | 358 this.hostOptions_.desktopScale = desktopScale; |
| 492 | 359 |
| 493 // onResize() will update the plugin size and scrollbars for the new | 360 // onResize() will update the plugin size and scrollbars for the new |
| 494 // scaled plugin dimensions, and send a client resolution notification. | 361 // scaled plugin dimensions, and send a client resolution notification. |
| 495 this.onResize(); | 362 this.onResize(); |
| 496 | 363 |
| 497 // Save the new desktop scale setting. | 364 // Save the new desktop scale setting. |
| 498 this.hostOptions_.save(); | 365 this.hostOptions_.save(); |
| 499 }; | 366 }; |
| 500 | 367 |
| 501 }()); | 368 }()); |
| OLD | NEW |