2023-08-20 17:14:31 -03:00
|
|
|
/*
|
2024-07-30 15:01:05 -03:00
|
|
|
* Copyright (c) 2023-2024, Tim Flynn <trflynn89@serenityos.org>
|
2023-08-20 17:14:31 -03:00
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
|
|
|
*/
|
|
|
|
|
|
2024-11-09 14:50:33 -03:00
|
|
|
#include <Interface/LadybirdWebViewBridge.h>
|
2023-08-20 17:14:31 -03:00
|
|
|
#include <LibGfx/Font/FontDatabase.h>
|
|
|
|
|
#include <LibGfx/Rect.h>
|
|
|
|
|
#include <LibIPC/File.h>
|
2024-07-30 15:01:05 -03:00
|
|
|
#include <LibWebView/Application.h>
|
2023-08-20 17:14:31 -03:00
|
|
|
|
2024-11-09 14:50:33 -03:00
|
|
|
#import <Interface/Palette.h>
|
2023-08-27 00:12:30 -03:00
|
|
|
|
2023-08-20 17:14:31 -03:00
|
|
|
namespace Ladybird {
|
|
|
|
|
|
|
|
|
|
template<typename T>
|
2026-01-05 22:05:10 -03:00
|
|
|
static T scale_for_device(T size, double device_pixel_ratio)
|
2023-08-20 17:14:31 -03:00
|
|
|
{
|
2026-01-05 22:05:10 -03:00
|
|
|
return size.template to_type<double>().scaled(device_pixel_ratio).template to_type<int>();
|
2023-08-20 17:14:31 -03:00
|
|
|
}
|
|
|
|
|
|
2026-05-28 14:04:22 -03:00
|
|
|
ErrorOr<NonnullOwnPtr<WebViewBridge>> WebViewBridge::create(Vector<Web::DevicePixelRect> screen_rects, double device_pixel_ratio, u64 maximum_frames_per_second, Optional<u64> display_id)
|
2023-08-20 17:14:31 -03:00
|
|
|
{
|
2026-05-28 14:04:22 -03:00
|
|
|
return adopt_nonnull_own_or_enomem(new (nothrow) WebViewBridge(move(screen_rects), device_pixel_ratio, maximum_frames_per_second, display_id));
|
2023-08-20 17:14:31 -03:00
|
|
|
}
|
|
|
|
|
|
2026-05-28 14:04:22 -03:00
|
|
|
WebViewBridge::WebViewBridge(Vector<Web::DevicePixelRect> screen_rects, double device_pixel_ratio, u64 maximum_frames_per_second, Optional<u64> display_id)
|
2023-08-20 17:14:31 -03:00
|
|
|
: m_screen_rects(move(screen_rects))
|
|
|
|
|
{
|
|
|
|
|
m_device_pixel_ratio = device_pixel_ratio;
|
2026-05-31 15:16:39 -03:00
|
|
|
m_display_id = display_id;
|
2025-07-25 09:23:50 -03:00
|
|
|
m_maximum_frames_per_second = static_cast<double>(maximum_frames_per_second);
|
2026-05-26 20:11:14 -03:00
|
|
|
set_page_background_color_to_system_canvas(is_using_dark_system_theme());
|
2023-08-20 17:14:31 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WebViewBridge::~WebViewBridge() = default;
|
|
|
|
|
|
2026-01-05 22:05:10 -03:00
|
|
|
void WebViewBridge::set_device_pixel_ratio(double device_pixel_ratio)
|
2023-09-20 17:10:42 -03:00
|
|
|
{
|
|
|
|
|
m_device_pixel_ratio = device_pixel_ratio;
|
2026-01-05 22:05:10 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebViewBridge::set_zoom_level(double zoom_level)
|
|
|
|
|
{
|
|
|
|
|
m_zoom_level = zoom_level;
|
|
|
|
|
update_zoom();
|
2023-09-20 17:10:42 -03:00
|
|
|
}
|
|
|
|
|
|
2024-11-07 14:26:42 -03:00
|
|
|
void WebViewBridge::set_viewport_rect(Gfx::IntRect viewport_rect)
|
2023-08-20 17:14:31 -03:00
|
|
|
{
|
2026-01-05 22:05:10 -03:00
|
|
|
viewport_rect.set_size(scale_for_device(viewport_rect.size(), device_pixel_ratio()));
|
2024-06-03 11:53:55 -03:00
|
|
|
m_viewport_size = viewport_rect.size();
|
2023-08-20 17:14:31 -03:00
|
|
|
|
2024-11-07 14:26:42 -03:00
|
|
|
handle_resize();
|
2023-08-20 17:14:31 -03:00
|
|
|
}
|
|
|
|
|
|
2026-05-28 14:04:22 -03:00
|
|
|
void WebViewBridge::set_display_metadata(u64 maximum_frames_per_second, Optional<u64> display_id)
|
2025-07-25 09:23:50 -03:00
|
|
|
{
|
|
|
|
|
m_maximum_frames_per_second = static_cast<double>(maximum_frames_per_second);
|
2026-05-28 14:04:22 -03:00
|
|
|
m_display_id = display_id;
|
2025-07-25 09:23:50 -03:00
|
|
|
client().async_set_maximum_frames_per_second(m_client_state.page_index, maximum_frames_per_second);
|
2026-05-28 14:04:22 -03:00
|
|
|
update_compositor_display_metadata();
|
2025-07-25 09:23:50 -03:00
|
|
|
}
|
|
|
|
|
|
2026-01-27 13:56:23 -03:00
|
|
|
void WebViewBridge::exit_fullscreen()
|
|
|
|
|
{
|
|
|
|
|
client().async_exit_fullscreen(m_client_state.page_index);
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-27 00:12:30 -03:00
|
|
|
void WebViewBridge::update_palette()
|
|
|
|
|
{
|
2026-05-26 20:11:14 -03:00
|
|
|
set_page_background_color_to_system_canvas(is_using_dark_system_theme());
|
2023-08-27 00:12:30 -03:00
|
|
|
auto theme = create_system_palette();
|
2024-02-02 22:00:48 -03:00
|
|
|
client().async_update_system_theme(m_client_state.page_index, move(theme));
|
2023-08-27 00:12:30 -03:00
|
|
|
}
|
|
|
|
|
|
2024-03-05 18:11:22 -03:00
|
|
|
void WebViewBridge::enqueue_input_event(Web::MouseEvent event)
|
2023-08-20 17:14:31 -03:00
|
|
|
{
|
2024-03-05 18:11:22 -03:00
|
|
|
event.position = to_content_position(event.position.to_type<int>()).to_type<Web::DevicePixels>();
|
|
|
|
|
event.screen_position = to_content_position(event.screen_position.to_type<int>()).to_type<Web::DevicePixels>();
|
|
|
|
|
ViewImplementation::enqueue_input_event(move(event));
|
2023-08-20 17:14:31 -03:00
|
|
|
}
|
|
|
|
|
|
2024-08-17 17:23:13 -03:00
|
|
|
void WebViewBridge::enqueue_input_event(Web::DragEvent event)
|
|
|
|
|
{
|
|
|
|
|
event.position = to_content_position(event.position.to_type<int>()).to_type<Web::DevicePixels>();
|
|
|
|
|
event.screen_position = to_content_position(event.screen_position.to_type<int>()).to_type<Web::DevicePixels>();
|
|
|
|
|
ViewImplementation::enqueue_input_event(move(event));
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-05 18:11:22 -03:00
|
|
|
void WebViewBridge::enqueue_input_event(Web::KeyEvent event)
|
2023-08-20 17:14:31 -03:00
|
|
|
{
|
2024-03-05 18:11:22 -03:00
|
|
|
ViewImplementation::enqueue_input_event(move(event));
|
2023-08-20 17:14:31 -03:00
|
|
|
}
|
|
|
|
|
|
2025-10-08 18:59:50 -03:00
|
|
|
void WebViewBridge::enqueue_input_event(Web::PinchEvent event)
|
|
|
|
|
{
|
|
|
|
|
ViewImplementation::enqueue_input_event(move(event));
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-20 17:14:31 -03:00
|
|
|
Optional<WebViewBridge::Paintable> WebViewBridge::paintable()
|
|
|
|
|
{
|
2026-04-07 13:35:26 -03:00
|
|
|
Gfx::SharedImageBuffer const* shared_image_buffer = nullptr;
|
2023-08-20 17:14:31 -03:00
|
|
|
Gfx::IntSize bitmap_size;
|
|
|
|
|
|
|
|
|
|
if (m_client_state.has_usable_bitmap) {
|
2026-04-07 13:35:26 -03:00
|
|
|
shared_image_buffer = m_client_state.front_bitmap.shared_image_buffer.ptr();
|
2023-12-14 03:17:00 -03:00
|
|
|
bitmap_size = m_client_state.front_bitmap.last_painted_size.to_type<int>();
|
2023-08-20 17:14:31 -03:00
|
|
|
} else {
|
2026-04-07 13:35:26 -03:00
|
|
|
shared_image_buffer = m_backup_shared_image_buffer.ptr();
|
2023-12-14 03:17:00 -03:00
|
|
|
bitmap_size = m_backup_bitmap_size.to_type<int>();
|
2023-08-20 17:14:31 -03:00
|
|
|
}
|
|
|
|
|
|
2026-04-07 13:35:26 -03:00
|
|
|
if (!shared_image_buffer)
|
2023-08-20 17:14:31 -03:00
|
|
|
return {};
|
2026-04-07 13:35:26 -03:00
|
|
|
return Paintable { shared_image_buffer, bitmap_size };
|
2023-08-20 17:14:31 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WebViewBridge::update_zoom()
|
|
|
|
|
{
|
2025-09-10 08:23:15 -03:00
|
|
|
WebView::ViewImplementation::update_zoom();
|
2023-10-07 18:21:00 -03:00
|
|
|
|
|
|
|
|
if (on_zoom_level_changed)
|
|
|
|
|
on_zoom_level_changed();
|
2023-08-20 17:14:31 -03:00
|
|
|
}
|
|
|
|
|
|
2024-06-03 11:53:55 -03:00
|
|
|
Web::DevicePixelSize WebViewBridge::viewport_size() const
|
2023-08-20 17:14:31 -03:00
|
|
|
{
|
2024-06-03 11:53:55 -03:00
|
|
|
return m_viewport_size.to_type<Web::DevicePixels>();
|
2023-08-20 17:14:31 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Gfx::IntPoint WebViewBridge::to_content_position(Gfx::IntPoint widget_position) const
|
|
|
|
|
{
|
2026-01-05 22:05:10 -03:00
|
|
|
return scale_for_device(widget_position, device_pixel_ratio());
|
2023-08-20 17:14:31 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Gfx::IntPoint WebViewBridge::to_widget_position(Gfx::IntPoint content_position) const
|
|
|
|
|
{
|
2023-09-20 17:10:42 -03:00
|
|
|
return scale_for_device(content_position, inverse_device_pixel_ratio());
|
2023-08-20 17:14:31 -03:00
|
|
|
}
|
|
|
|
|
|
2024-09-17 16:49:00 -03:00
|
|
|
void WebViewBridge::initialize_client(CreateNewClient create_new_client)
|
2023-08-20 17:14:31 -03:00
|
|
|
{
|
2024-11-13 18:35:17 -03:00
|
|
|
ViewImplementation::initialize_client(create_new_client);
|
2023-08-20 17:14:31 -03:00
|
|
|
update_palette();
|
2026-05-28 14:04:22 -03:00
|
|
|
update_compositor_display_metadata();
|
2023-08-20 17:14:31 -03:00
|
|
|
|
|
|
|
|
if (!m_screen_rects.is_empty()) {
|
|
|
|
|
// FIXME: Update the screens again if they ever change.
|
2024-02-02 22:00:48 -03:00
|
|
|
client().async_update_screen_rects(m_client_state.page_index, m_screen_rects, 0);
|
2023-08-20 17:14:31 -03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-15 18:54:30 -03:00
|
|
|
void WebViewBridge::initialize_client_as_child(WebViewBridge& parent, u64 page_index)
|
2024-09-17 16:49:00 -03:00
|
|
|
{
|
|
|
|
|
m_client_state.client = parent.client();
|
|
|
|
|
m_client_state.page_index = page_index;
|
|
|
|
|
|
|
|
|
|
initialize_client(CreateNewClient::No);
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-28 14:04:22 -03:00
|
|
|
void WebViewBridge::update_compositor_display_metadata()
|
|
|
|
|
{
|
|
|
|
|
if (!m_client_state.client)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
auto compositor_context_id = client().compositor_context_id_for_page(m_client_state.page_index);
|
|
|
|
|
WebView::Application::the().update_compositor_display_metadata(compositor_context_id, m_display_id, m_maximum_frames_per_second);
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-20 17:14:31 -03:00
|
|
|
}
|