diff options
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/dock_info.h | 2 | ||||
-rw-r--r-- | chrome/browser/dock_info_gtk.cc | 185 | ||||
-rw-r--r-- | chrome/browser/gtk/browser_window_gtk.cc | 43 | ||||
-rw-r--r-- | chrome/browser/gtk/browser_window_gtk.h | 21 | ||||
-rw-r--r-- | chrome/browser/gtk/tabs/dragged_tab_controller_gtk.cc | 27 | ||||
-rw-r--r-- | chrome/browser/gtk/tabs/dragged_tab_controller_gtk.h | 11 | ||||
-rw-r--r-- | chrome/browser/gtk/tabs/dragged_tab_gtk.h | 2 | ||||
-rw-r--r-- | chrome/browser/gtk/tabs/tab_strip_gtk.cc | 48 | ||||
-rw-r--r-- | chrome/browser/tab_contents/tab_contents_view_gtk.cc | 4 | ||||
-rw-r--r-- | chrome/chrome.gyp | 5 | ||||
-rw-r--r-- | chrome/common/x11_util.cc | 42 | ||||
-rw-r--r-- | chrome/common/x11_util.h | 27 |
12 files changed, 372 insertions, 45 deletions
diff --git a/chrome/browser/dock_info.h b/chrome/browser/dock_info.h index a2beccb..4f6d476 100644 --- a/chrome/browser/dock_info.h +++ b/chrome/browser/dock_info.h @@ -34,7 +34,7 @@ class DockInfo { const std::set<gfx::NativeView>& ignore) = 0; }; - // Possible dock positions. + // Possible dock positions. enum Type { // Indicates there is no valid dock position for the current location. NONE, diff --git a/chrome/browser/dock_info_gtk.cc b/chrome/browser/dock_info_gtk.cc index e64b966..aadb417 100644 --- a/chrome/browser/dock_info_gtk.cc +++ b/chrome/browser/dock_info_gtk.cc @@ -8,8 +8,172 @@ #include "base/gfx/native_widget_types.h" #include "base/logging.h" +#include "base/task.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_window.h" +#include "chrome/browser/gtk/browser_window_gtk.h" +#include "chrome/common/x11_util.h" + +//////////////////////////////////////////////////////////////////////////////// +// BaseWindowFinder +// +// Base class used to locate a window. A subclass need only override +// ShouldStopIterating to determine when iteration should stop. +class BaseWindowFinder : public x11_util::EnumerateWindowsDelegate { + public: + explicit BaseWindowFinder(const std::set<GtkWidget*>& ignore) { + std::set<GtkWidget*>::iterator iter; + for (iter = ignore.begin(); iter != ignore.end(); iter++) { + XID xid = x11_util::GetX11WindowFromGtkWidget(*iter); + ignore_.insert(xid); + } + } + + virtual ~BaseWindowFinder() {} + + protected: + // Returns true if iteration should stop, false otherwise. + virtual bool ShouldStopIterating(XID window) { + return (ignore_.find(window) != ignore_.end()); + } + + private: + std::set<XID> ignore_; + + DISALLOW_COPY_AND_ASSIGN(BaseWindowFinder); +}; + +//////////////////////////////////////////////////////////////////////////////// +// TopMostFinder +// +// Helper class to determine if a particular point of a window is not obscured +// by another window. +class TopMostFinder : public BaseWindowFinder { + public: + // Returns true if |window| is not obscured by another window at the + // location |screen_loc|, not including the windows in |ignore|. + static bool IsTopMostWindowAtPoint(XID window, + const gfx::Point& screen_loc, + const std::set<GtkWidget*>& ignore) { + TopMostFinder finder(window, screen_loc, ignore); + return finder.is_top_most_; + } + + protected: + virtual bool ShouldStopIterating(XID window) { + if (BaseWindowFinder::ShouldStopIterating(window)) + return true; + + if (window == target_) { + // Window is topmost, stop iterating. + is_top_most_ = true; + return true; + } + + if (x11_util::IsWindowVisible(window)) { + // The window isn't visible, keep iterating. + return false; + } + + gfx::Rect rect; + if (x11_util::GetWindowRect(window, &rect) && rect.Contains(screen_loc_)) { + // At this point we haven't found our target window, so this window is + // higher in the z-order than the target window. If this window contains + // the point, then we can stop the search now because this window is + // obscuring the target window at this point. + return true; + } + + return false; + } + + private: + TopMostFinder(XID window, + const gfx::Point& screen_loc, + const std::set<GtkWidget*>& ignore) + : BaseWindowFinder(ignore), + target_(window), + screen_loc_(screen_loc), + is_top_most_(false) { + XID root = x11_util::GetX11RootWindow(); + x11_util::EnumerateChildWindows(root, this); + } + + // The window we're looking for. + XID target_; + + // Location of window to find. + gfx::Point screen_loc_; + + // Is target_ the top most window? This is initially false but set to true + // in ShouldStopIterating if target_ is passed in. + bool is_top_most_; + + DISALLOW_COPY_AND_ASSIGN(TopMostFinder); +}; + +//////////////////////////////////////////////////////////////////////////////// +// LocalProcessWindowFinder +// +// Helper class to determine if a particular point of a window from our process +// is not obscured by another window. +class LocalProcessWindowFinder : public BaseWindowFinder { + public: + // Returns the XID from our process at screen_loc that is not obscured by + // another window. Returns 0 otherwise. + static XID GetProcessWindowAtPoint(const gfx::Point& screen_loc, + const std::set<GtkWidget*>& ignore) { + LocalProcessWindowFinder finder(screen_loc, ignore); + if (finder.result_ && + TopMostFinder::IsTopMostWindowAtPoint(finder.result_, screen_loc, + ignore)) { + return finder.result_; + } + return 0; + } + + protected: + virtual bool ShouldStopIterating(XID window) { + if (BaseWindowFinder::ShouldStopIterating(window)) + return true; + + // Check if this window is in our process. + if (!BrowserWindowGtk::GetBrowserWindowForXID(window)) + return false; + + if (!x11_util::IsWindowVisible(window)) + return false; + + gfx::Rect rect; + if (x11_util::GetWindowRect(window, &rect) && rect.Contains(screen_loc_)) { + result_ = window; + return true; + } + + return false; + } + + private: + LocalProcessWindowFinder(const gfx::Point& screen_loc, + const std::set<GtkWidget*>& ignore) + : BaseWindowFinder(ignore), + screen_loc_(screen_loc), + result_(0) { + XID root = x11_util::GetX11RootWindow(); + x11_util::EnumerateChildWindows(root, this); + } + + // Position of the mouse. + gfx::Point screen_loc_; + + // The resulting window. This is initially null but set to true in + // ShouldStopIterating if an appropriate window is found. + XID result_; + + DISALLOW_COPY_AND_ASSIGN(LocalProcessWindowFinder); +}; + +DockInfo::Factory* DockInfo::factory_ = NULL; // static DockInfo DockInfo::GetDockInfoAtPoint(const gfx::Point& screen_point, @@ -21,29 +185,16 @@ DockInfo DockInfo::GetDockInfoAtPoint(const gfx::Point& screen_point, return DockInfo(); } +// static GtkWindow* DockInfo::GetLocalProcessWindowAtPoint( const gfx::Point& screen_point, const std::set<GtkWidget*>& ignore) { if (factory_) return factory_->GetLocalProcessWindowAtPoint(screen_point, ignore); - // Iterate over the browserlist to find the window at the specified point. - // This is technically not correct as it doesn't take into account other - // windows that may be on top of a browser window at the same point, but is - // good enough for now. - for (BrowserList::const_iterator i = BrowserList::begin(); - i != BrowserList::end(); ++i) { - Browser* browser = *i; - GtkWindow* window = browser->window()->GetNativeHandle(); - if (ignore.count(GTK_WIDGET(window)) == 0) { - int x, y, w, h; - gtk_window_get_position(window, &x, &y); - gtk_window_get_size(window, &w, &h); - if (gfx::Rect(x, y, w, h).Contains(screen_point)) - return window; - } - } - return NULL; + XID xid = + LocalProcessWindowFinder::GetProcessWindowAtPoint(screen_point, ignore); + return BrowserWindowGtk::GetBrowserWindowForXID(xid); } bool DockInfo::GetWindowBounds(gfx::Rect* bounds) const { diff --git a/chrome/browser/gtk/browser_window_gtk.cc b/chrome/browser/gtk/browser_window_gtk.cc index 8cbf438..5c090d6 100644 --- a/chrome/browser/gtk/browser_window_gtk.cc +++ b/chrome/browser/gtk/browser_window_gtk.cc @@ -46,6 +46,8 @@ const int kLoadingAnimationFrameTimeMs = 30; const GdkColor kBorderColor = GDK_COLOR_RGB(0xbe, 0xc8, 0xd4); +const char* kBrowserWindowKey = "__BROWSER_WINDOW_GTK__"; + gboolean MainWindowConfigured(GtkWindow* window, GdkEventConfigure* event, BrowserWindowGtk* browser_win) { gfx::Rect bounds = gfx::Rect(event->x, event->y, event->width, event->height); @@ -273,6 +275,8 @@ gboolean OnFocusIn(GtkWidget* widget, GdkEventFocus* event, Browser* browser) { } // namespace +std::map<XID, GtkWindow*> BrowserWindowGtk::xid_map_; + // TODO(estade): Break up this constructor into helper functions to improve // readability. BrowserWindowGtk::BrowserWindowGtk(Browser* browser) @@ -283,7 +287,6 @@ BrowserWindowGtk::BrowserWindowGtk(Browser* browser) window_ = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL)); SetWindowIcon(); SetGeometryHints(); - g_object_set_data(G_OBJECT(window_), "browser_window_gtk", this); g_signal_connect(window_, "delete-event", G_CALLBACK(MainWindowDeleteEvent), this); g_signal_connect(window_, "destroy", @@ -292,12 +295,17 @@ BrowserWindowGtk::BrowserWindowGtk(Browser* browser) G_CALLBACK(MainWindowConfigured), this); g_signal_connect(window_, "window-state-event", G_CALLBACK(MainWindowStateChanged), this); + g_signal_connect(window_, "map", + G_CALLBACK(MainWindowMapped), this); + g_signal_connect(window_, "unmap", + G_CALLBACK(MainWindowUnMapped), this); g_signal_connect(window_, "key-press-event", G_CALLBACK(OnKeyPress), browser_.get()); g_signal_connect(window_, "button-press-event", G_CALLBACK(OnButtonPressEvent), browser_.get()); g_signal_connect(window_, "focus-in-event", G_CALLBACK(OnFocusIn), browser_.get()); + g_object_set_data(G_OBJECT(window_), kBrowserWindowKey, this); ConnectAccelerators(); bounds_ = GetInitialWindowBounds(window_); @@ -741,6 +749,22 @@ void BrowserWindowGtk::AddFindBar(FindBarGtk* findbar) { gtk_box_reorder_child(GTK_BOX(render_area_vbox_), findbar->widget(), 0); } +// static +BrowserWindowGtk* BrowserWindowGtk::GetBrowserWindowForNativeWindow( + gfx::NativeWindow window) { + if (window) { + return static_cast<BrowserWindowGtk*>( + g_object_get_data(G_OBJECT(window), kBrowserWindowKey)); + } + + return NULL; +} + +// static +GtkWindow* BrowserWindowGtk::GetBrowserWindowForXID(XID xid) { + return BrowserWindowGtk::xid_map_.find(xid)->second; +} + void BrowserWindowGtk::SetGeometryHints() { // Allow the user to resize us arbitrarily small. GdkGeometry geometry; @@ -833,6 +857,23 @@ gboolean BrowserWindowGtk::OnGtkAccelerator(GtkAccelGroup* accel_group, return TRUE; } +// static +void BrowserWindowGtk::MainWindowMapped(GtkWidget* widget, + BrowserWindowGtk* window) { + // Map the X Window ID of the window to our window. + XID xid = x11_util::GetX11WindowFromGtkWidget(widget); + BrowserWindowGtk::xid_map_.insert( + std::pair<XID, GtkWindow*>(xid, GTK_WINDOW(widget))); +} + +// static +void BrowserWindowGtk::MainWindowUnMapped(GtkWidget* widget, + BrowserWindowGtk* window) { + // Unmap the X Window ID. + XID xid = x11_util::GetX11WindowFromGtkWidget(widget); + BrowserWindowGtk::xid_map_.erase(xid); +} + void BrowserWindowGtk::ExecuteBrowserCommand(int id) { if (browser_->command_updater()->IsCommandEnabled(id)) browser_->ExecuteCommand(id); diff --git a/chrome/browser/gtk/browser_window_gtk.h b/chrome/browser/gtk/browser_window_gtk.h index d2c0589..8e6dee5 100644 --- a/chrome/browser/gtk/browser_window_gtk.h +++ b/chrome/browser/gtk/browser_window_gtk.h @@ -7,12 +7,15 @@ #include <gtk/gtk.h> +#include <map> + #include "base/gfx/rect.h" #include "base/scoped_ptr.h" #include "base/timer.h" #include "chrome/browser/browser_window.h" #include "chrome/browser/tabs/tab_strip_model.h" #include "chrome/common/notification_registrar.h" +#include "chrome/common/x11_util.h" class BookmarkBarGtk; class BrowserToolbarGtk; @@ -94,6 +97,9 @@ class BrowserWindowGtk : public BrowserWindow, bool user_gesture); virtual void TabStripEmpty(); + // Accessor for the tab strip. + TabStripGtk* tabstrip() const { return tabstrip_.get(); } + void MaybeShowBookmarkBar(TabContents* contents); void UpdateUIForContents(TabContents* contents); @@ -109,6 +115,14 @@ class BrowserWindowGtk : public BrowserWindow, // Add the find bar widget to the window hierarchy. void AddFindBar(FindBarGtk* findbar); + // Returns the BrowserWindowGtk registered with |window|. + static BrowserWindowGtk* GetBrowserWindowForNativeWindow( + gfx::NativeWindow window); + + // Retrieves the GtkWindow associated with |xid|, which is the X Window + // ID of the top-level X window of this object. + static GtkWindow* GetBrowserWindowForXID(XID xid); + protected: virtual void DestroyBrowser(); // Top level window. @@ -154,6 +168,10 @@ class BrowserWindowGtk : public BrowserWindow, GdkModifierType modifier, BrowserWindowGtk* browser_window); + // Maps and Unmaps the xid of |widget| to |window|. + static void MainWindowMapped(GtkWidget* widget, BrowserWindowGtk* window); + static void MainWindowUnMapped(GtkWidget* widget, BrowserWindowGtk* window); + // A small shim for browser_->ExecuteCommand. void ExecuteBrowserCommand(int id); @@ -205,6 +223,9 @@ class BrowserWindowGtk : public BrowserWindow, // The timer used to update frames for the Loading Animation. base::RepeatingTimer<BrowserWindowGtk> loading_animation_timer_; + // A map which translates an X Window ID into its respective GtkWindow. + static std::map<XID, GtkWindow*> xid_map_; + DISALLOW_COPY_AND_ASSIGN(BrowserWindowGtk); }; diff --git a/chrome/browser/gtk/tabs/dragged_tab_controller_gtk.cc b/chrome/browser/gtk/tabs/dragged_tab_controller_gtk.cc index 96b4758..59c69ce 100644 --- a/chrome/browser/gtk/tabs/dragged_tab_controller_gtk.cc +++ b/chrome/browser/gtk/tabs/dragged_tab_controller_gtk.cc @@ -5,7 +5,7 @@ #include "chrome/browser/gtk/tabs/dragged_tab_controller_gtk.h" #include "chrome/browser/browser.h" -#include "chrome/browser/browser_window.h" +#include "chrome/browser/gtk/browser_window_gtk.h" #include "chrome/browser/gtk/tabs/dragged_tab_gtk.h" #include "chrome/browser/gtk/tabs/tab_strip_gtk.h" #include "chrome/browser/tabs/tab_strip_model.h" @@ -75,6 +75,13 @@ bool DraggedTabControllerGtk::EndDrag(bool canceled) { return EndDragImpl(canceled ? CANCELED : NORMAL); } +TabGtk* DraggedTabControllerGtk::GetDragSourceTabForContents( + TabContents* contents) const { + if (attached_tabstrip_ == source_tabstrip_) + return contents == dragged_contents_ ? source_tab_ : NULL; + return NULL; +} + bool DraggedTabControllerGtk::IsDragSourceTab(TabGtk* tab) const { return source_tab_ == tab; } @@ -266,8 +273,22 @@ void DraggedTabControllerGtk::MoveTab(const gfx::Point& screen_point) { TabStripGtk* DraggedTabControllerGtk::GetTabStripForPoint( const gfx::Point& screen_point) { - // TODO(jhawkins): Actually get the correct tabstrip under |screen_point|. - return GetTabStripIfItContains(source_tabstrip_, screen_point); + GtkWidget* dragged_window = dragged_tab_->widget(); + dock_windows_.insert(dragged_window); + gfx::NativeWindow local_window = + DockInfo::GetLocalProcessWindowAtPoint(screen_point, dock_windows_); + dock_windows_.erase(dragged_window); + if (!local_window) + return NULL; + + BrowserWindowGtk* browser = + BrowserWindowGtk::GetBrowserWindowForNativeWindow(local_window); + if (!browser) + return NULL; + + TabStripGtk* other_tabstrip = browser->tabstrip(); + // TODO(jhawkins): Make sure the tabstrips are compatible. + return GetTabStripIfItContains(other_tabstrip, screen_point); } TabStripGtk* DraggedTabControllerGtk::GetTabStripIfItContains( diff --git a/chrome/browser/gtk/tabs/dragged_tab_controller_gtk.h b/chrome/browser/gtk/tabs/dragged_tab_controller_gtk.h index 08d656f..87ef243 100644 --- a/chrome/browser/gtk/tabs/dragged_tab_controller_gtk.h +++ b/chrome/browser/gtk/tabs/dragged_tab_controller_gtk.h @@ -7,11 +7,14 @@ #include <gtk/gtk.h> +#include <set> + #include "base/scoped_ptr.h" #include "base/timer.h" #include "chrome/browser/dock_info.h" #include "chrome/browser/tab_contents/tab_contents_delegate.h" #include "chrome/common/notification_registrar.h" +#include "chrome/common/x11_util.h" class DraggedTabGtk; class TabGtk; @@ -39,6 +42,11 @@ class DraggedTabControllerGtk : public NotificationObserver, // begun. Returns whether the tab has been destroyed. bool EndDrag(bool canceled); + // Retrieve the source tab if the TabContents specified matches the one being + // dragged by this controller, or NULL if the specified TabContents is not + // the same as the one being dragged. + TabGtk* GetDragSourceTabForContents(TabContents* contents) const; + // Returns true if the specified tab matches the tab being dragged. bool IsDragSourceTab(TabGtk* tab) const; @@ -225,6 +233,9 @@ class DraggedTabControllerGtk : public NotificationObserver, // DockInfo for the tabstrip. DockInfo dock_info_; + typedef std::set<GtkWidget*> DockWindows; + DockWindows dock_windows_; + // Timer used to bring the window under the cursor to front. If the user // stops moving the mouse for a brief time over a browser window, it is // brought to front. diff --git a/chrome/browser/gtk/tabs/dragged_tab_gtk.h b/chrome/browser/gtk/tabs/dragged_tab_gtk.h index 3ff4231..fab68e1 100644 --- a/chrome/browser/gtk/tabs/dragged_tab_gtk.h +++ b/chrome/browser/gtk/tabs/dragged_tab_gtk.h @@ -49,6 +49,8 @@ class DraggedTabGtk : public AnimationDelegate { // to determine where to place the tab in the attached tabstrip. gfx::Size attached_tab_size() const { return attached_tab_size_; } + GtkWidget* widget() const { return container_; } + private: // Overridden from AnimationDelegate: virtual void AnimationProgressed(const Animation* animation); diff --git a/chrome/browser/gtk/tabs/tab_strip_gtk.cc b/chrome/browser/gtk/tabs/tab_strip_gtk.cc index 00f3fbf..57891f7 100644 --- a/chrome/browser/gtk/tabs/tab_strip_gtk.cc +++ b/chrome/browser/gtk/tabs/tab_strip_gtk.cc @@ -592,20 +592,48 @@ void TabStripGtk::TabInsertedAt(TabContents* contents, if (active_animation_.get()) active_animation_->Stop(); - TabGtk* tab = new TabGtk(this); + bool contains_tab = false; + TabGtk* tab = NULL; + // First see if this Tab is one that was dragged out of this TabStrip and is + // now being dragged back in. In this case, the DraggedTabController actually + // has the Tab already constructed and we can just insert it into our list + // again. + if (IsDragSessionActive()) { + tab = drag_controller_->GetDragSourceTabForContents(contents); + if (tab) { + // If the Tab was detached, it would have been animated closed but not + // removed, so we need to reset this property. + tab->set_closing(false); + tab->ValidateLoadingAnimation(TabRendererGtk::ANIMATION_NONE); + tab->SetVisible(true); + } + + // See if we're already in the list. We don't want to add ourselves twice. + std::vector<TabData>::const_iterator iter = tab_data_.begin(); + for (; iter != tab_data_.end() && !contains_tab; ++iter) { + if (iter->tab == tab) + contains_tab = true; + } + } + + if (!tab) + tab = new TabGtk(this); // Only insert if we're not already in the list. - if (index == TabStripModel::kNoTab) { - TabData d = { tab, gfx::Rect() }; - tab_data_.push_back(d); - tab->UpdateData(contents, false); - } else { - TabData d = { tab, gfx::Rect() }; - tab_data_.insert(tab_data_.begin() + index, d); - tab->UpdateData(contents, false); + if (!contains_tab) { + if (index == TabStripModel::kNoTab) { + TabData d = { tab, gfx::Rect() }; + tab_data_.push_back(d); + tab->UpdateData(contents, false); + } else { + TabData d = { tab, gfx::Rect() }; + tab_data_.insert(tab_data_.begin() + index, d); + tab->UpdateData(contents, false); + } } - gtk_fixed_put(GTK_FIXED(tabstrip_.get()), tab->widget(), 0, 0); + if (gtk_widget_get_parent(tab->widget()) != tabstrip_.get()) + gtk_fixed_put(GTK_FIXED(tabstrip_.get()), tab->widget(), 0, 0); // Don't animate the first tab; it looks weird. if (GetTabCount() > 1) { diff --git a/chrome/browser/tab_contents/tab_contents_view_gtk.cc b/chrome/browser/tab_contents/tab_contents_view_gtk.cc index d6a537a..174b7e7 100644 --- a/chrome/browser/tab_contents/tab_contents_view_gtk.cc +++ b/chrome/browser/tab_contents/tab_contents_view_gtk.cc @@ -255,8 +255,8 @@ void TabContentsViewGtk::HandleKeyboardEvent( return; } - BrowserWindowGtk* browser_window = static_cast<BrowserWindowGtk*>( - g_object_get_data(G_OBJECT(window), "browser_window_gtk")); + BrowserWindowGtk* browser_window = + BrowserWindowGtk::GetBrowserWindowForNativeWindow(window); DCHECK(browser_window); browser_window->HandleAccelerator(event.os_event->keyval, static_cast<GdkModifierType>(event.os_event->state)); diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index a82e7dc..552dd5b 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -1795,11 +1795,6 @@ ['exclude', '^browser/bookmarks/bookmark_context_menu_gtk.cc'], ], }], - ['toolkit_views==0',{ - 'sources/': [ - ['exclude', '^browser/dock_info_gtk.cc'], - ], - }], ], # Exclude files that should be excluded for all non-Windows platforms. 'sources!': [ diff --git a/chrome/common/x11_util.cc b/chrome/common/x11_util.cc index 5371573..b1a24bf 100644 --- a/chrome/common/x11_util.cc +++ b/chrome/common/x11_util.cc @@ -6,9 +6,7 @@ // ported from XCB since we can't use XCB on Ubuntu while its 32-bit support // remains woefully incomplete. -#include "base/thread.h" #include "chrome/common/x11_util.h" -#include "chrome/common/x11_util_internal.h" #include <string.h> @@ -21,6 +19,8 @@ #include "base/logging.h" #include "base/gfx/size.h" +#include "base/thread.h" +#include "chrome/common/x11_util_internal.h" namespace x11_util { @@ -137,6 +137,44 @@ int BitsPerPixelForPixmapDepth(Display* dpy, int depth) { return bits_per_pixel; } +bool IsWindowVisible(XID window) { + XWindowAttributes win_attributes; + XGetWindowAttributes(GetXDisplay(), window, &win_attributes); + return (win_attributes.map_state == IsViewable); +} + +bool GetWindowRect(XID window, gfx::Rect* rect) { + Window root_window; + int x, y; + unsigned int width, height; + unsigned int border_width, depth; + + if (!XGetGeometry(GetXDisplay(), window, &root_window, &x, &y, + &width, &height, &border_width, &depth)) + return false; + + *rect = gfx::Rect(x, y, width, height); + return true; +} + +bool EnumerateChildWindows(XID root, EnumerateWindowsDelegate* delegate) { + XID parent; + XID* children; + unsigned int num_children; + int status = XQueryTree(GetXDisplay(), root, &root, &parent, + &children, &num_children); + if (status == 0) + return false; + + for (unsigned int i = 0; i < num_children; i++) { + if (delegate->ShouldStopIterating(children[i])) + break; + } + + XFree(children); + return true; +} + XRenderPictFormat* GetRenderVisualFormat(Display* dpy, Visual* visual) { static XRenderPictFormat* pictformat = NULL; if (pictformat) diff --git a/chrome/common/x11_util.h b/chrome/common/x11_util.h index dddd40c..d177800 100644 --- a/chrome/common/x11_util.h +++ b/chrome/common/x11_util.h @@ -11,6 +11,9 @@ // we use a void* for Visual*). The Xlib headers are highly polluting so we try // hard to limit their spread into the rest of the code. +#include "base/gfx/rect.h" +#include "base/task.h" + typedef struct _GdkDrawable GdkWindow; typedef struct _GtkWidget GtkWidget; typedef unsigned long XID; @@ -45,13 +48,29 @@ int GetDefaultScreen(Display* display); // Get the X window id for the default root window XID GetX11RootWindow(); // Get the X window id for the given GTK widget. -XID GetX11WindowFromGtkWidget(GtkWidget*); -XID GetX11WindowFromGdkWindow(GdkWindow*); +XID GetX11WindowFromGtkWidget(GtkWidget* widget); +XID GetX11WindowFromGdkWindow(GdkWindow* window); // Get a Visual from the given widget. Since we don't include the Xlib // headers, this is returned as a void*. -void* GetVisualFromGtkWidget(GtkWidget*); +void* GetVisualFromGtkWidget(GtkWidget* widget); // Return the number of bits-per-pixel for a pixmap of the given depth -int BitsPerPixelForPixmapDepth(Display*, int depth); +int BitsPerPixelForPixmapDepth(Display* display, int depth); +// Returns true if |window| is visible. +bool IsWindowVisible(XID window); +// Returns the bounds of |window|. +bool GetWindowRect(XID window, gfx::Rect* rect); + +// Implementers of this interface receive a notification for every X window of +// the main display. +class EnumerateWindowsDelegate { + public: + // |xid| is the X Window ID of the enumerated window. Return true to stop + // further iteration. + virtual bool ShouldStopIterating(XID xid) = 0; +}; + +// Enumerates the child windows of |root|. +bool EnumerateChildWindows(XID root, EnumerateWindowsDelegate* delegate); // Return a handle to a server side pixmap. |shared_memory_key| is a SysV // IPC key. The shared memory region must contain 32-bit pixels. |