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