Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(214)

Side by Side Diff: chrome/browser/gtk/status_bubble_gtk.cc

Issue 6103005: [gtk] fix a corner case where the status bubble was in the way of the cursor. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/gtk/status_bubble_gtk.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/gtk/status_bubble_gtk.h" 5 #include "chrome/browser/gtk/status_bubble_gtk.h"
6 6
7 #include <gtk/gtk.h> 7 #include <gtk/gtk.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 10
(...skipping 27 matching lines...) Expand all
38 } // namespace 38 } // namespace
39 39
40 StatusBubbleGtk::StatusBubbleGtk(Profile* profile) 40 StatusBubbleGtk::StatusBubbleGtk(Profile* profile)
41 : theme_provider_(GtkThemeProvider::GetFrom(profile)), 41 : theme_provider_(GtkThemeProvider::GetFrom(profile)),
42 padding_(NULL), 42 padding_(NULL),
43 label_(NULL), 43 label_(NULL),
44 flip_horizontally_(false), 44 flip_horizontally_(false),
45 y_offset_(0), 45 y_offset_(0),
46 download_shelf_is_visible_(false), 46 download_shelf_is_visible_(false),
47 last_mouse_location_(0, 0), 47 last_mouse_location_(0, 0),
48 last_mouse_left_content_(false) { 48 last_mouse_left_content_(false),
49 ignore_next_left_content_(false) {
49 InitWidgets(); 50 InitWidgets();
50 51
51 theme_provider_->InitThemesFor(this); 52 theme_provider_->InitThemesFor(this);
52 registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED, 53 registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
53 NotificationService::AllSources()); 54 NotificationService::AllSources());
54 } 55 }
55 56
56 StatusBubbleGtk::~StatusBubbleGtk() { 57 StatusBubbleGtk::~StatusBubbleGtk() {
57 container_.Destroy(); 58 container_.Destroy();
58 } 59 }
59 60
60 void StatusBubbleGtk::SetStatus(const string16& status_text_wide) { 61 void StatusBubbleGtk::SetStatus(const string16& status_text_wide) {
61 std::string status_text = UTF16ToUTF8(status_text_wide); 62 std::string status_text = UTF16ToUTF8(status_text_wide);
62 if (status_text_ == status_text) 63 if (status_text_ == status_text)
63 return; 64 return;
64 65
65 status_text_ = status_text; 66 status_text_ = status_text;
66 if (!status_text_.empty()) { 67 if (!status_text_.empty())
67 SetStatusTextTo(status_text_); 68 SetStatusTextTo(status_text_);
68 } else if (!url_text_.empty()) { 69 else if (!url_text_.empty())
69 SetStatusTextTo(url_text_); 70 SetStatusTextTo(url_text_);
70 } else { 71 else
71 SetStatusTextTo(std::string()); 72 SetStatusTextTo(std::string());
72 }
73 } 73 }
74 74
75 void StatusBubbleGtk::SetURL(const GURL& url, const string16& languages) { 75 void StatusBubbleGtk::SetURL(const GURL& url, const string16& languages) {
76 url_ = url; 76 url_ = url;
77 languages_ = languages; 77 languages_ = languages;
78 78
79 // If we want to clear a displayed URL but there is a status still to 79 // If we want to clear a displayed URL but there is a status still to
80 // display, display that status instead. 80 // display, display that status instead.
81 if (url.is_empty() && !status_text_.empty()) { 81 if (url.is_empty() && !status_text_.empty()) {
82 url_text_ = std::string(); 82 url_text_ = std::string();
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
148 // ourselves away from the pointer now. 148 // ourselves away from the pointer now.
149 gtk_widget_show_all(padding_); 149 gtk_widget_show_all(padding_);
150 MouseMoved(last_mouse_location_, false); 150 MouseMoved(last_mouse_location_, false);
151 } 151 }
152 Show(); 152 Show();
153 } 153 }
154 } 154 }
155 155
156 void StatusBubbleGtk::MouseMoved( 156 void StatusBubbleGtk::MouseMoved(
157 const gfx::Point& location, bool left_content) { 157 const gfx::Point& location, bool left_content) {
158 if (left_content && ignore_next_left_content_) {
159 ignore_next_left_content_ = false;
160 return;
161 }
162
158 last_mouse_location_ = location; 163 last_mouse_location_ = location;
159 last_mouse_left_content_ = left_content; 164 last_mouse_left_content_ = left_content;
160 165
161 if (!GTK_WIDGET_REALIZED(container_.get())) 166 if (!GTK_WIDGET_REALIZED(container_.get()))
162 return; 167 return;
163 168
164 GtkWidget* parent = gtk_widget_get_parent(container_.get()); 169 GtkWidget* parent = gtk_widget_get_parent(container_.get());
165 if (!parent || !GTK_WIDGET_REALIZED(parent)) 170 if (!parent || !GTK_WIDGET_REALIZED(parent))
166 return; 171 return;
167 172
(...skipping 14 matching lines...) Expand all
182 gtk_widget_size_request(container_.get(), &requisition); 187 gtk_widget_size_request(container_.get(), &requisition);
183 188
184 // Get our base position (that is, not including the current offset) 189 // Get our base position (that is, not including the current offset)
185 // relative to the origin of the root window. 190 // relative to the origin of the root window.
186 gint toplevel_x = 0, toplevel_y = 0; 191 gint toplevel_x = 0, toplevel_y = 0;
187 gdk_window_get_position(toplevel->window, &toplevel_x, &toplevel_y); 192 gdk_window_get_position(toplevel->window, &toplevel_x, &toplevel_y);
188 gfx::Rect parent_rect = 193 gfx::Rect parent_rect =
189 gtk_util::GetWidgetRectRelativeToToplevel(parent); 194 gtk_util::GetWidgetRectRelativeToToplevel(parent);
190 gfx::Rect bubble_rect( 195 gfx::Rect bubble_rect(
191 toplevel_x + parent_rect.x() + 196 toplevel_x + parent_rect.x() +
192 (ltr ? 0 : parent->allocation.width - requisition.width), 197 (ltr ? 0 : parent->allocation.width - requisition.width),
193 toplevel_y + parent_rect.y() + 198 toplevel_y + parent_rect.y() +
194 parent->allocation.height - requisition.height, 199 parent->allocation.height - requisition.height,
195 requisition.width, 200 requisition.width,
196 requisition.height); 201 requisition.height);
197 202
198 int left_threshold = 203 int left_threshold =
199 bubble_rect.x() - bubble_rect.height() - kMousePadding; 204 bubble_rect.x() - bubble_rect.height() - kMousePadding;
200 int right_threshold = 205 int right_threshold =
201 bubble_rect.right() + bubble_rect.height() + kMousePadding; 206 bubble_rect.right() + bubble_rect.height() + kMousePadding;
202 int top_threshold = bubble_rect.y() - kMousePadding; 207 int top_threshold = bubble_rect.y() - kMousePadding;
203 208
204 if (((ltr && location.x() < right_threshold) || 209 if (((ltr && location.x() < right_threshold) ||
205 (!ltr && location.x() > left_threshold)) && 210 (!ltr && location.x() > left_threshold)) &&
206 location.y() > top_threshold) { 211 location.y() > top_threshold) {
207 if (download_shelf_is_visible_) { 212 if (download_shelf_is_visible_) {
208 SetFlipHorizontally(true); 213 SetFlipHorizontally(true);
209 y_offset_ = 0; 214 y_offset_ = 0;
210 } else { 215 } else {
211 SetFlipHorizontally(false); 216 SetFlipHorizontally(false);
212 int distance = std::max(ltr ? 217 int distance = std::max(ltr ?
213 location.x() - right_threshold : 218 location.x() - right_threshold :
214 left_threshold - location.x(), 219 left_threshold - location.x(),
215 top_threshold - location.y()); 220 top_threshold - location.y());
216 y_offset_ = std::min(-1 * distance, requisition.height); 221 y_offset_ = std::min(-1 * distance, requisition.height);
217 } 222 }
218 } else { 223 } else {
219 SetFlipHorizontally(false); 224 SetFlipHorizontally(false);
220 y_offset_ = 0; 225 y_offset_ = 0;
221 } 226 }
222 } 227 }
223 228
224 if (y_offset_ != old_y_offset || flip_horizontally_ != old_flip_horizontally) 229 if (y_offset_ != old_y_offset || flip_horizontally_ != old_flip_horizontally)
(...skipping 28 matching lines...) Expand all
253 gtk_util::ActAsRoundedWindow( 258 gtk_util::ActAsRoundedWindow(
254 container_.get(), gtk_util::kGdkWhite, kCornerSize, 259 container_.get(), gtk_util::kGdkWhite, kCornerSize,
255 gtk_util::ROUNDED_TOP_RIGHT, 260 gtk_util::ROUNDED_TOP_RIGHT,
256 gtk_util::BORDER_TOP | gtk_util::BORDER_RIGHT); 261 gtk_util::BORDER_TOP | gtk_util::BORDER_RIGHT);
257 gtk_widget_set_name(container_.get(), "status-bubble"); 262 gtk_widget_set_name(container_.get(), "status-bubble");
258 gtk_container_add(GTK_CONTAINER(container_.get()), padding_); 263 gtk_container_add(GTK_CONTAINER(container_.get()), padding_);
259 264
260 // We need to listen for mouse motion events, since a fast-moving pointer may 265 // We need to listen for mouse motion events, since a fast-moving pointer may
261 // enter our window without us getting any motion events on the browser near 266 // enter our window without us getting any motion events on the browser near
262 // enough for us to run away. 267 // enough for us to run away.
263 gtk_widget_add_events(container_.get(), GDK_POINTER_MOTION_MASK); 268 gtk_widget_add_events(container_.get(), GDK_POINTER_MOTION_MASK |
269 GDK_ENTER_NOTIFY_MASK);
264 g_signal_connect(container_.get(), "motion-notify-event", 270 g_signal_connect(container_.get(), "motion-notify-event",
265 G_CALLBACK(HandleMotionNotifyThunk), this); 271 G_CALLBACK(HandleMotionNotifyThunk), this);
272 g_signal_connect(container_.get(), "enter-notify-event",
273 G_CALLBACK(HandleEnterNotifyThunk), this);
266 274
267 UserChangedTheme(); 275 UserChangedTheme();
268 } 276 }
269 277
270 void StatusBubbleGtk::UserChangedTheme() { 278 void StatusBubbleGtk::UserChangedTheme() {
271 if (theme_provider_->UseGtkTheme()) { 279 if (theme_provider_->UseGtkTheme()) {
272 gtk_widget_modify_fg(label_, GTK_STATE_NORMAL, NULL); 280 gtk_widget_modify_fg(label_, GTK_STATE_NORMAL, NULL);
273 gtk_widget_modify_bg(container_.get(), GTK_STATE_NORMAL, NULL); 281 gtk_widget_modify_bg(container_.get(), GTK_STATE_NORMAL, NULL);
274 } else { 282 } else {
275 // TODO(erg): This is the closest to "text that will look good on a 283 // TODO(erg): This is the closest to "text that will look good on a
(...skipping 23 matching lines...) Expand all
299 307
300 gtk_alignment_set_padding(GTK_ALIGNMENT(padding_), 308 gtk_alignment_set_padding(GTK_ALIGNMENT(padding_),
301 kInternalTopBottomPadding, kInternalTopBottomPadding, 309 kInternalTopBottomPadding, kInternalTopBottomPadding,
302 kInternalLeftRightPadding + (on_left ? 0 : kCornerSize), 310 kInternalLeftRightPadding + (on_left ? 0 : kCornerSize),
303 kInternalLeftRightPadding + (on_left ? kCornerSize : 0)); 311 kInternalLeftRightPadding + (on_left ? kCornerSize : 0));
304 // The rounded window code flips these arguments if we're RTL. 312 // The rounded window code flips these arguments if we're RTL.
305 gtk_util::SetRoundedWindowEdgesAndBorders( 313 gtk_util::SetRoundedWindowEdgesAndBorders(
306 container_.get(), 314 container_.get(),
307 kCornerSize, 315 kCornerSize,
308 flip_horizontally ? 316 flip_horizontally ?
309 gtk_util::ROUNDED_TOP_LEFT : 317 gtk_util::ROUNDED_TOP_LEFT :
310 gtk_util::ROUNDED_TOP_RIGHT, 318 gtk_util::ROUNDED_TOP_RIGHT,
311 gtk_util::BORDER_TOP | 319 gtk_util::BORDER_TOP |
312 (flip_horizontally ? gtk_util::BORDER_LEFT : gtk_util::BORDER_RIGHT)); 320 (flip_horizontally ? gtk_util::BORDER_LEFT : gtk_util::BORDER_RIGHT));
313 gtk_widget_queue_draw(container_.get()); 321 gtk_widget_queue_draw(container_.get());
314 } 322 }
315 323
316 void StatusBubbleGtk::ExpandURL() { 324 void StatusBubbleGtk::ExpandURL() {
317 start_width_ = label_->allocation.width; 325 start_width_ = label_->allocation.width;
318 expand_animation_.reset(new SlideAnimation(this)); 326 expand_animation_.reset(new SlideAnimation(this));
319 expand_animation_->SetTweenType(Tween::LINEAR); 327 expand_animation_->SetTweenType(Tween::LINEAR);
320 expand_animation_->Show(); 328 expand_animation_->Show();
321 329
322 SetStatusTextToURL(); 330 SetStatusTextToURL();
323 } 331 }
324 332
325 void StatusBubbleGtk::UpdateLabelSizeRequest() { 333 void StatusBubbleGtk::UpdateLabelSizeRequest() {
326 if (!expanded() || !expand_animation_->is_animating()) { 334 if (!expanded() || !expand_animation_->is_animating()) {
327 gtk_widget_set_size_request(label_, -1, -1); 335 gtk_widget_set_size_request(label_, -1, -1);
328 return; 336 return;
329 } 337 }
330 338
331 int new_width = start_width_ + 339 int new_width = start_width_ +
332 (desired_width_ - start_width_) * expand_animation_->GetCurrentValue(); 340 (desired_width_ - start_width_) * expand_animation_->GetCurrentValue();
333 gtk_widget_set_size_request(label_, new_width, -1); 341 gtk_widget_set_size_request(label_, new_width, -1);
334 } 342 }
335 343
344 // See http://crbug.com/68897 for why we have to handle this event.
345 gboolean StatusBubbleGtk::HandleEnterNotify(GtkWidget* sender,
346 GdkEventCrossing* event) {
347 ignore_next_left_content_ = true;
348 MouseMoved(gfx::Point(event->x_root, event->y_root), false);
349 return FALSE;
350 }
351
336 gboolean StatusBubbleGtk::HandleMotionNotify(GtkWidget* sender, 352 gboolean StatusBubbleGtk::HandleMotionNotify(GtkWidget* sender,
337 GdkEventMotion* event) { 353 GdkEventMotion* event) {
338 MouseMoved(gfx::Point(event->x_root, event->y_root), false); 354 MouseMoved(gfx::Point(event->x_root, event->y_root), false);
339 return FALSE; 355 return FALSE;
340 } 356 }
341 357
342 void StatusBubbleGtk::AnimationEnded(const Animation* animation) { 358 void StatusBubbleGtk::AnimationEnded(const Animation* animation) {
343 UpdateLabelSizeRequest(); 359 UpdateLabelSizeRequest();
344 } 360 }
345 361
346 void StatusBubbleGtk::AnimationProgressed(const Animation* animation) { 362 void StatusBubbleGtk::AnimationProgressed(const Animation* animation) {
347 UpdateLabelSizeRequest(); 363 UpdateLabelSizeRequest();
348 } 364 }
OLDNEW
« no previous file with comments | « chrome/browser/gtk/status_bubble_gtk.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698