LadybirdWebViewBridge.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /*
  2. * Copyright (c) 2023, Tim Flynn <trflynn89@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <Ladybird/HelperProcess.h>
  7. #include <Ladybird/Types.h>
  8. #include <Ladybird/Utilities.h>
  9. #include <LibGfx/Font/FontDatabase.h>
  10. #include <LibGfx/Rect.h>
  11. #include <LibIPC/File.h>
  12. #include <LibWeb/Crypto/Crypto.h>
  13. #include <UI/LadybirdWebViewBridge.h>
  14. #import <UI/Palette.h>
  15. namespace Ladybird {
  16. template<typename T>
  17. static T scale_for_device(T size, float device_pixel_ratio)
  18. {
  19. return size.template to_type<float>().scaled(device_pixel_ratio).template to_type<int>();
  20. }
  21. ErrorOr<NonnullOwnPtr<WebViewBridge>> WebViewBridge::create(Vector<Web::DevicePixelRect> screen_rects, float device_pixel_ratio, WebContentOptions const& web_content_options, Optional<StringView> webdriver_content_ipc_path, Web::CSS::PreferredColorScheme preferred_color_scheme, Web::CSS::PreferredContrast preferred_contrast, Web::CSS::PreferredMotion preferred_motion)
  22. {
  23. return adopt_nonnull_own_or_enomem(new (nothrow) WebViewBridge(move(screen_rects), device_pixel_ratio, web_content_options, move(webdriver_content_ipc_path), preferred_color_scheme, preferred_contrast, preferred_motion));
  24. }
  25. WebViewBridge::WebViewBridge(Vector<Web::DevicePixelRect> screen_rects, float device_pixel_ratio, WebContentOptions const& web_content_options, Optional<StringView> webdriver_content_ipc_path, Web::CSS::PreferredColorScheme preferred_color_scheme, Web::CSS::PreferredContrast preferred_contrast, Web::CSS::PreferredMotion preferred_motion)
  26. : m_screen_rects(move(screen_rects))
  27. , m_web_content_options(web_content_options)
  28. , m_webdriver_content_ipc_path(move(webdriver_content_ipc_path))
  29. , m_preferred_color_scheme(preferred_color_scheme)
  30. , m_preferred_contrast(preferred_contrast)
  31. , m_preferred_motion(preferred_motion)
  32. {
  33. m_device_pixel_ratio = device_pixel_ratio;
  34. }
  35. WebViewBridge::~WebViewBridge() = default;
  36. void WebViewBridge::set_device_pixel_ratio(float device_pixel_ratio)
  37. {
  38. m_device_pixel_ratio = device_pixel_ratio;
  39. client().async_set_device_pixels_per_css_pixel(m_client_state.page_index, m_device_pixel_ratio * m_zoom_level);
  40. }
  41. void WebViewBridge::set_system_visibility_state(bool is_visible)
  42. {
  43. client().async_set_system_visibility_state(m_client_state.page_index, is_visible);
  44. }
  45. void WebViewBridge::set_viewport_rect(Gfx::IntRect viewport_rect, ForResize for_resize)
  46. {
  47. viewport_rect.set_size(scale_for_device(viewport_rect.size(), m_device_pixel_ratio));
  48. m_viewport_size = viewport_rect.size();
  49. client().async_set_viewport_size(m_client_state.page_index, m_viewport_size.to_type<Web::DevicePixels>());
  50. if (for_resize == ForResize::Yes) {
  51. handle_resize();
  52. }
  53. }
  54. void WebViewBridge::update_palette()
  55. {
  56. auto theme = create_system_palette();
  57. client().async_update_system_theme(m_client_state.page_index, move(theme));
  58. }
  59. void WebViewBridge::set_preferred_color_scheme(Web::CSS::PreferredColorScheme color_scheme)
  60. {
  61. m_preferred_color_scheme = color_scheme;
  62. client().async_set_preferred_color_scheme(m_client_state.page_index, color_scheme);
  63. }
  64. void WebViewBridge::set_preferred_contrast(Web::CSS::PreferredContrast contrast)
  65. {
  66. m_preferred_contrast = contrast;
  67. client().async_set_preferred_contrast(m_client_state.page_index, contrast);
  68. }
  69. void WebViewBridge::set_preferred_motion(Web::CSS::PreferredMotion motion)
  70. {
  71. m_preferred_motion = motion;
  72. client().async_set_preferred_motion(m_client_state.page_index, motion);
  73. }
  74. void WebViewBridge::enqueue_input_event(Web::MouseEvent event)
  75. {
  76. event.position = to_content_position(event.position.to_type<int>()).to_type<Web::DevicePixels>();
  77. event.screen_position = to_content_position(event.screen_position.to_type<int>()).to_type<Web::DevicePixels>();
  78. ViewImplementation::enqueue_input_event(move(event));
  79. }
  80. void WebViewBridge::enqueue_input_event(Web::KeyEvent event)
  81. {
  82. ViewImplementation::enqueue_input_event(move(event));
  83. }
  84. Optional<WebViewBridge::Paintable> WebViewBridge::paintable()
  85. {
  86. Gfx::Bitmap* bitmap = nullptr;
  87. Gfx::IntSize bitmap_size;
  88. if (m_client_state.has_usable_bitmap) {
  89. bitmap = m_client_state.front_bitmap.bitmap.ptr();
  90. bitmap_size = m_client_state.front_bitmap.last_painted_size.to_type<int>();
  91. } else {
  92. bitmap = m_backup_bitmap.ptr();
  93. bitmap_size = m_backup_bitmap_size.to_type<int>();
  94. }
  95. if (!bitmap)
  96. return {};
  97. return Paintable { *bitmap, bitmap_size };
  98. }
  99. void WebViewBridge::update_zoom()
  100. {
  101. client().async_set_device_pixels_per_css_pixel(m_client_state.page_index, m_device_pixel_ratio * m_zoom_level);
  102. if (on_zoom_level_changed)
  103. on_zoom_level_changed();
  104. }
  105. Web::DevicePixelSize WebViewBridge::viewport_size() const
  106. {
  107. return m_viewport_size.to_type<Web::DevicePixels>();
  108. }
  109. Gfx::IntPoint WebViewBridge::to_content_position(Gfx::IntPoint widget_position) const
  110. {
  111. return scale_for_device(widget_position, m_device_pixel_ratio);
  112. }
  113. Gfx::IntPoint WebViewBridge::to_widget_position(Gfx::IntPoint content_position) const
  114. {
  115. return scale_for_device(content_position, inverse_device_pixel_ratio());
  116. }
  117. void WebViewBridge::initialize_client(CreateNewClient)
  118. {
  119. VERIFY(on_request_web_content);
  120. // FIXME: Don't create a new process when CreateNewClient is false
  121. // We should create a new tab/window in the UI instead, and re-use the existing WebContentClient object.
  122. m_client_state = {};
  123. m_client_state.client = on_request_web_content();
  124. m_client_state.client->on_web_content_process_crash = [this] {
  125. Core::deferred_invoke([this] {
  126. handle_web_content_process_crash();
  127. });
  128. };
  129. m_client_state.client_handle = MUST(Web::Crypto::generate_random_uuid());
  130. client().async_set_window_handle(m_client_state.page_index, m_client_state.client_handle);
  131. client().async_set_device_pixels_per_css_pixel(m_client_state.page_index, m_device_pixel_ratio);
  132. client().async_set_preferred_color_scheme(m_client_state.page_index, m_preferred_color_scheme);
  133. update_palette();
  134. if (!m_screen_rects.is_empty()) {
  135. // FIXME: Update the screens again if they ever change.
  136. client().async_update_screen_rects(m_client_state.page_index, m_screen_rects, 0);
  137. }
  138. if (m_webdriver_content_ipc_path.has_value()) {
  139. client().async_connect_to_webdriver(m_client_state.page_index, *m_webdriver_content_ipc_path);
  140. }
  141. }
  142. }