chromium/ash/wm/wm_event.h

// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef ASH_WM_WM_EVENT_H_
#define ASH_WM_WM_EVENT_H_

#include "ash/ash_export.h"
#include "ash/wm/window_state.h"
#include "ash/wm/wm_metrics.h"
#include "chromeos/ui/frame/caption_buttons/snap_controller.h"
#include "chromeos/ui/frame/multitask_menu/float_controller_base.h"
#include "ui/display/display_observer.h"

namespace base {
class TimeDelta;
}  // namespace base

namespace gfx {
class Rect;
}  // namespace gfx

namespace ash {

// WMEventType defines a set of operations that can change the
// window's state type and bounds.
enum WMEventType {
  // Following events are the request to become corresponding state.
  // Note that this does not mean the window will be in corresponding
  // state and the request may not be fullfilled.

  WM_EVENT_NORMAL = 0,
  WM_EVENT_MAXIMIZE,
  WM_EVENT_MINIMIZE,
  WM_EVENT_FULLSCREEN,
  // PRIMARY is left in primary landscape orientation and right in secondary
  // landscape orientation. If |kVerticalSnapState| is enabled, PRIMARY is
  // top in primary portrait orientation and SECONDARY is bottom in secondary
  // portrait orientation. If not, in the clamshell mode, PRIMARY is left and
  // SECONDARY is right.
  WM_EVENT_SNAP_PRIMARY,
  // SECONDARY is the opposite position of PRIMARY, i.e. if PRIMARY is left,
  // SECONDARY is right.
  WM_EVENT_SNAP_SECONDARY,

  // The restore event will change the window state back to its previous
  // applicable window state.
  WM_EVENT_RESTORE,

  // A window is requested to be the given bounds. The request may or
  // may not be fulfilled depending on the requested bounds and window's
  // state. This will not change the window state type.
  WM_EVENT_SET_BOUNDS,

  // Following events are compond events which may lead to different
  // states depending on the current state.

  // A user requested to toggle maximized state by double clicking window
  // header.
  WM_EVENT_TOGGLE_MAXIMIZE_CAPTION,

  // A user requested to toggle maximized state using shortcut.
  WM_EVENT_TOGGLE_MAXIMIZE,

  // A user requested to toggle vertical maximize by double clicking
  // top/bottom edge.
  WM_EVENT_TOGGLE_VERTICAL_MAXIMIZE,

  // A user requested to toggle horizontal maximize by double clicking
  // left/right edge.
  WM_EVENT_TOGGLE_HORIZONTAL_MAXIMIZE,

  // A user requested to toggle fullscreen state.
  WM_EVENT_TOGGLE_FULLSCREEN,

  // A user requested a cycle of snap primary (left).
  // The way this event is processed is the current window state is used as
  // the starting state. Assuming normal window start state; if the window can
  // be snapped primary (left), snap it; otherwise progress to next state. If
  // the window can be restored; and this isn't the entry condition restore it;
  // otherwise apply the bounce animation to the window.
  WM_EVENT_CYCLE_SNAP_PRIMARY,

  // A user requested a cycle of snap secondary (right).
  // See description of WM_EVENT_CYCLE_SNAP_PRIMARY.
  WM_EVENT_CYCLE_SNAP_SECONDARY,

  // TODO(oshima): Investigate if this can be removed from ash.
  // Widget requested to show in inactive state.
  WM_EVENT_SHOW_INACTIVE,

  // Following events are generated when the workspace envrionment has changed.
  // The window's state type will not be changed by these events.

  // The window is added to the workspace, either as a new window, due to
  // display disconnection or dragging.
  WM_EVENT_ADDED_TO_WORKSPACE,

  // A display metric has changed. See DisplayObserver::DisplayMetric for
  // display related metrics.
  WM_EVENT_DISPLAY_METRICS_CHANGED,

  // A user requested to pin a window.
  WM_EVENT_PIN,

  // A user requested to pip a window.
  WM_EVENT_PIP,

  // A user requested to pin a window for a trusted application. This is similar
  // WM_EVENT_PIN but does not allow user to exit the mode by shortcut key.
  WM_EVENT_TRUSTED_PIN,

  // A user requested to float a window.
  WM_EVENT_FLOAT,
};

ASH_EXPORT std::ostream& operator<<(std::ostream& out, WMEventType type);

class SetBoundsWMEvent;
class DisplayMetricsChangedWMEvent;
class WindowFloatWMEvent;
class WindowSnapWMEvent;

class ASH_EXPORT WMEvent {
 public:
  explicit WMEvent(WMEventType type);

  WMEvent(const WMEvent&) = delete;
  WMEvent& operator=(const WMEvent&) = delete;

  virtual ~WMEvent();

  WMEventType type() const { return type_; }

  // Predicates to test the type of event.

  // Event that notifies that workspace has changed. (its size, being
  // added/moved to another workspace,
  // e.g. WM_EVENT_ADDED_TO_WORKSPACE).
  bool IsWorkspaceEvent() const;

  // True if the event will result in another event. For example
  // TOGGLE_FULLSCREEN sends WM_EVENT_FULLSCREEN or WM_EVENT_NORMAL
  // depending on the current state.
  bool IsCompoundEvent() const;

