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 |