Home | History | Annotate | Download | only in workspace
      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 
      5 #ifndef ASH_WM_WORKSPACE_MULTI_WINDOW_RESIZE_CONTROLLER_H_
      6 #define ASH_WM_WORKSPACE_MULTI_WINDOW_RESIZE_CONTROLLER_H_
      7 
      8 #include <vector>
      9 
     10 #include "ash/ash_export.h"
     11 #include "base/basictypes.h"
     12 #include "base/memory/scoped_ptr.h"
     13 #include "base/timer/timer.h"
     14 #include "ui/aura/window_observer.h"
     15 #include "ui/gfx/rect.h"
     16 #include "ui/views/mouse_watcher.h"
     17 
     18 namespace aura {
     19 class Window;
     20 }
     21 
     22 namespace views {
     23 class Widget;
     24 }
     25 
     26 namespace ash {
     27 namespace internal {
     28 
     29 class MultiWindowResizeControllerTest;
     30 class WorkspaceWindowResizer;
     31 
     32 // Two directions resizes happen in.
     33 enum Direction {
     34   TOP_BOTTOM,
     35   LEFT_RIGHT,
     36 };
     37 
     38 // MultiWindowResizeController is responsible for determining and showing a
     39 // widget that allows resizing multiple windows at the same time.
     40 // MultiWindowResizeController is driven by WorkspaceEventFilter.
     41 class ASH_EXPORT MultiWindowResizeController :
     42     public views::MouseWatcherListener, public aura::WindowObserver {
     43  public:
     44   MultiWindowResizeController();
     45   virtual ~MultiWindowResizeController();
     46 
     47   // If necessary, shows the resize widget. |window| is the window the mouse
     48   // is over, |component| the edge and |point| the location of the mouse.
     49   void Show(aura::Window* window, int component, const gfx::Point& point);
     50 
     51   // Hides the resize widget.
     52   void Hide();
     53 
     54   // MouseWatcherListenre overrides:
     55   virtual void MouseMovedOutOfHost() OVERRIDE;
     56 
     57   // WindowObserver overrides:
     58   virtual void OnWindowDestroying(aura::Window* window) OVERRIDE;
     59 
     60  private:
     61   friend class MultiWindowResizeControllerTest;
     62 
     63   // Used to track the two resizable windows and direction.
     64   struct ResizeWindows {
     65     ResizeWindows();
     66     ~ResizeWindows();
     67 
     68     // Returns true if |other| equals this ResizeWindows. This does *not*
     69     // consider the windows in |other_windows|.
     70     bool Equals(const ResizeWindows& other) const;
     71 
     72     // Returns true if this ResizeWindows is valid.
     73     bool is_valid() const { return window1 && window2; }
     74 
     75     // The left/top window to resize.
     76     aura::Window* window1;
     77 
     78     // Other window to resize.
     79     aura::Window* window2;
     80 
     81     // Direction
     82     Direction direction;
     83 
     84     // Windows after |window2| that are to be resized. Determined at the time
     85     // the resize starts.
     86     std::vector<aura::Window*> other_windows;
     87   };
     88 
     89   class ResizeMouseWatcherHost;
     90   class ResizeView;
     91 
     92   // Returns a ResizeWindows based on the specified arguments. Use is_valid()
     93   // to test if the return value is a valid multi window resize location.
     94   ResizeWindows DetermineWindows(aura::Window* window,
     95                                  int window_component,
     96                                  const gfx::Point& point) const;
     97 
     98   // Variant of DetermineWindows() that uses the current location of the mouse
     99   // to determine the resize windows.
    100   ResizeWindows DetermineWindowsFromScreenPoint(aura::Window* window) const;
    101 
    102   // Finds a window by edge (one of the constants HitTestCompat.
    103   aura::Window* FindWindowByEdge(aura::Window* window_to_ignore,
    104                                  int edge_want,
    105                                  int x,
    106                                  int y) const;
    107 
    108   // Returns the first window touching |window|.
    109   aura::Window* FindWindowTouching(aura::Window* window,
    110                                    Direction direction) const;
    111 
    112   // Places any windows touching |start| into |others|.
    113   void FindWindowsTouching(aura::Window* start,
    114                            Direction direction,
    115                            std::vector<aura::Window*>* others) const;
    116 
    117   // Hides the window after a delay.
    118   void DelayedHide();
    119 
    120   // Shows the resizer if the mouse is still at a valid location. This is called
    121   // from the |show_timer_|.
    122   void ShowIfValidMouseLocation();
    123 
    124   // Shows the widget immediately.
    125   void ShowNow();
    126 
    127   // Returns true if the widget is showing.
    128   bool IsShowing() const;
    129 
    130   // Initiates a resize.
    131   void StartResize(const gfx::Point& location_in_screen);
    132 
    133   // Resizes to the new location.
    134   void Resize(const gfx::Point& location_in_screen, int event_flags);
    135 
    136   // Completes the resize.
    137   void CompleteResize(int event_flags);
    138 
    139   // Cancels the resize.
    140   void CancelResize();
    141 
    142   // Returns the bounds for the resize widget.
    143   gfx::Rect CalculateResizeWidgetBounds(
    144       const gfx::Point& location_in_parent) const;
    145 
    146   // Returns true if |location_in_screen| is over the resize windows
    147   // (or the resize widget itself).
    148   bool IsOverWindows(const gfx::Point& location_in_screen) const;
    149 
    150   // Returns true if |location_in_screen| is over |window|.
    151   bool IsOverWindow(aura::Window* window,
    152                     const gfx::Point& location_in_screen,
    153                     int component) const;
    154 
    155   // Windows and direction to resize.
    156   ResizeWindows windows_;
    157 
    158   // Timer before hiding.
    159   base::OneShotTimer<MultiWindowResizeController> hide_timer_;
    160 
    161   // Timer used before showing.
    162   base::OneShotTimer<MultiWindowResizeController> show_timer_;
    163 
    164   scoped_ptr<views::Widget> resize_widget_;
    165 
    166   // If non-null we're in a resize loop.
    167   scoped_ptr<WorkspaceWindowResizer> window_resizer_;
    168 
    169   // Mouse coordinate passed to Show() in container's coodinates.
    170   gfx::Point show_location_in_parent_;
    171 
    172   // Bounds the widget was last shown at in screen coordinates.
    173   gfx::Rect show_bounds_in_screen_;
    174 
    175   // Used to detect whether the mouse is over the windows. While
    176   // |resize_widget_| is non-NULL (ie the widget is showing) we ignore calls
    177   // to Show().
    178   scoped_ptr<views::MouseWatcher> mouse_watcher_;
    179 
    180   DISALLOW_COPY_AND_ASSIGN(MultiWindowResizeController);
    181 };
    182 
    183 }  // namespace internal
    184 }  // namespace ash
    185 
    186 #endif  // ASH_WM_WORKSPACE_MULTI_WINDOW_RESIZE_CONTROLLER_H_
    187