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

Unified 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, 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/ui/views/status_bubble_views.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/ui/views/status_bubble_views.cc
diff --git a/chrome/browser/ui/views/status_bubble_views.cc b/chrome/browser/ui/views/status_bubble_views.cc
index 036f791a4fd1b735cd67e7ccaf7e7921b31c693a..1844cccbb829a19693793b85d680c4b7eef6435c 100644
--- a/chrome/browser/ui/views/status_bubble_views.cc
+++ b/chrome/browser/ui/views/status_bubble_views.cc
@@ -19,7 +19,8 @@
#include "components/url_formatter/elide_url.h"
#include "components/url_formatter/url_formatter.h"
#include "third_party/skia/include/core/SkPaint.h"
-#include "third_party/skia/include/core/SkRRect.h"
+#include "third_party/skia/include/core/SkPath.h"
+#include "third_party/skia/include/pathops/SkPathOps.h"
#include "ui/base/theme_provider.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
@@ -135,7 +136,10 @@ class StatusBubbleViews::StatusView : public views::View {
};
StatusView(views::Widget* popup,
- const ui::ThemeProvider* theme_provider);
+ const gfx::Size& popup_size_,
+ SkColor bubble_color,
+ SkColor bubble_text_color,
+ bool has_client_edge);
~StatusView() override;
// Set the bubble text to a certain value, hides the bubble if text is
@@ -164,6 +168,8 @@ class StatusBubbleViews::StatusView : public views::View {
// not.
void OnAnimationEnded();
+ void SetWidth(int new_width);
+
private:
class InitialTimer;
@@ -193,22 +199,30 @@ class StatusBubbleViews::StatusView : public views::View {
// The currently-displayed text.
base::string16 text_;
- // Holds the theme provider of the frame that created us.
- const ui::ThemeProvider* theme_provider_;
+ gfx::Size popup_size_;
+
+ const SkColor bubble_color_;
+ const SkColor bubble_text_color_;
+ const bool has_client_edge_;
base::WeakPtrFactory<StatusBubbleViews::StatusView> timer_factory_;
DISALLOW_COPY_AND_ASSIGN(StatusView);
};
-StatusBubbleViews::StatusView::StatusView(
- views::Widget* popup,
- const ui::ThemeProvider* theme_provider)
+StatusBubbleViews::StatusView::StatusView(views::Widget* popup,
+ const gfx::Size& popup_size,
+ SkColor bubble_color,
+ SkColor bubble_text_color,
+ bool has_client_edge)
: state_(BUBBLE_HIDDEN),
style_(STYLE_STANDARD),
animation_(new StatusViewAnimation(this, 0, 0)),
popup_(popup),
- theme_provider_(theme_provider),
+ popup_size_(popup_size),
+ bubble_color_(bubble_color),
+ bubble_text_color_(bubble_text_color),
+ has_client_edge_(has_client_edge),
timer_factory_(this) {}
StatusBubbleViews::StatusView::~StatusView() {
@@ -361,19 +375,18 @@ void StatusBubbleViews::StatusView::OnAnimationEnded() {
}
}
+void StatusBubbleViews::StatusView::SetWidth(int new_width) {
+ popup_size_.set_width(new_width);
+}
+
const char* StatusBubbleViews::StatusView::GetClassName() const {
return "StatusBubbleViews::StatusView";
}
void StatusBubbleViews::StatusView::OnPaint(gfx::Canvas* canvas) {
- SkPaint paint;
- paint.setStyle(SkPaint::kFill_Style);
- paint.setAntiAlias(true);
- SkColor toolbar_color = theme_provider_->GetColor(
- ThemeProperties::COLOR_TOOLBAR);
- paint.setColor(toolbar_color);
-
- gfx::Rect popup_bounds = popup_->GetWindowBoundsInScreen();
+ canvas->Save();
+ float scale = canvas->UndoDeviceScaleFactor();
+ const float radius = kBubbleCornerRadius * scale;
SkScalar rad[8] = {};
@@ -386,12 +399,12 @@ void StatusBubbleViews::StatusView::OnPaint(gfx::Canvas* canvas) {
// The text is RtL or the bubble is on the right side (but not both).
// Top Left corner.
- rad[0] = kBubbleCornerRadius;
- rad[1] = kBubbleCornerRadius;
+ rad[0] = radius;
+ rad[1] = radius;
} else {
// Top Right corner.
- rad[2] = kBubbleCornerRadius;
- rad[3] = kBubbleCornerRadius;
+ rad[2] = radius;
+ rad[3] = radius;
}
}
@@ -399,54 +412,100 @@ void StatusBubbleViews::StatusView::OnPaint(gfx::Canvas* canvas) {
// position (sticking upward).
if (style_ != STYLE_STANDARD && style_ != STYLE_STANDARD_RIGHT) {
// Bottom Right Corner.
- rad[4] = kBubbleCornerRadius;
- rad[5] = kBubbleCornerRadius;
+ rad[4] = radius;
+ rad[5] = radius;
// Bottom Left Corner.
- rad[6] = kBubbleCornerRadius;
- rad[7] = kBubbleCornerRadius;
+ rad[6] = radius;
+ rad[7] = radius;
+ }
+
+ // Snap to pixels to avoid shadow blurriness.
+ const float width = std::round(popup_size_.width() * scale);
+ 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
+
+#if defined(OS_WIN)
+ // In Reposition() below we move the bubble 1 dip to the bottom/left so that
+ // the bubble shadow will overlap the client edge/window frame. But we draw
+ // the shadow 1 pixel thick, which means we need to draw at the inner-most
+ // pixel of that dip for a proper overlap.
+ //
+ // Unfortunately the bubble's position relative to the window is dependent on
+ // the bubble's absolute screen position we can't position the bubble
+ // 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.
+ // away" from the frame (leaving a gap where the web content shows through)
+ // looks a lot worse than allowing the bubble to hang off the edge of the
+ // 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
+ // So these values are very conservative but still look better than not
+ // compensating at all.
+ 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
+#else
+ // 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
+ // to figure out appropriate values for non-Windows platforms.
+ const int subdip_layout_inset = 0;
+#endif
+
+ if (!has_client_edge_) {
+ const int clip_size = subdip_layout_inset + 1;
+ // Clip out the edges when the bubble is docked so that it doesn't draw over
+ // the window border, since there's no client edge. But we do want the
+ // border when the bubble is floating so it looks complete.
+ const int clip_left = style_ == STYLE_STANDARD ? clip_size : 0;
+ const int clip_right = style_ == STYLE_STANDARD_RIGHT ? clip_size : 0;
+ const int clip_bottom = clip_left || clip_right ? clip_size : 0;
+ gfx::Rect clip_rect(clip_left, 0, width - clip_right, height - clip_bottom);
+ canvas->ClipRect(clip_rect);
}
- // Draw the bubble's shadow.
- int width = popup_bounds.width();
- int height = popup_bounds.height();
- gfx::Rect rect(gfx::Rect(popup_bounds.size()));
- SkPaint shadow_paint;
- shadow_paint.setAntiAlias(true);
- shadow_paint.setColor(kShadowColor);
-
- SkRRect rrect;
- rrect.setRectRadii(RectToSkRect(rect), (const SkVector*)rad);
- canvas->sk_canvas()->drawRRect(rrect, shadow_paint);
-
- const int shadow_size = 2 * kShadowThickness;
- // Draw the bubble.
- rect.SetRect(SkIntToScalar(kShadowThickness), SkIntToScalar(kShadowThickness),
- SkIntToScalar(width - shadow_size),
- SkIntToScalar(height - shadow_size));
- rrect.setRectRadii(RectToSkRect(rect), (const SkVector*)rad);
- canvas->sk_canvas()->drawRRect(rrect, paint);
+ gfx::RectF bubble_rect(width, height);
+ const int error_left =
+ style_ != STYLE_STANDARD_RIGHT ? subdip_layout_inset : 0;
+ const int error_right =
+ style_ == STYLE_STANDARD_RIGHT ? subdip_layout_inset : 0;
+ // The bottom edge is very close to the top of the client edge, so trying to
+ // 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
+ const int error_bottom = has_client_edge_ ? 0 : subdip_layout_inset;
+ bubble_rect.Inset(error_left + 0.5, 0.5, error_right + 0.5,
+ error_bottom + 0.5);
+
+ SkPath path;
+ path.addRoundRect(gfx::RectFToSkRect(bubble_rect), rad);
+
+ SkPaint paint;
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(1);
+ paint.setAntiAlias(true);
+
+ SkPath stroke_path;
+ paint.getFillPath(path, &stroke_path);
+
+ // 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.
+ SkPath fill_path;
+ Op(path, stroke_path, kDifference_SkPathOp, &fill_path);
+ paint.setStyle(SkPaint::kFill_Style);
+ paint.setColor(bubble_color_);
+ canvas->sk_canvas()->drawPath(fill_path, paint);
+
+ paint.setColor(kShadowColor);
+ canvas->sk_canvas()->drawPath(stroke_path, paint);
+
+ canvas->Restore();
// Compute text bounds.
- const gfx::FontList font_list;
- int text_width =
- std::min(gfx::GetStringWidth(text_, font_list),
- width - shadow_size - kTextPositionX - kTextHorizPadding);
- int text_height = height - shadow_size;
- gfx::Rect text_bounds(kShadowThickness + kTextPositionX,
- kShadowThickness,
- std::max(0, text_width),
- std::max(0, text_height));
+ gfx::Rect text_rect(kTextPositionX, 0,
+ popup_size_.width() - kTextHorizPadding,
+ popup_size_.height());
+ text_rect.Inset(kShadowThickness, kShadowThickness);
// Make sure the text is aligned to the right on RTL UIs.
- text_bounds.set_x(GetMirroredXForRect(text_bounds));
+ text_rect.set_x(GetMirroredXForRect(text_rect));
// Text color is the foreground tab text color at 60% alpha.
- SkColor text_color = color_utils::AlphaBlend(
- theme_provider_->GetColor(ThemeProperties::COLOR_TAB_TEXT), toolbar_color,
- 0x99);
+ SkColor blended_text_color =
+ color_utils::AlphaBlend(bubble_text_color_, bubble_color_, 0x99);
canvas->DrawStringRect(
- text_, font_list,
- color_utils::GetReadableColor(text_color, toolbar_color), text_bounds);
+ text_, gfx::FontList(),
+ color_utils::GetReadableColor(blended_text_color, bubble_color_),
+ text_rect);
}
@@ -505,9 +564,6 @@ class StatusBubbleViews::StatusViewExpander : public gfx::LinearAnimation,
int current_width,
int expansion_end);
- // Set width of fully expanded bubble.
- void SetExpandedWidth(int expanded_width);
-
private:
// Animation functions.
int GetCurrentBubbleWidth();
@@ -569,13 +625,15 @@ void StatusBubbleViews::StatusViewExpander::SetBubbleWidth(int width) {
const int StatusBubbleViews::kShadowThickness = 1;
-StatusBubbleViews::StatusBubbleViews(views::View* base_view)
+StatusBubbleViews::StatusBubbleViews(views::View* base_view,
+ bool has_client_edge)
: contains_mouse_(false),
offset_(0),
base_view_(base_view),
view_(NULL),
download_shelf_is_visible_(false),
is_expanded_(false),
+ has_client_edge_(has_client_edge),
expand_timer_factory_(this) {
expand_view_.reset();
}
@@ -590,8 +648,14 @@ void StatusBubbleViews::Init() {
if (!popup_.get()) {
popup_.reset(new views::Widget);
views::Widget* frame = base_view_->GetWidget();
- if (!view_)
- view_ = new StatusView(popup_.get(), frame->GetThemeProvider());
+ if (!view_) {
+ const ui::ThemeProvider* theme_provider = frame->GetThemeProvider();
+ view_ = new StatusView(
+ popup_.get(), size_,
+ theme_provider->GetColor(ThemeProperties::COLOR_TOOLBAR),
+ theme_provider->GetColor(ThemeProperties::COLOR_TAB_TEXT),
+ has_client_edge_);
+ }
if (!expand_view_.get())
expand_view_.reset(new StatusViewExpander(this, view_));
@@ -626,8 +690,8 @@ void StatusBubbleViews::Init() {
}
void StatusBubbleViews::Reposition() {
- // In restored mode, the client area has a client edge between it and the
- // frame.
+ // Overlap the client edge that's shown in restored mode, or when there is no
+ // client edge this makes the bubble snug with the corner of the window.
int overlap = kShadowThickness;
int height = GetPreferredSize().height();
int base_view_height = base_view()->bounds().height();
@@ -642,6 +706,7 @@ void StatusBubbleViews::RepositionPopup() {
// popup window's position is consistent with the base_view_'s window.
views::View::ConvertPointToScreen(base_view_, &top_left);
+ view_->SetWidth(size_.width());
popup_->SetBounds(gfx::Rect(top_left.x() + position_.x(),
top_left.y() + position_.y(),
size_.width(), size_.height()));
@@ -706,9 +771,8 @@ void StatusBubbleViews::SetURL(const GURL& url) {
}
// Set Elided Text corresponding to the GURL object.
- gfx::Rect popup_bounds = popup_->GetWindowBoundsInScreen();
- int text_width = static_cast<int>(popup_bounds.width() -
- (kShadowThickness * 2) - kTextPositionX - kTextHorizPadding - 1);
+ int text_width = static_cast<int>(size_.width() - (kShadowThickness * 2) -
+ kTextPositionX - kTextHorizPadding - 1);
url_text_ =
url_formatter::ElideUrl(url, gfx::FontList(), text_width);
@@ -872,7 +936,6 @@ bool StatusBubbleViews::IsFrameMaximized() {
void StatusBubbleViews::ExpandBubble() {
// Elide URL to maximum possible size, then check actual length (it may
// still be too long to fit) before expanding bubble.
- gfx::Rect popup_bounds = popup_->GetWindowBoundsInScreen();
int max_status_bubble_width = GetMaxStatusBubbleWidth();
const gfx::FontList font_list;
url_text_ = url_formatter::ElideUrl(url_, font_list, max_status_bubble_width);
@@ -883,8 +946,7 @@ void StatusBubbleViews::ExpandBubble() {
kTextHorizPadding + 1,
max_status_bubble_width));
is_expanded_ = true;
- expand_view_->StartExpansion(url_text_, popup_bounds.width(),
- expanded_bubble_width);
+ expand_view_->StartExpansion(url_text_, size_.width(), expanded_bubble_width);
}
int StatusBubbleViews::GetStandardStatusBubbleWidth() {
« 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