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