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

Side by Side Diff: chrome/browser/ui/views/status_bubble_views.cc

Issue 2247563002: Change status bubble rendering at hidpi and when there is no client edge (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: remove tmp file Created 4 years, 3 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
« no previous file with comments | « chrome/browser/ui/views/status_bubble_views.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) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/ui/views/status_bubble_views.h" 5 #include "chrome/browser/ui/views/status_bubble_views.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/i18n/rtl.h" 10 #include "base/i18n/rtl.h"
11 #include "base/location.h" 11 #include "base/location.h"
12 #include "base/macros.h" 12 #include "base/macros.h"
13 #include "base/single_thread_task_runner.h" 13 #include "base/single_thread_task_runner.h"
14 #include "base/strings/string_util.h" 14 #include "base/strings/string_util.h"
15 #include "base/strings/utf_string_conversions.h" 15 #include "base/strings/utf_string_conversions.h"
16 #include "base/threading/thread_task_runner_handle.h" 16 #include "base/threading/thread_task_runner_handle.h"
17 #include "build/build_config.h" 17 #include "build/build_config.h"
18 #include "chrome/browser/themes/theme_properties.h" 18 #include "chrome/browser/themes/theme_properties.h"
19 #include "components/url_formatter/elide_url.h" 19 #include "components/url_formatter/elide_url.h"
20 #include "components/url_formatter/url_formatter.h" 20 #include "components/url_formatter/url_formatter.h"
21 #include "third_party/skia/include/core/SkPaint.h" 21 #include "third_party/skia/include/core/SkPaint.h"
22 #include "third_party/skia/include/core/SkRRect.h" 22 #include "third_party/skia/include/core/SkPath.h"
23 #include "third_party/skia/include/pathops/SkPathOps.h"
23 #include "ui/base/theme_provider.h" 24 #include "ui/base/theme_provider.h"
24 #include "ui/display/display.h" 25 #include "ui/display/display.h"
25 #include "ui/display/screen.h" 26 #include "ui/display/screen.h"
26 #include "ui/gfx/animation/animation_delegate.h" 27 #include "ui/gfx/animation/animation_delegate.h"
27 #include "ui/gfx/animation/linear_animation.h" 28 #include "ui/gfx/animation/linear_animation.h"
28 #include "ui/gfx/canvas.h" 29 #include "ui/gfx/canvas.h"
29 #include "ui/gfx/font_list.h" 30 #include "ui/gfx/font_list.h"
30 #include "ui/gfx/geometry/point.h" 31 #include "ui/gfx/geometry/point.h"
31 #include "ui/gfx/geometry/rect.h" 32 #include "ui/gfx/geometry/rect.h"
32 #include "ui/gfx/skia_util.h" 33 #include "ui/gfx/skia_util.h"
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
128 }; 129 };
129 130
130 enum BubbleStyle { 131 enum BubbleStyle {
131 STYLE_BOTTOM, 132 STYLE_BOTTOM,
132 STYLE_FLOATING, 133 STYLE_FLOATING,
133 STYLE_STANDARD, 134 STYLE_STANDARD,
134 STYLE_STANDARD_RIGHT 135 STYLE_STANDARD_RIGHT
135 }; 136 };
136 137
137 StatusView(views::Widget* popup, 138 StatusView(views::Widget* popup,
138 const ui::ThemeProvider* theme_provider); 139 const gfx::Size& popup_size_,
140 SkColor bubble_color,
141 SkColor bubble_text_color,
142 bool has_client_edge);
139 ~StatusView() override; 143 ~StatusView() override;
140 144
141 // Set the bubble text to a certain value, hides the bubble if text is 145 // Set the bubble text to a certain value, hides the bubble if text is
142 // an empty string. Trigger animation sequence to display if 146 // an empty string. Trigger animation sequence to display if
143 // |should_animate_open|. 147 // |should_animate_open|.
144 void SetText(const base::string16& text, bool should_animate_open); 148 void SetText(const base::string16& text, bool should_animate_open);
145 149
146 BubbleState state() const { return state_; } 150 BubbleState state() const { return state_; }
147 BubbleStyle style() const { return style_; } 151 BubbleStyle style() const { return style_; }
148 void SetStyle(BubbleStyle style); 152 void SetStyle(BubbleStyle style);
149 153
150 // Show the bubble instantly. 154 // Show the bubble instantly.
151 void Show(); 155 void Show();
152 156
153 // Hide the bubble instantly. 157 // Hide the bubble instantly.
154 void Hide(); 158 void Hide();
155 159
156 // Resets any timers we have. Typically called when the user moves a 160 // Resets any timers we have. Typically called when the user moves a
157 // mouse. 161 // mouse.
158 void ResetTimer(); 162 void ResetTimer();
159 163
160 // This call backs the StatusView in order to fade the bubble in and out. 164 // This call backs the StatusView in order to fade the bubble in and out.
161 void SetOpacity(float opacity); 165 void SetOpacity(float opacity);
162 166
163 // Depending on the state of the bubble this will either hide the popup or 167 // Depending on the state of the bubble this will either hide the popup or
164 // not. 168 // not.
165 void OnAnimationEnded(); 169 void OnAnimationEnded();
166 170
171 void SetWidth(int new_width);
172
167 private: 173 private:
168 class InitialTimer; 174 class InitialTimer;
169 175
170 // Manage the timers that control the delay before a fade begins or ends. 176 // Manage the timers that control the delay before a fade begins or ends.
171 void StartTimer(base::TimeDelta time); 177 void StartTimer(base::TimeDelta time);
172 void OnTimer(); 178 void OnTimer();
173 void CancelTimer(); 179 void CancelTimer();
174 void RestartTimer(base::TimeDelta delay); 180 void RestartTimer(base::TimeDelta delay);
175 181
176 // Manage the fades and starting and stopping the animations correctly. 182 // Manage the fades and starting and stopping the animations correctly.
177 void StartFade(float start, float end, int duration); 183 void StartFade(float start, float end, int duration);
178 void StartHiding(); 184 void StartHiding();
179 void StartShowing(); 185 void StartShowing();
180 186
181 // views::View: 187 // views::View:
182 const char* GetClassName() const override; 188 const char* GetClassName() const override;
183 void OnPaint(gfx::Canvas* canvas) override; 189 void OnPaint(gfx::Canvas* canvas) override;
184 190
185 BubbleState state_; 191 BubbleState state_;
186 BubbleStyle style_; 192 BubbleStyle style_;
187 193
188 std::unique_ptr<StatusViewAnimation> animation_; 194 std::unique_ptr<StatusViewAnimation> animation_;
189 195
190 // Handle to the widget that contains us. 196 // Handle to the widget that contains us.
191 views::Widget* popup_; 197 views::Widget* popup_;
192 198
193 // The currently-displayed text. 199 // The currently-displayed text.
194 base::string16 text_; 200 base::string16 text_;
195 201
196 // Holds the theme provider of the frame that created us. 202 gfx::Size popup_size_;
197 const ui::ThemeProvider* theme_provider_; 203
204 const SkColor bubble_color_;
205 const SkColor bubble_text_color_;
206 const bool has_client_edge_;
198 207
199 base::WeakPtrFactory<StatusBubbleViews::StatusView> timer_factory_; 208 base::WeakPtrFactory<StatusBubbleViews::StatusView> timer_factory_;
200 209
201 DISALLOW_COPY_AND_ASSIGN(StatusView); 210 DISALLOW_COPY_AND_ASSIGN(StatusView);
202 }; 211 };
203 212
204 StatusBubbleViews::StatusView::StatusView( 213 StatusBubbleViews::StatusView::StatusView(views::Widget* popup,
205 views::Widget* popup, 214 const gfx::Size& popup_size,
206 const ui::ThemeProvider* theme_provider) 215 SkColor bubble_color,
216 SkColor bubble_text_color,
217 bool has_client_edge)
207 : state_(BUBBLE_HIDDEN), 218 : state_(BUBBLE_HIDDEN),
208 style_(STYLE_STANDARD), 219 style_(STYLE_STANDARD),
209 animation_(new StatusViewAnimation(this, 0, 0)), 220 animation_(new StatusViewAnimation(this, 0, 0)),
210 popup_(popup), 221 popup_(popup),
211 theme_provider_(theme_provider), 222 popup_size_(popup_size),
223 bubble_color_(bubble_color),
224 bubble_text_color_(bubble_text_color),
225 has_client_edge_(has_client_edge),
212 timer_factory_(this) {} 226 timer_factory_(this) {}
213 227
214 StatusBubbleViews::StatusView::~StatusView() { 228 StatusBubbleViews::StatusView::~StatusView() {
215 animation_->Stop(); 229 animation_->Stop();
216 CancelTimer(); 230 CancelTimer();
217 } 231 }
218 232
219 void StatusBubbleViews::StatusView::SetText(const base::string16& text, 233 void StatusBubbleViews::StatusView::SetText(const base::string16& text,
220 bool should_animate_open) { 234 bool should_animate_open) {
221 if (text.empty()) { 235 if (text.empty()) {
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
354 368
355 void StatusBubbleViews::StatusView::OnAnimationEnded() { 369 void StatusBubbleViews::StatusView::OnAnimationEnded() {
356 if (state_ == BUBBLE_HIDING_FADE) { 370 if (state_ == BUBBLE_HIDING_FADE) {
357 state_ = BUBBLE_HIDDEN; 371 state_ = BUBBLE_HIDDEN;
358 popup_->Hide(); 372 popup_->Hide();
359 } else if (state_ == BUBBLE_SHOWING_FADE) { 373 } else if (state_ == BUBBLE_SHOWING_FADE) {
360 state_ = BUBBLE_SHOWN; 374 state_ = BUBBLE_SHOWN;
361 } 375 }
362 } 376 }
363 377
378 void StatusBubbleViews::StatusView::SetWidth(int new_width) {
379 popup_size_.set_width(new_width);
380 }
381
364 const char* StatusBubbleViews::StatusView::GetClassName() const { 382 const char* StatusBubbleViews::StatusView::GetClassName() const {
365 return "StatusBubbleViews::StatusView"; 383 return "StatusBubbleViews::StatusView";
366 } 384 }
367 385
368 void StatusBubbleViews::StatusView::OnPaint(gfx::Canvas* canvas) { 386 void StatusBubbleViews::StatusView::OnPaint(gfx::Canvas* canvas) {
369 SkPaint paint; 387 canvas->Save();
370 paint.setStyle(SkPaint::kFill_Style); 388 float scale = canvas->UndoDeviceScaleFactor();
371 paint.setAntiAlias(true); 389 const float radius = kBubbleCornerRadius * scale;
372 SkColor toolbar_color = theme_provider_->GetColor(
373 ThemeProperties::COLOR_TOOLBAR);
374 paint.setColor(toolbar_color);
375
376 gfx::Rect popup_bounds = popup_->GetWindowBoundsInScreen();
377 390
378 SkScalar rad[8] = {}; 391 SkScalar rad[8] = {};
379 392
380 // Top Edges - if the bubble is in its bottom position (sticking downwards), 393 // Top Edges - if the bubble is in its bottom position (sticking downwards),
381 // then we square the top edges. Otherwise, we square the edges based on the 394 // then we square the top edges. Otherwise, we square the edges based on the
382 // position of the bubble within the window (the bubble is positioned in the 395 // position of the bubble within the window (the bubble is positioned in the
383 // southeast corner in RTL and in the southwest corner in LTR). 396 // southeast corner in RTL and in the southwest corner in LTR).
384 if (style_ != STYLE_BOTTOM) { 397 if (style_ != STYLE_BOTTOM) {
385 if (base::i18n::IsRTL() != (style_ == STYLE_STANDARD_RIGHT)) { 398 if (base::i18n::IsRTL() != (style_ == STYLE_STANDARD_RIGHT)) {
386 // The text is RtL or the bubble is on the right side (but not both). 399 // The text is RtL or the bubble is on the right side (but not both).
387 400
388 // Top Left corner. 401 // Top Left corner.
389 rad[0] = kBubbleCornerRadius; 402 rad[0] = radius;
390 rad[1] = kBubbleCornerRadius; 403 rad[1] = radius;
391 } else { 404 } else {
392 // Top Right corner. 405 // Top Right corner.
393 rad[2] = kBubbleCornerRadius; 406 rad[2] = radius;
394 rad[3] = kBubbleCornerRadius; 407 rad[3] = radius;
395 } 408 }
396 } 409 }
397 410
398 // Bottom edges - Keep these squared off if the bubble is in its standard 411 // Bottom edges - Keep these squared off if the bubble is in its standard
399 // position (sticking upward). 412 // position (sticking upward).
400 if (style_ != STYLE_STANDARD && style_ != STYLE_STANDARD_RIGHT) { 413 if (style_ != STYLE_STANDARD && style_ != STYLE_STANDARD_RIGHT) {
401 // Bottom Right Corner. 414 // Bottom Right Corner.
402 rad[4] = kBubbleCornerRadius; 415 rad[4] = radius;
403 rad[5] = kBubbleCornerRadius; 416 rad[5] = radius;
404 417
405 // Bottom Left Corner. 418 // Bottom Left Corner.
406 rad[6] = kBubbleCornerRadius; 419 rad[6] = radius;
407 rad[7] = kBubbleCornerRadius; 420 rad[7] = radius;
408 } 421 }
409 422
410 // Draw the bubble's shadow. 423 // Snap to pixels to avoid shadow blurriness.
411 int width = popup_bounds.width(); 424 const float width = std::round(popup_size_.width() * scale);
412 int height = popup_bounds.height(); 425 const float height = std::round(popup_size_.height() * scale);
Peter Kasting 2016/08/24 22:53:24 Why are we rounding if we're storing in floats? I
Bret 2016/08/25 18:05:38 The types are just an oversight. I didn't think th
413 gfx::Rect rect(gfx::Rect(popup_bounds.size()));
414 SkPaint shadow_paint;
415 shadow_paint.setAntiAlias(true);
416 shadow_paint.setColor(kShadowColor);
417 426
418 SkRRect rrect; 427 #if defined(OS_WIN)
419 rrect.setRectRadii(RectToSkRect(rect), (const SkVector*)rad); 428 // In Reposition() below we move the bubble 1 dip to the bottom/left so that
420 canvas->sk_canvas()->drawRRect(rrect, shadow_paint); 429 // the bubble shadow will overlap the client edge/window frame. But we draw
430 // the shadow 1 pixel thick, which means we need to draw at the inner-most
431 // pixel of that dip for a proper overlap.
432 //
433 // Unfortunately the bubble's position relative to the window is dependent on
434 // the bubble's absolute screen position we can't position the bubble
435 // precisely enough to guarantee exactly what we want. Having the bubble "pull
Peter Kasting 2016/08/24 22:53:24 I think you meant to divide this first sentence in
Bret 2016/08/25 18:05:37 Done.
436 // away" from the frame (leaving a gap where the web content shows through)
437 // looks a lot worse than allowing the bubble to hang off the edge of the
438 // window. Plus the possible positioning imprecision increases at higher dsfs.
Peter Kasting 2016/08/24 22:53:24 Are you saying that sometimes (for example) the bu
Bret 2016/08/25 18:05:37 To your first question: you have the basic idea ri
439 // So these values are very conservative but still look better than not
440 // compensating at all.
441 const int subdip_layout_inset = scale > 1.25 ? (scale > 2 ? 2 : 1) : 0;
Peter Kasting 2016/08/24 22:53:24 It clearly isn't right to just use "2" for all sca
Bret 2016/08/25 18:05:37 I'm not claiming this isn't a hack, basically, but
442 #else
443 // FIXME: Since the dip error is dependent on platform-specific code we need
Peter Kasting 2016/08/24 22:53:24 Which platform-specific code? The DIP-vs.px posit
Bret 2016/08/25 18:05:38 ScreenWin::DIPToScreenRect is what I was thinking
444 // to figure out appropriate values for non-Windows platforms.
445 const int subdip_layout_inset = 0;
446 #endif
421 447
422 const int shadow_size = 2 * kShadowThickness; 448 if (!has_client_edge_) {
423 // Draw the bubble. 449 const int clip_size = subdip_layout_inset + 1;
424 rect.SetRect(SkIntToScalar(kShadowThickness), SkIntToScalar(kShadowThickness), 450 // Clip out the edges when the bubble is docked so that it doesn't draw over
425 SkIntToScalar(width - shadow_size), 451 // the window border, since there's no client edge. But we do want the
426 SkIntToScalar(height - shadow_size)); 452 // border when the bubble is floating so it looks complete.
427 rrect.setRectRadii(RectToSkRect(rect), (const SkVector*)rad); 453 const int clip_left = style_ == STYLE_STANDARD ? clip_size : 0;
428 canvas->sk_canvas()->drawRRect(rrect, paint); 454 const int clip_right = style_ == STYLE_STANDARD_RIGHT ? clip_size : 0;
455 const int clip_bottom = clip_left || clip_right ? clip_size : 0;
456 gfx::Rect clip_rect(clip_left, 0, width - clip_right, height - clip_bottom);
457 canvas->ClipRect(clip_rect);
458 }
459
460 gfx::RectF bubble_rect(width, height);
461 const int error_left =
462 style_ != STYLE_STANDARD_RIGHT ? subdip_layout_inset : 0;
463 const int error_right =
464 style_ == STYLE_STANDARD_RIGHT ? subdip_layout_inset : 0;
465 // The bottom edge is very close to the top of the client edge, so trying to
466 // inset it at all causes it to pull away from the frame.
Peter Kasting 2016/08/24 22:53:24 I don't understand why this is different than the
Bret 2016/08/25 18:05:38 I'm not sure either, tbh. It might have something
467 const int error_bottom = has_client_edge_ ? 0 : subdip_layout_inset;
468 bubble_rect.Inset(error_left + 0.5, 0.5, error_right + 0.5,
469 error_bottom + 0.5);
470
471 SkPath path;
472 path.addRoundRect(gfx::RectFToSkRect(bubble_rect), rad);
473
474 SkPaint paint;
475 paint.setStyle(SkPaint::kStroke_Style);
476 paint.setStrokeWidth(1);
477 paint.setAntiAlias(true);
478
479 SkPath stroke_path;
480 paint.getFillPath(path, &stroke_path);
481
482 // Get the fill path by subtracting the shadow so they algin neatly.
Peter Kasting 2016/08/24 22:53:24 Nit: align
Bret 2016/08/25 18:05:38 Done.
483 SkPath fill_path;
484 Op(path, stroke_path, kDifference_SkPathOp, &fill_path);
485 paint.setStyle(SkPaint::kFill_Style);
486 paint.setColor(bubble_color_);
487 canvas->sk_canvas()->drawPath(fill_path, paint);
488
489 paint.setColor(kShadowColor);
490 canvas->sk_canvas()->drawPath(stroke_path, paint);
491
492 canvas->Restore();
429 493
430 // Compute text bounds. 494 // Compute text bounds.
431 const gfx::FontList font_list; 495 gfx::Rect text_rect(kTextPositionX, 0,
432 int text_width = 496 popup_size_.width() - kTextHorizPadding,
433 std::min(gfx::GetStringWidth(text_, font_list), 497 popup_size_.height());
434 width - shadow_size - kTextPositionX - kTextHorizPadding); 498 text_rect.Inset(kShadowThickness, kShadowThickness);
435 int text_height = height - shadow_size;
436 gfx::Rect text_bounds(kShadowThickness + kTextPositionX,
437 kShadowThickness,
438 std::max(0, text_width),
439 std::max(0, text_height));
440 // Make sure the text is aligned to the right on RTL UIs. 499 // Make sure the text is aligned to the right on RTL UIs.
441 text_bounds.set_x(GetMirroredXForRect(text_bounds)); 500 text_rect.set_x(GetMirroredXForRect(text_rect));
442 501
443 // Text color is the foreground tab text color at 60% alpha. 502 // Text color is the foreground tab text color at 60% alpha.
444 SkColor text_color = color_utils::AlphaBlend( 503 SkColor blended_text_color =
445 theme_provider_->GetColor(ThemeProperties::COLOR_TAB_TEXT), toolbar_color, 504 color_utils::AlphaBlend(bubble_text_color_, bubble_color_, 0x99);
446 0x99);
447 canvas->DrawStringRect( 505 canvas->DrawStringRect(
448 text_, font_list, 506 text_, gfx::FontList(),
449 color_utils::GetReadableColor(text_color, toolbar_color), text_bounds); 507 color_utils::GetReadableColor(blended_text_color, bubble_color_),
508 text_rect);
450 } 509 }
451 510
452 511
453 // StatusBubbleViews::StatusViewAnimation -------------------------------------- 512 // StatusBubbleViews::StatusViewAnimation --------------------------------------
454 513
455 StatusBubbleViews::StatusViewAnimation::StatusViewAnimation( 514 StatusBubbleViews::StatusViewAnimation::StatusViewAnimation(
456 StatusView* status_view, 515 StatusView* status_view,
457 float opacity_start, 516 float opacity_start,
458 float opacity_end) 517 float opacity_end)
459 : gfx::LinearAnimation(kFramerate, this), 518 : gfx::LinearAnimation(kFramerate, this),
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
498 status_view_(status_view), 557 status_view_(status_view),
499 expansion_start_(0), 558 expansion_start_(0),
500 expansion_end_(0) { 559 expansion_end_(0) {
501 } 560 }
502 561
503 // Manage the expansion of the bubble. 562 // Manage the expansion of the bubble.
504 void StartExpansion(const base::string16& expanded_text, 563 void StartExpansion(const base::string16& expanded_text,
505 int current_width, 564 int current_width,
506 int expansion_end); 565 int expansion_end);
507 566
508 // Set width of fully expanded bubble.
509 void SetExpandedWidth(int expanded_width);
510
511 private: 567 private:
512 // Animation functions. 568 // Animation functions.
513 int GetCurrentBubbleWidth(); 569 int GetCurrentBubbleWidth();
514 void SetBubbleWidth(int width); 570 void SetBubbleWidth(int width);
515 void AnimateToState(double state) override; 571 void AnimateToState(double state) override;
516 void AnimationEnded(const gfx::Animation* animation) override; 572 void AnimationEnded(const gfx::Animation* animation) override;
517 573
518 // Manager that owns us. 574 // Manager that owns us.
519 StatusBubbleViews* status_bubble_; 575 StatusBubbleViews* status_bubble_;
520 576
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
562 void StatusBubbleViews::StatusViewExpander::SetBubbleWidth(int width) { 618 void StatusBubbleViews::StatusViewExpander::SetBubbleWidth(int width) {
563 status_bubble_->SetBubbleWidth(width); 619 status_bubble_->SetBubbleWidth(width);
564 status_view_->SchedulePaint(); 620 status_view_->SchedulePaint();
565 } 621 }
566 622
567 623
568 // StatusBubbleViews ----------------------------------------------------------- 624 // StatusBubbleViews -----------------------------------------------------------
569 625
570 const int StatusBubbleViews::kShadowThickness = 1; 626 const int StatusBubbleViews::kShadowThickness = 1;
571 627
572 StatusBubbleViews::StatusBubbleViews(views::View* base_view) 628 StatusBubbleViews::StatusBubbleViews(views::View* base_view,
629 bool has_client_edge)
573 : contains_mouse_(false), 630 : contains_mouse_(false),
574 offset_(0), 631 offset_(0),
575 base_view_(base_view), 632 base_view_(base_view),
576 view_(NULL), 633 view_(NULL),
577 download_shelf_is_visible_(false), 634 download_shelf_is_visible_(false),
578 is_expanded_(false), 635 is_expanded_(false),
636 has_client_edge_(has_client_edge),
579 expand_timer_factory_(this) { 637 expand_timer_factory_(this) {
580 expand_view_.reset(); 638 expand_view_.reset();
581 } 639 }
582 640
583 StatusBubbleViews::~StatusBubbleViews() { 641 StatusBubbleViews::~StatusBubbleViews() {
584 CancelExpandTimer(); 642 CancelExpandTimer();
585 if (popup_.get()) 643 if (popup_.get())
586 popup_->CloseNow(); 644 popup_->CloseNow();
587 } 645 }
588 646
589 void StatusBubbleViews::Init() { 647 void StatusBubbleViews::Init() {
590 if (!popup_.get()) { 648 if (!popup_.get()) {
591 popup_.reset(new views::Widget); 649 popup_.reset(new views::Widget);
592 views::Widget* frame = base_view_->GetWidget(); 650 views::Widget* frame = base_view_->GetWidget();
593 if (!view_) 651 if (!view_) {
594 view_ = new StatusView(popup_.get(), frame->GetThemeProvider()); 652 const ui::ThemeProvider* theme_provider = frame->GetThemeProvider();
653 view_ = new StatusView(
654 popup_.get(), size_,
655 theme_provider->GetColor(ThemeProperties::COLOR_TOOLBAR),
656 theme_provider->GetColor(ThemeProperties::COLOR_TAB_TEXT),
657 has_client_edge_);
658 }
595 if (!expand_view_.get()) 659 if (!expand_view_.get())
596 expand_view_.reset(new StatusViewExpander(this, view_)); 660 expand_view_.reset(new StatusViewExpander(this, view_));
597 661
598 views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP); 662 views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
599 #if defined(OS_WIN) 663 #if defined(OS_WIN)
600 // On Windows use the software compositor to ensure that we don't block 664 // On Windows use the software compositor to ensure that we don't block
601 // the UI thread blocking issue during command buffer creation. We can 665 // the UI thread blocking issue during command buffer creation. We can
602 // revert this change once http://crbug.com/125248 is fixed. 666 // revert this change once http://crbug.com/125248 is fixed.
603 params.force_software_compositing = true; 667 params.force_software_compositing = true;
604 #endif 668 #endif
(...skipping 14 matching lines...) Expand all
619 popup_->SetContentsView(view_); 683 popup_->SetContentsView(view_);
620 #if defined(USE_ASH) 684 #if defined(USE_ASH)
621 ash::wm::GetWindowState(popup_->GetNativeWindow())-> 685 ash::wm::GetWindowState(popup_->GetNativeWindow())->
622 set_ignored_by_shelf(true); 686 set_ignored_by_shelf(true);
623 #endif 687 #endif
624 RepositionPopup(); 688 RepositionPopup();
625 } 689 }
626 } 690 }
627 691
628 void StatusBubbleViews::Reposition() { 692 void StatusBubbleViews::Reposition() {
629 // In restored mode, the client area has a client edge between it and the 693 // Overlap the client edge that's shown in restored mode, or when there is no
630 // frame. 694 // client edge this makes the bubble snug with the corner of the window.
631 int overlap = kShadowThickness; 695 int overlap = kShadowThickness;
632 int height = GetPreferredSize().height(); 696 int height = GetPreferredSize().height();
633 int base_view_height = base_view()->bounds().height(); 697 int base_view_height = base_view()->bounds().height();
634 gfx::Point origin(-overlap, base_view_height - height + overlap); 698 gfx::Point origin(-overlap, base_view_height - height + overlap);
635 SetBounds(origin.x(), origin.y(), base_view()->bounds().width() / 3, height); 699 SetBounds(origin.x(), origin.y(), base_view()->bounds().width() / 3, height);
636 } 700 }
637 701
638 void StatusBubbleViews::RepositionPopup() { 702 void StatusBubbleViews::RepositionPopup() {
639 if (popup_.get()) { 703 if (popup_.get()) {
640 gfx::Point top_left; 704 gfx::Point top_left;
641 // TODO(flackr): Get the non-transformed point so that the status bubble 705 // TODO(flackr): Get the non-transformed point so that the status bubble
642 // popup window's position is consistent with the base_view_'s window. 706 // popup window's position is consistent with the base_view_'s window.
643 views::View::ConvertPointToScreen(base_view_, &top_left); 707 views::View::ConvertPointToScreen(base_view_, &top_left);
644 708
709 view_->SetWidth(size_.width());
645 popup_->SetBounds(gfx::Rect(top_left.x() + position_.x(), 710 popup_->SetBounds(gfx::Rect(top_left.x() + position_.x(),
646 top_left.y() + position_.y(), 711 top_left.y() + position_.y(),
647 size_.width(), size_.height())); 712 size_.width(), size_.height()));
648 } 713 }
649 } 714 }
650 715
651 gfx::Size StatusBubbleViews::GetPreferredSize() { 716 gfx::Size StatusBubbleViews::GetPreferredSize() {
652 return gfx::Size(0, gfx::FontList().GetHeight() + kTotalVerticalPadding); 717 return gfx::Size(0, gfx::FontList().GetHeight() + kTotalVerticalPadding);
653 } 718 }
654 719
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
699 return; 764 return;
700 } 765 }
701 766
702 // Reset expansion state only when bubble is completely hidden. 767 // Reset expansion state only when bubble is completely hidden.
703 if (view_->state() == StatusView::BUBBLE_HIDDEN) { 768 if (view_->state() == StatusView::BUBBLE_HIDDEN) {
704 is_expanded_ = false; 769 is_expanded_ = false;
705 SetBubbleWidth(GetStandardStatusBubbleWidth()); 770 SetBubbleWidth(GetStandardStatusBubbleWidth());
706 } 771 }
707 772
708 // Set Elided Text corresponding to the GURL object. 773 // Set Elided Text corresponding to the GURL object.
709 gfx::Rect popup_bounds = popup_->GetWindowBoundsInScreen(); 774 int text_width = static_cast<int>(size_.width() - (kShadowThickness * 2) -
710 int text_width = static_cast<int>(popup_bounds.width() - 775 kTextPositionX - kTextHorizPadding - 1);
711 (kShadowThickness * 2) - kTextPositionX - kTextHorizPadding - 1);
712 url_text_ = 776 url_text_ =
713 url_formatter::ElideUrl(url, gfx::FontList(), text_width); 777 url_formatter::ElideUrl(url, gfx::FontList(), text_width);
714 778
715 // An URL is always treated as a left-to-right string. On right-to-left UIs 779 // An URL is always treated as a left-to-right string. On right-to-left UIs
716 // we need to explicitly mark the URL as LTR to make sure it is displayed 780 // we need to explicitly mark the URL as LTR to make sure it is displayed
717 // correctly. 781 // correctly.
718 url_text_ = base::i18n::GetDisplayStringInLTRDirectionality(url_text_); 782 url_text_ = base::i18n::GetDisplayStringInLTRDirectionality(url_text_);
719 783
720 if (IsFrameVisible()) { 784 if (IsFrameVisible()) {
721 view_->SetText(url_text_, true); 785 view_->SetText(url_text_, true);
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
865 929
866 bool StatusBubbleViews::IsFrameMaximized() { 930 bool StatusBubbleViews::IsFrameMaximized() {
867 views::Widget* frame = base_view_->GetWidget(); 931 views::Widget* frame = base_view_->GetWidget();
868 views::Widget* window = frame->GetTopLevelWidget(); 932 views::Widget* window = frame->GetTopLevelWidget();
869 return window && window->IsMaximized(); 933 return window && window->IsMaximized();
870 } 934 }
871 935
872 void StatusBubbleViews::ExpandBubble() { 936 void StatusBubbleViews::ExpandBubble() {
873 // Elide URL to maximum possible size, then check actual length (it may 937 // Elide URL to maximum possible size, then check actual length (it may
874 // still be too long to fit) before expanding bubble. 938 // still be too long to fit) before expanding bubble.
875 gfx::Rect popup_bounds = popup_->GetWindowBoundsInScreen();
876 int max_status_bubble_width = GetMaxStatusBubbleWidth(); 939 int max_status_bubble_width = GetMaxStatusBubbleWidth();
877 const gfx::FontList font_list; 940 const gfx::FontList font_list;
878 url_text_ = url_formatter::ElideUrl(url_, font_list, max_status_bubble_width); 941 url_text_ = url_formatter::ElideUrl(url_, font_list, max_status_bubble_width);
879 int expanded_bubble_width = 942 int expanded_bubble_width =
880 std::max(GetStandardStatusBubbleWidth(), 943 std::max(GetStandardStatusBubbleWidth(),
881 std::min(gfx::GetStringWidth(url_text_, font_list) + 944 std::min(gfx::GetStringWidth(url_text_, font_list) +
882 (kShadowThickness * 2) + kTextPositionX + 945 (kShadowThickness * 2) + kTextPositionX +
883 kTextHorizPadding + 1, 946 kTextHorizPadding + 1,
884 max_status_bubble_width)); 947 max_status_bubble_width));
885 is_expanded_ = true; 948 is_expanded_ = true;
886 expand_view_->StartExpansion(url_text_, popup_bounds.width(), 949 expand_view_->StartExpansion(url_text_, size_.width(), expanded_bubble_width);
887 expanded_bubble_width);
888 } 950 }
889 951
890 int StatusBubbleViews::GetStandardStatusBubbleWidth() { 952 int StatusBubbleViews::GetStandardStatusBubbleWidth() {
891 return base_view_->bounds().width() / 3; 953 return base_view_->bounds().width() / 3;
892 } 954 }
893 955
894 int StatusBubbleViews::GetMaxStatusBubbleWidth() { 956 int StatusBubbleViews::GetMaxStatusBubbleWidth() {
895 const ui::NativeTheme* theme = base_view_->GetNativeTheme(); 957 const ui::NativeTheme* theme = base_view_->GetNativeTheme();
896 return static_cast<int>(std::max(0, base_view_->bounds().width() - 958 return static_cast<int>(std::max(0, base_view_->bounds().width() -
897 (kShadowThickness * 2) - kTextPositionX - kTextHorizPadding - 1 - 959 (kShadowThickness * 2) - kTextPositionX - kTextHorizPadding - 1 -
898 views::NativeScrollBar::GetVerticalScrollBarWidth(theme))); 960 views::NativeScrollBar::GetVerticalScrollBarWidth(theme)));
899 } 961 }
900 962
901 void StatusBubbleViews::SetBubbleWidth(int width) { 963 void StatusBubbleViews::SetBubbleWidth(int width) {
902 size_.set_width(width); 964 size_.set_width(width);
903 SetBounds(original_position_.x(), original_position_.y(), 965 SetBounds(original_position_.x(), original_position_.y(),
904 size_.width(), size_.height()); 966 size_.width(), size_.height());
905 } 967 }
906 968
907 void StatusBubbleViews::CancelExpandTimer() { 969 void StatusBubbleViews::CancelExpandTimer() {
908 if (expand_timer_factory_.HasWeakPtrs()) 970 if (expand_timer_factory_.HasWeakPtrs())
909 expand_timer_factory_.InvalidateWeakPtrs(); 971 expand_timer_factory_.InvalidateWeakPtrs();
910 } 972 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/views/status_bubble_views.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698