blob: cb62c2f46e20469bc32b1b1699be55702be329ed [file] [log] [blame]
// Copyright 2018 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_HOME_SCREEN_HOME_LAUNCHER_GESTURE_HANDLER_H_
#define ASH_HOME_SCREEN_HOME_LAUNCHER_GESTURE_HANDLER_H_
#include <map>
#include <vector>
#include "ash/ash_export.h"
#include "ash/home_screen/home_screen_delegate.h"
#include "ash/wm/tablet_mode/tablet_mode_controller.h"
#include "ash/wm/tablet_mode/tablet_mode_observer.h"
#include "base/macros.h"
#include "base/optional.h"
#include "base/scoped_observer.h"
#include "ui/aura/window.h"
#include "ui/aura/window_observer.h"
#include "ui/compositor/layer_animation_observer.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/transform.h"
namespace ash {
class HomeLauncherGestureHandlerObserver;
// HomeLauncherGestureHandler makes modifications to a window's transform and
// opacity when gesture drag events are received and forwarded to it.
// Additionally hides windows which may block the home launcher. All
// modifications are either transitioned to their final state, or back to their
// initial state on release event.
class ASH_EXPORT HomeLauncherGestureHandler
: public aura::WindowObserver,
public TabletModeObserver,
public ui::ImplicitAnimationObserver {
public:
// Enum which tracks which mode the current scroll process is in.
enum class Mode {
// There is no current scroll process.
kNone,
// Sliding up the MRU window to display launcher. If in overview mode,
// slides up overview mode as well.
kSlideUpToShow,
// Sliding down the MRU window to hide launcher.
kSlideDownToHide,
};
HomeLauncherGestureHandler();
~HomeLauncherGestureHandler() override;
// Called by owner of this object when a gesture event is received. |location|
// should be in screen coordinates. Returns false if the the gesture event
// was not processed.
bool OnPressEvent(Mode mode, const gfx::Point& location);
bool OnScrollEvent(const gfx::Point& location, float scroll_y);
bool OnReleaseEvent(const gfx::Point& location);
// Cancel a current drag and animates the items to their final state based on
// |last_event_location_|.
void Cancel();
// Hide MRU window and show home launcher on specified display.
bool ShowHomeLauncher(const display::Display& display);
// Hide home launcher and show MRU window on specified display.
bool HideHomeLauncherForWindow(const display::Display& display,
aura::Window* window);
// Returns the windows being tracked. May be null.
aura::Window* GetActiveWindow();
aura::Window* GetSecondaryWindow();
bool IsDragInProgress() const { return last_event_location_.has_value(); }
void AddObserver(HomeLauncherGestureHandlerObserver* observer);
void RemoveObserver(HomeLauncherGestureHandlerObserver* obsever);
void NotifyHomeLauncherTargetPositionChanged(bool showing,
int64_t display_id);
void NotifyHomeLauncherAnimationComplete(bool shown, int64_t display_id);
// TODO(sammiequon): Investigate if it is needed to observe potential window
// visibility changes, if they can happen.
// aura::WindowObserver:
void OnWindowDestroying(aura::Window* window) override;
// TabletModeObserver:
void OnTabletModeEnded() override;
// ui::ImplicitAnimationObserver:
void OnImplicitAnimationsCompleted() override;
Mode mode() const { return mode_; }
private:
class ScopedWindowModifier;
FRIEND_TEST_ALL_PREFIXES(HomeLauncherModeGestureHandlerTest,
AnimatingToEndResetsState);
using AnimationTrigger = HomeScreenDelegate::AnimationTrigger;
// Stores the initial and target opacities and transforms of window.
struct WindowValues {
float initial_opacity;
float target_opacity;
gfx::Transform initial_transform;
gfx::Transform target_transform;
};
// Animates the items based on IsFinalStateShow(). |trigger| is what triggered
// the animation.
void AnimateToFinalState(AnimationTrigger trigger);
// Updates |settings| based on what we want for this class.
void UpdateSettings(ui::ScopedLayerAnimationSettings* settings);
// Updates the opacity and transform |window_| and its transient children base
// on the values in |window_values_| and |transient_descendants_values_|.
// |progress| is between 0.0 and 1.0, where 0.0 means the window will have its
// original opacity and transform, and 1.0 means the window will be faded out
// and transformed offscreen.
void UpdateWindows(double progress, bool animate);
// Stop observing all windows and remove their local pointers.
void RemoveObserversAndStopTracking();
// Returns true if there's no gesture dragging and animation.
bool IsIdle();
// Returns true if animation is running.
bool IsAnimating();
// Returns true if home launcher should run animation to show. Otherwise,
// returns false.
bool IsFinalStateShow();
// Sets up windows that will be used in dragging and animation. If |window| is
// not null for kSlideDownToHide mode, it will be set as the window to run
// slide down animation. |window| is not used for kSlideUpToShow mode. Returns
// true if windows are successfully set up.
bool SetUpWindows(Mode mode, aura::Window* window);
Mode mode_ = Mode::kNone;
// The windows we are tracking. They are null if a drag is not underway, or if
// overview without splitview is active. |secondary_window_| is the secondary
// window for splitview and is always null if |active_window_| is null.
std::unique_ptr<ScopedWindowModifier> active_window_;
std::unique_ptr<ScopedWindowModifier> secondary_window_;
// Original and target transform and opacity of the backdrop window. Empty if
// there is no backdrop on mouse pressed.
base::Optional<WindowValues> backdrop_values_;
// Original and target transform and opacity of the split view divider window.
// Empty if there is no divider on press event (ie. split view is not active).
base::Optional<WindowValues> divider_values_;
// Stores windows which were shown behind the mru window. They need to be
// hidden so the home launcher is visible when swiping up.
std::vector<aura::Window*> hidden_windows_;
// Tracks the location of the last received event in screen coordinates. Empty
// if there is currently no window being processed.
base::Optional<gfx::Point> last_event_location_;
// Tracks the last y scroll amount. On gesture end, animates to end state if
// |last_scroll_y_| is greater than a certain threshold, even if
// |last_event_location_| is in a different half.
float last_scroll_y_ = 0.f;
// Stores whether overview was actived when we first perform the swipe up
// gesture. This is needed in case someone enters overview while the show home
// launcher animation is running, overview will be active, but we do not want
// to toggle overview again in that case.
bool overview_active_on_gesture_start_ = false;
// Marked as true if overview is currently animating to a close state, and
// will be exited at the end of the animation. Prevents us form starting
// another operation while this is true.
bool animating_to_close_overview_ = false;
ScopedObserver<TabletModeController, TabletModeObserver>
tablet_mode_observer_{this};
// The display where the windows are being processed.
display::Display display_;
base::ObserverList<HomeLauncherGestureHandlerObserver> observers_;
DISALLOW_COPY_AND_ASSIGN(HomeLauncherGestureHandler);
};
} // namespace ash
#endif // ASH_HOME_SCREEN_HOME_LAUNCHER_GESTURE_HANDLER_H_