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

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: Created 4 years, 4 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"
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
128 }; 128 };
129 129
130 enum BubbleStyle { 130 enum BubbleStyle {
131 STYLE_BOTTOM, 131 STYLE_BOTTOM,
132 STYLE_FLOATING, 132 STYLE_FLOATING,
133 STYLE_STANDARD, 133 STYLE_STANDARD,
134 STYLE_STANDARD_RIGHT 134 STYLE_STANDARD_RIGHT
135 }; 135 };
136 136
137 StatusView(views::Widget* popup, 137 StatusView(views::Widget* popup,
138 const ui::ThemeProvider* theme_provider); 138 const ui::ThemeProvider* theme_provider,
139 const BrowserView* browser_view);
139 ~StatusView() override; 140 ~StatusView() override;
140 141
141 // Set the bubble text to a certain value, hides the bubble if text is 142 // Set the bubble text to a certain value, hides the bubble if text is
142 // an empty string. Trigger animation sequence to display if 143 // an empty string. Trigger animation sequence to display if
143 // |should_animate_open|. 144 // |should_animate_open|.
144 void SetText(const base::string16& text, bool should_animate_open); 145 void SetText(const base::string16& text, bool should_animate_open);
145 146
146 BubbleState state() const { return state_; } 147 BubbleState state() const { return state_; }
147 BubbleStyle style() const { return style_; } 148 BubbleStyle style() const { return style_; }
148 void SetStyle(BubbleStyle style); 149 void SetStyle(BubbleStyle style);
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
189 190
190 // Handle to the widget that contains us. 191 // Handle to the widget that contains us.
191 views::Widget* popup_; 192 views::Widget* popup_;
192 193
193 // The currently-displayed text. 194 // The currently-displayed text.
194 base::string16 text_; 195 base::string16 text_;
195 196
196 // Holds the theme provider of the frame that created us. 197 // Holds the theme provider of the frame that created us.
197 const ui::ThemeProvider* theme_provider_; 198 const ui::ThemeProvider* theme_provider_;
198 199
200 const BrowserView* browser_view_;
201
199 base::WeakPtrFactory<StatusBubbleViews::StatusView> timer_factory_; 202 base::WeakPtrFactory<StatusBubbleViews::StatusView> timer_factory_;
200 203
201 DISALLOW_COPY_AND_ASSIGN(StatusView); 204 DISALLOW_COPY_AND_ASSIGN(StatusView);
202 }; 205 };
203 206
204 StatusBubbleViews::StatusView::StatusView( 207 StatusBubbleViews::StatusView::StatusView(
205 views::Widget* popup, 208 views::Widget* popup,
206 const ui::ThemeProvider* theme_provider) 209 const ui::ThemeProvider* theme_provider,
210 const BrowserView* browser_view)
207 : state_(BUBBLE_HIDDEN), 211 : state_(BUBBLE_HIDDEN),
208 style_(STYLE_STANDARD), 212 style_(STYLE_STANDARD),
209 animation_(new StatusViewAnimation(this, 0, 0)), 213 animation_(new StatusViewAnimation(this, 0, 0)),
210 popup_(popup), 214 popup_(popup),
211 theme_provider_(theme_provider), 215 theme_provider_(theme_provider),
216 browser_view_(browser_view),
212 timer_factory_(this) {} 217 timer_factory_(this) {}
213 218
214 StatusBubbleViews::StatusView::~StatusView() { 219 StatusBubbleViews::StatusView::~StatusView() {
215 animation_->Stop(); 220 animation_->Stop();
216 CancelTimer(); 221 CancelTimer();
217 } 222 }
218 223
219 void StatusBubbleViews::StatusView::SetText(const base::string16& text, 224 void StatusBubbleViews::StatusView::SetText(const base::string16& text,
220 bool should_animate_open) { 225 bool should_animate_open) {
221 if (text.empty()) { 226 if (text.empty()) {
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
359 } else if (state_ == BUBBLE_SHOWING_FADE) { 364 } else if (state_ == BUBBLE_SHOWING_FADE) {
360 state_ = BUBBLE_SHOWN; 365 state_ = BUBBLE_SHOWN;
361 } 366 }
362 } 367 }
363 368
364 const char* StatusBubbleViews::StatusView::GetClassName() const { 369 const char* StatusBubbleViews::StatusView::GetClassName() const {
365 return "StatusBubbleViews::StatusView"; 370 return "StatusBubbleViews::StatusView";
366 } 371 }
367 372
368 void StatusBubbleViews::StatusView::OnPaint(gfx::Canvas* canvas) { 373 void StatusBubbleViews::StatusView::OnPaint(gfx::Canvas* canvas) {
369 SkPaint paint;
370 paint.setStyle(SkPaint::kFill_Style);
371 paint.setAntiAlias(true);
372 SkColor toolbar_color = theme_provider_->GetColor(
373 ThemeProperties::COLOR_TOOLBAR);
374 paint.setColor(toolbar_color);
375 374
376 gfx::Rect popup_bounds = popup_->GetWindowBoundsInScreen(); 375 gfx::Rect popup_bounds = popup_->GetWindowBoundsInScreen();
Peter Kasting 2016/08/13 06:13:07 Nit: I would avoid GetWindowBoundsInScreen() here
Bret 2016/08/18 18:58:04 I played around with this and I think GetWindowBou
377 376
377 canvas->Save();
378 float scale = canvas->UndoDeviceScaleFactor();
379 const int radius = std::round(kBubbleCornerRadius * scale);
Peter Kasting 2016/08/13 06:13:07 Seems like we should just use a float, not round.
Bret 2016/08/18 18:58:03 Done.
380
378 SkScalar rad[8] = {}; 381 SkScalar rad[8] = {};
379 382
380 // Top Edges - if the bubble is in its bottom position (sticking downwards), 383 // 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 384 // 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 385 // 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). 386 // southeast corner in RTL and in the southwest corner in LTR).
384 if (style_ != STYLE_BOTTOM) { 387 if (style_ != STYLE_BOTTOM) {
385 if (base::i18n::IsRTL() != (style_ == STYLE_STANDARD_RIGHT)) { 388 if (base::i18n::IsRTL() != (style_ == STYLE_STANDARD_RIGHT)) {
386 // The text is RtL or the bubble is on the right side (but not both). 389 // The text is RtL or the bubble is on the right side (but not both).
387 390
388 // Top Left corner. 391 // Top Left corner.
389 rad[0] = kBubbleCornerRadius; 392 rad[0] = radius;
390 rad[1] = kBubbleCornerRadius; 393 rad[1] = radius;
391 } else { 394 } else {
392 // Top Right corner. 395 // Top Right corner.
393 rad[2] = kBubbleCornerRadius; 396 rad[2] = radius;
394 rad[3] = kBubbleCornerRadius; 397 rad[3] = radius;
395 } 398 }
396 } 399 }
397 400
398 // Bottom edges - Keep these squared off if the bubble is in its standard 401 // Bottom edges - Keep these squared off if the bubble is in its standard
399 // position (sticking upward). 402 // position (sticking upward).
400 if (style_ != STYLE_STANDARD && style_ != STYLE_STANDARD_RIGHT) { 403 if (style_ != STYLE_STANDARD && style_ != STYLE_STANDARD_RIGHT) {
401 // Bottom Right Corner. 404 // Bottom Right Corner.
402 rad[4] = kBubbleCornerRadius; 405 rad[4] = radius;
403 rad[5] = kBubbleCornerRadius; 406 rad[5] = radius;
404 407
405 // Bottom Left Corner. 408 // Bottom Left Corner.
406 rad[6] = kBubbleCornerRadius; 409 rad[6] = radius;
407 rad[7] = kBubbleCornerRadius; 410 rad[7] = radius;
408 } 411 }
409 412
410 // Draw the bubble's shadow. 413 const int width = std::round(popup_bounds.width() * scale);
411 int width = popup_bounds.width(); 414 const int height = std::round(popup_bounds.height() * scale);
Peter Kasting 2016/08/13 06:13:07 Similarly, I think we should use floats here and R
Bret 2016/08/18 18:58:04 Done.
412 int height = popup_bounds.height(); 415
413 gfx::Rect rect(gfx::Rect(popup_bounds.size())); 416 if (!browser_view_->HasClientEdge()) {
Peter Kasting 2016/08/13 06:13:07 This function's return value isn't going to change
Bret 2016/08/18 18:58:04 Ok, I was thinking the value could change over the
417 // Clip out the edges when the bubble is docked so that it doesn't draw over
418 // the window border, since there's no client edge. But we do want the
419 // border when the bubble is floating so it looks complete.
420 const int clip_left = style_ == STYLE_STANDARD ? 1 : 0;
421 const bool clip_right = style_ == STYLE_STANDARD_RIGHT ? 1 : 0;
422 const bool clip_bottom = clip_left || clip_right ? 1 : 0;
423 gfx::Rect clip_rect(clip_left, 0, width - clip_right, height - clip_bottom);
424 canvas->ClipRect(clip_rect);
425 }
426
427 // Draw the shadow that borders the bubble.
428 gfx::Rect bubble_rect(width, height);
429 SkRRect rrect;
430 rrect.setRectRadii(RectToSkRect(bubble_rect), (const SkVector*)rad);
Peter Kasting 2016/08/13 06:13:07 The reason you're having layout issues at higher D
Bret 2016/08/18 18:58:04 I changed the painting to work the same way as Bac
431
414 SkPaint shadow_paint; 432 SkPaint shadow_paint;
Peter Kasting 2016/08/13 06:13:07 Nit: No need to use a different SkPaint here than
Bret 2016/08/18 18:58:04 Done.
415 shadow_paint.setAntiAlias(true); 433 shadow_paint.setAntiAlias(true);
416 shadow_paint.setColor(kShadowColor); 434 shadow_paint.setColor(kShadowColor);
417
418 SkRRect rrect;
419 rrect.setRectRadii(RectToSkRect(rect), (const SkVector*)rad);
420 canvas->sk_canvas()->drawRRect(rrect, shadow_paint); 435 canvas->sk_canvas()->drawRRect(rrect, shadow_paint);
421 436
422 const int shadow_size = 2 * kShadowThickness;
423 // Draw the bubble. 437 // Draw the bubble.
424 rect.SetRect(SkIntToScalar(kShadowThickness), SkIntToScalar(kShadowThickness), 438 bubble_rect.Inset(kShadowThickness, kShadowThickness);
425 SkIntToScalar(width - shadow_size), 439 rrect.setRectRadii(RectToSkRect(bubble_rect), (const SkVector*)rad);
Peter Kasting 2016/08/13 06:13:07 This is another place that's incorrect, and should
Bret 2016/08/18 18:58:04 Done. See above comment.
426 SkIntToScalar(height - shadow_size)); 440
427 rrect.setRectRadii(RectToSkRect(rect), (const SkVector*)rad); 441 SkPaint paint;
442 paint.setStyle(SkPaint::kFill_Style);
443 paint.setAntiAlias(true);
444 SkColor toolbar_color =
445 theme_provider_->GetColor(ThemeProperties::COLOR_TOOLBAR);
446 paint.setColor(toolbar_color);
428 canvas->sk_canvas()->drawRRect(rrect, paint); 447 canvas->sk_canvas()->drawRRect(rrect, paint);
429 448
449 canvas->Restore();
450
430 // Compute text bounds. 451 // Compute text bounds.
431 const gfx::FontList font_list; 452 gfx::Rect text_rect(popup_bounds.width() - kTextHorizPadding,
432 int text_width = 453 popup_bounds.height());
433 std::min(gfx::GetStringWidth(text_, font_list), 454 text_rect.Inset(kShadowThickness, kShadowThickness);
434 width - shadow_size - kTextPositionX - kTextHorizPadding); 455 text_rect.Inset(kTextPositionX, 0);
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. 456 // Make sure the text is aligned to the right on RTL UIs.
441 text_bounds.set_x(GetMirroredXForRect(text_bounds)); 457 text_rect.set_x(GetMirroredXForRect(text_rect));
442 458
443 // Text color is the foreground tab text color at 60% alpha. 459 // Text color is the foreground tab text color at 60% alpha.
444 SkColor text_color = color_utils::AlphaBlend( 460 SkColor text_color = color_utils::AlphaBlend(
445 theme_provider_->GetColor(ThemeProperties::COLOR_TAB_TEXT), toolbar_color, 461 theme_provider_->GetColor(ThemeProperties::COLOR_TAB_TEXT), toolbar_color,
446 0x99); 462 0x99);
463 const gfx::FontList font_list;
Peter Kasting 2016/08/13 06:13:07 Nit: Can we just pass FontList() in the call below
Bret 2016/08/18 18:58:04 Done.
447 canvas->DrawStringRect( 464 canvas->DrawStringRect(
448 text_, font_list, 465 text_, font_list,
449 color_utils::GetReadableColor(text_color, toolbar_color), text_bounds); 466 color_utils::GetReadableColor(text_color, toolbar_color), text_rect);
450 } 467 }
451 468
452 469
453 // StatusBubbleViews::StatusViewAnimation -------------------------------------- 470 // StatusBubbleViews::StatusViewAnimation --------------------------------------
454 471
455 StatusBubbleViews::StatusViewAnimation::StatusViewAnimation( 472 StatusBubbleViews::StatusViewAnimation::StatusViewAnimation(
456 StatusView* status_view, 473 StatusView* status_view,
457 float opacity_start, 474 float opacity_start,
458 float opacity_end) 475 float opacity_end)
459 : gfx::LinearAnimation(kFramerate, this), 476 : gfx::LinearAnimation(kFramerate, this),
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
562 void StatusBubbleViews::StatusViewExpander::SetBubbleWidth(int width) { 579 void StatusBubbleViews::StatusViewExpander::SetBubbleWidth(int width) {
563 status_bubble_->SetBubbleWidth(width); 580 status_bubble_->SetBubbleWidth(width);
564 status_view_->SchedulePaint(); 581 status_view_->SchedulePaint();
565 } 582 }
566 583
567 584
568 // StatusBubbleViews ----------------------------------------------------------- 585 // StatusBubbleViews -----------------------------------------------------------
569 586
570 const int StatusBubbleViews::kShadowThickness = 1; 587 const int StatusBubbleViews::kShadowThickness = 1;
571 588
572 StatusBubbleViews::StatusBubbleViews(views::View* base_view) 589 StatusBubbleViews::StatusBubbleViews(const BrowserView* browser_view,
590 views::View* base_view)
573 : contains_mouse_(false), 591 : contains_mouse_(false),
574 offset_(0), 592 offset_(0),
593 browser_view_(browser_view),
575 base_view_(base_view), 594 base_view_(base_view),
576 view_(NULL), 595 view_(NULL),
577 download_shelf_is_visible_(false), 596 download_shelf_is_visible_(false),
578 is_expanded_(false), 597 is_expanded_(false),
579 expand_timer_factory_(this) { 598 expand_timer_factory_(this) {
580 expand_view_.reset(); 599 expand_view_.reset();
581 } 600 }
582 601
583 StatusBubbleViews::~StatusBubbleViews() { 602 StatusBubbleViews::~StatusBubbleViews() {
584 CancelExpandTimer(); 603 CancelExpandTimer();
585 if (popup_.get()) 604 if (popup_.get())
586 popup_->CloseNow(); 605 popup_->CloseNow();
587 } 606 }
588 607
589 void StatusBubbleViews::Init() { 608 void StatusBubbleViews::Init() {
590 if (!popup_.get()) { 609 if (!popup_.get()) {
591 popup_.reset(new views::Widget); 610 popup_.reset(new views::Widget);
592 views::Widget* frame = base_view_->GetWidget(); 611 views::Widget* frame = base_view_->GetWidget();
593 if (!view_) 612 if (!view_)
594 view_ = new StatusView(popup_.get(), frame->GetThemeProvider()); 613 view_ = new StatusView(popup_.get(), frame->GetThemeProvider(),
614 browser_view_);
595 if (!expand_view_.get()) 615 if (!expand_view_.get())
596 expand_view_.reset(new StatusViewExpander(this, view_)); 616 expand_view_.reset(new StatusViewExpander(this, view_));
597 617
598 views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP); 618 views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
599 #if defined(OS_WIN) 619 #if defined(OS_WIN)
600 // On Windows use the software compositor to ensure that we don't block 620 // 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 621 // the UI thread blocking issue during command buffer creation. We can
602 // revert this change once http://crbug.com/125248 is fixed. 622 // revert this change once http://crbug.com/125248 is fixed.
603 params.force_software_compositing = true; 623 params.force_software_compositing = true;
604 #endif 624 #endif
(...skipping 14 matching lines...) Expand all
619 popup_->SetContentsView(view_); 639 popup_->SetContentsView(view_);
620 #if defined(USE_ASH) 640 #if defined(USE_ASH)
621 ash::wm::GetWindowState(popup_->GetNativeWindow())-> 641 ash::wm::GetWindowState(popup_->GetNativeWindow())->
622 set_ignored_by_shelf(true); 642 set_ignored_by_shelf(true);
623 #endif 643 #endif
624 RepositionPopup(); 644 RepositionPopup();
625 } 645 }
626 } 646 }
627 647
628 void StatusBubbleViews::Reposition() { 648 void StatusBubbleViews::Reposition() {
629 // In restored mode, the client area has a client edge between it and the 649 // Overlap the client edge that's shown in restored mode, or when there is no
630 // frame. 650 // client edge this makes the bubble snug with the corner of the window.
631 int overlap = kShadowThickness; 651 int overlap = kShadowThickness;
632 int height = GetPreferredSize().height(); 652 int height = GetPreferredSize().height();
633 int base_view_height = base_view()->bounds().height(); 653 int base_view_height = base_view()->bounds().height();
634 gfx::Point origin(-overlap, base_view_height - height + overlap); 654 gfx::Point origin(-overlap, base_view_height - height + overlap);
635 SetBounds(origin.x(), origin.y(), base_view()->bounds().width() / 3, height); 655 SetBounds(origin.x(), origin.y(), base_view()->bounds().width() / 3, height);
636 } 656 }
637 657
638 void StatusBubbleViews::RepositionPopup() { 658 void StatusBubbleViews::RepositionPopup() {
639 if (popup_.get()) { 659 if (popup_.get()) {
640 gfx::Point top_left; 660 gfx::Point top_left;
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
901 void StatusBubbleViews::SetBubbleWidth(int width) { 921 void StatusBubbleViews::SetBubbleWidth(int width) {
902 size_.set_width(width); 922 size_.set_width(width);
903 SetBounds(original_position_.x(), original_position_.y(), 923 SetBounds(original_position_.x(), original_position_.y(),
904 size_.width(), size_.height()); 924 size_.width(), size_.height());
905 } 925 }
906 926
907 void StatusBubbleViews::CancelExpandTimer() { 927 void StatusBubbleViews::CancelExpandTimer() {
908 if (expand_timer_factory_.HasWeakPtrs()) 928 if (expand_timer_factory_.HasWeakPtrs())
909 expand_timer_factory_.InvalidateWeakPtrs(); 929 expand_timer_factory_.InvalidateWeakPtrs();
910 } 930 }
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