OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/views/bubble/tray_bubble_view.h" | 5 #include "ui/views/bubble/tray_bubble_view.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/macros.h" | 9 #include "base/macros.h" |
10 #include "cc/paint/paint_flags.h" | 10 #include "cc/paint/paint_flags.h" |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
187 owned_bubble_border_(bubble_border_), | 187 owned_bubble_border_(bubble_border_), |
188 is_gesture_dragging_(false), | 188 is_gesture_dragging_(false), |
189 mouse_actively_entered_(false) { | 189 mouse_actively_entered_(false) { |
190 DCHECK(delegate_); | 190 DCHECK(delegate_); |
191 DCHECK(params_.parent_window); | 191 DCHECK(params_.parent_window); |
192 DCHECK(anchor_widget()); // Computed by BubbleDialogDelegateView(). | 192 DCHECK(anchor_widget()); // Computed by BubbleDialogDelegateView(). |
193 bubble_border_->set_use_theme_background_color(!init_params.bg_color); | 193 bubble_border_->set_use_theme_background_color(!init_params.bg_color); |
194 bubble_border_->set_alignment(BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE); | 194 bubble_border_->set_alignment(BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE); |
195 bubble_border_->set_paint_arrow(BubbleBorder::PAINT_NONE); | 195 bubble_border_->set_paint_arrow(BubbleBorder::PAINT_NONE); |
196 set_parent_window(params_.parent_window); | 196 set_parent_window(params_.parent_window); |
197 set_can_activate(false); | 197 set_can_activate(params_.can_activate); |
198 set_notify_enter_exit_on_child(true); | 198 set_notify_enter_exit_on_child(true); |
199 set_close_on_deactivate(init_params.close_on_deactivate); | 199 set_close_on_deactivate(init_params.close_on_deactivate); |
200 set_margins(gfx::Insets()); | 200 set_margins(gfx::Insets()); |
201 SetPaintToLayer(); | 201 SetPaintToLayer(); |
202 | 202 |
203 bubble_content_mask_.reset( | 203 bubble_content_mask_.reset( |
204 new TrayBubbleContentMask(bubble_border_->GetBorderCornerRadius())); | 204 new TrayBubbleContentMask(bubble_border_->GetBorderCornerRadius())); |
205 | 205 |
206 layout_->SetDefaultFlex(1); | 206 layout_->SetDefaultFlex(1); |
207 SetLayoutManager(layout_); | 207 SetLayoutManager(layout_); |
208 } | 208 } |
209 | 209 |
210 TrayBubbleView::~TrayBubbleView() { | 210 TrayBubbleView::~TrayBubbleView() { |
211 mouse_watcher_.reset(); | 211 mouse_watcher_.reset(); |
212 if (delegate_) { | 212 // Inform host items (models) that their views are being destroyed. |
213 delegate_->UnregisterAllAccelerators(this); | 213 if (delegate_) |
214 | |
215 // Inform host items (models) that their views are being destroyed. | |
216 delegate_->BubbleViewDestroyed(); | 214 delegate_->BubbleViewDestroyed(); |
217 } | |
218 } | 215 } |
219 | 216 |
220 // static | 217 // static |
221 bool TrayBubbleView::IsATrayBubbleOpen() { | 218 bool TrayBubbleView::IsATrayBubbleOpen() { |
222 return g_current_tray_bubble_showing_count_ > 0; | 219 return g_current_tray_bubble_showing_count_ > 0; |
223 } | 220 } |
224 | 221 |
225 void TrayBubbleView::InitializeAndShowBubble() { | 222 void TrayBubbleView::InitializeAndShowBubble() { |
226 layer()->parent()->SetMaskLayer(bubble_content_mask_->layer()); | 223 layer()->parent()->SetMaskLayer(bubble_content_mask_->layer()); |
227 | 224 |
228 GetWidget()->Show(); | 225 GetWidget()->Show(); |
229 GetWidget()->GetNativeWindow()->SetEventTargeter( | 226 GetWidget()->GetNativeWindow()->SetEventTargeter( |
230 std::unique_ptr<ui::EventTargeter>(new BubbleWindowTargeter(this))); | 227 std::unique_ptr<ui::EventTargeter>(new BubbleWindowTargeter(this))); |
231 UpdateBubble(); | 228 UpdateBubble(); |
232 | 229 |
233 ++g_current_tray_bubble_showing_count_; | 230 ++g_current_tray_bubble_showing_count_; |
234 | |
235 // If TrayBubbleView cannot be activated, register accelerators to capture key | |
236 // events for activating the view or closing it. TrayBubbleView expects that | |
237 // those accelerators are registered at the global level. | |
238 if (delegate_ && !CanActivate()) { | |
239 delegate_->RegisterAccelerators( | |
240 {ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_NONE), | |
241 ui::Accelerator(ui::VKEY_TAB, ui::EF_NONE), | |
242 ui::Accelerator(ui::VKEY_TAB, ui::EF_SHIFT_DOWN)}, | |
243 this); | |
244 } | |
245 } | 231 } |
246 | 232 |
247 void TrayBubbleView::UpdateBubble() { | 233 void TrayBubbleView::UpdateBubble() { |
248 if (GetWidget()) { | 234 if (GetWidget()) { |
249 SizeToContents(); | 235 SizeToContents(); |
250 bubble_content_mask_->layer()->SetBounds(layer()->bounds()); | 236 bubble_content_mask_->layer()->SetBounds(layer()->bounds()); |
251 GetWidget()->GetRootView()->SchedulePaint(); | 237 GetWidget()->GetRootView()->SchedulePaint(); |
252 | |
253 // When extra keyboard accessibility is enabled, focus the default item if | |
254 // no item is focused. | |
255 if (delegate_ && delegate_->ShouldEnableExtraKeyboardAccessibility()) | |
256 FocusDefaultIfNeeded(); | |
257 } | 238 } |
258 } | 239 } |
259 | 240 |
260 void TrayBubbleView::SetMaxHeight(int height) { | 241 void TrayBubbleView::SetMaxHeight(int height) { |
261 params_.max_height = height; | 242 params_.max_height = height; |
262 if (GetWidget()) | 243 if (GetWidget()) |
263 SizeToContents(); | 244 SizeToContents(); |
264 } | 245 } |
265 | 246 |
266 void TrayBubbleView::SetBottomPadding(int padding) { | 247 void TrayBubbleView::SetBottomPadding(int padding) { |
267 layout_->set_inside_border_insets(gfx::Insets(0, 0, padding, 0)); | 248 layout_->set_inside_border_insets(gfx::Insets(0, 0, padding, 0)); |
268 } | 249 } |
269 | 250 |
270 void TrayBubbleView::SetWidth(int width) { | 251 void TrayBubbleView::SetWidth(int width) { |
271 width = std::max(std::min(width, params_.max_width), params_.min_width); | 252 width = std::max(std::min(width, params_.max_width), params_.min_width); |
272 if (preferred_width_ == width) | 253 if (preferred_width_ == width) |
273 return; | 254 return; |
274 preferred_width_ = width; | 255 preferred_width_ = width; |
275 if (GetWidget()) | 256 if (GetWidget()) |
276 SizeToContents(); | 257 SizeToContents(); |
277 } | 258 } |
278 | 259 |
279 gfx::Insets TrayBubbleView::GetBorderInsets() const { | 260 gfx::Insets TrayBubbleView::GetBorderInsets() const { |
280 return bubble_border_->GetInsets(); | 261 return bubble_border_->GetInsets(); |
281 } | 262 } |
282 | 263 |
283 void TrayBubbleView::ResetDelegate() { | |
284 if (delegate_) | |
285 delegate_->UnregisterAllAccelerators(this); | |
286 | |
287 delegate_ = nullptr; | |
288 } | |
289 | |
290 int TrayBubbleView::GetDialogButtons() const { | 264 int TrayBubbleView::GetDialogButtons() const { |
291 return ui::DIALOG_BUTTON_NONE; | 265 return ui::DIALOG_BUTTON_NONE; |
292 } | 266 } |
293 | 267 |
294 void TrayBubbleView::OnBeforeBubbleWidgetInit(Widget::InitParams* params, | 268 void TrayBubbleView::OnBeforeBubbleWidgetInit(Widget::InitParams* params, |
295 Widget* bubble_widget) const { | 269 Widget* bubble_widget) const { |
296 // Apply a WM-provided shadow (see ui/wm/core/). | 270 // Apply a WM-provided shadow (see ui/wm/core/). |
297 params->shadow_type = Widget::InitParams::SHADOW_TYPE_DROP; | 271 params->shadow_type = Widget::InitParams::SHADOW_TYPE_DROP; |
298 params->shadow_elevation = wm::ShadowElevation::LARGE; | 272 params->shadow_elevation = wm::ShadowElevation::LARGE; |
299 } | 273 } |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
390 | 364 |
391 void TrayBubbleView::MouseMovedOutOfHost() { | 365 void TrayBubbleView::MouseMovedOutOfHost() { |
392 // The mouse was accidentally over the bubble when it opened and the AutoClose | 366 // The mouse was accidentally over the bubble when it opened and the AutoClose |
393 // logic was not activated. Now that the user did move the mouse we tell the | 367 // logic was not activated. Now that the user did move the mouse we tell the |
394 // delegate to disable AutoClose. | 368 // delegate to disable AutoClose. |
395 delegate_->OnMouseEnteredView(); | 369 delegate_->OnMouseEnteredView(); |
396 mouse_actively_entered_ = true; | 370 mouse_actively_entered_ = true; |
397 mouse_watcher_->Stop(); | 371 mouse_watcher_->Stop(); |
398 } | 372 } |
399 | 373 |
400 bool TrayBubbleView::AcceleratorPressed(const ui::Accelerator& accelerator) { | |
401 if (accelerator == ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_NONE)) { | |
402 CloseBubbleView(); | |
403 return true; | |
404 } | |
405 | |
406 if (accelerator == ui::Accelerator(ui::VKEY_TAB, ui::EF_NONE) || | |
407 accelerator == ui::Accelerator(ui::VKEY_TAB, ui::EF_SHIFT_DOWN)) { | |
408 ui::KeyEvent key_event( | |
409 accelerator.key_state() == ui::Accelerator::KeyState::PRESSED | |
410 ? ui::EventType::ET_KEY_PRESSED | |
411 : ui::EventType::ET_KEY_RELEASED, | |
412 accelerator.key_code(), accelerator.modifiers()); | |
413 ActivateAndStartNavigation(key_event); | |
414 return true; | |
415 } | |
416 | |
417 return false; | |
418 } | |
419 | |
420 void TrayBubbleView::ChildPreferredSizeChanged(View* child) { | 374 void TrayBubbleView::ChildPreferredSizeChanged(View* child) { |
421 SizeToContents(); | 375 SizeToContents(); |
422 } | 376 } |
423 | 377 |
424 void TrayBubbleView::ViewHierarchyChanged( | 378 void TrayBubbleView::ViewHierarchyChanged( |
425 const ViewHierarchyChangedDetails& details) { | 379 const ViewHierarchyChangedDetails& details) { |
426 if (details.is_add && details.child == this) { | 380 if (details.is_add && details.child == this) { |
427 details.parent->SetPaintToLayer(); | 381 details.parent->SetPaintToLayer(); |
428 details.parent->layer()->SetMasksToBounds(true); | 382 details.parent->layer()->SetMasksToBounds(true); |
429 } | 383 } |
430 } | 384 } |
431 | 385 |
432 void TrayBubbleView::CloseBubbleView() { | |
433 if (!delegate_) | |
434 return; | |
435 | |
436 delegate_->UnregisterAllAccelerators(this); | |
437 delegate_->HideBubble(this); | |
438 } | |
439 | |
440 void TrayBubbleView::ActivateAndStartNavigation(const ui::KeyEvent& key_event) { | |
441 // No need to explicitly activate the widget. FocusManager will activate it if | |
442 // necessary. | |
443 set_can_activate(true); | |
444 | |
445 if (!GetWidget()->GetFocusManager()->OnKeyEvent(key_event) && delegate_) { | |
446 // No need to handle accelerators by TrayBubbleView after focus has moved to | |
447 // the widget. The focused view will handle focus traversal. | |
448 // FocusManager::OnKeyEvent returns false when it consumes a key event. | |
449 delegate_->UnregisterAllAccelerators(this); | |
450 } | |
451 } | |
452 | |
453 void TrayBubbleView::FocusDefaultIfNeeded() { | |
454 views::FocusManager* manager = GetFocusManager(); | |
455 if (!manager || manager->GetFocusedView()) | |
456 return; | |
457 | |
458 views::View* view = | |
459 manager->GetNextFocusableView(nullptr, nullptr, false, false); | |
460 if (!view) | |
461 return; | |
462 | |
463 // No need to explicitly activate the widget. View::RequestFocus will activate | |
464 // it if necessary. | |
465 set_can_activate(true); | |
466 | |
467 view->RequestFocus(); | |
468 } | |
469 | |
470 } // namespace views | 386 } // namespace views |
OLD | NEW |