| 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(params_.can_activate); | 197 set_can_activate(false); |
| 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 // Inform host items (models) that their views are being destroyed. | 212 if (delegate_) { |
| 213 if (delegate_) | 213 delegate_->UnregisterAllAccelerators(this); |
| 214 |
| 215 // Inform host items (models) that their views are being destroyed. |
| 214 delegate_->BubbleViewDestroyed(); | 216 delegate_->BubbleViewDestroyed(); |
| 217 } |
| 215 } | 218 } |
| 216 | 219 |
| 217 // static | 220 // static |
| 218 bool TrayBubbleView::IsATrayBubbleOpen() { | 221 bool TrayBubbleView::IsATrayBubbleOpen() { |
| 219 return g_current_tray_bubble_showing_count_ > 0; | 222 return g_current_tray_bubble_showing_count_ > 0; |
| 220 } | 223 } |
| 221 | 224 |
| 222 void TrayBubbleView::InitializeAndShowBubble() { | 225 void TrayBubbleView::InitializeAndShowBubble() { |
| 223 layer()->parent()->SetMaskLayer(bubble_content_mask_->layer()); | 226 layer()->parent()->SetMaskLayer(bubble_content_mask_->layer()); |
| 224 | 227 |
| 225 GetWidget()->Show(); | 228 GetWidget()->Show(); |
| 226 GetWidget()->GetNativeWindow()->SetEventTargeter( | 229 GetWidget()->GetNativeWindow()->SetEventTargeter( |
| 227 std::unique_ptr<ui::EventTargeter>(new BubbleWindowTargeter(this))); | 230 std::unique_ptr<ui::EventTargeter>(new BubbleWindowTargeter(this))); |
| 228 UpdateBubble(); | 231 UpdateBubble(); |
| 229 | 232 |
| 230 ++g_current_tray_bubble_showing_count_; | 233 ++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 } |
| 231 } | 245 } |
| 232 | 246 |
| 233 void TrayBubbleView::UpdateBubble() { | 247 void TrayBubbleView::UpdateBubble() { |
| 234 if (GetWidget()) { | 248 if (GetWidget()) { |
| 235 SizeToContents(); | 249 SizeToContents(); |
| 236 bubble_content_mask_->layer()->SetBounds(layer()->bounds()); | 250 bubble_content_mask_->layer()->SetBounds(layer()->bounds()); |
| 237 GetWidget()->GetRootView()->SchedulePaint(); | 251 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(); |
| 238 } | 257 } |
| 239 } | 258 } |
| 240 | 259 |
| 241 void TrayBubbleView::SetMaxHeight(int height) { | 260 void TrayBubbleView::SetMaxHeight(int height) { |
| 242 params_.max_height = height; | 261 params_.max_height = height; |
| 243 if (GetWidget()) | 262 if (GetWidget()) |
| 244 SizeToContents(); | 263 SizeToContents(); |
| 245 } | 264 } |
| 246 | 265 |
| 247 void TrayBubbleView::SetBottomPadding(int padding) { | 266 void TrayBubbleView::SetBottomPadding(int padding) { |
| 248 layout_->set_inside_border_insets(gfx::Insets(0, 0, padding, 0)); | 267 layout_->set_inside_border_insets(gfx::Insets(0, 0, padding, 0)); |
| 249 } | 268 } |
| 250 | 269 |
| 251 void TrayBubbleView::SetWidth(int width) { | 270 void TrayBubbleView::SetWidth(int width) { |
| 252 width = std::max(std::min(width, params_.max_width), params_.min_width); | 271 width = std::max(std::min(width, params_.max_width), params_.min_width); |
| 253 if (preferred_width_ == width) | 272 if (preferred_width_ == width) |
| 254 return; | 273 return; |
| 255 preferred_width_ = width; | 274 preferred_width_ = width; |
| 256 if (GetWidget()) | 275 if (GetWidget()) |
| 257 SizeToContents(); | 276 SizeToContents(); |
| 258 } | 277 } |
| 259 | 278 |
| 260 gfx::Insets TrayBubbleView::GetBorderInsets() const { | 279 gfx::Insets TrayBubbleView::GetBorderInsets() const { |
| 261 return bubble_border_->GetInsets(); | 280 return bubble_border_->GetInsets(); |
| 262 } | 281 } |
| 263 | 282 |
| 283 void TrayBubbleView::ResetDelegate() { |
| 284 if (delegate_) |
| 285 delegate_->UnregisterAllAccelerators(this); |
| 286 |
| 287 delegate_ = nullptr; |
| 288 } |
| 289 |
| 264 int TrayBubbleView::GetDialogButtons() const { | 290 int TrayBubbleView::GetDialogButtons() const { |
| 265 return ui::DIALOG_BUTTON_NONE; | 291 return ui::DIALOG_BUTTON_NONE; |
| 266 } | 292 } |
| 267 | 293 |
| 268 void TrayBubbleView::OnBeforeBubbleWidgetInit(Widget::InitParams* params, | 294 void TrayBubbleView::OnBeforeBubbleWidgetInit(Widget::InitParams* params, |
| 269 Widget* bubble_widget) const { | 295 Widget* bubble_widget) const { |
| 270 // Apply a WM-provided shadow (see ui/wm/core/). | 296 // Apply a WM-provided shadow (see ui/wm/core/). |
| 271 params->shadow_type = Widget::InitParams::SHADOW_TYPE_DROP; | 297 params->shadow_type = Widget::InitParams::SHADOW_TYPE_DROP; |
| 272 params->shadow_elevation = wm::ShadowElevation::LARGE; | 298 params->shadow_elevation = wm::ShadowElevation::LARGE; |
| 273 } | 299 } |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 364 | 390 |
| 365 void TrayBubbleView::MouseMovedOutOfHost() { | 391 void TrayBubbleView::MouseMovedOutOfHost() { |
| 366 // The mouse was accidentally over the bubble when it opened and the AutoClose | 392 // The mouse was accidentally over the bubble when it opened and the AutoClose |
| 367 // logic was not activated. Now that the user did move the mouse we tell the | 393 // logic was not activated. Now that the user did move the mouse we tell the |
| 368 // delegate to disable AutoClose. | 394 // delegate to disable AutoClose. |
| 369 delegate_->OnMouseEnteredView(); | 395 delegate_->OnMouseEnteredView(); |
| 370 mouse_actively_entered_ = true; | 396 mouse_actively_entered_ = true; |
| 371 mouse_watcher_->Stop(); | 397 mouse_watcher_->Stop(); |
| 372 } | 398 } |
| 373 | 399 |
| 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 |
| 374 void TrayBubbleView::ChildPreferredSizeChanged(View* child) { | 420 void TrayBubbleView::ChildPreferredSizeChanged(View* child) { |
| 375 SizeToContents(); | 421 SizeToContents(); |
| 376 } | 422 } |
| 377 | 423 |
| 378 void TrayBubbleView::ViewHierarchyChanged( | 424 void TrayBubbleView::ViewHierarchyChanged( |
| 379 const ViewHierarchyChangedDetails& details) { | 425 const ViewHierarchyChangedDetails& details) { |
| 380 if (details.is_add && details.child == this) { | 426 if (details.is_add && details.child == this) { |
| 381 details.parent->SetPaintToLayer(); | 427 details.parent->SetPaintToLayer(); |
| 382 details.parent->layer()->SetMasksToBounds(true); | 428 details.parent->layer()->SetMasksToBounds(true); |
| 383 } | 429 } |
| 384 } | 430 } |
| 385 | 431 |
| 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 |
| 386 } // namespace views | 470 } // namespace views |
| OLD | NEW |