Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / ui / display / chromeos / display_configurator.cc
index 1283b58..f25f05a 100644 (file)
@@ -22,10 +22,16 @@ namespace {
 
 typedef std::vector<const DisplayMode*> DisplayModeList;
 
-// The delay to perform configuration after RRNotify.  See the comment
-// in |Dispatch()|.
+// The delay to perform configuration after RRNotify. See the comment for
+// |configure_timer_|.
 const int kConfigureDelayMs = 500;
 
+// The delay spent before reading the display configuration after coming out of
+// suspend. While coming out of suspend the display state may be updating. This
+// is used to wait until the hardware had a chance to update the display state
+// such that we read an up to date state.
+const int kResumeDelayMs = 500;
+
 // Returns a string describing |state|.
 std::string DisplayPowerStateToString(chromeos::DisplayPowerState state) {
   switch (state) {
@@ -89,11 +95,11 @@ int GetDisplayPower(
 
 }  // namespace
 
-DisplayConfigurator::CoordinateTransformation::CoordinateTransformation()
-    : x_scale(1.0),
-      x_offset(0.0),
-      y_scale(1.0),
-      y_offset(0.0) {}
+
+const int DisplayConfigurator::kSetDisplayPowerNoFlags = 0;
+const int DisplayConfigurator::kSetDisplayPowerForceProbe = 1 << 0;
+const int
+DisplayConfigurator::kSetDisplayPowerOnlyIfSingleInternalDisplay = 1 << 1;
 
 DisplayConfigurator::DisplayState::DisplayState()
     : display(NULL),
@@ -102,10 +108,9 @@ DisplayConfigurator::DisplayState::DisplayState()
       mirror_mode(NULL) {}
 
 bool DisplayConfigurator::TestApi::TriggerConfigureTimeout() {
-  if (configurator_->configure_timer_.get() &&
-      configurator_->configure_timer_->IsRunning()) {
-    configurator_->configure_timer_.reset();
-    configurator_->ConfigureDisplays();
+  if (configurator_->configure_timer_.IsRunning()) {
+    configurator_->configure_timer_.user_task().Run();
+    configurator_->configure_timer_.Stop();
     return true;
   } else {
     return false;
@@ -170,7 +175,8 @@ void DisplayConfigurator::SetDelegatesForTesting(
   DCHECK(!native_display_delegate_);
   DCHECK(!touchscreen_delegate_);
 
-  InitializeDelegates(display_delegate.Pass(), touchscreen_delegate.Pass());
+  native_display_delegate_ = display_delegate.Pass();
+  touchscreen_delegate_ = touchscreen_delegate.Pass();
   configure_display_ = true;
 }
 
@@ -185,18 +191,15 @@ void DisplayConfigurator::Init(bool is_panel_fitting_enabled) {
   if (!configure_display_)
     return;
 
-  PlatformInitialize();
-}
-
-void DisplayConfigurator::InitializeDelegates(
-    scoped_ptr<NativeDisplayDelegate> display_delegate,
-    scoped_ptr<TouchscreenDelegate> touchscreen_delegate) {
-  if (!native_display_delegate_ && !touchscreen_delegate_) {
-    native_display_delegate_ = display_delegate.Pass();
-    touchscreen_delegate_ = touchscreen_delegate.Pass();
-
+  // If the delegates are already initialized don't update them (For example,
+  // tests set their own delegates).
+  if (!native_display_delegate_) {
+    native_display_delegate_ = CreatePlatformNativeDisplayDelegate();
     native_display_delegate_->AddObserver(this);
   }
+
+  if (!touchscreen_delegate_)
+    touchscreen_delegate_ = CreatePlatformTouchscreenDelegate();
 }
 
 void DisplayConfigurator::ForceInitialConfigure(
@@ -221,15 +224,33 @@ void DisplayConfigurator::ForceInitialConfigure(
   NotifyObservers(success, new_state);
 }
 
+bool DisplayConfigurator::IsMirroring() const {
+  return display_state_ == MULTIPLE_DISPLAY_STATE_DUAL_MIRROR ||
+      (mirroring_controller_ &&
+       mirroring_controller_->SoftwareMirroringEnabled());
+}
+
 bool DisplayConfigurator::ApplyProtections(const ContentProtections& requests) {
   for (DisplayStateList::const_iterator it = cached_displays_.begin();
        it != cached_displays_.end();
        ++it) {
     uint32_t all_desired = 0;
-    ContentProtections::const_iterator request_it =
-        requests.find(it->display->display_id());
-    if (request_it != requests.end())
-      all_desired = request_it->second;
+
+    // In mirror mode, protection request of all displays need to be fulfilled.
+    // In non-mirror mode, only request of client's display needs to be
+    // fulfilled.
+    ContentProtections::const_iterator request_it;
+    if (IsMirroring()) {
+      for (request_it = requests.begin();
+           request_it != requests.end();
+           ++request_it)
+        all_desired |= request_it->second;
+    } else {
+      request_it = requests.find(it->display->display_id());
+      if (request_it != requests.end())
+        all_desired = request_it->second;
+    }
+
     switch (it->display->type()) {
       case DISPLAY_CONNECTION_TYPE_UNKNOWN:
         return false;
@@ -300,8 +321,10 @@ bool DisplayConfigurator::QueryContentProtectionStatus(
   for (DisplayStateList::const_iterator it = cached_displays_.begin();
        it != cached_displays_.end();
        ++it) {
-    if (it->display->display_id() != display_id)
+    // Query display if it is in mirror mode or client on the same display.
+    if (!IsMirroring() && it->display->display_id() != display_id)
       continue;
+
     *link_mask |= it->display->type();
     switch (it->display->type()) {
       case DISPLAY_CONNECTION_TYPE_UNKNOWN:
@@ -425,8 +448,7 @@ bool DisplayConfigurator::SetDisplayPower(
   VLOG(1) << "SetDisplayPower: power_state="
           << DisplayPowerStateToString(power_state) << " flags=" << flags
           << ", configure timer="
-          << ((configure_timer_.get() && configure_timer_->IsRunning()) ?
-                  "Running" : "Stopped");
+          << (configure_timer_.IsRunning() ? "Running" : "Stopped");
   if (power_state == power_state_ && !(flags & kSetDisplayPowerForceProbe))
     return true;
 
@@ -487,11 +509,15 @@ bool DisplayConfigurator::SetDisplayMode(MultipleDisplayState new_state) {
 void DisplayConfigurator::OnConfigurationChanged() {
   // Configure displays with |kConfigureDelayMs| delay,
   // so that time-consuming ConfigureDisplays() won't be called multiple times.
-  if (configure_timer_.get()) {
-    configure_timer_->Reset();
+  if (configure_timer_.IsRunning()) {
+    // Note: when the timer is running it is possible that a different task
+    // (SetDisplayPower()) is scheduled. In these cases, prefer the already
+    // scheduled task to ConfigureDisplays() since ConfigureDisplays() performs
+    // only basic configuration while SetDisplayPower() will perform additional
+    // operations.
+    configure_timer_.Reset();
   } else {
-    configure_timer_.reset(new base::OneShotTimer<DisplayConfigurator>());
-    configure_timer_->Start(
+    configure_timer_.Start(
         FROM_HERE,
         base::TimeDelta::FromMilliseconds(kConfigureDelayMs),
         this,
@@ -527,7 +553,13 @@ void DisplayConfigurator::SuspendDisplays() {
 void DisplayConfigurator::ResumeDisplays() {
   // Force probing to ensure that we pick up any changes that were made
   // while the system was suspended.
-  SetDisplayPower(power_state_, kSetDisplayPowerForceProbe);
+  configure_timer_.Start(
+      FROM_HERE,
+      base::TimeDelta::FromMilliseconds(kResumeDelayMs),
+      base::Bind(base::IgnoreResult(&DisplayConfigurator::SetDisplayPower),
+                 base::Unretained(this),
+                 power_state_,
+                 kSetDisplayPowerForceProbe));
 }
 
 void DisplayConfigurator::UpdateCachedDisplays() {
@@ -675,8 +707,6 @@ bool DisplayConfigurator::FindMirrorMode(DisplayState* internal_display,
 }
 
 void DisplayConfigurator::ConfigureDisplays() {
-  configure_timer_.reset();
-
   if (!configure_display_)
     return;
 
@@ -763,8 +793,11 @@ bool DisplayConfigurator::EnterState(MultipleDisplayState display_state,
 
         if (display_power[i] || cached_displays_.size() == 1) {
           const DisplayMode* mode_info = state->selected_mode;
-          if (!mode_info)
+          if (!mode_info) {
+            LOG(WARNING) << "No selected mode when configuring display: "
+                         << state->display->ToString();
             return false;
+          }
           if (mode_info->size() == gfx::Size(1024, 768)) {
             VLOG(1) << "Potentially misdetecting display(1024x768):"
                     << " displays size=" << cached_displays_.size()
@@ -788,23 +821,16 @@ bool DisplayConfigurator::EnterState(MultipleDisplayState display_state,
       }
 
       const DisplayMode* mode_info = cached_displays_[0].mirror_mode;
-      if (!mode_info)
+      if (!mode_info) {
+        LOG(WARNING) << "No mirror mode when configuring display: "
+                     << cached_displays_[0].display->ToString();
         return false;
+      }
       size = mode_info->size();
 
       for (size_t i = 0; i < cached_displays_.size(); ++i) {
         DisplayState* state = &cached_displays_[i];
         new_mode[i] = display_power[i] ? state->mirror_mode : NULL;
-        if (state->touch_device_id) {
-          // CTM needs to be calculated if aspect preserving scaling is used.
-          // Otherwise, assume it is full screen, and use identity CTM.
-          if (state->mirror_mode != state->display->native_mode() &&
-              state->display->is_aspect_preserving_scaling()) {
-            state->transform = GetMirrorModeCTM(*state);
-            mirrored_display_area_ratio_map_[state->touch_device_id] =
-                GetMirroredDisplayAreaRatio(*state);
-          }
-        }
       }
       break;
     }
@@ -826,19 +852,16 @@ bool DisplayConfigurator::EnterState(MultipleDisplayState display_state,
         // same desktop configuration can be restored when the displays are
         // turned back on.
         const DisplayMode* mode_info = cached_displays_[i].selected_mode;
-        if (!mode_info)
+        if (!mode_info) {
+          LOG(WARNING) << "No selected mode when configuring display: "
+                       << state->display->ToString();
           return false;
+        }
 
         size.set_width(std::max<int>(size.width(), mode_info->size().width()));
         size.set_height(size.height() + (size.height() ? kVerticalGap : 0) +
                         mode_info->size().height());
       }
-
-      for (size_t i = 0; i < cached_displays_.size(); ++i) {
-        DisplayState* state = &cached_displays_[i];
-        if (state->touch_device_id)
-          state->transform = GetExtendedModeCTM(*state, new_origins[i], size);
-      }
       break;
     }
   }
@@ -886,13 +909,8 @@ bool DisplayConfigurator::EnterState(MultipleDisplayState display_state,
           break;
       }
 
-      if (configure_succeeded) {
-        if (state.touch_device_id)
-          touchscreen_delegate_->ConfigureCTM(state.touch_device_id,
-                                              state.transform);
-      } else {
+      if (!configure_succeeded)
         all_succeeded = false;
-      }
 
       // If we are trying to set mirror mode and one of the modesets fails,
       // then the two monitors will be mis-matched.  In this case, return
@@ -907,6 +925,7 @@ bool DisplayConfigurator::EnterState(MultipleDisplayState display_state,
   if (all_succeeded) {
     display_state_ = display_state;
     power_state_ = power_state;
+    framebuffer_size_ = size;
   }
   return all_succeeded;
 }
@@ -945,102 +964,4 @@ MultipleDisplayState DisplayConfigurator::ChooseDisplayState(
   return MULTIPLE_DISPLAY_STATE_INVALID;
 }
 
-DisplayConfigurator::CoordinateTransformation
-DisplayConfigurator::GetMirrorModeCTM(const DisplayState& display_state) {
-  CoordinateTransformation ctm;  // Default to identity
-  const DisplayMode* native_mode_info = display_state.display->native_mode();
-  const DisplayMode* mirror_mode_info = display_state.mirror_mode;
-
-  if (!native_mode_info || !mirror_mode_info ||
-      native_mode_info->size().height() == 0 ||
-      mirror_mode_info->size().height() == 0 ||
-      native_mode_info->size().width() == 0 ||
-      mirror_mode_info->size().width() == 0)
-    return ctm;
-
-  float native_mode_ar = static_cast<float>(native_mode_info->size().width()) /
-                         static_cast<float>(native_mode_info->size().height());
-  float mirror_mode_ar = static_cast<float>(mirror_mode_info->size().width()) /
-                         static_cast<float>(mirror_mode_info->size().height());
-
-  if (mirror_mode_ar > native_mode_ar) {  // Letterboxing
-    ctm.x_scale = 1.0;
-    ctm.x_offset = 0.0;
-    ctm.y_scale = mirror_mode_ar / native_mode_ar;
-    ctm.y_offset = (native_mode_ar / mirror_mode_ar - 1.0) * 0.5;
-    return ctm;
-  }
-  if (native_mode_ar > mirror_mode_ar) {  // Pillarboxing
-    ctm.y_scale = 1.0;
-    ctm.y_offset = 0.0;
-    ctm.x_scale = native_mode_ar / mirror_mode_ar;
-    ctm.x_offset = (mirror_mode_ar / native_mode_ar - 1.0) * 0.5;
-    return ctm;
-  }
-
-  return ctm;  // Same aspect ratio - return identity
-}
-
-DisplayConfigurator::CoordinateTransformation
-DisplayConfigurator::GetExtendedModeCTM(const DisplayState& display_state,
-                                        const gfx::Point& new_origin,
-                                        const gfx::Size& framebuffer_size) {
-  CoordinateTransformation ctm;  // Default to identity
-  const DisplayMode* mode_info = display_state.selected_mode;
-  DCHECK(mode_info);
-  if (!mode_info)
-    return ctm;
-  // An example of how to calculate the CTM.
-  // Suppose we have 2 monitors, the first one has size 1366 x 768.
-  // The second one has size 2560 x 1600
-  // The total size of framebuffer is 2560 x 2428
-  // where 2428 = 768 + 60 (hidden gap) + 1600
-  // and the sceond monitor is translated to Point (0, 828) in the
-  // framebuffer.
-  // X will first map input event location to [0, 2560) x [0, 2428),
-  // then apply CTM on it.
-  // So to compute CTM, for monitor1, we have
-  // x_scale = (1366 - 1) / (2560 - 1)
-  // x_offset = 0 / (2560 - 1)
-  // y_scale = (768 - 1) / (2428 - 1)
-  // y_offset = 0 / (2428 -1)
-  // For Monitor 2, we have
-  // x_scale = (2560 - 1) / (2560 - 1)
-  // x_offset = 0 / (2560 - 1)
-  // y_scale = (1600 - 1) / (2428 - 1)
-  // y_offset = 828 / (2428 -1)
-  // See the unittest DisplayConfiguratorTest.CTMForMultiScreens.
-  ctm.x_scale = static_cast<float>(mode_info->size().width() - 1) /
-                (framebuffer_size.width() - 1);
-  ctm.x_offset =
-      static_cast<float>(new_origin.x()) / (framebuffer_size.width() - 1);
-  ctm.y_scale = static_cast<float>(mode_info->size().height() - 1) /
-                (framebuffer_size.height() - 1);
-  ctm.y_offset =
-      static_cast<float>(new_origin.y()) / (framebuffer_size.height() - 1);
-  return ctm;
-}
-
-float DisplayConfigurator::GetMirroredDisplayAreaRatio(
-    const DisplayState& display_state) {
-  float area_ratio = 1.0f;
-  const DisplayMode* native_mode_info = display_state.display->native_mode();
-  const DisplayMode* mirror_mode_info = display_state.mirror_mode;
-
-  if (!native_mode_info || !mirror_mode_info ||
-      native_mode_info->size().height() == 0 ||
-      mirror_mode_info->size().height() == 0 ||
-      native_mode_info->size().width() == 0 ||
-      mirror_mode_info->size().width() == 0)
-    return area_ratio;
-
-  float width_ratio = static_cast<float>(mirror_mode_info->size().width()) /
-                      static_cast<float>(native_mode_info->size().width());
-  float height_ratio = static_cast<float>(mirror_mode_info->size().height()) /
-                       static_cast<float>(native_mode_info->size().height());
-
-  area_ratio = width_ratio * height_ratio;
-  return area_ratio;
-}
-
 }  // namespace ui