diff options
10 files changed, 544 insertions, 28 deletions
diff --git a/chrome/browser/resources/options/browser_options.js b/chrome/browser/resources/options/browser_options.js index d6e92d6..c5347ef 100644 --- a/chrome/browser/resources/options/browser_options.js +++ b/chrome/browser/resources/options/browser_options.js @@ -1735,12 +1735,17 @@ cr.define('options', function() { /** * Enables or disables the Chrome OS display settings button and overlay. + * @param {boolean} enabled + * @param {boolean} showUnifiedDesktop + * @param {boolean} multiDisplayLayout * @private */ - enableDisplaySettings_: function(enabled, showUnifiedDesktop) { + enableDisplaySettings_: function( + enabled, showUnifiedDesktop, multiDisplayLayout) { if (cr.isChromeOS) { $('display-options').disabled = !enabled; - DisplayOptions.getInstance().setEnabled(enabled, showUnifiedDesktop); + DisplayOptions.getInstance().setEnabled( + enabled, showUnifiedDesktop, multiDisplayLayout); } }, diff --git a/chrome/browser/resources/options/chromeos/display_layout.js b/chrome/browser/resources/options/chromeos/display_layout.js index ea6bf76..f7506d66 100644 --- a/chrome/browser/resources/options/chromeos/display_layout.js +++ b/chrome/browser/resources/options/chromeos/display_layout.js @@ -44,21 +44,28 @@ cr.define('options', function() { * @param {number} width The width of the region. * @param {number} basePoint The starting point of the base region. * @param {number} baseWidth The width of the base region. + * @param {number=} opt_snapDistance Provide to override the snap distance. + * 0 means snap at any distance. * @return {number} The moved point. Returns the point itself if it doesn't * need to snap to the edge. * @private */ - function snapToEdge(point, width, basePoint, baseWidth) { + function snapToEdge_(point, width, basePoint, baseWidth, opt_snapDistance) { // If the edge of the region is smaller than this, it will snap to the // base's edge. /** @const */ var SNAP_DISTANCE_PX = 16; + var snapDist; + if (opt_snapDistance !== undefined) + snapDist = opt_snapDistance; + else + snapDist = SNAP_DISTANCE_PX; var startDiff = Math.abs(point - basePoint); var endDiff = Math.abs(point + width - (basePoint + baseWidth)); // Prefer the closer one if both edges are close enough. - if (startDiff < SNAP_DISTANCE_PX && startDiff < endDiff) + if ((!snapDist || startDiff < snapDist) && startDiff < endDiff) return basePoint; - else if (endDiff < SNAP_DISTANCE_PX) + else if (!snapDist || endDiff < snapDist) return basePoint + baseWidth - width; return point; @@ -150,9 +157,9 @@ cr.define('options', function() { }, /** - * Calculates the offset for displayLayout relative to its parent. + * Calculates the offset relative to |parent|. * @param {number} scale - * @param {options.DisplayLayout} parent + * @param {?options.DisplayLayout} parent */ calculateOffset: function(scale, parent) { // Offset is calculated from top or left edge. @@ -172,12 +179,67 @@ cr.define('options', function() { }, /** + * Calculates the bounds relative to |parentBounds|. + * @param {!options.DisplayBounds} parentBounds + * @return {!options.DisplayBounds} + */ + calculateBounds: function(parentBounds) { + var left = 0, top = 0; + switch (this.layoutType) { + case options.DisplayLayoutType.TOP: + left = parentBounds.left + this.offset; + top = parentBounds.top - this.bounds.height; + break; + case options.DisplayLayoutType.RIGHT: + left = parentBounds.left + parentBounds.width; + top = parentBounds.top + this.offset; + break; + case options.DisplayLayoutType.BOTTOM: + left = parentBounds.left + this.offset; + top = parentBounds.top + parentBounds.height; + break; + case options.DisplayLayoutType.LEFT: + left = parentBounds.left - this.bounds.width; + top = parentBounds.top + this.offset; + break; + } + return { + left: left, + top: top, + width: this.bounds.width, + height: this.bounds.height + }; + }, + + /** + * Snap |newPosition| to the edge specified by |layoutType| and call + * setDivPosition. + * @param {options.DisplayPosition} newPosition + * @param {?HTMLElement} parentDiv + * @param {!options.DisplayLayoutType} layoutType + */ + snapAndSetDivPosition(newPosition, parentDiv, layoutType) { + var snapX = (layoutType == options.DisplayLayoutType.LEFT || + layoutType == options.DisplayLayoutType.RIGHT) ? + 0 /* infinite */ : + undefined /* default */; + var snapY = (layoutType == options.DisplayLayoutType.TOP || + layoutType == options.DisplayLayoutType.BOTTOM) ? + 0 /* infinite */ : + undefined /* default */; + + newPosition.x = this.snapToX(newPosition.x, parentDiv, snapX); + newPosition.y = this.snapToY(newPosition.y, parentDiv, snapY); + + this.setDivPosition(newPosition, parentDiv, layoutType); + }, + + /** * Update the div location to the position closest to |newPosition| along * the edge of |parentDiv| specified by |layoutType|. * @param {options.DisplayPosition} newPosition * @param {?HTMLElement} parentDiv * @param {!options.DisplayLayoutType} layoutType - * @private */ setDivPosition(newPosition, parentDiv, layoutType) { var div = this.div; @@ -205,7 +267,6 @@ cr.define('options', function() { * Ensures that there is a minimum overlap when displays meet at a corner. * @param {?HTMLElement} parentDiv * @param {options.DisplayLayoutType} layoutType - * @private */ adjustCorners: function(parentDiv, layoutType) { // The number of pixels to share the edges between displays. @@ -233,29 +294,73 @@ cr.define('options', function() { }, /** + * Calculates the layoutType for |position| relative to |parentDiv|. + * @param {?HTMLElement} parentDiv + * @param {!options.DisplayPosition} position + * @return {options.DisplayLayoutType} + */ + getLayoutTypeForPosition: function(parentDiv, position) { + var div = this.div; + + // Translate position from top-left to center. + var x = position.x + div.offsetWidth / 2; + var y = position.y + div.offsetHeight / 2; + + // Determine the distance from the new position to both of the near edges. + var div = parentDiv; + var left = div.offsetLeft; + var top = div.offsetTop; + var width = div.offsetWidth; + var height = div.offsetHeight; + + // Signed deltas to the center of the div. + var dx = x - (left + width / 2); + var dy = y - (top + height / 2); + + // Unsigned distance to each edge. + var distx = Math.abs(dx) - width / 2; + var disty = Math.abs(dy) - height / 2; + + if (distx > disty) { + if (dx < 0) + return options.DisplayLayoutType.LEFT; + else + return options.DisplayLayoutType.RIGHT; + } else { + if (dy < 0) + return options.DisplayLayoutType.TOP; + else + return options.DisplayLayoutType.BOTTOM; + } + }, + + /** * Snaps a horizontal value, see SnapToEdge. * @param {number} x * @param {?HTMLElement} parentDiv + * @param {number=} opt_snapDistance Provide to override the snap distance. + * 0 means snap from any distance. * @return {number} - * @private */ - snapToX: function(x, parentDiv) { - return snapToEdge( - x, this.div.offsetWidth, parentDiv.offsetLeft, parentDiv.offsetWidth); + snapToX: function(x, parentDiv, opt_snapDistance) { + return snapToEdge_( + x, this.div.offsetWidth, parentDiv.offsetLeft, parentDiv.offsetWidth, + opt_snapDistance); }, /** * Snaps a vertical value, see SnapToEdge. * @param {number} y * @param {?HTMLElement} parentDiv + * @param {number=} opt_snapDistance Provide to override the snap distance. + * 0 means snap from any distance. * @return {number} - * @private */ - snapToY: function(y, parentDiv) { - return snapToEdge( - y, this.div.offsetHeight, parentDiv.offsetTop, - parentDiv.offsetHeight); - }, + snapToY: function(y, parentDiv, opt_snapDistance) { + return snapToEdge_( + y, this.div.offsetHeight, parentDiv.offsetTop, parentDiv.offsetHeight, + opt_snapDistance); + } }; // Export diff --git a/chrome/browser/resources/options/chromeos/display_layout_manager.js b/chrome/browser/resources/options/chromeos/display_layout_manager.js index 54ba6a1..c51cbdc 100644 --- a/chrome/browser/resources/options/chromeos/display_layout_manager.js +++ b/chrome/browser/resources/options/chromeos/display_layout_manager.js @@ -151,8 +151,10 @@ cr.define('options', function() { * Sets the display layout div corresponding to |id| to focused and * sets all other display layouts to unfocused. * @param {string} focusedId + * @param {boolean=} opt_userAction If true, focus was triggered by a + * user action. (Used in DisplayLayoutManagerMulti override). */ - setFocusedId: function(focusedId) { + setFocusedId: function(focusedId, opt_userAction) { for (var id in this.displayLayoutMap_) { var layout = this.displayLayoutMap_[id]; layout.div.classList.toggle('displays-focused', layout.id == focusedId); diff --git a/chrome/browser/resources/options/chromeos/display_layout_manager_multi.js b/chrome/browser/resources/options/chromeos/display_layout_manager_multi.js new file mode 100644 index 0000000..b5cc4ab --- /dev/null +++ b/chrome/browser/resources/options/chromeos/display_layout_manager_multi.js @@ -0,0 +1,366 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +cr.exportPath('options'); + +cr.define('options', function() { + 'use strict'; + + var DisplayLayoutManager = options.DisplayLayoutManager; + + /** @const */ var FAKE_ID_PREFIX = 'fakeId'; + var fakeDisplayNum = 3; + var fakeDisplays = []; + + /** + * @constructor + * @extends {options.DisplayLayoutManager} + */ + function DisplayLayoutManagerMulti() { DisplayLayoutManager.call(this); } + + // Helper class for display layout management. Implements logic for laying + // out 3+ displays. + DisplayLayoutManagerMulti.prototype = { + __proto__: DisplayLayoutManager.prototype, + + /** @type {string} */ + dragId_: '', + + /** @type {string} */ + dragParentId_: '', + + /** @type {options.DisplayLayoutType} */ + dragLayoutType_: options.DisplayLayoutType.RIGHT, + + /** @override */ + createDisplayArea: function(displayAreaDiv, minVisualScale) { + // Add fake displays just before creating divs. + this.createFakeDisplays_(fakeDisplayNum); + for (var i = 0; i < fakeDisplayNum; ++i) { + var fake = fakeDisplays[i]; + this.displayLayoutMap_[fake.id] = fake; + } + return DisplayLayoutManager.prototype.createDisplayArea.call( + this, displayAreaDiv, minVisualScale); + }, + + /** @override */ + setFocusedId: function(focusedId, opt_userAction) { + DisplayLayoutManager.prototype.setFocusedId.call(this, focusedId); + if (!opt_userAction || this.dragId_ != '') + return; + var layout = this.displayLayoutMap_[focusedId]; + this.highlightEdge_(layout.parentId, layout.layoutType); + }, + + /** @override */ + updatePosition: function(id, newPosition) { + this.dragId_ = id; + // Find the closest parent. + var layout = this.displayLayoutMap_[id]; + this.dragParentId_ = this.findClosest_(layout, newPosition); + var parent = this.displayLayoutMap_[this.dragParentId_]; + + // Find the closest edge. + this.dragLayoutType_ = + layout.getLayoutTypeForPosition(parent.div, newPosition); + + // Update the div (but not the actual layout type or offset yet), + layout.snapAndSetDivPosition( + newPosition, parent.div, this.dragLayoutType_); + + this.highlightEdge_(this.dragParentId_, this.dragLayoutType_); + }, + + /** @override */ + finalizePosition: function(id) { + if (id != this.dragId_) { + this.dragId_ = ''; + return false; + } + + var layout = this.displayLayoutMap_[id]; + + // All immediate children of |layout| will need to be re-parented. + var orphanIds = this.findChildren_(id, false /* do not recurse */); + + if (layout.parentId == '') { + // We can not re-parent the primary display, so instead re-parent the + // "drag parent" to the primary display and make all other displays + // orphans. + orphanIds = this.findChildren_(id, true /* recurse */); + + // Remove the "drag parent" from the orphans list and reparent it first. + var index = orphanIds.indexOf(this.dragParentId_); + assert(index != -1); + orphanIds.splice(index, 1); + this.reparentOrphan_(this.dragParentId_, orphanIds); + } else { + var dragParent = this.displayLayoutMap_[this.dragParentId_]; + + // Special case: re-parenting to a descendant. Parent the immediate + // child (the 'top parent') to the dragged display's current parent. + var topParent = dragParent; + while (topParent) { + if (topParent.parentId == '') + break; + if (topParent.parentId == id) { + topParent.parentId = layout.parentId; + break; + } + topParent = this.displayLayoutMap_[topParent.parentId]; + } + + // Re-parent the dragged display. + layout.parentId = this.dragParentId_; + layout.layoutType = this.dragLayoutType_; + + // Snap to corners and calculate the offset from the new parent. + // This does not depend on any unresolved child layout. + layout.adjustCorners(dragParent.div, this.dragLayoutType_); + layout.calculateOffset(this.visualScale_, dragParent); + } + + // Update any orphaned children. This may cause the dragged display to + // be re-attached if it was attached to a child. + this.updateOrphans_(orphanIds); + + // Update the fake displays. + for (var i = 0; i < fakeDisplayNum; ++i) { + var fakeId = fakeDisplays[i].id; + var current = this.displayLayoutMap_[fakeId]; + var bounds = /** @type {!options.DisplayBounds} */ ( + this.calcLayoutBounds_(current)); + fakeDisplays[i] = new options.DisplayLayout( + current.id, current.name, bounds, current.layoutType, + current.parentId); + } + + this.highlightEdge_('', undefined); // Remove any highlights. + this.dragId_ = ''; + + return layout.originalDivOffsets.x != layout.div.offsetLeft || + layout.originalDivOffsets.y != layout.div.offsetTop; + }, + + /** + * Re-parent all entries in |orphanIds| and any children. + * @param {Array<string>} orphanIds The list of ids affected by the move. + * @private + */ + updateOrphans_: function(orphanIds) { + var orphans = orphanIds.slice(); + for (var orphan of orphanIds) { + var newOrphans = this.findChildren_(orphan, true /* recurse */); + // If the dragged display was re-parented to one of its children, + // there may be duplicates so merge the lists. + for (var o of newOrphans) { + if (orphans.indexOf(o) == -1) + orphans.push(o); + } + } + + // Remove each orphan from the list as it is re-parented so that + // subsequent orphans can be parented to it. + while (orphans.length) { + var orphanId = orphans.shift(); + this.reparentOrphan_(orphanId, orphans); + } + }, + + /** + * Re-parent the orphan to a layout that is not a member of + * |otherOrphanIds|. + * @param {string} orphanId The id of the orphan to re-parent. + * @param {Array<string>} otherOrphanIds The list of ids of other orphans + * to ignore when re-parenting. + * @private + */ + reparentOrphan_: function(orphanId, otherOrphanIds) { + var orphan = this.displayLayoutMap_[orphanId]; + + if (orphanId == this.dragId_ && orphan.parentId != '') { + // Preserve the layout and offset of the dragged div. + var parent = this.displayLayoutMap_[orphan.parentId]; + orphan.bounds = this.calcLayoutBounds_(orphan); + orphan.layoutDivFromBounds( + this.displayAreaOffset_, this.visualScale_, parent); + return; + } + + // Find the closest parent. + var pos = {x: orphan.div.offsetLeft, y: orphan.div.offsetTop}; + var newParentId = this.findClosest_(orphan, pos, otherOrphanIds); + orphan.parentId = newParentId; + assert(newParentId != ''); + var parent = this.displayLayoutMap_[newParentId]; + + // Find the closest edge. + orphan.layoutType = orphan.getLayoutTypeForPosition(parent.div, pos); + + // Update the div and adjust the corners. + orphan.snapAndSetDivPosition(pos, parent.div, orphan.layoutType); + orphan.adjustCorners(parent.div, orphan.layoutType); + + // Calculate the bounds from the new div position. + orphan.calculateOffset(this.visualScale_, parent); + + // TODO(stevenjb): Set bounds and send orphan update. + }, + + /** + * @param {string} parentId + * @param {boolean} recurse Include descendants of children. + * @return {!Array<string>} + * @private + */ + findChildren_: function(parentId, recurse) { + var children = []; + for (var childId in this.displayLayoutMap_) { + if (childId == parentId) + continue; + if (this.displayLayoutMap_[childId].parentId == parentId) { + // Insert immediate children at the front of the array. + children.unshift(childId); + if (recurse) { + // Descendants get added to the end of the list. + children = children.concat(this.findChildren_(childId, true)); + } + } + } + return children; + }, + + /** + * Finds the display closest to |position| ignoring |child|. + * @param {!options.DisplayLayout} child + * @param {!options.DisplayPosition} position + * @param {Array<string>=} opt_ignoreIds Ids to ignore. + * @return {string} + * @private + */ + findClosest_: function(child, position, opt_ignoreIds) { + var x = position.x + child.div.offsetWidth / 2; + var y = position.y + child.div.offsetHeight / 2; + var closestId = ''; + var closestDelta2 = 0; + for (var id in this.displayLayoutMap_) { + if (id == child.id) + continue; + if (opt_ignoreIds && opt_ignoreIds.indexOf(id) != -1) + continue; + var div = this.displayLayoutMap_[id].div; + var left = div.offsetLeft; + var top = div.offsetTop; + var width = div.offsetWidth; + var height = div.offsetHeight; + if (x >= left && x < left + width && y >= top && y < top + height) + return id; // point is inside rect + var dx, dy; + if (x < left) + dx = left - x; + else if (x > left + width) + dx = x - (left + width); + else + dx = 0; + if (y < top) + dy = top - y; + else if (y > top + height) + dy = y - (top + height); + else + dy = 0; + var delta2 = dx * dx + dy * dy; + if (closestId == '' || delta2 < closestDelta2) { + closestId = id; + closestDelta2 = delta2; + } + } + return closestId; + }, + + /** + * Highlights the edge of the div associated with |parentId| based on + * |layoutType| and removes any other highlights. If |layoutType| is + * undefined, removes all highlights. + * @param {string} id + * @param {options.DisplayLayoutType|undefined} layoutType + * @private + */ + highlightEdge_: function(id, layoutType) { + for (var tid in this.displayLayoutMap_) { + var tlayout = this.displayLayoutMap_[tid]; + var highlight = ''; + if (tlayout.id == id) { + switch (layoutType) { + case options.DisplayLayoutType.RIGHT: + highlight = 'displays-parent-right'; + break; + case options.DisplayLayoutType.LEFT: + highlight = 'displays-parent-left'; + break; + case options.DisplayLayoutType.TOP: + highlight = 'displays-parent-top'; + break; + case options.DisplayLayoutType.BOTTOM: + highlight = 'displays-parent-bottom'; + break; + } + } + tlayout.div.classList.toggle( + 'displays-parent-right', highlight == 'displays-parent-right'); + tlayout.div.classList.toggle( + 'displays-parent-left', highlight == 'displays-parent-left'); + tlayout.div.classList.toggle( + 'displays-parent-top', highlight == 'displays-parent-top'); + tlayout.div.classList.toggle( + 'displays-parent-bottom', highlight == 'displays-parent-bottom'); + } + }, + + /** + * Calculates but do not set the div bound. + * @param {!options.DisplayLayout} layout + * @return {!options.DisplayBounds} + */ + calcLayoutBounds_: function(layout) { + if (layout.parentId == '') + return /** @type {!options.DisplayBounds} */ (layout.bounds); + var parent = this.displayLayoutMap_[layout.parentId]; + // Parent layout bounds may not be calculated yet, so calculate (but + // do not set) them. + var parentBounds = this.calcLayoutBounds_(parent); + return layout.calculateBounds(parentBounds); + }, + + /** + * @param {number} num + */ + createFakeDisplays_: function(num) { + if (num != fakeDisplayNum) + fakeDisplays = []; + var primary; + for (var id in this.displayLayoutMap_) { + var layout = this.displayLayoutMap_[id]; + if (layout.parentId == '') + primary = layout; + } + for (var i = 0; i < num; ++i) { + if (i < fakeDisplays.length) { + fakeDisplays[i].div = null; + } else { + var fakeId = FAKE_ID_PREFIX + i; + var layoutType = /** @type {options.DisplayLayoutType} */ (i % 4); + var bounds = /** @type {!options.DisplayBounds} */ (primary.bounds); + var fakeDisplayLayout = new options.DisplayLayout( + fakeId, 'Fake Display ' + i, bounds, layoutType, primary.id); + fakeDisplayLayout.bounds = this.calcLayoutBounds_(fakeDisplayLayout); + fakeDisplays.push(fakeDisplayLayout); + } + } + } + }; + + // Export + return {DisplayLayoutManagerMulti: DisplayLayoutManagerMulti}; +}); diff --git a/chrome/browser/resources/options/chromeos/display_options.css b/chrome/browser/resources/options/chromeos/display_options.css index de3995f..36b6332 100644 --- a/chrome/browser/resources/options/chromeos/display_options.css +++ b/chrome/browser/resources/options/chromeos/display_options.css @@ -93,6 +93,22 @@ color: rgb(0, 138, 255); } +.displays-parent-left { + border-left: solid 1px rgb(255, 138, 0); +} + +.displays-parent-right { + border-right: solid 1px rgb(255, 138, 0); +} + +.displays-parent-top { + border-top: solid 1px rgb(255, 138, 0); +} + +.displays-parent-bottom { + border-bottom: solid 1px rgb(255, 138, 0); +} + #display-options-select-mirroring { margin-right: 5px; } diff --git a/chrome/browser/resources/options/chromeos/display_options.js b/chrome/browser/resources/options/chromeos/display_options.js index 778b21c..b90e346 100644 --- a/chrome/browser/resources/options/chromeos/display_options.js +++ b/chrome/browser/resources/options/chromeos/display_options.js @@ -106,6 +106,13 @@ cr.define('options', function() { displays_: [], /** + * Whether to use DisplayLayoutManagerMulti. + * @type {boolean} + * @private + */ + multiDisplayLayout_: false, + + /** * Manages the display layout. * @type {?options.DisplayLayoutManager} * @private @@ -234,14 +241,15 @@ cr.define('options', function() { * @param {boolean} enabled Whether the page should be enabled. * @param {boolean} showUnifiedDesktop Whether the unified desktop option * should be present. + * @param {boolean} multiDisplayLayout Whether to use + * DisplayLayoutManagerMulti. */ - setEnabled: function(enabled, showUnifiedDesktop) { - if (this.enabled_ == enabled && - this.showUnifiedDesktopOption_ == showUnifiedDesktop) { + setEnabled: function(enabled, showUnifiedDesktop, multiDisplayLayout) { + this.showUnifiedDesktopOption_ = showUnifiedDesktop; + this.multiDisplayLayout_ = multiDisplayLayout; + if (this.enabled_ == enabled) return; - } this.enabled_ = enabled; - this.showUnifiedDesktopOption_ = showUnifiedDesktop; if (!enabled && this.visible) PageManager.closeOverlay(); }, @@ -389,7 +397,8 @@ cr.define('options', function() { var updateDisplayDescription = focused.id != this.focusedId_; this.focusedId_ = focused.id; - this.displayLayoutManager_.setFocusedId(focused.id); + this.displayLayoutManager_.setFocusedId( + focused.id, true /* user action */); if (this.displayLayoutManager_.getDisplayLayoutCount() > 1) { this.dragInfo_ = { @@ -639,7 +648,10 @@ cr.define('options', function() { */ layoutDisplays_: function(layoutType) { // Create the layout manager. - this.displayLayoutManager_ = new options.DisplayLayoutManager(); + if (this.multiDisplayLayout_) + this.displayLayoutManager_ = new options.DisplayLayoutManagerMulti(); + else + this.displayLayoutManager_ = new options.DisplayLayoutManager(); // Create the display layouts. Child displays are parented to the primary. // TODO(stevenjb): DisplayInfo should provide the parent id for displays. diff --git a/chrome/browser/resources/options/options_bundle.js b/chrome/browser/resources/options/options_bundle.js index 7e14154..811c5f0 100644 --- a/chrome/browser/resources/options/options_bundle.js +++ b/chrome/browser/resources/options/options_bundle.js @@ -34,6 +34,7 @@ <include src="chromeos/consumer_management_overlay.js"> <include src="chromeos/display_layout.js"> <include src="chromeos/display_layout_manager.js"> +<include src="chromeos/display_layout_manager_multi.js"> <include src="chromeos/display_options.js"> <include src="chromeos/display_overscan.js"> <include src="chromeos/keyboard_overlay.js"> diff --git a/chrome/browser/ui/webui/options/chromeos/display_options_handler.cc b/chrome/browser/ui/webui/options/chromeos/display_options_handler.cc index 5813b42..1396536 100644 --- a/chrome/browser/ui/webui/options/chromeos/display_options_handler.cc +++ b/chrome/browser/ui/webui/options/chromeos/display_options_handler.cc @@ -17,12 +17,14 @@ #include "ash/screen_util.h" #include "ash/shell.h" #include "base/bind.h" +#include "base/command_line.h" #include "base/logging.h" #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" #include "base/values.h" #include "chrome/browser/chromeos/display/display_preferences.h" #include "chrome/grit/generated_resources.h" +#include "chromeos/chromeos_switches.h" #include "content/public/browser/user_metrics.h" #include "content/public/browser/web_ui.h" #include "grit/ash_strings.h" @@ -346,11 +348,14 @@ void DisplayOptionsHandler::SendDisplayInfo( void DisplayOptionsHandler::UpdateDisplaySettingsEnabled() { bool enabled = GetDisplayManager()->num_connected_displays() <= 2; bool show_unified_desktop = GetDisplayManager()->unified_desktop_enabled(); + bool multi_display_layout = base::CommandLine::ForCurrentProcess()->HasSwitch( + chromeos::switches::kEnableMultiDisplayLayout); web_ui()->CallJavascriptFunction( "options.BrowserOptions.enableDisplaySettings", base::FundamentalValue(enabled), - base::FundamentalValue(show_unified_desktop)); + base::FundamentalValue(show_unified_desktop), + base::FundamentalValue(multi_display_layout)); } void DisplayOptionsHandler::HandleDisplayInfo( diff --git a/chromeos/chromeos_switches.cc b/chromeos/chromeos_switches.cc index b148ac7..afb9b83f 100644 --- a/chromeos/chromeos_switches.cc +++ b/chromeos/chromeos_switches.cc @@ -158,6 +158,9 @@ const char kEnableScreenshotTestingWithMode[] = // than the kiosk app mode. const char kEnableKioskMode[] = "enable-kiosk-mode"; +// Enable the multiple display layout UI. +const char kEnableMultiDisplayLayout[] = "enable-multi-display-layout"; + // Enables request of tablet site (via user agent override). const char kEnableRequestTabletSite[] = "enable-request-tablet-site"; diff --git a/chromeos/chromeos_switches.h b/chromeos/chromeos_switches.h index 87e7a4c..ee53d4e 100644 --- a/chromeos/chromeos_switches.h +++ b/chromeos/chromeos_switches.h @@ -63,6 +63,7 @@ CHROMEOS_EXPORT extern const char kEnableExtensionAssetsSharing[]; CHROMEOS_EXPORT extern const char kEnableFirstRunUITransitions[]; CHROMEOS_EXPORT extern const char kEnableImeMenu[]; CHROMEOS_EXPORT extern const char kEnableKioskMode[]; +CHROMEOS_EXPORT extern const char kEnableMultiDisplayLayout[]; CHROMEOS_EXPORT extern const char kEnableNetworkPortalNotification[]; CHROMEOS_EXPORT extern const char kDisableNewKoreanIme[]; CHROMEOS_EXPORT extern const char kEnablePhysicalKeyboardAutocorrect[]; |