multi_window_resize_controller.h 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. // Copyright (c) 2012 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. #ifndef ASH_WM_WORKSPACE_MULTI_WINDOW_RESIZE_CONTROLLER_H_
  5. #define ASH_WM_WORKSPACE_MULTI_WINDOW_RESIZE_CONTROLLER_H_
  6. #include <memory>
  7. #include <vector>
  8. #include "ash/ash_export.h"
  9. #include "ash/wm/overview/overview_observer.h"
  10. #include "ash/wm/window_state.h"
  11. #include "ash/wm/window_state_observer.h"
  12. #include "base/scoped_multi_source_observation.h"
  13. #include "base/timer/timer.h"
  14. #include "ui/aura/window.h"
  15. #include "ui/aura/window_observer.h"
  16. #include "ui/gfx/geometry/rect.h"
  17. #include "ui/views/mouse_watcher.h"
  18. namespace gfx {
  19. class PointF;
  20. }
  21. namespace views {
  22. class Widget;
  23. }
  24. namespace ash {
  25. class MultiWindowResizeControllerTest;
  26. class WorkspaceWindowResizer;
  27. // MultiWindowResizeController is responsible for determining and showing a
  28. // widget that allows resizing multiple windows at the same time.
  29. // MultiWindowResizeController is driven by WorkspaceEventHandler.
  30. class ASH_EXPORT MultiWindowResizeController
  31. : public views::MouseWatcherListener,
  32. public aura::WindowObserver,
  33. public WindowStateObserver,
  34. public OverviewObserver {
  35. public:
  36. MultiWindowResizeController();
  37. MultiWindowResizeController(const MultiWindowResizeController&) = delete;
  38. MultiWindowResizeController& operator=(const MultiWindowResizeController&) =
  39. delete;
  40. ~MultiWindowResizeController() override;
  41. // If necessary, shows the resize widget. |window| is the window the mouse
  42. // is over, |component| the edge and |point| the location of the mouse.
  43. void Show(aura::Window* window, int component, const gfx::Point& point);
  44. // MouseWatcherListener:
  45. void MouseMovedOutOfHost() override;
  46. // WindowObserver:
  47. void OnWindowPropertyChanged(aura::Window* window,
  48. const void* key,
  49. intptr_t old) override;
  50. void OnWindowVisibilityChanged(aura::Window* window, bool visible) override;
  51. void OnWindowDestroying(aura::Window* window) override;
  52. // WindowStateObserver:
  53. void OnPostWindowStateTypeChange(WindowState* window_state,
  54. chromeos::WindowStateType old_type) override;
  55. // OverviewObserver:
  56. void OnOverviewModeStarting() override;
  57. void OnOverviewModeEndingAnimationComplete(bool canceled) override;
  58. private:
  59. friend class MultiWindowResizeControllerTest;
  60. class ResizeMouseWatcherHost;
  61. class ResizeView;
  62. // Two directions resizes happen in.
  63. enum class Direction {
  64. kTopBottom,
  65. kLeftRight,
  66. };
  67. // Used to track the two resizable windows and direction.
  68. struct ResizeWindows {
  69. ResizeWindows();
  70. ResizeWindows(const ResizeWindows& other);
  71. ~ResizeWindows();
  72. // Returns true if |other| equals this ResizeWindows. This does *not*
  73. // consider the windows in |other_windows|.
  74. bool Equals(const ResizeWindows& other) const;
  75. // Returns true if this ResizeWindows is valid.
  76. bool is_valid() const { return window1 && window2; }
  77. // The left/top window to resize.
  78. aura::Window* window1 = nullptr;
  79. // Other window to resize.
  80. aura::Window* window2 = nullptr;
  81. // Direction
  82. Direction direction;
  83. // Windows after |window2| that are to be resized. Determined at the time
  84. // the resize starts.
  85. std::vector<aura::Window*> other_windows;
  86. };
  87. void CreateMouseWatcher();
  88. // Returns a ResizeWindows based on the specified arguments. Use is_valid()
  89. // to test if the return value is a valid multi window resize location.
  90. ResizeWindows DetermineWindows(aura::Window* window,
  91. int window_component,
  92. const gfx::Point& point) const;
  93. // Variant of DetermineWindows() that uses the current location of the mouse
  94. // to determine the resize windows.
  95. ResizeWindows DetermineWindowsFromScreenPoint(aura::Window* window) const;
  96. // Finds a window by edge (one of the constants HitTestCompat.
  97. aura::Window* FindWindowByEdge(aura::Window* window_to_ignore,
  98. int edge_want,
  99. int x_in_parent,
  100. int y_in_parent) const;
  101. // Returns the first window touching |window|.
  102. aura::Window* FindWindowTouching(aura::Window* window,
  103. Direction direction) const;
  104. // Places any windows touching |start| into |others|.
  105. void FindWindowsTouching(aura::Window* start,
  106. Direction direction,
  107. std::vector<aura::Window*>* others) const;
  108. // Starts/Stops observing |window|.
  109. void StartObserving(aura::Window* window);
  110. void StopObserving(aura::Window* window);
  111. // Check if we're observing |window|.
  112. bool IsObserving(aura::Window* window) const;
  113. // Shows the resizer if the mouse is still at a valid location. This is called
  114. // from the |show_timer_|.
  115. void ShowIfValidMouseLocation();
  116. // Shows the widget immediately.
  117. void ShowNow();
  118. // Returns true if the widget is showing.
  119. bool IsShowing() const;
  120. // Hides the resize widget.
  121. void Hide();
  122. // Resets the window resizer and hides the resize widget.
  123. void ResetResizer();
  124. // Initiates a resize.
  125. void StartResize(const gfx::PointF& location_in_screen);
  126. // Resizes to the new location.
  127. void Resize(const gfx::PointF& location_in_screen, int event_flags);
  128. // Completes the resize.
  129. void CompleteResize();
  130. // Cancels the resize.
  131. void CancelResize();
  132. // Returns the bounds for the resize widget.
  133. gfx::Rect CalculateResizeWidgetBounds(
  134. const gfx::PointF& location_in_parent) const;
  135. // Returns true if |location_in_screen| is over the resize widget.
  136. bool IsOverResizeWidget(const gfx::Point& location_in_screen) const;
  137. // Returns true if |location_in_screen| is over the resize windows
  138. // (or the resize widget itself).
  139. bool IsOverWindows(const gfx::Point& location_in_screen) const;
  140. // Returns true if |location_in_screen| is over |component| in |window|.
  141. bool IsOverComponent(aura::Window* window,
  142. const gfx::Point& location_in_screen,
  143. int component) const;
  144. // Windows and direction to resize.
  145. ResizeWindows windows_;
  146. // Timer used before showing.
  147. base::OneShotTimer show_timer_;
  148. std::unique_ptr<views::Widget> resize_widget_;
  149. // If non-null we're in a resize loop.
  150. std::unique_ptr<WorkspaceWindowResizer> window_resizer_;
  151. // Mouse coordinate passed to Show() in container's coodinates.
  152. gfx::Point show_location_in_parent_;
  153. // Bounds the widget was last shown at in screen coordinates.
  154. gfx::Rect show_bounds_in_screen_;
  155. // Used to detect whether the mouse is over the windows. While
  156. // |resize_widget_| is non-NULL (ie the widget is showing) we ignore calls
  157. // to Show().
  158. std::unique_ptr<views::MouseWatcher> mouse_watcher_;
  159. base::ScopedMultiSourceObservation<aura::Window, aura::WindowObserver>
  160. window_observations_{this};
  161. base::ScopedMultiSourceObservation<WindowState, WindowStateObserver>
  162. window_state_observations_{this};
  163. };
  164. } // namespace ash
  165. #endif // ASH_WM_WORKSPACE_MULTI_WINDOW_RESIZE_CONTROLLER_H_