Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(340)

Side by Side Diff: chrome/browser/resources/options/chromeos/display_options.js

Issue 11195036: Overscan calibration UI. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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.define('options', function() { 5 cr.define('options', function() {
6 var OptionsPage = options.OptionsPage; 6 var OptionsPage = options.OptionsPage;
7 7
8 // The scale ratio of the display rectangle to its original size. 8 // The scale ratio of the display rectangle to its original size.
9 /** @const */ var VISUAL_SCALE = 1 / 10; 9 /** @const */ var VISUAL_SCALE = 1 / 10;
10 10
11 // The number of pixels to share the edges between displays. 11 // The number of pixels to share the edges between displays.
12 /** @const */ var MIN_OFFSET_OVERLAP = 5; 12 /** @const */ var MIN_OFFSET_OVERLAP = 5;
13 13
14 // The border width of the display rectangles for the focused one.
15 /** @const */ var FOCUSED_BORDER_WIDTH_PX = 2;
16 // The border width of the display rectangles for the normal one.
17 /** @const */ var NORMAL_BORDER_WIDTH_PX = 1;
18
19 // The constant values for the overscan calibration settings.
20 // The height of an arrow.
21 /** @const */ var ARROW_SIZE_PX = 10;
22
23 // The gap from the boundary of the display rectangle and the arrow.
24 /** @const */ var ARROW_GAP_PX = 2;
25
26 // The margin size to handle events outside the target display.
27 /** @const */ var ARROW_CONTAINER_MARGIN_PX = ARROW_SIZE_PX * 3;
28
29 // The interval times to update the overscan while the user keeps pressing
30 // the mouse button or touching.
31 /** @const */ var OVERSCAN_TIC_INTERVAL_MS = 100;
32
14 /** 33 /**
15 * Enumeration of secondary display layout. The value has to be same as the 34 * Enumeration of secondary display layout. The value has to be same as the
16 * values in ash/display/display_controller.cc. 35 * values in ash/display/display_controller.cc.
17 * @enum {number} 36 * @enum {number}
18 */ 37 */
19 var SecondaryDisplayLayout = { 38 var SecondaryDisplayLayout = {
20 TOP: 0, 39 TOP: 0,
21 RIGHT: 1, 40 RIGHT: 1,
22 BOTTOM: 2, 41 BOTTOM: 2,
23 LEFT: 3 42 LEFT: 3
24 }; 43 };
25 44
26 /** 45 /**
46 * Enumeration of the direction for the calibrating overscan settings.
47 * @enum {number}
48 */
49 var CalibrationDirection = {
50 INNER: 1,
51 OUTER: -1
52 };
53
54 /**
55 * Calculates the bounds of |element| relative to the page.
56 * @param {HTMLElement} element The element to be known.
57 * @return {Object} The object for the bounds, with x, y, width, and height.
58 */
59 function getBoundsInPage(element) {
60 if (element == document.body)
61 return {x: 0, y: 0};
62
63 var point = getBoundsInPage(element.parentNode);
xiyuan 2012/10/22 19:54:44 Should we use element.offsetParent instead? Also
Jun Mukai 2012/10/22 22:35:30 Done.
64 point.x += element.offsetLeft;
65 point.y += element.offsetTop;
66 point.width = element.offsetWidth;
67 point.height = element.offsetHeight;
68 return point;
xiyuan 2012/10/22 19:54:44 nit: How about return { x: point.x + element
Jun Mukai 2012/10/22 22:35:30 Changed the code not to use recursion, so the code
69 }
70
71 /**
72 * Gets the position of |point| to |rect|, left, right, top, or bottom.
73 * @param {Object} rect The base rectangle with x, y, width, and height.
74 * @param {Object} point The point to check the position.
75 * @return {SecondaryDisplayLayout} The position of the calculated point.
76 */
77 function getPositionToRectangle(rect, point) {
78 // Separates the area into four (LEFT/RIGHT/TOP/BOTTOM) by the diagonals of
79 // the rect, and decides which area the display should reside.
80 var diagonalSlope = rect.height / rect.width;
81 var topDownIntercept = rect.y - rect.x * diagonalSlope;
82 var bottomUpIntercept = rect.y + rect.height + rect.x * diagonalSlope;
83
84 if (point.y > topDownIntercept + point.x * diagonalSlope) {
85 if (point.y > bottomUpIntercept - point.x * diagonalSlope)
86 return SecondaryDisplayLayout.BOTTOM;
87 else
88 return SecondaryDisplayLayout.LEFT;
89 } else {
90 if (point.y > bottomUpIntercept - point.x * diagonalSlope)
91 return SecondaryDisplayLayout.RIGHT;
92 else
93 return SecondaryDisplayLayout.TOP;
94 }
95 }
96
97 /**
98 * DisplayOverscanCalibrator shows the arrows to calibrate overscan settings
99 * and handles events of the actual user control.
100 * @param {Object} display The display object for the calibrating overscan.
101 * @constructor
102 */
103 function DisplayOverscanCalibrator(display) {
104 // Creates the calibration arrows over |display|. To achieve the UI,
105 // a transparent container holds the arrows and handles events.
106 this.container_ = document.createElement('div');
107 this.container_.id = 'display-overscan-calibration-arrow-container';
108 var containerSize = {
109 width: display.div.offsetWidth + ARROW_CONTAINER_MARGIN_PX * 2,
110 height: display.div.offsetHeight + ARROW_CONTAINER_MARGIN_PX * 2
111 };
112 this.container_.style.width = containerSize.width + 'px';
113 this.container_.style.height = containerSize.height + 'px';
114 this.container_.style.left =
115 display.div.offsetLeft - ARROW_CONTAINER_MARGIN_PX + 'px';
116 this.container_.style.top =
117 display.div.offsetTop - ARROW_CONTAINER_MARGIN_PX + 'px';
118 this.container_.onmousedown = this.onMouseDown_.bind(this);
119 this.container_.onmouseup = this.onOperationEnd_.bind(this);
120 this.container_.ontouchstart = this.onTouchStart_.bind(this);
121 this.container_.ontouchend = this.onOperationEnd_.bind(this);
122
123 // Creates arrows for each direction.
124 var topArrow = this.createVerticalArrows_();
125 topArrow.style.left = containerSize.width / 2 - ARROW_SIZE_PX + 'px';
126 topArrow.style.top = ARROW_CONTAINER_MARGIN_PX -
127 ARROW_SIZE_PX - ARROW_GAP_PX + 'px';
128 this.container_.appendChild(topArrow);
129 var bottomArrow = this.createVerticalArrows_();
130 bottomArrow.style.left = containerSize.width / 2 - ARROW_SIZE_PX + 'px';
131 bottomArrow.style.bottom = ARROW_CONTAINER_MARGIN_PX -
132 ARROW_SIZE_PX - ARROW_GAP_PX + 'px';
133 this.container_.appendChild(bottomArrow);
134 var leftArrow = this.createHorizontalArrows_();
135 leftArrow.style.left = ARROW_CONTAINER_MARGIN_PX -
136 ARROW_SIZE_PX - ARROW_GAP_PX + 'px';
137 leftArrow.style.top = containerSize.height / 2 - ARROW_SIZE_PX + 'px';
138 this.container_.appendChild(leftArrow);
139 var rightArrow = this.createHorizontalArrows_();
140 rightArrow.style.right = ARROW_CONTAINER_MARGIN_PX -
141 ARROW_SIZE_PX - ARROW_GAP_PX + 'px';
142 rightArrow.style.top = containerSize.height / 2 - ARROW_SIZE_PX + 'px';
143 this.container_.appendChild(rightArrow);
144
145 display.div.parentNode.appendChild(this.container_);
146 this.displayBounds_ = getBoundsInPage(display.div);
147 this.overscan_ = display.overscan;
148 chrome.send('startOverscanCalibration', [display.id]);
149 };
150
151 DisplayOverscanCalibrator.prototype = {
152 /**
153 * The container of arrows. It also receives the user events.
154 * @private
155 */
156 container_: null,
157
158 /**
159 * The bounds of the display rectangle in the page.
160 * @private
161 */
162 displayBounds_: null,
163
164 /**
165 * The current overscan settins.
166 * @private
167 */
168 overscan_: null,
169
170 /**
171 * The location of the current user operation against the display. The
172 * contents should be one of 'left', 'right', 'top', or 'bottom'.
173 * @type {string}
174 * @private
175 */
176 location_: null,
177
178 /**
179 * The direction of the current user operation against the display.
180 * @type {CalibrationDirection}
181 * @private
182 */
183 direction_: null,
184
185 /**
186 * The ID for the periodic timer to tic the calibration settings while the
187 * user keeps pressing the mouse button.
188 * @type {number}
189 * @private
190 */
191 timer_: null,
192
193 /**
194 * Called when everything is finished.
195 */
196 Finish: function() {
xiyuan 2012/10/22 19:54:44 nit: js method should start with lower case. Fin
Jun Mukai 2012/10/22 22:35:30 Done.
197 this.container_.parentNode.removeChild(this.container_);
198 chrome.send('finishOverscanCalibration');
199 },
200
201 /**
202 * Called when every settings are cleared.
203 */
204 Clear: function() {
xiyuan 2012/10/22 19:54:44 nit: Clear -> clear
Jun Mukai 2012/10/22 22:35:30 Done.
205 chrome.send('clearOverscanCalibration');
206 },
207
208 /**
209 * Mouse down event handler for overscan calibration.
210 * @param {Event} e The mouse down event.
211 * @private
212 */
213 onMouseDown_: function(e) {
214 e.preventDefault();
215 this.setupOverscanCalibration_(e);
216 },
217
218 /**
219 * Touch start event handler for overscan calibration.
220 * @param {Event} e The touch start event.
221 * @private
222 */
223 onTouchStart_: function(e) {
224 if (e.touches.length != 1)
225 return;
226
227 e.preventDefault();
228 var touch = e.touches[0];
229 this.setupOverscanCalibration_(e.touches[0]);
230 },
231
232 /**
233 * Event handler for ending the user operation of overscan calibration.
234 * @param {Event} e The event object, mouse up event or touch end event.
235 * @private
236 */
237 onOperationEnd_: function(e) {
238 if (this.timer_) {
239 window.clearInterval(this.timer_);
240 this.timer_ = null;
241 e.preventDefault();
242 }
243 },
244
245 /**
246 * Sets up a new overscan calibration operation. It calculates the event
247 * location and determines the contents of location. It also sets up a
248 * timer to change the overscan settings continuously as far as the user
249 * keeps pressing the mouse button or touching. The timer will be cleared
250 * on ending the operation.
251 * @param {Object} e The object to contain the location of the event with
252 * pageX and pageY attributes.
253 * @private
254 */
255 setupOverscanCalibration_: function(e) {
256 switch (getPositionToRectangle(
257 this.displayBounds_, {x: e.pageX, y: e.pageY})) {
258 case SecondaryDisplayLayout.RIGHT:
259 this.location_ = 'right';
260 if (e.pageX < this.displayBounds_.x + this.displayBounds_.width)
261 this.direction_ = CalibrationDirection.INNER;
262 else
263 this.direction_ = CalibrationDirection.OUTER;
264 break;
265 case SecondaryDisplayLayout.LEFT:
266 this.location_ = 'left';
267 if (e.pageX > this.displayBounds_.x)
268 this.direction_ = CalibrationDirection.INNER;
269 else
270 this.direction_ = CalibrationDirection.OUTER;
271 break;
272 case SecondaryDisplayLayout.TOP:
273 this.location_ = 'top';
274 if (e.pageY > this.displayBounds_.y)
275 this.direction_ = CalibrationDirection.INNER;
276 else
277 this.direction_ = CalibrationDirection.OUTER;
278 break;
279 case SecondaryDisplayLayout.BOTTOM:
280 this.location_ = 'bottom';
281 if (e.pageY < this.displayBounds_.y + this.displayBounds_.height) {
282 this.direction_ = CalibrationDirection.INNER;
283 } else {
284 this.direction_ = CalibrationDirection.OUTER;
285 }
286 break;
287 }
288
289 this.ticOverscanSize_();
290 this.timer_ = window.setInterval(
291 this.ticOverscanSize_.bind(this), OVERSCAN_TIC_INTERVAL_MS);
292 },
293
294 /**
295 * Modifies the current overscans actually and sends the update to the
296 * system.
297 * @private
298 */
299 ticOverscanSize_: function() {
300 // Overscan inset values have to be positive.
301 if (this.direction_ == CalibrationDirection.OUTER &&
302 this.overscan_[this.location_] == 0) {
xiyuan 2012/10/22 19:54:44 This does not match what the comment above says. S
Jun Mukai 2012/10/22 22:35:30 The code is correct, my intention is that this.ove
303 return;
304 }
305
306 this.overscan_[this.location_] += this.direction_;
307 chrome.send('updateOverscanCalibration',
308 [this.overscan_.top, this.overscan_.left,
309 this.overscan_.bottom, this.overscan_.right]);
310 },
311
312 /**
313 * Creates the arrows vertically aligned, for the calibration UI at the top
314 * and bottom of the target display.
315 * @return {HTMLElement} The created div which contains the arrows.
316 * @private
317 */
318 createVerticalArrows_: function() {
319 var container = document.createElement('div');
320 container.style.width = ARROW_SIZE_PX * 2 + 'px';
321 container.style.height =
322 ARROW_SIZE_PX * 2 + ARROW_GAP_PX * 2 + FOCUSED_BORDER_WIDTH_PX + 'px';
323 container.style.position = 'absolute';
324
325 var arrowUp = document.createElement('div');
326 arrowUp.className = 'display-overscan-calibration-arrow ' +
327 'display-overscan-arrow-to-top';
328 arrowUp.style.left = '0';
329 arrowUp.style.top = -ARROW_SIZE_PX + 'px';
330 container.appendChild(arrowUp);
331 var arrowDown = document.createElement('div');
332 arrowDown.className = 'display-overscan-calibration-arrow ' +
333 'display-overscan-arrow-to-bottom';
334 arrowDown.style.left = '0';
335 arrowDown.style.bottom = -ARROW_SIZE_PX + 'px';
336 container.appendChild(arrowDown);
337 return container;
338 },
339
340 /**
341 * Creates the arrows horizontally aligned, for the calibration UI at the
342 * left and right of the target display.
343 * @return {HTMLElement} The created div which contains the arrows.
344 * @private
345 */
346 createHorizontalArrows_: function() {
347 var container = document.createElement('div');
348 container.style.width =
349 ARROW_SIZE_PX * 2 + ARROW_GAP_PX * 2 + FOCUSED_BORDER_WIDTH_PX + 'px';
350 container.style.height = ARROW_SIZE_PX * 2 + 'px';
351 container.style.position = 'absolute';
352
353 var arrowLeft = document.createElement('div');
354 arrowLeft.className = 'display-overscan-calibration-arrow ' +
355 'display-overscan-arrow-to-left';
356 arrowLeft.style.left = -ARROW_SIZE_PX + 'px';
357 arrowLeft.style.top = '0';
358 container.appendChild(arrowLeft);
359 var arrowRight = document.createElement('div');
360 arrowRight.className = 'display-overscan-calibration-arrow ' +
361 'display-overscan-arrow-to-right';
362 arrowRight.style.right = -ARROW_SIZE_PX + 'px';
363 arrowRight.style.top = '0';
364 container.appendChild(arrowRight);
365 return container;
366 }
367 };
368
369 /**
27 * Encapsulated handling of the 'Display' page. 370 * Encapsulated handling of the 'Display' page.
28 * @constructor 371 * @constructor
29 */ 372 */
30 function DisplayOptions() { 373 function DisplayOptions() {
31 OptionsPage.call(this, 'display', 374 OptionsPage.call(this, 'display',
32 loadTimeData.getString('displayOptionsPageTabTitle'), 375 loadTimeData.getString('displayOptionsPageTabTitle'),
33 'display-options-page'); 376 'display-options-page');
34 } 377 }
35 378
36 cr.addSingletonGetter(DisplayOptions); 379 cr.addSingletonGetter(DisplayOptions);
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 var container = $('display-options-displays-view-host'); 461 var container = $('display-options-displays-view-host');
119 container.onmousemove = this.onMouseMove_.bind(this); 462 container.onmousemove = this.onMouseMove_.bind(this);
120 container.onmouseup = this.endDragging_.bind(this); 463 container.onmouseup = this.endDragging_.bind(this);
121 container.ontouchmove = this.onTouchMove_.bind(this); 464 container.ontouchmove = this.onTouchMove_.bind(this);
122 container.ontouchend = this.endDragging_.bind(this); 465 container.ontouchend = this.endDragging_.bind(this);
123 466
124 $('display-options-set-primary').onclick = (function() { 467 $('display-options-set-primary').onclick = (function() {
125 chrome.send('setPrimary', [this.displays_[this.focusedIndex_].id]); 468 chrome.send('setPrimary', [this.displays_[this.focusedIndex_].id]);
126 }).bind(this); 469 }).bind(this);
127 470
471 $('selected-display-start-calibrating-overscan').onclick = (function() {
472 this.overscanCalibrator_ = new DisplayOverscanCalibrator(
473 this.displays_[this.focusedIndex_]);
474 this.updateSelectedDisplayDescription_();
475 }).bind(this);
476 $('selected-display-finish-calibrating-overscan').onclick = (function() {
477 this.overscanCalibrator_.Finish();
478 this.overscanCalibrator_ = null;
479 this.updateSelectedDisplayDescription_();
480 }).bind(this);
481 $('selected-display-clear-calibrating-overscan').onclick = (function() {
482 this.overscanCalibrator_.Clear();
483 this.overscanCalibrator_ = null;
484 this.updateSelectedDisplayDescription_();
485 }).bind(this);
486
128 chrome.send('getDisplayInfo'); 487 chrome.send('getDisplayInfo');
129 }, 488 },
130 489
131 /** @override */ 490 /** @override */
132 onVisibilityChanged_: function() { 491 onVisibilityChanged_: function() {
133 OptionsPage.prototype.onVisibilityChanged_(this); 492 OptionsPage.prototype.onVisibilityChanged_(this);
134 if (this.visible) 493 if (this.visible)
135 chrome.send('getDisplayInfo'); 494 chrome.send('getDisplayInfo');
136 }, 495 },
137 496
138 /** 497 /**
139 * Mouse move handler for dragging display rectangle. 498 * Mouse move handler for dragging display rectangle.
499 * @param {Event} e The mouse move event.
140 * @private 500 * @private
141 * @param {Event} e The mouse move event.
142 */ 501 */
143 onMouseMove_: function(e) { 502 onMouseMove_: function(e) {
144 return this.processDragging_(e, {x: e.pageX, y: e.pageY}); 503 return this.processDragging_(e, {x: e.pageX, y: e.pageY});
145 }, 504 },
146 505
147 /** 506 /**
148 * Touch move handler for dragging display rectangle. 507 * Touch move handler for dragging display rectangle.
508 * @param {Event} e The touch move event.
149 * @private 509 * @private
150 * @param {Event} e The touch move event.
151 */ 510 */
152 onTouchMove_: function(e) { 511 onTouchMove_: function(e) {
153 if (e.touches.length != 1) 512 if (e.touches.length != 1)
154 return true; 513 return true;
155 514
156 var touchLocation = {x: e.touches[0].pageX, y: e.touches[0].pageY}; 515 var touchLocation = {x: e.touches[0].pageX, y: e.touches[0].pageY};
157 // Touch move events happen even if the touch location doesn't change, but 516 // Touch move events happen even if the touch location doesn't change, but
158 // it doesn't need to process the dragging. Since sometimes the touch 517 // it doesn't need to process the dragging. Since sometimes the touch
159 // position changes slightly even though the user doesn't think to move 518 // position changes slightly even though the user doesn't think to move
160 // the finger, very small move is just ignored. 519 // the finger, very small move is just ignored.
161 /** @const */ var IGNORABLE_TOUCH_MOVE_PX = 1; 520 /** @const */ var IGNORABLE_TOUCH_MOVE_PX = 1;
162 var x_diff = Math.abs(touchLocation.x - this.lastTouchLocation_.x); 521 var x_diff = Math.abs(touchLocation.x - this.lastTouchLocation_.x);
163 var y_diff = Math.abs(touchLocation.y - this.lastTouchLocation_.y); 522 var y_diff = Math.abs(touchLocation.y - this.lastTouchLocation_.y);
164 if (x_diff <= IGNORABLE_TOUCH_MOVE_PX && 523 if (x_diff <= IGNORABLE_TOUCH_MOVE_PX &&
165 y_diff <= IGNORABLE_TOUCH_MOVE_PX) { 524 y_diff <= IGNORABLE_TOUCH_MOVE_PX) {
166 return true; 525 return true;
167 } 526 }
168 527
169 this.lastTouchLocation_ = touchLocation; 528 this.lastTouchLocation_ = touchLocation;
170 return this.processDragging_(e, touchLocation); 529 return this.processDragging_(e, touchLocation);
171 }, 530 },
172 531
173 /** 532 /**
174 * Mouse down handler for dragging display rectangle. 533 * Mouse down handler for dragging display rectangle.
534 * @param {Event} e The mouse down event.
175 * @private 535 * @private
176 * @param {Event} e The mouse down event.
177 */ 536 */
178 onMouseDown_: function(e) { 537 onMouseDown_: function(e) {
179 if (this.mirroring_) 538 if (this.mirroring_)
180 return true; 539 return true;
181 540
182 if (e.button != 0) 541 if (e.button != 0)
183 return true; 542 return true;
184 543
185 e.preventDefault(); 544 e.preventDefault();
186 return this.startDragging_(e.target, {x: e.pageX, y: e.pageY}); 545 return this.startDragging_(e.target, {x: e.pageX, y: e.pageY});
187 }, 546 },
188 547
189 /** 548 /**
190 * Touch start handler for dragging display rectangle. 549 * Touch start handler for dragging display rectangle.
550 * @param {Event} e The touch start event.
191 * @private 551 * @private
192 * @param {Event} e The touch start event.
193 */ 552 */
194 onTouchStart_: function(e) { 553 onTouchStart_: function(e) {
195 if (this.mirroring_) 554 if (this.mirroring_)
196 return true; 555 return true;
197 556
198 if (e.touches.length != 1) 557 if (e.touches.length != 1)
199 return false; 558 return false;
200 559
201 e.preventDefault(); 560 e.preventDefault();
202 var touch = e.touches[0]; 561 var touch = e.touches[0];
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
246 if (startDiff < SNAP_DISTANCE_PX && startDiff < endDiff) 605 if (startDiff < SNAP_DISTANCE_PX && startDiff < endDiff)
247 return basePoint; 606 return basePoint;
248 else if (endDiff < SNAP_DISTANCE_PX) 607 else if (endDiff < SNAP_DISTANCE_PX)
249 return basePoint + baseWidth - width; 608 return basePoint + baseWidth - width;
250 609
251 return point; 610 return point;
252 }, 611 },
253 612
254 /** 613 /**
255 * Processes the actual dragging of display rectangle. 614 * Processes the actual dragging of display rectangle.
256 * @private
257 * @param {Event} e The event which triggers this drag. 615 * @param {Event} e The event which triggers this drag.
258 * @param {Object} eventLocation The location where the event happens. 616 * @param {Object} eventLocation The location where the event happens.
617 * @private
259 */ 618 */
260 processDragging_: function(e, eventLocation) { 619 processDragging_: function(e, eventLocation) {
261 if (!this.dragging_) 620 if (!this.dragging_)
262 return true; 621 return true;
263 622
264 var index = -1; 623 var index = -1;
265 for (var i = 0; i < this.displays_.length; i++) { 624 for (var i = 0; i < this.displays_.length; i++) {
266 if (this.displays_[i] == this.dragging_.display) { 625 if (this.displays_[i] == this.dragging_.display) {
267 index = i; 626 index = i;
268 break; 627 break;
(...skipping 21 matching lines...) Expand all
290 newPosition.x = this.snapToEdge_(newPosition.x, draggingDiv.offsetWidth, 649 newPosition.x = this.snapToEdge_(newPosition.x, draggingDiv.offsetWidth,
291 baseDiv.offsetLeft, baseDiv.offsetWidth); 650 baseDiv.offsetLeft, baseDiv.offsetWidth);
292 newPosition.y = this.snapToEdge_(newPosition.y, draggingDiv.offsetHeight, 651 newPosition.y = this.snapToEdge_(newPosition.y, draggingDiv.offsetHeight,
293 baseDiv.offsetTop, baseDiv.offsetHeight); 652 baseDiv.offsetTop, baseDiv.offsetHeight);
294 653
295 var newCenter = { 654 var newCenter = {
296 x: newPosition.x + draggingDiv.offsetWidth / 2, 655 x: newPosition.x + draggingDiv.offsetWidth / 2,
297 y: newPosition.y + draggingDiv.offsetHeight / 2 656 y: newPosition.y + draggingDiv.offsetHeight / 2
298 }; 657 };
299 658
300 // Separate the area into four (LEFT/RIGHT/TOP/BOTTOM) by the diagonals of 659 var baseBounds = {
301 // the base display, and decide which area the display should reside. 660 x: baseDiv.offsetLeft,
302 var diagonalSlope = baseDiv.offsetHeight / baseDiv.offsetWidth; 661 y: baseDiv.offsetTop,
303 var topDownIntercept = 662 width: baseDiv.offsetWidth,
304 baseDiv.offsetTop - baseDiv.offsetLeft * diagonalSlope; 663 height: baseDiv.offsetHeight
305 var bottomUpIntercept = baseDiv.offsetTop + 664 };
306 baseDiv.offsetHeight + baseDiv.offsetLeft * diagonalSlope; 665 switch (getPositionToRectangle(baseBounds, newCenter)) {
307 666 case SecondaryDisplayLayout.RIGHT:
308 if (newCenter.y > 667 this.layout_ = this.dragging_.display.isPrimary ?
309 topDownIntercept + newCenter.x * diagonalSlope) { 668 SecondaryDisplayLayout.LEFT : SecondaryDisplayLayout.RIGHT;
310 if (newCenter.y > 669 break;
311 bottomUpIntercept - newCenter.x * diagonalSlope) 670 case SecondaryDisplayLayout.LEFT:
312 this.layout_ = this.dragging_.display.isPrimary ? 671 this.layout_ = this.dragging_.display.isPrimary ?
313 SecondaryDisplayLayout.TOP : SecondaryDisplayLayout.BOTTOM; 672 SecondaryDisplayLayout.RIGHT : SecondaryDisplayLayout.LEFT;
314 else 673 break;
315 this.layout_ = this.dragging_.display.isPrimary ? 674 case SecondaryDisplayLayout.TOP:
316 SecondaryDisplayLayout.RIGHT : SecondaryDisplayLayout.LEFT; 675 this.layout_ = this.dragging_.display.isPrimary ?
317 } else { 676 SecondaryDisplayLayout.BOTTOM : SecondaryDisplayLayout.TOP;
318 if (newCenter.y > 677 break;
319 bottomUpIntercept - newCenter.x * diagonalSlope) 678 case SecondaryDisplayLayout.BOTTOM:
320 this.layout_ = this.dragging_.display.isPrimary ? 679 this.layout_ = this.dragging_.display.isPrimary ?
321 SecondaryDisplayLayout.LEFT : SecondaryDisplayLayout.RIGHT; 680 SecondaryDisplayLayout.TOP : SecondaryDisplayLayout.BOTTOM;
322 else 681 break;
323 this.layout_ = this.dragging_.display.isPrimary ?
324 SecondaryDisplayLayout.BOTTOM : SecondaryDisplayLayout.TOP;
325 } 682 }
326 683
327 if (this.layout_ == SecondaryDisplayLayout.LEFT || 684 if (this.layout_ == SecondaryDisplayLayout.LEFT ||
328 this.layout_ == SecondaryDisplayLayout.RIGHT) { 685 this.layout_ == SecondaryDisplayLayout.RIGHT) {
329 if (newPosition.y > baseDiv.offsetTop + baseDiv.offsetHeight) 686 if (newPosition.y > baseDiv.offsetTop + baseDiv.offsetHeight)
330 this.layout_ = this.dragging_.display.isPrimary ? 687 this.layout_ = this.dragging_.display.isPrimary ?
331 SecondaryDisplayLayout.TOP : SecondaryDisplayLayout.BOTTOM; 688 SecondaryDisplayLayout.TOP : SecondaryDisplayLayout.BOTTOM;
332 else if (newPosition.y + draggingDiv.offsetHeight < 689 else if (newPosition.y + draggingDiv.offsetHeight <
333 baseDiv.offsetTop) 690 baseDiv.offsetTop)
334 this.layout_ = this.dragging_.display.isPrimary ? 691 this.layout_ = this.dragging_.display.isPrimary ?
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
385 draggingDiv.style.left = newPosition.x + 'px'; 742 draggingDiv.style.left = newPosition.x + 'px';
386 break; 743 break;
387 } 744 }
388 745
389 this.dirty_ = true; 746 this.dirty_ = true;
390 return false; 747 return false;
391 }, 748 },
392 749
393 /** 750 /**
394 * start dragging of a display rectangle. 751 * start dragging of a display rectangle.
395 * @private
396 * @param {HTMLElement} target The event target. 752 * @param {HTMLElement} target The event target.
397 * @param {Object} eventLocation The object to hold the location where 753 * @param {Object} eventLocation The object to hold the location where
398 * this event happens. 754 * this event happens.
755 * @private
399 */ 756 */
400 startDragging_: function(target, eventLocation) { 757 startDragging_: function(target, eventLocation) {
401 this.focusedIndex_ = null; 758 this.focusedIndex_ = null;
402 for (var i = 0; i < this.displays_.length; i++) { 759 for (var i = 0; i < this.displays_.length; i++) {
403 var display = this.displays_[i]; 760 var display = this.displays_[i];
404 if (display.div == target || 761 if (display.div == target ||
405 (display.isPrimary && $('display-launcher') == target)) { 762 (display.isPrimary && $('display-launcher') == target)) {
406 this.focusedIndex_ = i; 763 this.focusedIndex_ = i;
407 break; 764 break;
408 } 765 }
409 } 766 }
410 767
411 for (var i = 0; i < this.displays_.length; i++) { 768 for (var i = 0; i < this.displays_.length; i++) {
412 var display = this.displays_[i]; 769 var display = this.displays_[i];
413 display.div.className = 'displays-display'; 770 display.div.className = 'displays-display';
414 this.resizeDisplayRectangle_(display, i); 771 this.resizeDisplayRectangle_(display, i);
415 if (i != this.focusedIndex_) 772 if (i != this.focusedIndex_)
416 continue; 773 continue;
417 774
418 display.div.classList.add('displays-focused'); 775 display.div.classList.add('displays-focused');
419 this.dragging_ = { 776 this.dragging_ = {
420 display: display, 777 display: display,
421 originalLocation: { 778 originalLocation: {
422 x: display.div.offsetLeft, y: display.div.offsetTop 779 x: display.div.offsetLeft, y: display.div.offsetTop
423 }, 780 },
424 eventLocation: eventLocation 781 eventLocation: eventLocation
425 }; 782 };
426 } 783 }
784
785 if (this.overscanCalibrator_) {
786 this.overscanCalibrator_.Finish();
787 this.overscanCalibrator_ = null;
788 }
427 this.updateSelectedDisplayDescription_(); 789 this.updateSelectedDisplayDescription_();
428 return false; 790 return false;
429 }, 791 },
430 792
431 /** 793 /**
432 * finish the current dragging of displays. 794 * finish the current dragging of displays.
795 * @param {Event} e The event which triggers this.
433 * @private 796 * @private
434 * @param {Event} e The event which triggers this.
435 */ 797 */
436 endDragging_: function(e) { 798 endDragging_: function(e) {
437 this.lastTouchLocation_ = null; 799 this.lastTouchLocation_ = null;
438 if (this.dragging_) { 800 if (this.dragging_) {
439 // Make sure the dragging location is connected. 801 // Make sure the dragging location is connected.
440 var baseDiv = this.dragging_.display.isPrimary ? 802 var baseDiv = this.dragging_.display.isPrimary ?
441 this.secondaryDisplay_.div : this.primaryDisplay_.div; 803 this.secondaryDisplay_.div : this.primaryDisplay_.div;
442 var draggingDiv = this.dragging_.display.div; 804 var draggingDiv = this.dragging_.display.div;
443 if (this.layout_ == SecondaryDisplayLayout.LEFT || 805 if (this.layout_ == SecondaryDisplayLayout.LEFT ||
444 this.layout_ == SecondaryDisplayLayout.RIGHT) { 806 this.layout_ == SecondaryDisplayLayout.RIGHT) {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
485 while (nameElement.childNodes.length > 0) 847 while (nameElement.childNodes.length > 0)
486 nameElement.removeChild(nameElement.firstChild); 848 nameElement.removeChild(nameElement.firstChild);
487 nameElement.appendChild(document.createTextNode(display.name)); 849 nameElement.appendChild(document.createTextNode(display.name));
488 850
489 var resolutionData = display.width + 'x' + display.height; 851 var resolutionData = display.width + 'x' + display.height;
490 var resolutionElement = $('selected-display-resolution'); 852 var resolutionElement = $('selected-display-resolution');
491 while (resolutionElement.childNodes.length > 0) 853 while (resolutionElement.childNodes.length > 0)
492 resolutionElement.removeChild(resolutionElement.firstChild); 854 resolutionElement.removeChild(resolutionElement.firstChild);
493 resolutionElement.appendChild(document.createTextNode(resolutionData)); 855 resolutionElement.appendChild(document.createTextNode(resolutionData));
494 856
857 if (this.overscanCalibrator_) {
858 $('start-calibrating-overscan-control').hidden = true;
859 $('end-calibrating-overscan-control').hidden = false;
860 } else {
861 $('start-calibrating-overscan-control').hidden = false;
862 $('end-calibrating-overscan-control').hidden = true;
863 }
864
495 var arrow = $('display-configuration-arrow'); 865 var arrow = $('display-configuration-arrow');
496 arrow.hidden = false; 866 arrow.hidden = false;
497 arrow.style.top = 867 arrow.style.top =
498 $('display-configurations').offsetTop - arrow.offsetHeight / 2 + 'px'; 868 $('display-configurations').offsetTop - arrow.offsetHeight / 2 + 'px';
499 arrow.style.left = display.div.offsetLeft + display.div.offsetWidth / 2 - 869 arrow.style.left = display.div.offsetLeft + display.div.offsetWidth / 2 -
500 arrow.offsetWidth / 2 + 'px'; 870 arrow.offsetWidth / 2 + 'px';
501 871
502 $('display-options-set-primary').disabled = 872 $('display-options-set-primary').disabled =
503 this.displays_[this.focusedIndex_].isPrimary; 873 this.displays_[this.focusedIndex_].isPrimary;
504 }, 874 },
(...skipping 11 matching lines...) Expand all
516 }, 886 },
517 887
518 /** 888 /**
519 * Resize the specified display rectangle to keep the change of 889 * Resize the specified display rectangle to keep the change of
520 * the border width. 890 * the border width.
521 * @param {Object} display The display object. 891 * @param {Object} display The display object.
522 * @param {number} index The index of the display. 892 * @param {number} index The index of the display.
523 * @private 893 * @private
524 */ 894 */
525 resizeDisplayRectangle_: function(display, index) { 895 resizeDisplayRectangle_: function(display, index) {
526 /** @const */ var FOCUSED_BORDER_WIDTH_PX = 2;
527 /** @const */ var NORMAL_BORDER_WIDTH_PX = 1;
528 var borderWidth = (index == this.focusedIndex_) ? 896 var borderWidth = (index == this.focusedIndex_) ?
529 FOCUSED_BORDER_WIDTH_PX : NORMAL_BORDER_WIDTH_PX; 897 FOCUSED_BORDER_WIDTH_PX : NORMAL_BORDER_WIDTH_PX;
530 display.div.style.width = 898 display.div.style.width =
531 display.width * this.visualScale_ - borderWidth * 2 + 'px'; 899 display.width * this.visualScale_ - borderWidth * 2 + 'px';
532 display.div.style.height = 900 display.div.style.height =
533 display.height * this.visualScale_ - borderWidth * 2 + 'px'; 901 display.height * this.visualScale_ - borderWidth * 2 + 'px';
534 display.div.style.lineHeight = display.div.style.height; 902 display.div.style.lineHeight = display.div.style.height;
535 if (display.isPrimary) { 903 if (display.isPrimary) {
536 var launcher = display.div.firstChild; 904 var launcher = display.div.firstChild;
537 if (launcher && launcher.id == 'display-launcher') { 905 if (launcher && launcher.id == 'display-launcher') {
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
654 1022
655 div.onmousedown = this.onMouseDown_.bind(this); 1023 div.onmousedown = this.onMouseDown_.bind(this);
656 div.ontouchstart = this.onTouchStart_.bind(this); 1024 div.ontouchstart = this.onTouchStart_.bind(this);
657 1025
658 this.displaysView_.appendChild(div); 1026 this.displaysView_.appendChild(div);
659 } 1027 }
660 }, 1028 },
661 1029
662 /** 1030 /**
663 * Called when the display arrangement has changed. 1031 * Called when the display arrangement has changed.
664 * @private
665 * @param {boolean} mirroring Whether current mode is mirroring or not. 1032 * @param {boolean} mirroring Whether current mode is mirroring or not.
666 * @param {Array} displays The list of the display information. 1033 * @param {Array} displays The list of the display information.
667 * @param {SecondaryDisplayLayout} layout The layout strategy. 1034 * @param {SecondaryDisplayLayout} layout The layout strategy.
668 * @param {number} offset The offset of the secondary display. 1035 * @param {number} offset The offset of the secondary display.
1036 * @private
669 */ 1037 */
670 onDisplayChanged_: function(mirroring, displays, layout, offset) { 1038 onDisplayChanged_: function(mirroring, displays, layout, offset) {
671 this.mirroring_ = mirroring; 1039 this.mirroring_ = mirroring;
672 this.layout_ = layout; 1040 this.layout_ = layout;
673 this.offset_ = offset; 1041 this.offset_ = offset;
674 this.dirty_ = false; 1042 this.dirty_ = false;
675 1043
676 $('display-options-toggle-mirroring').textContent = 1044 $('display-options-toggle-mirroring').textContent =
677 loadTimeData.getString( 1045 loadTimeData.getString(
678 this.mirroring_ ? 'stopMirroring' : 'startMirroring'); 1046 this.mirroring_ ? 'stopMirroring' : 'startMirroring');
679 1047
680 // Focus to the first display next to the primary one when |displays| list 1048 // Focus to the first display next to the primary one when |displays| list
681 // is updated. 1049 // is updated.
682 if (this.mirroring_) 1050 if (this.mirroring_)
683 this.focusedIndex_ = null; 1051 this.focusedIndex_ = null;
684 else if (this.displays_.length != displays.length) 1052 else if (this.displays_.length != displays.length)
685 this.focusedIndex_ = 1; 1053 this.focusedIndex_ = 1;
686 1054
687 this.displays_ = displays; 1055 this.displays_ = displays;
688 1056
689 this.resetDisplaysView_(); 1057 this.resetDisplaysView_();
690 if (this.mirroring_) 1058 if (this.mirroring_)
691 this.layoutMirroringDisplays_(); 1059 this.layoutMirroringDisplays_();
692 else 1060 else
693 this.layoutDisplays_(); 1061 this.layoutDisplays_();
1062
1063 if (this.overscanCalibrator_) {
1064 this.overscanCalibrator_.Finish();
1065 this.overscanCalibrator_ = new DisplayOverscanCalibrator(
1066 this.displays_[this.focusedIndex_]);
1067 }
694 this.updateSelectedDisplayDescription_(); 1068 this.updateSelectedDisplayDescription_();
695 } 1069 }
696 }; 1070 };
697 1071
698 DisplayOptions.setDisplayInfo = function( 1072 DisplayOptions.setDisplayInfo = function(
699 mirroring, displays, layout, offset) { 1073 mirroring, displays, layout, offset) {
700 DisplayOptions.getInstance().onDisplayChanged_( 1074 DisplayOptions.getInstance().onDisplayChanged_(
701 mirroring, displays, layout, offset); 1075 mirroring, displays, layout, offset);
702 }; 1076 };
703 1077
704 // Export 1078 // Export
705 return { 1079 return {
706 DisplayOptions: DisplayOptions 1080 DisplayOptions: DisplayOptions
707 }; 1081 };
708 }); 1082 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698