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 3 // found in the LICENSE file. 4 5 #include <gtk/gtk.h> 6 7 #include "base/memory/scoped_ptr.h" 8 #include "chrome/browser/ui/browser.h" 9 #include "chrome/browser/ui/browser_window.h" 10 #include "chrome/browser/ui/gtk/browser_window_gtk.h" 11 #include "chrome/browser/ui/gtk/bubble/bubble_gtk.h" 12 #include "chrome/browser/ui/gtk/gtk_theme_service.h" 13 #include "chrome/browser/ui/gtk/gtk_util.h" 14 #include "chrome/test/base/in_process_browser_test.h" 15 #include "ui/base/gtk/gtk_hig_constants.h" 16 17 class BubbleGtkTest : public InProcessBrowserTest, 18 public BubbleDelegateGtk { 19 public: 20 BubbleGtkTest() : browser_window_(NULL) { 21 } 22 23 virtual ~BubbleGtkTest() { 24 } 25 26 // BubbleDelegateGtk implementation. 27 virtual void BubbleClosing(BubbleGtk* bubble, 28 bool closed_by_escape) OVERRIDE { 29 } 30 31 Profile* GetProfile() { 32 return browser()->profile(); 33 } 34 35 GtkWidget* GetNativeBrowserWindow() { 36 if (!browser_window_) 37 browser_window_ = GTK_WIDGET(browser()->window()->GetNativeWindow()); 38 return browser_window_; 39 } 40 41 private: 42 GtkWidget* browser_window_; 43 }; 44 45 // Tests that we can adjust a bubble arrow so we can show a bubble without being 46 // clipped. This test verifies the following four issues: 47 // 1. Shows a bubble to the top-left corner and see its frame style always 48 // becomes ANCHOR_TOP_LEFT. 49 // 2. Shows a bubble to the top-right corner and see its frame style always 50 // becomes ANCHOR_TOP_RIGHT. 51 // 3. Shows a bubble to the bottom-left corner and see its frame style always 52 // becomes ANCHOR_BOTTOM_LEFT. 53 // 4. Shows a bubble to the top-left corner and see its frame style always 54 // becomes ANCHOR_BOTTOM_RIGHT. 55 IN_PROC_BROWSER_TEST_F(BubbleGtkTest, ArrowLocation) { 56 int width = gdk_screen_get_width(gdk_screen_get_default()); 57 int height = gdk_screen_get_height(gdk_screen_get_default()); 58 struct { 59 int x, y; 60 BubbleGtk::FrameStyle expected; 61 } points[] = { 62 {0, 0, BubbleGtk::ANCHOR_TOP_LEFT}, 63 {width - 1, 0, BubbleGtk::ANCHOR_TOP_RIGHT}, 64 {0, height - 1, BubbleGtk::ANCHOR_BOTTOM_LEFT}, 65 {width - 1, height - 1, BubbleGtk::ANCHOR_BOTTOM_RIGHT}, 66 }; 67 static const BubbleGtk::FrameStyle kPreferredLocations[] = { 68 BubbleGtk::ANCHOR_TOP_LEFT, 69 BubbleGtk::ANCHOR_TOP_RIGHT, 70 BubbleGtk::ANCHOR_BOTTOM_LEFT, 71 BubbleGtk::ANCHOR_BOTTOM_RIGHT, 72 }; 73 74 GtkWidget* anchor = GetNativeBrowserWindow(); 75 GtkThemeService* theme_service = GtkThemeService::GetFrom(GetProfile()); 76 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(points); ++i) { 77 for (size_t j = 0; j < arraysize(kPreferredLocations); ++j) { 78 static const char kText[] = 79 "Google's mission is to organize the world's information and make it" 80 " universally accessible and useful."; 81 GtkWidget* label = theme_service->BuildLabel(kText, ui::kGdkBlack); 82 gfx::Rect rect(points[i].x, points[i].y, 0, 0); 83 BubbleGtk* bubble = BubbleGtk::Show(anchor, 84 &rect, 85 label, 86 kPreferredLocations[j], 87 BubbleGtk::MATCH_SYSTEM_THEME | 88 BubbleGtk::POPUP_WINDOW | 89 BubbleGtk::GRAB_INPUT, 90 theme_service, 91 this); 92 EXPECT_EQ(points[i].expected, bubble->actual_frame_style_); 93 bubble->Close(); 94 } 95 } 96 } 97 98 IN_PROC_BROWSER_TEST_F(BubbleGtkTest, NoArrow) { 99 int width = gdk_screen_get_width(gdk_screen_get_default()); 100 int height = gdk_screen_get_height(gdk_screen_get_default()); 101 struct { 102 int x, y; 103 BubbleGtk::FrameStyle expected; 104 } points[] = { 105 {0, 0, BubbleGtk::FLOAT_BELOW_RECT}, 106 {width - 1, 0, BubbleGtk::FLOAT_BELOW_RECT}, 107 {0, height - 1, BubbleGtk::CENTER_OVER_RECT}, 108 {width - 1, height - 1, BubbleGtk::CENTER_OVER_RECT}, 109 }; 110 static const BubbleGtk::FrameStyle kPreferredLocations[] = { 111 BubbleGtk::FLOAT_BELOW_RECT, 112 BubbleGtk::CENTER_OVER_RECT, 113 }; 114 115 GtkWidget* anchor = GetNativeBrowserWindow(); 116 GtkThemeService* theme_service = GtkThemeService::GetFrom(GetProfile()); 117 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(points); ++i) { 118 for (size_t j = 0; j < arraysize(kPreferredLocations); ++j) { 119 static const char kText[] = 120 "Google's mission is to organize the world's information and make it" 121 " universally accessible and useful."; 122 GtkWidget* label = theme_service->BuildLabel(kText, ui::kGdkBlack); 123 gfx::Rect rect(points[i].x, points[i].y, 0, 0); 124 BubbleGtk* bubble = BubbleGtk::Show(anchor, 125 &rect, 126 label, 127 kPreferredLocations[j], 128 BubbleGtk::MATCH_SYSTEM_THEME | 129 BubbleGtk::POPUP_WINDOW | 130 BubbleGtk::GRAB_INPUT, 131 theme_service, 132 this); 133 EXPECT_EQ(points[i].expected, bubble->actual_frame_style_); 134 bubble->Close(); 135 } 136 } 137 } 138