Internals.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. /*
  2. * Copyright (c) 2023, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibJS/Runtime/VM.h>
  7. #include <LibWeb/Bindings/InternalsPrototype.h>
  8. #include <LibWeb/Bindings/Intrinsics.h>
  9. #include <LibWeb/DOM/Document.h>
  10. #include <LibWeb/DOM/Event.h>
  11. #include <LibWeb/DOM/EventTarget.h>
  12. #include <LibWeb/HTML/BrowsingContext.h>
  13. #include <LibWeb/HTML/HTMLElement.h>
  14. #include <LibWeb/HTML/Window.h>
  15. #include <LibWeb/Internals/Internals.h>
  16. #include <LibWeb/Page/InputEvent.h>
  17. #include <LibWeb/Page/Page.h>
  18. #include <LibWeb/Painting/PaintableBox.h>
  19. #include <LibWeb/Painting/ViewportPaintable.h>
  20. namespace Web::Internals {
  21. JS_DEFINE_ALLOCATOR(Internals);
  22. Internals::Internals(JS::Realm& realm)
  23. : Bindings::PlatformObject(realm)
  24. {
  25. }
  26. Internals::~Internals() = default;
  27. void Internals::initialize(JS::Realm& realm)
  28. {
  29. Base::initialize(realm);
  30. WEB_SET_PROTOTYPE_FOR_INTERFACE(Internals);
  31. }
  32. void Internals::signal_text_test_is_done()
  33. {
  34. global_object().browsing_context()->page().client().page_did_finish_text_test();
  35. }
  36. void Internals::gc()
  37. {
  38. vm().heap().collect_garbage();
  39. }
  40. JS::Object* Internals::hit_test(double x, double y)
  41. {
  42. auto* active_document = global_object().browsing_context()->top_level_browsing_context()->active_document();
  43. // NOTE: Force a layout update just before hit testing. This is because the current layout tree, which is required
  44. // for stacking context traversal, might not exist if this call occurs between the tear_down_layout_tree()
  45. // and update_layout() calls
  46. active_document->update_layout();
  47. auto result = active_document->paintable_box()->hit_test({ x, y }, Painting::HitTestType::Exact);
  48. if (result.has_value()) {
  49. auto hit_tеsting_result = JS::Object::create(realm(), nullptr);
  50. hit_tеsting_result->define_direct_property("node", result->dom_node(), JS::default_attributes);
  51. hit_tеsting_result->define_direct_property("indexInNode", JS::Value(result->index_in_node), JS::default_attributes);
  52. return hit_tеsting_result;
  53. }
  54. return nullptr;
  55. }
  56. void Internals::send_text(HTML::HTMLElement& target, String const& text)
  57. {
  58. auto& page = global_object().browsing_context()->page();
  59. target.focus();
  60. for (auto code_point : text.code_points())
  61. page.handle_keydown(UIEvents::code_point_to_key_code(code_point), 0, code_point);
  62. }
  63. void Internals::commit_text()
  64. {
  65. global_object().browsing_context()->page().handle_keydown(UIEvents::Key_Return, 0, 0);
  66. }
  67. void Internals::click(double x, double y)
  68. {
  69. click(x, y, UIEvents::MouseButton::Primary);
  70. }
  71. void Internals::middle_click(double x, double y)
  72. {
  73. click(x, y, UIEvents::MouseButton::Middle);
  74. }
  75. void Internals::click(double x, double y, UIEvents::MouseButton button)
  76. {
  77. auto& page = global_object().browsing_context()->page();
  78. page.handle_mousedown({ x, y }, { x, y }, button, 0, 0);
  79. page.handle_mouseup({ x, y }, { x, y }, button, 0, 0);
  80. }
  81. void Internals::move_pointer_to(double x, double y)
  82. {
  83. auto& page = global_object().browsing_context()->page();
  84. page.handle_mousemove({ x, y }, { x, y }, 0, 0);
  85. }
  86. void Internals::wheel(double x, double y, double delta_x, double delta_y)
  87. {
  88. auto& page = global_object().browsing_context()->page();
  89. page.handle_mousewheel({ x, y }, { x, y }, 0, 0, 0, delta_x, delta_y);
  90. }
  91. WebIDL::ExceptionOr<bool> Internals::dispatch_user_activated_event(DOM::EventTarget& target, DOM::Event& event)
  92. {
  93. event.set_is_trusted(true);
  94. return target.dispatch_event(event);
  95. }
  96. JS::NonnullGCPtr<InternalAnimationTimeline> Internals::create_internal_animation_timeline()
  97. {
  98. auto& realm = this->realm();
  99. return realm.heap().allocate<InternalAnimationTimeline>(realm, realm);
  100. }
  101. void Internals::simulate_drag_start(double x, double y, String const& name, String const& contents)
  102. {
  103. Vector<HTML::SelectedFile> files;
  104. files.empend(name.to_byte_string(), MUST(ByteBuffer::copy(contents.bytes())));
  105. auto& page = global_object().browsing_context()->page();
  106. page.handle_drag_and_drop_event(DragEvent::Type::DragStart, { x, y }, { x, y }, UIEvents::MouseButton::Primary, 0, 0, move(files));
  107. }
  108. void Internals::simulate_drag_move(double x, double y)
  109. {
  110. auto& page = global_object().browsing_context()->page();
  111. page.handle_drag_and_drop_event(DragEvent::Type::DragMove, { x, y }, { x, y }, UIEvents::MouseButton::Primary, 0, 0, {});
  112. }
  113. void Internals::simulate_drop(double x, double y)
  114. {
  115. auto& page = global_object().browsing_context()->page();
  116. page.handle_drag_and_drop_event(DragEvent::Type::Drop, { x, y }, { x, y }, UIEvents::MouseButton::Primary, 0, 0, {});
  117. }
  118. }