diff options
author | erg@google.com <erg@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-12 18:19:59 +0000 |
---|---|---|
committer | erg@google.com <erg@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-12 18:19:59 +0000 |
commit | 7e342930e757290f6bd1ba80ed9e25853d2e3e75 (patch) | |
tree | 1316834dc00d905e796d6d905122cd96cfdf92b0 | |
parent | d1d25e4d3c8fa47a78352813c061cc9f71f562ab (diff) | |
download | chromium_src-7e342930e757290f6bd1ba80ed9e25853d2e3e75.zip chromium_src-7e342930e757290f6bd1ba80ed9e25853d2e3e75.tar.gz chromium_src-7e342930e757290f6bd1ba80ed9e25853d2e3e75.tar.bz2 |
GTK: Popup notification should have transparent rounded corners.
Also uses the new consistent border color in GTK theme mode.
Review URL: http://codereview.chromium.org/165356
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@23189 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/gtk/blocked_popup_container_view_gtk.cc | 118 | ||||
-rw-r--r-- | chrome/browser/gtk/blocked_popup_container_view_gtk.h | 5 | ||||
-rw-r--r-- | chrome/browser/gtk/info_bubble_gtk.cc | 7 | ||||
-rw-r--r-- | chrome/browser/gtk/status_bubble_gtk.cc | 7 | ||||
-rw-r--r-- | chrome/common/gtk_util.cc | 5 | ||||
-rw-r--r-- | chrome/common/gtk_util.h | 4 |
6 files changed, 102 insertions, 44 deletions
diff --git a/chrome/browser/gtk/blocked_popup_container_view_gtk.cc b/chrome/browser/gtk/blocked_popup_container_view_gtk.cc index 6fe1671..b48b93e 100644 --- a/chrome/browser/gtk/blocked_popup_container_view_gtk.cc +++ b/chrome/browser/gtk/blocked_popup_container_view_gtk.cc @@ -22,18 +22,57 @@ namespace { // The minimal border around the edge of the notification. const int kSmallPadding = 2; -// Size of the border painted in kBorderColor -const int kBorderPadding = 1; - // Color of the border. -const double kBorderColor[] = { 190.0 / 255, 205.0 / 255, 223.0 / 255 }; +const GdkColor kBorderColor = GDK_COLOR_RGB(190, 205, 223); // Color of the gradient in the background. const double kBackgroundColorTop[] = { 246.0 / 255, 250.0 / 255, 1.0 }; const double kBackgroundColorBottom[] = { 219.0 / 255, 235.0 / 255, 1.0 }; // Rounded corner radius (in pixels). -const int kBackgroundCornerRadius = 4; +const int kCornerSize = 4; + +enum FrameType { + FRAME_MASK, + FRAME_STROKE, +}; + +std::vector<GdkPoint> MakeFramePolygonPoints(int width, + int height, + FrameType type) { + using gtk_util::MakeBidiGdkPoint; + std::vector<GdkPoint> points; + + bool ltr = l10n_util::GetTextDirection() == l10n_util::LEFT_TO_RIGHT; + // If we have a stroke, we have to offset some of our points by 1 pixel. + // We have to inset by 1 pixel when we draw horizontal lines that are on the + // bottom or when we draw vertical lines that are closer to the end (end is + // right for ltr). + int y_off = (type == FRAME_MASK) ? 0 : -1; + // We use this one for LTR. + int x_off_l = ltr ? y_off : 0; + // We use this one for RTL. + int x_off_r = !ltr ? -y_off : 0; + + // Bottom left corner. + points.push_back(MakeBidiGdkPoint(0, height + y_off, width, ltr)); + + // Top left (rounded) corner. + points.push_back(MakeBidiGdkPoint(x_off_r, kCornerSize - 1, width, ltr)); + points.push_back(MakeBidiGdkPoint(kCornerSize + x_off_r - 1, 0, width, ltr)); + + // Top right (rounded) corner. + points.push_back(MakeBidiGdkPoint( + width - kCornerSize + 1 + x_off_l, 0, width, ltr)); + points.push_back(MakeBidiGdkPoint( + width + x_off_l, kCornerSize - 1, width, ltr)); + + // Bottom right corner. + points.push_back(MakeBidiGdkPoint( + width + x_off_l, height + y_off, width, ltr)); + + return points; +} } // namespace @@ -150,7 +189,9 @@ BlockedPopupContainerViewGtk::BlockedPopupContainerViewGtk( BlockedPopupContainer* container) : model_(container), theme_provider_(GtkThemeProvider::GetFrom(container->profile())), - close_button_(CustomDrawButton::CloseButton(theme_provider_)) { + close_button_(CustomDrawButton::CloseButton(theme_provider_)), + notification_width_(-1), + notification_height_(-1) { Init(); registrar_.Add(this, @@ -223,13 +264,30 @@ gboolean BlockedPopupContainerViewGtk::OnContainerExpose( int width = widget->allocation.width; int height = widget->allocation.height; - // Clip to our damage rect - cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(widget->window)); - cairo_rectangle(cr, event->area.x, event->area.y, - event->area.width, event->area.height); - cairo_clip(cr); + // Update our window shape if we need to. + if (container->notification_width_ != widget->allocation.width || + container->notification_height_ != widget->allocation.height) { + // We need to update the shape of the status bubble whenever our GDK + // window changes shape. + std::vector<GdkPoint> mask_points = MakeFramePolygonPoints( + widget->allocation.width, widget->allocation.height, FRAME_MASK); + GdkRegion* mask_region = gdk_region_polygon(&mask_points[0], + mask_points.size(), + GDK_EVEN_ODD_RULE); + gdk_window_shape_combine_region(widget->window, mask_region, 0, 0); + gdk_region_destroy(mask_region); + + container->notification_width_ = widget->allocation.width; + container->notification_height_ = widget->allocation.height; + } if (!container->theme_provider_->UseGtkTheme()) { + // Clip to our damage rect. + cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(event->window)); + cairo_rectangle(cr, event->area.x, event->area.y, + event->area.width, event->area.height); + cairo_clip(cr); + // TODO(erg): We draw the gradient background only when GTK themes are // off. This isn't a perfect solution as this isn't themed! The views // version doesn't appear to be themed either, so at least for now, @@ -247,30 +305,24 @@ gboolean BlockedPopupContainerViewGtk::OnContainerExpose( cairo_set_source(cr, pattern); cairo_paint(cr); cairo_pattern_destroy(pattern); + + cairo_destroy(cr); + } + + GdkDrawable* drawable = GDK_DRAWABLE(event->window); + GdkGC* gc = gdk_gc_new(drawable); + if (container->theme_provider_->UseGtkTheme()) { + GdkColor color = container->theme_provider_->GetBorderColor(); + gdk_gc_set_rgb_fg_color(gc, &color); + } else { + gdk_gc_set_rgb_fg_color(gc, &kBorderColor); } - // TODO(erg): We need to figure out the border situation, too. We aren't - // provided a color from the theme system and the Windows implementation - // still uses constants for color. See the status bubble, too. - - // Sets up our stroke pen. - cairo_set_source_rgb(cr, kBorderColor[0], kBorderColor[1], kBorderColor[2]); - cairo_set_line_width(cr, 1.5); - - // Draws rounded corners around the edge of the notification, clockwise - // starting from the bottom left. (A bezier curve with control points at 90 - // degree angles forms a circular arc.) - cairo_move_to(cr, 0, height); - cairo_line_to(cr, 0, kBackgroundCornerRadius); - cairo_curve_to(cr, 0, kBackgroundCornerRadius, - 0, 0, kBackgroundCornerRadius, 0); - cairo_line_to(cr, width - kBackgroundCornerRadius, 0); - cairo_curve_to(cr, width - kBackgroundCornerRadius, 0, - width, 0, width, kBackgroundCornerRadius); - cairo_line_to(cr, width, height); - cairo_stroke(cr); - - cairo_destroy(cr); + // Stroke the frame border. + std::vector<GdkPoint> points = MakeFramePolygonPoints( + widget->allocation.width, widget->allocation.height, FRAME_STROKE); + gdk_draw_lines(drawable, gc, &points[0], points.size()); + g_object_unref(gc); return FALSE; // Allow subwidgets to paint. } diff --git a/chrome/browser/gtk/blocked_popup_container_view_gtk.h b/chrome/browser/gtk/blocked_popup_container_view_gtk.h index f74e880..f8de623 100644 --- a/chrome/browser/gtk/blocked_popup_container_view_gtk.h +++ b/chrome/browser/gtk/blocked_popup_container_view_gtk.h @@ -105,6 +105,11 @@ class BlockedPopupContainerViewGtk : public BlockedPopupContainerView, // The popup menu with options to launch blocked popups. scoped_ptr<MenuGtk> launch_menu_; + // Cached allocation of |container_|. We keep this on hand so that we can + // reset the widget's shape when the width/height change. + int notification_width_; + int notification_height_; + DISALLOW_COPY_AND_ASSIGN(BlockedPopupContainerViewGtk); }; diff --git a/chrome/browser/gtk/info_bubble_gtk.cc b/chrome/browser/gtk/info_bubble_gtk.cc index 8c7286f..5bb5715 100644 --- a/chrome/browser/gtk/info_bubble_gtk.cc +++ b/chrome/browser/gtk/info_bubble_gtk.cc @@ -14,6 +14,7 @@ #include "base/gfx/rect.h" #include "base/logging.h" #include "chrome/browser/gtk/gtk_theme_provider.h" +#include "chrome/common/gtk_util.h" #include "chrome/common/notification_service.h" namespace { @@ -38,11 +39,6 @@ const GdkColor kFrameColor = GDK_COLOR_RGB(0x63, 0x63, 0x63); const gchar* kInfoBubbleToplevelKey = "__INFO_BUBBLE_TOPLEVEL__"; -GdkPoint MakeBidiGdkPoint(gint x, gint y, gint width, bool ltr) { - GdkPoint point = {ltr ? x : width - x, y}; - return point; -} - enum FrameType { FRAME_MASK, FRAME_STROKE, @@ -57,6 +53,7 @@ enum FrameType { std::vector<GdkPoint> MakeFramePolygonPoints(int width, int height, FrameType type) { + using gtk_util::MakeBidiGdkPoint; std::vector<GdkPoint> points; bool ltr = l10n_util::GetTextDirection() == l10n_util::LEFT_TO_RIGHT; diff --git a/chrome/browser/gtk/status_bubble_gtk.cc b/chrome/browser/gtk/status_bubble_gtk.cc index a951e52..335d780 100644 --- a/chrome/browser/gtk/status_bubble_gtk.cc +++ b/chrome/browser/gtk/status_bubble_gtk.cc @@ -31,12 +31,6 @@ const int kCornerSize = 4; // Milliseconds before we hide the status bubble widget when you mouseout. const int kHideDelay = 250; -// Reverses a point in RTL mode. -GdkPoint MakeBidiGdkPoint(gint x, gint y, gint width, bool ltr) { - GdkPoint point = {ltr ? x : width - x, y}; - return point; -} - enum FrameType { FRAME_MASK, FRAME_STROKE, @@ -48,6 +42,7 @@ enum FrameType { std::vector<GdkPoint> MakeFramePolygonPoints(int width, int height, FrameType type) { + using gtk_util::MakeBidiGdkPoint; std::vector<GdkPoint> points; bool ltr = l10n_util::GetTextDirection() == l10n_util::LEFT_TO_RIGHT; diff --git a/chrome/common/gtk_util.cc b/chrome/common/gtk_util.cc index c97a3a5..661517e 100644 --- a/chrome/common/gtk_util.cc +++ b/chrome/common/gtk_util.cc @@ -501,4 +501,9 @@ gfx::Point ClientPoint(GtkWidget* widget) { return gfx::Point(x, y); } +GdkPoint MakeBidiGdkPoint(gint x, gint y, gint width, bool ltr) { + GdkPoint point = {ltr ? x : width - x, y}; + return point; +} + } // namespace gtk_util diff --git a/chrome/common/gtk_util.h b/chrome/common/gtk_util.h index 867dbc5..556e77f 100644 --- a/chrome/common/gtk_util.h +++ b/chrome/common/gtk_util.h @@ -156,6 +156,10 @@ gfx::Point ScreenPoint(GtkWidget* widget); // Get the current location of the mouse cursor relative to the widget. gfx::Point ClientPoint(GtkWidget* widget); +// Reverses a point in RTL mode. Used in making vectors of GdkPoints for window +// shapes. +GdkPoint MakeBidiGdkPoint(gint x, gint y, gint width, bool ltr); + } // namespace gtk_util #endif // CHROME_COMMON_GTK_UTIL_H_ |