| Index: chrome/browser/ui/gtk/rounded_window.cc
|
| diff --git a/chrome/browser/ui/gtk/rounded_window.cc b/chrome/browser/ui/gtk/rounded_window.cc
|
| deleted file mode 100644
|
| index ded87a9b3388a20c9e14db732ec1e9ae75a08e77..0000000000000000000000000000000000000000
|
| --- a/chrome/browser/ui/gtk/rounded_window.cc
|
| +++ /dev/null
|
| @@ -1,326 +0,0 @@
|
| -// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "chrome/browser/ui/gtk/rounded_window.h"
|
| -
|
| -#include <gtk/gtk.h>
|
| -#include <math.h>
|
| -
|
| -#include "base/i18n/rtl.h"
|
| -#include "base/logging.h"
|
| -#include "chrome/browser/ui/gtk/gtk_util.h"
|
| -#include "ui/base/gtk/gtk_signal_registrar.h"
|
| -#include "ui/gfx/gtk_compat.h"
|
| -
|
| -namespace gtk_util {
|
| -
|
| -namespace {
|
| -
|
| -const char* kRoundedData = "rounded-window-data";
|
| -
|
| -// If the border radius is less than |kMinRoundedBorderSize|, we don't actually
|
| -// round the corners, we just truncate the corner.
|
| -const int kMinRoundedBorderSize = 8;
|
| -
|
| -struct RoundedWindowData {
|
| - // Expected window size. Used to detect when we need to reshape the window.
|
| - int expected_width;
|
| - int expected_height;
|
| -
|
| - // Color of the border.
|
| - GdkColor border_color;
|
| -
|
| - // Radius of the edges in pixels.
|
| - int corner_size;
|
| -
|
| - // Which corners should be rounded?
|
| - int rounded_edges;
|
| -
|
| - // Which sides of the window should have an internal border?
|
| - int drawn_borders;
|
| -
|
| - // Keeps track of attached signal handlers.
|
| - ui::GtkSignalRegistrar signals;
|
| -};
|
| -
|
| -// Callback from GTK to release allocated memory.
|
| -void FreeRoundedWindowData(gpointer data) {
|
| - delete static_cast<RoundedWindowData*>(data);
|
| -}
|
| -
|
| -enum FrameType {
|
| - FRAME_MASK,
|
| - FRAME_STROKE,
|
| -};
|
| -
|
| -// Returns a list of points that either form the outline of the status bubble
|
| -// (|type| == FRAME_MASK) or form the inner border around the inner edge
|
| -// (|type| == FRAME_STROKE).
|
| -std::vector<GdkPoint> MakeFramePolygonPoints(RoundedWindowData* data,
|
| - FrameType type) {
|
| - using gtk_util::MakeBidiGdkPoint;
|
| - int width = data->expected_width;
|
| - int height = data->expected_height;
|
| - int corner_size = data->corner_size;
|
| -
|
| - std::vector<GdkPoint> points;
|
| -
|
| - bool ltr = !base::i18n::IsRTL();
|
| - // 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;
|
| -
|
| - // Build up points starting with the bottom left corner and continuing
|
| - // clockwise.
|
| -
|
| - // Bottom left corner.
|
| - if (type == FRAME_MASK ||
|
| - (data->drawn_borders & (BORDER_LEFT | BORDER_BOTTOM))) {
|
| - if (data->rounded_edges & ROUNDED_BOTTOM_LEFT) {
|
| - if (corner_size >= kMinRoundedBorderSize) {
|
| - // We are careful to only add points that are horizontal or vertically
|
| - // offset from the previous point (not both). This avoids rounding
|
| - // differences when two points are connected.
|
| - for (int x = 0; x <= corner_size; ++x) {
|
| - int y = static_cast<int>(sqrt(static_cast<double>(
|
| - (corner_size * corner_size) - (x * x))));
|
| - if (x > 0) {
|
| - points.push_back(MakeBidiGdkPoint(
|
| - corner_size - x + x_off_r + 1,
|
| - height - (corner_size - y) + y_off, width, ltr));
|
| - }
|
| - points.push_back(MakeBidiGdkPoint(
|
| - corner_size - x + x_off_r,
|
| - height - (corner_size - y) + y_off, width, ltr));
|
| - }
|
| - } else {
|
| - points.push_back(MakeBidiGdkPoint(
|
| - corner_size + x_off_l, height + y_off, width, ltr));
|
| - points.push_back(MakeBidiGdkPoint(
|
| - x_off_r, height - corner_size, width, ltr));
|
| - }
|
| - } else {
|
| - points.push_back(MakeBidiGdkPoint(x_off_r, height + y_off, width, ltr));
|
| - }
|
| - }
|
| -
|
| - // Top left corner.
|
| - if (type == FRAME_MASK ||
|
| - (data->drawn_borders & (BORDER_LEFT | BORDER_TOP))) {
|
| - if (data->rounded_edges & ROUNDED_TOP_LEFT) {
|
| - if (corner_size >= kMinRoundedBorderSize) {
|
| - for (int x = corner_size; x >= 0; --x) {
|
| - int y = static_cast<int>(sqrt(static_cast<double>(
|
| - (corner_size * corner_size) - (x * x))));
|
| - points.push_back(MakeBidiGdkPoint(corner_size - x + x_off_r,
|
| - corner_size - y, width, ltr));
|
| - if (x > 0) {
|
| - points.push_back(MakeBidiGdkPoint(corner_size - x + 1 + x_off_r,
|
| - corner_size - y, width, ltr));
|
| - }
|
| - }
|
| - } else {
|
| - points.push_back(MakeBidiGdkPoint(
|
| - x_off_r, corner_size - 1, width, ltr));
|
| - points.push_back(MakeBidiGdkPoint(
|
| - corner_size + x_off_r - 1, 0, width, ltr));
|
| - }
|
| - } else {
|
| - points.push_back(MakeBidiGdkPoint(x_off_r, 0, width, ltr));
|
| - }
|
| - }
|
| -
|
| - // Top right corner.
|
| - if (type == FRAME_MASK ||
|
| - (data->drawn_borders & (BORDER_TOP | BORDER_RIGHT))) {
|
| - if (data->rounded_edges & ROUNDED_TOP_RIGHT) {
|
| - if (corner_size >= kMinRoundedBorderSize) {
|
| - for (int x = 0; x <= corner_size; ++x) {
|
| - int y = static_cast<int>(sqrt(static_cast<double>(
|
| - (corner_size * corner_size) - (x * x))));
|
| - if (x > 0) {
|
| - points.push_back(MakeBidiGdkPoint(
|
| - width - (corner_size - x) + x_off_l - 1,
|
| - corner_size - y, width, ltr));
|
| - }
|
| - points.push_back(MakeBidiGdkPoint(
|
| - width - (corner_size - x) + x_off_l,
|
| - corner_size - y, width, ltr));
|
| - }
|
| - } else {
|
| - points.push_back(MakeBidiGdkPoint(
|
| - width - corner_size + 1 + x_off_l, 0, width, ltr));
|
| - points.push_back(MakeBidiGdkPoint(
|
| - width + x_off_l, corner_size - 1, width, ltr));
|
| - }
|
| - } else {
|
| - points.push_back(MakeBidiGdkPoint(
|
| - width + x_off_l, 0, width, ltr));
|
| - }
|
| - }
|
| -
|
| - // Bottom right corner.
|
| - if (type == FRAME_MASK ||
|
| - (data->drawn_borders & (BORDER_RIGHT | BORDER_BOTTOM))) {
|
| - if (data->rounded_edges & ROUNDED_BOTTOM_RIGHT) {
|
| - if (corner_size >= kMinRoundedBorderSize) {
|
| - for (int x = corner_size; x >= 0; --x) {
|
| - int y = static_cast<int>(sqrt(static_cast<double>(
|
| - (corner_size * corner_size) - (x * x))));
|
| - points.push_back(MakeBidiGdkPoint(
|
| - width - (corner_size - x) + x_off_l,
|
| - height - (corner_size - y) + y_off, width, ltr));
|
| - if (x > 0) {
|
| - points.push_back(MakeBidiGdkPoint(
|
| - width - (corner_size - x) + x_off_l - 1,
|
| - height - (corner_size - y) + y_off, width, ltr));
|
| - }
|
| - }
|
| - } else {
|
| - points.push_back(MakeBidiGdkPoint(
|
| - width + x_off_l, height - corner_size, width, ltr));
|
| - points.push_back(MakeBidiGdkPoint(
|
| - width - corner_size + x_off_r, height + y_off, width, ltr));
|
| - }
|
| - } else {
|
| - points.push_back(MakeBidiGdkPoint(
|
| - width + x_off_l, height + y_off, width, ltr));
|
| - }
|
| - }
|
| -
|
| - return points;
|
| -}
|
| -
|
| -// Set the window shape in needed, lets our owner do some drawing (if it wants
|
| -// to), and finally draw the border.
|
| -gboolean OnRoundedWindowExpose(GtkWidget* widget,
|
| - GdkEventExpose* event) {
|
| - RoundedWindowData* data = static_cast<RoundedWindowData*>(
|
| - g_object_get_data(G_OBJECT(widget), kRoundedData));
|
| -
|
| - GtkAllocation allocation;
|
| - gtk_widget_get_allocation(widget, &allocation);
|
| -
|
| - if (data->expected_width != allocation.width ||
|
| - data->expected_height != allocation.height) {
|
| - data->expected_width = allocation.width;
|
| - data->expected_height = allocation.height;
|
| -
|
| - // We need to update the shape of the status bubble whenever our GDK
|
| - // window changes shape.
|
| - std::vector<GdkPoint> mask_points = MakeFramePolygonPoints(
|
| - data, FRAME_MASK);
|
| - GdkRegion* mask_region = gdk_region_polygon(&mask_points[0],
|
| - mask_points.size(),
|
| - GDK_EVEN_ODD_RULE);
|
| - gdk_window_shape_combine_region(gtk_widget_get_window(widget),
|
| - mask_region, 0, 0);
|
| - gdk_region_destroy(mask_region);
|
| - }
|
| -
|
| - GdkDrawable* drawable = GDK_DRAWABLE(event->window);
|
| - GdkGC* gc = gdk_gc_new(drawable);
|
| - gdk_gc_set_clip_rectangle(gc, &event->area);
|
| - gdk_gc_set_rgb_fg_color(gc, &data->border_color);
|
| -
|
| - // Stroke the frame border.
|
| - std::vector<GdkPoint> points = MakeFramePolygonPoints(
|
| - data, FRAME_STROKE);
|
| - if (data->drawn_borders == BORDER_ALL) {
|
| - // If we want to have borders everywhere, we need to draw a polygon instead
|
| - // of a set of lines.
|
| - gdk_draw_polygon(drawable, gc, FALSE, &points[0], points.size());
|
| - } else if (!points.empty()) {
|
| - gdk_draw_lines(drawable, gc, &points[0], points.size());
|
| - }
|
| -
|
| - g_object_unref(gc);
|
| - return FALSE; // Propagate so our children paint, etc.
|
| -}
|
| -
|
| -// On theme changes, window shapes are reset, but we detect whether we need to
|
| -// reshape a window by whether its allocation has changed so force it to reset
|
| -// the window shape on next expose.
|
| -void OnStyleSet(GtkWidget* widget, GtkStyle* previous_style) {
|
| - DCHECK(widget);
|
| - RoundedWindowData* data = static_cast<RoundedWindowData*>(
|
| - g_object_get_data(G_OBJECT(widget), kRoundedData));
|
| - DCHECK(data);
|
| - data->expected_width = -1;
|
| - data->expected_height = -1;
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -void ActAsRoundedWindow(
|
| - GtkWidget* widget, const GdkColor& color, int corner_size,
|
| - int rounded_edges, int drawn_borders) {
|
| - DCHECK(widget);
|
| - DCHECK(!g_object_get_data(G_OBJECT(widget), kRoundedData));
|
| -
|
| - gtk_widget_set_app_paintable(widget, TRUE);
|
| -
|
| - RoundedWindowData* data = new RoundedWindowData;
|
| - data->signals.Connect(widget, "expose-event",
|
| - G_CALLBACK(OnRoundedWindowExpose), NULL);
|
| - data->signals.Connect(widget, "style-set", G_CALLBACK(OnStyleSet), NULL);
|
| -
|
| - data->expected_width = -1;
|
| - data->expected_height = -1;
|
| -
|
| - data->border_color = color;
|
| - data->corner_size = corner_size;
|
| -
|
| - data->rounded_edges = rounded_edges;
|
| - data->drawn_borders = drawn_borders;
|
| -
|
| - g_object_set_data_full(G_OBJECT(widget), kRoundedData,
|
| - data, FreeRoundedWindowData);
|
| -
|
| - if (gtk_widget_get_visible(widget))
|
| - gtk_widget_queue_draw(widget);
|
| -}
|
| -
|
| -void StopActingAsRoundedWindow(GtkWidget* widget) {
|
| - g_object_set_data(G_OBJECT(widget), kRoundedData, NULL);
|
| -
|
| - if (gtk_widget_get_realized(widget))
|
| - gdk_window_shape_combine_mask(gtk_widget_get_window(widget), NULL, 0, 0);
|
| -
|
| - if (gtk_widget_get_visible(widget))
|
| - gtk_widget_queue_draw(widget);
|
| -}
|
| -
|
| -bool IsActingAsRoundedWindow(GtkWidget* widget) {
|
| - return g_object_get_data(G_OBJECT(widget), kRoundedData) != NULL;
|
| -}
|
| -
|
| -void SetRoundedWindowEdgesAndBorders(GtkWidget* widget,
|
| - int corner_size,
|
| - int rounded_edges,
|
| - int drawn_borders) {
|
| - DCHECK(widget);
|
| - RoundedWindowData* data = static_cast<RoundedWindowData*>(
|
| - g_object_get_data(G_OBJECT(widget), kRoundedData));
|
| - DCHECK(data);
|
| - data->corner_size = corner_size;
|
| - data->rounded_edges = rounded_edges;
|
| - data->drawn_borders = drawn_borders;
|
| -}
|
| -
|
| -void SetRoundedWindowBorderColor(GtkWidget* widget, GdkColor color) {
|
| - DCHECK(widget);
|
| - RoundedWindowData* data = static_cast<RoundedWindowData*>(
|
| - g_object_get_data(G_OBJECT(widget), kRoundedData));
|
| - DCHECK(data);
|
| - data->border_color = color;
|
| -}
|
| -
|
| -} // namespace gtk_util
|
|
|