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
7ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/views/bubble/border_contents.h"
8ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/views/bubble/border_widget_win.h"
972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/views/frame/browser_view.h"
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/widget/root_view.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/widget/widget_win.h"
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/window/window.h"
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass BubbleWidget : public views::WidgetWin {
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  explicit BubbleWidget(BrowserBubble* bubble)
17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      : bubble_(bubble),
18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        border_widget_(new BorderWidgetWin) {
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    set_window_style(WS_POPUP | WS_CLIPCHILDREN);
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    set_window_ex_style(WS_EX_TOOLWINDOW);
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
23dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  void ShowAndActivate(bool activate) {
24ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Show the border first, then the popup overlaid on top.
25ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    border_widget_->Show();
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (activate)
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ShowWindow(SW_SHOW);
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    else
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      views::WidgetWin::Show();
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void Close() {
333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (!bubble_)
343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return;  // We have already been closed.
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (IsActive()) {
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      BrowserBubble::Delegate* delegate = bubble_->delegate();
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (delegate)
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        delegate->BubbleLostFocus(bubble_, NULL);
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
40ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    border_widget_->Close();
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    views::WidgetWin::Close();
423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    bubble_ = NULL;
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void Hide() {
463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (IsActive() && bubble_) {
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      BrowserBubble::Delegate* delegate = bubble_->delegate();
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (delegate)
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        delegate->BubbleLostFocus(bubble_, NULL);
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    views::WidgetWin::Hide();
52ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    border_widget_->Hide();
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void OnActivate(UINT action, BOOL minimized, HWND window) {
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    WidgetWin::OnActivate(action, minimized, window);
573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (!bubble_)
583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return;
593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    BrowserBubble::Delegate* delegate = bubble_->delegate();
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!delegate) {
623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      if (action == WA_INACTIVE) {
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        bubble_->DetachFromBrowser();
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        delete bubble_;
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return;
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (action == WA_INACTIVE) {
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      bool lost_focus_to_child = false;
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Are we a parent of this window?
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gfx::NativeView parent = window;
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      while (parent = ::GetParent(parent)) {
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (window == GetNativeView()) {
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          lost_focus_to_child = true;
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          break;
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Do we own this window?
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (!lost_focus_to_child &&
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          ::GetWindow(window, GW_OWNER) == GetNativeView()) {
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        lost_focus_to_child = true;
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      delegate->BubbleLostFocus(bubble_, lost_focus_to_child);
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void OnSetFocus(HWND focused_window) {
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    WidgetWin::OnSetFocus(focused_window);
933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (bubble_ && bubble_->delegate())
943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      bubble_->delegate()->BubbleGotFocus(bubble_);
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
97ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  BorderWidgetWin* border_widget() {
98ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return border_widget_;
99ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BrowserBubble* bubble_;
103ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  BorderWidgetWin* border_widget_;
1043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DISALLOW_COPY_AND_ASSIGN(BubbleWidget);
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserBubble::InitPopup() {
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // popup_ is a Widget, but we need to do some WidgetWin stuff first, then
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // we'll assign it into popup_.
111ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  BubbleWidget* pop = new BubbleWidget(this);
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
113ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  BorderWidgetWin* border_widget = pop->border_widget();
114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  border_widget->Init(new BorderContents, frame_->GetNativeView());
115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
116ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // We make the BorderWidgetWin the owner of the Bubble HWND, so that the
117ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // latter is displayed on top of the former.
118ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  pop->Init(border_widget->GetNativeView(), gfx::Rect());
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  pop->SetContentsView(view_);
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  popup_ = pop;
122ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
123ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ResizeToView();
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Reposition();
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  AttachToBrowser();
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserBubble::MovePopup(int x, int y, int w, int h) {
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  views::WidgetWin* pop = static_cast<views::WidgetWin*>(popup_);
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  pop->SetBounds(gfx::Rect(x, y, w, h));
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserBubble::Show(bool activate) {
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (visible_)
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BubbleWidget* pop = static_cast<BubbleWidget*>(popup_);
137dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  pop->ShowAndActivate(activate);
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  visible_ = true;
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserBubble::Hide() {
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!visible_)
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  views::WidgetWin* pop = static_cast<views::WidgetWin*>(popup_);
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  pop->Hide();
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  visible_ = false;
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
148ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
149ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid BrowserBubble::ResizeToView() {
150ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  BorderWidgetWin* border_widget =
151ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      static_cast<BubbleWidget*>(popup_)->border_widget();
152ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
153ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  gfx::Rect window_bounds;
154ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  window_bounds = border_widget->SizeAndGetBounds(GetAbsoluteRelativeTo(),
155ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      arrow_location_, view_->size());
156ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
157ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SetAbsoluteBounds(window_bounds);
158ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
159