Chromium Code Reviews| 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 cr.exportPath('options'); | 5 cr.exportPath('options'); |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * Enumeration of display layout. These values must match the C++ values in | 8 * Enumeration of display layout. These values must match the C++ values in |
| 9 * ash::DisplayController. | 9 * ash::DisplayController. |
| 10 * @enum {number} | 10 * @enum {number} |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 66 * name: string | 66 * name: string |
| 67 * }} | 67 * }} |
| 68 */ | 68 */ |
| 69 options.ColorProfile; | 69 options.ColorProfile; |
| 70 | 70 |
| 71 /** | 71 /** |
| 72 * @typedef {{ | 72 * @typedef {{ |
| 73 * availableColorProfiles: !Array<!options.ColorProfile>, | 73 * availableColorProfiles: !Array<!options.ColorProfile>, |
| 74 * bounds: !options.DisplayBounds, | 74 * bounds: !options.DisplayBounds, |
| 75 * colorProfileId: number, | 75 * colorProfileId: number, |
| 76 * div: ?Element, | |
| 77 * id: string, | 76 * id: string, |
| 78 * isInternal: boolean, | 77 * isInternal: boolean, |
| 79 * isPrimary: boolean, | 78 * isPrimary: boolean, |
| 80 * resolutions: !Array<!options.DisplayMode>, | 79 * resolutions: !Array<!options.DisplayMode>, |
| 81 * name: string, | 80 * name: string, |
| 82 * rotation: number, | 81 * rotation: number |
| 83 * originalPosition: ?options.DisplayPosition | |
| 84 * }} | 82 * }} |
| 85 */ | 83 */ |
| 86 options.DisplayInfo; | 84 options.DisplayInfo; |
| 87 | 85 |
| 86 /** | |
| 87 * @typedef {{ | |
| 88 * bounds: !options.DisplayBounds, | |
| 89 * div: ?HTMLElement, | |
| 90 * id: string, | |
| 91 * isPrimary: boolean, | |
| 92 * name: string, | |
| 93 * originalPosition: !options.DisplayPosition | |
| 94 * }} | |
| 95 */ | |
| 96 options.DisplayLayout; | |
| 97 | |
| 88 cr.define('options', function() { | 98 cr.define('options', function() { |
| 89 var Page = cr.ui.pageManager.Page; | 99 var Page = cr.ui.pageManager.Page; |
| 90 var PageManager = cr.ui.pageManager.PageManager; | 100 var PageManager = cr.ui.pageManager.PageManager; |
| 91 | 101 |
| 92 // The scale ratio of the display rectangle to its original size. | 102 // The scale ratio of the display rectangle to its original size. |
| 93 /** @const */ var VISUAL_SCALE = 1 / 10; | 103 /** @const */ var VISUAL_SCALE = 1 / 10; |
| 94 | 104 |
| 95 // The number of pixels to share the edges between displays. | 105 // The number of pixels to share the edges between displays. |
| 96 /** @const */ var MIN_OFFSET_OVERLAP = 5; | 106 /** @const */ var MIN_OFFSET_OVERLAP = 5; |
| 97 | 107 |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 156 * @type {boolean} | 166 * @type {boolean} |
| 157 * @private | 167 * @private |
| 158 */ | 168 */ |
| 159 showUnifiedDesktopOption_: false, | 169 showUnifiedDesktopOption_: false, |
| 160 | 170 |
| 161 /** | 171 /** |
| 162 * The current secondary display layout. | 172 * The current secondary display layout. |
| 163 * @type {options.DisplayLayoutType} | 173 * @type {options.DisplayLayoutType} |
| 164 * @private | 174 * @private |
| 165 */ | 175 */ |
| 166 layout_: options.DisplayLayoutType.RIGHT, | 176 layoutType_: options.DisplayLayoutType.RIGHT, |
| 167 | 177 |
| 168 /** | 178 /** |
| 169 * The array of current output displays. It also contains the display | 179 * The array of current output displays. It also contains the display |
| 170 * rectangles currently rendered on screen. | 180 * rectangles currently rendered on screen. |
| 171 * @type {!Array<!options.DisplayInfo>} | 181 * @type {!Array<!options.DisplayInfo>} |
| 172 * @private | 182 * @private |
| 173 */ | 183 */ |
| 174 displays_: [], | 184 displays_: [], |
| 175 | 185 |
| 176 /** | 186 /** |
| 177 * The index of the currently focused display, or -1 for none. | 187 * An object containing DisplayLayout objects for each entry in |displays_|. |
| 178 * @type {number} | 188 * @type {!Object<!options.DisplayLayout>} |
|
xiyuan
2016/01/22 16:46:06
Do we need to doc the key type as well?
e.g.
@t
stevenjb
2016/01/22 18:48:44
Object keys are actually always strings (even when
xiyuan
2016/01/22 18:55:28
I see. Thanks for the clarification.
| |
| 179 * @private | 189 * @private |
| 180 */ | 190 */ |
| 181 focusedIndex_: -1, | 191 displayLayoutMap_: {}, |
| 182 | 192 |
| 183 /** | 193 /** |
| 184 * The primary display edit info. | 194 * The id of the currently focused display, or empty for none. |
| 185 * @type {?options.DisplayInfo} | 195 * @type {string} |
| 186 * @private | 196 * @private |
| 187 */ | 197 */ |
| 188 primaryDisplay_: null, | 198 focusedId_: '', |
| 189 | 199 |
| 190 /** | 200 /** |
| 191 * The secondary display edit info. | 201 * The primary display id. |
| 192 * @type {?options.DisplayInfo} | 202 * @type {string} |
| 193 * @private | 203 * @private |
| 194 */ | 204 */ |
| 195 secondaryDisplay_: null, | 205 primaryDisplayId_: '', |
| 206 | |
| 207 /** | |
| 208 * The secondary display id. | |
| 209 * @type {string} | |
| 210 * @private | |
| 211 */ | |
| 212 secondaryDisplayId_: '', | |
| 196 | 213 |
| 197 /** | 214 /** |
| 198 * Drag info. | 215 * Drag info. |
| 199 * @type {?{display: !options.DisplayInfo, | 216 * @type {?{displayId: string, |
| 200 * originalLocation: !options.DisplayPosition, | 217 * originalLocation: !options.DisplayPosition, |
| 201 * eventLocation: !options.DisplayPosition}} | 218 * eventLocation: !options.DisplayPosition}} |
| 202 * @private | 219 * @private |
| 203 */ | 220 */ |
| 204 dragging_: null, | 221 dragInfo_: null, |
| 205 | 222 |
| 206 /** | 223 /** |
| 207 * The container div element which contains all of the display rectangles. | 224 * The container div element which contains all of the display rectangles. |
| 208 * @type {?Element} | 225 * @type {?Element} |
| 209 * @private | 226 * @private |
| 210 */ | 227 */ |
| 211 displaysView_: null, | 228 displaysView_: null, |
| 212 | 229 |
| 213 /** | 230 /** |
| 214 * The scale factor of the actual display size to the drawn display | 231 * The scale factor of the actual display size to the drawn display |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 244 chrome.send('setMirroring', [this.mirroring_]); | 261 chrome.send('setMirroring', [this.mirroring_]); |
| 245 }).bind(this); | 262 }).bind(this); |
| 246 | 263 |
| 247 var container = $('display-options-displays-view-host'); | 264 var container = $('display-options-displays-view-host'); |
| 248 container.onmousemove = this.onMouseMove_.bind(this); | 265 container.onmousemove = this.onMouseMove_.bind(this); |
| 249 window.addEventListener('mouseup', this.endDragging_.bind(this), true); | 266 window.addEventListener('mouseup', this.endDragging_.bind(this), true); |
| 250 container.ontouchmove = this.onTouchMove_.bind(this); | 267 container.ontouchmove = this.onTouchMove_.bind(this); |
| 251 container.ontouchend = this.endDragging_.bind(this); | 268 container.ontouchend = this.endDragging_.bind(this); |
| 252 | 269 |
| 253 $('display-options-set-primary').onclick = (function() { | 270 $('display-options-set-primary').onclick = (function() { |
| 254 chrome.send('setPrimary', [this.displays_[this.focusedIndex_].id]); | 271 chrome.send('setPrimary', [this.focusedId_]); |
| 255 }).bind(this); | 272 }).bind(this); |
| 256 $('display-options-resolution-selection').onchange = (function(ev) { | 273 $('display-options-resolution-selection').onchange = (function(ev) { |
| 257 var display = this.displays_[this.focusedIndex_]; | 274 var display = this.getDisplayInfoFromId(this.focusedId_); |
| 258 var resolution = display.resolutions[ev.target.value]; | 275 var resolution = display.resolutions[ev.target.value]; |
| 259 chrome.send('setDisplayMode', [display.id, resolution]); | 276 chrome.send('setDisplayMode', [this.focusedId_, resolution]); |
| 260 }).bind(this); | 277 }).bind(this); |
| 261 $('display-options-orientation-selection').onchange = (function(ev) { | 278 $('display-options-orientation-selection').onchange = (function(ev) { |
| 262 var displayIndex = | |
| 263 (this.focusedIndex_ == -1) ? 0 : this.focusedIndex_; | |
| 264 var rotation = parseInt(ev.target.value, 10); | 279 var rotation = parseInt(ev.target.value, 10); |
| 265 chrome.send('setRotation', [this.displays_[displayIndex].id, rotation]); | 280 chrome.send('setRotation', [this.focusedId_, rotation]); |
| 266 }).bind(this); | 281 }).bind(this); |
| 267 $('display-options-color-profile-selection').onchange = (function(ev) { | 282 $('display-options-color-profile-selection').onchange = (function(ev) { |
| 268 chrome.send('setColorProfile', [this.displays_[this.focusedIndex_].id, | 283 chrome.send('setColorProfile', [this.focusedId_, ev.target.value]); |
| 269 ev.target.value]); | |
| 270 }).bind(this); | 284 }).bind(this); |
| 271 $('selected-display-start-calibrating-overscan').onclick = (function() { | 285 $('selected-display-start-calibrating-overscan').onclick = (function() { |
| 272 // Passes the target display ID. Do not specify it through URL hash, | 286 // Passes the target display ID. Do not specify it through URL hash, |
| 273 // we do not care back/forward. | 287 // we do not care back/forward. |
| 274 var displayOverscan = options.DisplayOverscan.getInstance(); | 288 var displayOverscan = options.DisplayOverscan.getInstance(); |
| 275 displayOverscan.setDisplayId(this.displays_[this.focusedIndex_].id); | 289 displayOverscan.setDisplayId(this.focusedId_); |
| 276 PageManager.showPageByName('displayOverscan'); | 290 PageManager.showPageByName('displayOverscan'); |
| 277 chrome.send('coreOptionsUserMetricsAction', | 291 chrome.send('coreOptionsUserMetricsAction', |
| 278 ['Options_DisplaySetOverscan']); | 292 ['Options_DisplaySetOverscan']); |
| 279 }).bind(this); | 293 }).bind(this); |
| 280 | 294 |
| 281 $('display-options-done').onclick = function() { | 295 $('display-options-done').onclick = function() { |
| 282 PageManager.closeOverlay(); | 296 PageManager.closeOverlay(); |
| 283 }; | 297 }; |
| 284 | 298 |
| 285 $('display-options-toggle-unified-desktop').onclick = (function() { | 299 $('display-options-toggle-unified-desktop').onclick = (function() { |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 387 return false; | 401 return false; |
| 388 | 402 |
| 389 e.preventDefault(); | 403 e.preventDefault(); |
| 390 var touch = e.touches[0]; | 404 var touch = e.touches[0]; |
| 391 this.lastTouchLocation_ = {x: touch.pageX, y: touch.pageY}; | 405 this.lastTouchLocation_ = {x: touch.pageX, y: touch.pageY}; |
| 392 var target = assertInstanceof(e.target, HTMLElement); | 406 var target = assertInstanceof(e.target, HTMLElement); |
| 393 return this.startDragging_(target, this.lastTouchLocation_); | 407 return this.startDragging_(target, this.lastTouchLocation_); |
| 394 }, | 408 }, |
| 395 | 409 |
| 396 /** | 410 /** |
| 411 * @param {string} id | |
| 412 * @return {options.DisplayInfo} | |
| 413 */ | |
| 414 getDisplayInfoFromId(id) { | |
| 415 return this.displays_.find(function(display) { | |
| 416 return display.id == id; | |
| 417 }); | |
| 418 }, | |
| 419 | |
| 420 /** | |
| 397 * Collects the current data and sends it to Chrome. | 421 * Collects the current data and sends it to Chrome. |
| 398 * @private | 422 * @private |
| 399 */ | 423 */ |
| 400 applyResult_: function() { | 424 sendDragResult_: function() { |
| 401 // Offset is calculated from top or left edge. | 425 // Offset is calculated from top or left edge. |
| 402 var primary = this.primaryDisplay_; | 426 var primary = this.displayLayoutMap_[this.primaryDisplayId_]; |
| 403 var secondary = this.secondaryDisplay_; | 427 var secondary = this.displayLayoutMap_[this.secondaryDisplayId_]; |
| 404 var offset; | 428 var offset; |
| 405 if (this.layout_ == options.DisplayLayoutType.LEFT || | 429 if (this.layoutType_ == options.DisplayLayoutType.LEFT || |
| 406 this.layout_ == options.DisplayLayoutType.RIGHT) { | 430 this.layoutType_ == options.DisplayLayoutType.RIGHT) { |
| 407 offset = secondary.div.offsetTop - primary.div.offsetTop; | 431 offset = secondary.div.offsetTop - primary.div.offsetTop; |
| 408 } else { | 432 } else { |
| 409 offset = secondary.div.offsetLeft - primary.div.offsetLeft; | 433 offset = secondary.div.offsetLeft - primary.div.offsetLeft; |
| 410 } | 434 } |
| 411 offset = Math.floor(offset / this.visualScale_); | 435 offset = Math.floor(offset / this.visualScale_); |
| 412 chrome.send('setDisplayLayout', [secondary.id, this.layout_, offset]); | 436 chrome.send( |
| 437 'setDisplayLayout', [secondary.id, this.layoutType_, offset]); | |
| 413 }, | 438 }, |
| 414 | 439 |
| 415 /** | 440 /** |
| 416 * Snaps the region [point, width] to [basePoint, baseWidth] if | 441 * Snaps the region [point, width] to [basePoint, baseWidth] if |
| 417 * the [point, width] is close enough to the base's edge. | 442 * the [point, width] is close enough to the base's edge. |
| 418 * @param {number} point The starting point of the region. | 443 * @param {number} point The starting point of the region. |
| 419 * @param {number} width The width of the region. | 444 * @param {number} width The width of the region. |
| 420 * @param {number} basePoint The starting point of the base region. | 445 * @param {number} basePoint The starting point of the base region. |
| 421 * @param {number} baseWidth The width of the base region. | 446 * @param {number} baseWidth The width of the base region. |
| 422 * @return {number} The moved point. Returns point itself if it doesn't | 447 * @return {number} The moved point. Returns point itself if it doesn't |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 440 }, | 465 }, |
| 441 | 466 |
| 442 /** | 467 /** |
| 443 * Processes the actual dragging of display rectangle. | 468 * Processes the actual dragging of display rectangle. |
| 444 * @param {Event} e The event which triggers this drag. | 469 * @param {Event} e The event which triggers this drag. |
| 445 * @param {options.DisplayPosition} eventLocation The location where the | 470 * @param {options.DisplayPosition} eventLocation The location where the |
| 446 * event happens. | 471 * event happens. |
| 447 * @private | 472 * @private |
| 448 */ | 473 */ |
| 449 processDragging_: function(e, eventLocation) { | 474 processDragging_: function(e, eventLocation) { |
| 450 if (!this.dragging_) | 475 if (!this.dragInfo_) |
| 451 return true; | |
| 452 | |
| 453 var index = -1; | |
| 454 for (var i = 0; i < this.displays_.length; i++) { | |
| 455 if (this.displays_[i] == this.dragging_.display) { | |
| 456 index = i; | |
| 457 break; | |
| 458 } | |
| 459 } | |
| 460 if (index < 0) | |
| 461 return true; | 476 return true; |
| 462 | 477 |
| 463 e.preventDefault(); | 478 e.preventDefault(); |
| 464 | 479 |
| 465 // Note that current code of moving display-rectangles doesn't work | 480 // Note that current code of moving display-rectangles doesn't work |
| 466 // if there are >=3 displays. This is our assumption for M21. | 481 // if there are >=3 displays. This is our assumption for M21. |
| 467 // TODO(mukai): Fix the code to allow >=3 displays. | 482 // TODO(mukai): Fix the code to allow >=3 displays. |
| 468 var newPosition = { | 483 var dragInfo = this.dragInfo_; |
| 469 x: this.dragging_.originalLocation.x + | 484 var dragLayout = this.displayLayoutMap_[dragInfo.displayId]; |
| 470 (eventLocation.x - this.dragging_.eventLocation.x), | 485 /** @type {options.DisplayPosition} */ var newPosition = { |
| 471 y: this.dragging_.originalLocation.y + | 486 x: dragInfo.originalLocation.x + |
| 472 (eventLocation.y - this.dragging_.eventLocation.y) | 487 (eventLocation.x - dragInfo.eventLocation.x), |
| 488 y: dragInfo.originalLocation.y + | |
| 489 (eventLocation.y - dragInfo.eventLocation.y) | |
| 473 }; | 490 }; |
| 474 | 491 |
| 475 var baseDiv = this.dragging_.display.isPrimary ? | 492 var baseDisplayId = dragLayout.isPrimary ? this.secondaryDisplayId_ : |
| 476 this.secondaryDisplay_.div : this.primaryDisplay_.div; | 493 this.primaryDisplayId_; |
| 477 var draggingDiv = this.dragging_.display.div; | 494 var baseDiv = this.displayLayoutMap_[baseDisplayId].div; |
| 495 var draggingDiv = dragLayout.div; | |
| 478 | 496 |
| 479 newPosition.x = this.snapToEdge_(newPosition.x, draggingDiv.offsetWidth, | 497 newPosition.x = this.snapToEdge_(newPosition.x, draggingDiv.offsetWidth, |
| 480 baseDiv.offsetLeft, baseDiv.offsetWidth); | 498 baseDiv.offsetLeft, baseDiv.offsetWidth); |
| 481 newPosition.y = this.snapToEdge_(newPosition.y, draggingDiv.offsetHeight, | 499 newPosition.y = this.snapToEdge_(newPosition.y, draggingDiv.offsetHeight, |
| 482 baseDiv.offsetTop, baseDiv.offsetHeight); | 500 baseDiv.offsetTop, baseDiv.offsetHeight); |
| 483 | 501 |
| 484 var newCenter = /** {!options.DisplayPosition} */({ | 502 /** @type {!options.DisplayPosition} */ var newCenter = { |
| 485 x: newPosition.x + draggingDiv.offsetWidth / 2, | 503 x: newPosition.x + draggingDiv.offsetWidth / 2, |
| 486 y: newPosition.y + draggingDiv.offsetHeight / 2 | 504 y: newPosition.y + draggingDiv.offsetHeight / 2 |
| 487 }); | 505 }; |
| 488 | 506 |
| 489 var baseBounds = /** {!options.DisplayBounds} */({ | 507 /** @type {!options.DisplayBounds} */ var baseBounds = { |
| 490 left: baseDiv.offsetLeft, | 508 left: baseDiv.offsetLeft, |
| 491 top: baseDiv.offsetTop, | 509 top: baseDiv.offsetTop, |
| 492 width: baseDiv.offsetWidth, | 510 width: baseDiv.offsetWidth, |
| 493 height: baseDiv.offsetHeight | 511 height: baseDiv.offsetHeight |
| 494 }); | 512 }; |
| 513 | |
| 514 var isPrimary = dragLayout.isPrimary; | |
| 515 var layoutType = this.layoutType_; | |
| 516 | |
| 495 switch (getPositionToRectangle(baseBounds, newCenter)) { | 517 switch (getPositionToRectangle(baseBounds, newCenter)) { |
| 496 case options.DisplayLayoutType.RIGHT: | 518 case options.DisplayLayoutType.RIGHT: |
| 497 this.layout_ = this.dragging_.display.isPrimary ? | 519 layoutType = isPrimary ? options.DisplayLayoutType.LEFT : |
| 498 options.DisplayLayoutType.LEFT : | 520 options.DisplayLayoutType.RIGHT; |
| 499 options.DisplayLayoutType.RIGHT; | |
| 500 break; | 521 break; |
| 501 case options.DisplayLayoutType.LEFT: | 522 case options.DisplayLayoutType.LEFT: |
| 502 this.layout_ = this.dragging_.display.isPrimary ? | 523 layoutType = isPrimary ? options.DisplayLayoutType.RIGHT : |
| 503 options.DisplayLayoutType.RIGHT : | 524 options.DisplayLayoutType.LEFT; |
| 504 options.DisplayLayoutType.LEFT; | |
| 505 break; | 525 break; |
| 506 case options.DisplayLayoutType.TOP: | 526 case options.DisplayLayoutType.TOP: |
| 507 this.layout_ = this.dragging_.display.isPrimary ? | 527 layoutType = isPrimary ? options.DisplayLayoutType.BOTTOM : |
| 508 options.DisplayLayoutType.BOTTOM : | 528 options.DisplayLayoutType.TOP; |
| 509 options.DisplayLayoutType.TOP; | |
| 510 break; | 529 break; |
| 511 case options.DisplayLayoutType.BOTTOM: | 530 case options.DisplayLayoutType.BOTTOM: |
| 512 this.layout_ = this.dragging_.display.isPrimary ? | 531 layoutType = isPrimary ? options.DisplayLayoutType.TOP : |
| 513 options.DisplayLayoutType.TOP : | 532 options.DisplayLayoutType.BOTTOM; |
| 514 options.DisplayLayoutType.BOTTOM; | |
| 515 break; | 533 break; |
| 516 } | 534 } |
| 517 | 535 |
| 518 if (this.layout_ == options.DisplayLayoutType.LEFT || | 536 if (layoutType == options.DisplayLayoutType.LEFT || |
| 519 this.layout_ == options.DisplayLayoutType.RIGHT) { | 537 layoutType == options.DisplayLayoutType.RIGHT) { |
| 520 if (newPosition.y > baseDiv.offsetTop + baseDiv.offsetHeight) | 538 if (newPosition.y > baseDiv.offsetTop + baseDiv.offsetHeight) |
| 521 this.layout_ = this.dragging_.display.isPrimary ? | 539 layoutType = isPrimary ? options.DisplayLayoutType.TOP : |
| 522 options.DisplayLayoutType.TOP : | 540 options.DisplayLayoutType.BOTTOM; |
| 523 options.DisplayLayoutType.BOTTOM; | |
| 524 else if (newPosition.y + draggingDiv.offsetHeight < baseDiv.offsetTop) | 541 else if (newPosition.y + draggingDiv.offsetHeight < baseDiv.offsetTop) |
| 525 this.layout_ = this.dragging_.display.isPrimary ? | 542 layoutType = isPrimary ? options.DisplayLayoutType.BOTTOM : |
| 526 options.DisplayLayoutType.BOTTOM : | 543 options.DisplayLayoutType.TOP; |
| 527 options.DisplayLayoutType.TOP; | |
| 528 } else { | 544 } else { |
| 529 if (newPosition.x > baseDiv.offsetLeft + baseDiv.offsetWidth) | 545 if (newPosition.x > baseDiv.offsetLeft + baseDiv.offsetWidth) |
| 530 this.layout_ = this.dragging_.display.isPrimary ? | 546 layoutType = isPrimary ? options.DisplayLayoutType.LEFT : |
| 531 options.DisplayLayoutType.LEFT : | 547 options.DisplayLayoutType.RIGHT; |
| 532 options.DisplayLayoutType.RIGHT; | |
| 533 else if (newPosition.x + draggingDiv.offsetWidth < baseDiv.offsetLeft) | 548 else if (newPosition.x + draggingDiv.offsetWidth < baseDiv.offsetLeft) |
| 534 this.layout_ = this.dragging_.display.isPrimary ? | 549 layoutType = isPrimary ? options.DisplayLayoutType.RIGHT : |
| 535 options.DisplayLayoutType.RIGHT : | 550 options.DisplayLayoutType.LEFT; |
| 536 options.DisplayLayoutType.LEFT; | |
| 537 } | 551 } |
| 538 | 552 |
| 553 this.layoutType_ = layoutType; | |
| 554 | |
| 539 var layoutToBase; | 555 var layoutToBase; |
| 540 if (!this.dragging_.display.isPrimary) { | 556 if (!isPrimary) { |
| 541 layoutToBase = this.layout_; | 557 layoutToBase = layoutType; |
| 542 } else { | 558 } else { |
| 543 switch (this.layout_) { | 559 switch (layoutType) { |
| 544 case options.DisplayLayoutType.RIGHT: | 560 case options.DisplayLayoutType.RIGHT: |
| 545 layoutToBase = options.DisplayLayoutType.LEFT; | 561 layoutToBase = options.DisplayLayoutType.LEFT; |
| 546 break; | 562 break; |
| 547 case options.DisplayLayoutType.LEFT: | 563 case options.DisplayLayoutType.LEFT: |
| 548 layoutToBase = options.DisplayLayoutType.RIGHT; | 564 layoutToBase = options.DisplayLayoutType.RIGHT; |
| 549 break; | 565 break; |
| 550 case options.DisplayLayoutType.TOP: | 566 case options.DisplayLayoutType.TOP: |
| 551 layoutToBase = options.DisplayLayoutType.BOTTOM; | 567 layoutToBase = options.DisplayLayoutType.BOTTOM; |
| 552 break; | 568 break; |
| 553 case options.DisplayLayoutType.BOTTOM: | 569 case options.DisplayLayoutType.BOTTOM: |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 582 return false; | 598 return false; |
| 583 }, | 599 }, |
| 584 | 600 |
| 585 /** | 601 /** |
| 586 * Start dragging of a display rectangle. | 602 * Start dragging of a display rectangle. |
| 587 * @param {!HTMLElement} target The event target. | 603 * @param {!HTMLElement} target The event target. |
| 588 * @param {!options.DisplayPosition} eventLocation The event location. | 604 * @param {!options.DisplayPosition} eventLocation The event location. |
| 589 * @private | 605 * @private |
| 590 */ | 606 */ |
| 591 startDragging_: function(target, eventLocation) { | 607 startDragging_: function(target, eventLocation) { |
| 592 var oldFocusedIndex = this.focusedIndex_; | 608 var oldFocusedId = this.focusedId_; |
| 609 var newFocusedId; | |
| 593 var willUpdateDisplayDescription = false; | 610 var willUpdateDisplayDescription = false; |
| 594 this.focusedIndex_ = -1; | |
| 595 for (var i = 0; i < this.displays_.length; i++) { | 611 for (var i = 0; i < this.displays_.length; i++) { |
| 596 var display = this.displays_[i]; | 612 var displayLayout = this.displayLayoutMap_[this.displays_[i].id]; |
| 597 if (display.div == target || | 613 if (displayLayout.div == target || |
| 598 (target.offsetParent && target.offsetParent == display.div)) { | 614 (target.offsetParent && target.offsetParent == displayLayout.div)) { |
| 599 this.focusedIndex_ = i; | 615 newFocusedId = displayLayout.id; |
| 600 if (oldFocusedIndex !== null && oldFocusedIndex != i) | |
| 601 willUpdateDisplayDescription = true; | |
| 602 break; | 616 break; |
| 603 } | 617 } |
| 604 } | 618 } |
| 619 if (!newFocusedId) | |
| 620 return false; | |
| 621 | |
| 622 this.focusedId_ = newFocusedId; | |
| 623 willUpdateDisplayDescription = newFocusedId != oldFocusedId; | |
| 605 | 624 |
| 606 for (var i = 0; i < this.displays_.length; i++) { | 625 for (var i = 0; i < this.displays_.length; i++) { |
| 607 var display = this.displays_[i]; | 626 var displayLayout = this.displayLayoutMap_[this.displays_[i].id]; |
| 608 display.div.className = 'displays-display'; | 627 displayLayout.div.className = 'displays-display'; |
| 609 if (i != this.focusedIndex_) | 628 if (displayLayout.id != this.focusedId_) |
| 610 continue; | 629 continue; |
| 611 | 630 |
| 612 display.div.classList.add('displays-focused'); | 631 displayLayout.div.classList.add('displays-focused'); |
| 613 if (this.displays_.length > 1) { | 632 if (this.displays_.length > 1) { |
| 614 this.dragging_ = { | 633 this.dragInfo_ = { |
| 615 display: display, | 634 displayId: displayLayout.id, |
| 616 originalLocation: { | 635 originalLocation: { |
| 617 x: display.div.offsetLeft, y: display.div.offsetTop | 636 x: displayLayout.div.offsetLeft, |
| 637 y: displayLayout.div.offsetTop | |
| 618 }, | 638 }, |
| 619 eventLocation: eventLocation | 639 eventLocation: {x: eventLocation.x, y: eventLocation.y} |
| 620 }; | 640 }; |
| 621 } | 641 } |
| 622 } | 642 } |
| 623 | 643 |
| 624 if (willUpdateDisplayDescription) | 644 if (willUpdateDisplayDescription) |
| 625 this.updateSelectedDisplayDescription_(); | 645 this.updateSelectedDisplayDescription_(); |
| 626 return false; | 646 return false; |
| 627 }, | 647 }, |
| 628 | 648 |
| 629 /** | 649 /** |
| 630 * finish the current dragging of displays. | 650 * finish the current dragging of displays. |
| 631 * @param {Event} e The event which triggers this. | 651 * @param {Event} e The event which triggers this. |
| 632 * @private | 652 * @private |
| 633 */ | 653 */ |
| 634 endDragging_: function(e) { | 654 endDragging_: function(e) { |
| 635 this.lastTouchLocation_ = null; | 655 this.lastTouchLocation_ = null; |
| 636 if (this.dragging_) { | 656 if (!this.dragInfo_) |
| 637 // Make sure the dragging location is connected. | 657 return false; |
| 638 var baseDiv = this.dragging_.display.isPrimary ? | 658 |
| 639 this.secondaryDisplay_.div : | 659 // Make sure the dragging location is connected. |
| 640 this.primaryDisplay_.div; | 660 var dragLayout = this.displayLayoutMap_[this.dragInfo_.displayId]; |
| 641 var draggingDiv = this.dragging_.display.div; | 661 var baseDisplayId = dragLayout.isPrimary ? this.secondaryDisplayId_ : |
| 642 if (this.layout_ == options.DisplayLayoutType.LEFT || | 662 this.primaryDisplayId_; |
| 643 this.layout_ == options.DisplayLayoutType.RIGHT) { | 663 var baseDiv = this.displayLayoutMap_[baseDisplayId].div; |
| 644 var top = Math.max( | 664 var draggingDiv = dragLayout.div; |
| 645 draggingDiv.offsetTop, baseDiv.offsetTop - | 665 if (this.layoutType_ == options.DisplayLayoutType.LEFT || |
| 646 draggingDiv.offsetHeight + MIN_OFFSET_OVERLAP); | 666 this.layoutType_ == options.DisplayLayoutType.RIGHT) { |
| 647 top = Math.min( | 667 var top = Math.max( |
| 648 top, | 668 draggingDiv.offsetTop, |
| 649 baseDiv.offsetTop + baseDiv.offsetHeight - MIN_OFFSET_OVERLAP); | 669 baseDiv.offsetTop - draggingDiv.offsetHeight + MIN_OFFSET_OVERLAP); |
| 650 draggingDiv.style.top = top + 'px'; | 670 top = Math.min( |
| 651 } else { | 671 top, baseDiv.offsetTop + baseDiv.offsetHeight - MIN_OFFSET_OVERLAP); |
| 652 var left = Math.max( | 672 draggingDiv.style.top = top + 'px'; |
| 653 draggingDiv.offsetLeft, baseDiv.offsetLeft - | 673 } else { |
| 654 draggingDiv.offsetWidth + MIN_OFFSET_OVERLAP); | 674 var left = Math.max( |
| 655 left = Math.min( | 675 draggingDiv.offsetLeft, |
| 656 left, | 676 baseDiv.offsetLeft - draggingDiv.offsetWidth + MIN_OFFSET_OVERLAP); |
| 657 baseDiv.offsetLeft + baseDiv.offsetWidth - MIN_OFFSET_OVERLAP); | 677 left = Math.min( |
| 658 draggingDiv.style.left = left + 'px'; | 678 left, |
| 659 } | 679 baseDiv.offsetLeft + baseDiv.offsetWidth - MIN_OFFSET_OVERLAP); |
| 660 var originalPosition = this.dragging_.display.originalPosition; | 680 draggingDiv.style.left = left + 'px'; |
| 661 if (originalPosition.x != draggingDiv.offsetLeft || | |
| 662 originalPosition.y != draggingDiv.offsetTop) | |
| 663 this.applyResult_(); | |
| 664 this.dragging_ = null; | |
| 665 } | 681 } |
| 682 if (dragLayout.originalPosition.x != draggingDiv.offsetLeft || | |
| 683 dragLayout.originalPosition.y != draggingDiv.offsetTop) { | |
| 684 this.sendDragResult_(); | |
| 685 } | |
| 686 | |
| 687 this.dragInfo_ = null; | |
| 688 | |
| 666 return false; | 689 return false; |
| 667 }, | 690 }, |
| 668 | 691 |
| 669 /** | 692 /** |
| 670 * Updates the description of selected display section for mirroring mode. | 693 * Updates the description of selected display section for mirroring mode. |
| 671 * @private | 694 * @private |
| 672 */ | 695 */ |
| 673 updateSelectedDisplaySectionMirroring_: function() { | 696 updateSelectedDisplaySectionMirroring_: function() { |
| 674 $('display-configuration-arrow').hidden = true; | 697 $('display-configuration-arrow').hidden = true; |
| 675 $('display-options-set-primary').disabled = true; | 698 $('display-options-set-primary').disabled = true; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 708 resolution.disabled = true; | 731 resolution.disabled = true; |
| 709 }, | 732 }, |
| 710 | 733 |
| 711 /** | 734 /** |
| 712 * Updates the description of selected display section for the selected | 735 * Updates the description of selected display section for the selected |
| 713 * display. | 736 * display. |
| 714 * @param {options.DisplayInfo} display The selected display object. | 737 * @param {options.DisplayInfo} display The selected display object. |
| 715 * @private | 738 * @private |
| 716 */ | 739 */ |
| 717 updateSelectedDisplaySectionForDisplay_: function(display) { | 740 updateSelectedDisplaySectionForDisplay_: function(display) { |
| 741 var displayLayout = this.displayLayoutMap_[display.id]; | |
| 718 var arrow = $('display-configuration-arrow'); | 742 var arrow = $('display-configuration-arrow'); |
| 719 arrow.hidden = false; | 743 arrow.hidden = false; |
| 720 // Adding 1 px to the position to fit the border line and the border in | 744 // Adding 1 px to the position to fit the border line and the border in |
| 721 // arrow precisely. | 745 // arrow precisely. |
| 722 arrow.style.top = $('display-configurations').offsetTop - | 746 arrow.style.top = $('display-configurations').offsetTop - |
| 723 arrow.offsetHeight / 2 + 'px'; | 747 arrow.offsetHeight / 2 + 'px'; |
| 724 arrow.style.left = display.div.offsetLeft + | 748 arrow.style.left = displayLayout.div.offsetLeft + |
| 725 display.div.offsetWidth / 2 - arrow.offsetWidth / 2 + 'px'; | 749 displayLayout.div.offsetWidth / 2 - arrow.offsetWidth / 2 + 'px'; |
| 726 | 750 |
| 727 $('display-options-set-primary').disabled = display.isPrimary; | 751 $('display-options-set-primary').disabled = display.isPrimary; |
| 728 $('display-options-select-mirroring').disabled = | 752 $('display-options-select-mirroring').disabled = |
| 729 (this.displays_.length <= 1 && !this.unifiedDesktopEnabled_); | 753 (this.displays_.length <= 1 && !this.unifiedDesktopEnabled_); |
| 730 $('selected-display-start-calibrating-overscan').disabled = | 754 $('selected-display-start-calibrating-overscan').disabled = |
| 731 display.isInternal; | 755 display.isInternal; |
| 732 | 756 |
| 733 var orientation = $('display-options-orientation-selection'); | 757 var orientation = $('display-options-orientation-selection'); |
| 734 orientation.disabled = this.unifiedDesktopEnabled_; | 758 orientation.disabled = this.unifiedDesktopEnabled_; |
| 735 | 759 |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 797 updateSelectedDisplayDescription_: function() { | 821 updateSelectedDisplayDescription_: function() { |
| 798 var resolution = $('display-options-resolution-selection'); | 822 var resolution = $('display-options-resolution-selection'); |
| 799 resolution.textContent = ''; | 823 resolution.textContent = ''; |
| 800 var orientation = $('display-options-orientation-selection'); | 824 var orientation = $('display-options-orientation-selection'); |
| 801 var orientationOptions = orientation.getElementsByTagName('option'); | 825 var orientationOptions = orientation.getElementsByTagName('option'); |
| 802 for (var i = 0; i < orientationOptions.length; i++) | 826 for (var i = 0; i < orientationOptions.length; i++) |
| 803 orientationOptions[i].selected = false; | 827 orientationOptions[i].selected = false; |
| 804 | 828 |
| 805 if (this.mirroring_) { | 829 if (this.mirroring_) { |
| 806 this.updateSelectedDisplaySectionMirroring_(); | 830 this.updateSelectedDisplaySectionMirroring_(); |
| 807 } else if (this.focusedIndex_ == -1 || | 831 } else if (this.focusedId_ == '') { |
| 808 this.displays_[this.focusedIndex_] == null) { | |
| 809 this.updateSelectedDisplaySectionNoSelected_(); | 832 this.updateSelectedDisplaySectionNoSelected_(); |
| 810 } else { | 833 } else { |
| 811 this.updateSelectedDisplaySectionForDisplay_( | 834 this.updateSelectedDisplaySectionForDisplay_( |
| 812 this.displays_[this.focusedIndex_]); | 835 this.getDisplayInfoFromId(this.focusedId_)); |
| 813 } | 836 } |
| 814 }, | 837 }, |
| 815 | 838 |
| 816 /** | 839 /** |
| 817 * Clears the drawing area for display rectangles. | 840 * Clears the drawing area for display rectangles. |
| 818 * @private | 841 * @private |
| 819 */ | 842 */ |
| 820 resetDisplaysView_: function() { | 843 resetDisplaysView_: function() { |
| 821 var displaysViewHost = $('display-options-displays-view-host'); | 844 var displaysViewHost = $('display-options-displays-view-host'); |
| 822 displaysViewHost.removeChild(displaysViewHost.firstChild); | 845 displaysViewHost.removeChild(displaysViewHost.firstChild); |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 849 var totalWidth = width + numDisplays * MIRRORING_OFFSET_PIXELS; | 872 var totalWidth = width + numDisplays * MIRRORING_OFFSET_PIXELS; |
| 850 var totalHeight = height + numDisplays * MIRRORING_OFFSET_PIXELS; | 873 var totalHeight = height + numDisplays * MIRRORING_OFFSET_PIXELS; |
| 851 | 874 |
| 852 this.displaysView_.style.height = totalHeight + 'px'; | 875 this.displaysView_.style.height = totalHeight + 'px'; |
| 853 | 876 |
| 854 // The displays should be centered. | 877 // The displays should be centered. |
| 855 var offsetX = | 878 var offsetX = |
| 856 $('display-options-displays-view').offsetWidth / 2 - totalWidth / 2; | 879 $('display-options-displays-view').offsetWidth / 2 - totalWidth / 2; |
| 857 | 880 |
| 858 for (var i = 0; i < numDisplays; i++) { | 881 for (var i = 0; i < numDisplays; i++) { |
| 859 var div = document.createElement('div'); | 882 var div = /** @type {HTMLElement} */ (document.createElement('div')); |
| 860 div.className = 'displays-display'; | 883 div.className = 'displays-display'; |
| 861 div.style.top = i * MIRRORING_OFFSET_PIXELS + 'px'; | 884 div.style.top = i * MIRRORING_OFFSET_PIXELS + 'px'; |
| 862 div.style.left = i * MIRRORING_OFFSET_PIXELS + offsetX + 'px'; | 885 div.style.left = i * MIRRORING_OFFSET_PIXELS + offsetX + 'px'; |
| 863 div.style.width = width + 'px'; | 886 div.style.width = width + 'px'; |
| 864 div.style.height = height + 'px'; | 887 div.style.height = height + 'px'; |
| 865 div.style.zIndex = i; | 888 div.style.zIndex = i; |
| 866 // set 'display-mirrored' class for the background display rectangles. | 889 // set 'display-mirrored' class for the background display rectangles. |
| 867 if (i != numDisplays - 1) | 890 if (i != numDisplays - 1) |
| 868 div.classList.add('display-mirrored'); | 891 div.classList.add('display-mirrored'); |
| 869 this.displaysView_.appendChild(div); | 892 this.displaysView_.appendChild(div); |
| 893 | |
| 894 // Not currently used but set for consistency / debugging. | |
| 895 this.displayLayoutMap_[this.displays_[i].id].div = div; | |
| 870 } | 896 } |
| 871 }, | 897 }, |
| 872 | 898 |
| 873 /** | 899 /** |
| 874 * Creates a div element representing the specified display. | 900 * Creates a DisplayLayout object representing the display. |
| 875 * @param {!options.DisplayInfo} display The display object. | 901 * @param {!options.DisplayInfo} display |
| 876 * @param {boolean} focused True if it's focused. | 902 * @return {!options.DisplayLayout} |
| 877 * @private | 903 * @private |
| 878 */ | 904 */ |
| 879 createDisplayRectangle_: function(display, focused) { | 905 createDisplayLayout_: function(display) { |
| 880 var div = document.createElement('div'); | 906 /** @type {options.DisplayLayout} */ var displayLayout = { |
| 881 display.div = div; | 907 bounds: display.bounds, |
| 908 div: null, | |
| 909 id: display.id, | |
| 910 isPrimary: display.isPrimary, | |
| 911 name: display.name, | |
| 912 originalPosition: {x: 0, y: 0} | |
| 913 }; | |
| 914 return displayLayout; | |
| 915 }, | |
| 916 | |
| 917 /** | |
| 918 * Creates a div element representing the specified display. | |
| 919 * @param {!options.DisplayLayout} displayLayout | |
| 920 * @param {options.DisplayLayoutType} layoutType The layout type for the | |
| 921 * secondary display. | |
| 922 * @param {!options.DisplayPosition} offset The offset to the center of the | |
| 923 * display area. | |
| 924 * @private | |
| 925 */ | |
| 926 createDisplayLayoutDiv_: function(displayLayout, layoutType, offset) { | |
| 927 var div = /** @type {!HTMLElement} */ (document.createElement('div')); | |
| 882 div.className = 'displays-display'; | 928 div.className = 'displays-display'; |
| 883 if (focused) | 929 if (displayLayout.id == this.focusedId_) |
| 884 div.classList.add('displays-focused'); | 930 div.classList.add('displays-focused'); |
|
xiyuan
2016/01/22 16:46:07
nit: div.classList.toggle('displays-focused', disp
stevenjb
2016/01/22 18:48:44
Done.
| |
| 885 | 931 |
| 886 // div needs to be added to the DOM tree first, otherwise offsetHeight for | 932 // div needs to be added to the DOM tree first, otherwise offsetHeight for |
| 887 // nameContainer below cannot be computed. | 933 // nameContainer below cannot be computed. |
| 888 this.displaysView_.appendChild(div); | 934 this.displaysView_.appendChild(div); |
| 889 | 935 |
| 890 var nameContainer = document.createElement('div'); | 936 var nameContainer = document.createElement('div'); |
| 891 nameContainer.textContent = display.name; | 937 nameContainer.textContent = displayLayout.name; |
| 892 div.appendChild(nameContainer); | 938 div.appendChild(nameContainer); |
| 893 div.style.width = | 939 |
| 894 Math.floor(display.bounds.width * this.visualScale_) + 'px'; | 940 var bounds = displayLayout.bounds; |
| 895 var newHeight = Math.floor(display.bounds.height * this.visualScale_); | 941 div.style.width = Math.floor(bounds.width * this.visualScale_) + 'px'; |
| 942 var newHeight = Math.floor(bounds.height * this.visualScale_); | |
| 896 div.style.height = newHeight + 'px'; | 943 div.style.height = newHeight + 'px'; |
| 897 nameContainer.style.marginTop = | 944 nameContainer.style.marginTop = |
| 898 (newHeight - nameContainer.offsetHeight) / 2 + 'px'; | 945 (newHeight - nameContainer.offsetHeight) / 2 + 'px'; |
| 899 | 946 |
| 900 div.onmousedown = this.onMouseDown_.bind(this); | 947 div.onmousedown = this.onMouseDown_.bind(this); |
| 901 div.ontouchstart = this.onTouchStart_.bind(this); | 948 div.ontouchstart = this.onTouchStart_.bind(this); |
| 902 return div; | 949 |
| 950 if (displayLayout.isPrimary) { | |
| 951 div.style.left = | |
| 952 Math.floor(bounds.left * this.visualScale_) + offset.x + 'px'; | |
| 953 div.style.top = | |
| 954 Math.floor(bounds.top * this.visualScale_) + offset.y + 'px'; | |
| 955 } else { | |
| 956 // Don't trust the secondary display's x or y, because it may cause a | |
| 957 // 1px gap due to rounding, which will create a fake update on end | |
| 958 // dragging. See crbug.com/386401 | |
| 959 var primaryDiv = this.displayLayoutMap_[this.primaryDisplayId_].div; | |
| 960 switch (layoutType) { | |
| 961 case options.DisplayLayoutType.TOP: | |
| 962 div.style.left = | |
| 963 Math.floor(bounds.left * this.visualScale_) + offset.x + 'px'; | |
| 964 div.style.top = primaryDiv.offsetTop - div.offsetHeight + 'px'; | |
| 965 break; | |
| 966 case options.DisplayLayoutType.RIGHT: | |
| 967 div.style.left = | |
| 968 primaryDiv.offsetLeft + primaryDiv.offsetWidth + 'px'; | |
| 969 div.style.top = | |
| 970 Math.floor(bounds.top * this.visualScale_) + offset.y + 'px'; | |
| 971 break; | |
| 972 case options.DisplayLayoutType.BOTTOM: | |
| 973 div.style.left = | |
| 974 Math.floor(bounds.left * this.visualScale_) + offset.x + 'px'; | |
| 975 div.style.top = | |
| 976 primaryDiv.offsetTop + primaryDiv.offsetHeight + 'px'; | |
| 977 break; | |
| 978 case options.DisplayLayoutType.LEFT: | |
| 979 div.style.left = primaryDiv.offsetLeft - div.offsetWidth + 'px'; | |
| 980 div.style.top = | |
| 981 Math.floor(bounds.top * this.visualScale_) + offset.y + 'px'; | |
| 982 break; | |
| 983 } | |
| 984 } | |
| 985 | |
| 986 displayLayout.div = div; | |
| 987 displayLayout.originalPosition.x = div.offsetLeft; | |
| 988 displayLayout.originalPosition.y = div.offsetTop; | |
| 903 }, | 989 }, |
| 904 | 990 |
| 905 /** | 991 /** |
| 906 * Layouts the display rectangles according to the current layout_. | 992 * Layouts the display rectangles according to the current layout_. |
| 993 * @param {options.DisplayLayoutType} layoutType | |
| 907 * @private | 994 * @private |
| 908 */ | 995 */ |
| 909 layoutDisplays_: function() { | 996 layoutDisplays_: function(layoutType) { |
| 910 var maxWidth = 0; | 997 var maxWidth = 0; |
| 911 var maxHeight = 0; | 998 var maxHeight = 0; |
| 912 var boundingBox = {left: 0, right: 0, top: 0, bottom: 0}; | 999 var boundingBox = {left: 0, right: 0, top: 0, bottom: 0}; |
| 913 this.primaryDisplay_ = null; | 1000 this.primaryDisplayId_ = ''; |
| 914 this.secondaryDisplay_ = null; | 1001 this.secondaryDisplayId_ = ''; |
| 915 var focusedDisplay = null; | |
| 916 for (var i = 0; i < this.displays_.length; i++) { | 1002 for (var i = 0; i < this.displays_.length; i++) { |
| 917 var display = this.displays_[i]; | 1003 var display = this.displays_[i]; |
| 918 if (display.isPrimary) | 1004 if (display.isPrimary) |
| 919 this.primaryDisplay_ = display; | 1005 this.primaryDisplayId_ = display.id; |
| 920 else | 1006 else if (this.secondaryDisplayId_ == '') |
| 921 this.secondaryDisplay_ = display; | 1007 this.secondaryDisplayId_ = display.id; |
| 922 if (i == this.focusedIndex_) | |
| 923 focusedDisplay = display; | |
| 924 | 1008 |
| 925 var bounds = display.bounds; | 1009 var bounds = display.bounds; |
| 926 boundingBox.left = Math.min(boundingBox.left, bounds.left); | 1010 boundingBox.left = Math.min(boundingBox.left, bounds.left); |
| 927 boundingBox.right = | 1011 boundingBox.right = |
| 928 Math.max(boundingBox.right, bounds.left + bounds.width); | 1012 Math.max(boundingBox.right, bounds.left + bounds.width); |
| 929 boundingBox.top = Math.min(boundingBox.top, bounds.top); | 1013 boundingBox.top = Math.min(boundingBox.top, bounds.top); |
| 930 boundingBox.bottom = | 1014 boundingBox.bottom = |
| 931 Math.max(boundingBox.bottom, bounds.top + bounds.height); | 1015 Math.max(boundingBox.bottom, bounds.top + bounds.height); |
| 932 maxWidth = Math.max(maxWidth, bounds.width); | 1016 maxWidth = Math.max(maxWidth, bounds.width); |
| 933 maxHeight = Math.max(maxHeight, bounds.height); | 1017 maxHeight = Math.max(maxHeight, bounds.height); |
| 934 } | 1018 } |
| 935 if (!this.primaryDisplay_) | 1019 if (this.primaryDisplayId_ == '') |
| 936 return; | 1020 return; |
| 937 | 1021 |
| 938 // Make the margin around the bounding box. | 1022 // Make the margin around the bounding box. |
| 939 var areaWidth = boundingBox.right - boundingBox.left + maxWidth; | 1023 var areaWidth = boundingBox.right - boundingBox.left + maxWidth; |
| 940 var areaHeight = boundingBox.bottom - boundingBox.top + maxHeight; | 1024 var areaHeight = boundingBox.bottom - boundingBox.top + maxHeight; |
| 941 | 1025 |
| 942 // Calculates the scale by the width since horizontal size is more strict. | 1026 // Calculates the scale by the width since horizontal size is more strict. |
| 943 // TODO(mukai): Adds the check of vertical size in case. | 1027 // TODO(mukai): Adds the check of vertical size in case. |
| 944 this.visualScale_ = Math.min( | 1028 this.visualScale_ = Math.min( |
| 945 VISUAL_SCALE, this.displaysView_.offsetWidth / areaWidth); | 1029 VISUAL_SCALE, this.displaysView_.offsetWidth / areaWidth); |
| 946 | 1030 |
| 947 // Prepare enough area for thisplays_view by adding the maximum height. | 1031 // Prepare enough area for thisplays_view by adding the maximum height. |
| 948 this.displaysView_.style.height = | 1032 this.displaysView_.style.height = |
| 949 Math.ceil(areaHeight * this.visualScale_) + 'px'; | 1033 Math.ceil(areaHeight * this.visualScale_) + 'px'; |
| 950 | 1034 |
| 951 // Centering the bounding box of the display rectangles. | 1035 // Centering the bounding box of the display rectangles. |
| 952 var offset = { | 1036 var offset = { |
| 953 x: Math.floor( | 1037 x: Math.floor( |
| 954 this.displaysView_.offsetWidth / 2 - | 1038 this.displaysView_.offsetWidth / 2 - |
| 955 (boundingBox.right + boundingBox.left) * this.visualScale_ / 2), | 1039 (boundingBox.right + boundingBox.left) * this.visualScale_ / 2), |
| 956 y: Math.floor( | 1040 y: Math.floor( |
| 957 this.displaysView_.offsetHeight / 2 - | 1041 this.displaysView_.offsetHeight / 2 - |
| 958 (boundingBox.bottom + boundingBox.top) * this.visualScale_ / 2) | 1042 (boundingBox.bottom + boundingBox.top) * this.visualScale_ / 2) |
| 959 }; | 1043 }; |
| 960 | 1044 |
| 961 // Layouting the display rectangles. First layout the primaryDisplay and | 1045 // Layout the display rectangles. First layout the primary display and |
| 962 // then layout the secondary which is attaching to the primary. | 1046 // then layout the secondary which is attached to the primary. |
| 963 var primaryDiv = this.createDisplayRectangle_( | 1047 for (var i = 0; i < this.displays_.length; i++) { |
| 964 this.primaryDisplay_, this.primaryDisplay_ == focusedDisplay); | 1048 this.createDisplayLayoutDiv_( |
| 965 primaryDiv.style.left = | 1049 this.displayLayoutMap_[this.displays_[i].id], layoutType, offset); |
| 966 Math.floor(this.primaryDisplay_.bounds.left * this.visualScale_) + | |
| 967 offset.x + 'px'; | |
| 968 primaryDiv.style.top = | |
| 969 Math.floor(this.primaryDisplay_.bounds.top * this.visualScale_) + | |
| 970 offset.y + 'px'; | |
| 971 this.primaryDisplay_.originalPosition = { | |
| 972 x: primaryDiv.offsetLeft, | |
| 973 y: primaryDiv.offsetTop | |
| 974 }; | |
| 975 | |
| 976 if (this.secondaryDisplay_) { | |
| 977 var secondaryDiv = this.createDisplayRectangle_( | |
| 978 this.secondaryDisplay_, this.secondaryDisplay_ == focusedDisplay); | |
| 979 // Don't trust the secondary display's x or y, because it may cause a | |
| 980 // 1px gap due to rounding, which will create a fake update on end | |
| 981 // dragging. See crbug.com/386401 | |
| 982 var bounds = this.secondaryDisplay_.bounds; | |
| 983 switch (this.layout_) { | |
| 984 case options.DisplayLayoutType.TOP: | |
| 985 secondaryDiv.style.left = | |
| 986 Math.floor(bounds.left * this.visualScale_) + offset.x + 'px'; | |
| 987 secondaryDiv.style.top = | |
| 988 primaryDiv.offsetTop - secondaryDiv.offsetHeight + 'px'; | |
| 989 break; | |
| 990 case options.DisplayLayoutType.RIGHT: | |
| 991 secondaryDiv.style.left = | |
| 992 primaryDiv.offsetLeft + primaryDiv.offsetWidth + 'px'; | |
| 993 secondaryDiv.style.top = | |
| 994 Math.floor(bounds.top * this.visualScale_) + offset.y + 'px'; | |
| 995 break; | |
| 996 case options.DisplayLayoutType.BOTTOM: | |
| 997 secondaryDiv.style.left = | |
| 998 Math.floor(bounds.left * this.visualScale_) + offset.x + 'px'; | |
| 999 secondaryDiv.style.top = | |
| 1000 primaryDiv.offsetTop + primaryDiv.offsetHeight + 'px'; | |
| 1001 break; | |
| 1002 case options.DisplayLayoutType.LEFT: | |
| 1003 secondaryDiv.style.left = | |
| 1004 primaryDiv.offsetLeft - secondaryDiv.offsetWidth + 'px'; | |
| 1005 secondaryDiv.style.top = | |
| 1006 Math.floor(bounds.top * this.visualScale_) + offset.y + 'px'; | |
| 1007 break; | |
| 1008 } | |
| 1009 this.secondaryDisplay_.originalPosition = { | |
| 1010 x: secondaryDiv.offsetLeft, | |
| 1011 y: secondaryDiv.offsetTop | |
| 1012 }; | |
| 1013 } | 1050 } |
| 1014 }, | 1051 }, |
| 1015 | 1052 |
| 1016 /** | 1053 /** |
| 1017 * Called when the display arrangement has changed. | 1054 * Called when the display arrangement has changed. |
| 1018 * @param {options.MultiDisplayMode} mode multi display mode. | 1055 * @param {options.MultiDisplayMode} mode multi display mode. |
| 1019 * @param {Array<options.DisplayInfo>} displays The list of the display | 1056 * @param {!Array<!options.DisplayInfo>} displays The list of the display |
| 1020 * information. | 1057 * information. |
| 1021 * @param {options.DisplayLayoutType} layout The layout strategy. | 1058 * @param {options.DisplayLayoutType} layoutType The layout strategy. |
| 1022 * @param {number} offset The offset of the secondary display. | 1059 * @param {number} offset The offset of the secondary display. |
| 1023 * @private | 1060 * @private |
| 1024 */ | 1061 */ |
| 1025 onDisplayChanged_: function(mode, displays, layout, offset) { | 1062 onDisplayChanged_: function(mode, displays, layoutType, offset) { |
| 1026 if (!this.visible) | 1063 if (!this.visible) |
| 1027 return; | 1064 return; |
| 1028 | 1065 |
| 1029 var hasExternal = false; | 1066 this.displays_ = displays; |
| 1067 this.displayLayoutMap_ = {}; | |
| 1030 for (var i = 0; i < displays.length; i++) { | 1068 for (var i = 0; i < displays.length; i++) { |
| 1031 if (!displays[i].isInternal) { | 1069 var display = displays[i]; |
| 1032 hasExternal = true; | 1070 this.displayLayoutMap_[display.id] = this.createDisplayLayout_(display); |
| 1033 break; | |
| 1034 } | |
| 1035 } | 1071 } |
| 1036 | 1072 |
| 1037 this.layout_ = layout; | |
| 1038 | |
| 1039 var mirroring = mode == options.MultiDisplayMode.MIRRORING; | 1073 var mirroring = mode == options.MultiDisplayMode.MIRRORING; |
| 1040 var unifiedDesktopEnabled = mode == options.MultiDisplayMode.UNIFIED; | 1074 var unifiedDesktopEnabled = mode == options.MultiDisplayMode.UNIFIED; |
| 1041 | 1075 |
| 1042 // Focus to the first display next to the primary one when |displays| list | 1076 // Focus to the first display next to the primary one when |displays_| |
| 1043 // is updated. | 1077 // is updated. |
| 1044 if (mirroring) { | 1078 if (mirroring) { |
| 1045 this.focusedIndex_ = -1; | 1079 this.focusedId_ = ''; |
| 1046 } else if (this.mirroring_ != mirroring || | 1080 } else if ( |
| 1047 this.unifiedDesktopEnabled_ != unifiedDesktopEnabled || | 1081 this.focusedId_ == '' || this.mirroring_ != mirroring || |
| 1048 this.displays_.length != displays.length) { | 1082 this.unifiedDesktopEnabled_ != unifiedDesktopEnabled || |
| 1049 this.focusedIndex_ = 0; | 1083 this.displays_.length != displays.length) { |
| 1084 this.focusedId_ = displays.length > 0 ? displays[0].id : ''; | |
| 1050 } | 1085 } |
| 1051 | 1086 |
| 1052 this.mirroring_ = mirroring; | 1087 this.mirroring_ = mirroring; |
| 1053 this.unifiedDesktopEnabled_ = unifiedDesktopEnabled; | 1088 this.unifiedDesktopEnabled_ = unifiedDesktopEnabled; |
| 1054 this.displays_ = displays; | |
| 1055 | 1089 |
| 1056 this.resetDisplaysView_(); | 1090 this.resetDisplaysView_(); |
| 1057 if (this.mirroring_) | 1091 if (this.mirroring_) |
| 1058 this.layoutMirroringDisplays_(); | 1092 this.layoutMirroringDisplays_(); |
| 1059 else | 1093 else |
| 1060 this.layoutDisplays_(); | 1094 this.layoutDisplays_(layoutType); |
| 1061 | 1095 |
| 1062 $('display-options-select-mirroring').value = | 1096 $('display-options-select-mirroring').value = |
| 1063 mirroring ? 'mirroring' : 'extended'; | 1097 mirroring ? 'mirroring' : 'extended'; |
| 1064 | 1098 |
| 1065 $('display-options-unified-desktop').hidden = | 1099 $('display-options-unified-desktop').hidden = |
| 1066 !this.showUnifiedDesktopOption_; | 1100 !this.showUnifiedDesktopOption_; |
| 1067 | 1101 |
| 1068 $('display-options-toggle-unified-desktop').checked = | 1102 $('display-options-toggle-unified-desktop').checked = |
| 1069 this.unifiedDesktopEnabled_; | 1103 this.unifiedDesktopEnabled_; |
| 1070 | 1104 |
| 1071 var disableUnifiedDesktopOption = | 1105 var disableUnifiedDesktopOption = |
| 1072 (this.mirroring_ || | 1106 (this.mirroring_ || |
| 1073 (!this.unifiedDesktopEnabled_ && | 1107 (!this.unifiedDesktopEnabled_ && |
| 1074 this.displays_.length == 1)); | 1108 this.displays_.length == 1)); |
| 1075 | 1109 |
| 1076 $('display-options-toggle-unified-desktop').disabled = | 1110 $('display-options-toggle-unified-desktop').disabled = |
| 1077 disableUnifiedDesktopOption; | 1111 disableUnifiedDesktopOption; |
| 1078 | 1112 |
| 1079 this.updateSelectedDisplayDescription_(); | 1113 this.updateSelectedDisplayDescription_(); |
| 1080 } | 1114 } |
| 1081 }; | 1115 }; |
| 1082 | 1116 |
| 1083 DisplayOptions.setDisplayInfo = function( | 1117 DisplayOptions.setDisplayInfo = function( |
| 1084 mode, displays, layout, offset) { | 1118 mode, displays, layoutType, offset) { |
| 1085 DisplayOptions.getInstance().onDisplayChanged_( | 1119 DisplayOptions.getInstance().onDisplayChanged_( |
| 1086 mode, displays, layout, offset); | 1120 mode, displays, layoutType, offset); |
| 1087 }; | 1121 }; |
| 1088 | 1122 |
| 1089 // Export | 1123 // Export |
| 1090 return { | 1124 return { |
| 1091 DisplayOptions: DisplayOptions | 1125 DisplayOptions: DisplayOptions |
| 1092 }; | 1126 }; |
| 1093 }); | 1127 }); |
| OLD | NEW |