bubble.cc revision ddb351dbec246cf1fab5ec20d2d5520909041de1
1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Use of this source code is governed by a BSD-style license that can be 3ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// found in the LICENSE file. 4ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 5ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/views/bubble/bubble.h" 6ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 7ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include <vector> 8ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 9ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/views/bubble/border_contents.h" 10ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_service.h" 11ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "ui/base/animation/slide_animation.h" 12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "ui/base/keycodes/keyboard_codes.h" 13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "ui/gfx/color_utils.h" 14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "views/layout/fill_layout.h" 15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "views/widget/root_view.h" 16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "views/widget/widget.h" 17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "views/window/client_view.h" 18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "views/window/window.h" 19ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 20ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#if defined(OS_CHROMEOS) 21ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/chromeos/wm_ipc.h" 22ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "third_party/cros/chromeos_wm_ipc_enums.h" 23ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#endif 24ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 25ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#if defined(OS_WIN) 26ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/views/bubble/border_widget_win.h" 27ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#endif 28ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 29ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenusing std::vector; 30ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 31ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// How long the fade should last for. 32ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstatic const int kHideFadeDurationMS = 200; 33ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 34ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Background color of the bubble. 35ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#if defined(OS_WIN) 36ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst SkColor Bubble::kBackgroundColor = 37ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen color_utils::GetSysSkColor(COLOR_WINDOW); 38ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#else 39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// TODO(beng): source from theme provider. 40ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst SkColor Bubble::kBackgroundColor = SK_ColorWHITE; 41ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#endif 42ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 43ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// BubbleDelegate --------------------------------------------------------- 44ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 45ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstd::wstring BubbleDelegate::accessible_name() { 46ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return L""; 47ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 48ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 49ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Bubble ----------------------------------------------------------------- 50ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 51ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// static 52ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenBubble* Bubble::Show(views::Widget* parent, 53ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const gfx::Rect& position_relative_to, 54ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BubbleBorder::ArrowLocation arrow_location, 55ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen views::View* contents, 56ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BubbleDelegate* delegate) { 57ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Bubble* bubble = new Bubble; 58ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bubble->InitBubble(parent, position_relative_to, arrow_location, 59ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen contents, delegate); 60ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return bubble; 61ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 62ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 63ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#if defined(OS_CHROMEOS) 64ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// static 65ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenBubble* Bubble::ShowFocusless( 66ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen views::Widget* parent, 67ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const gfx::Rect& position_relative_to, 68ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BubbleBorder::ArrowLocation arrow_location, 69ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen views::View* contents, 70ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BubbleDelegate* delegate, 71ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool show_while_screen_is_locked) { 72ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Bubble* bubble = new Bubble(views::WidgetGtk::TYPE_POPUP, 73ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen show_while_screen_is_locked); 74ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bubble->InitBubble(parent, position_relative_to, arrow_location, 75ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen contents, delegate); 76ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return bubble; 77ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 78ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#endif 79ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 80ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid Bubble::Close() { 81ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (show_status_ != kOpen) 82ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 83ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 84ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen show_status_ = kClosing; 85ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 86ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (fade_away_on_close_) 87ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FadeOut(); 88ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen else 89ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DoClose(false); 90ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 91ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 92ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid Bubble::AnimationEnded(const ui::Animation* animation) { 93ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (static_cast<int>(animation_->GetCurrentValue()) == 0) { 94ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // When fading out we just need to close the bubble at the end 95ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DoClose(false); 96ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 97ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#if defined(OS_WIN) 98ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // When fading in we need to remove the layered window style flag, since 99ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // that style prevents some bubble content from working properly. 100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SetWindowLong(GWL_EXSTYLE, GetWindowLong(GWL_EXSTYLE) & ~WS_EX_LAYERED); 101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#endif 102ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 103ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 104ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 105ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid Bubble::AnimationProgressed(const ui::Animation* animation) { 106ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#if defined(OS_WIN) 107ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Set the opacity for the main contents window. 108ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen unsigned char opacity = static_cast<unsigned char>( 109ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen animation_->GetCurrentValue() * 255); 110ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SetLayeredWindowAttributes(GetNativeView(), 0, 111ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen static_cast<byte>(opacity), LWA_ALPHA); 112ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen contents_->SchedulePaint(); 113ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Also fade in/out the bubble border window. 115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen border_->SetOpacity(opacity); 116ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen border_->border_contents()->SchedulePaint(); 117ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#else 118ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NOTIMPLEMENTED(); 119ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#endif 120ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 121ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 122ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenBubble::Bubble() 123ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen : 124ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#if defined(OS_LINUX) 125ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen WidgetGtk(TYPE_WINDOW), 126ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen border_contents_(NULL), 127ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#elif defined(OS_WIN) 128ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen border_(NULL), 129ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#endif 130ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen delegate_(NULL), 131ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen show_status_(kOpen), 132ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen fade_away_on_close_(false), 133ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#if defined(OS_CHROMEOS) 134ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen show_while_screen_is_locked_(false), 135ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#endif 136ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen arrow_location_(BubbleBorder::NONE), 137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen contents_(NULL) { 138ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 139ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 140ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#if defined(OS_CHROMEOS) 141ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenBubble::Bubble(views::WidgetGtk::Type type, bool show_while_screen_is_locked) 142ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen : WidgetGtk(type), 143ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen border_contents_(NULL), 144ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen delegate_(NULL), 145ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen show_status_(kOpen), 146ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen fade_away_on_close_(false), 147ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen show_while_screen_is_locked_(show_while_screen_is_locked), 148ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen arrow_location_(BubbleBorder::NONE), 149ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen contents_(NULL) { 150ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 151ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#endif 152ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 153ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenBubble::~Bubble() { 154ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 155ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 156ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid Bubble::InitBubble(views::Widget* parent, 157ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const gfx::Rect& position_relative_to, 158ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BubbleBorder::ArrowLocation arrow_location, 159ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen views::View* contents, 160ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BubbleDelegate* delegate) { 161ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen delegate_ = delegate; 162ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen position_relative_to_ = position_relative_to; 163ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen arrow_location_ = arrow_location; 164ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen contents_ = contents; 165ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 166ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Create the main window. 167ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#if defined(OS_WIN) 168ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen views::Window* parent_window = parent->GetWindow(); 169ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (parent_window) 170ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen parent_window->DisableInactiveRendering(); 171ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen set_window_style(WS_POPUP | WS_CLIPCHILDREN); 172ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int extended_style = WS_EX_TOOLWINDOW; 173ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // During FadeIn we need to turn on the layered window style to deal with 174ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // transparency. This flag needs to be reset after fading in is complete. 175ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool fade_in = delegate_ && delegate_->FadeInOnShow(); 176ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (fade_in) 177ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen extended_style |= WS_EX_LAYERED; 178ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen set_window_ex_style(extended_style); 179ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 180ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(!border_); 181ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen border_ = new BorderWidgetWin(); 182ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 183ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (fade_in) { 184ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen border_->SetOpacity(0); 185ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SetOpacity(0); 186ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 187ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 188ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen border_->Init(CreateBorderContents(), parent->GetNativeView()); 189ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen border_->border_contents()->SetBackgroundColor(kBackgroundColor); 190ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 191ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // We make the BorderWidgetWin the owner of the Bubble HWND, so that the 192ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // latter is displayed on top of the former. 193ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen WidgetWin::Init(border_->GetNativeView(), gfx::Rect()); 194ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 195ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SetWindowText(GetNativeView(), delegate_->accessible_name().c_str()); 196ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#elif defined(OS_LINUX) 197ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen MakeTransparent(); 198ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen make_transient_to_parent(); 199ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen WidgetGtk::InitWithWidget(parent, gfx::Rect()); 200ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#if defined(OS_CHROMEOS) 201ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen { 202ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen vector<int> params; 203ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen params.push_back(show_while_screen_is_locked_ ? 1 : 0); 204ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen chromeos::WmIpc::instance()->SetWindowType( 205ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GetNativeView(), 206ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen chromeos::WM_IPC_WINDOW_CHROME_INFO_BUBBLE, 207ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ¶ms); 208ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 209ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#endif 210ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#endif 211ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 212ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Create a View to hold the contents of the main window. 213ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen views::View* contents_view = new views::View; 214ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // We add |contents_view| to ourselves before the AddChildView() call below so 215ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // that when |contents| gets added, it will already have a widget, and thus 216ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // any NativeButtons it creates in ViewHierarchyChanged() will be functional 217ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // (e.g. calling SetChecked() on checkboxes is safe). 218ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SetContentsView(contents_view); 219ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Adding |contents| as a child has to be done before we call 220ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // contents->GetPreferredSize() below, since some supplied views don't 221ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // actually initialize themselves until they're added to a hierarchy. 222ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen contents_view->AddChildView(contents); 223ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 224ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Calculate and set the bounds for all windows and views. 225ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen gfx::Rect window_bounds; 226ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 227ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#if defined(OS_WIN) 228ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Initialize and position the border window. 229ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen window_bounds = border_->SizeAndGetBounds(position_relative_to, 230ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen arrow_location, 231ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen contents->GetPreferredSize()); 232ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 233ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Make |contents| take up the entire contents view. 234ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen contents_view->SetLayoutManager(new views::FillLayout); 235ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 236ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Paint the background color behind the contents. 237ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen contents_view->set_background( 238ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen views::Background::CreateSolidBackground(kBackgroundColor)); 239ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#else 240ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Create a view to paint the border and background. 241ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen border_contents_ = CreateBorderContents(); 242ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen border_contents_->Init(); 243ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen border_contents_->SetBackgroundColor(kBackgroundColor); 244ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen gfx::Rect contents_bounds; 245ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen border_contents_->SizeAndGetBounds(position_relative_to, 246ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen arrow_location, false, contents->GetPreferredSize(), 247ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &contents_bounds, &window_bounds); 248ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // This new view must be added before |contents| so it will paint under it. 249ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen contents_view->AddChildViewAt(border_contents_, 0); 250ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 251ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // |contents_view| has no layout manager, so we have to explicitly position 252ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // its children. 253ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen border_contents_->SetBoundsRect( 254ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen gfx::Rect(gfx::Point(), window_bounds.size())); 255ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen contents->SetBoundsRect(contents_bounds); 256ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#endif 257ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SetBounds(window_bounds); 258ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 259ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Register the Escape accelerator for closing. 260ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GetFocusManager()->RegisterAccelerator( 261ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen views::Accelerator(ui::VKEY_ESCAPE, false, false, false), this); 262ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 263ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Done creating the bubble. 264ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NotificationService::current()->Notify(NotificationType::INFO_BUBBLE_CREATED, 265ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Source<Bubble>(this), 266ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NotificationService::NoDetails()); 267ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 268ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Show the window. 269ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#if defined(OS_WIN) 270ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen border_->ShowWindow(SW_SHOW); 271ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ShowWindow(SW_SHOW); 272ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (fade_in) 273ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FadeIn(); 274ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#elif defined(OS_LINUX) 275ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen views::WidgetGtk::Show(); 276ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#endif 277ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 278ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 279ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenBorderContents* Bubble::CreateBorderContents() { 280ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return new BorderContents(); 281ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 282ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 283ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid Bubble::SizeToContents() { 284ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen gfx::Rect window_bounds; 285ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 286ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#if defined(OS_WIN) 287ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Initialize and position the border window. 288ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen window_bounds = border_->SizeAndGetBounds(position_relative_to_, 289ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen arrow_location_, 290ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen contents_->GetPreferredSize()); 291ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#else 292ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen gfx::Rect contents_bounds; 293ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen border_contents_->SizeAndGetBounds(position_relative_to_, 294ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen arrow_location_, false, contents_->GetPreferredSize(), 295ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &contents_bounds, &window_bounds); 296ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // |contents_view| has no layout manager, so we have to explicitly position 297ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // its children. 298ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen border_contents_->SetBoundsRect( 299ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen gfx::Rect(gfx::Point(), window_bounds.size())); 300ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen contents_->SetBoundsRect(contents_bounds); 301ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#endif 302ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SetBounds(window_bounds); 303ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 304ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 305ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#if defined(OS_WIN) 306ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid Bubble::OnActivate(UINT action, BOOL minimized, HWND window) { 307ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // The popup should close when it is deactivated. 308ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (action == WA_INACTIVE) { 309ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Close(); 310ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else if (action == WA_ACTIVE) { 311ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(GetRootView()->has_children()); 312ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GetRootView()->GetChildViewAt(0)->RequestFocus(); 313ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 314ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 315ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#elif defined(OS_LINUX) 316ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid Bubble::IsActiveChanged() { 317ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!IsActive()) 318ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Close(); 319ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 320ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#endif 321ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 322ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid Bubble::DoClose(bool closed_by_escape) { 323ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (show_status_ == kClosed) 324ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 325ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 326ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GetFocusManager()->UnregisterAccelerator( 327ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen views::Accelerator(ui::VKEY_ESCAPE, false, false, false), this); 328ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (delegate_) 329ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen delegate_->BubbleClosing(this, closed_by_escape); 330ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen show_status_ = kClosed; 331ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#if defined(OS_WIN) 332ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen border_->Close(); 333ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen WidgetWin::Close(); 334ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#elif defined(OS_LINUX) 335ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen WidgetGtk::Close(); 336ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#endif 337ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 338ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 339ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid Bubble::FadeIn() { 340ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Fade(true); // |fade_in|. 341ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 342ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 343ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid Bubble::FadeOut() { 344ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#if defined(OS_WIN) 345ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // The contents window cannot have the layered flag on by default, since its 346ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // content doesn't always work inside a layered window, but when animating it 347ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // is ok to set that style on the window for the purpose of fading it out. 348ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SetWindowLong(GWL_EXSTYLE, GetWindowLong(GWL_EXSTYLE) | WS_EX_LAYERED); 349ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // This must be the very next call, otherwise we can get flicker on close. 350ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SetLayeredWindowAttributes(GetNativeView(), 0, 351ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen static_cast<byte>(255), LWA_ALPHA); 352ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#endif 353ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 354ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Fade(false); // |fade_in|. 355ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 356ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 357ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid Bubble::Fade(bool fade_in) { 358ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen animation_.reset(new ui::SlideAnimation(this)); 359ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen animation_->SetSlideDuration(kHideFadeDurationMS); 360ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen animation_->SetTweenType(ui::Tween::LINEAR); 361ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 362ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen animation_->Reset(fade_in ? 0.0 : 1.0); 363ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (fade_in) 364ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen animation_->Show(); 365ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen else 366ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen animation_->Hide(); 367ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 368ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 369ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool Bubble::AcceleratorPressed(const views::Accelerator& accelerator) { 370ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!delegate_ || delegate_->CloseOnEscape()) { 371ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DoClose(true); 372ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return true; 373ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 374ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 375ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 376