blob: 04fce3e5860d15970ce3a3591fd717928f0e0e04 [file] [log] [blame]
// Copyright 2017 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.
#include <memory>
#include "ash/ash_export.h"
#include "base/macros.h"
#include "base/scoped_observer.h"
#include "ui/aura/window.h"
#include "ui/aura/window_observer.h"
#include "ui/display/display.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#include "ui/wm/core/transient_window_observer.h"
#include "ui/wm/public/activation_change_observer.h"
namespace views {
class Widget;
} // namespace views
namespace aura {
class ScopedWindowTargeter;
} // namespace aura
namespace ash {
namespace mojom {
enum class OrientationLockType;
class SplitViewController;
// Split view divider. It passes the mouse/gesture events to SplitViewController
// to resize the left and right windows accordingly. The divider widget should
// always placed above its observed windows to be able to receive events.
class ASH_EXPORT SplitViewDivider : public aura::WindowObserver,
public ::wm::ActivationChangeObserver,
public ::wm::TransientWindowObserver {
SplitViewDivider(SplitViewController* controller, aura::Window* root_window);
~SplitViewDivider() override;
// Gets the size of the divider widget. The divider widget is enlarged during
// dragging. For now, it's a vertical rectangle.
static gfx::Size GetDividerSize(const gfx::Rect& work_area_bounds,
mojom::OrientationLockType screen_orientation,
bool is_dragging);
// static version of GetDividerBoundsInScreen(bool is_dragging) function.
static gfx::Rect GetDividerBoundsInScreen(
const gfx::Rect& work_area_bounds_in_screen,
mojom::OrientationLockType screen_orientation,
int divider_position,
bool is_dragging);
// Updates |divider_widget_|'s bounds.
void UpdateDividerBounds();
// Calculates the divider's expected bounds according to the divider's
// position.
gfx::Rect GetDividerBoundsInScreen(bool is_dragging);
void AddObservedWindow(aura::Window* window);
void RemoveObservedWindow(aura::Window* window);
// Called when a window tab(s) are being dragged around the workspace. The
// divider should be placed beneath the dragged window during dragging.
void OnWindowDragStarted(aura::Window* dragged_window);
void OnWindowDragEnded();
// aura::WindowObserver:
void OnWindowDestroying(aura::Window* window) override;
// wm::ActivationChangeObserver:
void OnWindowActivated(ActivationReason reason,
aura::Window* gained_active,
aura::Window* lost_active) override;
void OnWindowBoundsChanged(aura::Window* window,
const gfx::Rect& old_bounds,
const gfx::Rect& new_bounds,
ui::PropertyChangeReason reason) override;
// ::wm::TransientWindowObserver:
void OnTransientChildAdded(aura::Window* window,
aura::Window* transient) override;
void OnTransientChildRemoved(aura::Window* window,
aura::Window* transient) override;
views::Widget* divider_widget() { return divider_widget_; }
void CreateDividerWidget(aura::Window* root_window);
void SetAlwaysOnTop(bool on_top);
SplitViewController* controller_;
// The window targeter that is installed on the always on top container window
// when the split view mode is active. It deletes itself when the split view
// mode is ended. Upon destruction, it restores the previous window targeter
// (if any) on the always on top container window.
std::unique_ptr<aura::ScopedWindowTargeter> split_view_window_targeter_;
// Split view divider widget. It's a black bar stretching from one edge of the
// screen to the other, containing a small white drag bar in the middle. As
// the user presses on it and drag it to left or right, the left and right
// window will be resized accordingly.
views::Widget* divider_widget_ = nullptr;
// If true there is a window whose tabs are currently being dragged around.
bool is_dragging_window_ = false;
// Tracks observed windows.
aura::Window::Windows observed_windows_;
// Tracks observed transient windows.
ScopedObserver<aura::Window, aura::WindowObserver>
} // namespace ash