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 CHROME_BROWSER_UI_TABS_DOCK_INFO_H_
6#define CHROME_BROWSER_UI_TABS_DOCK_INFO_H_
7
8#include <set>
9
10#include "chrome/browser/ui/host_desktop.h"
11#include "ui/gfx/native_widget_types.h"
12#include "ui/gfx/point.h"
13#include "ui/gfx/rect.h"
14
15// DockInfo is used to do determine possible dock locations for a dragged
16// tab. To use DockInfo invoke GetDockInfoAtPoint. This returns a new
17// DockInfo whose type indicates the type of dock that should occur based
18// on the screen location. As the user drags the mouse around invoke
19// IsValidForPoint, this returns true if the DockInfo is still valid for the
20// new location. If the DockInfo is not valid, invoke GetDockInfoAtPoint to
21// get the new DockInfo. Use GetNewWindowBounds to get the position to place
22// the new window at.
23//
24// DockInfos are cheap and explicitly allow copy and assignment operators.
25class DockInfo {
26 public:
27  // Possible dock positions.
28  enum Type {
29    // Indicates there is no valid dock position for the current location.
30    NONE,
31
32    // Indicates the new window should be positioned relative to the window
33    // identified by window().
34    LEFT_OF_WINDOW,
35    RIGHT_OF_WINDOW,
36    BOTTOM_OF_WINDOW,
37    TOP_OF_WINDOW,
38
39    // Indicates the window should be maximized on the monitor at hot_spot.
40    MAXIMIZE,
41
42    // Indicates the window should be docked to a specific side of the monitor.
43    LEFT_HALF,
44    RIGHT_HALF,
45    BOTTOM_HALF
46  };
47
48  DockInfo() : type_(NONE), window_(NULL), in_enable_area_(false) {}
49
50  // Returns true if |screen_loc| is close to the hotspot at |x|, |y|. If the
51  // point is close enough to the hotspot true is returned and |in_enable_area|
52  // is set appropriately.
53  static bool IsCloseToPoint(const gfx::Point& screen_loc,
54                             int x,
55                             int y,
56                             bool* in_enable_area);
57
58  // Variant of IsCloseToPoint used for monitor relative positions.
59  static bool IsCloseToMonitorPoint(const gfx::Point& screen_loc,
60                                    int x,
61                                    int y,
62                                    DockInfo::Type type,
63                                    bool* in_enable_area);
64
65  // Size of the popup window shown to indicate a valid dock location.
66  static int popup_width();
67  static int popup_height();
68
69  // Returns the DockInfo for the specified point |screen_point|. |ignore|
70  // contains the set of windows to ignore from consideration. This contains the
71  // dragged window as well as any windows showing possible dock locations.
72  //
73  // If there is no docking position for the specified location the returned
74  // DockInfo has a type of NONE.
75  static DockInfo GetDockInfoAtPoint(chrome::HostDesktopType host_desktop_type,
76                                     const gfx::Point& screen_point,
77                                     const std::set<gfx::NativeView>& ignore);
78
79  // Returns the top most window from the current process at |screen_point|.
80  // See GetDockInfoAtPoint for a description of |ignore|. This returns NULL if
81  // there is no window from the current process at |screen_point|, or another
82  // window obscures the topmost window from our process at |screen_point|.
83  static gfx::NativeWindow GetLocalProcessWindowAtPoint(
84      chrome::HostDesktopType host_desktop_type,
85      const gfx::Point& screen_point,
86      const std::set<gfx::NativeView>& ignore);
87
88  static int GetHotSpotDeltaY();
89
90  // Returns true if this DockInfo is valid for the specified point. This
91  // resets in_enable_area based on the new location.
92  bool IsValidForPoint(const gfx::Point& screen_point);
93
94  // Returns the bounds for the new window in |new_window_bounds|. If the new
95  // window is to be maximized, |maximize_new_window| is set to true.
96  // This returns true if type is other than NONE or the mouse isn't in the
97  // enable area, false otherwise.
98  bool GetNewWindowBounds(gfx::Rect* new_window_bounds,
99                          bool* maximize_new_window) const;
100
101  // Adjust the bounds of the other window during docking. Does nothing if type
102  // is NONE, in_enable_are is false, or the type is not window relative.
103  void AdjustOtherWindowBounds() const;
104
105  // Type of docking to occur.
106  void set_type(Type type) { type_ = type; }
107  Type type() const { return type_; }
108
109  // The window to dock too. Is null for dock types that are relative to the
110  // monitor.
111  void set_window(gfx::NativeWindow window) { window_ = window; }
112  gfx::NativeWindow window() const { return window_; }
113
114  // The location of the hotspot.
115  void set_hot_spot(const gfx::Point& hot_spot) { hot_spot_ = hot_spot; }
116  const gfx::Point& hot_spot() const { return hot_spot_; }
117
118  // Bounds of the monitor.
119  void set_monitor_bounds(const gfx::Rect& monitor_bounds) {
120    monitor_bounds_ = monitor_bounds;
121  }
122  const gfx::Rect& monitor_bounds() const { return monitor_bounds_; }
123
124  // Returns the bounds of the window to show the indicator for.
125  gfx::Rect GetPopupRect() const;
126
127  // Returns true if the drop should result in docking. DockInfo maintains two
128  // states (as indicated by this boolean):
129  // 1. The mouse is close enough to the hot spot such that a visual indicator
130  //    should be shown, but if the user releases the mouse docking shouldn't
131  //    result. This corresponds to a value of false for in_enable_area.
132  // 2. The mouse is close enough to the hot spot such that releasing the mouse
133  //    should result in docking. This corresponds to a value of true for
134  //    in_enable_area.
135  void set_in_enable_area(bool in_enable_area) {
136    in_enable_area_ = in_enable_area;
137  }
138  bool in_enable_area() const { return in_enable_area_; }
139
140  // Returns true if |other| is considered equal to this. Two DockInfos are
141  // considered equal if they have the same type and same window.
142  bool equals(const DockInfo& other) const {
143    return type_ == other.type_ && window_ == other.window_ &&
144           monitor_bounds_ == other.monitor_bounds_;
145  }
146
147  // If screen_loc is close enough to the hot spot given by |x| and |y|, the
148  // type and hot_spot are set from the supplied parameters. This is used
149  // internally, there is no need to invoke this otherwise.
150  bool CheckMonitorPoint(const gfx::Point& screen_loc,
151                         int x,
152                         int y,
153                         Type type);
154
155 private:
156  // Returns the bounds of the window.
157  bool GetWindowBounds(gfx::Rect* bounds) const;
158
159  // Sets the bounds of |window_| to |bounds|.
160  void SizeOtherWindowTo(const gfx::Rect& bounds) const;
161
162  Type type_;
163  gfx::NativeWindow window_;
164  gfx::Point hot_spot_;
165  gfx::Rect monitor_bounds_;
166  bool in_enable_area_;
167};
168
169#endif  // CHROME_BROWSER_UI_TABS_DOCK_INFO_H_
170