  // WM_EVENT_PIN or WM_EVENT_TRUSTD_PIN.
  bool IsPinEvent() const;

  // True If the event requurests bounds change, e.g. SET_BOUNDS
  bool IsBoundsEvent() const;

  // True if the event requests the window state transition,
  // e.g. WM_EVENT_MAXIMIZED.
  bool IsTransitionEvent() const;

  // True if the event is a window snap event.
  bool IsSnapEvent() const;

  // Utility methods to downcast to specific WMEvent types.
  virtual const SetBoundsWMEvent* AsSetBoundsWMEvent() const;
  virtual const DisplayMetricsChangedWMEvent* AsDisplayMetricsChangedWMEvent()
      const;
  virtual const WindowFloatWMEvent* AsFloatEvent() const;
  virtual const WindowSnapWMEvent* AsSnapEvent() const;

 private:
  WMEventType type_;
};

// A WMEvent to request new bounds for the window in parent coordinates.
class ASH_EXPORT SetBoundsWMEvent : public WMEvent {
 public:
  explicit SetBoundsWMEvent(
      const gfx::Rect& requested_bounds_in_parent,
      bool animate = false,
      base::TimeDelta duration = WindowState::kBoundsChangeSlideDuration);
  SetBoundsWMEvent(const gfx::Rect& requested_bounds_in_parent,
                   int64_t display_id);

  SetBoundsWMEvent(const SetBoundsWMEvent&) = delete;
  SetBoundsWMEvent& operator=(const SetBoundsWMEvent&) = delete;

  ~SetBoundsWMEvent() override;

  const gfx::Rect& requested_bounds_in_parent() const {
    return requested_bounds_in_parent_;
  }

  bool animate() const { return animate_; }

  base::TimeDelta duration() const { return duration_; }

  int64_t display_id() const { return display_id_; }

  // WMevent:
  const SetBoundsWMEvent* AsSetBoundsWMEvent() const override;

 private:
  const gfx::Rect requested_bounds_in_parent_;
  const int64_t display_id_ = display::kInvalidDisplayId;
  const bool animate_;
  const base::TimeDelta duration_;
};

// A WMEvent sent when display metrics have changed.
class ASH_EXPORT DisplayMetricsChangedWMEvent : public WMEvent {
 public:
  explicit DisplayMetricsChangedWMEvent(int display_metrics);

  DisplayMetricsChangedWMEvent(const DisplayMetricsChangedWMEvent&) = delete;
  DisplayMetricsChangedWMEvent& operator=(const DisplayMetricsChangedWMEvent&) =
      delete;

  ~DisplayMetricsChangedWMEvent() override;

  bool display_bounds_changed() const {
    return changed_metrics_ & display::DisplayObserver::DISPLAY_METRIC_BOUNDS;
  }

  bool primary_changed() const {
    return changed_metrics_ & display::DisplayObserver::DISPLAY_METRIC_PRIMARY;
  }

  bool work_area_changed() const {
    return changed_metrics_ &
           display::DisplayObserver::DISPLAY_METRIC_WORK_AREA;
  }

 private:
  const uint32_t changed_metrics_;
};

// An WMEvent to float a window.
class ASH_EXPORT WindowFloatWMEvent : public WMEvent {
 public:
  explicit WindowFloatWMEvent(
      chromeos::FloatStartLocation float_start_location);
  WindowFloatWMEvent(const WindowFloatWMEvent&) = delete;
  WindowFloatWMEvent& operator=(const WindowFloatWMEvent&) = delete;
  ~WindowFloatWMEvent() override;

  chromeos::FloatStartLocation float_start_location() const {
    return float_start_location_;
  }

  // WMEvent:
  const WindowFloatWMEvent* AsFloatEvent() const override;

 private:
  const chromeos::FloatStartLocation float_start_location_;
};

// An WMEvent to snap a window.
class ASH_EXPORT WindowSnapWMEvent : public WMEvent {
 public:
  explicit WindowSnapWMEvent(WMEventType type);
  WindowSnapWMEvent(WMEventType type, float snap_ratio);
  WindowSnapWMEvent(WMEventType type,
                    WindowSnapActionSource snap_action_source);
  WindowSnapWMEvent(WMEventType type,
                    float snap_ratio,
                    WindowSnapActionSource snap_action_source);

  WindowSnapWMEvent(const WindowSnapWMEvent&) = delete;
  WindowSnapWMEvent& operator=(const WindowSnapWMEvent&) = delete;

  ~WindowSnapWMEvent() override;

  float snap_ratio() const { return snap_ratio_; }
  WindowSnapActionSource snap_action_source() const {
    return snap_action_source_;
  }

  // WMEvent:
  const WindowSnapWMEvent* AsSnapEvent() const override;

 private:
  float snap_ratio_ = chromeos::kDefaultSnapRatio;

  WindowSnapActionSource snap_action_source_ =
      WindowSnapActionSource::kNotSpecified;
};

}  // namespace ash

#endif  // ASH_WM_WM_EVENT_H_