172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/tabs/dock_info.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <gtk/gtk.h>
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/logging.h"
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/task.h"
1121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/browser_list.h"
1221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/browser_window.h"
1372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/browser_window_gtk.h"
1472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/gtk_util.h"
1572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/x/x11_util.h"
1672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/native_widget_types.h"
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////////////
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// BaseWindowFinder
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Base class used to locate a window. A subclass need only override
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// ShouldStopIterating to determine when iteration should stop.
2372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenclass BaseWindowFinder : public ui::EnumerateWindowsDelegate {
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  explicit BaseWindowFinder(const std::set<GtkWidget*>& ignore) {
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::set<GtkWidget*>::iterator iter;
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (iter = ignore.begin(); iter != ignore.end(); iter++) {
2872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      XID xid = ui::GetX11WindowFromGtkWidget(*iter);
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ignore_.insert(xid);
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual ~BaseWindowFinder() {}
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch protected:
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Returns true if |window| is in the ignore list.
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool ShouldIgnoreWindow(XID window) {
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return (ignore_.find(window) != ignore_.end());
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Returns true if iteration should stop, false otherwise.
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual bool ShouldStopIterating(XID window) {
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::set<XID> ignore_;
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DISALLOW_COPY_AND_ASSIGN(BaseWindowFinder);
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////////////
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TopMostFinder
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Helper class to determine if a particular point of a window is not obscured
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// by another window.
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass TopMostFinder : public BaseWindowFinder {
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Returns true if |window| is not obscured by another window at the
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // location |screen_loc|, not including the windows in |ignore|.
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static bool IsTopMostWindowAtPoint(XID window,
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                     const gfx::Point& screen_loc,
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                     const std::set<GtkWidget*>& ignore) {
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TopMostFinder finder(window, screen_loc, ignore);
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return finder.is_top_most_;
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch protected:
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual bool ShouldStopIterating(XID window) {
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (BaseWindowFinder::ShouldIgnoreWindow(window))
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return false;
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (window == target_) {
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Window is topmost, stop iterating.
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      is_top_most_ = true;
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return true;
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (!ui::IsWindowVisible(window)) {
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // The window isn't visible, keep iterating.
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return false;
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gfx::Rect rect;
8572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (ui::GetWindowRect(window, &rect) && rect.Contains(screen_loc_)) {
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // At this point we haven't found our target window, so this window is
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // higher in the z-order than the target window.  If this window contains
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // the point, then we can stop the search now because this window is
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // obscuring the target window at this point.
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return true;
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TopMostFinder(XID window,
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                const gfx::Point& screen_loc,
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                const std::set<GtkWidget*>& ignore)
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : BaseWindowFinder(ignore),
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      target_(window),
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      screen_loc_(screen_loc),
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      is_top_most_(false) {
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_util::EnumerateTopLevelWindows(this);
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The window we're looking for.
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  XID target_;
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Location of window to find.
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Point screen_loc_;
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Is target_ the top most window? This is initially false but set to true
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // in ShouldStopIterating if target_ is passed in.
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool is_top_most_;
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DISALLOW_COPY_AND_ASSIGN(TopMostFinder);
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////////////
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// LocalProcessWindowFinder
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Helper class to determine if a particular point of a window from our process
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// is not obscured by another window.
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass LocalProcessWindowFinder : public BaseWindowFinder {
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Returns the XID from our process at screen_loc that is not obscured by
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // another window. Returns 0 otherwise.
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static XID GetProcessWindowAtPoint(const gfx::Point& screen_loc,
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                     const std::set<GtkWidget*>& ignore) {
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    LocalProcessWindowFinder finder(screen_loc, ignore);
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (finder.result_ &&
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        TopMostFinder::IsTopMostWindowAtPoint(finder.result_, screen_loc,
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                              ignore)) {
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return finder.result_;
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return 0;
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch protected:
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual bool ShouldStopIterating(XID window) {
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (BaseWindowFinder::ShouldIgnoreWindow(window))
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return false;
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Check if this window is in our process.
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!BrowserWindowGtk::GetBrowserWindowForXID(window))
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return false;
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
14972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (!ui::IsWindowVisible(window))
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return false;
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gfx::Rect rect;
15372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (ui::GetWindowRect(window, &rect) && rect.Contains(screen_loc_)) {
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      result_ = window;
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return true;
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  LocalProcessWindowFinder(const gfx::Point& screen_loc,
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                           const std::set<GtkWidget*>& ignore)
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : BaseWindowFinder(ignore),
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      screen_loc_(screen_loc),
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      result_(0) {
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_util::EnumerateTopLevelWindows(this);
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Position of the mouse.
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Point screen_loc_;
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The resulting window. This is initially null but set to true in
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // ShouldStopIterating if an appropriate window is found.
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  XID result_;
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DISALLOW_COPY_AND_ASSIGN(LocalProcessWindowFinder);
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochDockInfo DockInfo::GetDockInfoAtPoint(const gfx::Point& screen_point,
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                      const std::set<GtkWidget*>& ignore) {
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (factory_)
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return factory_->GetDockInfoAtPoint(screen_point, ignore);
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NOTIMPLEMENTED();
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return DockInfo();
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGtkWindow* DockInfo::GetLocalProcessWindowAtPoint(
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const gfx::Point& screen_point,
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const std::set<GtkWidget*>& ignore) {
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (factory_)
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return factory_->GetLocalProcessWindowAtPoint(screen_point, ignore);
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_CHROMEOS) || defined(TOOLKIT_VIEWS)
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return NULL;
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#else
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  XID xid =
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      LocalProcessWindowFinder::GetProcessWindowAtPoint(screen_point, ignore);
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return BrowserWindowGtk::GetBrowserWindowForXID(xid);
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool DockInfo::GetWindowBounds(gfx::Rect* bounds) const {
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!window())
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int x, y, w, h;
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_window_get_position(window(), &x, &y);
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_window_get_size(window(), &w, &h);
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bounds->SetRect(x, y, w, h);
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DockInfo::SizeOtherWindowTo(const gfx::Rect& bounds) const {
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_window_move(window(), bounds.x(), bounds.y());
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_window_resize(window(), bounds.width(), bounds.height());
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
221