Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / ash / wm / window_state.cc
index 8553b9c..9f89596 100644 (file)
@@ -8,6 +8,7 @@
 #include "ash/root_window_controller.h"
 #include "ash/screen_util.h"
 #include "ash/shell_window_ids.h"
+#include "ash/wm/default_state.h"
 #include "ash/wm/window_properties.h"
 #include "ash/wm/window_state_delegate.h"
 #include "ash/wm/window_state_observer.h"
 #include "base/auto_reset.h"
 #include "base/command_line.h"
 #include "ui/aura/client/aura_constants.h"
+#include "ui/aura/layout_manager.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_delegate.h"
+#include "ui/compositor/scoped_layer_animation_settings.h"
 #include "ui/gfx/display.h"
 #include "ui/views/corewm/window_util.h"
 
 namespace ash {
 namespace wm {
 
+namespace {
+
+// A tentative class to set the bounds on the window.
+// TODO(oshima): Once all logic is cleaned up, move this to the real layout
+// manager with proper friendship.
+class BoundsSetter : public aura::LayoutManager {
+ public:
+  BoundsSetter() {}
+  virtual ~BoundsSetter() {}
+
+  // aura::LayoutManager overrides:
+  virtual void OnWindowResized() OVERRIDE {}
+  virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE {}
+  virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE {}
+  virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE {}
+  virtual void OnChildWindowVisibilityChanged(
+      aura::Window* child, bool visible) OVERRIDE {}
+  virtual void SetChildBounds(
+      aura::Window* child, const gfx::Rect& requested_bounds) OVERRIDE {}
+
+  void SetBounds(aura::Window* window, const gfx::Rect& bounds) {
+    SetChildBoundsDirect(window, bounds);
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(BoundsSetter);
+};
+
+WMEvent WMEventFromShowState(ui::WindowShowState requested_show_state) {
+  switch (requested_show_state) {
+    case ui::SHOW_STATE_DEFAULT:
+    case ui::SHOW_STATE_NORMAL:
+      return NORMAL;
+    case ui::SHOW_STATE_MINIMIZED:
+      return MINIMIZE;
+    case ui::SHOW_STATE_MAXIMIZED:
+      return MAXIMIZE;
+    case ui::SHOW_STATE_FULLSCREEN:
+      return FULLSCREEN;
+    case ui::SHOW_STATE_INACTIVE:
+      return SHOW_INACTIVE;
+    case ui::SHOW_STATE_DETACHED:
+    case ui::SHOW_STATE_END:
+      NOTREACHED() << "No WMEvent defined for the show type:"
+                   << requested_show_state;
+  }
+  return NORMAL;
+}
+
+}  // namespace
+
 WindowState::WindowState(aura::Window* window)
     : window_(window),
       window_position_managed_(false),
@@ -33,14 +87,14 @@ WindowState::WindowState(aura::Window* window)
       ignored_by_shelf_(false),
       can_consume_system_keys_(false),
       top_row_keys_are_function_keys_(false),
-      always_restores_to_restore_bounds_(false),
+      unminimize_to_restore_bounds_(false),
       hide_shelf_when_fullscreen_(true),
       animate_to_fullscreen_(true),
       minimum_visibility_(false),
-      in_set_window_show_type_(false),
-      window_show_type_(ToWindowShowType(GetShowState())) {
+      ignore_property_change_(false),
+      window_show_type_(ToWindowShowType(GetShowState())),
+      current_state_(new DefaultState) {
   window_->AddObserver(this);
-
 #if defined(OS_CHROMEOS)
   // NOTE(pkotwicz): Animating to immersive fullscreen does not look good. When
   // switches::UseImmersiveFullscreenForAllWindows() returns true, most windows
@@ -86,10 +140,15 @@ bool WindowState::IsMaximizedOrFullscreen() const {
 }
 
 bool WindowState::IsNormalShowState() const {
-  ui::WindowShowState state = window_->GetProperty(aura::client::kShowStateKey);
+  ui::WindowShowState state = GetShowState();
   return state == ui::SHOW_STATE_NORMAL || state == ui::SHOW_STATE_DEFAULT;
 }
 
+bool WindowState::IsNormalShowType() const {
+  return window_show_type_ == SHOW_TYPE_NORMAL ||
+      window_show_type_ == SHOW_TYPE_DEFAULT;
+}
+
 bool WindowState::IsActive() const {
   return IsActiveWindow(window_);
 }
@@ -174,30 +233,16 @@ void WindowState::Deactivate() {
 }
 
 void WindowState::Restore() {
-  window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
+  if (!IsNormalShowType())
+    OnWMEvent(NORMAL);
 }
 
-void WindowState::ToggleMaximized() {
-  if (IsMaximized())
-    Restore();
-  else if (CanMaximize())
-    Maximize();
+void WindowState::ToggleFullscreen() {
+  OnWMEvent(TOGGLE_FULLSCREEN);
 }
 
-void WindowState::ToggleFullscreen() {
-  // Window which cannot be maximized should not be fullscreened.
-  // It can, however, be restored if it was fullscreened.
-  bool is_fullscreen = IsFullscreen();
-  if (!is_fullscreen && !CanMaximize())
-    return;
-  if (delegate_ && delegate_->ToggleFullscreen(this))
-    return;
-  if (is_fullscreen) {
-    Restore();
-  } else {
-    window_->SetProperty(aura::client::kShowStateKey,
-                         ui::SHOW_STATE_FULLSCREEN);
-  }
+void WindowState::OnWMEvent(WMEvent event) {
+  current_state_->OnWMEvent(this, event);
 }
 
 void WindowState::SetBoundsInScreen(
@@ -250,28 +295,43 @@ void WindowState::RemoveObserver(WindowStateObserver* observer) {
   observer_list_.RemoveObserver(observer);
 }
 
-bool WindowState::CreateDragDetails(aura::Window* window,
+void WindowState::CreateDragDetails(aura::Window* window,
                                     const gfx::Point& point_in_parent,
                                     int window_component,
                                     aura::client::WindowMoveSource source) {
-  scoped_ptr<DragDetails> details(new DragDetails(
-        window, point_in_parent, window_component, source));
-  if (!details->is_resizable)
-    return false;
-  drag_details_ = details.Pass();
-  return true;
+  drag_details_.reset(
+      new DragDetails(window, point_in_parent, window_component, source));
 }
 
 void WindowState::DeleteDragDetails() {
   drag_details_.reset();
 }
 
+void WindowState::SetAndClearRestoreBounds() {
+  DCHECK(HasRestoreBounds());
+  SetBoundsInScreen(GetRestoreBoundsInScreen());
+  ClearRestoreBounds();
+}
+
+void WindowState::AdjustSnappedBounds(gfx::Rect* bounds) {
+  if (is_dragged() || !IsSnapped())
+    return;
+  gfx::Rect maximized_bounds = ScreenUtil::GetMaximizedWindowBoundsInParent(
+      window_);
+  if (window_show_type() == SHOW_TYPE_LEFT_SNAPPED)
+    bounds->set_x(maximized_bounds.x());
+  else if (window_show_type() == SHOW_TYPE_RIGHT_SNAPPED)
+    bounds->set_x(maximized_bounds.right() - bounds->width());
+  bounds->set_y(maximized_bounds.y());
+  bounds->set_height(maximized_bounds.height());
+}
+
 void WindowState::OnWindowPropertyChanged(aura::Window* window,
                                           const void* key,
                                           intptr_t old) {
   DCHECK_EQ(window, window_);
-  if (key == aura::client::kShowStateKey)
-    SetWindowShowType(ToWindowShowType(GetShowState()));
+  if (key == aura::client::kShowStateKey && !ignore_property_change_)
+    OnWMEvent(WMEventFromShowState(GetShowState()));
 }
 
 void WindowState::SnapWindow(WindowShowType left_or_right,
@@ -292,7 +352,9 @@ void WindowState::SnapWindow(WindowShowType left_or_right,
 
   DCHECK(left_or_right == SHOW_TYPE_LEFT_SNAPPED ||
          left_or_right == SHOW_TYPE_RIGHT_SNAPPED);
-  SetWindowShowType(left_or_right);
+  OnWMEvent(left_or_right == SHOW_TYPE_LEFT_SNAPPED ?
+            SNAP_LEFT : SNAP_RIGHT);
+
   // TODO(varkha): Ideally the bounds should be changed in a LayoutManager upon
   // observing the WindowShowType change.
   // If the window is a child of kShellWindowId_DockedContainer such as during
@@ -305,21 +367,41 @@ void WindowState::SnapWindow(WindowShowType left_or_right,
   SetRestoreBoundsInScreen(restore_bounds_in_screen);
 }
 
-void WindowState::SetWindowShowType(WindowShowType new_window_show_type) {
-  if (in_set_window_show_type_)
-    return;
-  base::AutoReset<bool> resetter(&in_set_window_show_type_, true);
-
+void WindowState::UpdateWindowShowType(WindowShowType new_window_show_type) {
   ui::WindowShowState new_window_state =
       ToWindowShowState(new_window_show_type);
-  if (new_window_state != GetShowState())
+  if (new_window_state != GetShowState()) {
+    base::AutoReset<bool> resetter(&ignore_property_change_, true);
     window_->SetProperty(aura::client::kShowStateKey, new_window_state);
-  WindowShowType old_window_show_type = window_show_type_;
-  window_show_type_ = new_window_show_type;
-  if (old_window_show_type != window_show_type_) {
-    FOR_EACH_OBSERVER(WindowStateObserver, observer_list_,
-                      OnWindowShowTypeChanged(this, old_window_show_type));
   }
+  window_show_type_ = new_window_show_type;
+}
+
+void WindowState::NotifyPreShowTypeChange(WindowShowType old_window_show_type) {
+  FOR_EACH_OBSERVER(WindowStateObserver, observer_list_,
+                    OnPreWindowShowTypeChange(this, old_window_show_type));
+}
+
+void WindowState::NotifyPostShowTypeChange(
+    WindowShowType old_window_show_type) {
+  FOR_EACH_OBSERVER(WindowStateObserver, observer_list_,
+                    OnPostWindowShowTypeChange(this, old_window_show_type));
+}
+
+void WindowState::SetBoundsDirect(const gfx::Rect& bounds) {
+  BoundsSetter().SetBounds(window_, bounds);
+}
+
+void WindowState::SetBoundsDirectAnimated(const gfx::Rect& bounds) {
+  const int kBoundsChangeSlideDurationMs = 120;
+
+  ui::Layer* layer = window_->layer();
+  ui::ScopedLayerAnimationSettings slide_settings(layer->GetAnimator());
+  slide_settings.SetPreemptionStrategy(
+      ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
+  slide_settings.SetTransitionDuration(
+      base::TimeDelta::FromMilliseconds(kBoundsChangeSlideDurationMs));
+  SetBoundsDirect(bounds);
 }
 
 WindowState* GetActiveWindowState() {