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