Event.cpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. /*
  2. * Copyright (c) 2020, the SerenityOS developers.
  3. * Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include <AK/TypeCasts.h>
  8. #include <LibWeb/DOM/Event.h>
  9. #include <LibWeb/DOM/Node.h>
  10. #include <LibWeb/DOM/ShadowRoot.h>
  11. namespace Web::DOM {
  12. void Event::append_to_path(EventTarget& invocation_target, RefPtr<EventTarget> shadow_adjusted_target, RefPtr<EventTarget> related_target, TouchTargetList& touch_targets, bool slot_in_closed_tree)
  13. {
  14. bool invocation_target_in_shadow_tree = false;
  15. bool root_of_closed_tree = false;
  16. if (is<Node>(invocation_target)) {
  17. auto& invocation_target_node = verify_cast<Node>(invocation_target);
  18. if (is<ShadowRoot>(invocation_target_node.root()))
  19. invocation_target_in_shadow_tree = true;
  20. if (is<ShadowRoot>(invocation_target_node)) {
  21. auto& invocation_target_shadow_root = verify_cast<ShadowRoot>(invocation_target_node);
  22. root_of_closed_tree = invocation_target_shadow_root.closed();
  23. }
  24. }
  25. m_path.append({ invocation_target, invocation_target_in_shadow_tree, shadow_adjusted_target, related_target, touch_targets, root_of_closed_tree, slot_in_closed_tree, m_path.size() });
  26. }
  27. void Event::set_cancelled_flag()
  28. {
  29. if (m_cancelable && !m_in_passive_listener)
  30. m_cancelled = true;
  31. }
  32. // https://dom.spec.whatwg.org/#concept-event-initialize
  33. void Event::initialize(const String& type, bool bubbles, bool cancelable)
  34. {
  35. m_initialized = true;
  36. m_stop_propagation = false;
  37. m_stop_immediate_propagation = false;
  38. m_cancelled = false;
  39. m_is_trusted = false;
  40. m_target = nullptr;
  41. m_type = type;
  42. m_bubbles = bubbles;
  43. m_cancelable = cancelable;
  44. }
  45. // https://dom.spec.whatwg.org/#dom-event-initevent
  46. void Event::init_event(const String& type, bool bubbles, bool cancelable)
  47. {
  48. if (m_dispatch)
  49. return;
  50. initialize(type, bubbles, cancelable);
  51. }
  52. // https://dom.spec.whatwg.org/#dom-event-timestamp
  53. double Event::time_stamp() const
  54. {
  55. return m_time_stamp;
  56. }
  57. // https://dom.spec.whatwg.org/#dom-event-composedpath
  58. NonnullRefPtrVector<EventTarget> Event::composed_path() const
  59. {
  60. // 1. Let composedPath be an empty list.
  61. NonnullRefPtrVector<EventTarget> composed_path;
  62. // 2. Let path be this’s path. (NOTE: Not necessary)
  63. // 3. If path is empty, then return composedPath.
  64. if (m_path.is_empty())
  65. return composed_path;
  66. // 4. Let currentTarget be this’s currentTarget attribute value. (NOTE: Not necessary)
  67. // 5. Append currentTarget to composedPath.
  68. // NOTE: If path is not empty, then the event is being dispatched and will have a currentTarget.
  69. VERIFY(m_current_target);
  70. composed_path.append(*m_current_target);
  71. // 6. Let currentTargetIndex be 0.
  72. size_t current_target_index = 0;
  73. // 7. Let currentTargetHiddenSubtreeLevel be 0.
  74. size_t current_target_hidden_subtree_level = 0;
  75. // 8. Let index be path’s size − 1.
  76. // 9. While index is greater than or equal to 0:
  77. for (ssize_t index = m_path.size() - 1; index >= 0; --index) {
  78. auto& path_entry = m_path.at(index);
  79. // 1. If path[index]'s root-of-closed-tree is true, then increase currentTargetHiddenSubtreeLevel by 1.
  80. if (path_entry.root_of_closed_tree)
  81. ++current_target_hidden_subtree_level;
  82. // 2. If path[index]'s invocation target is currentTarget, then set currentTargetIndex to index and break.
  83. if (path_entry.invocation_target == m_current_target) {
  84. current_target_index = index;
  85. break;
  86. }
  87. // 3. If path[index]'s slot-in-closed-tree is true, then decrease currentTargetHiddenSubtreeLevel by 1.
  88. if (path_entry.slot_in_closed_tree)
  89. --current_target_hidden_subtree_level;
  90. // 4. Decrease index by 1.
  91. }
  92. // 10. Let currentHiddenLevel and maxHiddenLevel be currentTargetHiddenSubtreeLevel.
  93. size_t current_hidden_level = current_target_hidden_subtree_level;
  94. size_t max_hidden_level = current_target_hidden_subtree_level;
  95. // 11. Set index to currentTargetIndex − 1.
  96. // 12. While index is greater than or equal to 0:
  97. for (ssize_t index = current_target_index - 1; index >= 0; --index) {
  98. auto& path_entry = m_path.at(index);
  99. // 1. If path[index]'s root-of-closed-tree is true, then increase currentHiddenLevel by 1.
  100. if (path_entry.root_of_closed_tree)
  101. ++current_hidden_level;
  102. // 2. If currentHiddenLevel is less than or equal to maxHiddenLevel, then prepend path[index]'s invocation target to composedPath.
  103. if (current_hidden_level <= max_hidden_level) {
  104. VERIFY(path_entry.invocation_target);
  105. composed_path.prepend(*path_entry.invocation_target);
  106. }
  107. // 3. If path[index]'s slot-in-closed-tree is true, then:
  108. if (path_entry.slot_in_closed_tree) {
  109. // 1. Decrease currentHiddenLevel by 1.
  110. --current_hidden_level;
  111. // 2. If currentHiddenLevel is less than maxHiddenLevel, then set maxHiddenLevel to currentHiddenLevel.
  112. if (current_hidden_level < max_hidden_level)
  113. max_hidden_level = current_hidden_level;
  114. }
  115. // 4. Decrease index by 1.
  116. }
  117. // 13. Set currentHiddenLevel and maxHiddenLevel to currentTargetHiddenSubtreeLevel.
  118. current_hidden_level = current_target_hidden_subtree_level;
  119. max_hidden_level = current_target_hidden_subtree_level;
  120. // 14. Set index to currentTargetIndex + 1.
  121. // 15. While index is less than path’s size:
  122. for (size_t index = current_target_index + 1; index < m_path.size(); ++index) {
  123. auto& path_entry = m_path.at(index);
  124. // 1. If path[index]'s slot-in-closed-tree is true, then increase currentHiddenLevel by 1.
  125. if (path_entry.slot_in_closed_tree)
  126. ++current_hidden_level;
  127. // 2. If currentHiddenLevel is less than or equal to maxHiddenLevel, then append path[index]'s invocation target to composedPath.
  128. if (current_hidden_level <= max_hidden_level) {
  129. VERIFY(path_entry.invocation_target);
  130. composed_path.append(*path_entry.invocation_target);
  131. }
  132. // 3. If path[index]'s root-of-closed-tree is true, then:
  133. if (path_entry.root_of_closed_tree) {
  134. // 1. Decrease currentHiddenLevel by 1.
  135. --current_hidden_level;
  136. // 2. If currentHiddenLevel is less than maxHiddenLevel, then set maxHiddenLevel to currentHiddenLevel.
  137. if (current_hidden_level < max_hidden_level)
  138. max_hidden_level = current_hidden_level;
  139. }
  140. // 4. Increase index by 1.
  141. }
  142. // 16. Return composedPath.
  143. return composed_path;
  144. }
  145. }