Home | History | Annotate | Download | only in wm
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "ash/wm/lock_window_state.h"
      6 
      7 #include "ash/screen_util.h"
      8 #include "ash/shell.h"
      9 #include "ash/wm/lock_layout_manager.h"
     10 #include "ash/wm/window_animations.h"
     11 #include "ash/wm/window_state.h"
     12 #include "ash/wm/window_state_delegate.h"
     13 #include "ash/wm/window_state_util.h"
     14 #include "ash/wm/window_util.h"
     15 #include "ash/wm/wm_event.h"
     16 #include "ui/aura/window.h"
     17 #include "ui/aura/window_delegate.h"
     18 #include "ui/gfx/rect.h"
     19 #include "ui/keyboard/keyboard_controller.h"
     20 #include "ui/keyboard/keyboard_util.h"
     21 #include "ui/wm/core/window_animations.h"
     22 
     23 namespace ash {
     24 
     25 LockWindowState::LockWindowState(aura::Window* window)
     26     : current_state_type_(wm::GetWindowState(window)->GetStateType()) {
     27 }
     28 
     29 LockWindowState::~LockWindowState() {
     30 }
     31 
     32 void LockWindowState::OnWMEvent(wm::WindowState* window_state,
     33                                 const wm::WMEvent* event) {
     34   aura::Window* window = window_state->window();
     35   gfx::Rect bounds = window->bounds();
     36 
     37   switch (event->type()) {
     38     case wm::WM_EVENT_TOGGLE_FULLSCREEN:
     39       ToggleFullScreen(window_state, window_state->delegate());
     40       break;
     41     case wm::WM_EVENT_FULLSCREEN:
     42       UpdateWindow(window_state, wm::WINDOW_STATE_TYPE_FULLSCREEN);
     43       break;
     44     case wm::WM_EVENT_TOGGLE_MAXIMIZE_CAPTION:
     45     case wm::WM_EVENT_TOGGLE_VERTICAL_MAXIMIZE:
     46     case wm::WM_EVENT_TOGGLE_HORIZONTAL_MAXIMIZE:
     47     case wm::WM_EVENT_TOGGLE_MAXIMIZE:
     48     case wm::WM_EVENT_CENTER:
     49     case wm::WM_EVENT_SNAP_LEFT:
     50     case wm::WM_EVENT_SNAP_RIGHT:
     51     case wm::WM_EVENT_NORMAL:
     52     case wm::WM_EVENT_MAXIMIZE:
     53       UpdateWindow(window_state,
     54                    GetMaximizedOrCenteredWindowType(window_state));
     55       return;
     56     case wm::WM_EVENT_MINIMIZE:
     57       UpdateWindow(window_state, wm::WINDOW_STATE_TYPE_MINIMIZED);
     58       return;
     59     case wm::WM_EVENT_SHOW_INACTIVE:
     60       return;
     61     case wm::WM_EVENT_SET_BOUNDS:
     62       if (window_state->IsMaximized() || window_state->IsFullscreen()) {
     63         UpdateBounds(window_state);
     64       } else {
     65         const ash::wm::SetBoundsEvent* bounds_event =
     66             static_cast<const ash::wm::SetBoundsEvent*>(event);
     67         window_state->SetBoundsConstrained(bounds_event->requested_bounds());
     68       }
     69       break;
     70     case wm::WM_EVENT_ADDED_TO_WORKSPACE:
     71       if (current_state_type_ != wm::WINDOW_STATE_TYPE_MAXIMIZED &&
     72           current_state_type_ != wm::WINDOW_STATE_TYPE_MINIMIZED &&
     73           current_state_type_ != wm::WINDOW_STATE_TYPE_FULLSCREEN) {
     74         UpdateWindow(window_state,
     75                      GetMaximizedOrCenteredWindowType(window_state));
     76       }
     77       break;
     78     case wm::WM_EVENT_WORKAREA_BOUNDS_CHANGED:
     79     case wm::WM_EVENT_DISPLAY_BOUNDS_CHANGED:
     80       UpdateBounds(window_state);
     81       break;
     82   }
     83 }
     84 
     85 wm::WindowStateType LockWindowState::GetType() const {
     86   return current_state_type_;
     87 }
     88 
     89 void LockWindowState::AttachState(wm::WindowState* window_state,
     90                                   wm::WindowState::State* previous_state) {
     91   current_state_type_ = previous_state->GetType();
     92 
     93   // Initialize the state to a good preset.
     94   if (current_state_type_ != wm::WINDOW_STATE_TYPE_MAXIMIZED &&
     95       current_state_type_ != wm::WINDOW_STATE_TYPE_MINIMIZED &&
     96       current_state_type_ != wm::WINDOW_STATE_TYPE_FULLSCREEN) {
     97     UpdateWindow(window_state,
     98                  GetMaximizedOrCenteredWindowType(window_state));
     99   }
    100 }
    101 
    102 void LockWindowState::DetachState(wm::WindowState* window_state) {
    103 }
    104 
    105 // static
    106 wm::WindowState* LockWindowState::SetLockWindowState(aura::Window* window) {
    107   scoped_ptr<wm::WindowState::State> lock_state(new LockWindowState(window));
    108   scoped_ptr<wm::WindowState::State> old_state(
    109       wm::GetWindowState(window)->SetStateObject(lock_state.Pass()));
    110   return wm::GetWindowState(window);
    111 }
    112 
    113 void LockWindowState::UpdateWindow(wm::WindowState* window_state,
    114                                    wm::WindowStateType target_state) {
    115   DCHECK(target_state == wm::WINDOW_STATE_TYPE_MINIMIZED ||
    116          target_state == wm::WINDOW_STATE_TYPE_MAXIMIZED ||
    117          (target_state == wm::WINDOW_STATE_TYPE_NORMAL &&
    118               !window_state->CanMaximize()) ||
    119          target_state == wm::WINDOW_STATE_TYPE_FULLSCREEN);
    120 
    121   if (target_state == wm::WINDOW_STATE_TYPE_MINIMIZED) {
    122     if (current_state_type_ == wm::WINDOW_STATE_TYPE_MINIMIZED)
    123       return;
    124 
    125     current_state_type_ = target_state;
    126     ::wm::SetWindowVisibilityAnimationType(
    127         window_state->window(), WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE);
    128     window_state->window()->Hide();
    129     if (window_state->IsActive())
    130       window_state->Deactivate();
    131     return;
    132   }
    133 
    134   if (current_state_type_ == target_state) {
    135     // If the state type did not change, update it accordingly.
    136     UpdateBounds(window_state);
    137     return;
    138   }
    139 
    140   const wm::WindowStateType old_state_type = current_state_type_;
    141   current_state_type_ = target_state;
    142   window_state->UpdateWindowShowStateFromStateType();
    143   window_state->NotifyPreStateTypeChange(old_state_type);
    144   UpdateBounds(window_state);
    145   window_state->NotifyPostStateTypeChange(old_state_type);
    146 
    147   if ((window_state->window()->TargetVisibility() ||
    148       old_state_type == wm::WINDOW_STATE_TYPE_MINIMIZED) &&
    149       !window_state->window()->layer()->visible()) {
    150     // The layer may be hidden if the window was previously minimized. Make
    151     // sure it's visible.
    152     window_state->window()->Show();
    153   }
    154 }
    155 
    156 wm::WindowStateType LockWindowState::GetMaximizedOrCenteredWindowType(
    157       wm::WindowState* window_state) {
    158   return window_state->CanMaximize() ? wm::WINDOW_STATE_TYPE_MAXIMIZED :
    159                                        wm::WINDOW_STATE_TYPE_NORMAL;
    160 }
    161 
    162 void LockWindowState::UpdateBounds(wm::WindowState* window_state) {
    163   if (!window_state->IsMaximized() && !window_state->IsFullscreen())
    164     return;
    165 
    166   keyboard::KeyboardController* keyboard_controller =
    167       keyboard::KeyboardController::GetInstance();
    168   gfx::Rect keyboard_bounds;
    169 
    170   if (keyboard_controller &&
    171       !keyboard::IsKeyboardOverscrollEnabled() &&
    172       keyboard_controller->keyboard_visible()) {
    173     keyboard_bounds = keyboard_controller->current_keyboard_bounds();
    174   }
    175 
    176   gfx::Rect bounds =
    177       ScreenUtil::GetDisplayBoundsInParent(window_state->window());
    178   bounds.set_height(bounds.height() - keyboard_bounds.height());
    179 
    180   VLOG(1) << "Updating window bounds to: " << bounds.ToString();
    181   window_state->SetBoundsDirect(bounds);
    182 }
    183 
    184 }  // namespace ash
    185