shelf_window_targeter.cc 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. // Copyright 2016 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. #include "ash/shelf/shelf_window_targeter.h"
  5. #include "ash/public/cpp/session/session_types.h"
  6. #include "ash/public/cpp/shelf_config.h"
  7. #include "ash/public/cpp/shelf_types.h"
  8. #include "ash/public/cpp/shell_window_ids.h"
  9. #include "ash/session/session_controller_impl.h"
  10. #include "ash/shelf/shelf.h"
  11. #include "ash/shelf/shelf_widget.h"
  12. #include "ash/shell.h"
  13. #include "ui/aura/window.h"
  14. namespace ash {
  15. namespace {
  16. gfx::Insets GetInsetsForAlignment(int distance, ShelfAlignment alignment) {
  17. if (alignment == ShelfAlignment::kLeft)
  18. return gfx::Insets::TLBR(0, 0, 0, distance);
  19. if (alignment == ShelfAlignment::kRight)
  20. return gfx::Insets::TLBR(0, distance, 0, 0);
  21. return gfx::Insets::TLBR(distance, 0, 0, 0);
  22. }
  23. } // namespace
  24. ShelfWindowTargeter::ShelfWindowTargeter(aura::Window* container, Shelf* shelf)
  25. : ::wm::EasyResizeWindowTargeter(gfx::Insets(), gfx::Insets()),
  26. shelf_(shelf) {
  27. WillChangeVisibilityState(shelf_->GetVisibilityState());
  28. container->AddObserver(this);
  29. shelf_->AddObserver(this);
  30. }
  31. ShelfWindowTargeter::~ShelfWindowTargeter() {
  32. // Ensure that the observers were removed and the shelf pointer was cleared.
  33. DCHECK(!shelf_);
  34. }
  35. bool ShelfWindowTargeter::ShouldUseExtendedBounds(const aura::Window* w) const {
  36. // Use extended bounds only for direct child of the container.
  37. return window() == w->parent();
  38. }
  39. bool ShelfWindowTargeter::GetHitTestRects(
  40. aura::Window* target,
  41. gfx::Rect* hit_test_rect_mouse,
  42. gfx::Rect* hit_test_rect_touch) const {
  43. // We only want to special case a very specific situation where we are not
  44. // currently in an active session (or unknown session state) and change only
  45. // the behavior of the login shelf. On secondary displays, the login shelf
  46. // will not be visible.
  47. // TODO(https://crbug.com/1343114): remove this code block after the login
  48. // shelf widget is in use.
  49. bool target_is_shelf_widget =
  50. target == shelf_->shelf_widget()->GetNativeWindow();
  51. if (target_is_shelf_widget &&
  52. Shell::Get()->session_controller()->GetSessionState() !=
  53. session_manager::SessionState::ACTIVE &&
  54. Shell::Get()->session_controller()->GetSessionState() !=
  55. session_manager::SessionState::UNKNOWN &&
  56. !features::IsUseLoginShelfWidgetEnabled()) {
  57. // When this is the case, let events pass through the "empty" part of
  58. // the shelf.
  59. return shelf_->shelf_widget()->GetHitTestRects(target, hit_test_rect_mouse,
  60. hit_test_rect_touch);
  61. }
  62. *hit_test_rect_mouse = *hit_test_rect_touch = target->bounds();
  63. if (ShouldUseExtendedBounds(target)) {
  64. hit_test_rect_mouse->Inset(mouse_extend());
  65. // Whether the touch hit area should be extended beyond the window top when
  66. // the shelf is in auto-hide state (to make targeting hidden shelf easier).
  67. // This should be applied for shelf widget only, to prevent other widgets
  68. // positioned below display bounds (e.g. hidden hotseat widget) from
  69. // handling touch events instead of the shelf.
  70. if (target_is_shelf_widget)
  71. hit_test_rect_touch->Inset(touch_extend());
  72. }
  73. return true;
  74. }
  75. void ShelfWindowTargeter::OnWindowDestroying(aura::Window* window) {
  76. window->RemoveObserver(this);
  77. shelf_->RemoveObserver(this);
  78. shelf_ = nullptr;
  79. }
  80. void ShelfWindowTargeter::WillChangeVisibilityState(
  81. ShelfVisibilityState new_state) {
  82. // Do not use |new_state| as it can be a shelf on other displays.
  83. auto visibility_state = shelf_->GetVisibilityState();
  84. gfx::Insets mouse_insets;
  85. gfx::Insets touch_insets;
  86. if (visibility_state == SHELF_VISIBLE) {
  87. // Let clicks at the very top of the shelf through so windows can be
  88. // resized with the bottom-right corner and bottom edge.
  89. mouse_insets = GetInsetsForAlignment(
  90. ShelfConfig::Get()->workspace_area_visible_inset(),
  91. shelf_->alignment());
  92. } else if (visibility_state == SHELF_AUTO_HIDE) {
  93. // Extend the touch hit target out a bit to allow users to drag shelf out
  94. // while hidden.
  95. touch_insets = GetInsetsForAlignment(
  96. -ShelfConfig::Get()->workspace_area_auto_hide_inset(),
  97. shelf_->alignment());
  98. }
  99. // Remember the insets. See GetHitTestsRects when they're actually used.
  100. SetInsets(mouse_insets, touch_insets);
  101. }
  102. } // namespace ash