Index: ash/display/display_controller.cc |
diff --git a/ash/display/display_controller.cc b/ash/display/display_controller.cc |
index 1a2ed6357271470d291e1762b909be87893996cc..16ee88ca900717390d58ab4d824ed5df8faf5193 100644 |
--- a/ash/display/display_controller.cc |
+++ b/ash/display/display_controller.cc |
@@ -15,6 +15,9 @@ |
#include "ash/wm/property_util.h" |
#include "ash/wm/window_util.h" |
#include "base/command_line.h" |
+#include "base/json/json_value_converter.h" |
+#include "base/string_piece.h" |
+#include "base/values.h" |
#include "ui/aura/client/screen_position_client.h" |
#include "ui/aura/env.h" |
#include "ui/aura/root_window.h" |
@@ -28,18 +31,102 @@ |
#endif |
namespace ash { |
-namespace internal { |
namespace { |
+// The maximum value for 'offset' in DisplayLayout in case of outliers. Need |
+// to change this value in case to support even larger displays. |
+const int kMaxValidOffset = 10000; |
+ |
// The number of pixels to overlap between the primary and secondary displays, |
// in case that the offset value is too large. |
const int kMinimumOverlapForInvalidOffset = 50; |
+bool GetPositionFromString(const base::StringPiece& position, |
+ DisplayLayout::Position* field) { |
+ if (position == "top") { |
+ *field = DisplayLayout::TOP; |
+ return true; |
+ } else if (position == "bottom") { |
+ *field = DisplayLayout::BOTTOM; |
+ return true; |
+ } else if (position == "right") { |
+ *field = DisplayLayout::RIGHT; |
+ return true; |
+ } else if (position == "left") { |
+ *field = DisplayLayout::LEFT; |
+ return true; |
+ } |
+ LOG(ERROR) << "Invalid position value: " << position; |
+ |
+ return false; |
+} |
+ |
+} // namespace |
+ |
+DisplayLayout::DisplayLayout() |
+ : position(RIGHT), |
+ offset(0) {} |
+ |
+DisplayLayout::DisplayLayout(DisplayLayout::Position position, int offset) |
+ : position(position), |
+ offset(offset) { |
+ DCHECK_LE(TOP, position); |
+ DCHECK_GE(LEFT, position); |
+ |
+ // Set the default value to |position| in case position is invalid. DCHECKs |
+ // above doesn't stop in Release builds. |
+ if (TOP > position || LEFT < position) |
+ this->position = RIGHT; |
+ |
+ DCHECK_GE(kMaxValidOffset, abs(offset)); |
+} |
+ |
+// static |
+bool DisplayLayout::ConvertFromValue(const base::Value& value, |
+ DisplayLayout* layout) { |
+ base::JSONValueConverter<DisplayLayout> converter; |
+ return converter.Convert(value, layout); |
+} |
+ |
+// static |
+bool DisplayLayout::ConvertToValue(const DisplayLayout& layout, |
+ base::Value* value) { |
+ base::DictionaryValue* dict_value = NULL; |
+ if (!value->GetAsDictionary(&dict_value) || dict_value == NULL) |
+ return false; |
+ |
+ std::string position_value; |
+ switch (layout.position) { |
+ case TOP: |
+ position_value = "top"; |
+ break; |
+ case BOTTOM: |
+ position_value = "bottom"; |
+ break; |
+ case RIGHT: |
+ position_value = "right"; |
+ break; |
+ case LEFT: |
+ position_value = "left"; |
+ break; |
+ default: |
+ return false; |
+ } |
+ |
+ dict_value->SetString("position", position_value); |
+ dict_value->SetInteger("offset", layout.offset); |
+ return true; |
+} |
+ |
+// static |
+void DisplayLayout::RegisterJSONConverter( |
+ base::JSONValueConverter<DisplayLayout>* converter) { |
+ converter->RegisterCustomField<Position>( |
+ "position", &DisplayLayout::position, &GetPositionFromString); |
+ converter->RegisterIntField("offset", &DisplayLayout::offset); |
} |
-DisplayController::DisplayController() |
- : secondary_display_layout_(RIGHT), |
- secondary_display_offset_(0) { |
+DisplayController::DisplayController() { |
aura::Env::GetInstance()->display_manager()->AddObserver(this); |
} |
@@ -80,14 +167,14 @@ void DisplayController::InitSecondaryDisplays() { |
int offset; |
if (sscanf(value.c_str(), "%c,%d", &layout, &offset) == 2) { |
if (layout == 't') |
- secondary_display_layout_ = TOP; |
+ default_display_layout_.position = DisplayLayout::TOP; |
else if (layout == 'b') |
- secondary_display_layout_ = BOTTOM; |
+ default_display_layout_.position = DisplayLayout::BOTTOM; |
else if (layout == 'r') |
- secondary_display_layout_ = RIGHT; |
+ default_display_layout_.position = DisplayLayout::RIGHT; |
else if (layout == 'l') |
- secondary_display_layout_ = LEFT; |
- secondary_display_offset_ = offset; |
+ default_display_layout_.position = DisplayLayout::LEFT; |
+ default_display_layout_.offset = offset; |
} |
} |
UpdateDisplayBoundsForLayout(); |
@@ -145,17 +232,26 @@ DisplayController::GetAllRootWindowControllers() { |
return controllers; |
} |
-void DisplayController::SetSecondaryDisplayLayout( |
- SecondaryDisplayLayout layout) { |
- secondary_display_layout_ = layout; |
+void DisplayController::SetDefaultDisplayLayout(const DisplayLayout& layout) { |
+ default_display_layout_ = layout; |
UpdateDisplayBoundsForLayout(); |
} |
-void DisplayController::SetSecondaryDisplayOffset(int offset) { |
- secondary_display_offset_ = offset; |
+void DisplayController::SetLayoutForDisplayName(const std::string& name, |
+ const DisplayLayout& layout) { |
+ secondary_layouts_[name] = layout; |
UpdateDisplayBoundsForLayout(); |
} |
+const DisplayLayout& DisplayController::GetLayoutForDisplayName( |
+ const std::string& name) { |
+ std::map<std::string, DisplayLayout>::const_iterator it = |
+ secondary_layouts_.find(name); |
+ |
+ if (it != secondary_layouts_.end()) |
+ return it->second; |
+ return default_display_layout_; |
+} |
void DisplayController::OnDisplayBoundsChanged(const gfx::Display& display) { |
root_windows_[display.id()]->SetHostBounds(display.bounds_in_pixel()); |
@@ -215,13 +311,22 @@ void DisplayController::UpdateDisplayBoundsForLayout() { |
aura::Env::GetInstance()->display_manager(); |
const gfx::Rect& primary_bounds = display_manager->GetDisplayAt(0)->bounds(); |
gfx::Display* secondary_display = display_manager->GetDisplayAt(1); |
+ const std::string& secondary_name = display_manager->GetDisplayNameAt(1); |
const gfx::Rect& secondary_bounds = secondary_display->bounds(); |
gfx::Point new_secondary_origin = primary_bounds.origin(); |
+ const DisplayLayout* layout = &default_display_layout_; |
+ std::map<std::string, DisplayLayout>::const_iterator iter = |
+ secondary_layouts_.find(secondary_name); |
+ if (iter != secondary_layouts_.end()) |
+ layout = &iter->second; |
+ |
+ DisplayLayout::Position position = layout->position; |
+ |
// Ignore the offset in case the secondary display doesn't share edges with |
// the primary display. |
- int offset = secondary_display_offset_; |
- if (secondary_display_layout_ == TOP || secondary_display_layout_ == BOTTOM) { |
+ int offset = layout->offset; |
+ if (position == DisplayLayout::TOP || position == DisplayLayout::BOTTOM) { |
offset = std::min( |
offset, primary_bounds.width() - kMinimumOverlapForInvalidOffset); |
offset = std::max( |
@@ -232,17 +337,17 @@ void DisplayController::UpdateDisplayBoundsForLayout() { |
offset = std::max( |
offset, -secondary_bounds.height() + kMinimumOverlapForInvalidOffset); |
} |
- switch (secondary_display_layout_) { |
- case TOP: |
+ switch (position) { |
+ case DisplayLayout::TOP: |
new_secondary_origin.Offset(offset, -secondary_bounds.height()); |
break; |
- case RIGHT: |
+ case DisplayLayout::RIGHT: |
new_secondary_origin.Offset(primary_bounds.width(), offset); |
break; |
- case BOTTOM: |
+ case DisplayLayout::BOTTOM: |
new_secondary_origin.Offset(offset, primary_bounds.height()); |
break; |
- case LEFT: |
+ case DisplayLayout::LEFT: |
new_secondary_origin.Offset(-secondary_bounds.width(), offset); |
break; |
} |
@@ -252,5 +357,4 @@ void DisplayController::UpdateDisplayBoundsForLayout() { |
secondary_display->UpdateWorkAreaFromInsets(insets); |
} |
-} // namespace internal |
} // namespace ash |