1// Copyright (c) 2011 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/ui/views/browser_bubble.h" 6 7#include <vector> 8 9#include "chrome/browser/ui/views/bubble/border_contents.h" 10#include "chrome/browser/ui/views/frame/browser_view.h" 11#include "views/widget/root_view.h" 12#include "views/widget/widget_gtk.h" 13 14#if defined(OS_CHROMEOS) 15#include "chrome/browser/chromeos/wm_ipc.h" 16#include "third_party/cros/chromeos_wm_ipc_enums.h" 17#endif 18 19using std::vector; 20 21namespace { 22 23class BubbleWidget : public views::WidgetGtk { 24 public: 25 explicit BubbleWidget(BrowserBubble* bubble) 26 : views::WidgetGtk(views::WidgetGtk::TYPE_WINDOW), 27 bubble_(bubble), 28 border_contents_(new BorderContents) { 29 border_contents_->Init(); 30 } 31 32 void ShowAndActivate(bool activate) { 33 // TODO: honor activate. 34 views::WidgetGtk::Show(); 35 } 36 37 virtual void Close() { 38 if (!bubble_) 39 return; // We have already been closed. 40 if (IsActive()) { 41 BrowserBubble::Delegate* delegate = bubble_->delegate(); 42 if (delegate) 43 delegate->BubbleLostFocus(bubble_, false); 44 } 45 views::WidgetGtk::Close(); 46 bubble_ = NULL; 47 } 48 49 virtual void Hide() { 50 if (IsActive()&& bubble_) { 51 BrowserBubble::Delegate* delegate = bubble_->delegate(); 52 if (delegate) 53 delegate->BubbleLostFocus(bubble_, false); 54 } 55 views::WidgetGtk::Hide(); 56 } 57 58 virtual void IsActiveChanged() { 59 if (IsActive() || !bubble_) 60 return; 61 BrowserBubble::Delegate* delegate = bubble_->delegate(); 62 if (!delegate) { 63 bubble_->DetachFromBrowser(); 64 delete bubble_; 65 return; 66 } 67 68 // TODO(jcampan): http://crbugs.com/29131 Check if the window we are losing 69 // focus to is a child window and pass that to the call 70 // below. 71 delegate->BubbleLostFocus(bubble_, false); 72 } 73 74 virtual gboolean OnFocusIn(GtkWidget* widget, GdkEventFocus* event) { 75 if (bubble_ && bubble_->delegate()) 76 bubble_->delegate()->BubbleGotFocus(bubble_); 77 return views::WidgetGtk::OnFocusIn(widget, event); 78 } 79 80 BorderContents* border_contents() { 81 return border_contents_; 82 } 83 84 private: 85 BrowserBubble* bubble_; 86 BorderContents* border_contents_; // Owned by root view of this widget. 87 88 DISALLOW_COPY_AND_ASSIGN(BubbleWidget); 89}; 90 91} // namespace 92 93void BrowserBubble::InitPopup() { 94 // TODO(port) 95 BubbleWidget* pop = new BubbleWidget(this); 96 pop->MakeTransparent(); 97 pop->make_transient_to_parent(); 98 pop->Init(frame_->GetNativeView(), gfx::Rect()); 99#if defined(OS_CHROMEOS) 100 { 101 vector<int> params; 102 params.push_back(0); // don't show while screen is locked 103 chromeos::WmIpc::instance()->SetWindowType( 104 pop->GetNativeView(), 105 chromeos::WM_IPC_WINDOW_CHROME_INFO_BUBBLE, 106 ¶ms); 107 } 108#endif 109 110 views::View* contents_view = new views::View; 111 112 // We add |contents_view| to ourselves before the AddChildView() call below so 113 // that when |contents| gets added, it will already have a widget, and thus 114 // any NativeButtons it creates in ViewHierarchyChanged() will be functional 115 // (e.g. calling SetChecked() on checkboxes is safe). 116 pop->SetContentsView(contents_view); 117 118 // Added border_contents before |view_| so it will paint under it. 119 contents_view->AddChildView(pop->border_contents()); 120 contents_view->AddChildView(view_); 121 122 popup_ = pop; 123 124 ResizeToView(); 125 Reposition(); 126 AttachToBrowser(); 127} 128 129void BrowserBubble::MovePopup(int x, int y, int w, int h) { 130 views::WidgetGtk* pop = static_cast<views::WidgetGtk*>(popup_); 131 pop->SetBounds(gfx::Rect(x, y, w, h)); 132} 133 134void BrowserBubble::Show(bool activate) { 135 if (visible_) 136 return; 137 static_cast<BubbleWidget*>(popup_)->ShowAndActivate(activate); 138 visible_ = true; 139} 140 141void BrowserBubble::Hide() { 142 if (!visible_) 143 return; 144 views::WidgetGtk* pop = static_cast<views::WidgetGtk*>(popup_); 145 pop->Hide(); 146 visible_ = false; 147} 148 149void BrowserBubble::ResizeToView() { 150 BorderContents* border_contents = 151 static_cast<BubbleWidget*>(popup_)->border_contents(); 152 153 // Calculate and set the bounds for all windows and views. 154 gfx::Rect window_bounds; 155 gfx::Rect contents_bounds; 156 border_contents->SizeAndGetBounds(GetAbsoluteRelativeTo(), 157 arrow_location_, false, view_->size(), 158 &contents_bounds, &window_bounds); 159 160 border_contents->SetBoundsRect(gfx::Rect(gfx::Point(), window_bounds.size())); 161 view_->SetBoundsRect(contents_bounds); 162 163 SetAbsoluteBounds(window_bounds); 164} 165