summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/browser.cc10
-rw-r--r--chrome/browser/browser.h6
-rw-r--r--chrome/browser/cocoa/status_bubble_mac.h2
-rw-r--r--chrome/browser/cocoa/status_bubble_mac.mm10
-rw-r--r--chrome/browser/gtk/download_shelf_gtk.cc7
-rw-r--r--chrome/browser/gtk/rounded_window.cc18
-rw-r--r--chrome/browser/gtk/rounded_window.h14
-rw-r--r--chrome/browser/gtk/status_bubble_gtk.cc140
-rw-r--r--chrome/browser/gtk/status_bubble_gtk.h35
-rw-r--r--chrome/browser/gtk/tab_contents_container_gtk.cc14
-rw-r--r--chrome/browser/status_bubble.h9
-rw-r--r--chrome/browser/tab_contents/tab_contents_delegate.h9
-rw-r--r--chrome/browser/tab_contents/tab_contents_view_gtk.cc6
-rw-r--r--chrome/browser/tab_contents/tab_contents_view_mac.mm7
-rw-r--r--chrome/browser/views/status_bubble_views.cc35
-rw-r--r--chrome/browser/views/status_bubble_views.h7
-rw-r--r--chrome/browser/views/tab_contents/tab_contents_view_gtk.cc10
-rw-r--r--chrome/browser/views/tab_contents/tab_contents_view_win.cc10
18 files changed, 275 insertions, 74 deletions
diff --git a/chrome/browser/browser.cc b/chrome/browser/browser.cc
index 7b728e3..ebca665 100644
--- a/chrome/browser/browser.cc
+++ b/chrome/browser/browser.cc
@@ -7,6 +7,7 @@
#include "app/animation.h"
#include "app/l10n_util.h"
#include "base/command_line.h"
+#include "base/gfx/point.h"
#include "base/keyboard_codes.h"
#include "base/logging.h"
#include "base/string_util.h"
@@ -2020,16 +2021,15 @@ void Browser::URLStarredChanged(TabContents* source, bool starred) {
window_->SetStarredState(starred);
}
-void Browser::ContentsMouseEvent(TabContents* source, bool motion) {
+void Browser::ContentsMouseEvent(
+ TabContents* source, const gfx::Point& location, bool motion) {
if (!GetStatusBubble())
return;
if (source == GetSelectedTabContents()) {
- if (motion) {
- GetStatusBubble()->MouseMoved();
- } else {
+ GetStatusBubble()->MouseMoved(location, !motion);
+ if (!motion)
GetStatusBubble()->SetURL(GURL(), std::wstring());
- }
}
}
diff --git a/chrome/browser/browser.h b/chrome/browser/browser.h
index 243b464..6e65c6a 100644
--- a/chrome/browser/browser.h
+++ b/chrome/browser/browser.h
@@ -35,6 +35,9 @@ class Profile;
class SkBitmap;
class StatusBubble;
class TabNavigation;
+namespace gfx {
+class Point;
+}
class Browser : public TabStripModelDelegate,
public TabStripModelObserver,
@@ -542,7 +545,8 @@ class Browser : public TabStripModelDelegate,
virtual void ToolbarSizeChanged(TabContents* source, bool is_animating);
virtual void URLStarredChanged(TabContents* source, bool starred);
virtual void UpdateTargetURL(TabContents* source, const GURL& url);
- virtual void ContentsMouseEvent(TabContents* source, bool motion);
+ virtual void ContentsMouseEvent(
+ TabContents* source, const gfx::Point& location, bool motion);
virtual void ContentsZoomChange(bool zoom_in);
virtual void TabContentsFocused(TabContents* tab_content);
virtual bool TakeFocus(bool reverse);
diff --git a/chrome/browser/cocoa/status_bubble_mac.h b/chrome/browser/cocoa/status_bubble_mac.h
index f110b1d..8d33f04 100644
--- a/chrome/browser/cocoa/status_bubble_mac.h
+++ b/chrome/browser/cocoa/status_bubble_mac.h
@@ -36,7 +36,7 @@ class StatusBubbleMac : public StatusBubble {
virtual void SetStatus(const std::wstring& status);
virtual void SetURL(const GURL& url, const std::wstring& languages);
virtual void Hide();
- virtual void MouseMoved();
+ virtual void MouseMoved(const gfx::Point& location, bool left_content);
virtual void UpdateDownloadShelfVisibility(bool visible);
// Mac-specific method: Update the size and position of the status bubble to
diff --git a/chrome/browser/cocoa/status_bubble_mac.mm b/chrome/browser/cocoa/status_bubble_mac.mm
index 9305100..55b57df 100644
--- a/chrome/browser/cocoa/status_bubble_mac.mm
+++ b/chrome/browser/cocoa/status_bubble_mac.mm
@@ -8,6 +8,7 @@
#include "app/gfx/text_elider.h"
#include "base/compiler_specific.h"
+#include "base/gfx/point.h"
#include "base/message_loop.h"
#include "base/string_util.h"
#include "base/sys_string_conversions.h"
@@ -206,10 +207,15 @@ void StatusBubbleMac::Hide() {
url_text_ = nil;
}
-void StatusBubbleMac::MouseMoved() {
+void StatusBubbleMac::MouseMoved(
+ const gfx::Point& location, bool left_content) {
+ if (left_content)
+ return;
+
if (!window_)
return;
+ // TODO(thakis): Use 'location' here instead of NSEvent.
NSPoint cursor_location = [NSEvent mouseLocation];
--cursor_location.y; // docs say the y coord starts at 1 not 0; don't ask why
@@ -330,7 +336,7 @@ void StatusBubbleMac::Create() {
Attach();
[view setCornerFlags:kRoundedTopRightCorner];
- MouseMoved();
+ MouseMoved(gfx::Point(), false);
}
void StatusBubbleMac::Attach() {
diff --git a/chrome/browser/gtk/download_shelf_gtk.cc b/chrome/browser/gtk/download_shelf_gtk.cc
index 336454f..1e13892 100644
--- a/chrome/browser/gtk/download_shelf_gtk.cc
+++ b/chrome/browser/gtk/download_shelf_gtk.cc
@@ -127,7 +127,7 @@ DownloadShelfGtk::DownloadShelfGtk(Browser* browser, GtkWidget* parent)
FALSE, FALSE, 0);
// Make sure we are at the very end.
gtk_box_reorder_child(GTK_BOX(parent), slide_widget_->widget(), 0);
- slide_widget_->Open();
+ Show();
}
DownloadShelfGtk::~DownloadShelfGtk() {
@@ -155,6 +155,7 @@ bool DownloadShelfGtk::IsClosing() const {
void DownloadShelfGtk::Show() {
slide_widget_->Open();
+ browser_->UpdateDownloadShelfVisibility(true);
}
void DownloadShelfGtk::Close() {
@@ -162,8 +163,6 @@ void DownloadShelfGtk::Close() {
// we are on top.
gdk_window_raise(shelf_.get()->window);
slide_widget_->Close();
-
- // TODO(estade): Remove. The status bubble should query its window instead.
browser_->UpdateDownloadShelfVisibility(false);
}
@@ -224,8 +223,6 @@ void DownloadShelfGtk::RemoveDownloadItem(DownloadItemGtk* download_item) {
delete download_item;
if (download_items_.empty()) {
slide_widget_->CloseWithoutAnimation();
-
- // TODO(estade): Remove. The status bubble should query its window instead.
browser_->UpdateDownloadShelfVisibility(false);
}
}
diff --git a/chrome/browser/gtk/rounded_window.cc b/chrome/browser/gtk/rounded_window.cc
index 79af804..b6174b4 100644
--- a/chrome/browser/gtk/rounded_window.cc
+++ b/chrome/browser/gtk/rounded_window.cc
@@ -184,6 +184,8 @@ void ActAsRoundedWindow(
GtkWidget* widget, const GdkColor& color, int corner_size,
int rounded_edges, int drawn_borders) {
DCHECK(widget);
+ DCHECK(!g_object_get_data(G_OBJECT(widget), kRoundedData));
+
gtk_widget_set_app_paintable(widget, TRUE);
g_signal_connect(G_OBJECT(widget), "expose-event",
G_CALLBACK(OnRoundedWindowExpose), NULL);
@@ -209,10 +211,26 @@ void StopActingAsRoundedWindow(GtkWidget* widget) {
g_signal_handlers_disconnect_by_func(widget,
reinterpret_cast<gpointer>(OnStyleSet), NULL);
+ delete static_cast<RoundedWindowData*>(
+ g_object_steal_data(G_OBJECT(widget), kRoundedData));
+
if (GTK_WIDGET_REALIZED(widget))
gdk_window_shape_combine_mask(widget->window, NULL, 0, 0);
}
+void SetRoundedWindowEdgesAndBorders(GtkWidget* widget,
+ int corner_size,
+ int rounded_edges,
+ int drawn_borders) {
+ DCHECK(widget);
+ RoundedWindowData* data = static_cast<RoundedWindowData*>(
+ g_object_get_data(G_OBJECT(widget), kRoundedData));
+ DCHECK(data);
+ data->corner_size = corner_size;
+ data->rounded_edges = rounded_edges;
+ data->drawn_borders = drawn_borders;
+}
+
void SetRoundedWindowBorderColor(GtkWidget* widget, GdkColor color) {
DCHECK(widget);
RoundedWindowData* data = static_cast<RoundedWindowData*>(
diff --git a/chrome/browser/gtk/rounded_window.h b/chrome/browser/gtk/rounded_window.h
index 46287ff..95f91d9 100644
--- a/chrome/browser/gtk/rounded_window.h
+++ b/chrome/browser/gtk/rounded_window.h
@@ -39,13 +39,21 @@ void ActAsRoundedWindow(
GtkWidget* widget, const GdkColor& color, int corner_size,
int rounded_edges, int drawn_borders);
-// Undo most of the actions of ActAsRoundedWindow.
+// Undoes most of the actions of ActAsRoundedWindow().
void StopActingAsRoundedWindow(GtkWidget* widget);
-// Sets the color of the border on a widget that was returned from
-// ActAsRoundedWindow().
+// Sets edge and border properties on a widget that has already been configured
+// with ActAsRoundedWindow().
+void SetRoundedWindowEdgesAndBorders(GtkWidget* widget,
+ int corner_size,
+ int rounded_edges,
+ int drawn_borders);
+
+// Sets the color of the border on a widget that has already been configured
+// with ActAsRoundedWindow().
void SetRoundedWindowBorderColor(GtkWidget* widget, GdkColor color);
+
} // namespace gtk_util
#endif // CHROME_BROWSER_GTK_ROUNDED_WINDOW_H_
diff --git a/chrome/browser/gtk/status_bubble_gtk.cc b/chrome/browser/gtk/status_bubble_gtk.cc
index 5ee330d..a57c05b 100644
--- a/chrome/browser/gtk/status_bubble_gtk.cc
+++ b/chrome/browser/gtk/status_bubble_gtk.cc
@@ -30,11 +30,20 @@ const int kCornerSize = 3;
// Milliseconds before we hide the status bubble widget when you mouseout.
const int kHideDelay = 250;
+// How close the mouse can get to the infobubble before it starts sliding
+// off-screen.
+const int kMousePadding = 20;
+
} // namespace
StatusBubbleGtk::StatusBubbleGtk(Profile* profile)
: theme_provider_(GtkThemeProvider::GetFrom(profile)),
- timer_factory_(this) {
+ padding_(NULL),
+ label_(NULL),
+ timer_factory_(this),
+ flip_horizontally_(false),
+ y_offset_(0),
+ download_shelf_is_visible_(false) {
InitWidgets();
theme_provider_->InitThemesFor(this);
@@ -114,13 +123,77 @@ void StatusBubbleGtk::HideInASecond() {
kHideDelay);
}
-void StatusBubbleGtk::MouseMoved() {
- // We can't do that fancy sliding behaviour where the status bubble slides
- // out of the window because the window manager gets in the way. So totally
- // ignore this message for now.
- //
- // TODO(erg): At least get some sliding behaviour so that it slides out of
- // the way to hide the status bubble on mouseover.
+void StatusBubbleGtk::MouseMoved(
+ const gfx::Point& location, bool left_content) {
+ if (!GTK_WIDGET_REALIZED(container_.get()))
+ return;
+
+ GtkWidget* parent = gtk_widget_get_parent(container_.get());
+ if (!parent || !GTK_WIDGET_REALIZED(parent))
+ return;
+
+ int old_y_offset = y_offset_;
+ bool old_flip_horizontally = flip_horizontally_;
+
+ if (left_content) {
+ SetFlipHorizontally(false);
+ y_offset_ = 0;
+ } else {
+ GtkWidget* toplevel = gtk_widget_get_toplevel(container_.get());
+ if (!toplevel || !GTK_WIDGET_REALIZED(toplevel))
+ return;
+
+ bool ltr = (l10n_util::GetTextDirection() == l10n_util::LEFT_TO_RIGHT);
+
+ GtkRequisition requisition;
+ gtk_widget_size_request(container_.get(), &requisition);
+
+ // Get our base position (that is, not including the current offset)
+ // relative to the origin of the root window.
+ gint toplevel_x = 0, toplevel_y = 0;
+ gdk_window_get_position(toplevel->window, &toplevel_x, &toplevel_y);
+ gfx::Rect parent_rect =
+ gtk_util::GetWidgetRectRelativeToToplevel(parent);
+ gfx::Rect bubble_rect(
+ toplevel_x + parent_rect.x() +
+ (ltr ? 0 : parent->allocation.width - requisition.width),
+ toplevel_y + parent_rect.y() +
+ parent->allocation.height - requisition.height,
+ requisition.width,
+ requisition.height);
+
+ int left_threshold =
+ bubble_rect.x() - bubble_rect.height() - kMousePadding;
+ int right_threshold =
+ bubble_rect.right() + bubble_rect.height() + kMousePadding;
+ int top_threshold = bubble_rect.y() - kMousePadding;
+
+ if (((ltr && location.x() < right_threshold) ||
+ (!ltr && location.x() > left_threshold)) &&
+ location.y() > top_threshold) {
+ if (download_shelf_is_visible_) {
+ SetFlipHorizontally(true);
+ y_offset_ = 0;
+ } else {
+ SetFlipHorizontally(false);
+ int distance = std::max(ltr ?
+ location.x() - right_threshold :
+ left_threshold - location.x(),
+ top_threshold - location.y());
+ y_offset_ = std::min(-1 * distance, requisition.height);
+ }
+ } else {
+ SetFlipHorizontally(false);
+ y_offset_ = 0;
+ }
+ }
+
+ if (y_offset_ != old_y_offset || flip_horizontally_ != old_flip_horizontally)
+ gtk_widget_queue_resize_no_redraw(parent);
+}
+
+void StatusBubbleGtk::UpdateDownloadShelfVisibility(bool visible) {
+ download_shelf_is_visible_ = visible;
}
void StatusBubbleGtk::Observe(NotificationType type,
@@ -132,14 +205,16 @@ void StatusBubbleGtk::Observe(NotificationType type,
}
void StatusBubbleGtk::InitWidgets() {
+ bool ltr = (l10n_util::GetTextDirection() == l10n_util::LEFT_TO_RIGHT);
+
label_ = gtk_label_new(NULL);
- GtkWidget* padding = gtk_alignment_new(0, 0, 1, 1);
- gtk_alignment_set_padding(GTK_ALIGNMENT(padding),
+ padding_ = gtk_alignment_new(0, 0, 1, 1);
+ gtk_alignment_set_padding(GTK_ALIGNMENT(padding_),
kInternalTopBottomPadding, kInternalTopBottomPadding,
- kInternalLeftRightPadding,
- kInternalLeftRightPadding + kCornerSize);
- gtk_container_add(GTK_CONTAINER(padding), label_);
+ kInternalLeftRightPadding + (ltr ? 0 : kCornerSize),
+ kInternalLeftRightPadding + (ltr ? kCornerSize : 0));
+ gtk_container_add(GTK_CONTAINER(padding_), label_);
container_.Own(gtk_event_box_new());
gtk_util::ActAsRoundedWindow(
@@ -147,7 +222,14 @@ void StatusBubbleGtk::InitWidgets() {
gtk_util::ROUNDED_TOP_RIGHT,
gtk_util::BORDER_TOP | gtk_util::BORDER_RIGHT);
gtk_widget_set_name(container_.get(), "status-bubble");
- gtk_container_add(GTK_CONTAINER(container_.get()), padding);
+ gtk_container_add(GTK_CONTAINER(container_.get()), padding_);
+
+ // We need to listen for mouse motion events, since a fast-moving pointer may
+ // enter our window without us getting any motion events on the browser near
+ // enough for us to run away.
+ gtk_widget_add_events(container_.get(), GDK_POINTER_MOTION_MASK);
+ g_signal_connect(container_.get(), "motion-notify-event",
+ G_CALLBACK(HandleMotionNotifyThunk), this);
UserChangedTheme();
}
@@ -172,3 +254,33 @@ void StatusBubbleGtk::UserChangedTheme() {
gtk_util::SetRoundedWindowBorderColor(container_.get(),
theme_provider_->GetBorderColor());
}
+
+void StatusBubbleGtk::SetFlipHorizontally(bool flip_horizontally) {
+ if (flip_horizontally == flip_horizontally_)
+ return;
+
+ flip_horizontally_ = flip_horizontally;
+
+ bool ltr = (l10n_util::GetTextDirection() == l10n_util::LEFT_TO_RIGHT);
+ bool on_left = (ltr && !flip_horizontally) || (!ltr && flip_horizontally);
+
+ gtk_alignment_set_padding(GTK_ALIGNMENT(padding_),
+ kInternalTopBottomPadding, kInternalTopBottomPadding,
+ kInternalLeftRightPadding + (on_left ? 0 : kCornerSize),
+ kInternalLeftRightPadding + (on_left ? kCornerSize : 0));
+ // The rounded window code flips these arguments if we're RTL.
+ gtk_util::SetRoundedWindowEdgesAndBorders(
+ container_.get(),
+ kCornerSize,
+ flip_horizontally ?
+ gtk_util::ROUNDED_TOP_LEFT :
+ gtk_util::ROUNDED_TOP_RIGHT,
+ gtk_util::BORDER_TOP |
+ (flip_horizontally ? gtk_util::BORDER_LEFT : gtk_util::BORDER_RIGHT));
+ gtk_widget_queue_draw(container_.get());
+}
+
+gboolean StatusBubbleGtk::HandleMotionNotify(GdkEventMotion* event) {
+ MouseMoved(gfx::Point(event->x_root, event->y_root), false);
+ return FALSE;
+}
diff --git a/chrome/browser/gtk/status_bubble_gtk.h b/chrome/browser/gtk/status_bubble_gtk.h
index 87b43d3..9784668 100644
--- a/chrome/browser/gtk/status_bubble_gtk.h
+++ b/chrome/browser/gtk/status_bubble_gtk.h
@@ -9,6 +9,7 @@
#include <string>
+#include "base/gfx/point.h"
#include "base/scoped_ptr.h"
#include "base/task.h"
#include "chrome/browser/status_bubble.h"
@@ -30,16 +31,19 @@ class StatusBubbleGtk : public StatusBubble,
explicit StatusBubbleGtk(Profile* profile);
virtual ~StatusBubbleGtk();
+ bool flip_horizontally() const { return flip_horizontally_; }
+ int y_offset() const { return y_offset_; }
+
// StatusBubble implementation.
virtual void SetStatus(const std::wstring& status);
virtual void SetURL(const GURL& url, const std::wstring& languages);
virtual void Hide();
- virtual void MouseMoved();
+ virtual void MouseMoved(const gfx::Point& location, bool left_content);
// Called when the download shelf becomes visible or invisible.
// This is used by to ensure that the status bubble does not obscure
// the download shelf, when it is visible.
- virtual void UpdateDownloadShelfVisibility(bool visible) { }
+ virtual void UpdateDownloadShelfVisibility(bool visible);
// Overridden from NotificationObserver:
void Observe(NotificationType type,
@@ -69,6 +73,19 @@ class StatusBubbleGtk : public StatusBubble,
// Notification from the window that we should retheme ourself.
void UserChangedTheme();
+ // Sets whether the bubble should be flipped horizontally and displayed on the
+ // opposite side of the tab contents. Reshapes the container and queues a
+ // redraw if necessary.
+ void SetFlipHorizontally(bool flip_horizontally);
+
+ static gboolean HandleMotionNotifyThunk(GtkWidget* widget,
+ GdkEventMotion* event,
+ gpointer user_data) {
+ return reinterpret_cast<StatusBubbleGtk*>(user_data)->
+ HandleMotionNotify(event);
+ }
+ gboolean HandleMotionNotify(GdkEventMotion* event);
+
NotificationRegistrar registrar_;
// Provides colors.
@@ -77,6 +94,9 @@ class StatusBubbleGtk : public StatusBubble,
// The toplevel event box.
OwnedWidgetGtk container_;
+ // The GtkAlignment holding |label_|.
+ GtkWidget* padding_;
+
// The GtkLabel holding the text.
GtkWidget* label_;
@@ -88,6 +108,17 @@ class StatusBubbleGtk : public StatusBubble,
// A timer that hides our window after a delay.
ScopedRunnableMethodFactory<StatusBubbleGtk> timer_factory_;
+
+ // Should the bubble be flipped horizontally (e.g. displayed on the right for
+ // an LTR language)? We move the bubble to the other side of the tab contents
+ // rather than sliding it down when the download shelf is visible.
+ bool flip_horizontally_;
+
+ // Vertical offset used to hide the status bubble as the pointer nears it.
+ int y_offset_;
+
+ // If the download shelf is visible, do not obscure it.
+ bool download_shelf_is_visible_;
};
#endif // CHROME_BROWSER_GTK_STATUS_BUBBLE_GTK_H_
diff --git a/chrome/browser/gtk/tab_contents_container_gtk.cc b/chrome/browser/gtk/tab_contents_container_gtk.cc
index 9425194..a4fe973 100644
--- a/chrome/browser/gtk/tab_contents_container_gtk.cc
+++ b/chrome/browser/gtk/tab_contents_container_gtk.cc
@@ -188,26 +188,28 @@ void TabContentsContainerGtk::OnFixedSizeAllocate(
void TabContentsContainerGtk::OnSetFloatingPosition(
GtkFloatingContainer* floating_container, GtkAllocation* allocation,
TabContentsContainerGtk* tab_contents_container) {
- GtkWidget* status = tab_contents_container->status_bubble_->widget();
+ StatusBubbleGtk* status = tab_contents_container->status_bubble_;
// Look at the size request of the status bubble and tell the
// GtkFloatingContainer where we want it positioned.
GtkRequisition requisition;
- gtk_widget_size_request(status, &requisition);
+ gtk_widget_size_request(status->widget(), &requisition);
+
+ bool ltr = (l10n_util::GetTextDirection() == l10n_util::LEFT_TO_RIGHT);
GValue value = { 0, };
g_value_init(&value, G_TYPE_INT);
- if (l10n_util::GetTextDirection() == l10n_util::LEFT_TO_RIGHT)
+ if (ltr ^ status->flip_horizontally()) // Is it on the left?
g_value_set_int(&value, 0);
else
g_value_set_int(&value, allocation->width - requisition.width);
gtk_container_child_set_property(GTK_CONTAINER(floating_container),
- status, "x", &value);
+ status->widget(), "x", &value);
int child_y = std::max(
allocation->y + allocation->height - requisition.height, 0);
- g_value_set_int(&value, child_y);
+ g_value_set_int(&value, child_y + status->y_offset());
gtk_container_child_set_property(GTK_CONTAINER(floating_container),
- status, "y", &value);
+ status->widget(), "y", &value);
g_value_unset(&value);
}
diff --git a/chrome/browser/status_bubble.h b/chrome/browser/status_bubble.h
index 9203b80..81379d0 100644
--- a/chrome/browser/status_bubble.h
+++ b/chrome/browser/status_bubble.h
@@ -8,6 +8,9 @@
#include <string>
class GURL;
+namespace gfx {
+class Point;
+}
////////////////////////////////////////////////////////////////////////////////
// StatusBubble interface
@@ -37,8 +40,10 @@ class StatusBubble {
// Called when the user's mouse has moved over web content. This is used to
// determine when the status area should move out of the way of the user's
// mouse. This may be windows specific pain due to the way messages are
- // processed for child HWNDs.
- virtual void MouseMoved() = 0;
+ // processed for child HWNDs. |position| is the absolute position of the
+ // pointer, and |left_content| is true if the mouse just left the content
+ // area.
+ virtual void MouseMoved(const gfx::Point& position, bool left_content) = 0;
// Called when the download shelf becomes visible or invisible.
// This is used by to ensure that the status bubble does not obscure
diff --git a/chrome/browser/tab_contents/tab_contents_delegate.h b/chrome/browser/tab_contents/tab_contents_delegate.h
index f5fdfcf..b4d3009 100644
--- a/chrome/browser/tab_contents/tab_contents_delegate.h
+++ b/chrome/browser/tab_contents/tab_contents_delegate.h
@@ -94,11 +94,14 @@ class TabContentsDelegate {
// Notification that the starredness of the current URL changed.
virtual void URLStarredChanged(TabContents* source, bool starred) = 0;
- // Notification that the target URL has changed
+ // Notification that the target URL has changed.
virtual void UpdateTargetURL(TabContents* source, const GURL& url) = 0;
- // Notification that there was a mouse event
- virtual void ContentsMouseEvent(TabContents* source, bool motion) { }
+ // Notification that there was a mouse event, along with the absolute
+ // coordinates of the mouse pointer and whether it was a normal motion event
+ // (otherwise, the pointer left the contents area).
+ virtual void ContentsMouseEvent(
+ TabContents* source, const gfx::Point& location, bool motion) { }
// Request the delegate to change the zoom level of the current tab.
virtual void ContentsZoomChange(bool zoom_in) { }
diff --git a/chrome/browser/tab_contents/tab_contents_view_gtk.cc b/chrome/browser/tab_contents/tab_contents_view_gtk.cc
index 332c7cd..61c685e 100644
--- a/chrome/browser/tab_contents/tab_contents_view_gtk.cc
+++ b/chrome/browser/tab_contents/tab_contents_view_gtk.cc
@@ -69,7 +69,8 @@ gboolean OnFocus(GtkWidget* widget, GtkDirectionType focus,
gboolean OnLeaveNotify(GtkWidget* widget, GdkEventCrossing* event,
TabContents* tab_contents) {
if (tab_contents->delegate())
- tab_contents->delegate()->ContentsMouseEvent(tab_contents, false);
+ tab_contents->delegate()->ContentsMouseEvent(
+ tab_contents, gfx::Point(event->x_root, event->y_root), false);
return FALSE;
}
@@ -77,7 +78,8 @@ gboolean OnLeaveNotify(GtkWidget* widget, GdkEventCrossing* event,
gboolean OnMouseMove(GtkWidget* widget, GdkEventMotion* event,
TabContents* tab_contents) {
if (tab_contents->delegate())
- tab_contents->delegate()->ContentsMouseEvent(tab_contents, true);
+ tab_contents->delegate()->ContentsMouseEvent(
+ tab_contents, gfx::Point(event->x_root, event->y_root), true);
return FALSE;
}
diff --git a/chrome/browser/tab_contents/tab_contents_view_mac.mm b/chrome/browser/tab_contents/tab_contents_view_mac.mm
index 9a06d66..60bc43a 100644
--- a/chrome/browser/tab_contents/tab_contents_view_mac.mm
+++ b/chrome/browser/tab_contents/tab_contents_view_mac.mm
@@ -406,10 +406,13 @@ void TabContentsViewMac::Observe(NotificationType type,
- (void)mouseEvent:(NSEvent *)theEvent {
TabContents* tabContents = [self tabContents];
if (tabContents->delegate()) {
+ NSPoint location = [NSEvent mouseLocation];
if ([theEvent type] == NSMouseMoved)
- tabContents->delegate()->ContentsMouseEvent(tabContents, true);
+ tabContents->delegate()->ContentsMouseEvent(
+ tabContents, gfx::Point(location.x, location.y), true);
if ([theEvent type] == NSMouseExited)
- tabContents->delegate()->ContentsMouseEvent(tabContents, false);
+ tabContents->delegate()->ContentsMouseEvent(
+ tabContents, gfx::Point(location.x, location.y), false);
}
}
diff --git a/chrome/browser/views/status_bubble_views.cc b/chrome/browser/views/status_bubble_views.cc
index 9642294..fbf8153 100644
--- a/chrome/browser/views/status_bubble_views.cc
+++ b/chrome/browser/views/status_bubble_views.cc
@@ -11,6 +11,7 @@
#include "app/l10n_util.h"
#include "app/animation.h"
#include "app/resource_bundle.h"
+#include "base/gfx/point.h"
#include "base/message_loop.h"
#include "base/string_util.h"
#include "chrome/browser/browser_theme_provider.h"
@@ -572,14 +573,18 @@ void StatusBubbleViews::Hide() {
view_->Hide();
}
-void StatusBubbleViews::MouseMoved() {
+void StatusBubbleViews::MouseMoved(const gfx::Point& location,
+ bool left_content) {
+ if (left_content)
+ return;
+
if (view_) {
view_->ResetTimer();
if (view_->GetState() != StatusView::BUBBLE_HIDDEN &&
view_->GetState() != StatusView::BUBBLE_HIDING_FADE &&
view_->GetState() != StatusView::BUBBLE_HIDING_TIMER) {
- AvoidMouse();
+ AvoidMouse(location);
}
}
}
@@ -588,42 +593,40 @@ void StatusBubbleViews::UpdateDownloadShelfVisibility(bool visible) {
download_shelf_is_visible_ = visible;
}
-void StatusBubbleViews::AvoidMouse() {
+void StatusBubbleViews::AvoidMouse(const gfx::Point& location) {
// Get the position of the frame.
gfx::Point top_left;
views::RootView* root = frame_->GetRootView();
views::View::ConvertPointToScreen(root, &top_left);
int window_width = root->GetLocalBounds(true).width(); // border included.
- // Our status bubble is located in screen coordinates, so we should get
- // those rather than attempting to reverse decode the web contents
- // coordinates.
- gfx::Point cursor_location = views::Screen::GetCursorScreenPoint();
-
// Get the cursor position relative to the popup.
+ gfx::Point relative_location = location;
if (view_->UILayoutIsRightToLeft()) {
int top_right_x = top_left.x() + window_width;
- cursor_location.set_x(top_right_x - cursor_location.x());
+ relative_location.set_x(top_right_x - relative_location.x());
} else {
- cursor_location.set_x(cursor_location.x() - (top_left.x() + position_.x()));
+ relative_location.set_x(
+ relative_location.x() - (top_left.x() + position_.x()));
}
- cursor_location.set_y(cursor_location.y() - (top_left.y() + position_.y()));
+ relative_location.set_y(
+ relative_location.y() - (top_left.y() + position_.y()));
// If the mouse is in a position where we think it would move the
// status bubble, figure out where and how the bubble should be moved.
- if (cursor_location.y() > -kMousePadding &&
- cursor_location.x() < size_.width() + kMousePadding) {
- int offset = kMousePadding + cursor_location.y();
+ if (relative_location.y() > -kMousePadding &&
+ relative_location.x() < size_.width() + kMousePadding) {
+ int offset = kMousePadding + relative_location.y();
// Make the movement non-linear.
offset = offset * offset / kMousePadding;
// When the mouse is entering from the right, we want the offset to be
// scaled by how horizontally far away the cursor is from the bubble.
- if (cursor_location.x() > size_.width()) {
+ if (relative_location.x() > size_.width()) {
offset = static_cast<int>(static_cast<float>(offset) * (
static_cast<float>(kMousePadding -
- (cursor_location.x() - size_.width())) /
+ (relative_location.x() - size_.width())) /
static_cast<float>(kMousePadding)));
}
diff --git a/chrome/browser/views/status_bubble_views.h b/chrome/browser/views/status_bubble_views.h
index 06bf6bd..78d3265 100644
--- a/chrome/browser/views/status_bubble_views.h
+++ b/chrome/browser/views/status_bubble_views.h
@@ -11,6 +11,9 @@
#include "chrome/browser/status_bubble.h"
class GURL;
+namespace gfx {
+class Point;
+}
namespace views {
class Widget;
}
@@ -44,7 +47,7 @@ class StatusBubbleViews : public StatusBubble {
virtual void SetStatus(const std::wstring& status);
virtual void SetURL(const GURL& url, const std::wstring& languages);
virtual void Hide();
- virtual void MouseMoved();
+ virtual void MouseMoved(const gfx::Point& location, bool left_content);
virtual void UpdateDownloadShelfVisibility(bool visible);
private:
@@ -55,7 +58,7 @@ class StatusBubbleViews : public StatusBubble {
// Attempt to move the status bubble out of the way of the cursor, allowing
// users to see links in the region normally occupied by the status bubble.
- void AvoidMouse();
+ void AvoidMouse(const gfx::Point& location);
// Returns true if the frame_ is visible and not minimized.
bool IsFrameVisible();
diff --git a/chrome/browser/views/tab_contents/tab_contents_view_gtk.cc b/chrome/browser/views/tab_contents/tab_contents_view_gtk.cc
index fce6c9c..7db5ad4 100644
--- a/chrome/browser/views/tab_contents/tab_contents_view_gtk.cc
+++ b/chrome/browser/views/tab_contents/tab_contents_view_gtk.cc
@@ -26,8 +26,9 @@
#include "chrome/browser/views/blocked_popup_container_view_views.h"
#include "chrome/browser/views/sad_tab_view.h"
#include "chrome/browser/views/tab_contents/render_view_context_menu_win.h"
-#include "views/focus/view_storage.h"
#include "views/controls/native/native_view_host.h"
+#include "views/focus/view_storage.h"
+#include "views/screen.h"
#include "views/widget/root_view.h"
using WebKit::WebDragOperation;
@@ -62,7 +63,8 @@ gboolean OnFocus(GtkWidget* widget, GtkDirectionType focus,
gboolean OnLeaveNotify2(GtkWidget* widget, GdkEventCrossing* event,
TabContents* tab_contents) {
if (tab_contents->delegate())
- tab_contents->delegate()->ContentsMouseEvent(tab_contents, false);
+ tab_contents->delegate()->ContentsMouseEvent(
+ tab_contents, views::Screen::GetCursorScreenPoint(), false);
return FALSE;
}
@@ -70,7 +72,8 @@ gboolean OnLeaveNotify2(GtkWidget* widget, GdkEventCrossing* event,
gboolean OnMouseMove(GtkWidget* widget, GdkEventMotion* event,
TabContents* tab_contents) {
if (tab_contents->delegate())
- tab_contents->delegate()->ContentsMouseEvent(tab_contents, true);
+ tab_contents->delegate()->ContentsMouseEvent(
+ tab_contents, views::Screen::GetCursorScreenPoint(), true);
return FALSE;
}
@@ -423,4 +426,3 @@ void TabContentsViewGtk::SetFloatingPosition(const gfx::Size& size) {
PositionChild(widget, child_x, 0, requisition.width, requisition.height);
}
}
-
diff --git a/chrome/browser/views/tab_contents/tab_contents_view_win.cc b/chrome/browser/views/tab_contents/tab_contents_view_win.cc
index a0a0beb..9c79650 100644
--- a/chrome/browser/views/tab_contents/tab_contents_view_win.cc
+++ b/chrome/browser/views/tab_contents/tab_contents_view_win.cc
@@ -31,6 +31,7 @@
#include "chrome/common/url_constants.h"
#include "net/base/net_util.h"
#include "views/focus/view_storage.h"
+#include "views/screen.h"
#include "views/widget/root_view.h"
#include "webkit/glue/webdropdata.h"
@@ -474,7 +475,8 @@ void TabContentsViewWin::OnMouseLeave() {
// Let our delegate know that the mouse moved (useful for resetting status
// bubble state).
if (tab_contents()->delegate())
- tab_contents()->delegate()->ContentsMouseEvent(tab_contents(), false);
+ tab_contents()->delegate()->ContentsMouseEvent(
+ tab_contents(), views::Screen::GetCursorScreenPoint(), false);
SetMsgHandled(FALSE);
}
@@ -496,9 +498,9 @@ LRESULT TabContentsViewWin::OnMouseRange(UINT msg,
case WM_MOUSEMOVE:
// Let our delegate know that the mouse moved (useful for resetting status
// bubble state).
- if (tab_contents()->delegate()) {
- tab_contents()->delegate()->ContentsMouseEvent(tab_contents(), true);
- }
+ if (tab_contents()->delegate())
+ tab_contents()->delegate()->ContentsMouseEvent(
+ tab_contents(), views::Screen::GetCursorScreenPoint(), true);
break;
default:
break;