summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-09 00:13:30 +0000
committerjhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-09 00:13:30 +0000
commit19aad64511d3fad539184abfe5af5ff6264e630c (patch)
tree02267694a54ea272091e74bfad14f4e7c6fa8d27
parent3aeef847d90b695428851813fc6ada34aac5a21d (diff)
downloadchromium_src-19aad64511d3fad539184abfe5af5ff6264e630c.zip
chromium_src-19aad64511d3fad539184abfe5af5ff6264e630c.tar.gz
chromium_src-19aad64511d3fad539184abfe5af5ff6264e630c.tar.bz2
Implement URL Drag & Drop for the linux tabstrip.
BUG=none TEST=Drag a link from Firefox into the Chromium tab strip. A new tab should open either before, after, or in the same tab depending on where the drop occurred. Review URL: http://codereview.chromium.org/118411 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@17915 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/gtk/dnd_registry.h6
-rw-r--r--chrome/browser/gtk/tabs/dragged_tab_gtk.cc8
-rw-r--r--chrome/browser/gtk/tabs/tab_strip_gtk.cc311
-rw-r--r--chrome/browser/gtk/tabs/tab_strip_gtk.h90
-rw-r--r--chrome/common/gtk_util.cc13
-rw-r--r--chrome/common/gtk_util.h6
6 files changed, 426 insertions, 8 deletions
diff --git a/chrome/browser/gtk/dnd_registry.h b/chrome/browser/gtk/dnd_registry.h
index 1500c44..141e33a 100644
--- a/chrome/browser/gtk/dnd_registry.h
+++ b/chrome/browser/gtk/dnd_registry.h
@@ -16,6 +16,11 @@ enum {
// Tab DND items:
X_CHROME_TAB = 0,
+ // Tabstrip DND items:
+ X_CHROME_STRING,
+ X_CHROME_TEXT_PLAIN,
+ X_CHROME_TEXT_URI_LIST,
+
// Bookmark DND items:
X_CHROME_BOOKMARK_ITEM
};
@@ -23,4 +28,3 @@ enum {
};
#endif // CHROME_BROWSER_GTK_DND_REGISTRY_H_
-
diff --git a/chrome/browser/gtk/tabs/dragged_tab_gtk.cc b/chrome/browser/gtk/tabs/dragged_tab_gtk.cc
index 48413ef..b7ca602 100644
--- a/chrome/browser/gtk/tabs/dragged_tab_gtk.cc
+++ b/chrome/browser/gtk/tabs/dragged_tab_gtk.cc
@@ -11,6 +11,7 @@
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/tabs/tab_strip_model.h"
#include "chrome/browser/gtk/tabs/tab_renderer_gtk.h"
+#include "chrome/common/gtk_util.h"
#include "third_party/skia/include/core/SkShader.h"
namespace {
@@ -24,11 +25,6 @@ const float kScalingFactor = 0.5;
const int kAnimateToBoundsDurationMs = 150;
-bool IsScreenComposited() {
- GdkScreen* screen = gdk_screen_get_default();
- return gdk_screen_is_composited(screen) == TRUE;
-}
-
} // namespace
////////////////////////////////////////////////////////////////////////////////
@@ -215,7 +211,7 @@ void DraggedTabGtk::SetContainerShapeMask() {
gboolean DraggedTabGtk::OnExposeEvent(GtkWidget* widget,
GdkEventExpose* event,
DraggedTabGtk* dragged_tab) {
- if (IsScreenComposited()) {
+ if (gtk_util::IsScreenComposited()) {
dragged_tab->SetContainerTransparency();
} else {
dragged_tab->SetContainerShapeMask();
diff --git a/chrome/browser/gtk/tabs/tab_strip_gtk.cc b/chrome/browser/gtk/tabs/tab_strip_gtk.cc
index 7cbdf67..38f610b 100644
--- a/chrome/browser/gtk/tabs/tab_strip_gtk.cc
+++ b/chrome/browser/gtk/tabs/tab_strip_gtk.cc
@@ -13,9 +13,11 @@
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_theme_provider.h"
#include "chrome/browser/gtk/custom_button.h"
+#include "chrome/browser/gtk/dnd_registry.h"
#include "chrome/browser/gtk/tabs/dragged_tab_controller_gtk.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/common/gtk_util.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/pref_service.h"
#include "grit/app_resources.h"
@@ -41,6 +43,10 @@ const int kTabHOffset = -16;
// A linux specific menu item for toggling window decorations.
const int kShowWindowDecorationsCommand = 200;
+// Size of the drop indicator.
+static int drop_indicator_width;
+static int drop_indicator_height;
+
inline int Round(double x) {
return static_cast<int>(x + 0.5);
}
@@ -53,6 +59,20 @@ gfx::Rect GetInitialWidgetBounds(GtkWidget* widget) {
return gfx::Rect(0, 0, request.width, request.height);
}
+// Mime types for DnD. Used to synchronize across applications.
+const char kTargetString[] = "STRING";
+const char kTargetTextPlain[] = "text/plain";
+const char kTargetTextUriList[] = "text/uri-list";
+
+// Table of the mime types that we accept with their options.
+const GtkTargetEntry kTargetTable[] = {
+ { const_cast<gchar*>(kTargetString), 0, dnd::X_CHROME_STRING },
+ { const_cast<gchar*>(kTargetTextPlain), 0, dnd::X_CHROME_TEXT_PLAIN },
+ { const_cast<gchar*>(kTargetTextUriList), 0, dnd::X_CHROME_TEXT_URI_LIST }
+};
+
+const int kTargetTableSize = G_N_ELEMENTS(kTargetTable);
+
} // namespace
////////////////////////////////////////////////////////////////////////////////
@@ -359,7 +379,7 @@ class MoveTabAnimation : public TabStripGtk::TabAnimation {
}
protected:
- // Overridden from TabStrip::TabAnimation:
+ // Overridden from TabStripGtk::TabAnimation:
virtual int GetDuration() const { return kReorderAnimationDurationMs; }
private:
@@ -469,18 +489,35 @@ void TabStripGtk::Init(int width, Profile* profile) {
gtk_widget_set_size_request(tabstrip_.get(), width,
TabGtk::GetMinimumUnselectedSize().height());
gtk_widget_set_app_paintable(tabstrip_.get(), TRUE);
+ gtk_drag_dest_set(tabstrip_.get(), GTK_DEST_DEFAULT_ALL,
+ kTargetTable, kTargetTableSize,
+ static_cast<GdkDragAction>(
+ GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK));
g_signal_connect(G_OBJECT(tabstrip_.get()), "expose-event",
G_CALLBACK(OnExpose), this);
g_signal_connect(G_OBJECT(tabstrip_.get()), "size-allocate",
G_CALLBACK(OnSizeAllocate), this);
g_signal_connect(G_OBJECT(tabstrip_.get()), "button-press-event",
G_CALLBACK(OnButtonPress), this);
+ g_signal_connect(G_OBJECT(tabstrip_.get()), "drag-motion",
+ G_CALLBACK(OnDragMotion), this);
+ g_signal_connect(G_OBJECT(tabstrip_.get()), "drag-drop",
+ G_CALLBACK(OnDragDrop), this);
+ g_signal_connect(G_OBJECT(tabstrip_.get()), "drag-data-received",
+ G_CALLBACK(OnDragDataReceived), this);
newtab_button_.reset(MakeNewTabButton());
gtk_widget_show_all(tabstrip_.get());
bounds_ = GetInitialWidgetBounds(tabstrip_.get());
+
+ if (drop_indicator_width == 0) {
+ // Direction doesn't matter, both images are the same size.
+ GdkPixbuf* drop_image = GetDropArrowImage(true);
+ drop_indicator_width = gdk_pixbuf_get_width(drop_image);
+ drop_indicator_height = gdk_pixbuf_get_height(drop_image);
+ }
}
void TabStripGtk::AddTabStripToBox(GtkWidget* box) {
@@ -974,6 +1011,231 @@ void TabStripGtk::ResizeLayoutTabs() {
StartResizeLayoutAnimation();
}
+gfx::Rect TabStripGtk::GetDropBounds(int drop_index,
+ bool drop_before,
+ bool* is_beneath) {
+ DCHECK(drop_index != -1);
+ int center_x;
+ if (drop_index < GetTabCount()) {
+ TabGtk* tab = GetTabAt(drop_index);
+ if (drop_before)
+ center_x = tab->x() - (kTabHOffset / 2);
+ else
+ center_x = tab->x() + (tab->width() / 2);
+ } else {
+ TabGtk* last_tab = GetTabAt(drop_index - 1);
+ center_x = last_tab->x() + last_tab->width() + (kTabHOffset / 2);
+ }
+
+ // TODO(jhawkins): Handle RTL layout.
+
+ // Determine the screen bounds.
+ gfx::Point drop_loc(center_x - drop_indicator_width / 2,
+ -drop_indicator_height);
+ gtk_util::ConvertWidgetPointToScreen(tabstrip_.get(), &drop_loc);
+ gfx::Rect drop_bounds(drop_loc.x(), drop_loc.y(), drop_indicator_width,
+ drop_indicator_height);
+
+ // TODO(jhawkins): We always display the arrow underneath the tab because we
+ // don't have custom frame support yet.
+ *is_beneath = true;
+ if (*is_beneath)
+ drop_bounds.Offset(0, drop_bounds.height() + bounds().height());
+
+ return drop_bounds;
+}
+
+void TabStripGtk::UpdateDropIndex(GdkDragContext* context, gint x, gint y) {
+ // TODO(jhawkins): Handle RTL layout.
+ for (int i = 0; i < GetTabCount(); ++i) {
+ TabGtk* tab = GetTabAt(i);
+ const int tab_max_x = tab->x() + tab->width();
+ const int hot_width = tab->width() / 3;
+ if (x < tab_max_x) {
+ if (x < tab->x() + hot_width)
+ SetDropIndex(i, true);
+ else if (x >= tab_max_x - hot_width)
+ SetDropIndex(i + 1, true);
+ else
+ SetDropIndex(i, false);
+ return;
+ }
+ }
+
+ // The drop isn't over a tab, add it to the end.
+ SetDropIndex(GetTabCount(), true);
+}
+
+void TabStripGtk::SetDropIndex(int index, bool drop_before) {
+ if (index == -1) {
+ if (drop_info_.get())
+ drop_info_.reset(NULL);
+ return;
+ }
+
+ if (drop_info_.get() && drop_info_->drop_index == index &&
+ drop_info_->drop_before == drop_before) {
+ return;
+ }
+
+ bool is_beneath;
+ gfx::Rect drop_bounds = GetDropBounds(index, drop_before, &is_beneath);
+
+ if (!drop_info_.get()) {
+ drop_info_.reset(new DropInfo(index, drop_before, !is_beneath));
+ } else {
+ drop_info_->drop_index = index;
+ drop_info_->drop_before = drop_before;
+ if (is_beneath == drop_info_->point_down) {
+ drop_info_->point_down = !is_beneath;
+ drop_info_->drop_arrow= GetDropArrowImage(drop_info_->point_down);
+ }
+ }
+
+ gtk_window_move(GTK_WINDOW(drop_info_->container),
+ drop_bounds.x(), drop_bounds.y());
+ gtk_window_resize(GTK_WINDOW(drop_info_->container),
+ drop_bounds.width(), drop_bounds.height());
+}
+
+void TabStripGtk::CompleteDrop(guchar* data) {
+ if (!drop_info_.get())
+ return;
+
+ const int drop_index = drop_info_->drop_index;
+ const bool drop_before = drop_info_->drop_before;
+
+ // Hide the drop indicator.
+ SetDropIndex(-1, false);
+
+ GURL url(reinterpret_cast<char*>(data));
+ if (!url.is_valid())
+ return;
+
+ if (drop_before) {
+ // Insert a new tab.
+ TabContents* contents =
+ model_->delegate()->CreateTabContentsForURL(
+ url, GURL(), model_->profile(), PageTransition::TYPED, false,
+ NULL);
+ model_->AddTabContents(contents, drop_index, false,
+ PageTransition::GENERATED, true);
+ } else {
+ model_->GetTabContentsAt(drop_index)->controller().LoadURL(
+ url, GURL(), PageTransition::GENERATED);
+ model_->SelectTabContentsAt(drop_index, true);
+ }
+}
+
+// static
+GdkPixbuf* TabStripGtk::GetDropArrowImage(bool is_down) {
+ return ResourceBundle::GetSharedInstance().GetPixbufNamed(
+ is_down ? IDR_TAB_DROP_DOWN : IDR_TAB_DROP_UP);
+}
+
+// TabStripGtk::DropInfo -------------------------------------------------------
+
+TabStripGtk::DropInfo::DropInfo(int drop_index, bool drop_before,
+ bool point_down)
+ : drop_index(drop_index),
+ drop_before(drop_before),
+ point_down(point_down) {
+ container = gtk_window_new(GTK_WINDOW_POPUP);
+ SetContainerColorMap();
+ gtk_widget_set_app_paintable(container, TRUE);
+ g_signal_connect(G_OBJECT(container), "expose-event",
+ G_CALLBACK(OnExposeEvent), this);
+ gtk_widget_add_events(container, GDK_STRUCTURE_MASK);
+ gtk_widget_show_all(container);
+
+ drop_arrow = GetDropArrowImage(point_down);
+
+ gtk_window_move(GTK_WINDOW(container), 0, 0);
+ gtk_window_resize(GTK_WINDOW(container),
+ drop_indicator_width, drop_indicator_height);
+}
+
+TabStripGtk::DropInfo::~DropInfo() {
+ gtk_widget_destroy(container);
+}
+
+// static
+gboolean TabStripGtk::DropInfo::OnExposeEvent(GtkWidget* widget,
+ GdkEventExpose* event,
+ DropInfo* drop_info) {
+ if (gtk_util::IsScreenComposited()) {
+ drop_info->SetContainerTransparency();
+ } else {
+ drop_info->SetContainerShapeMask();
+ }
+
+ gdk_pixbuf_render_to_drawable(drop_info->drop_arrow,
+ drop_info->container->window,
+ 0, 0, 0,
+ 0, 0,
+ drop_indicator_width,
+ drop_indicator_height,
+ GDK_RGB_DITHER_NONE, 0, 0);
+
+ return FALSE;
+}
+
+// Sets the color map of the container window to allow the window to be
+// transparent.
+void TabStripGtk::DropInfo::SetContainerColorMap() {
+ GdkScreen* screen = gtk_widget_get_screen(container);
+ GdkColormap* colormap = gdk_screen_get_rgba_colormap(screen);
+
+ // If rgba is not available, use rgb instead.
+ if (!colormap)
+ colormap = gdk_screen_get_rgb_colormap(screen);
+
+ gtk_widget_set_colormap(container, colormap);
+}
+
+// Sets full transparency for the container window. This is used if
+// compositing is available for the screen.
+void TabStripGtk::DropInfo::SetContainerTransparency() {
+ cairo_t* cairo_context = gdk_cairo_create(container->window);
+ if (!cairo_context)
+ return;
+
+ // Make the background of the dragged tab window fully transparent. All of
+ // the content of the window (child widgets) will be completely opaque.
+
+ cairo_scale(cairo_context, static_cast<double>(drop_indicator_width),
+ static_cast<double>(drop_indicator_height));
+ cairo_set_source_rgba(cairo_context, 1.0f, 1.0f, 1.0f, 0.0f);
+ cairo_set_operator(cairo_context, CAIRO_OPERATOR_SOURCE);
+ cairo_paint(cairo_context);
+ cairo_destroy(cairo_context);
+}
+
+// Sets the shape mask for the container window to emulate a transparent
+// container window. This is used if compositing is not available for the
+// screen.
+void TabStripGtk::DropInfo::SetContainerShapeMask() {
+ // Create a 1bpp bitmap the size of |container|.
+ GdkPixmap* pixmap = gdk_pixmap_new(NULL,
+ drop_indicator_width,
+ drop_indicator_height, 1);
+ cairo_t* cairo_context = gdk_cairo_create(GDK_DRAWABLE(pixmap));
+
+ // Set the transparency.
+ cairo_set_source_rgba(cairo_context, 1, 1, 1, 0);
+
+ // Blit the rendered bitmap into a pixmap. Any pixel set in the pixmap will
+ // be opaque in the container window.
+ cairo_set_operator(cairo_context, CAIRO_OPERATOR_SOURCE);
+ gdk_cairo_set_source_pixbuf(cairo_context, drop_arrow, 0, 0);
+ cairo_paint(cairo_context);
+ cairo_destroy(cairo_context);
+
+ // Set the shape mask.
+ gdk_window_shape_combine_mask(container->window, pixmap, 0, 0);
+ g_object_unref(pixmap);
+}
+
// Called from:
// - animation tick
void TabStripGtk::AnimationLayout(double unselected_width) {
@@ -1142,6 +1404,53 @@ gboolean TabStripGtk::OnButtonPress(GtkWidget* widget, GdkEventButton* event,
}
// static
+gboolean TabStripGtk::OnDragMotion(GtkWidget* widget, GdkDragContext* context,
+ gint x, gint y, guint time,
+ TabStripGtk* tabstrip) {
+ tabstrip->UpdateDropIndex(context, x, y);
+ return TRUE;
+}
+
+// static
+gboolean TabStripGtk::OnDragDrop(GtkWidget* widget, GdkDragContext* context,
+ gint x, gint y, guint time,
+ TabStripGtk* tabstrip) {
+ if (!tabstrip->drop_info_.get())
+ return FALSE;
+
+ GtkTargetList* list = gtk_target_list_new(kTargetTable, kTargetTableSize);
+ DCHECK(list);
+
+ GList* target = context->targets;
+ for (; target != NULL; target = target->next) {
+ guint info;
+ GdkAtom target_atom = GDK_POINTER_TO_ATOM(target->data);
+ if (gtk_target_list_find(list, target_atom, &info)) {
+ gtk_drag_get_data(widget, context, target_atom, time);
+ }
+ }
+
+ g_free(list);
+ return TRUE;
+}
+
+// static
+gboolean TabStripGtk::OnDragDataReceived(GtkWidget* widget,
+ GdkDragContext* context,
+ gint x, gint y,
+ GtkSelectionData* data,
+ guint info, guint time,
+ TabStripGtk* tabstrip) {
+ // TODO(jhawkins): Parse URI lists.
+ if (info == dnd::X_CHROME_STRING || info == dnd::X_CHROME_TEXT_PLAIN) {
+ tabstrip->CompleteDrop(data->data);
+ gtk_drag_finish(context, TRUE, TRUE, time);
+ }
+
+ return TRUE;
+}
+
+// static
void TabStripGtk::OnNewTabClicked(GtkWidget* widget, TabStripGtk* tabstrip) {
tabstrip->model_->delegate()->AddBlankTab(true);
}
diff --git a/chrome/browser/gtk/tabs/tab_strip_gtk.h b/chrome/browser/gtk/tabs/tab_strip_gtk.h
index 0b3a809..ddb79b0 100644
--- a/chrome/browser/gtk/tabs/tab_strip_gtk.h
+++ b/chrome/browser/gtk/tabs/tab_strip_gtk.h
@@ -121,6 +121,55 @@ class TabStripGtk : public TabStripModelObserver,
gfx::Rect ideal_bounds;
};
+ // Used during a drop session of a url. Tracks the position of the drop as
+ // well as a window used to highlight where the drop occurs.
+ class DropInfo {
+ public:
+ DropInfo(int index, bool drop_before, bool point_down);
+ ~DropInfo();
+
+ // TODO(jhawkins): Factor out this code into a TransparentContainer class.
+
+ // expose-event handler that redraws the drop indicator.
+ static gboolean OnExposeEvent(GtkWidget* widget, GdkEventExpose* event,
+ DropInfo* drop_info);
+
+ // Sets the color map of the container window to allow the window to be
+ // transparent.
+ void SetContainerColorMap();
+
+ // Sets full transparency for the container window. This is used if
+ // compositing is available for the screen.
+ void SetContainerTransparency();
+
+ // Sets the shape mask for the container window to emulate a transparent
+ // container window. This is used if compositing is not available for the
+ // screen.
+ void SetContainerShapeMask();
+
+ // Index of the tab to drop on. If drop_before is true, the drop should
+ // occur between the tab at drop_index - 1 and drop_index.
+ // WARNING: if drop_before is true it is possible this will == tab_count,
+ // which indicates the drop should create a new tab at the end of the tabs.
+ int drop_index;
+ bool drop_before;
+
+ // Direction the arrow should point in. If true, the arrow is displayed
+ // above the tab and points down. If false, the arrow is displayed beneath
+ // the tab and points up.
+ bool point_down;
+
+ // Transparent container window used to render the drop indicator over the
+ // tabstrip and toolbar.
+ GtkWidget* container;
+
+ // The drop indicator image.
+ GdkPixbuf* drop_arrow;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DropInfo);
+ };
+
// expose-event handler that redraws the tabstrip
static gboolean OnExpose(GtkWidget* widget, GdkEventExpose* e,
TabStripGtk* tabstrip);
@@ -133,6 +182,23 @@ class TabStripGtk : public TabStripModelObserver,
static gboolean OnButtonPress(GtkWidget* widget, GdkEventButton* event,
TabStripGtk* tabstrip);
+ // drag-motion handler that is signaled when the user performs a drag in the
+ // tabstrip bounds.
+ static gboolean OnDragMotion(GtkWidget* widget, GdkDragContext* context,
+ gint x, gint y, guint time,
+ TabStripGtk* tabstrip);
+
+ // drag-drop handler that is notified when the user finishes a drag.
+ static gboolean OnDragDrop(GtkWidget* widget, GdkDragContext* context,
+ gint x, gint y, guint time,
+ TabStripGtk* tabstrip);
+
+ // drag-data-received handler that receives the data assocated with the drag.
+ static gboolean OnDragDataReceived(GtkWidget* widget, GdkDragContext* context,
+ gint x, gint y, GtkSelectionData* data,
+ guint info, guint time,
+ TabStripGtk* tabstrip);
+
// Handles the clicked signal from the new tab button.
static void OnNewTabClicked(GtkWidget* widget, TabStripGtk* tabstrip);
@@ -200,6 +266,27 @@ class TabStripGtk : public TabStripModelObserver,
virtual bool IsItemChecked(int command_id) const;
virtual void ExecuteCommand(int command_id);
+ // -- Link Drag & Drop ------------------------------------------------------
+
+ // Returns the bounds to render the drop at, in screen coordinates. Sets
+ // |is_beneath| to indicate whether the arrow is beneath the tab, or above
+ // it.
+ gfx::Rect GetDropBounds(int drop_index, bool drop_before, bool* is_beneath);
+
+ // Updates the location of the drop based on the event.
+ void UpdateDropIndex(GdkDragContext* context, gint x, gint y);
+
+ // Sets the location of the drop, repainting as necessary.
+ void SetDropIndex(int index, bool drop_before);
+
+ // Determines whether the data is acceptable by the tabstrip and opens a new
+ // tab with the data as URL if it is.
+ void CompleteDrop(guchar* data);
+
+ // Returns the image to use for indicating a drop on a tab. If is_down is
+ // true, this returns an arrow pointing down.
+ static GdkPixbuf* GetDropArrowImage(bool is_down);
+
// -- Animations -------------------------------------------------------------
// A generic Layout method for various classes of TabStrip animations,
@@ -264,6 +351,9 @@ class TabStripGtk : public TabStripModelObserver,
// The New Tab button.
scoped_ptr<CustomDrawButton> newtab_button_;
+ // Valid for the lifetime of a drag over us.
+ scoped_ptr<DropInfo> drop_info_;
+
// The controller for a drag initiated from a Tab. Valid for the lifetime of
// the drag session.
scoped_ptr<DraggedTabControllerGtk> drag_controller_;
diff --git a/chrome/common/gtk_util.cc b/chrome/common/gtk_util.cc
index 515482b..c3369d9 100644
--- a/chrome/common/gtk_util.cc
+++ b/chrome/common/gtk_util.cc
@@ -93,6 +93,14 @@ gfx::Rect GetWidgetScreenBounds(GtkWidget* widget) {
widget->allocation.width, widget->allocation.height);
}
+void ConvertWidgetPointToScreen(GtkWidget* widget, gfx::Point* p) {
+ DCHECK(widget);
+ DCHECK(p);
+
+ gfx::Point position = GetWidgetScreenPosition(widget);
+ p->SetPoint(p->x() + position.x(), p->y() + position.y());
+}
+
void InitRCStyles() {
static const char kRCText[] =
// Make our dialogs styled like the GNOME HIG.
@@ -151,4 +159,9 @@ std::string ConvertAcceleratorsFromWindowsStyle(const std::string& label) {
return ret;
}
+bool IsScreenComposited() {
+ GdkScreen* screen = gdk_screen_get_default();
+ return gdk_screen_is_composited(screen) == TRUE;
+}
+
} // namespace gtk_util
diff --git a/chrome/common/gtk_util.h b/chrome/common/gtk_util.h
index 5e5a275..4f42380 100644
--- a/chrome/common/gtk_util.h
+++ b/chrome/common/gtk_util.h
@@ -60,6 +60,9 @@ gfx::Point GetWidgetScreenPosition(GtkWidget* widget);
// Returns the bounds of the specified widget in screen coordinates.
gfx::Rect GetWidgetScreenBounds(GtkWidget* widget);
+// Converts a point in a widget to screen coordinates.
+void ConvertWidgetPointToScreen(GtkWidget* widget, gfx::Point* p);
+
// Initialize some GTK settings so that our dialogs are consistent.
void InitRCStyles();
@@ -73,6 +76,9 @@ void CenterWidgetInHBox(GtkWidget* hbox, GtkWidget* widget, bool pack_at_end,
// accelerators. Windows uses & with && as an escape for &.)
std::string ConvertAcceleratorsFromWindowsStyle(const std::string& label);
+// Returns true if the screen is composited, false otherwise.
+bool IsScreenComposited();
+
} // namespace gtk_util
#endif // CHROME_COMMON_GTK_UTIL_H_