bubble_window.cc revision 72a454cd3513ac24fbdd0e0cb9ad70b86a99b801
1// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/chromeos/frame/bubble_window.h" 6 7#include <gtk/gtk.h> 8 9#include "chrome/browser/chromeos/frame/bubble_frame_view.h" 10#include "chrome/browser/chromeos/wm_ipc.h" 11#include "third_party/cros/chromeos_wm_ipc_enums.h" 12#include "ui/gfx/skia_utils_gtk.h" 13#include "views/window/non_client_view.h" 14 15namespace chromeos { 16 17bool IsInsideCircle(int x0, int y0, int x1, int y1, int r) { 18 return (x0 - x1) * (x0 - x1) + (y0 - y1) * (y0 - y1) <= r * r; 19} 20 21void SetRegionUnionWithPoint(int i, int j, GdkRegion* region) { 22 GdkRectangle rect = {i, j, 1, 1}; 23 gdk_region_union_with_rect(region, &rect); 24} 25 26// static 27const SkColor BubbleWindow::kBackgroundColor = SK_ColorWHITE; 28 29BubbleWindow::BubbleWindow(views::WindowDelegate* window_delegate) 30 : views::WindowGtk(window_delegate) { 31 MakeTransparent(); 32} 33 34void BubbleWindow::Init(GtkWindow* parent, const gfx::Rect& bounds) { 35 views::WindowGtk::Init(parent, bounds); 36 37 // Turn on double buffering so that the hosted GtkWidgets does not 38 // flash as in http://crosbug.com/9065. 39 EnableDoubleBuffer(true); 40 41 GdkColor background_color = gfx::SkColorToGdkColor(kBackgroundColor); 42 gtk_widget_modify_bg(GetNativeView(), GTK_STATE_NORMAL, &background_color); 43 44 // A work-around for http://crosbug.com/8538. All GdkWidnow of top-level 45 // GtkWindow should participate _NET_WM_SYNC_REQUEST protocol and window 46 // manager should only show the window after getting notified. And we 47 // should only notify window manager after at least one paint is done. 48 // TODO(xiyuan): Figure out the right fix. 49 gtk_widget_realize(GetNativeView()); 50 gdk_window_set_back_pixmap(GetNativeView()->window, NULL, FALSE); 51 gtk_widget_realize(window_contents()); 52 gdk_window_set_back_pixmap(window_contents()->window, NULL, FALSE); 53} 54 55void BubbleWindow::TrimMargins(int margin_left, int margin_right, 56 int margin_top, int margin_bottom, 57 int border_radius) { 58 gfx::Size size = GetNonClientView()->GetPreferredSize(); 59 const int w = size.width() - margin_left - margin_right; 60 const int h = size.height() - margin_top - margin_bottom; 61 GdkRectangle rect0 = {0, border_radius, w, h - 2 * border_radius}; 62 GdkRectangle rect1 = {border_radius, 0, w - 2 * border_radius, h}; 63 GdkRegion* region = gdk_region_rectangle(&rect0); 64 gdk_region_union_with_rect(region, &rect1); 65 66 // Top Left 67 for (int i = 0; i < border_radius; ++i) { 68 for (int j = 0; j < border_radius; ++j) { 69 if (IsInsideCircle(i + 0.5, j + 0.5, border_radius, border_radius, 70 border_radius)) { 71 SetRegionUnionWithPoint(i, j, region); 72 } 73 } 74 } 75 // Top Right 76 for (int i = w - border_radius - 1; i < w; ++i) { 77 for (int j = 0; j < border_radius; ++j) { 78 if (IsInsideCircle(i + 0.5, j + 0.5, w - border_radius - 1, 79 border_radius, border_radius)) { 80 SetRegionUnionWithPoint(i, j, region); 81 } 82 } 83 } 84 // Bottom Left 85 for (int i = 0; i < border_radius; ++i) { 86 for (int j = h - border_radius - 1; j < h; ++j) { 87 if (IsInsideCircle(i + 0.5, j + 0.5, border_radius, h - border_radius - 1, 88 border_radius)) { 89 SetRegionUnionWithPoint(i, j, region); 90 } 91 } 92 } 93 // Bottom Right 94 for (int i = w - border_radius - 1; i < w; ++i) { 95 for (int j = h - border_radius - 1; j < h; ++j) { 96 if (IsInsideCircle(i + 0.5, j + 0.5, w - border_radius - 1, 97 h - border_radius - 1, border_radius)) { 98 SetRegionUnionWithPoint(i, j, region); 99 } 100 } 101 } 102 103 gdk_window_shape_combine_region(window_contents()->window, region, 104 margin_left, margin_top); 105 gdk_region_destroy(region); 106} 107 108views::Window* BubbleWindow::Create( 109 gfx::NativeWindow parent, 110 const gfx::Rect& bounds, 111 Style style, 112 views::WindowDelegate* window_delegate) { 113 BubbleWindow* window = new BubbleWindow(window_delegate); 114 window->GetNonClientView()->SetFrameView(new BubbleFrameView(window, style)); 115 window->Init(parent, bounds); 116 117 if (style == STYLE_XSHAPE) { 118 const int kMarginLeft = 14; 119 const int kMarginRight = 14; 120 const int kMarginTop = 12; 121 const int kMarginBottom = 16; 122 const int kBorderRadius = 8; 123 window->TrimMargins(kMarginLeft, kMarginRight, kMarginTop, kMarginBottom, 124 kBorderRadius); 125 } 126 127 return window; 128} 129 130} // namespace chromeos 131