blob: 79d09a5df040b0ef957c9ec339f535fe38b989bc [file] [log] [blame]
// Copyright 2013 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_WM_OVERVIEW_WINDOW_SELECTOR_H_
#define ASH_WM_OVERVIEW_WINDOW_SELECTOR_H_
#include <stddef.h>
#include <stdint.h>
#include <memory>
#include <set>
#include <vector>
#include "ash/ash_export.h"
#include "ash/wm/overview/scoped_hide_overview_windows.h"
#include "ash/wm/splitview/split_view_controller.h"
#include "base/macros.h"
#include "base/time/time.h"
#include "ui/aura/window_observer.h"
#include "ui/display/display_observer.h"
#include "ui/views/controls/textfield/textfield_controller.h"
#include "ui/wm/public/activation_change_observer.h"
namespace gfx {
class Point;
class Rect;
} // namespace gfx
namespace views {
class Textfield;
class Widget;
} // namespace views
namespace ash {
class OverviewWindowDragController;
class SplitViewDragIndicators;
class WindowGrid;
class WindowSelectorDelegate;
class WindowSelectorItem;
class WindowSelectorTest;
enum class IndicatorState;
// The WindowSelector shows a grid of all of your windows, allowing to select
// one by clicking or tapping on it.
class ASH_EXPORT WindowSelector : public display::DisplayObserver,
public aura::WindowObserver,
public ::wm::ActivationChangeObserver,
public views::TextfieldController,
public SplitViewController::Observer {
public:
// Returns true if the window can be selected in overview mode.
static bool IsSelectable(const aura::Window* window);
enum Direction { LEFT, UP, RIGHT, DOWN };
enum class OverviewTransition {
kEnter, // In the entering process of overview.
kExit // In the exiting process of overview.
};
using WindowList = std::vector<aura::Window*>;
explicit WindowSelector(WindowSelectorDelegate* delegate);
~WindowSelector() override;
// Initialize with the windows that can be selected.
void Init(const WindowList& windows, const WindowList& hide_windows);
// Perform cleanup that cannot be done in the destructor.
void Shutdown();
// Cancels window selection.
void CancelSelection();
// Called when the last window selector item from a grid is deleted.
void OnGridEmpty(WindowGrid* grid);
// Moves the current selection by |increment| items. Positive values of
// |increment| move the selection forward, negative values move it backward.
void IncrementSelection(int increment);
// Accepts current selection if any. Returns true if a selection was made,
// false otherwise.
bool AcceptSelection();
// Activates |item's| window.
void SelectWindow(WindowSelectorItem* item);
// Called when |window| is about to get closed.
void WindowClosing(WindowSelectorItem* window);
// Called to set bounds for window grids. Used for split view.
void SetBoundsForWindowGridsInScreenIgnoringWindow(
const gfx::Rect& bounds,
WindowSelectorItem* ignored_item);
// Called to show or hide the split view drag indicators. This will do
// nothing if split view is not enabled. |event_location| is used to reparent
// |split_view_drag_indicators_|'s widget, if necessary.
void SetSplitViewDragIndicatorsIndicatorState(
IndicatorState indicator_state,
const gfx::Point& event_location);
// Retrieves the window grid whose root window matches |root_window|. Returns
// nullptr if the window grid is not found.
WindowGrid* GetGridWithRootWindow(aura::Window* root_window);
// Add |window| to the grid in |grid_list_| with the same root window. Does
// nothing if the grid already contains |window|. This may be called in two
// scenarioes: 1) when a item in split view mode was previously snapped but
// should now be returned to the window grid (e.g. split view divider dragged
// to either edge, or a window is snapped to a postion that already has a
// snapped window); 2) when a window (not from overview) is dragged while
// overview is open and the window is dropped on the new selector item, the
// dragged window is then added to the overview.
void AddItem(aura::Window* window);
// Removes the window selector item from the overview window grid.
void RemoveWindowSelectorItem(WindowSelectorItem* item);
void InitiateDrag(WindowSelectorItem* item,
const gfx::Point& location_in_screen);
void Drag(WindowSelectorItem* item, const gfx::Point& location_in_screen);
void CompleteDrag(WindowSelectorItem* item,
const gfx::Point& location_in_screen);
void StartSplitViewDragMode(const gfx::Point& location_in_screen);
void Fling(WindowSelectorItem* item,
const gfx::Point& location_in_screen,
float velocity_x,
float velocity_y);
void ActivateDraggedWindow();
void ResetDraggedWindowGesture();
// Called when a window's tab(s) start/continue/end being dragged around if
// overview mode is active.
// TODO(xdai): Currently it doesn't work for multi-display scenario.
void OnWindowDragStarted(aura::Window* dragged_window);
void OnWindowDragContinued(aura::Window* dragged_window,
const gfx::Point& location_in_screen);
void OnWindowDragEnded(aura::Window* dragged_window,
const gfx::Point& location_in_screen);
// Positions all of the windows in the overview, except |ignored_item|.
void PositionWindows(bool animate,
WindowSelectorItem* ignored_item = nullptr);
// If we are in middle of ending overview mode.
bool IsShuttingDown() const;
// Checks if the grid associated with a given |root_window| needs to have the
// wallpaper animated. Returns false if one of the grids windows covers the
// the entire workspace, true otherwise.
bool ShouldAnimateWallpaper(aura::Window* root_window);
bool IsWindowInOverview(const aura::Window* window);
WindowSelectorDelegate* delegate() { return delegate_; }
bool restoring_minimized_windows() const {
return restoring_minimized_windows_;
}
int text_filter_bottom() const { return text_filter_bottom_; }
const std::vector<std::unique_ptr<WindowGrid>>& grid_list_for_testing()
const {
return grid_list_;
}
SplitViewDragIndicators* split_view_drag_indicators() {
return split_view_drag_indicators_.get();
}
OverviewWindowDragController* window_drag_controller() {
return window_drag_controller_.get();
}
// display::DisplayObserver:
void OnDisplayAdded(const display::Display& display) override;
void OnDisplayRemoved(const display::Display& display) override;
void OnDisplayMetricsChanged(const display::Display& display,
uint32_t metrics) override;
// aura::WindowObserver:
void OnWindowHierarchyChanged(const HierarchyChangeParams& params) override;
void OnWindowDestroying(aura::Window* window) override;
// wm::ActivationChangeObserver:
void OnWindowActivated(ActivationReason reason,
aura::Window* gained_active,
aura::Window* lost_active) override;
void OnAttemptToReactivateWindow(aura::Window* request_active,
aura::Window* actual_active) override;
// views::TextfieldController:
void ContentsChanged(views::Textfield* sender,
const base::string16& new_contents) override;
bool HandleKeyEvent(views::Textfield* sender,
const ui::KeyEvent& key_event) override;
// SplitViewController::Observer:
void OnSplitViewStateChanged(SplitViewController::State previous_state,
SplitViewController::State state) override;
void OnSplitViewDividerPositionChanged() override;
private:
friend class WindowSelectorTest;
// Returns the aura::Window for |text_filter_widget_|.
aura::Window* GetTextFilterWidgetWindow();
// Repositions and resizes |text_filter_widget_| on
// DisplayMetricsChanged event.
void RepositionTextFilterOnDisplayMetricsChange();
// |focus|, restores focus to the stored window.
void ResetFocusRestoreWindow(bool focus);
// Helper function that moves the selection widget to |direction| on the
// corresponding window grid.
void Move(Direction direction, bool animate);
// Removes all observers that were registered during construction and/or
// initialization.
void RemoveAllObservers();
// Called when the display area for the overview window grids changed.
void OnDisplayBoundsChanged();
// Returns true if all its window grids don't have any window item.
bool IsEmpty();
// Tracks observed windows.
std::set<aura::Window*> observed_windows_;
// Weak pointer to the selector delegate which will be called when a
// selection is made.
WindowSelectorDelegate* delegate_;
// A weak pointer to the window which was focused on beginning window
// selection. If window selection is canceled the focus should be restored to
// this window.
aura::Window* restore_focus_window_;
// True when performing operations that may cause window activations. This is
// used to prevent handling the resulting expected activation.
bool ignore_activations_ = false;
// List of all the window overview grids, one for each root window.
std::vector<std::unique_ptr<WindowGrid>> grid_list_;
// The owner of the widget which displays splitview related information in
// overview mode. This will be nullptr if split view is not enabled.
std::unique_ptr<SplitViewDragIndicators> split_view_drag_indicators_;
// Tracks the index of the root window the selection widget is in.
size_t selected_grid_index_ = 0;
// The following variables are used for metric collection purposes. All of
// them refer to this particular overview session and are not cumulative:
// The time when overview was started.
base::Time overview_start_time_;
// The number of arrow key presses.
size_t num_key_presses_ = 0;
// The number of items in the overview.
size_t num_items_ = 0;
// Indicates if the text filter is shown on screen (rather than above it).
bool showing_text_filter_ = false;
// Window text filter widget. As the user writes on it, we filter the items
// in the overview. It is also responsible for handling overview key events,
// such as enter key to select.
std::unique_ptr<views::Widget> text_filter_widget_;
// The current length of the string entered into the text filtering textfield.
size_t text_filter_string_length_ = 0;
// The number of times the text filtering textfield has been cleared of text
// during this overview mode session.
size_t num_times_textfield_cleared_ = 0;
// Tracks whether minimized windows are currently being restored for overview
// mode.
bool restoring_minimized_windows_ = false;
// The distance between the top edge of the screen and the bottom edge of
// the text filtering textfield.
int text_filter_bottom_ = 0;
// The selected item when exiting overview mode. nullptr if no window
// selected.
WindowSelectorItem* selected_item_ = nullptr;
// The drag controller for a window in the overview mode.
std::unique_ptr<OverviewWindowDragController> window_drag_controller_;
std::unique_ptr<ScopedHideOverviewWindows> hide_overview_windows_;
DISALLOW_COPY_AND_ASSIGN(WindowSelector);
};
} // namespace ash
#endif // ASH_WM_OVERVIEW_WINDOW_SELECTOR_H_