ink_drop_impl.cc 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863
  1. // Copyright 2015 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 "ui/views/animation/ink_drop_impl.h"
  5. #include <utility>
  6. #include "base/auto_reset.h"
  7. #include "base/bind.h"
  8. #include "base/timer/timer.h"
  9. #include "ui/compositor/layer.h"
  10. #include "ui/views/animation/ink_drop_highlight.h"
  11. #include "ui/views/animation/ink_drop_host_view.h"
  12. #include "ui/views/animation/ink_drop_util.h"
  13. #include "ui/views/animation/square_ink_drop_ripple.h"
  14. #include "ui/views/style/platform_style.h"
  15. namespace views {
  16. namespace {
  17. // The duration for the highlight state fade in/out animations when they are
  18. // triggered by a hover changed event.
  19. constexpr auto kHighlightFadeInOnHoverChangeDuration = base::Milliseconds(250);
  20. constexpr auto kHighlightFadeOutOnHoverChangeDuration = base::Milliseconds(250);
  21. // The duration for the highlight state fade in/out animations when they are
  22. // triggered by a focus changed event.
  23. constexpr auto kHighlightFadeInOnFocusChangeDuration = base::TimeDelta();
  24. constexpr auto kHighlightFadeOutOnFocusChangeDuration = base::TimeDelta();
  25. // The duration for showing/hiding the highlight when triggered by ripple
  26. // visibility changes for the HIDE_ON_RIPPLE AutoHighlightMode.
  27. constexpr auto kHighlightFadeInOnRippleHidingDuration = base::Milliseconds(250);
  28. constexpr auto kHighlightFadeOutOnRippleShowingDuration =
  29. base::Milliseconds(120);
  30. // The duration for showing/hiding the highlight when triggered by ripple
  31. // visibility changes for the SHOW_ON_RIPPLE AutoHighlightMode.
  32. constexpr auto kHighlightFadeInOnRippleShowingDuration =
  33. base::Milliseconds(250);
  34. constexpr auto kHighlightFadeOutOnRippleHidingDuration =
  35. base::Milliseconds(120);
  36. // The amount of time that |highlight_| should delay after a ripple animation
  37. // before fading in, for highlight due to mouse hover.
  38. constexpr auto kHoverFadeInAfterRippleDelay = base::Milliseconds(1000);
  39. // Returns true if an ink drop with the given |ink_drop_state| should
  40. // automatically transition to the InkDropState::HIDDEN state.
  41. bool ShouldAnimateToHidden(InkDropState ink_drop_state) {
  42. switch (ink_drop_state) {
  43. case views::InkDropState::ACTION_TRIGGERED:
  44. case views::InkDropState::ALTERNATE_ACTION_TRIGGERED:
  45. case views::InkDropState::DEACTIVATED:
  46. return true;
  47. default:
  48. return false;
  49. }
  50. }
  51. } // namespace
  52. // HighlightState definition
  53. InkDropImpl* InkDropImpl::HighlightState::GetInkDrop() {
  54. return state_factory_->ink_drop();
  55. }
  56. // A HighlightState to be used during InkDropImpl destruction. All event
  57. // handlers are no-ops so as to avoid triggering animations during tear down.
  58. class InkDropImpl::DestroyingHighlightState
  59. : public InkDropImpl::HighlightState {
  60. public:
  61. DestroyingHighlightState() : HighlightState(nullptr) {}
  62. DestroyingHighlightState(const DestroyingHighlightState&) = delete;
  63. DestroyingHighlightState& operator=(const DestroyingHighlightState&) = delete;
  64. // InkDropImpl::HighlightState:
  65. void Enter() override {}
  66. void ShowOnHoverChanged() override {}
  67. void OnHoverChanged() override {}
  68. void ShowOnFocusChanged() override {}
  69. void OnFocusChanged() override {}
  70. void AnimationStarted(InkDropState ink_drop_state) override {}
  71. void AnimationEnded(InkDropState ink_drop_state,
  72. InkDropAnimationEndedReason reason) override {}
  73. };
  74. //
  75. // AutoHighlightMode::NONE states
  76. //
  77. // Animates the highlight to hidden upon entering this state. Transitions to a
  78. // visible state based on hover/focus changes.
  79. class InkDropImpl::NoAutoHighlightHiddenState
  80. : public InkDropImpl::HighlightState {
  81. public:
  82. NoAutoHighlightHiddenState(HighlightStateFactory* state_factory,
  83. base::TimeDelta animation_duration);
  84. NoAutoHighlightHiddenState(const NoAutoHighlightHiddenState&) = delete;
  85. NoAutoHighlightHiddenState& operator=(const NoAutoHighlightHiddenState&) =
  86. delete;
  87. // InkDropImpl::HighlightState:
  88. void Enter() override;
  89. void ShowOnHoverChanged() override;
  90. void OnHoverChanged() override;
  91. void ShowOnFocusChanged() override;
  92. void OnFocusChanged() override;
  93. void AnimationStarted(InkDropState ink_drop_state) override;
  94. void AnimationEnded(InkDropState ink_drop_state,
  95. InkDropAnimationEndedReason reason) override;
  96. private:
  97. // Handles all changes to the hover/focus status and transitions to a visible
  98. // state if necessary.
  99. void HandleHoverAndFocusChangeChanges(base::TimeDelta animation_duration);
  100. // The fade out animation duration.
  101. base::TimeDelta animation_duration_;
  102. };
  103. // Animates the highlight to visible upon entering this state. Transitions to a
  104. // hidden state based on hover/focus changes.
  105. class InkDropImpl::NoAutoHighlightVisibleState
  106. : public InkDropImpl::HighlightState {
  107. public:
  108. NoAutoHighlightVisibleState(HighlightStateFactory* state_factory,
  109. base::TimeDelta animation_duration);
  110. NoAutoHighlightVisibleState(const NoAutoHighlightVisibleState&) = delete;
  111. NoAutoHighlightVisibleState& operator=(const NoAutoHighlightVisibleState&) =
  112. delete;
  113. // InkDropImpl::HighlightState:
  114. void Enter() override;
  115. void Exit() override {}
  116. void ShowOnHoverChanged() override;
  117. void OnHoverChanged() override;
  118. void ShowOnFocusChanged() override;
  119. void OnFocusChanged() override;
  120. void AnimationStarted(InkDropState ink_drop_state) override;
  121. void AnimationEnded(InkDropState ink_drop_state,
  122. InkDropAnimationEndedReason reason) override;
  123. private:
  124. // Handles all changes to the hover/focus status and transitions to a hidden
  125. // state if necessary.
  126. void HandleHoverAndFocusChangeChanges(base::TimeDelta animation_duration);
  127. // The fade in animation duration.
  128. base::TimeDelta animation_duration_;
  129. };
  130. // NoAutoHighlightHiddenState definition
  131. InkDropImpl::NoAutoHighlightHiddenState::NoAutoHighlightHiddenState(
  132. HighlightStateFactory* state_factory,
  133. base::TimeDelta animation_duration)
  134. : InkDropImpl::HighlightState(state_factory),
  135. animation_duration_(animation_duration) {}
  136. void InkDropImpl::NoAutoHighlightHiddenState::Enter() {
  137. GetInkDrop()->SetHighlight(false, animation_duration_);
  138. }
  139. void InkDropImpl::NoAutoHighlightHiddenState::ShowOnHoverChanged() {
  140. HandleHoverAndFocusChangeChanges(
  141. GetInkDrop()->hover_highlight_fade_duration().value_or(
  142. kHighlightFadeInOnHoverChangeDuration));
  143. }
  144. void InkDropImpl::NoAutoHighlightHiddenState::OnHoverChanged() {
  145. HandleHoverAndFocusChangeChanges(
  146. GetInkDrop()->hover_highlight_fade_duration().value_or(
  147. kHighlightFadeInOnHoverChangeDuration));
  148. }
  149. void InkDropImpl::NoAutoHighlightHiddenState::ShowOnFocusChanged() {
  150. HandleHoverAndFocusChangeChanges(kHighlightFadeInOnFocusChangeDuration);
  151. }
  152. void InkDropImpl::NoAutoHighlightHiddenState::OnFocusChanged() {
  153. HandleHoverAndFocusChangeChanges(kHighlightFadeInOnFocusChangeDuration);
  154. }
  155. void InkDropImpl::NoAutoHighlightHiddenState::HandleHoverAndFocusChangeChanges(
  156. base::TimeDelta animation_duration) {
  157. if (GetInkDrop()->ShouldHighlight()) {
  158. GetInkDrop()->SetHighlightState(
  159. state_factory()->CreateVisibleState(animation_duration));
  160. }
  161. }
  162. void InkDropImpl::NoAutoHighlightHiddenState::AnimationStarted(
  163. InkDropState ink_drop_state) {}
  164. void InkDropImpl::NoAutoHighlightHiddenState::AnimationEnded(
  165. InkDropState ink_drop_state,
  166. InkDropAnimationEndedReason reason) {}
  167. // NoAutoHighlightVisibleState definition
  168. InkDropImpl::NoAutoHighlightVisibleState::NoAutoHighlightVisibleState(
  169. HighlightStateFactory* state_factory,
  170. base::TimeDelta animation_duration)
  171. : InkDropImpl::HighlightState(state_factory),
  172. animation_duration_(animation_duration) {}
  173. void InkDropImpl::NoAutoHighlightVisibleState::Enter() {
  174. GetInkDrop()->SetHighlight(true, animation_duration_);
  175. }
  176. void InkDropImpl::NoAutoHighlightVisibleState::ShowOnHoverChanged() {
  177. HandleHoverAndFocusChangeChanges(
  178. GetInkDrop()->hover_highlight_fade_duration().value_or(
  179. kHighlightFadeOutOnHoverChangeDuration));
  180. }
  181. void InkDropImpl::NoAutoHighlightVisibleState::OnHoverChanged() {
  182. HandleHoverAndFocusChangeChanges(
  183. GetInkDrop()->hover_highlight_fade_duration().value_or(
  184. kHighlightFadeOutOnHoverChangeDuration));
  185. }
  186. void InkDropImpl::NoAutoHighlightVisibleState::ShowOnFocusChanged() {
  187. HandleHoverAndFocusChangeChanges(kHighlightFadeOutOnFocusChangeDuration);
  188. }
  189. void InkDropImpl::NoAutoHighlightVisibleState::OnFocusChanged() {
  190. HandleHoverAndFocusChangeChanges(kHighlightFadeOutOnFocusChangeDuration);
  191. }
  192. void InkDropImpl::NoAutoHighlightVisibleState::HandleHoverAndFocusChangeChanges(
  193. base::TimeDelta animation_duration) {
  194. if (!GetInkDrop()->ShouldHighlight()) {
  195. GetInkDrop()->SetHighlightState(
  196. state_factory()->CreateHiddenState(animation_duration));
  197. }
  198. }
  199. void InkDropImpl::NoAutoHighlightVisibleState::AnimationStarted(
  200. InkDropState ink_drop_state) {}
  201. void InkDropImpl::NoAutoHighlightVisibleState::AnimationEnded(
  202. InkDropState ink_drop_state,
  203. InkDropAnimationEndedReason reason) {}
  204. //
  205. // AutoHighlightMode::HIDE_ON_RIPPLE states
  206. //
  207. // Extends the base hidden state to re-show the highlight after the ripple
  208. // becomes hidden.
  209. class InkDropImpl::HideHighlightOnRippleHiddenState
  210. : public InkDropImpl::NoAutoHighlightHiddenState {
  211. public:
  212. HideHighlightOnRippleHiddenState(HighlightStateFactory* state_factory,
  213. base::TimeDelta animation_duration);
  214. HideHighlightOnRippleHiddenState(const HideHighlightOnRippleHiddenState&) =
  215. delete;
  216. HideHighlightOnRippleHiddenState& operator=(
  217. const HideHighlightOnRippleHiddenState&) = delete;
  218. // InkDropImpl::NoAutoHighlightHiddenState:
  219. void ShowOnHoverChanged() override;
  220. void OnHoverChanged() override;
  221. void ShowOnFocusChanged() override;
  222. void OnFocusChanged() override;
  223. void AnimationStarted(InkDropState ink_drop_state) override;
  224. void AnimationEnded(InkDropState ink_drop_state,
  225. InkDropAnimationEndedReason reason) override;
  226. private:
  227. // Starts the |highlight_after_ripple_timer_|. This will stop the current
  228. // |highlight_after_ripple_timer_| instance if it exists.
  229. void StartHighlightAfterRippleTimer();
  230. // Callback for when the |highlight_after_ripple_timer_| fires. Transitions to
  231. // a visible state if the ink drop should be highlighted.
  232. void HighlightAfterRippleTimerFired();
  233. // The timer used to delay the highlight fade in after an ink drop ripple
  234. // animation.
  235. std::unique_ptr<base::OneShotTimer> highlight_after_ripple_timer_;
  236. };
  237. // Extends the base visible state to hide the highlight when the ripple becomes
  238. // visible.
  239. class InkDropImpl::HideHighlightOnRippleVisibleState
  240. : public InkDropImpl::NoAutoHighlightVisibleState {
  241. public:
  242. HideHighlightOnRippleVisibleState(HighlightStateFactory* state_factory,
  243. base::TimeDelta animation_duration);
  244. HideHighlightOnRippleVisibleState(const HideHighlightOnRippleVisibleState&) =
  245. delete;
  246. HideHighlightOnRippleVisibleState& operator=(
  247. const HideHighlightOnRippleVisibleState&) = delete;
  248. // InkDropImpl::NoAutoHighlightVisibleState:
  249. void AnimationStarted(InkDropState ink_drop_state) override;
  250. };
  251. // HideHighlightOnRippleHiddenState definition
  252. InkDropImpl::HideHighlightOnRippleHiddenState::HideHighlightOnRippleHiddenState(
  253. HighlightStateFactory* state_factory,
  254. base::TimeDelta animation_duration)
  255. : InkDropImpl::NoAutoHighlightHiddenState(state_factory,
  256. animation_duration),
  257. highlight_after_ripple_timer_(nullptr) {}
  258. void InkDropImpl::HideHighlightOnRippleHiddenState::ShowOnHoverChanged() {
  259. if (GetInkDrop()->GetTargetInkDropState() != InkDropState::HIDDEN)
  260. return;
  261. NoAutoHighlightHiddenState::ShowOnHoverChanged();
  262. }
  263. void InkDropImpl::HideHighlightOnRippleHiddenState::OnHoverChanged() {
  264. if (GetInkDrop()->GetTargetInkDropState() != InkDropState::HIDDEN)
  265. return;
  266. NoAutoHighlightHiddenState::OnHoverChanged();
  267. }
  268. void InkDropImpl::HideHighlightOnRippleHiddenState::ShowOnFocusChanged() {
  269. if (GetInkDrop()->GetTargetInkDropState() != InkDropState::HIDDEN)
  270. return;
  271. NoAutoHighlightHiddenState::ShowOnFocusChanged();
  272. }
  273. void InkDropImpl::HideHighlightOnRippleHiddenState::OnFocusChanged() {
  274. if (GetInkDrop()->GetTargetInkDropState() != InkDropState::HIDDEN)
  275. return;
  276. NoAutoHighlightHiddenState::OnFocusChanged();
  277. }
  278. void InkDropImpl::HideHighlightOnRippleHiddenState::AnimationStarted(
  279. InkDropState ink_drop_state) {
  280. if (ink_drop_state == views::InkDropState::DEACTIVATED &&
  281. GetInkDrop()->ShouldHighlightBasedOnFocus()) {
  282. // It's possible to get animation started events when destroying the
  283. // |ink_drop_ripple_|.
  284. // TODO(bruthig): Investigate if the animation framework can address this
  285. // issue instead. See https://crbug.com/663335.
  286. InkDropImpl* ink_drop = GetInkDrop();
  287. HighlightStateFactory* highlight_state_factory = state_factory();
  288. if (ink_drop->ink_drop_ripple_)
  289. ink_drop->ink_drop_ripple_->SnapToHidden();
  290. // |this| may be destroyed after SnapToHidden(), so be sure not to access
  291. // |any members.
  292. ink_drop->SetHighlightState(
  293. highlight_state_factory->CreateVisibleState(base::TimeDelta()));
  294. }
  295. }
  296. void InkDropImpl::HideHighlightOnRippleHiddenState::AnimationEnded(
  297. InkDropState ink_drop_state,
  298. InkDropAnimationEndedReason reason) {
  299. if (ink_drop_state == InkDropState::HIDDEN) {
  300. // Re-highlight, as necessary. For hover, there's a delay; for focus, jump
  301. // straight into the animation.
  302. if (GetInkDrop()->ShouldHighlightBasedOnFocus()) {
  303. GetInkDrop()->SetHighlightState(
  304. state_factory()->CreateVisibleState(base::TimeDelta()));
  305. return;
  306. } else {
  307. StartHighlightAfterRippleTimer();
  308. }
  309. }
  310. }
  311. void InkDropImpl::HideHighlightOnRippleHiddenState::
  312. StartHighlightAfterRippleTimer() {
  313. highlight_after_ripple_timer_ = std::make_unique<base::OneShotTimer>();
  314. highlight_after_ripple_timer_->Start(
  315. FROM_HERE, kHoverFadeInAfterRippleDelay,
  316. base::BindOnce(&InkDropImpl::HideHighlightOnRippleHiddenState::
  317. HighlightAfterRippleTimerFired,
  318. base::Unretained(this)));
  319. }
  320. void InkDropImpl::HideHighlightOnRippleHiddenState::
  321. HighlightAfterRippleTimerFired() {
  322. highlight_after_ripple_timer_.reset();
  323. if (GetInkDrop()->GetTargetInkDropState() == InkDropState::HIDDEN &&
  324. GetInkDrop()->ShouldHighlight()) {
  325. GetInkDrop()->SetHighlightState(state_factory()->CreateVisibleState(
  326. kHighlightFadeInOnRippleHidingDuration));
  327. }
  328. }
  329. // HideHighlightOnRippleVisibleState definition
  330. InkDropImpl::HideHighlightOnRippleVisibleState::
  331. HideHighlightOnRippleVisibleState(HighlightStateFactory* state_factory,
  332. base::TimeDelta animation_duration)
  333. : InkDropImpl::NoAutoHighlightVisibleState(state_factory,
  334. animation_duration) {}
  335. void InkDropImpl::HideHighlightOnRippleVisibleState::AnimationStarted(
  336. InkDropState ink_drop_state) {
  337. if (ink_drop_state != InkDropState::HIDDEN) {
  338. GetInkDrop()->SetHighlightState(state_factory()->CreateHiddenState(
  339. kHighlightFadeOutOnRippleShowingDuration));
  340. }
  341. }
  342. //
  343. // AutoHighlightMode::SHOW_ON_RIPPLE states
  344. //
  345. // Extends the base hidden state to show the highlight when the ripple becomes
  346. // visible.
  347. class InkDropImpl::ShowHighlightOnRippleHiddenState
  348. : public InkDropImpl::NoAutoHighlightHiddenState {
  349. public:
  350. ShowHighlightOnRippleHiddenState(HighlightStateFactory* state_factory,
  351. base::TimeDelta animation_duration);
  352. ShowHighlightOnRippleHiddenState(const ShowHighlightOnRippleHiddenState&) =
  353. delete;
  354. ShowHighlightOnRippleHiddenState& operator=(
  355. const ShowHighlightOnRippleHiddenState&) = delete;
  356. // InkDropImpl::NoAutoHighlightHiddenState:
  357. void AnimationStarted(InkDropState ink_drop_state) override;
  358. };
  359. // Extends the base visible state to hide the highlight when the ripple becomes
  360. // hidden.
  361. class InkDropImpl::ShowHighlightOnRippleVisibleState
  362. : public InkDropImpl::NoAutoHighlightVisibleState {
  363. public:
  364. ShowHighlightOnRippleVisibleState(HighlightStateFactory* state_factory,
  365. base::TimeDelta animation_duration);
  366. ShowHighlightOnRippleVisibleState(const ShowHighlightOnRippleVisibleState&) =
  367. delete;
  368. ShowHighlightOnRippleVisibleState& operator=(
  369. const ShowHighlightOnRippleVisibleState&) = delete;
  370. // InkDropImpl::NoAutoHighlightVisibleState:
  371. void ShowOnHoverChanged() override;
  372. void OnHoverChanged() override;
  373. void ShowOnFocusChanged() override;
  374. void OnFocusChanged() override;
  375. void AnimationStarted(InkDropState ink_drop_state) override;
  376. };
  377. // ShowHighlightOnRippleHiddenState definition
  378. InkDropImpl::ShowHighlightOnRippleHiddenState::ShowHighlightOnRippleHiddenState(
  379. HighlightStateFactory* state_factory,
  380. base::TimeDelta animation_duration)
  381. : InkDropImpl::NoAutoHighlightHiddenState(state_factory,
  382. animation_duration) {}
  383. void InkDropImpl::ShowHighlightOnRippleHiddenState::AnimationStarted(
  384. InkDropState ink_drop_state) {
  385. if (ink_drop_state != views::InkDropState::HIDDEN) {
  386. GetInkDrop()->SetHighlightState(state_factory()->CreateVisibleState(
  387. kHighlightFadeInOnRippleShowingDuration));
  388. }
  389. }
  390. // ShowHighlightOnRippleVisibleState definition
  391. InkDropImpl::ShowHighlightOnRippleVisibleState::
  392. ShowHighlightOnRippleVisibleState(HighlightStateFactory* state_factory,
  393. base::TimeDelta animation_duration)
  394. : InkDropImpl::NoAutoHighlightVisibleState(state_factory,
  395. animation_duration) {}
  396. void InkDropImpl::ShowHighlightOnRippleVisibleState::ShowOnHoverChanged() {
  397. if (GetInkDrop()->GetTargetInkDropState() != InkDropState::HIDDEN)
  398. return;
  399. NoAutoHighlightVisibleState::ShowOnHoverChanged();
  400. }
  401. void InkDropImpl::ShowHighlightOnRippleVisibleState::OnHoverChanged() {
  402. if (GetInkDrop()->GetTargetInkDropState() != InkDropState::HIDDEN)
  403. return;
  404. NoAutoHighlightVisibleState::OnHoverChanged();
  405. }
  406. void InkDropImpl::ShowHighlightOnRippleVisibleState::ShowOnFocusChanged() {
  407. if (GetInkDrop()->GetTargetInkDropState() != InkDropState::HIDDEN)
  408. return;
  409. NoAutoHighlightVisibleState::ShowOnFocusChanged();
  410. }
  411. void InkDropImpl::ShowHighlightOnRippleVisibleState::OnFocusChanged() {
  412. if (GetInkDrop()->GetTargetInkDropState() != InkDropState::HIDDEN)
  413. return;
  414. NoAutoHighlightVisibleState::OnFocusChanged();
  415. }
  416. void InkDropImpl::ShowHighlightOnRippleVisibleState::AnimationStarted(
  417. InkDropState ink_drop_state) {
  418. if (ink_drop_state == InkDropState::HIDDEN &&
  419. !GetInkDrop()->ShouldHighlight()) {
  420. GetInkDrop()->SetHighlightState(state_factory()->CreateHiddenState(
  421. kHighlightFadeOutOnRippleHidingDuration));
  422. }
  423. }
  424. InkDropImpl::HighlightStateFactory::HighlightStateFactory(
  425. InkDropImpl::AutoHighlightMode highlight_mode,
  426. InkDropImpl* ink_drop)
  427. : highlight_mode_(highlight_mode), ink_drop_(ink_drop) {}
  428. std::unique_ptr<InkDropImpl::HighlightState>
  429. InkDropImpl::HighlightStateFactory::CreateStartState() {
  430. switch (highlight_mode_) {
  431. case InkDropImpl::AutoHighlightMode::NONE:
  432. return std::make_unique<NoAutoHighlightHiddenState>(this,
  433. base::TimeDelta());
  434. case InkDropImpl::AutoHighlightMode::HIDE_ON_RIPPLE:
  435. return std::make_unique<HideHighlightOnRippleHiddenState>(
  436. this, base::TimeDelta());
  437. case InkDropImpl::AutoHighlightMode::SHOW_ON_RIPPLE:
  438. return std::make_unique<ShowHighlightOnRippleHiddenState>(
  439. this, base::TimeDelta());
  440. }
  441. // Required for some compilers.
  442. NOTREACHED();
  443. return nullptr;
  444. }
  445. std::unique_ptr<InkDropImpl::HighlightState>
  446. InkDropImpl::HighlightStateFactory::CreateHiddenState(
  447. base::TimeDelta animation_duration) {
  448. switch (highlight_mode_) {
  449. case InkDropImpl::AutoHighlightMode::NONE:
  450. return std::make_unique<NoAutoHighlightHiddenState>(this,
  451. animation_duration);
  452. case InkDropImpl::AutoHighlightMode::HIDE_ON_RIPPLE:
  453. return std::make_unique<HideHighlightOnRippleHiddenState>(
  454. this, animation_duration);
  455. case InkDropImpl::AutoHighlightMode::SHOW_ON_RIPPLE:
  456. return std::make_unique<ShowHighlightOnRippleHiddenState>(
  457. this, animation_duration);
  458. }
  459. // Required for some compilers.
  460. NOTREACHED();
  461. return nullptr;
  462. }
  463. std::unique_ptr<InkDropImpl::HighlightState>
  464. InkDropImpl::HighlightStateFactory::CreateVisibleState(
  465. base::TimeDelta animation_duration) {
  466. switch (highlight_mode_) {
  467. case InkDropImpl::AutoHighlightMode::NONE:
  468. return std::make_unique<NoAutoHighlightVisibleState>(this,
  469. animation_duration);
  470. case InkDropImpl::AutoHighlightMode::HIDE_ON_RIPPLE:
  471. return std::make_unique<HideHighlightOnRippleVisibleState>(
  472. this, animation_duration);
  473. case InkDropImpl::AutoHighlightMode::SHOW_ON_RIPPLE:
  474. return std::make_unique<ShowHighlightOnRippleVisibleState>(
  475. this, animation_duration);
  476. }
  477. // Required for some compilers.
  478. NOTREACHED();
  479. return nullptr;
  480. }
  481. InkDropImpl::InkDropImpl(InkDropHost* ink_drop_host,
  482. const gfx::Size& host_size,
  483. AutoHighlightMode auto_highlight_mode)
  484. : ink_drop_host_(ink_drop_host),
  485. highlight_state_factory_(auto_highlight_mode, this),
  486. root_layer_(new ui::Layer(ui::LAYER_NOT_DRAWN)) {
  487. root_layer_->SetBounds(gfx::Rect(host_size));
  488. root_layer_->SetName("InkDropImpl:RootLayer");
  489. SetHighlightState(highlight_state_factory_.CreateStartState());
  490. }
  491. InkDropImpl::~InkDropImpl() {
  492. destroying_ = true;
  493. // Setting a no-op state prevents animations from being triggered on a null
  494. // |ink_drop_ripple_| as a side effect of the tear down.
  495. SetHighlightState(std::make_unique<DestroyingHighlightState>());
  496. // Explicitly destroy the InkDropRipple so that this still exists if
  497. // views::InkDropRippleObserver methods are called on this.
  498. DestroyInkDropRipple();
  499. DestroyInkDropHighlight();
  500. }
  501. void InkDropImpl::HostSizeChanged(const gfx::Size& new_size) {
  502. // |root_layer_| should fill the entire host because it affects the clipping
  503. // when a mask layer is applied to it. This will not affect clipping if no
  504. // mask layer is set.
  505. root_layer_->SetBounds(gfx::Rect(new_size) +
  506. root_layer_->bounds().OffsetFromOrigin());
  507. const bool create_ink_drop_ripple = !!ink_drop_ripple_;
  508. InkDropState state = GetTargetInkDropState();
  509. if (ShouldAnimateToHidden(state))
  510. state = views::InkDropState::HIDDEN;
  511. DestroyInkDropRipple();
  512. if (highlight_) {
  513. bool visible = highlight_->IsFadingInOrVisible();
  514. DestroyInkDropHighlight();
  515. // Both the ripple and the highlight must have been destroyed before
  516. // recreating either of them otherwise the mask will not get recreated.
  517. CreateInkDropHighlight();
  518. if (visible)
  519. highlight_->FadeIn(base::TimeDelta());
  520. }
  521. if (create_ink_drop_ripple) {
  522. CreateInkDropRipple();
  523. ink_drop_ripple_->SnapToState(state);
  524. }
  525. }
  526. void InkDropImpl::HostTransformChanged(const gfx::Transform& new_transform) {
  527. // If the host has a transform applied, the root and its children layers
  528. // should be affected too.
  529. root_layer_->SetTransform(new_transform);
  530. }
  531. InkDropState InkDropImpl::GetTargetInkDropState() const {
  532. if (!ink_drop_ripple_)
  533. return InkDropState::HIDDEN;
  534. return ink_drop_ripple_->target_ink_drop_state();
  535. }
  536. void InkDropImpl::AnimateToState(InkDropState ink_drop_state) {
  537. // Never animate hidden -> hidden, since that will add layers which may never
  538. // be needed. Other same-state transitions may restart animations.
  539. if (ink_drop_state == InkDropState::HIDDEN &&
  540. GetTargetInkDropState() == InkDropState::HIDDEN)
  541. return;
  542. DestroyHiddenTargetedAnimations();
  543. if (!ink_drop_ripple_)
  544. CreateInkDropRipple();
  545. ink_drop_ripple_->AnimateToState(ink_drop_state);
  546. }
  547. void InkDropImpl::SetHoverHighlightFadeDuration(base::TimeDelta duration) {
  548. hover_highlight_fade_duration_ = duration;
  549. }
  550. void InkDropImpl::UseDefaultHoverHighlightFadeDuration() {
  551. hover_highlight_fade_duration_.reset();
  552. }
  553. void InkDropImpl::SnapToActivated() {
  554. DestroyHiddenTargetedAnimations();
  555. if (!ink_drop_ripple_)
  556. CreateInkDropRipple();
  557. ink_drop_ripple_->SnapToActivated();
  558. }
  559. void InkDropImpl::SnapToHidden() {
  560. DestroyHiddenTargetedAnimations();
  561. if (!ink_drop_ripple_)
  562. return;
  563. ink_drop_ripple_->SnapToHidden();
  564. }
  565. void InkDropImpl::SetHovered(bool is_hovered) {
  566. is_hovered_ = is_hovered;
  567. highlight_state_->OnHoverChanged();
  568. }
  569. void InkDropImpl::SetFocused(bool is_focused) {
  570. is_focused_ = is_focused;
  571. highlight_state_->OnFocusChanged();
  572. }
  573. bool InkDropImpl::IsHighlightFadingInOrVisible() const {
  574. return highlight_ && highlight_->IsFadingInOrVisible();
  575. }
  576. void InkDropImpl::SetShowHighlightOnHover(bool show_highlight_on_hover) {
  577. show_highlight_on_hover_ = show_highlight_on_hover;
  578. highlight_state_->ShowOnHoverChanged();
  579. }
  580. void InkDropImpl::SetShowHighlightOnFocus(bool show_highlight_on_focus) {
  581. show_highlight_on_focus_ = show_highlight_on_focus;
  582. highlight_state_->ShowOnFocusChanged();
  583. }
  584. void InkDropImpl::DestroyHiddenTargetedAnimations() {
  585. if (ink_drop_ripple_ &&
  586. (ink_drop_ripple_->target_ink_drop_state() == InkDropState::HIDDEN ||
  587. ShouldAnimateToHidden(ink_drop_ripple_->target_ink_drop_state()))) {
  588. DestroyInkDropRipple();
  589. }
  590. }
  591. void InkDropImpl::CreateInkDropRipple() {
  592. DCHECK(!destroying_);
  593. DestroyInkDropRipple();
  594. ink_drop_ripple_ = ink_drop_host_->CreateInkDropRipple();
  595. ink_drop_ripple_->set_observer(this);
  596. root_layer_->Add(ink_drop_ripple_->GetRootLayer());
  597. AddRootLayerToHostIfNeeded();
  598. }
  599. void InkDropImpl::DestroyInkDropRipple() {
  600. if (!ink_drop_ripple_)
  601. return;
  602. // Ensures no observer callback happens from removing from |root_layer_|
  603. // or destroying |ink_drop_ripple_|. Speculative fix for crashes in
  604. // https://crbug.com/1088432 and https://crbug.com/1099844.
  605. ink_drop_ripple_->set_observer(nullptr);
  606. root_layer_->Remove(ink_drop_ripple_->GetRootLayer());
  607. ink_drop_ripple_.reset();
  608. RemoveRootLayerFromHostIfNeeded();
  609. }
  610. void InkDropImpl::CreateInkDropHighlight() {
  611. DCHECK(!destroying_);
  612. DestroyInkDropHighlight();
  613. highlight_ = ink_drop_host_->CreateInkDropHighlight();
  614. DCHECK(highlight_);
  615. // If the platform provides HC colors, we need to show them fully on hover and
  616. // press.
  617. if (views::UsingPlatformHighContrastInkDrop(ink_drop_host_->host_view()))
  618. highlight_->set_visible_opacity(1.0f);
  619. highlight_->set_observer(this);
  620. root_layer_->Add(highlight_->layer());
  621. AddRootLayerToHostIfNeeded();
  622. }
  623. void InkDropImpl::DestroyInkDropHighlight() {
  624. if (!highlight_)
  625. return;
  626. // Ensures no observer callback happens from removing from |root_layer_|
  627. // or destroying |highlight_|. Speculative fix for crashes in
  628. // https://crbug.com/1088432 and https://crbug.com/1099844.
  629. highlight_->set_observer(nullptr);
  630. root_layer_->Remove(highlight_->layer());
  631. highlight_.reset();
  632. RemoveRootLayerFromHostIfNeeded();
  633. }
  634. void InkDropImpl::AddRootLayerToHostIfNeeded() {
  635. DCHECK(highlight_ || ink_drop_ripple_);
  636. DCHECK(!root_layer_->children().empty());
  637. if (!root_layer_added_to_host_) {
  638. root_layer_added_to_host_ = true;
  639. ink_drop_host_->AddInkDropLayer(root_layer_.get());
  640. }
  641. }
  642. void InkDropImpl::RemoveRootLayerFromHostIfNeeded() {
  643. if (root_layer_added_to_host_ && !highlight_ && !ink_drop_ripple_) {
  644. root_layer_added_to_host_ = false;
  645. ink_drop_host_->RemoveInkDropLayer(root_layer_.get());
  646. }
  647. }
  648. // -----------------------------------------------------------------------------
  649. // views::InkDropRippleObserver:
  650. void InkDropImpl::AnimationStarted(InkDropState ink_drop_state) {
  651. // AnimationStarted should only be called from |ink_drop_ripple_|.
  652. DCHECK(ink_drop_ripple_);
  653. highlight_state_->AnimationStarted(ink_drop_state);
  654. NotifyInkDropAnimationStarted();
  655. }
  656. void InkDropImpl::AnimationEnded(InkDropState ink_drop_state,
  657. InkDropAnimationEndedReason reason) {
  658. highlight_state_->AnimationEnded(ink_drop_state, reason);
  659. NotifyInkDropRippleAnimationEnded(ink_drop_state);
  660. if (reason != InkDropAnimationEndedReason::SUCCESS)
  661. return;
  662. // |ink_drop_ripple_| might be null during destruction.
  663. if (!ink_drop_ripple_)
  664. return;
  665. if (ShouldAnimateToHidden(ink_drop_state)) {
  666. ink_drop_ripple_->AnimateToState(views::InkDropState::HIDDEN);
  667. } else if (ink_drop_state == views::InkDropState::HIDDEN) {
  668. // TODO(bruthig): Investigate whether creating and destroying
  669. // InkDropRipples is expensive and consider creating an
  670. // InkDropRipplePool. See www.crbug.com/522175.
  671. DestroyInkDropRipple();
  672. }
  673. }
  674. // -----------------------------------------------------------------------------
  675. // views::InkDropHighlightObserver:
  676. void InkDropImpl::AnimationStarted(
  677. InkDropHighlight::AnimationType animation_type) {
  678. NotifyInkDropAnimationStarted();
  679. }
  680. void InkDropImpl::AnimationEnded(InkDropHighlight::AnimationType animation_type,
  681. InkDropAnimationEndedReason reason) {
  682. if (animation_type == InkDropHighlight::AnimationType::kFadeOut &&
  683. reason == InkDropAnimationEndedReason::SUCCESS) {
  684. DestroyInkDropHighlight();
  685. }
  686. }
  687. void InkDropImpl::SetHighlight(bool should_highlight,
  688. base::TimeDelta animation_duration) {
  689. if (IsHighlightFadingInOrVisible() == should_highlight)
  690. return;
  691. if (should_highlight) {
  692. CreateInkDropHighlight();
  693. highlight_->FadeIn(animation_duration);
  694. } else {
  695. highlight_->FadeOut(animation_duration);
  696. }
  697. ink_drop_host_->OnInkDropHighlightedChanged();
  698. }
  699. bool InkDropImpl::ShouldHighlight() const {
  700. return ShouldHighlightBasedOnFocus() ||
  701. (show_highlight_on_hover_ && is_hovered_);
  702. }
  703. bool InkDropImpl::ShouldHighlightBasedOnFocus() const {
  704. return show_highlight_on_focus_ && is_focused_;
  705. }
  706. void InkDropImpl::SetHighlightState(
  707. std::unique_ptr<HighlightState> highlight_state) {
  708. ExitHighlightState();
  709. highlight_state_ = std::move(highlight_state);
  710. highlight_state_->Enter();
  711. }
  712. void InkDropImpl::ExitHighlightState() {
  713. DCHECK(!exiting_highlight_state_) << "HighlightStates should not be changed "
  714. "within a call to "
  715. "HighlightState::Exit().";
  716. if (highlight_state_) {
  717. base::AutoReset<bool> exit_guard(&exiting_highlight_state_, true);
  718. highlight_state_->Exit();
  719. }
  720. highlight_state_ = nullptr;
  721. }
  722. } // namespace views