diff options
-rw-r--r-- | ash/accelerators/accelerator_controller_unittest.cc | 5 | ||||
-rw-r--r-- | ash/ash.gyp | 2 | ||||
-rw-r--r-- | ash/dip_unittest.cc | 14 | ||||
-rw-r--r-- | ash/display/display_change_observer_x11.cc | 65 | ||||
-rw-r--r-- | ash/display/display_controller.cc | 44 | ||||
-rw-r--r-- | ash/display/display_controller.h | 3 | ||||
-rw-r--r-- | ash/display/display_controller_unittest.cc | 35 | ||||
-rw-r--r-- | ash/display/display_info.cc | 143 | ||||
-rw-r--r-- | ash/display/display_info.h | 130 | ||||
-rw-r--r-- | ash/display/display_manager.cc | 393 | ||||
-rw-r--r-- | ash/display/display_manager.h | 75 | ||||
-rw-r--r-- | ash/display/display_manager_unittest.cc | 221 | ||||
-rw-r--r-- | ash/test/ash_test_base.cc | 10 | ||||
-rw-r--r-- | ash/test/ash_test_base.h | 4 | ||||
-rw-r--r-- | ash/test/display_manager_test_api.cc | 49 | ||||
-rw-r--r-- | ash/test/display_manager_test_api.h | 4 | ||||
-rw-r--r-- | ash/wm/system_gesture_event_filter_unittest.cc | 5 | ||||
-rw-r--r-- | ui/aura/root_window.cc | 1 | ||||
-rw-r--r-- | ui/base/x/events_x.cc | 8 | ||||
-rw-r--r-- | ui/base/x/x11_util.cc | 10 | ||||
-rw-r--r-- | ui/base/x/x11_util.h | 8 | ||||
-rw-r--r-- | ui/gfx/display.cc | 14 | ||||
-rw-r--r-- | ui/gfx/display.h | 10 |
23 files changed, 498 insertions, 755 deletions
diff --git a/ash/accelerators/accelerator_controller_unittest.cc b/ash/accelerators/accelerator_controller_unittest.cc index 62b52c2..ccc574d 100644 --- a/ash/accelerators/accelerator_controller_unittest.cc +++ b/ash/accelerators/accelerator_controller_unittest.cc @@ -14,7 +14,6 @@ #include "ash/system/keyboard_brightness/keyboard_brightness_control_delegate.h" #include "ash/system/tray/system_tray_delegate.h" #include "ash/test/ash_test_base.h" -#include "ash/test/display_manager_test_api.h" #include "ash/test/test_shell_delegate.h" #include "ash/volume_control_delegate.h" #include "ash/wm/window_util.h" @@ -314,8 +313,8 @@ class AcceleratorControllerTest : public test::AshTestBase { protected: void EnableInternalDisplay() { - test::DisplayManagerTestApi(Shell::GetInstance()->display_manager()). - SetFirstDisplayAsInternalDisplay(); + Shell::GetInstance()->display_manager()-> + SetFirstDisplayAsInternalDisplayForTest(); } static AcceleratorController* GetController(); diff --git a/ash/ash.gyp b/ash/ash.gyp index ec824a4..a4c6f7c 100644 --- a/ash/ash.gyp +++ b/ash/ash.gyp @@ -81,8 +81,6 @@ 'display/display_controller.h', 'display/display_error_dialog.cc', 'display/display_error_dialog.h', - 'display/display_info.h', - 'display/display_info.cc', 'display/display_manager.cc', 'display/display_manager.h', 'display/event_transformation_handler.cc', diff --git a/ash/dip_unittest.cc b/ash/dip_unittest.cc index 2c00d71a..1df1ec7 100644 --- a/ash/dip_unittest.cc +++ b/ash/dip_unittest.cc @@ -5,7 +5,6 @@ #include <algorithm> #include <vector> -#include "ash/display/display_manager.h" #include "ash/launcher/launcher.h" #include "ash/shell.h" #include "ash/test/ash_test_base.h" @@ -30,7 +29,7 @@ typedef ash::test::AshTestBase DIPTest; // Test if the WM sets correct work area under different density. TEST_F(DIPTest, WorkArea) { - UpdateDisplay("1000x900*1.0f"); + ChangeDisplayConfig(1.0f, gfx::Rect(0, 0, 1000, 900)); aura::RootWindow* root = Shell::GetPrimaryRootWindow(); const gfx::Display display = @@ -41,16 +40,13 @@ TEST_F(DIPTest, WorkArea) { EXPECT_EQ("0,0 1000x852", work_area.ToString()); EXPECT_EQ("0,0,48,0", display.bounds().InsetsFrom(work_area).ToString()); - UpdateDisplay("2000x1800*2.0f"); - gfx::Screen* screen = Shell::GetScreen(); + ChangeDisplayConfig(2.0f, gfx::Rect(0, 0, 2000, 1800)); - const gfx::Display display_2x = screen->GetDisplayNearestWindow(root); - const internal::DisplayInfo display_info_2x = - Shell::GetInstance()->display_manager()->GetDisplayInfo(display_2x); + const gfx::Display display_2x = + Shell::GetScreen()->GetDisplayNearestWindow(root); // The |bounds_in_pixel()| should report bounds in pixel coordinate. - EXPECT_EQ("1,1 2000x1800", - display_info_2x.bounds_in_pixel().ToString()); + EXPECT_EQ("0,0 2000x1800", display_2x.bounds_in_pixel().ToString()); // Aura and views coordinates are in DIP, so they their bounds do not change. EXPECT_EQ("0,0 1000x900", display_2x.bounds().ToString()); diff --git a/ash/display/display_change_observer_x11.cc b/ash/display/display_change_observer_x11.cc index d4d7c4e..b7114ce 100644 --- a/ash/display/display_change_observer_x11.cc +++ b/ash/display/display_change_observer_x11.cc @@ -11,12 +11,9 @@ #include <X11/extensions/Xrandr.h> -#include "ash/display/display_info.h" #include "ash/display/display_manager.h" #include "ash/shell.h" #include "base/message_pump_aurax11.h" -#include "grit/ash_strings.h" -#include "ui/base/l10n/l10n_util.h" #include "ui/base/x/x11_util.h" #include "ui/compositor/dip_util.h" #include "ui/gfx/display.h" @@ -48,7 +45,7 @@ XRRModeInfo* FindMode(XRRScreenResources* screen_resources, XID current_mode) { return NULL; } -bool CompareDisplayY(const DisplayInfo& lhs, const DisplayInfo& rhs) { +bool CompareDisplayY(const gfx::Display& lhs, const gfx::Display& rhs) { return lhs.bounds_in_pixel().y() < rhs.bounds_in_pixel().y(); } @@ -79,12 +76,6 @@ bool ShouldIgnoreSize(XRROutputInfo *output_info) { return false; } -std::string GetDisplayName(XID output_id) { - std::string display_name; - ui::GetOutputDeviceData(output_id, NULL, NULL, &display_name); - return display_name; -} - } // namespace DisplayChangeObserverX11::DisplayChangeObserverX11() @@ -110,14 +101,15 @@ void DisplayChangeObserverX11::OnDisplayModeChanged() { crtc_info_map[crtc_id] = crtc_info; } - std::vector<DisplayInfo> displays; + std::vector<gfx::Display> displays; std::set<int> y_coords; std::set<int64> ids; for (int output_index = 0; output_index < screen_resources->noutput; output_index++) { - XID output = screen_resources->outputs[output_index]; XRROutputInfo *output_info = - XRRGetOutputInfo(xdisplay_, screen_resources, output); + XRRGetOutputInfo(xdisplay_, + screen_resources, + screen_resources->outputs[output_index]); if (output_info->connection != RR_Connected) { XRRFreeOutputInfo(output_info); continue; @@ -137,6 +129,7 @@ void DisplayChangeObserverX11::OnDisplayModeChanged() { // Mirrored monitors have the same y coordinates. if (y_coords.find(crtc_info->y) != y_coords.end()) continue; + displays.push_back(gfx::Display()); float device_scale_factor = 1.0f; if (!ShouldIgnoreSize(output_info) && @@ -144,43 +137,24 @@ void DisplayChangeObserverX11::OnDisplayModeChanged() { kHighDensityDPIThreshold) { device_scale_factor = 2.0f; } - gfx::Rect display_bounds( - crtc_info->x, crtc_info->y, mode->width, mode->height); - - XRRFreeOutputInfo(output_info); - bool is_internal = chromeos::OutputConfigurator::IsInternalOutputName( - std::string(output_info->name)); - - std::string name = is_internal ? - l10n_util::GetStringUTF8(IDS_ASH_INTERNAL_DISPLAY_NAME) : - GetDisplayName(output); - if (name.empty()) - name = l10n_util::GetStringUTF8(IDS_ASH_STATUS_TRAY_UNKNOWN_DISPLAY_NAME); - - bool has_overscan; - ui::GetOutputOverscanFlag(output, &has_overscan); + displays.back().SetScaleAndBounds( + device_scale_factor, + gfx::Rect(crtc_info->x, crtc_info->y, mode->width, mode->height)); uint16 manufacturer_id = 0; uint16 product_code = 0; - int64 id = gfx::Display::kInvalidDisplayID; - - if (ui::GetOutputDeviceData( - output, &manufacturer_id, &product_code, NULL) && + if (ui::GetOutputDeviceData(screen_resources->outputs[output_index], + &manufacturer_id, &product_code, NULL) && manufacturer_id != 0) { // An ID based on display's index will be assigned later if this call // fails. int64 new_id = gfx::Display::GetID( manufacturer_id, product_code, output_index); - if (ids.find(new_id) == ids.end()) - id = new_id; + if (ids.find(new_id) == ids.end()) { + displays.back().set_id(new_id); + ids.insert(new_id); + } } - if (id == gfx::Display::kInvalidDisplayID) - id = output_index; - ids.insert(id); - - displays.push_back(DisplayInfo(id, name, has_overscan)); - displays.back().set_device_scale_factor(device_scale_factor); - displays.back().SetBounds(display_bounds); y_coords.insert(crtc_info->y); XRRFreeOutputInfo(output_info); @@ -196,7 +170,14 @@ void DisplayChangeObserverX11::OnDisplayModeChanged() { // PowerManager lays out the outputs vertically. Sort them by Y // coordinates. std::sort(displays.begin(), displays.end(), CompareDisplayY); - + int64 id = 0; + for (std::vector<gfx::Display>::iterator iter = displays.begin(); + iter != displays.end(); ++iter) { + if (iter->id() == gfx::Display::kInvalidDisplayID) { + iter->set_id(id); + ++id; + } + } // DisplayManager can be null during the boot. Shell::GetInstance()->display_manager()->OnNativeDisplaysChanged(displays); } diff --git a/ash/display/display_controller.cc b/ash/display/display_controller.cc index 29987d5..2d645a1 100644 --- a/ash/display/display_controller.cc +++ b/ash/display/display_controller.cc @@ -296,8 +296,26 @@ bool DisplayController::HasPrimaryDisplay() { } void DisplayController::InitPrimaryDisplay() { - const gfx::Display* primary_candidate = - GetDisplayManager()->GetPrimaryDisplayCandidate(); + const gfx::Display* primary_candidate = GetDisplayManager()->GetDisplayAt(0); +#if defined(OS_CHROMEOS) + if (base::chromeos::IsRunningOnChromeOS()) { + internal::DisplayManager* display_manager = GetDisplayManager(); + // On ChromeOS device, root windows are stacked vertically, and + // default primary is the one on top. + int count = display_manager->GetNumDisplays(); + int y = primary_candidate->bounds_in_pixel().y(); + for (int i = 1; i < count; ++i) { + const gfx::Display* display = display_manager->GetDisplayAt(i); + if (display->IsInternal()) { + primary_candidate = display; + break; + } else if (display->bounds_in_pixel().y() < y) { + primary_candidate = display; + y = display->bounds_in_pixel().y(); + } + } + } +#endif primary_display_id = primary_candidate->id(); AddRootWindowForDisplay(*primary_candidate); UpdateDisplayBoundsForLayout(); @@ -387,10 +405,6 @@ void DisplayController::SetOverscanInsets(int64 display_id, GetDisplayManager()->SetOverscanInsets(display_id, insets_in_dip); } -void DisplayController::ClearCustomOverscanInsets(int64 display_id) { - GetDisplayManager()->ClearCustomOverscanInsets(display_id); -} - std::vector<internal::RootWindowController*> DisplayController::GetAllRootWindowControllers() { std::vector<internal::RootWindowController*> controllers; @@ -545,13 +559,11 @@ void DisplayController::SetPrimaryDisplay( GetLayoutForDisplay(new_primary_display).Invert()); // Update the dispay manager with new display info. - std::vector<internal::DisplayInfo> display_info_list; - display_info_list.push_back(display_manager->GetDisplayInfo( - display_manager->GetDisplayForId(primary_display_id))); - display_info_list.push_back(display_manager->GetDisplayInfo( - *GetSecondaryDisplay())); + std::vector<gfx::Display> displays; + displays.push_back(display_manager->GetDisplayForId(primary_display_id)); + displays.push_back(*GetSecondaryDisplay()); GetDisplayManager()->set_force_bounds_changed(true); - GetDisplayManager()->UpdateDisplays(display_info_list); + GetDisplayManager()->UpdateDisplays(displays); GetDisplayManager()->set_force_bounds_changed(false); } @@ -565,15 +577,12 @@ gfx::Display* DisplayController::GetSecondaryDisplay() { void DisplayController::OnDisplayBoundsChanged(const gfx::Display& display) { if (limiter_.get()) limiter_->SetThrottleTimeout(kAfterDisplayChangeThrottleTimeoutMs); - DCHECK(!GetDisplayManager()->GetDisplayInfo(display). - bounds_in_pixel().IsEmpty()); NotifyDisplayConfigurationChanging(); UpdateDisplayBoundsForLayout(); aura::RootWindow* root = root_windows_[display.id()]; SetDisplayPropertiesOnHostWindow(root, display); - root->SetHostBounds( - GetDisplayManager()->GetDisplayInfo(display).bounds_in_pixel()); + root->SetHostBounds(display.bounds_in_pixel()); } void DisplayController::OnDisplayAdded(const gfx::Display& display) { @@ -589,8 +598,7 @@ void DisplayController::OnDisplayAdded(const gfx::Display& display) { internal::kDisplayIdKey, display.id()); primary_root_window_for_replace_ = NULL; UpdateDisplayBoundsForLayout(); - root_windows_[display.id()]->SetHostBounds( - GetDisplayManager()->GetDisplayInfo(display).bounds_in_pixel()); + root_windows_[display.id()]->SetHostBounds(display.bounds_in_pixel()); } else { DCHECK(!root_windows_.empty()); aura::RootWindow* root = AddRootWindowForDisplay(display); diff --git a/ash/display/display_controller.h b/ash/display/display_controller.h index 65b4570..2674483 100644 --- a/ash/display/display_controller.h +++ b/ash/display/display_controller.h @@ -141,11 +141,10 @@ class ASH_EXPORT DisplayController : public gfx::DisplayObserver { // mode, this return a RootWindowController for the primary root window only. std::vector<internal::RootWindowController*> GetAllRootWindowControllers(); - // Gets/Sets/Clears the overscan insets for the specified |display_id|. See + // Gets/Sets the overscan insets for the specified |display_id|. See // display_manager.h for the details. gfx::Insets GetOverscanInsets(int64 display_id) const; void SetOverscanInsets(int64 display_id, const gfx::Insets& insets_in_dip); - void ClearCustomOverscanInsets(int64 display_id); const DisplayLayout& default_display_layout() const { return default_display_layout_; diff --git a/ash/display/display_controller_unittest.cc b/ash/display/display_controller_unittest.cc index c07a9b7..a507062 100644 --- a/ash/display/display_controller_unittest.cc +++ b/ash/display/display_controller_unittest.cc @@ -395,15 +395,14 @@ TEST_F(DisplayControllerTest, SwapPrimaryById) { EXPECT_FALSE(tracker.Contains(secondary_root)); EXPECT_TRUE(primary_root->Contains(launcher_window)); - internal::DisplayManager* display_manager = - Shell::GetInstance()->display_manager(); // Adding 2nd display with the same ID. The 2nd display should become primary // since secondary id is still stored as desirable_primary_id. - std::vector<internal::DisplayInfo> display_info_list; - display_info_list.push_back(display_manager->GetDisplayInfo(primary_display)); - display_info_list.push_back( - display_manager->GetDisplayInfo(secondary_display)); - display_manager->OnNativeDisplaysChanged(display_info_list); + std::vector<gfx::Display> displays; + displays.push_back(primary_display); + displays.push_back(secondary_display); + internal::DisplayManager* display_manager = + Shell::GetInstance()->display_manager(); + display_manager->OnNativeDisplaysChanged(displays); EXPECT_EQ(2, Shell::GetScreen()->GetNumDisplays()); EXPECT_EQ(secondary_display.id(), @@ -420,27 +419,23 @@ TEST_F(DisplayControllerTest, SwapPrimaryById) { // Deleting 2nd display and adding 2nd display with a different ID. The 2nd // display shouldn't become primary. UpdateDisplay("200x200"); - internal::DisplayInfo third_display_info( - secondary_display.id() + 1, std::string(), false); - third_display_info.SetBounds(secondary_display.bounds()); - ASSERT_NE(primary_display.id(), third_display_info.id()); - - const internal::DisplayInfo& primary_display_info = - display_manager->GetDisplayInfo(primary_display); - std::vector<internal::DisplayInfo> display_info_list2; - display_info_list2.push_back(primary_display_info); - display_info_list2.push_back(third_display_info); - display_manager->OnNativeDisplaysChanged(display_info_list2); + std::vector<gfx::Display> displays2; + gfx::Display third_display( + secondary_display.id() + 1, secondary_display.bounds()); + ASSERT_NE(primary_display.id(), third_display.id()); + displays2.push_back(primary_display); + displays2.push_back(third_display); + display_manager->OnNativeDisplaysChanged(displays2); EXPECT_EQ(2, Shell::GetScreen()->GetNumDisplays()); EXPECT_EQ(primary_display.id(), Shell::GetScreen()->GetPrimaryDisplay().id()); - EXPECT_EQ(third_display_info.id(), ScreenAsh::GetSecondaryDisplay().id()); + EXPECT_EQ(third_display.id(), ScreenAsh::GetSecondaryDisplay().id()); EXPECT_EQ( primary_root, display_controller->GetRootWindowForDisplayId(primary_display.id())); EXPECT_NE( primary_root, - display_controller->GetRootWindowForDisplayId(third_display_info.id())); + display_controller->GetRootWindowForDisplayId(third_display.id())); EXPECT_TRUE(primary_root->Contains(launcher_window)); } diff --git a/ash/display/display_info.cc b/ash/display/display_info.cc deleted file mode 100644 index e94ea9e..0000000 --- a/ash/display/display_info.cc +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright (c) 2013 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. - -#include <stdio.h> - -#include "ash/display/display_info.h" -#include "base/logging.h" -#include "base/stringprintf.h" -#include "ui/gfx/display.h" - -#if defined(OS_WIN) -#include "ui/aura/root_window_host.h" -#endif - -namespace ash { -namespace internal { - -// satic -DisplayInfo DisplayInfo::CreateFromSpec(const std::string& spec) { - return CreateFromSpecWithID(spec, gfx::Display::kInvalidDisplayID); -} - -// static -DisplayInfo DisplayInfo::CreateFromSpecWithID(const std::string& spec, - int64 id) { - // Default bounds for a display. - const int kDefaultHostWindowX = 200; - const int kDefaultHostWindowY = 200; - const int kDefaultHostWindowWidth = 1280; - const int kDefaultHostWindowHeight = 1024; - - static int64 synthesized_display_id = 1000; - -#if defined(OS_WIN) - gfx::Rect bounds(aura::RootWindowHost::GetNativeScreenSize()); -#else - gfx::Rect bounds(kDefaultHostWindowX, kDefaultHostWindowY, - kDefaultHostWindowWidth, kDefaultHostWindowHeight); -#endif - - int x = 0, y = 0, width, height; - float scale = 1.0f; - if (sscanf(spec.c_str(), "%dx%d*%f", &width, &height, &scale) >= 2 || - sscanf(spec.c_str(), "%d+%d-%dx%d*%f", &x, &y, &width, &height, - &scale) >= 4) { - bounds.SetRect(x, y, width, height); - } - if (id == gfx::Display::kInvalidDisplayID) - id = synthesized_display_id++; - DisplayInfo display_info( - id, base::StringPrintf("Display-%d", static_cast<int>(id)), false); - display_info.set_device_scale_factor(scale); - display_info.SetBounds(bounds); - DVLOG(1) << "DisplayInfoFromSpec info=" << display_info.ToString() - << ", spec=" << spec; - return display_info; -} - -DisplayInfo::DisplayInfo() - : id_(gfx::Display::kInvalidDisplayID), - has_overscan_(false), - device_scale_factor_(1.0f), - overscan_insets_in_dip_(-1, -1, -1, -1), - has_custom_overscan_insets_(false) { -} - -DisplayInfo::DisplayInfo(int64 id, - const std::string& name, - bool has_overscan) - : id_(id), - name_(name), - has_overscan_(has_overscan), - device_scale_factor_(1.0f), - overscan_insets_in_dip_(-1, -1, -1, -1), - has_custom_overscan_insets_(false) { -} - -DisplayInfo::~DisplayInfo() { -} - -void DisplayInfo::CopyFromNative(const DisplayInfo& native_info) { - DCHECK(id_ == native_info.id_); - name_ = native_info.name_; - has_overscan_ = native_info.has_overscan_; - - DCHECK(!native_info.original_bounds_in_pixel_.IsEmpty()); - original_bounds_in_pixel_ = native_info.original_bounds_in_pixel_; - bounds_in_pixel_ = native_info.bounds_in_pixel_; - device_scale_factor_ = native_info.device_scale_factor_; -} - -void DisplayInfo::SetBounds(const gfx::Rect& new_original_bounds) { - original_bounds_in_pixel_ = bounds_in_pixel_ = new_original_bounds; -} - -void DisplayInfo::UpdateBounds(const gfx::Rect& new_original_bounds) { - bool overscan = original_bounds_in_pixel_ != bounds_in_pixel_; - original_bounds_in_pixel_ = bounds_in_pixel_ = new_original_bounds; - if (overscan) { - original_bounds_in_pixel_.Inset( - overscan_insets_in_dip_.Scale(-device_scale_factor_)); - } -} - -void DisplayInfo::UpdateOverscanInfo(bool can_overscan) { - bounds_in_pixel_ = original_bounds_in_pixel_; - if (can_overscan) { - if (has_custom_overscan_insets_) { - bounds_in_pixel_.Inset( - overscan_insets_in_dip_.Scale(device_scale_factor_)); - } else if (has_overscan_) { - // Currently we assume 5% overscan and hope for the best if TV claims it - // overscan, but doesn't expose how much. - int width = bounds_in_pixel_.width() / 40; - int height = bounds_in_pixel_.height() / 40; - gfx::Insets insets_in_pixel(height, width, height, width); - overscan_insets_in_dip_ = - insets_in_pixel.Scale(1.0 / device_scale_factor_); - bounds_in_pixel_.Inset( - overscan_insets_in_dip_.Scale(device_scale_factor_)); - } - } -} - -void DisplayInfo::SetOverscanInsets(bool custom, - const gfx::Insets& insets_in_dip) { - has_custom_overscan_insets_ = custom; - overscan_insets_in_dip_ = insets_in_dip; -} - -std::string DisplayInfo::ToString() const { - return base::StringPrintf( - "DisplayInfo[%lld] bounds=%s, original=%s, scale=%f, overscan=%s", - static_cast<long long int>(id_), - bounds_in_pixel_.ToString().c_str(), - original_bounds_in_pixel_.ToString().c_str(), - device_scale_factor_, - overscan_insets_in_dip_.ToString().c_str()); -} - -} // namespace internal -} // namespace ash diff --git a/ash/display/display_info.h b/ash/display/display_info.h deleted file mode 100644 index 94adf1d..0000000 --- a/ash/display/display_info.h +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright (c) 2013 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. - -#ifndef ASH_DISPLAY_DISPLAY_INFO_H_ -#define ASH_DISPLAY_DISPLAY_INFO_H_ - -#include <string> - -#include "ash/ash_export.h" -#include "base/gtest_prod_util.h" -#include "ui/gfx/insets.h" -#include "ui/gfx/rect.h" - -namespace gfx { -class Display; -} - -namespace ash { -namespace internal { - -// DisplayInfo contains metadata for each display. This is used to -// create |gfx::Display| as well as to maintain extra infomation -// to manage displays in ash environment. -// This class is intentionally made copiable. -class ASH_EXPORT DisplayInfo { - public: - // Creates a DisplayInfo from string spec. 100+200-1440x800 creates display - // whose size is 1440x800 at the location (100, 200) in screen's coordinates. - // The location can be omitted and be just "1440x800", which creates - // display at the origin of the screen. An empty string creates - // the display with default size. - // The device scale factor can be specified by "*", like "1280x780*2", - // or will use the value of |gfx::Display::GetForcedDeviceScaleFactor()| if - // --force-device-scale-factor is specified. - static DisplayInfo CreateFromSpec(const std::string& spec); - - // Creates a DisplayInfo from string spec using given |id|. - static DisplayInfo CreateFromSpecWithID(const std::string& spec, - int64 id); - - DisplayInfo(); - DisplayInfo(int64 id, const std::string& name, bool has_overscan); - ~DisplayInfo(); - - int64 id() const { return id_; } - - // The name of the display. - const std::string& name() const { return name_; } - - // True if the display has overscan. - bool has_overscan() const { return has_overscan_; } - - // Gets/Sets the device scale factor of the display. - float device_scale_factor() const { return device_scale_factor_; } - void set_device_scale_factor(float scale) { device_scale_factor_ = scale; } - - // The original bounds_in_pixel for the display. This can be different from - // the |bounds_in_pixel| in case of overscan insets. - const gfx::Rect original_bounds_in_pixel() const { - return original_bounds_in_pixel_; - } - - // The bounds for the display in pixels. - const gfx::Rect bounds_in_pixel() const { return bounds_in_pixel_; } - - // The overscan insets for the display in DIP. The default value is - // (-1, -1, -1, -1), which indicates that no overscan should be applied. - const gfx::Insets& overscan_insets_in_dip() const { - return overscan_insets_in_dip_; - } - - // Copy the display info except for two fields that can be modified by a user - // (|has_custom_overscan_insets_| and |custom_overscan_insets_in_dip_|). - void CopyFromNative(const DisplayInfo& native_info); - - // Set the |original_bounds_in_pixel| and |bounds_in_pixel| to - // given |bounds|. - void SetBounds(const gfx::Rect& bounds_in_pixel); - - // Sets the |bounds_in_pixel| and updates original bounds based on - // current overscan configuration. - void UpdateBounds(const gfx::Rect& bounds_in_pixel); - - // Update the |bounds_in_pixel| according to the current overscan - // settings. - // 1) If can_overscan is false, then |bounds_in_pixel| is equal to - // |original_bounds_in_pixel|. - // 2) If this has custom overscan insets - // (i.e. |has_custom_overscan_insets_| is true), it simply applies - // the existing |overscan_insets_in_dip_|. - // 3) If this doesn't have custom overscan insets, then this updates - // |overscan_insets_in_dip_| to default value (5% of the display size) - // and apply the insets. - void UpdateOverscanInfo(bool can_overscan); - - // Sets/Clears the overscan insets. - void SetOverscanInsets(bool custom, - const gfx::Insets& insets_in_dip); - void clear_has_custom_overscan_insets() { - has_custom_overscan_insets_ = false; - } - - // Returns a string representation of the DisplayInfo; - std::string ToString() const; - - private: - FRIEND_TEST_ALL_PREFIXES(DisplayManagerTest, AutomaticOverscanInsets); - // Set the overscan flag. Used for test. - void set_has_overscan_for_test(bool has_overscan) { - has_overscan_ = has_overscan; - } - - int64 id_; - std::string name_; - bool has_overscan_; - float device_scale_factor_; - gfx::Rect original_bounds_in_pixel_; - gfx::Rect bounds_in_pixel_; - gfx::Insets overscan_insets_in_dip_; - - // True if the |overscan_insets_in_dip| is specified by a user. This - // is used not to override the insets by native insets. - bool has_custom_overscan_insets_; -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_DISPLAY_DISPLAY_INFO_H_ diff --git a/ash/display/display_manager.cc b/ash/display/display_manager.cc index 6aef6f4..170b340 100644 --- a/ash/display/display_manager.cc +++ b/ash/display/display_manager.cc @@ -46,12 +46,10 @@ #endif DECLARE_WINDOW_PROPERTY_TYPE(int64); +typedef std::vector<gfx::Display> DisplayList; namespace ash { namespace internal { -typedef std::vector<gfx::Display> DisplayList; -typedef std::vector<DisplayInfo> DisplayInfoList; - namespace { // Default bounds for a display. @@ -66,38 +64,29 @@ struct DisplaySortFunctor { } }; -struct DisplayInfoSortFunctor { - bool operator()(const DisplayInfo& a, const DisplayInfo& b) { - return a.id() < b.id(); - } -}; - gfx::Display& GetInvalidDisplay() { static gfx::Display* invalid_display = new gfx::Display(); return *invalid_display; } #if defined(OS_CHROMEOS) - -int64 FindInternalDisplayID() { - std::vector<XID> outputs; - ui::GetOutputDeviceHandles(&outputs); - std::vector<std::string> output_names = ui::GetOutputNames(outputs); - for (size_t i = 0; i < output_names.size(); ++i) { - if (chromeos::OutputConfigurator::IsInternalOutputName( - output_names[i])) { - uint16 manufacturer_id = 0; - uint16 product_code = 0; - ui::GetOutputDeviceData( - outputs[i], &manufacturer_id, &product_code, NULL); - return gfx::Display::GetID(manufacturer_id, product_code, i); - } - } - return gfx::Display::kInvalidDisplayID; +int64 GetDisplayIdForOutput(XID output, int output_index) { + uint16 manufacturer_id = 0; + uint16 product_code = 0; + ui::GetOutputDeviceData( + output, &manufacturer_id, &product_code, NULL); + return gfx::Display::GetID(manufacturer_id, product_code, output_index); } - #endif +gfx::Insets GetDefaultDisplayOverscan(const gfx::Display& display) { + // Currently we assume 5% overscan and hope for the best if TV claims it + // overscan, but doesn't expose how much. + int width = display.bounds().width() / 40; + int height = display.bounds().height() / 40; + return gfx::Insets(height, width, height, width); +} + } // namespace using aura::RootWindow; @@ -170,34 +159,24 @@ const gfx::Display& DisplayManager::FindDisplayContainingPoint( void DisplayManager::SetOverscanInsets(int64 display_id, const gfx::Insets& insets_in_dip) { - display_info_[display_id].SetOverscanInsets(true, insets_in_dip); - DisplayInfoList display_info_list; - for (DisplayList::const_iterator iter = displays_.begin(); - iter != displays_.end(); ++iter) { - display_info_list.push_back(GetDisplayInfo(*iter)); - } - UpdateDisplays(display_info_list); -} + display_info_[display_id].overscan_insets_in_dip = insets_in_dip; + display_info_[display_id].has_custom_overscan_insets = true; -void DisplayManager::ClearCustomOverscanInsets(int64 display_id) { - display_info_[display_id].clear_has_custom_overscan_insets(); - DisplayInfoList display_info_list; - for (DisplayList::const_iterator iter = displays_.begin(); - iter != displays_.end(); ++iter) { - display_info_list.push_back(GetDisplayInfo(*iter)); - } - UpdateDisplays(display_info_list); + // Copies the |displays_| because UpdateDisplays() compares the passed + // displays and its internal |displays_|. + DisplayList displays = displays_; + UpdateDisplays(displays); } gfx::Insets DisplayManager::GetOverscanInsets(int64 display_id) const { std::map<int64, DisplayInfo>::const_iterator it = display_info_.find(display_id); return (it != display_info_.end()) ? - it->second.overscan_insets_in_dip() : gfx::Insets(); + it->second.overscan_insets_in_dip : gfx::Insets(); } void DisplayManager::OnNativeDisplaysChanged( - const std::vector<DisplayInfo>& updated_displays) { + const std::vector<gfx::Display>& updated_displays) { if (updated_displays.empty()) { // Don't update the displays when all displays are disconnected. // This happens when: @@ -211,34 +190,55 @@ void DisplayManager::OnNativeDisplaysChanged( // display list will be updated correctly. return; } - - bool internal_display_connected = false; - for (DisplayInfoList::const_iterator iter = updated_displays.begin(); - iter != updated_displays.end() && !internal_display_connected; - ++iter) { - internal_display_connected = IsInternalDisplayId(iter->id()); - if (internal_display_connected) - internal_display_info_.reset(new DisplayInfo(*iter)); + DisplayList new_displays = updated_displays; + if (HasInternalDisplay()) { + bool internal_display_connected = false; + for (DisplayList::const_iterator iter = updated_displays.begin(); + iter != updated_displays.end(); ++iter) { + if ((*iter).IsInternal()) { + internal_display_connected = true; + // Update the internal display cache. + internal_display_.reset(new gfx::Display); + *internal_display_.get() = *iter; + break; + } + } + // If the internal display wasn't connected, use the cached value. + if (!internal_display_connected) { + // Internal display may be reported as disconnect during startup time. + if (!internal_display_.get()) { + internal_display_.reset( + new gfx::Display(gfx::Display::InternalDisplayId(), + gfx::Rect(800, 600))); + } + new_displays.push_back(*internal_display_.get()); + } + } else { + new_displays = updated_displays; } - DisplayInfoList new_display_info_list = updated_displays; - - if (HasInternalDisplay() && !internal_display_connected) { - if (!internal_display_info_.get()) { - // TODO(oshima): Get has_custom value. - internal_display_info_.reset(new DisplayInfo( - gfx::Display::InternalDisplayId(), - l10n_util::GetStringUTF8(IDS_ASH_INTERNAL_DISPLAY_NAME), - false)); - internal_display_info_->SetBounds(gfx::Rect(0, 0, 800, 600)); + + RefreshDisplayInfo(); + + for (DisplayList::const_iterator iter = new_displays.begin(); + iter != new_displays.end(); ++iter) { + std::map<int64, DisplayInfo>::iterator info = + display_info_.find(iter->id()); + if (info != display_info_.end()) { + info->second.original_bounds_in_pixel = iter->bounds_in_pixel(); + if (info->second.has_overscan && !info->second.has_custom_overscan_insets) + info->second.overscan_insets_in_dip = GetDefaultDisplayOverscan(*iter); + } else { + display_info_[iter->id()].original_bounds_in_pixel = + iter->bounds_in_pixel(); } - new_display_info_list.push_back(*internal_display_info_.get()); } - UpdateDisplays(new_display_info_list); + UpdateDisplays(new_displays); } void DisplayManager::UpdateDisplays( - const std::vector<DisplayInfo>& updated_display_info_list) { + const std::vector<gfx::Display>& updated_displays) { + DisplayList new_displays = updated_displays; #if defined(OS_CHROMEOS) // Overscan is always enabled when not running on the device // in order for unit tests to work. @@ -246,15 +246,26 @@ void DisplayManager::UpdateDisplays( !base::chromeos::IsRunningOnChromeOS() || (Shell::GetInstance()->output_configurator()->output_state() != chromeos::STATE_DUAL_MIRROR && - updated_display_info_list.size() == 1); + updated_displays.size() == 1); #else bool can_overscan = true; #endif - DisplayInfoList new_display_info_list = updated_display_info_list; + if (can_overscan) { + for (DisplayList::iterator iter = new_displays.begin(); + iter != new_displays.end(); ++iter) { + std::map<int64, DisplayInfo>::const_iterator info = + display_info_.find(iter->id()); + if (info != display_info_.end()) { + gfx::Rect bounds = info->second.original_bounds_in_pixel; + bounds.Inset(info->second.overscan_insets_in_dip.Scale( + iter->device_scale_factor())); + iter->SetScaleAndBounds(iter->device_scale_factor(), bounds); + } + } + } + std::sort(displays_.begin(), displays_.end(), DisplaySortFunctor()); - std::sort(new_display_info_list.begin(), - new_display_info_list.end(), - DisplayInfoSortFunctor()); + std::sort(new_displays.begin(), new_displays.end(), DisplaySortFunctor()); DisplayList removed_displays; std::vector<size_t> changed_display_indices; std::vector<size_t> added_display_indices; @@ -262,54 +273,44 @@ void DisplayManager::UpdateDisplays( if (DisplayController::HasPrimaryDisplay()) current_primary = DisplayController::GetPrimaryDisplay(); - DisplayList::iterator curr_iter = displays_.begin(); - DisplayInfoList::const_iterator new_info_iter = new_display_info_list.begin(); - - DisplayList new_displays; - while (curr_iter != displays_.end() || - new_info_iter != new_display_info_list.end()) { + for (DisplayList::iterator curr_iter = displays_.begin(), + new_iter = new_displays.begin(); + curr_iter != displays_.end() || new_iter != new_displays.end();) { if (curr_iter == displays_.end()) { // more displays in new list. - added_display_indices.push_back(new_displays.size()); - InsertAndUpdateDisplayInfo(*new_info_iter, can_overscan); - new_displays.push_back( - CreateDisplayFromDisplayInfoById(new_info_iter->id())); - ++new_info_iter; - } else if (new_info_iter == new_display_info_list.end()) { + added_display_indices.push_back(new_iter - new_displays.begin()); + ++new_iter; + } else if (new_iter == new_displays.end()) { // more displays in current list. removed_displays.push_back(*curr_iter); ++curr_iter; - } else if (curr_iter->id() == new_info_iter->id()) { + } else if ((*curr_iter).id() == (*new_iter).id()) { const gfx::Display& current_display = *curr_iter; - // Copy the info because |CreateDisplayFromInfo| updates the instance. - const DisplayInfo current_display_info = GetDisplayInfo(current_display); - InsertAndUpdateDisplayInfo(*new_info_iter, can_overscan); - gfx::Display new_display = - CreateDisplayFromDisplayInfoById(new_info_iter->id()); - const DisplayInfo& new_display_info = GetDisplayInfo(new_display); + gfx::Display& new_display = *new_iter; if (force_bounds_changed_ || - (current_display_info.bounds_in_pixel() != - new_display_info.bounds_in_pixel()) || - (current_display.device_scale_factor() != - new_display.device_scale_factor())) { - changed_display_indices.push_back(new_displays.size()); + current_display.bounds_in_pixel() != new_display.bounds_in_pixel() || + current_display.device_scale_factor() != + new_display.device_scale_factor()) { + changed_display_indices.push_back(new_iter - new_displays.begin()); } + // If the display is primary, then simpy set the origin to (0,0). + // The secondary display's bounds will be updated by + // |DisplayController::UpdateDisplayBoundsForLayout|, so no need + // to change there. + if ((*new_iter).id() == current_primary.id()) + new_display.set_bounds(gfx::Rect(new_display.bounds().size())); new_display.UpdateWorkAreaFromInsets(current_display.GetWorkAreaInsets()); - new_displays.push_back(new_display); ++curr_iter; - ++new_info_iter; - } else if (curr_iter->id() < new_info_iter->id()) { + ++new_iter; + } else if ((*curr_iter).id() < (*new_iter).id()) { // more displays in current list between ids, which means it is deleted. removed_displays.push_back(*curr_iter); ++curr_iter; } else { // more displays in new list between ids, which means it is added. - added_display_indices.push_back(new_displays.size()); - InsertAndUpdateDisplayInfo(*new_info_iter, can_overscan); - new_displays.push_back( - CreateDisplayFromDisplayInfoById(new_info_iter->id())); - ++new_info_iter; + added_display_indices.push_back(new_iter - new_displays.begin()); + ++new_iter; } } @@ -351,10 +352,10 @@ void DisplayManager::UpdateDisplays( RootWindow* DisplayManager::CreateRootWindowForDisplay( const gfx::Display& display) { static int root_window_count = 0; - const gfx::Rect& bounds_in_pixel = GetDisplayInfo(display).bounds_in_pixel(); - RootWindow::CreateParams params(bounds_in_pixel); + + RootWindow::CreateParams params(display.bounds_in_pixel()); params.host = Shell::GetInstance()->root_window_host_factory()-> - CreateRootWindowHost(bounds_in_pixel); + CreateRootWindowHost(display.bounds_in_pixel()); aura::RootWindow* root_window = new aura::RootWindow(params); root_window->SetName(StringPrintf("RootWindow-%d", root_window_count++)); @@ -370,30 +371,6 @@ gfx::Display* DisplayManager::GetDisplayAt(size_t index) { return index < displays_.size() ? &displays_[index] : NULL; } -const gfx::Display* DisplayManager::GetPrimaryDisplayCandidate() const { - const gfx::Display* primary_candidate = &displays_[0]; -#if defined(OS_CHROMEOS) - if (base::chromeos::IsRunningOnChromeOS()) { - // On ChromeOS device, root windows are stacked vertically, and - // default primary is the one on top. - int count = GetNumDisplays(); - int y = GetDisplayInfo(*primary_candidate).bounds_in_pixel().y(); - for (int i = 1; i < count; ++i) { - const gfx::Display* display = &displays_[i]; - const DisplayInfo& display_info = GetDisplayInfo(*display); - if (display->IsInternal()) { - primary_candidate = display; - break; - } else if (display_info.bounds_in_pixel().y() < y) { - primary_candidate = display; - y = display_info.bounds_in_pixel().y(); - } - } - } -#endif - return primary_candidate; -} - size_t DisplayManager::GetNumDisplays() const { return displays_.size(); } @@ -438,14 +415,6 @@ const gfx::Display& DisplayManager::GetDisplayMatching( return matching ? *matching : DisplayController::GetPrimaryDisplay(); } -const DisplayInfo& DisplayManager::GetDisplayInfo( - const gfx::Display& display) const { - std::map<int64, DisplayInfo>::const_iterator iter = - display_info_.find(display.id()); - CHECK(iter != display_info_.end()); - return iter->second; -} - std::string DisplayManager::GetDisplayNameFor( const gfx::Display& display) { if (!display.is_valid()) @@ -453,8 +422,8 @@ std::string DisplayManager::GetDisplayNameFor( std::map<int64, DisplayInfo>::const_iterator iter = display_info_.find(display.id()); - if (iter != display_info_.end() && !iter->second.name().empty()) - return iter->second.name(); + if (iter != display_info_.end() && !iter->second.name.empty()) + return iter->second.name; return base::StringPrintf("Display %d", static_cast<int>(display.id())); } @@ -469,8 +438,6 @@ void DisplayManager::OnRootWindowResized(const aura::RootWindow* root, gfx::Display& display = FindDisplayForRootWindow(root); if (display.size() != root->GetHostSize()) { display.SetSize(root->GetHostSize()); - display_info_[display.id()].UpdateBounds( - gfx::Rect(root->GetHostOrigin(), root->GetHostSize())); Shell::GetInstance()->screen()->NotifyBoundsChanged(display); } } @@ -478,10 +445,23 @@ void DisplayManager::OnRootWindowResized(const aura::RootWindow* root, void DisplayManager::Init() { #if defined(OS_CHROMEOS) - if (base::chromeos::IsRunningOnChromeOS()) - gfx::Display::SetInternalDisplayId(FindInternalDisplayID()); + if (base::chromeos::IsRunningOnChromeOS()) { + std::vector<XID> outputs; + ui::GetOutputDeviceHandles(&outputs); + std::vector<std::string> output_names = ui::GetOutputNames(outputs); + for (size_t i = 0; i < output_names.size(); ++i) { + if (chromeos::OutputConfigurator::IsInternalOutputName( + output_names[i])) { + gfx::Display::SetInternalDisplayId( + GetDisplayIdForOutput(outputs[i], i)); + break; + } + } + } #endif + RefreshDisplayInfo(); + // TODO(oshima): Move this logic to DisplayChangeObserver. const string size_str = CommandLine::ForCurrentProcess()->GetSwitchValueASCII( switches::kAshHostWindowBounds); @@ -497,32 +477,34 @@ void DisplayManager::Init() { void DisplayManager::CycleDisplayImpl() { DCHECK(!displays_.empty()); - std::vector<DisplayInfo> new_display_info_list; - new_display_info_list.push_back( - GetDisplayInfo(DisplayController::GetPrimaryDisplay())); + std::vector<gfx::Display> new_displays; + new_displays.push_back(DisplayController::GetPrimaryDisplay()); // Add if there is only one display. if (displays_.size() == 1) { // Layout the 2nd display below the primary as with the real device. aura::RootWindow* primary = Shell::GetPrimaryRootWindow(); gfx::Rect host_bounds = gfx::Rect(primary->GetHostOrigin(), primary->GetHostSize()); - new_display_info_list.push_back(DisplayInfo::CreateFromSpec( + new_displays.push_back(CreateDisplayFromSpec( StringPrintf("%d+%d-500x400", host_bounds.x(), host_bounds.bottom()))); } - OnNativeDisplaysChanged(new_display_info_list); + OnNativeDisplaysChanged(new_displays); } void DisplayManager::ScaleDisplayImpl() { DCHECK(!displays_.empty()); - std::vector<DisplayInfo> new_display_info_list; + std::vector<gfx::Display> new_displays; for (DisplayList::const_iterator iter = displays_.begin(); iter != displays_.end(); ++iter) { - DisplayInfo display_info = GetDisplayInfo(*iter); - display_info.set_device_scale_factor( - display_info.device_scale_factor() == 1.0f ? 2.0f : 1.0f); - new_display_info_list.push_back(display_info); + gfx::Display display = *iter; + float factor = display.device_scale_factor() == 1.0f ? 2.0f : 1.0f; + gfx::Point display_origin = display.bounds_in_pixel().origin(); + gfx::Size display_size = gfx::ToFlooredSize( + gfx::ScaleSize(display.size(), factor)); + display.SetScaleAndBounds(factor, gfx::Rect(display_origin, display_size)); + new_displays.push_back(display); } - OnNativeDisplaysChanged(new_display_info_list); + OnNativeDisplaysChanged(new_displays); } gfx::Display& DisplayManager::FindDisplayForRootWindow( @@ -546,12 +528,22 @@ gfx::Display& DisplayManager::FindDisplayForId(int64 id) { } void DisplayManager::AddDisplayFromSpec(const std::string& spec) { - DisplayInfo display_info = DisplayInfo::CreateFromSpec(spec); - InsertAndUpdateDisplayInfo(display_info, false); - gfx::Display display = CreateDisplayFromDisplayInfoById(display_info.id()); + gfx::Display display = CreateDisplayFromSpec(spec); + + const gfx::Insets insets = display.GetWorkAreaInsets(); + const gfx::Rect& native_bounds = display.bounds_in_pixel(); + display.SetScaleAndBounds(display.device_scale_factor(), native_bounds); + display.UpdateWorkAreaFromInsets(insets); displays_.push_back(display); } +int64 DisplayManager::SetFirstDisplayAsInternalDisplayForTest() { + gfx::Display::SetInternalDisplayId(displays_[0].id()); + internal_display_.reset(new gfx::Display); + *internal_display_ = displays_[0]; + return gfx::Display::InternalDisplayId(); +} + void DisplayManager::EnsurePointerInDisplays() { // Don't try to move the pointer during the boot/startup. if (!DisplayController::HasPrimaryDisplay()) @@ -590,35 +582,76 @@ void DisplayManager::EnsurePointerInDisplays() { root_window->MoveCursorTo(target_location); } -void DisplayManager::InsertAndUpdateDisplayInfo(const DisplayInfo& new_info, - bool can_overscan) { - std::map<int64, DisplayInfo>::iterator info = - display_info_.find(new_info.id()); - if (info != display_info_.end()) - info->second.CopyFromNative(new_info); - else - display_info_[new_info.id()] = new_info; +DisplayManager::DisplayInfo::DisplayInfo() + : has_overscan(false), + has_custom_overscan_insets(false) { +} + +void DisplayManager::RefreshDisplayInfo() { +#if defined(OS_CHROMEOS) + if (!base::chromeos::IsRunningOnChromeOS()) + return; +#endif + +#if defined(USE_X11) + std::vector<XID> outputs; + if (!ui::GetOutputDeviceHandles(&outputs)) + return; + + for (size_t output_index = 0; output_index < outputs.size(); ++output_index) { + uint16 manufacturer_id = 0; + uint16 product_code = 0; + std::string name; + ui::GetOutputDeviceData( + outputs[output_index], &manufacturer_id, &product_code, &name); + int64 id = gfx::Display::GetID(manufacturer_id, product_code, output_index); + if (IsInternalDisplayId(id)) { + display_info_[id].name = + l10n_util::GetStringUTF8(IDS_ASH_INTERNAL_DISPLAY_NAME); + } else if (!name.empty()) { + display_info_[id].name = name; + } + + ui::GetOutputOverscanFlag( + outputs[output_index], &display_info_[id].has_overscan); + } +#endif +} - display_info_[new_info.id()].UpdateOverscanInfo(can_overscan); +void DisplayManager::SetDisplayIdsForTest(DisplayList* to_update) const { + DisplayList::iterator iter_to_update = to_update->begin(); + DisplayList::const_iterator iter = displays_.begin(); + for (; iter != displays_.end() && iter_to_update != to_update->end(); + ++iter, ++iter_to_update) { + (*iter_to_update).set_id((*iter).id()); + } } -gfx::Display DisplayManager::CreateDisplayFromDisplayInfoById(int64 id) { - DCHECK(display_info_.find(id) != display_info_.end()); - const DisplayInfo& display_info = display_info_[id]; +void DisplayManager::SetHasOverscanFlagForTest(int64 id, bool has_overscan) { + display_info_[id].has_overscan = has_overscan; +} - gfx::Display new_display(display_info.id()); - new_display.SetScaleAndBounds( - display_info.device_scale_factor(), display_info.bounds_in_pixel()); +gfx::Display CreateDisplayFromSpec(const std::string& spec) { + static int64 synthesized_display_id = 1000; - // If the display is primary, then simply set the origin to (0,0). - // The secondary display's bounds will be updated by - // |DisplayController::UpdateDisplayBoundsForLayout|, so no need - // to change there. - if (DisplayController::HasPrimaryDisplay() && - display_info.id() == DisplayController::GetPrimaryDisplay().id()) { - new_display.set_bounds(gfx::Rect(new_display.bounds().size())); +#if defined(OS_WIN) + gfx::Rect bounds(aura::RootWindowHost::GetNativeScreenSize()); +#else + gfx::Rect bounds(kDefaultHostWindowX, kDefaultHostWindowY, + kDefaultHostWindowWidth, kDefaultHostWindowHeight); +#endif + int x = 0, y = 0, width, height; + float scale = 1.0f; + if (sscanf(spec.c_str(), "%dx%d*%f", &width, &height, &scale) >= 2 || + sscanf(spec.c_str(), "%d+%d-%dx%d*%f", &x, &y, &width, &height, + &scale) >= 4) { + bounds.SetRect(x, y, width, height); } - return new_display; + + gfx::Display display(synthesized_display_id++); + display.SetScaleAndBounds(scale, bounds); + DVLOG(1) << "Display bounds=" << bounds.ToString() << ", scale=" << scale; + return display; } } // namespace internal diff --git a/ash/display/display_manager.h b/ash/display/display_manager.h index 541ea4b..25be7c1 100644 --- a/ash/display/display_manager.h +++ b/ash/display/display_manager.h @@ -9,7 +9,6 @@ #include <vector> #include "ash/ash_export.h" -#include "ash/display/display_info.h" #include "base/compiler_specific.h" #include "base/gtest_prod_util.h" #include "ui/aura/root_window_observer.h" @@ -77,9 +76,6 @@ class ASH_EXPORT DisplayManager : public aura::RootWindowObserver { // display's bounds change. void SetOverscanInsets(int64 display_id, const gfx::Insets& insets_in_dip); - // Clears the overscan insets - void ClearCustomOverscanInsets(int64 display_id); - // Returns the current overscan insets for the specified |display_id|. // Returns an empty insets (0, 0, 0, 0) if no insets are specified for // the display. @@ -88,11 +84,10 @@ class ASH_EXPORT DisplayManager : public aura::RootWindowObserver { // Called when display configuration has changed. The new display // configurations is passed as a vector of Display object, which // contains each display's new infomration. - void OnNativeDisplaysChanged( - const std::vector<DisplayInfo>& display_info_list); + void OnNativeDisplaysChanged(const std::vector<gfx::Display>& displays); // Updates the internal display data and notifies observers about the changes. - void UpdateDisplays(const std::vector<DisplayInfo>& display_info_list); + void UpdateDisplays(const std::vector<gfx::Display>& displays); // Create a root window for given |display|. aura::RootWindow* CreateRootWindowForDisplay(const gfx::Display& display); @@ -102,8 +97,6 @@ class ASH_EXPORT DisplayManager : public aura::RootWindowObserver { // no longer considered "primary". gfx::Display* GetDisplayAt(size_t index); - const gfx::Display* GetPrimaryDisplayCandidate() const; - size_t GetNumDisplays() const; // Returns the display object nearest given |window|. @@ -118,9 +111,6 @@ class ASH_EXPORT DisplayManager : public aura::RootWindowObserver { const gfx::Display& GetDisplayMatching( const gfx::Rect& match_rect)const; - // Retuns the display info associated with |display|. - const DisplayInfo& GetDisplayInfo(const gfx::Display& display) const; - // Returns the human-readable name for the display specified by |display|. std::string GetDisplayNameFor(const gfx::Display& display); @@ -141,6 +131,29 @@ class ASH_EXPORT DisplayManager : public aura::RootWindowObserver { typedef std::vector<gfx::Display> DisplayList; + // Metadata for each display. + struct DisplayInfo { + DisplayInfo(); + + // The cached name of the display. + std::string name; + + // The original bounds_in_pixel for the display. This can be different from + // the current one in case of overscan insets. + gfx::Rect original_bounds_in_pixel; + + // The overscan insets for the display. + gfx::Insets overscan_insets_in_dip; + + // True if we detect that the display has overscan area. False if the + // display doesn't have it, or failed to detect it. + bool has_overscan; + + // True if the |overscan_insets_in_dip| is specified. This is set because + // the user may specify an empty inset intentionally. + bool has_custom_overscan_insets; + }; + void Init(); void CycleDisplayImpl(); void ScaleDisplayImpl(); @@ -151,26 +164,30 @@ class ASH_EXPORT DisplayManager : public aura::RootWindowObserver { // Refer to |CreateDisplayFromSpec| API for the format of |spec|. void AddDisplayFromSpec(const std::string& spec); + // Set the 1st display as an internal display and returns the display Id for + // the internal display. + int64 SetFirstDisplayAsInternalDisplayForTest(); + // Checks if the mouse pointer is on one of displays, and moves to // the center of the nearest display if it's outside of all displays. void EnsurePointerInDisplays(); - // Inserts and update the DisplayInfo according to the overscan - // state. Note that The DisplayInfo stored in the |internal_display_info_| - // can be different from |new_info| (due to overscan state), so - // you must use |GetDisplayInfo| to get the correct DisplayInfo for - // a display. - void InsertAndUpdateDisplayInfo(const DisplayInfo& new_info, - bool can_overscan); + // Updates |display_info_| by calling platform-dependent functions. + void RefreshDisplayInfo(); + + // Update the display's id in the |display_list| to match the ones + // stored in this display manager's |displays_|. This is used to + // emulate display change behavior during the test byn creating the + // display list with the same display ids but with different bounds + void SetDisplayIdsForTest(DisplayList* display_list) const; - // Creates a display object from the DisplayInfo for |display_id|. - gfx::Display CreateDisplayFromDisplayInfoById(int64 display_id); + // Forcibly specify 'has_overscan' flag of the DisplayInfo for specified |id|. + void SetHasOverscanFlagForTest(int64 id, bool has_overscan); DisplayList displays_; - // An internal display info cache used when the internal display is - // disconnectd. - scoped_ptr<DisplayInfo> internal_display_info_; + // An internal display cache used when the internal display is disconnectd. + scoped_ptr<gfx::Display> internal_display_; bool force_bounds_changed_; @@ -180,6 +197,16 @@ class ASH_EXPORT DisplayManager : public aura::RootWindowObserver { DISALLOW_COPY_AND_ASSIGN(DisplayManager); }; +// Creates a display from string spec. 100+200-1440x800 creates display +// whose size is 1440x800 at the location (100, 200) in screen's coordinates. +// The location can be omitted and be just "1440x800", which creates +// display at the origin of the screen. An empty string creates +// the display with default size. +// The device scale factor can be specified by "*", like "1280x780*2", +// or will use the value of |gfx::Display::GetForcedDeviceScaleFactor()| if +// --force-device-scale-factor is specified. +ASH_EXPORT gfx::Display CreateDisplayFromSpec(const std::string& str); + extern const aura::WindowProperty<int64>* const kDisplayIdKey; } // namespace internal diff --git a/ash/display/display_manager_unittest.cc b/ash/display/display_manager_unittest.cc index b3bba2c..43e2593 100644 --- a/ash/display/display_manager_unittest.cc +++ b/ash/display/display_manager_unittest.cc @@ -8,7 +8,6 @@ #include "ash/screen_ash.h" #include "ash/shell.h" #include "ash/test/ash_test_base.h" -#include "ash/test/display_manager_test_api.h" #include "base/format_macros.h" #include "base/stringprintf.h" #include "ui/aura/env.h" @@ -66,22 +65,10 @@ class DisplayManagerTest : public test::AshTestBase, return root_window_destroyed_; } - const DisplayInfo& GetDisplayInfo(const gfx::Display& display) { - return display_manager()->GetDisplayInfo(display); - } - - const DisplayInfo& GetDisplayInfoAt(int index) { - return GetDisplayInfo(*display_manager()->GetDisplayAt(index)); - } - const gfx::Display& FindDisplayForId(int64 id) { return display_manager()->FindDisplayForId(id); } - const DisplayInfo& FindDisplayInfoForId(int64 id) { - return GetDisplayInfo(display_manager()->FindDisplayForId(id)); - } - // aura::DisplayObserver overrides: virtual void OnDisplayBoundsChanged(const gfx::Display& display) OVERRIDE { changed_.push_back(display); @@ -123,8 +110,7 @@ TEST_F(DisplayManagerTest, NativeDisplayTest) { EXPECT_EQ("0,0 500x500", changed()[0].bounds().ToString()); // Secondary display is on right. EXPECT_EQ("500,0 400x400", added()[0].bounds().ToString()); - EXPECT_EQ("0,501 400x400", - GetDisplayInfo(added()[0]).bounds_in_pixel().ToString()); + EXPECT_EQ("0,501 400x400", added()[0].bounds_in_pixel().ToString()); reset(); // Delete secondary. @@ -146,8 +132,7 @@ TEST_F(DisplayManagerTest, NativeDisplayTest) { EXPECT_EQ(display_manager()->GetDisplayAt(1)->id(), added()[0].id()); // Secondary display is on right. EXPECT_EQ("1000,0 600x400", added()[0].bounds().ToString()); - EXPECT_EQ("1002,0 600x400", - GetDisplayInfo(added()[0]).bounds_in_pixel().ToString()); + EXPECT_EQ("1002,0 600x400", added()[0].bounds_in_pixel().ToString()); reset(); // Secondary removed, primary changed. @@ -159,7 +144,7 @@ TEST_F(DisplayManagerTest, NativeDisplayTest) { reset(); // # of display can go to zero when screen is off. - const vector<DisplayInfo> empty; + const vector<gfx::Display> empty; display_manager()->OnNativeDisplaysChanged(empty); EXPECT_EQ(1U, display_manager()->GetNumDisplays()); EXPECT_EQ("0 0 0", GetCountSummary()); @@ -175,8 +160,7 @@ TEST_F(DisplayManagerTest, NativeDisplayTest) { EXPECT_EQ("1 0 0", GetCountSummary()); EXPECT_FALSE(root_window_destroyed()); EXPECT_EQ("0,0 500x400", changed()[0].bounds().ToString()); - EXPECT_EQ("100,100 500x400", - GetDisplayInfo(changed()[0]).bounds_in_pixel().ToString()); + EXPECT_EQ("100,100 500x400", changed()[0].bounds_in_pixel().ToString()); reset(); // Go back to zero and wake up with multiple displays. @@ -194,7 +178,7 @@ TEST_F(DisplayManagerTest, NativeDisplayTest) { EXPECT_EQ("1000,0 600x400", display_manager()->GetDisplayAt(1)->bounds().ToString()); EXPECT_EQ("1000,1000 600x400", - GetDisplayInfoAt(1).bounds_in_pixel().ToString()); + display_manager()->GetDisplayAt(1)->bounds_in_pixel().ToString()); reset(); } @@ -223,75 +207,74 @@ TEST_F(DisplayManagerTest, OverscanInsetsTest) { UpdateDisplay("0+0-500x500,0+501-400x400"); reset(); ASSERT_EQ(2u, display_manager()->GetNumDisplays()); - const DisplayInfo& display_info1 = GetDisplayInfoAt(0); - const DisplayInfo& display_info2 = GetDisplayInfoAt(1); - display_manager()->SetOverscanInsets( - display_info2.id(), gfx::Insets(13, 12, 11, 10)); + gfx::Display display1(*display_manager()->GetDisplayAt(0)); + gfx::Display display2(*display_manager()->GetDisplayAt(1)); + display_manager()->SetOverscanInsets( + display2.id(), gfx::Insets(13, 12, 11, 10)); std::vector<gfx::Display> changed_displays = changed(); EXPECT_EQ(1u, changed_displays.size()); - EXPECT_EQ(display_info2.id(), changed_displays[0].id()); + EXPECT_EQ(display2.id(), changed_displays[0].id()); EXPECT_EQ("0,0 500x500", - GetDisplayInfoAt(0).bounds_in_pixel().ToString()); + display_manager()->GetDisplayAt(0)->bounds_in_pixel().ToString()); EXPECT_EQ("12,514 378x376", - GetDisplayInfoAt(1).bounds_in_pixel().ToString()); + display_manager()->GetDisplayAt(1)->bounds_in_pixel().ToString()); // Make sure that SetOverscanInsets() is idempotent. - display_manager()->SetOverscanInsets(display_info1.id(), gfx::Insets()); + display_manager()->SetOverscanInsets(display1.id(), gfx::Insets()); display_manager()->SetOverscanInsets( - display_info2.id(), gfx::Insets(13, 12, 11, 10)); + display2.id(), gfx::Insets(13, 12, 11, 10)); EXPECT_EQ("0,0 500x500", - GetDisplayInfoAt(0).bounds_in_pixel().ToString()); + display_manager()->GetDisplayAt(0)->bounds_in_pixel().ToString()); EXPECT_EQ("12,514 378x376", - GetDisplayInfoAt(1).bounds_in_pixel().ToString()); + display_manager()->GetDisplayAt(1)->bounds_in_pixel().ToString()); display_manager()->SetOverscanInsets( - display_info2.id(), gfx::Insets(10, 11, 12, 13)); + display2.id(), gfx::Insets(10, 11, 12, 13)); EXPECT_EQ("0,0 500x500", - GetDisplayInfoAt(0).bounds_in_pixel().ToString()); + display_manager()->GetDisplayAt(0)->bounds_in_pixel().ToString()); EXPECT_EQ("11,511 376x378", - GetDisplayInfoAt(1).bounds_in_pixel().ToString()); + display_manager()->GetDisplayAt(1)->bounds_in_pixel().ToString()); // Recreate a new 2nd display. It won't apply the overscan inset because the // new display has a different ID. UpdateDisplay("0+0-500x500"); UpdateDisplay("0+0-500x500,0+501-400x400"); EXPECT_EQ("0,0 500x500", - GetDisplayInfoAt(0).bounds_in_pixel().ToString()); + display_manager()->GetDisplayAt(0)->bounds_in_pixel().ToString()); EXPECT_EQ("0,501 400x400", - GetDisplayInfoAt(1).bounds_in_pixel().ToString()); + display_manager()->GetDisplayAt(1)->bounds_in_pixel().ToString()); // Recreate the displays with the same ID. It should apply the overscan // inset. UpdateDisplay("0+0-500x500"); - std::vector<DisplayInfo> display_info_list; - display_info_list.push_back(display_info1); - display_info_list.push_back(display_info2); - display_manager()->OnNativeDisplaysChanged(display_info_list); - EXPECT_EQ("1,1 500x500", - GetDisplayInfoAt(0).bounds_in_pixel().ToString()); + std::vector<gfx::Display> displays; + displays.push_back(display1); + displays.push_back(display2); + display_manager()->OnNativeDisplaysChanged(displays); + EXPECT_EQ("0,0 500x500", + display_manager()->GetDisplayAt(0)->bounds_in_pixel().ToString()); EXPECT_EQ("11,511 376x378", - GetDisplayInfoAt(1).bounds_in_pixel().ToString()); + display_manager()->GetDisplayAt(1)->bounds_in_pixel().ToString()); // HiDPI but overscan display. The specified insets size should be doubled. + UpdateDisplay("0+0-500x500"); UpdateDisplay("0+0-500x500,0+501-400x400*2"); display_manager()->SetOverscanInsets( display_manager()->GetDisplayAt(1)->id(), gfx::Insets(4, 5, 6, 7)); EXPECT_EQ("0,0 500x500", - GetDisplayInfoAt(0).bounds_in_pixel().ToString()); + display_manager()->GetDisplayAt(0)->bounds_in_pixel().ToString()); EXPECT_EQ("10,509 376x380", - GetDisplayInfoAt(1).bounds_in_pixel().ToString()); + display_manager()->GetDisplayAt(1)->bounds_in_pixel().ToString()); EXPECT_EQ("188x190", display_manager()->GetDisplayAt(1)->size().ToString()); // Make sure switching primary display applies the overscan offset only once. ash::Shell::GetInstance()->display_controller()->SetPrimaryDisplay( ScreenAsh::GetSecondaryDisplay()); EXPECT_EQ("0,0 500x500", - GetDisplayInfo(ScreenAsh::GetSecondaryDisplay()). - bounds_in_pixel().ToString()); - EXPECT_EQ("10,509 376x380", - GetDisplayInfo(gfx::Screen::GetNativeScreen()->GetPrimaryDisplay()). - bounds_in_pixel().ToString()); + ScreenAsh::GetSecondaryDisplay().bounds_in_pixel().ToString()); + EXPECT_EQ("10,509 376x380", gfx::Screen::GetNativeScreen()-> + GetPrimaryDisplay().bounds_in_pixel().ToString()); } TEST_F(DisplayManagerTest, ZeroOverscanInsets) { @@ -328,93 +311,84 @@ TEST_F(DisplayManagerTest, TestDeviceScaleOnlyChange) { Shell::GetPrimaryRootWindow()->bounds().size().ToString()); } -DisplayInfo CreateDisplayInfo(int64 id, const gfx::Rect& bounds) { - DisplayInfo info(id, std::string(), false); - info.SetBounds(bounds); - return info; -} - TEST_F(DisplayManagerTest, TestNativeDisplaysChanged) { const int64 internal_display_id = - test::DisplayManagerTestApi(display_manager()). - SetFirstDisplayAsInternalDisplay(); - const DisplayInfo native_display_info = - CreateDisplayInfo(internal_display_id, gfx::Rect(0, 0, 500, 500)); - const DisplayInfo external_display_info = - CreateDisplayInfo(10, gfx::Rect(1, 1, 100, 100)); + display_manager()->SetFirstDisplayAsInternalDisplayForTest(); + const gfx::Display native_display(internal_display_id, + gfx::Rect(0, 0, 500, 500)); + const gfx::Display external_display(10, gfx::Rect(1, 1, 100, 100)); EXPECT_EQ(1U, display_manager()->GetNumDisplays()); std::string default_bounds = display_manager()->GetDisplayAt(0)->bounds().ToString(); - std::vector<DisplayInfo> display_info_list; + std::vector<gfx::Display> displays; // Primary disconnected. - display_manager()->OnNativeDisplaysChanged(display_info_list); + display_manager()->OnNativeDisplaysChanged(displays); EXPECT_EQ(1U, display_manager()->GetNumDisplays()); EXPECT_EQ(default_bounds, display_manager()->GetDisplayAt(0)->bounds().ToString()); // External connected while primary was disconnected. - display_info_list.push_back(external_display_info); - display_manager()->OnNativeDisplaysChanged(display_info_list); + displays.push_back(external_display); + display_manager()->OnNativeDisplaysChanged(displays); EXPECT_EQ(2U, display_manager()->GetNumDisplays()); - EXPECT_EQ(default_bounds, FindDisplayForId(internal_display_id).bounds().ToString()); EXPECT_EQ("1,1 100x100", - FindDisplayInfoForId(10).bounds_in_pixel().ToString()); + FindDisplayForId(10).bounds_in_pixel().ToString()); // Primary connected, with different bounds. - display_info_list.clear(); - display_info_list.push_back(native_display_info); - display_info_list.push_back(external_display_info); - display_manager()->OnNativeDisplaysChanged(display_info_list); + displays.clear(); + displays.push_back(native_display); + displays.push_back(external_display); + display_manager()->OnNativeDisplaysChanged(displays); EXPECT_EQ(2U, display_manager()->GetNumDisplays()); EXPECT_EQ("0,0 500x500", FindDisplayForId(internal_display_id).bounds().ToString()); EXPECT_EQ("1,1 100x100", - FindDisplayInfoForId(10).bounds_in_pixel().ToString()); + FindDisplayForId(10).bounds_in_pixel().ToString()); // Turn off primary. - display_info_list.clear(); - display_info_list.push_back(external_display_info); - display_manager()->OnNativeDisplaysChanged(display_info_list); + displays.clear(); + displays.push_back(external_display); + display_manager()->OnNativeDisplaysChanged(displays); EXPECT_EQ(2U, display_manager()->GetNumDisplays()); EXPECT_EQ("0,0 500x500", FindDisplayForId(internal_display_id).bounds().ToString()); EXPECT_EQ("1,1 100x100", - FindDisplayInfoForId(10).bounds_in_pixel().ToString()); + FindDisplayForId(10).bounds_in_pixel().ToString()); // Emulate suspend. - display_info_list.clear(); - display_manager()->OnNativeDisplaysChanged(display_info_list); + displays.clear(); + display_manager()->OnNativeDisplaysChanged(displays); EXPECT_EQ(2U, display_manager()->GetNumDisplays()); EXPECT_EQ("0,0 500x500", FindDisplayForId(internal_display_id).bounds().ToString()); EXPECT_EQ("1,1 100x100", - FindDisplayInfoForId(10).bounds_in_pixel().ToString()); + FindDisplayForId(10).bounds_in_pixel().ToString()); // External display has disconnected then resumed. - display_info_list.push_back(native_display_info); - display_manager()->OnNativeDisplaysChanged(display_info_list); + displays.push_back(native_display); + display_manager()->OnNativeDisplaysChanged(displays); EXPECT_EQ(1U, display_manager()->GetNumDisplays()); EXPECT_EQ("0,0 500x500", FindDisplayForId(internal_display_id).bounds().ToString()); // External display was changed during suspend. - display_info_list.push_back(external_display_info); - display_manager()->OnNativeDisplaysChanged(display_info_list); + displays.push_back(external_display); + display_manager()->OnNativeDisplaysChanged(displays); EXPECT_EQ(2U, display_manager()->GetNumDisplays()); // suspend... - display_info_list.clear(); - display_manager()->OnNativeDisplaysChanged(display_info_list); + displays.clear(); + display_manager()->OnNativeDisplaysChanged(displays); EXPECT_EQ(2U, display_manager()->GetNumDisplays()); // and resume with different external display. - display_info_list.push_back(native_display_info); - display_info_list.push_back(CreateDisplayInfo(11, gfx::Rect(1, 1, 100, 100))); - display_manager()->OnNativeDisplaysChanged(display_info_list); + displays.push_back(native_display); + displays.push_back(gfx::Display(11, gfx::Rect(1, 1, 100, 100))); + display_manager()->OnNativeDisplaysChanged(displays); EXPECT_EQ(2U, display_manager()->GetNumDisplays()); } @@ -432,18 +406,17 @@ TEST_F(DisplayManagerTest, MAYBE_TestNativeDisplaysChangedNoInternal) { EXPECT_EQ(1U, display_manager()->GetNumDisplays()); // Don't change the display info if all displays are disconnected. - std::vector<DisplayInfo> display_info_list; - display_manager()->OnNativeDisplaysChanged(display_info_list); + std::vector<gfx::Display> displays; + display_manager()->OnNativeDisplaysChanged(displays); EXPECT_EQ(1U, display_manager()->GetNumDisplays()); // Connect another display which will become primary. - const DisplayInfo external_display_info = - CreateDisplayInfo(10, gfx::Rect(1, 1, 100, 100)); - display_info_list.push_back(external_display_info); - display_manager()->OnNativeDisplaysChanged(display_info_list); + const gfx::Display external_display(10, gfx::Rect(1, 1, 100, 100)); + displays.push_back(external_display); + display_manager()->OnNativeDisplaysChanged(displays); EXPECT_EQ(1U, display_manager()->GetNumDisplays()); EXPECT_EQ("1,1 100x100", - FindDisplayInfoForId(10).bounds_in_pixel().ToString()); + FindDisplayForId(10).bounds_in_pixel().ToString()); EXPECT_EQ("100x100", ash::Shell::GetPrimaryRootWindow()->GetHostSize().ToString()); } @@ -523,31 +496,29 @@ TEST_F(DisplayManagerTest, EnsurePointerInDisplays_2ndOnLeft) { TEST_F(DisplayManagerTest, NativeDisplaysChangedAfterPrimaryChange) { const int64 internal_display_id = - test::DisplayManagerTestApi(display_manager()). - SetFirstDisplayAsInternalDisplay(); - const DisplayInfo native_display_info = - CreateDisplayInfo(internal_display_id, gfx::Rect(0, 0, 500, 500)); - const DisplayInfo secondary_display_info = - CreateDisplayInfo(10, gfx::Rect(1, 1, 100, 100)); - - std::vector<DisplayInfo> display_info_list; - display_info_list.push_back(native_display_info); - display_info_list.push_back(secondary_display_info); - display_manager()->OnNativeDisplaysChanged(display_info_list); + display_manager()->SetFirstDisplayAsInternalDisplayForTest(); + const gfx::Display native_display(internal_display_id, + gfx::Rect(0, 0, 500, 500)); + const gfx::Display secondary_display(10, gfx::Rect(1, 1, 100, 100)); + + std::vector<gfx::Display> displays; + displays.push_back(native_display); + displays.push_back(secondary_display); + display_manager()->OnNativeDisplaysChanged(displays); EXPECT_EQ(2U, display_manager()->GetNumDisplays()); EXPECT_EQ("0,0 500x500", FindDisplayForId(internal_display_id).bounds().ToString()); EXPECT_EQ("500,0 100x100", FindDisplayForId(10).bounds().ToString()); ash::Shell::GetInstance()->display_controller()->SetPrimaryDisplay( - FindDisplayForId(secondary_display_info.id())); + secondary_display); EXPECT_EQ("-500,0 500x500", FindDisplayForId(internal_display_id).bounds().ToString()); EXPECT_EQ("0,0 100x100", FindDisplayForId(10).bounds().ToString()); // OnNativeDisplaysChanged may change the display bounds. Here makes sure // nothing changed if the exactly same displays are specified. - display_manager()->OnNativeDisplaysChanged(display_info_list); + display_manager()->OnNativeDisplaysChanged(displays); EXPECT_EQ("-500,0 500x500", FindDisplayForId(internal_display_id).bounds().ToString()); EXPECT_EQ("0,0 100x100", FindDisplayForId(10).bounds().ToString()); @@ -556,35 +527,29 @@ TEST_F(DisplayManagerTest, NativeDisplaysChangedAfterPrimaryChange) { TEST_F(DisplayManagerTest, AutomaticOverscanInsets) { UpdateDisplay("200x200,400x400"); - std::vector<DisplayInfo> display_info_list; - display_info_list.push_back(GetDisplayInfoAt(0)); - display_info_list.push_back(GetDisplayInfoAt(1)); - display_info_list[1].set_has_overscan_for_test(true); - int64 id = display_info_list[1].id(); - // SetDefaultOverscanInsets(&display_info_list[1]); - display_manager()->OnNativeDisplaysChanged(display_info_list); + std::vector<gfx::Display> displays; + displays.push_back(*display_manager()->GetDisplayAt(0)); + displays.push_back(*display_manager()->GetDisplayAt(1)); + int64 id = displays[1].id(); + display_manager()->SetHasOverscanFlagForTest(id, true); + + display_manager()->OnNativeDisplaysChanged(displays); // It has overscan insets, although SetOverscanInsets() isn't called. EXPECT_EQ("11,211 380x380", - GetDisplayInfoAt(1).bounds_in_pixel().ToString()); + display_manager()->GetDisplayAt(1)->bounds_in_pixel().ToString()); // If custom overscan insets is specified, the specified value is used. display_manager()->SetOverscanInsets(id, gfx::Insets(5, 6, 7, 8)); - display_manager()->OnNativeDisplaysChanged(display_info_list); + display_manager()->OnNativeDisplaysChanged(displays); EXPECT_EQ("7,206 386x388", - GetDisplayInfoAt(1).bounds_in_pixel().ToString()); + display_manager()->GetDisplayAt(1)->bounds_in_pixel().ToString()); // Do not overscan even though it has 'has_overscan' flag, if the custom // insets is empty. display_manager()->SetOverscanInsets(id, gfx::Insets()); - display_manager()->OnNativeDisplaysChanged(display_info_list); + display_manager()->OnNativeDisplaysChanged(displays); EXPECT_EQ("1,201 400x400", - GetDisplayInfoAt(1).bounds_in_pixel().ToString()); - - // Clearing the custom overscan should set the bounds to - // original. - display_manager()->ClearCustomOverscanInsets(id); - EXPECT_EQ("11,211 380x380", - GetDisplayInfoAt(1).bounds_in_pixel().ToString()); + display_manager()->GetDisplayAt(1)->bounds_in_pixel().ToString()); } } // namespace internal diff --git a/ash/test/ash_test_base.cc b/ash/test/ash_test_base.cc index 853cdff..980777e 100644 --- a/ash/test/ash_test_base.cc +++ b/ash/test/ash_test_base.cc @@ -161,6 +161,16 @@ aura::test::EventGenerator& AshTestBase::GetEventGenerator() { return *event_generator_.get(); } +void AshTestBase::ChangeDisplayConfig(float scale, + const gfx::Rect& bounds_in_pixel) { + gfx::Display display = + gfx::Display(Shell::GetScreen()->GetPrimaryDisplay().id()); + display.SetScaleAndBounds(scale, bounds_in_pixel); + std::vector<gfx::Display> displays; + displays.push_back(display); + Shell::GetInstance()->display_manager()->OnNativeDisplaysChanged(displays); +} + void AshTestBase::UpdateDisplay(const std::string& display_specs) { DisplayManagerTestApi display_manager_test_api( Shell::GetInstance()->display_manager()); diff --git a/ash/test/ash_test_base.h b/ash/test/ash_test_base.h index 3b4bd1d..2541c15 100644 --- a/ash/test/ash_test_base.h +++ b/ash/test/ash_test_base.h @@ -57,6 +57,10 @@ class AshTestBase : public testing::Test { virtual void SetUp() OVERRIDE; virtual void TearDown() OVERRIDE; + // Change the primary display's configuration to use |bounds| + // and |scale|. + void ChangeDisplayConfig(float scale, const gfx::Rect& bounds); + // Update the display configuration as given in |display_specs|. // See ash::test::DisplayManagerTestApi::UpdateDisplay for more details. void UpdateDisplay(const std::string& display_specs); diff --git a/ash/test/display_manager_test_api.cc b/ash/test/display_manager_test_api.cc index 067bbc6..dbfb8495 100644 --- a/ash/test/display_manager_test_api.cc +++ b/ash/test/display_manager_test_api.cc @@ -6,7 +6,6 @@ #include <vector> -#include "ash/display/display_info.h" #include "ash/display/display_manager.h" #include "ash/shell.h" #include "base/string_split.h" @@ -15,27 +14,18 @@ namespace ash { namespace test { -typedef std::vector<gfx::Display> DisplayList; -typedef internal::DisplayInfo DisplayInfo; -typedef std::vector<DisplayInfo> DisplayInfoList; - namespace { -std::vector<DisplayInfo> CreateDisplayInfoListFromString( - const std::string specs, - internal::DisplayManager* display_manager) { - std::vector<DisplayInfo> display_info_list; +std::vector<gfx::Display> CreateDisplaysFromString( + const std::string specs) { + std::vector<gfx::Display> displays; std::vector<std::string> parts; base::SplitString(specs, ',', &parts); - int index = 0; for (std::vector<std::string>::const_iterator iter = parts.begin(); - iter != parts.end(); ++iter, ++index) { - gfx::Display* display = display_manager->GetDisplayAt(index); - int64 id = display ? display->id() : gfx::Display::kInvalidDisplayID; - display_info_list.push_back( - DisplayInfo::CreateFromSpecWithID(*iter, id)); + iter != parts.end(); ++iter) { + displays.push_back(internal::CreateDisplayFromSpec(*iter)); } - return display_info_list; + return displays; } } // namespace @@ -49,12 +39,10 @@ DisplayManagerTestApi::~DisplayManagerTestApi() {} void DisplayManagerTestApi::UpdateDisplay( const std::string& display_specs) { - std::vector<DisplayInfo> display_info_list = - CreateDisplayInfoListFromString(display_specs, display_manager_); + std::vector<gfx::Display> displays = CreateDisplaysFromString(display_specs); bool is_host_origin_set = false; - for (size_t i = 0; i < display_info_list.size(); ++i) { - const DisplayInfo& display_info = display_info_list[i]; - if (display_info.bounds_in_pixel().origin() != gfx::Point(0, 0)) { + for (size_t i = 0; i < displays.size(); ++i) { + if (displays[i].bounds_in_pixel().origin() != gfx::Point(0, 0)) { is_host_origin_set = true; break; } @@ -68,25 +56,18 @@ void DisplayManagerTestApi::UpdateDisplay( // Sart from (1,1) so that windows won't overlap with native mouse cursor. // See |AshTestBase::SetUp()|. int next_y = 1; - for (std::vector<DisplayInfo>::iterator iter = display_info_list.begin(); - iter != display_info_list.end(); ++iter) { - gfx::Rect bounds(iter->bounds_in_pixel().size()); + for (std::vector<gfx::Display>::iterator iter = displays.begin(); + iter != displays.end(); ++iter) { + gfx::Rect bounds(iter->GetSizeInPixel()); bounds.set_x(1); bounds.set_y(next_y); next_y += bounds.height(); - iter->SetBounds(bounds); + iter->SetScaleAndBounds(iter->device_scale_factor(), bounds); } } - display_manager_->OnNativeDisplaysChanged(display_info_list); -} - -int64 DisplayManagerTestApi::SetFirstDisplayAsInternalDisplay() { - const gfx::Display& internal = display_manager_->displays_[0]; - gfx::Display::SetInternalDisplayId(internal.id()); - display_manager_->internal_display_info_.reset(new DisplayInfo( - display_manager_->GetDisplayInfo(internal))); - return gfx::Display::InternalDisplayId(); + display_manager_->SetDisplayIdsForTest(&displays); + display_manager_->OnNativeDisplaysChanged(displays); } } // namespace test diff --git a/ash/test/display_manager_test_api.h b/ash/test/display_manager_test_api.h index e6a83708..57e961d 100644 --- a/ash/test/display_manager_test_api.h +++ b/ash/test/display_manager_test_api.h @@ -27,10 +27,6 @@ class DisplayManagerTestApi { // the format of the display spec. void UpdateDisplay(const std::string& display_specs); - // Set the 1st display as an internal display and returns the display Id for - // the internal display. - int64 SetFirstDisplayAsInternalDisplay(); - private: internal::DisplayManager* display_manager_; // not owned diff --git a/ash/wm/system_gesture_event_filter_unittest.cc b/ash/wm/system_gesture_event_filter_unittest.cc index 391cfbf..a5d345c 100644 --- a/ash/wm/system_gesture_event_filter_unittest.cc +++ b/ash/wm/system_gesture_event_filter_unittest.cc @@ -13,7 +13,6 @@ #include "ash/system/brightness/brightness_control_delegate.h" #include "ash/system/tray/system_tray_delegate.h" #include "ash/test/ash_test_base.h" -#include "ash/test/display_manager_test_api.h" #include "ash/test/shell_test_api.h" #include "ash/test/test_launcher_delegate.h" #include "ash/volume_control_delegate.h" @@ -217,8 +216,8 @@ class SystemGestureEventFilterTest : public AshTestBase { ::switches::kEnableBezelTouch); test::AshTestBase::SetUp(); // Enable brightness key. - test::DisplayManagerTestApi(Shell::GetInstance()->display_manager()). - SetFirstDisplayAsInternalDisplay(); + Shell::GetInstance()->display_manager()-> + SetFirstDisplayAsInternalDisplayForTest(); } private: diff --git a/ui/aura/root_window.cc b/ui/aura/root_window.cc index 7ff474f..7305ca7 100644 --- a/ui/aura/root_window.cc +++ b/ui/aura/root_window.cc @@ -196,7 +196,6 @@ gfx::Size RootWindow::GetHostSize() const { } void RootWindow::SetHostBounds(const gfx::Rect& bounds_in_pixel) { - DCHECK(!bounds_in_pixel.IsEmpty()); DispatchHeldMouseMove(); host_->SetBounds(bounds_in_pixel); synthesize_mouse_move_ = false; diff --git a/ui/base/x/events_x.cc b/ui/base/x/events_x.cc index e4ca121..3fba257f0 100644 --- a/ui/base/x/events_x.cc +++ b/ui/base/x/events_x.cc @@ -718,10 +718,10 @@ gfx::Point CalibrateTouchCoordinates( !top_border_touch_calibration && !bottom_border_touch_calibration) return gfx::Point(x, y); - gfx::Display display = gfx::Screen::GetNativeScreen()->GetPrimaryDisplay(); - gfx::Rect bounds = display.bounds(); - const int resolution_x = bounds.width() * display.device_scale_factor(); - const int resolution_y = bounds.height() * display.device_scale_factor(); + gfx::Rect bounds = + gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().bounds_in_pixel(); + const int resolution_x = bounds.width(); + const int resolution_y = bounds.height(); // The "grace area" (10% in this case) is to make it easier for the user to // navigate to the corner. const double kGraceAreaFraction = 0.1; diff --git a/ui/base/x/x11_util.cc b/ui/base/x/x11_util.cc index ad59097..cb57e09 100644 --- a/ui/base/x/x11_util.cc +++ b/ui/base/x/x11_util.cc @@ -1488,6 +1488,16 @@ bool ParseOutputOverscanFlag(const unsigned char* prop, return false; } +std::vector<std::string> GetDisplayNames(const std::vector<XID>& output_ids) { + std::vector<std::string> names; + for (size_t i = 0; i < output_ids.size(); ++i) { + std::string display_name; + if (GetOutputDeviceData(output_ids[i], NULL, NULL, &display_name)) + names.push_back(display_name); + } + return names; +} + std::vector<std::string> GetOutputNames(const std::vector<XID>& output_ids) { std::vector<std::string> names; Display* display = GetXDisplay(); diff --git a/ui/base/x/x11_util.h b/ui/base/x/x11_util.h index 1169f87..377dd41 100644 --- a/ui/base/x/x11_util.h +++ b/ui/base/x/x11_util.h @@ -303,9 +303,13 @@ UI_EXPORT bool ParseOutputOverscanFlag(const unsigned char* prop, unsigned long nitems, bool* flag); -// Gets the name of outputs given by |output_ids|. +// Gets the names of the all displays physically connected to the system. +UI_EXPORT std::vector<std::string> GetDisplayNames( + const std::vector<XID>& output_id); + +// Gets the name of outputs given by |output_id|. UI_EXPORT std::vector<std::string> GetOutputNames( - const std::vector<XID>& output_ids); + const std::vector<XID>& output_id); enum WindowManagerName { WM_UNKNOWN, diff --git a/ui/gfx/display.cc b/ui/gfx/display.cc index 73f33b3..7aa1241 100644 --- a/ui/gfx/display.cc +++ b/ui/gfx/display.cc @@ -11,7 +11,6 @@ #include "ui/base/ui_base_switches.h" #include "ui/base/win/dpi.h" #include "ui/gfx/insets.h" -#include "ui/gfx/point_f.h" #include "ui/gfx/size_conversions.h" namespace gfx { @@ -104,19 +103,22 @@ void Display::SetScaleAndBounds( device_scale_factor_ = device_scale_factor; } device_scale_factor_ = std::max(1.0f, device_scale_factor_); +#if defined(USE_AURA) + bounds_in_pixel_ = bounds_in_pixel; +#endif bounds_ = gfx::Rect(gfx::ToFlooredSize( gfx::ScaleSize(bounds_in_pixel.size(), 1.0f / device_scale_factor_))); UpdateWorkAreaFromInsets(insets); } void Display::SetSize(const gfx::Size& size_in_pixel) { - gfx::Point origin = bounds_.origin(); + SetScaleAndBounds( + device_scale_factor_, #if defined(USE_AURA) - gfx::PointF origin_f = origin; - origin_f.Scale(device_scale_factor_); - origin.SetPoint(origin_f.x(), origin_f.y()); + gfx::Rect(bounds_in_pixel_.origin(), size_in_pixel)); +#else + gfx::Rect(bounds_.origin(), size_in_pixel)); #endif - SetScaleAndBounds(device_scale_factor_, gfx::Rect(origin, size_in_pixel)); } void Display::UpdateWorkAreaFromInsets(const gfx::Insets& insets) { diff --git a/ui/gfx/display.h b/ui/gfx/display.h index 81963f2..4df69b7 100644 --- a/ui/gfx/display.h +++ b/ui/gfx/display.h @@ -88,6 +88,13 @@ class UI_EXPORT Display { // Returns the display's size in pixel coordinates. gfx::Size GetSizeInPixel() const; +#if defined(USE_AURA) + // TODO(oshima|skuhne): Eliminate the use of bounds_in_pixel in events_x.cc + // and remove bounds_in_pixel from gfx::Display. + // Returns the display's bounds in pixel coordinates. + const Rect& bounds_in_pixel() const { return bounds_in_pixel_; } +#endif + // Returns a string representation of the display; std::string ToString() const; @@ -107,6 +114,9 @@ class UI_EXPORT Display { int64 id_; Rect bounds_; Rect work_area_; +#if defined(USE_AURA) + Rect bounds_in_pixel_; +#endif float device_scale_factor_; }; |