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        &params);
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