snap_selection_strategy.cc 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. // Copyright 2018 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 "cc/input/snap_selection_strategy.h"
  5. #include <cmath>
  6. namespace cc {
  7. std::unique_ptr<SnapSelectionStrategy>
  8. SnapSelectionStrategy::CreateForEndPosition(
  9. const gfx::PointF& current_position,
  10. bool scrolled_x,
  11. bool scrolled_y,
  12. SnapTargetsPrioritization prioritization) {
  13. return std::make_unique<EndPositionStrategy>(current_position, scrolled_x,
  14. scrolled_y, prioritization);
  15. }
  16. std::unique_ptr<SnapSelectionStrategy>
  17. SnapSelectionStrategy::CreateForDirection(gfx::PointF current_position,
  18. gfx::Vector2dF step,
  19. bool use_fractional_offsets,
  20. SnapStopAlwaysFilter filter) {
  21. return std::make_unique<DirectionStrategy>(current_position, step, filter,
  22. use_fractional_offsets);
  23. }
  24. std::unique_ptr<SnapSelectionStrategy>
  25. SnapSelectionStrategy::CreateForEndAndDirection(gfx::PointF current_position,
  26. gfx::Vector2dF displacement,
  27. bool use_fractional_offsets) {
  28. return std::make_unique<EndAndDirectionStrategy>(
  29. current_position, displacement, use_fractional_offsets);
  30. }
  31. std::unique_ptr<SnapSelectionStrategy>
  32. SnapSelectionStrategy::CreateForTargetElement(gfx::PointF current_position) {
  33. return std::make_unique<EndPositionStrategy>(
  34. current_position, true /* scrolled_x */, true /* scrolled_y */,
  35. SnapTargetsPrioritization::kRequire);
  36. }
  37. bool SnapSelectionStrategy::HasIntendedDirection() const {
  38. return true;
  39. }
  40. bool SnapSelectionStrategy::ShouldRespectSnapStop() const {
  41. return false;
  42. }
  43. bool SnapSelectionStrategy::IsValidSnapArea(SearchAxis axis,
  44. const SnapAreaData& area) const {
  45. return axis == SearchAxis::kX
  46. ? area.scroll_snap_align.alignment_inline != SnapAlignment::kNone
  47. : area.scroll_snap_align.alignment_block != SnapAlignment::kNone;
  48. }
  49. bool SnapSelectionStrategy::ShouldPrioritizeSnapTargets() const {
  50. return false;
  51. }
  52. bool SnapSelectionStrategy::UsingFractionalOffsets() const {
  53. return false;
  54. }
  55. bool EndPositionStrategy::ShouldSnapOnX() const {
  56. return scrolled_x_;
  57. }
  58. bool EndPositionStrategy::ShouldSnapOnY() const {
  59. return scrolled_y_;
  60. }
  61. gfx::PointF EndPositionStrategy::intended_position() const {
  62. return current_position_;
  63. }
  64. gfx::PointF EndPositionStrategy::base_position() const {
  65. return current_position_;
  66. }
  67. // |position| is unused in this method.
  68. bool EndPositionStrategy::IsValidSnapPosition(SearchAxis axis,
  69. float position) const {
  70. return (scrolled_x_ && axis == SearchAxis::kX) ||
  71. (scrolled_y_ && axis == SearchAxis::kY);
  72. }
  73. bool EndPositionStrategy::HasIntendedDirection() const {
  74. return false;
  75. }
  76. bool EndPositionStrategy::ShouldPrioritizeSnapTargets() const {
  77. return snap_targets_prioritization_ == SnapTargetsPrioritization::kRequire;
  78. }
  79. const absl::optional<SnapSearchResult>& EndPositionStrategy::PickBestResult(
  80. const absl::optional<SnapSearchResult>& closest,
  81. const absl::optional<SnapSearchResult>& covering) const {
  82. return covering.has_value() ? covering : closest;
  83. }
  84. bool DirectionStrategy::ShouldSnapOnX() const {
  85. return step_.x() != 0;
  86. }
  87. bool DirectionStrategy::ShouldSnapOnY() const {
  88. return step_.y() != 0;
  89. }
  90. gfx::PointF DirectionStrategy::intended_position() const {
  91. return current_position_ + step_;
  92. }
  93. gfx::PointF DirectionStrategy::base_position() const {
  94. return current_position_;
  95. }
  96. bool DirectionStrategy::IsValidSnapPosition(SearchAxis axis,
  97. float position) const {
  98. // If not using fractional offsets then it is possible for the currently
  99. // snapped area's offset, which is fractional, to not be equal to the current
  100. // scroll offset, which is not fractional. Therefore we truncate the offsets
  101. // so that any position within 1 of the current position is ignored.
  102. if (axis == SearchAxis::kX) {
  103. float delta = position - current_position_.x();
  104. if (!use_fractional_offsets_)
  105. delta = delta > 0 ? std::floor(delta) : std::ceil(delta);
  106. return (step_.x() > 0 && delta > 0) || // "Right" arrow
  107. (step_.x() < 0 && delta < 0); // "Left" arrow
  108. } else {
  109. float delta = position - current_position_.y();
  110. if (!use_fractional_offsets_)
  111. delta = delta > 0 ? std::floor(delta) : std::ceil(delta);
  112. return (step_.y() > 0 && delta > 0) || // "Down" arrow
  113. (step_.y() < 0 && delta < 0); // "Up" arrow
  114. }
  115. }
  116. bool DirectionStrategy::IsValidSnapArea(SearchAxis axis,
  117. const SnapAreaData& area) const {
  118. return SnapSelectionStrategy::IsValidSnapArea(axis, area) &&
  119. (snap_stop_always_filter_ == SnapStopAlwaysFilter::kIgnore ||
  120. area.must_snap);
  121. }
  122. const absl::optional<SnapSearchResult>& DirectionStrategy::PickBestResult(
  123. const absl::optional<SnapSearchResult>& closest,
  124. const absl::optional<SnapSearchResult>& covering) const {
  125. // We choose the |closest| result only if the default landing position (using
  126. // the default step) is not a valid snap position (not making a snap area
  127. // covering the snapport), or the |closest| is closer than the default landing
  128. // position.
  129. if (!closest.has_value())
  130. return covering;
  131. if (!covering.has_value())
  132. return closest;
  133. // "Right" or "Down" arrow.
  134. if ((step_.x() > 0 || step_.y() > 0) &&
  135. closest.value().snap_offset() < covering.value().snap_offset()) {
  136. return closest;
  137. }
  138. // "Left" or "Up" arrow.
  139. if ((step_.x() < 0 || step_.y() < 0) &&
  140. closest.value().snap_offset() > covering.value().snap_offset()) {
  141. return closest;
  142. }
  143. return covering;
  144. }
  145. bool DirectionStrategy::UsingFractionalOffsets() const {
  146. return use_fractional_offsets_;
  147. }
  148. bool EndAndDirectionStrategy::ShouldSnapOnX() const {
  149. return displacement_.x() != 0;
  150. }
  151. bool EndAndDirectionStrategy::ShouldSnapOnY() const {
  152. return displacement_.y() != 0;
  153. }
  154. gfx::PointF EndAndDirectionStrategy::intended_position() const {
  155. return current_position_ + displacement_;
  156. }
  157. gfx::PointF EndAndDirectionStrategy::base_position() const {
  158. return current_position_ + displacement_;
  159. }
  160. bool EndAndDirectionStrategy::IsValidSnapPosition(SearchAxis axis,
  161. float position) const {
  162. // If not using fractional offsets then it is possible for the currently
  163. // snapped area's offset, which is fractional, to not be equal to the current
  164. // scroll offset, which is not fractional. Therefore we round the offsets so
  165. // that any position within 0.5 of the current position is ignored.
  166. if (axis == SearchAxis::kX) {
  167. float delta = position - current_position_.x();
  168. if (!use_fractional_offsets_)
  169. delta = std::round(delta);
  170. return (displacement_.x() > 0 && delta > 0) || // Right
  171. (displacement_.x() < 0 && delta < 0); // Left
  172. } else {
  173. float delta = position - current_position_.y();
  174. if (!use_fractional_offsets_)
  175. delta = std::round(delta);
  176. return (displacement_.y() > 0 && delta > 0) || // Down
  177. (displacement_.y() < 0 && delta < 0); // Up
  178. }
  179. }
  180. bool EndAndDirectionStrategy::ShouldRespectSnapStop() const {
  181. return true;
  182. }
  183. const absl::optional<SnapSearchResult>& EndAndDirectionStrategy::PickBestResult(
  184. const absl::optional<SnapSearchResult>& closest,
  185. const absl::optional<SnapSearchResult>& covering) const {
  186. return covering.has_value() ? covering : closest;
  187. }
  188. bool EndAndDirectionStrategy::UsingFractionalOffsets() const {
  189. return use_fractional_offsets_;
  190. }
  191. } // namespace cc