- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / gtk / tabs / dock_info_gtk.cc
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 #include "chrome/browser/ui/tabs/dock_info.h"
6
7 #include <gtk/gtk.h>
8
9 #include "base/logging.h"
10 #include "chrome/browser/ui/browser_list.h"
11 #include "chrome/browser/ui/browser_window.h"
12 #include "chrome/browser/ui/gtk/browser_window_gtk.h"
13 #include "chrome/browser/ui/gtk/gtk_util.h"
14 #include "chrome/browser/ui/gtk/tabs/tab_gtk.h"
15 #include "chrome/browser/ui/host_desktop.h"
16 #include "ui/base/x/x11_util.h"
17 #include "ui/gfx/native_widget_types.h"
18
19 ////////////////////////////////////////////////////////////////////////////////
20 // BaseWindowFinder
21 //
22 // Base class used to locate a window. A subclass need only override
23 // ShouldStopIterating to determine when iteration should stop.
24 class BaseWindowFinder : public ui::EnumerateWindowsDelegate {
25  public:
26   explicit BaseWindowFinder(const std::set<GtkWidget*>& ignore) {
27     std::set<GtkWidget*>::iterator iter;
28     for (iter = ignore.begin(); iter != ignore.end(); iter++) {
29       XID xid = ui::GetX11WindowFromGtkWidget(*iter);
30       ignore_.insert(xid);
31     }
32   }
33
34   virtual ~BaseWindowFinder() {}
35
36  protected:
37   // Returns true if |window| is in the ignore list.
38   bool ShouldIgnoreWindow(XID window) {
39     return (ignore_.find(window) != ignore_.end());
40   }
41
42   // Returns true if iteration should stop, false otherwise.
43   virtual bool ShouldStopIterating(XID window) OVERRIDE {
44     return false;
45   }
46
47  private:
48   std::set<XID> ignore_;
49
50   DISALLOW_COPY_AND_ASSIGN(BaseWindowFinder);
51 };
52
53 ////////////////////////////////////////////////////////////////////////////////
54 // TopMostFinder
55 //
56 // Helper class to determine if a particular point of a window is not obscured
57 // by another window.
58 class TopMostFinder : public BaseWindowFinder {
59  public:
60   // Returns true if |window| is not obscured by another window at the
61   // location |screen_loc|, not including the windows in |ignore|.
62   static bool IsTopMostWindowAtPoint(XID window,
63                                      const gfx::Point& screen_loc,
64                                      const std::set<GtkWidget*>& ignore) {
65     TopMostFinder finder(window, screen_loc, ignore);
66     return finder.is_top_most_;
67   }
68
69  protected:
70   virtual bool ShouldStopIterating(XID window) OVERRIDE {
71     if (BaseWindowFinder::ShouldIgnoreWindow(window))
72       return false;
73
74     if (window == target_) {
75       // Window is topmost, stop iterating.
76       is_top_most_ = true;
77       return true;
78     }
79
80     if (!ui::IsWindowVisible(window)) {
81       // The window isn't visible, keep iterating.
82       return false;
83     }
84
85     if (ui::WindowContainsPoint(window, screen_loc_))
86       return true;
87
88     return false;
89   }
90
91  private:
92   TopMostFinder(XID window,
93                 const gfx::Point& screen_loc,
94                 const std::set<GtkWidget*>& ignore)
95     : BaseWindowFinder(ignore),
96       target_(window),
97       screen_loc_(screen_loc),
98       is_top_most_(false) {
99     ui::EnumerateTopLevelWindows(this);
100   }
101
102   // The window we're looking for.
103   XID target_;
104
105   // Location of window to find.
106   gfx::Point screen_loc_;
107
108   // Is target_ the top most window? This is initially false but set to true
109   // in ShouldStopIterating if target_ is passed in.
110   bool is_top_most_;
111
112   DISALLOW_COPY_AND_ASSIGN(TopMostFinder);
113 };
114
115 ////////////////////////////////////////////////////////////////////////////////
116 // LocalProcessWindowFinder
117 //
118 // Helper class to determine if a particular point of a window from our process
119 // is not obscured by another window.
120 class LocalProcessWindowFinder : public BaseWindowFinder {
121  public:
122   // Returns the XID from our process at screen_loc that is not obscured by
123   // another window. Returns 0 otherwise.
124   static XID GetProcessWindowAtPoint(const gfx::Point& screen_loc,
125                                      const std::set<GtkWidget*>& ignore) {
126     LocalProcessWindowFinder finder(screen_loc, ignore);
127     if (finder.result_ &&
128         TopMostFinder::IsTopMostWindowAtPoint(finder.result_, screen_loc,
129                                               ignore)) {
130       return finder.result_;
131     }
132     return 0;
133   }
134
135  protected:
136   virtual bool ShouldStopIterating(XID window) OVERRIDE {
137     if (BaseWindowFinder::ShouldIgnoreWindow(window))
138       return false;
139
140     // Check if this window is in our process.
141     if (!BrowserWindowGtk::GetBrowserWindowForXID(window))
142       return false;
143
144     if (!ui::IsWindowVisible(window))
145       return false;
146
147     if (ui::WindowContainsPoint(window, screen_loc_)) {
148       result_ = window;
149       return true;
150     }
151
152     return false;
153   }
154
155  private:
156   LocalProcessWindowFinder(const gfx::Point& screen_loc,
157                            const std::set<GtkWidget*>& ignore)
158     : BaseWindowFinder(ignore),
159       screen_loc_(screen_loc),
160       result_(0) {
161     ui::EnumerateTopLevelWindows(this);
162   }
163
164   // Position of the mouse.
165   gfx::Point screen_loc_;
166
167   // The resulting window. This is initially null but set to true in
168   // ShouldStopIterating if an appropriate window is found.
169   XID result_;
170
171   DISALLOW_COPY_AND_ASSIGN(LocalProcessWindowFinder);
172 };
173
174 // static
175 DockInfo DockInfo::GetDockInfoAtPoint(chrome::HostDesktopType host_desktop_type,
176                                       const gfx::Point& screen_point,
177                                       const std::set<GtkWidget*>& ignore) {
178   NOTIMPLEMENTED();
179   return DockInfo();
180 }
181
182 // static
183 GtkWindow* DockInfo::GetLocalProcessWindowAtPoint(
184     chrome::HostDesktopType host_desktop_type,
185     const gfx::Point& screen_point,
186     const std::set<GtkWidget*>& ignore) {
187   XID xid =
188       LocalProcessWindowFinder::GetProcessWindowAtPoint(screen_point, ignore);
189   return BrowserWindowGtk::GetBrowserWindowForXID(xid);
190 }
191
192 bool DockInfo::GetWindowBounds(gfx::Rect* bounds) const {
193   if (!window())
194     return false;
195
196   int x, y, w, h;
197   gtk_window_get_position(window(), &x, &y);
198   gtk_window_get_size(window(), &w, &h);
199   bounds->SetRect(x, y, w, h);
200   return true;
201 }
202
203 void DockInfo::SizeOtherWindowTo(const gfx::Rect& bounds) const {
204   gtk_window_move(window(), bounds.x(), bounds.y());
205   gtk_window_resize(window(), bounds.width(), bounds.height());
206 }
207
208 // static
209 int DockInfo::GetHotSpotDeltaY() {
210   return TabGtk::GetMinimumUnselectedSize().height() - 1;
211 }