Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / ash / display / display_manager.cc
index 0f3bdda..f3b7a20 100644 (file)
@@ -4,6 +4,7 @@
 
 #include "ash/display/display_manager.h"
 
+#include <algorithm>
 #include <cmath>
 #include <set>
 #include <string>
@@ -27,6 +28,8 @@
 #include "ui/base/layout.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/display.h"
+#include "ui/gfx/display_observer.h"
+#include "ui/gfx/font_render_params.h"
 #include "ui/gfx/rect.h"
 #include "ui/gfx/screen.h"
 #include "ui/gfx/size_conversions.h"
@@ -64,6 +67,7 @@ const int kMinimumOverlapForInvalidOffset = 100;
 // for the full list of resolutions.
 const float kUIScalesFor2x[] =
     {0.5f, 0.625f, 0.8f, 1.0f, 1.125f, 1.25f, 1.5f, 2.0f};
+const float kUIScalesFor1_25x[] = {0.5f, 0.625f, 0.8f, 1.0f, 1.25f };
 const float kUIScalesFor1280[] = {0.5f, 0.625f, 0.8f, 1.0f, 1.125f };
 const float kUIScalesFor1366[] = {0.5f, 0.6f, 0.75f, 1.0f, 1.125f };
 
@@ -80,9 +84,12 @@ struct DisplayInfoSortFunctor {
 };
 
 struct DisplayModeMatcher {
-  DisplayModeMatcher(const gfx::Size& size) : size(size) {}
-  bool operator()(const DisplayMode& mode) { return mode.size == size; }
-  gfx::Size size;
+  DisplayModeMatcher(const DisplayMode& target_mode)
+      : target_mode(target_mode) {}
+  bool operator()(const DisplayMode& mode) {
+    return target_mode.IsEquivalent(mode);
+  }
+  DisplayMode target_mode;
 };
 
 struct ScaleComparator {
@@ -177,28 +184,35 @@ DisplayManager::DisplayManager()
 }
 
 DisplayManager::~DisplayManager() {
+#if defined(OS_CHROMEOS)
+  // Reset the font params.
+  gfx::SetFontRenderParamsDeviceScaleFactor(1.0f);
+#endif
 }
 
 // static
 std::vector<float> DisplayManager::GetScalesForDisplay(
     const DisplayInfo& info) {
+
+#define ASSIGN_ARRAY(v, a) v.assign(a, a + arraysize(a))
+
   std::vector<float> ret;
   if (info.device_scale_factor() == 2.0f) {
-    ret.assign(kUIScalesFor2x, kUIScalesFor2x + arraysize(kUIScalesFor2x));
+    ASSIGN_ARRAY(ret, kUIScalesFor2x);
+    return ret;
+  } else if (info.device_scale_factor() == 1.25f) {
+    ASSIGN_ARRAY(ret, kUIScalesFor1_25x);
     return ret;
   }
   switch (info.bounds_in_native().width()) {
     case 1280:
-      ret.assign(kUIScalesFor1280,
-                 kUIScalesFor1280 + arraysize(kUIScalesFor1280));
+      ASSIGN_ARRAY(ret, kUIScalesFor1280);
       break;
     case 1366:
-      ret.assign(kUIScalesFor1366,
-                 kUIScalesFor1366 + arraysize(kUIScalesFor1366));
+      ASSIGN_ARRAY(ret, kUIScalesFor1366);
       break;
     default:
-      ret.assign(kUIScalesFor1280,
-                 kUIScalesFor1280 + arraysize(kUIScalesFor1280));
+      ASSIGN_ARRAY(ret, kUIScalesFor1280);
 #if defined(OS_CHROMEOS)
       if (base::SysInfo::IsRunningOnChromeOS())
         NOTREACHED() << "Unknown resolution:" << info.ToString();
@@ -253,6 +267,17 @@ void DisplayManager::InitDefaultDisplay() {
   OnNativeDisplaysChanged(info_list);
 }
 
+void DisplayManager::InitFontParams() {
+#if defined(OS_CHROMEOS)
+  if (!HasInternalDisplay())
+    return;
+  const DisplayInfo& display_info =
+      GetDisplayInfo(gfx::Display::InternalDisplayId());
+  gfx::SetFontRenderParamsDeviceScaleFactor(
+      display_info.device_scale_factor());
+#endif  // OS_CHROMEOS
+}
+
 // static
 void DisplayManager::UpdateDisplayBoundsForLayoutById(
     const DisplayLayout& layout,
@@ -347,8 +372,10 @@ void DisplayManager::SetLayoutForCurrentDisplays(
 
     // Primary's bounds stay the same. Just notify bounds change
     // on the secondary.
-    screen_ash_->NotifyBoundsChanged(
-        ScreenUtil::GetSecondaryDisplay());
+    screen_ash_->NotifyMetricsChanged(
+        ScreenUtil::GetSecondaryDisplay(),
+        gfx::DisplayObserver::DISPLAY_METRIC_BOUNDS |
+            gfx::DisplayObserver::DISPLAY_METRIC_WORK_AREA);
     if (delegate_)
       delegate_->PostDisplayConfigurationChange();
   }
@@ -422,6 +449,7 @@ void DisplayManager::SetDisplayUIScale(int64 display_id,
     return;
   }
 
+  // TODO(mukai): merge this implementation into SetDisplayMode().
   DisplayInfoList display_info_list;
   for (DisplayList::const_iterator iter = displays_.begin();
        iter != displays_.end(); ++iter) {
@@ -451,8 +479,10 @@ void DisplayManager::SetDisplayResolution(int64 display_id,
   const DisplayInfo& display_info = GetDisplayInfo(display_id);
   const std::vector<DisplayMode>& modes = display_info.display_modes();
   DCHECK_NE(0u, modes.size());
+  DisplayMode target_mode;
+  target_mode.size = resolution;
   std::vector<DisplayMode>::const_iterator iter =
-      std::find_if(modes.begin(), modes.end(), DisplayModeMatcher(resolution));
+      std::find_if(modes.begin(), modes.end(), DisplayModeMatcher(target_mode));
   if (iter == modes.end()) {
     LOG(WARNING) << "Unsupported resolution was requested:"
                  << resolution.ToString();
@@ -465,12 +495,58 @@ void DisplayManager::SetDisplayResolution(int64 display_id,
 #endif
 }
 
+bool DisplayManager::SetDisplayMode(int64 display_id,
+                                    const DisplayMode& display_mode) {
+  if (IsInternalDisplayId(display_id)) {
+    SetDisplayUIScale(display_id, display_mode.ui_scale);
+    return false;
+  }
+
+  DisplayInfoList display_info_list;
+  bool display_property_changed = false;
+  bool resolution_changed = false;
+  for (DisplayList::const_iterator iter = displays_.begin();
+       iter != displays_.end(); ++iter) {
+    DisplayInfo info = GetDisplayInfo(iter->id());
+    if (info.id() == display_id) {
+      const std::vector<DisplayMode>& modes = info.display_modes();
+      std::vector<DisplayMode>::const_iterator iter =
+          std::find_if(modes.begin(),
+                       modes.end(),
+                       DisplayModeMatcher(display_mode));
+      if (iter == modes.end()) {
+        LOG(WARNING) << "Unsupported resolution was requested:"
+                     << display_mode.size.ToString();
+        return false;
+      }
+      display_modes_[display_id] = *iter;
+      if (info.bounds_in_native().size() != display_mode.size)
+        resolution_changed = true;
+      if (info.device_scale_factor() != display_mode.device_scale_factor) {
+        info.set_device_scale_factor(display_mode.device_scale_factor);
+        display_property_changed = true;
+      }
+    }
+    display_info_list.push_back(info);
+  }
+  if (display_property_changed) {
+    AddMirrorDisplayInfoIfAny(&display_info_list);
+    UpdateDisplays(display_info_list);
+  }
+#if defined(OS_CHROMEOS)
+  if (resolution_changed && base::SysInfo::IsRunningOnChromeOS())
+    Shell::GetInstance()->display_configurator()->OnConfigurationChanged();
+#endif
+  return resolution_changed;
+}
+
 void DisplayManager::RegisterDisplayProperty(
     int64 display_id,
     gfx::Display::Rotation rotation,
     float ui_scale,
     const gfx::Insets* overscan_insets,
     const gfx::Size& resolution_in_pixels,
+    float device_scale_factor,
     ui::ColorCalibrationProfile color_profile) {
   if (display_info_.find(display_id) == display_info_.end())
     display_info_[display_id] = DisplayInfo(display_id, std::string(), false);
@@ -478,16 +554,47 @@ void DisplayManager::RegisterDisplayProperty(
   display_info_[display_id].set_rotation(rotation);
   display_info_[display_id].SetColorProfile(color_profile);
   // Just in case the preference file was corrupted.
+  // TODO(mukai): register |display_modes_| here as well, so the lookup for the
+  // default mode in GetActiveModeForDisplayId() gets much simpler.
   if (0.5f <= ui_scale && ui_scale <= 2.0f)
     display_info_[display_id].set_configured_ui_scale(ui_scale);
   if (overscan_insets)
     display_info_[display_id].SetOverscanInsets(*overscan_insets);
   if (!resolution_in_pixels.IsEmpty()) {
+    DCHECK(!IsInternalDisplayId(display_id));
     // Default refresh rate, until OnNativeDisplaysChanged() updates us with the
     // actual display info, is 60 Hz.
-    display_modes_[display_id] =
-        DisplayMode(resolution_in_pixels, 60.0f, false, false);
+    DisplayMode mode(resolution_in_pixels, 60.0f, false, false);
+    mode.device_scale_factor = device_scale_factor;
+    display_modes_[display_id] = mode;
+  }
+}
+
+DisplayMode DisplayManager::GetActiveModeForDisplayId(int64 display_id) const {
+  DisplayMode selected_mode;
+  if (GetSelectedModeForDisplayId(display_id, &selected_mode))
+    return selected_mode;
+
+  // If 'selected' mode is empty, it should return the default mode. This means
+  // the native mode for the external display. Unfortunately this is not true
+  // for the internal display because restoring UI-scale doesn't register the
+  // restored mode to |display_mode_|, so it needs to look up the mode whose
+  // UI-scale value matches. See the TODO in RegisterDisplayProperty().
+  const DisplayInfo& info = GetDisplayInfo(display_id);
+  const std::vector<DisplayMode>& display_modes = info.display_modes();
+
+  if (IsInternalDisplayId(display_id)) {
+    for (size_t i = 0; i < display_modes.size(); ++i) {
+      if (info.configured_ui_scale() == display_modes[i].ui_scale)
+        return display_modes[i];
+    }
+  } else {
+    for (size_t i = 0; i < display_modes.size(); ++i) {
+      if (display_modes[i].native)
+        return display_modes[i];
+    }
   }
+  return selected_mode;
 }
 
 bool DisplayManager::GetSelectedModeForDisplayId(int64 id,
@@ -590,7 +697,10 @@ void DisplayManager::OnNativeDisplaysChanged(
       new_display_info_list.push_back(*iter);
     }
 
-    const gfx::Size& resolution = iter->bounds_in_native().size();
+    DisplayMode new_mode;
+    new_mode.size = iter->bounds_in_native().size();
+    new_mode.device_scale_factor = iter->device_scale_factor();
+    new_mode.ui_scale = iter->configured_ui_scale();
     const std::vector<DisplayMode>& display_modes = iter->display_modes();
     // This is empty the displays are initialized from InitFromCommandLine.
     if (!display_modes.size())
@@ -598,7 +708,7 @@ void DisplayManager::OnNativeDisplaysChanged(
     std::vector<DisplayMode>::const_iterator display_modes_iter =
         std::find_if(display_modes.begin(),
                      display_modes.end(),
-                     DisplayModeMatcher(resolution));
+                     DisplayModeMatcher(new_mode));
     // Update the actual resolution selected as the resolution request may fail.
     if (display_modes_iter == display_modes.end())
       display_modes_.erase(iter->id());
@@ -632,11 +742,9 @@ void DisplayManager::UpdateDisplays() {
 void DisplayManager::UpdateDisplays(
     const std::vector<DisplayInfo>& updated_display_info_list) {
 #if defined(OS_WIN)
-  if (base::win::GetVersion() >= base::win::VERSION_WIN8) {
-    DCHECK_EQ(1u, updated_display_info_list.size()) <<
-        "Multiple display test does not work on Win8 bots. Please "
-        "skip (don't disable) the test using SupportsMultipleDisplays()";
-  }
+  DCHECK_EQ(1u, updated_display_info_list.size()) <<
+      ": Multiple display test does not work on Windows bots. Please "
+      "skip (don't disable) the test using SupportsMultipleDisplays()";
 #endif
 
   DisplayInfoList new_display_info_list = updated_display_info_list;
@@ -645,7 +753,7 @@ void DisplayManager::UpdateDisplays(
             new_display_info_list.end(),
             DisplayInfoSortFunctor());
   DisplayList removed_displays;
-  std::vector<size_t> changed_display_indices;
+  std::map<size_t, uint32_t> display_changes;
   std::vector<size_t> added_display_indices;
 
   DisplayList::iterator curr_iter = displays_.begin();
@@ -715,18 +823,32 @@ void DisplayManager::UpdateDisplays(
           CreateDisplayFromDisplayInfoById(new_info_iter->id());
       const DisplayInfo& new_display_info = GetDisplayInfo(new_display.id());
 
-      bool host_window_bounds_changed =
-          current_display_info.bounds_in_native() !=
-          new_display_info.bounds_in_native();
+      uint32_t metrics = gfx::DisplayObserver::DISPLAY_METRIC_NONE;
 
-      if (force_bounds_changed_ ||
-          host_window_bounds_changed ||
-          (current_display.device_scale_factor() !=
-           new_display.device_scale_factor()) ||
+      // At that point the new Display objects we have are not entirely updated,
+      // they are missing the translation related to the Display disposition in
+      // the layout.
+      // Using display.bounds() and display.work_area() would fail most of the
+      // time.
+      if (force_bounds_changed_ || (current_display_info.bounds_in_native() !=
+                                    new_display_info.bounds_in_native()) ||
           (current_display_info.size_in_pixel() !=
-           new_display.GetSizeInPixel()) ||
-          (current_display.rotation() != new_display.rotation())) {
-        changed_display_indices.push_back(new_displays.size());
+           new_display.GetSizeInPixel())) {
+        metrics |= gfx::DisplayObserver::DISPLAY_METRIC_BOUNDS |
+                   gfx::DisplayObserver::DISPLAY_METRIC_WORK_AREA;
+      }
+
+      if (current_display.device_scale_factor() !=
+          new_display.device_scale_factor()) {
+        metrics |= gfx::DisplayObserver::DISPLAY_METRIC_DEVICE_SCALE_FACTOR;
+      }
+
+      if (current_display.rotation() != new_display.rotation())
+        metrics |= gfx::DisplayObserver::DISPLAY_METRIC_ROTATION;
+
+      if (metrics != gfx::DisplayObserver::DISPLAY_METRIC_NONE) {
+        display_changes.insert(
+            std::pair<size_t, uint32_t>(new_displays.size(), metrics));
       }
 
       new_display.UpdateWorkAreaFromInsets(current_display.GetWorkAreaInsets());
@@ -753,7 +875,7 @@ void DisplayManager::UpdateDisplays(
   // Do not update |displays_| if there's nothing to be updated. Without this,
   // it will not update the display layout, which causes the bug
   // http://crbug.com/155948.
-  if (changed_display_indices.empty() && added_display_indices.empty() &&
+  if (display_changes.empty() && added_display_indices.empty() &&
       removed_displays.empty()) {
     return;
   }
@@ -770,11 +892,13 @@ void DisplayManager::UpdateDisplays(
   if (UpdateSecondaryDisplayBoundsForLayout(&new_displays, &updated_index) &&
       std::find(added_display_indices.begin(),
                 added_display_indices.end(),
-                updated_index) == added_display_indices.end() &&
-      std::find(changed_display_indices.begin(),
-                changed_display_indices.end(),
-                updated_index) == changed_display_indices.end()) {
-    changed_display_indices.push_back(updated_index);
+                updated_index) == added_display_indices.end()) {
+    uint32_t metrics = gfx::DisplayObserver::DISPLAY_METRIC_BOUNDS |
+                       gfx::DisplayObserver::DISPLAY_METRIC_WORK_AREA;
+    if (display_changes.find(updated_index) != display_changes.end())
+      metrics |= display_changes[updated_index];
+
+    display_changes[updated_index] = metrics;
   }
 
   displays_ = new_displays;
@@ -803,15 +927,16 @@ void DisplayManager::UpdateDisplays(
   // it can mirror the display newly added. This can happen when switching
   // from dock mode to software mirror mode.
   non_desktop_display_updater.reset();
-  for (std::vector<size_t>::iterator iter = changed_display_indices.begin();
-       iter != changed_display_indices.end(); ++iter) {
-    screen_ash_->NotifyBoundsChanged(displays_[*iter]);
+  for (std::map<size_t, uint32_t>::iterator iter = display_changes.begin();
+       iter != display_changes.end();
+       ++iter) {
+    screen_ash_->NotifyMetricsChanged(displays_[iter->first], iter->second);
   }
   if (delegate_)
     delegate_->PostDisplayConfigurationChange();
 
 #if defined(USE_X11) && defined(OS_CHROMEOS)
-  if (!changed_display_indices.empty() && base::SysInfo::IsRunningOnChromeOS())
+  if (!display_changes.empty() && base::SysInfo::IsRunningOnChromeOS())
     ui::ClearX11DefaultRootWindow();
 #endif
 }
@@ -938,6 +1063,10 @@ void DisplayManager::SetSoftwareMirroring(bool enabled) {
     return;
   SetSecondDisplayMode(enabled ? MIRRORING : EXTENDED);
 }
+
+bool DisplayManager::SoftwareMirroringEnabled() const {
+  return software_mirroring_enabled();
+}
 #endif
 
 void DisplayManager::SetSecondDisplayMode(SecondDisplayMode mode) {
@@ -955,7 +1084,8 @@ bool DisplayManager::UpdateDisplayBounds(int64 display_id,
       return false;
     gfx::Display* display = FindDisplayForId(display_id);
     display->SetSize(display_info_[display_id].size_in_pixel());
-    screen_ash_->NotifyBoundsChanged(*display);
+    screen_ash_->NotifyMetricsChanged(
+        *display, gfx::DisplayObserver::DISPLAY_METRIC_BOUNDS);
     return true;
   }
   return false;