| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2023-05-14 18:57:14 +02:00
										 |  |  |  * Copyright (c) 2022-2023, Andreas Kling <kling@serenityos.org> | 
					
						
							| 
									
										
										
										
											2023-01-12 14:39:53 +00:00
										 |  |  |  * Copyright (c) 2023, Linus Groh <linusg@serenityos.org> | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  |  * | 
					
						
							|  |  |  |  * SPDX-License-Identifier: BSD-2-Clause | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "WebContentView.h"
 | 
					
						
							| 
									
										
										
										
											2024-04-15 17:39:48 -06:00
										 |  |  | #include "Application.h"
 | 
					
						
							| 
									
										
										
										
											2023-08-05 10:42:26 -06:00
										 |  |  | #include "StringUtils.h"
 | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  | #include <AK/Assertions.h>
 | 
					
						
							|  |  |  | #include <AK/ByteBuffer.h>
 | 
					
						
							|  |  |  | #include <AK/Format.h>
 | 
					
						
							|  |  |  | #include <AK/LexicalPath.h>
 | 
					
						
							|  |  |  | #include <AK/NonnullOwnPtr.h>
 | 
					
						
							|  |  |  | #include <AK/Types.h>
 | 
					
						
							| 
									
										
										
										
											2023-08-05 10:42:26 -06:00
										 |  |  | #include <Ladybird/HelperProcess.h>
 | 
					
						
							|  |  |  | #include <Ladybird/Utilities.h>
 | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  | #include <LibCore/EventLoop.h>
 | 
					
						
							| 
									
										
										
										
											2023-11-05 09:46:28 -05:00
										 |  |  | #include <LibCore/Resource.h>
 | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  | #include <LibCore/Timer.h>
 | 
					
						
							|  |  |  | #include <LibGfx/Bitmap.h>
 | 
					
						
							|  |  |  | #include <LibGfx/Font/FontDatabase.h>
 | 
					
						
							| 
									
										
										
										
											2023-03-21 14:58:06 -04:00
										 |  |  | #include <LibGfx/ImageFormats/PNGWriter.h>
 | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  | #include <LibGfx/Painter.h>
 | 
					
						
							| 
									
										
										
										
											2023-03-15 22:56:47 +01:00
										 |  |  | #include <LibGfx/Palette.h>
 | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  | #include <LibGfx/Rect.h>
 | 
					
						
							| 
									
										
										
										
											2022-12-18 00:50:53 +00:00
										 |  |  | #include <LibGfx/SystemTheme.h>
 | 
					
						
							| 
									
										
										
										
											2023-03-16 18:35:19 +03:00
										 |  |  | #include <LibWeb/Crypto/Crypto.h>
 | 
					
						
							| 
									
										
										
										
											2024-06-06 13:29:08 -06:00
										 |  |  | #include <LibWeb/UIEvents/KeyCode.h>
 | 
					
						
							| 
									
										
										
										
											2024-06-02 19:00:42 +02:00
										 |  |  | #include <LibWeb/UIEvents/MouseButton.h>
 | 
					
						
							| 
									
										
										
										
											2024-01-06 13:13:59 -07:00
										 |  |  | #include <LibWeb/Worker/WebWorkerClient.h>
 | 
					
						
							| 
									
										
										
										
											2024-07-30 14:01:05 -04:00
										 |  |  | #include <LibWebView/Application.h>
 | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  | #include <LibWebView/WebContentClient.h>
 | 
					
						
							|  |  |  | #include <QApplication>
 | 
					
						
							|  |  |  | #include <QCursor>
 | 
					
						
							| 
									
										
										
										
											2023-06-12 12:52:44 +02:00
										 |  |  | #include <QGuiApplication>
 | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  | #include <QIcon>
 | 
					
						
							| 
									
										
										
										
											2023-01-07 17:40:04 +01:00
										 |  |  | #include <QMimeData>
 | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  | #include <QMouseEvent>
 | 
					
						
							|  |  |  | #include <QPaintEvent>
 | 
					
						
							|  |  |  | #include <QPainter>
 | 
					
						
							| 
									
										
										
										
											2023-03-15 22:56:47 +01:00
										 |  |  | #include <QPalette>
 | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  | #include <QScrollBar>
 | 
					
						
							|  |  |  | #include <QTextEdit>
 | 
					
						
							|  |  |  | #include <QTimer>
 | 
					
						
							|  |  |  | #include <QToolTip>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-02 11:52:59 -06:00
										 |  |  | namespace Ladybird { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-29 18:35:06 +02:00
										 |  |  | bool is_using_dark_system_theme(QWidget&); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-30 14:01:05 -04:00
										 |  |  | WebContentView::WebContentView(QWidget* window, RefPtr<WebView::WebContentClient> parent_client, size_t page_index) | 
					
						
							| 
									
										
										
										
											2024-01-26 23:14:41 -05:00
										 |  |  |     : QAbstractScrollArea(window) | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-06-03 17:53:55 +03:00
										 |  |  |     setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); | 
					
						
							|  |  |  |     setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-30 09:12:14 -07:00
										 |  |  |     m_client_state.client = parent_client; | 
					
						
							|  |  |  |     m_client_state.page_index = page_index; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-12 14:06:41 +02:00
										 |  |  |     setAttribute(Qt::WA_InputMethodEnabled, true); | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  |     setMouseTracking(true); | 
					
						
							| 
									
										
										
										
											2023-01-07 17:40:04 +01:00
										 |  |  |     setAcceptDrops(true); | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-11 11:38:03 +02:00
										 |  |  |     setFocusPolicy(Qt::FocusPolicy::StrongFocus); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-12 14:39:05 +00:00
										 |  |  |     m_device_pixel_ratio = devicePixelRatio(); | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     verticalScrollBar()->setSingleStep(24); | 
					
						
							|  |  |  |     horizontalScrollBar()->setSingleStep(24); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-05 19:19:50 +02:00
										 |  |  |     QObject::connect(qGuiApp, &QGuiApplication::screenRemoved, [this](QScreen*) { | 
					
						
							|  |  |  |         update_screen_rects(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QObject::connect(qGuiApp, &QGuiApplication::screenAdded, [this](QScreen*) { | 
					
						
							|  |  |  |         update_screen_rects(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-02 14:16:24 +02:00
										 |  |  |     m_tooltip_hover_timer.setSingleShot(true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QObject::connect(&m_tooltip_hover_timer, &QTimer::timeout, [this] { | 
					
						
							|  |  |  |         if (m_tooltip_text.has_value()) | 
					
						
							|  |  |  |             QToolTip::showText( | 
					
						
							|  |  |  |                 QCursor::pos(), | 
					
						
							|  |  |  |                 qstring_from_ak_string(m_tooltip_text.value()), | 
					
						
							|  |  |  |                 this); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-30 09:12:14 -07:00
										 |  |  |     initialize_client((parent_client == nullptr) ? CreateNewClient::Yes : CreateNewClient::No); | 
					
						
							| 
									
										
										
										
											2023-05-20 10:50:05 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     on_ready_to_paint = [this]() { | 
					
						
							|  |  |  |         viewport()->update(); | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2023-08-23 10:43:27 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     on_cursor_change = [this](auto cursor) { | 
					
						
							|  |  |  |         update_cursor(cursor); | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2023-08-23 11:11:39 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-02 16:48:57 +02:00
										 |  |  |     on_request_tooltip_override = [this](auto position, auto const& tooltip) { | 
					
						
							|  |  |  |         m_tooltip_override = true; | 
					
						
							|  |  |  |         if (m_tooltip_hover_timer.isActive()) | 
					
						
							|  |  |  |             m_tooltip_hover_timer.stop(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         auto tooltip_without_carriage_return = tooltip.contains("\r"sv) | 
					
						
							|  |  |  |             ? tooltip.replace("\r\n"sv, "\n"sv, ReplaceMode::All).replace("\r"sv, "\n"sv, ReplaceMode::All) | 
					
						
							|  |  |  |             : tooltip; | 
					
						
							|  |  |  |         QToolTip::showText( | 
					
						
							|  |  |  |             mapToGlobal(QPoint(position.x(), position.y())), | 
					
						
							|  |  |  |             qstring_from_ak_string(tooltip_without_carriage_return), | 
					
						
							|  |  |  |             this); | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     on_stop_tooltip_override = [this]() { | 
					
						
							|  |  |  |         m_tooltip_override = false; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-02 14:16:24 +02:00
										 |  |  |     on_enter_tooltip_area = [this](auto const& tooltip) { | 
					
						
							|  |  |  |         m_tooltip_text = tooltip.contains("\r"sv) | 
					
						
							| 
									
										
										
										
											2024-03-09 01:11:30 +01:00
										 |  |  |             ? tooltip.replace("\r\n"sv, "\n"sv, ReplaceMode::All).replace("\r"sv, "\n"sv, ReplaceMode::All) | 
					
						
							|  |  |  |             : tooltip; | 
					
						
							| 
									
										
										
										
											2023-08-23 11:11:39 -04:00
										 |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-02 14:16:24 +02:00
										 |  |  |     on_leave_tooltip_area = [this]() { | 
					
						
							|  |  |  |         m_tooltip_text.clear(); | 
					
						
							| 
									
										
										
										
											2023-08-23 11:11:39 -04:00
										 |  |  |     }; | 
					
						
							| 
									
										
										
										
											2024-01-06 13:13:59 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-05 07:53:57 -05:00
										 |  |  |     on_finish_handling_key_event = [this](auto const& event) { | 
					
						
							|  |  |  |         finish_handling_key_event(event); | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-17 14:47:28 -04:00
										 |  |  |     on_finish_handling_drag_event = [this](auto const& event) { | 
					
						
							|  |  |  |         finish_handling_drag_event(event); | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-06 03:41:07 +01:00
										 |  |  |     on_request_worker_agent = [&]() { | 
					
						
							| 
									
										
										
										
											2024-08-06 21:51:20 -06:00
										 |  |  |         RefPtr<Requests::RequestClient> request_server_client {}; | 
					
						
							| 
									
										
										
										
											2024-07-30 14:01:05 -04:00
										 |  |  |         if (WebView::Application::web_content_options().use_lagom_networking == WebView::UseLagomNetworking::Yes) | 
					
						
							| 
									
										
										
										
											2024-07-06 03:41:07 +01:00
										 |  |  |             request_server_client = static_cast<Ladybird::Application*>(QApplication::instance())->request_server_client; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         auto worker_client = MUST(launch_web_worker_process(MUST(get_paths_for_helper_process("WebWorker"sv)), request_server_client)); | 
					
						
							| 
									
										
										
										
											2024-04-17 18:44:39 -06:00
										 |  |  |         return worker_client->dup_socket(); | 
					
						
							| 
									
										
										
										
											2024-01-06 13:13:59 -07:00
										 |  |  |     }; | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-03 12:48:00 -04:00
										 |  |  | WebContentView::~WebContentView() = default; | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-17 14:47:28 -04:00
										 |  |  | static Web::UIEvents::MouseButton get_button_from_qt_event(Qt::MouseButton button) | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-08-17 14:47:28 -04:00
										 |  |  |     if (button == Qt::MouseButton::LeftButton) | 
					
						
							| 
									
										
										
										
											2024-06-02 19:00:42 +02:00
										 |  |  |         return Web::UIEvents::MouseButton::Primary; | 
					
						
							| 
									
										
										
										
											2024-08-17 14:47:28 -04:00
										 |  |  |     if (button == Qt::MouseButton::RightButton) | 
					
						
							| 
									
										
										
										
											2024-06-02 19:00:42 +02:00
										 |  |  |         return Web::UIEvents::MouseButton::Secondary; | 
					
						
							| 
									
										
										
										
											2024-08-17 14:47:28 -04:00
										 |  |  |     if (button == Qt::MouseButton::MiddleButton) | 
					
						
							| 
									
										
										
										
											2024-06-02 19:00:42 +02:00
										 |  |  |         return Web::UIEvents::MouseButton::Middle; | 
					
						
							| 
									
										
										
										
											2024-08-17 14:47:28 -04:00
										 |  |  |     if (button == Qt::MouseButton::BackButton) | 
					
						
							| 
									
										
										
										
											2024-06-02 19:00:42 +02:00
										 |  |  |         return Web::UIEvents::MouseButton::Backward; | 
					
						
							| 
									
										
										
										
											2024-08-17 14:47:28 -04:00
										 |  |  |     if (button == Qt::MouseButton::ForwardButton) | 
					
						
							| 
									
										
										
										
											2024-06-02 19:00:42 +02:00
										 |  |  |         return Web::UIEvents::MouseButton::Forward; | 
					
						
							|  |  |  |     return Web::UIEvents::MouseButton::None; | 
					
						
							| 
									
										
										
										
											2024-03-05 07:53:57 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-17 14:47:28 -04:00
										 |  |  | static Web::UIEvents::MouseButton get_buttons_from_qt_event(Qt::MouseButtons buttons) | 
					
						
							| 
									
										
										
										
											2024-03-05 07:53:57 -05:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-08-17 14:47:28 -04:00
										 |  |  |     auto result = Web::UIEvents::MouseButton::None; | 
					
						
							|  |  |  |     if (buttons.testFlag(Qt::MouseButton::LeftButton)) | 
					
						
							|  |  |  |         result |= Web::UIEvents::MouseButton::Primary; | 
					
						
							|  |  |  |     if (buttons.testFlag(Qt::MouseButton::RightButton)) | 
					
						
							|  |  |  |         result |= Web::UIEvents::MouseButton::Secondary; | 
					
						
							|  |  |  |     if (buttons.testFlag(Qt::MouseButton::MiddleButton)) | 
					
						
							|  |  |  |         result |= Web::UIEvents::MouseButton::Middle; | 
					
						
							|  |  |  |     if (buttons.testFlag(Qt::MouseButton::BackButton)) | 
					
						
							|  |  |  |         result |= Web::UIEvents::MouseButton::Backward; | 
					
						
							|  |  |  |     if (buttons.testFlag(Qt::MouseButton::ForwardButton)) | 
					
						
							|  |  |  |         result |= Web::UIEvents::MouseButton::Forward; | 
					
						
							|  |  |  |     return result; | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-17 14:47:28 -04:00
										 |  |  | static Web::UIEvents::KeyModifier get_modifiers_from_qt_mouse_event(Qt::KeyboardModifiers modifiers) | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-08-17 14:47:28 -04:00
										 |  |  |     auto result = Web::UIEvents::KeyModifier::Mod_None; | 
					
						
							|  |  |  |     if (modifiers.testFlag(Qt::AltModifier)) | 
					
						
							|  |  |  |         result |= Web::UIEvents::KeyModifier::Mod_Alt; | 
					
						
							|  |  |  |     if (modifiers.testFlag(Qt::ControlModifier)) | 
					
						
							|  |  |  |         result |= Web::UIEvents::KeyModifier::Mod_Ctrl; | 
					
						
							|  |  |  |     if (modifiers.testFlag(Qt::ShiftModifier)) | 
					
						
							|  |  |  |         result |= Web::UIEvents::KeyModifier::Mod_Shift; | 
					
						
							|  |  |  |     return result; | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-06 13:29:08 -06:00
										 |  |  | static Web::UIEvents::KeyModifier get_modifiers_from_qt_keyboard_event(QKeyEvent const& event) | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-06-06 13:29:08 -06:00
										 |  |  |     auto modifiers = Web::UIEvents::KeyModifier::Mod_None; | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  |     if (event.modifiers().testFlag(Qt::AltModifier)) | 
					
						
							| 
									
										
										
										
											2024-06-06 13:29:08 -06:00
										 |  |  |         modifiers |= Web::UIEvents::KeyModifier::Mod_Alt; | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  |     if (event.modifiers().testFlag(Qt::ControlModifier)) | 
					
						
							| 
									
										
										
										
											2024-06-06 13:29:08 -06:00
										 |  |  |         modifiers |= Web::UIEvents::KeyModifier::Mod_Ctrl; | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  |     if (event.modifiers().testFlag(Qt::MetaModifier)) | 
					
						
							| 
									
										
										
										
											2024-06-06 13:29:08 -06:00
										 |  |  |         modifiers |= Web::UIEvents::KeyModifier::Mod_Super; | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  |     if (event.modifiers().testFlag(Qt::ShiftModifier)) | 
					
						
							| 
									
										
										
										
											2024-06-06 13:29:08 -06:00
										 |  |  |         modifiers |= Web::UIEvents::KeyModifier::Mod_Shift; | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  |     if (event.modifiers().testFlag(Qt::AltModifier)) | 
					
						
							| 
									
										
										
										
											2024-06-06 13:29:08 -06:00
										 |  |  |         modifiers |= Web::UIEvents::KeyModifier::Mod_AltGr; | 
					
						
							| 
									
										
										
										
											2023-07-08 16:01:32 -04:00
										 |  |  |     if (event.modifiers().testFlag(Qt::KeypadModifier)) | 
					
						
							| 
									
										
										
										
											2024-06-06 13:29:08 -06:00
										 |  |  |         modifiers |= Web::UIEvents::KeyModifier::Mod_Keypad; | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  |     return modifiers; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-06 13:29:08 -06:00
										 |  |  | static Web::UIEvents::KeyCode get_keycode_from_qt_keyboard_event(QKeyEvent const& event) | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     struct Mapping { | 
					
						
							| 
									
										
										
										
											2024-06-06 13:29:08 -06:00
										 |  |  |         constexpr Mapping(Qt::Key q, Web::UIEvents::KeyCode s) | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  |             : qt_key(q) | 
					
						
							|  |  |  |             , serenity_key(s) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Qt::Key qt_key; | 
					
						
							| 
									
										
										
										
											2024-06-06 13:29:08 -06:00
										 |  |  |         Web::UIEvents::KeyCode serenity_key; | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-08 16:58:22 -04:00
										 |  |  |     // https://doc.qt.io/qt-6/qt.html#Key-enum
 | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  |     constexpr Mapping mappings[] = { | 
					
						
							| 
									
										
										
										
											2024-06-06 13:29:08 -06:00
										 |  |  |         { Qt::Key_0, Web::UIEvents::Key_0 }, | 
					
						
							|  |  |  |         { Qt::Key_1, Web::UIEvents::Key_1 }, | 
					
						
							|  |  |  |         { Qt::Key_2, Web::UIEvents::Key_2 }, | 
					
						
							|  |  |  |         { Qt::Key_3, Web::UIEvents::Key_3 }, | 
					
						
							|  |  |  |         { Qt::Key_4, Web::UIEvents::Key_4 }, | 
					
						
							|  |  |  |         { Qt::Key_5, Web::UIEvents::Key_5 }, | 
					
						
							|  |  |  |         { Qt::Key_6, Web::UIEvents::Key_6 }, | 
					
						
							|  |  |  |         { Qt::Key_7, Web::UIEvents::Key_7 }, | 
					
						
							|  |  |  |         { Qt::Key_8, Web::UIEvents::Key_8 }, | 
					
						
							|  |  |  |         { Qt::Key_9, Web::UIEvents::Key_9 }, | 
					
						
							|  |  |  |         { Qt::Key_A, Web::UIEvents::Key_A }, | 
					
						
							|  |  |  |         { Qt::Key_Alt, Web::UIEvents::Key_Alt }, | 
					
						
							|  |  |  |         { Qt::Key_Ampersand, Web::UIEvents::Key_Ampersand }, | 
					
						
							|  |  |  |         { Qt::Key_Apostrophe, Web::UIEvents::Key_Apostrophe }, | 
					
						
							|  |  |  |         { Qt::Key_AsciiCircum, Web::UIEvents::Key_Circumflex }, | 
					
						
							|  |  |  |         { Qt::Key_AsciiTilde, Web::UIEvents::Key_Tilde }, | 
					
						
							|  |  |  |         { Qt::Key_Asterisk, Web::UIEvents::Key_Asterisk }, | 
					
						
							|  |  |  |         { Qt::Key_At, Web::UIEvents::Key_AtSign }, | 
					
						
							|  |  |  |         { Qt::Key_B, Web::UIEvents::Key_B }, | 
					
						
							|  |  |  |         { Qt::Key_Backslash, Web::UIEvents::Key_Backslash }, | 
					
						
							|  |  |  |         { Qt::Key_Backspace, Web::UIEvents::Key_Backspace }, | 
					
						
							|  |  |  |         { Qt::Key_Bar, Web::UIEvents::Key_Pipe }, | 
					
						
							|  |  |  |         { Qt::Key_BraceLeft, Web::UIEvents::Key_LeftBrace }, | 
					
						
							|  |  |  |         { Qt::Key_BraceRight, Web::UIEvents::Key_RightBrace }, | 
					
						
							|  |  |  |         { Qt::Key_BracketLeft, Web::UIEvents::Key_LeftBracket }, | 
					
						
							|  |  |  |         { Qt::Key_BracketRight, Web::UIEvents::Key_RightBracket }, | 
					
						
							|  |  |  |         { Qt::Key_C, Web::UIEvents::Key_C }, | 
					
						
							|  |  |  |         { Qt::Key_CapsLock, Web::UIEvents::Key_CapsLock }, | 
					
						
							|  |  |  |         { Qt::Key_Colon, Web::UIEvents::Key_Colon }, | 
					
						
							|  |  |  |         { Qt::Key_Comma, Web::UIEvents::Key_Comma }, | 
					
						
							|  |  |  |         { Qt::Key_Control, Web::UIEvents::Key_Control }, | 
					
						
							|  |  |  |         { Qt::Key_D, Web::UIEvents::Key_D }, | 
					
						
							|  |  |  |         { Qt::Key_Delete, Web::UIEvents::Key_Delete }, | 
					
						
							|  |  |  |         { Qt::Key_Dollar, Web::UIEvents::Key_Dollar }, | 
					
						
							|  |  |  |         { Qt::Key_Down, Web::UIEvents::Key_Down }, | 
					
						
							|  |  |  |         { Qt::Key_E, Web::UIEvents::Key_E }, | 
					
						
							|  |  |  |         { Qt::Key_End, Web::UIEvents::Key_End }, | 
					
						
							|  |  |  |         { Qt::Key_Equal, Web::UIEvents::Key_Equal }, | 
					
						
							|  |  |  |         { Qt::Key_Enter, Web::UIEvents::Key_Return }, | 
					
						
							|  |  |  |         { Qt::Key_Escape, Web::UIEvents::Key_Escape }, | 
					
						
							|  |  |  |         { Qt::Key_Exclam, Web::UIEvents::Key_ExclamationPoint }, | 
					
						
							|  |  |  |         { Qt::Key_exclamdown, Web::UIEvents::Key_ExclamationPoint }, | 
					
						
							|  |  |  |         { Qt::Key_F, Web::UIEvents::Key_F }, | 
					
						
							|  |  |  |         { Qt::Key_F1, Web::UIEvents::Key_F1 }, | 
					
						
							|  |  |  |         { Qt::Key_F10, Web::UIEvents::Key_F10 }, | 
					
						
							|  |  |  |         { Qt::Key_F11, Web::UIEvents::Key_F11 }, | 
					
						
							|  |  |  |         { Qt::Key_F12, Web::UIEvents::Key_F12 }, | 
					
						
							|  |  |  |         { Qt::Key_F2, Web::UIEvents::Key_F2 }, | 
					
						
							|  |  |  |         { Qt::Key_F3, Web::UIEvents::Key_F3 }, | 
					
						
							|  |  |  |         { Qt::Key_F4, Web::UIEvents::Key_F4 }, | 
					
						
							|  |  |  |         { Qt::Key_F5, Web::UIEvents::Key_F5 }, | 
					
						
							|  |  |  |         { Qt::Key_F6, Web::UIEvents::Key_F6 }, | 
					
						
							|  |  |  |         { Qt::Key_F7, Web::UIEvents::Key_F7 }, | 
					
						
							|  |  |  |         { Qt::Key_F8, Web::UIEvents::Key_F8 }, | 
					
						
							|  |  |  |         { Qt::Key_F9, Web::UIEvents::Key_F9 }, | 
					
						
							|  |  |  |         { Qt::Key_G, Web::UIEvents::Key_G }, | 
					
						
							|  |  |  |         { Qt::Key_Greater, Web::UIEvents::Key_GreaterThan }, | 
					
						
							|  |  |  |         { Qt::Key_H, Web::UIEvents::Key_H }, | 
					
						
							|  |  |  |         { Qt::Key_Home, Web::UIEvents::Key_Home }, | 
					
						
							|  |  |  |         { Qt::Key_I, Web::UIEvents::Key_I }, | 
					
						
							|  |  |  |         { Qt::Key_Insert, Web::UIEvents::Key_Insert }, | 
					
						
							|  |  |  |         { Qt::Key_J, Web::UIEvents::Key_J }, | 
					
						
							|  |  |  |         { Qt::Key_K, Web::UIEvents::Key_K }, | 
					
						
							|  |  |  |         { Qt::Key_L, Web::UIEvents::Key_L }, | 
					
						
							|  |  |  |         { Qt::Key_Left, Web::UIEvents::Key_Left }, | 
					
						
							|  |  |  |         { Qt::Key_Less, Web::UIEvents::Key_LessThan }, | 
					
						
							|  |  |  |         { Qt::Key_M, Web::UIEvents::Key_M }, | 
					
						
							|  |  |  |         { Qt::Key_Menu, Web::UIEvents::Key_Menu }, | 
					
						
							|  |  |  |         { Qt::Key_Meta, Web::UIEvents::Key_Super }, | 
					
						
							|  |  |  |         { Qt::Key_Minus, Web::UIEvents::Key_Minus }, | 
					
						
							|  |  |  |         { Qt::Key_N, Web::UIEvents::Key_N }, | 
					
						
							|  |  |  |         { Qt::Key_NumberSign, Web::UIEvents::Key_Hashtag }, | 
					
						
							|  |  |  |         { Qt::Key_NumLock, Web::UIEvents::Key_NumLock }, | 
					
						
							|  |  |  |         { Qt::Key_O, Web::UIEvents::Key_O }, | 
					
						
							|  |  |  |         { Qt::Key_P, Web::UIEvents::Key_P }, | 
					
						
							|  |  |  |         { Qt::Key_PageDown, Web::UIEvents::Key_PageDown }, | 
					
						
							|  |  |  |         { Qt::Key_PageUp, Web::UIEvents::Key_PageUp }, | 
					
						
							|  |  |  |         { Qt::Key_ParenLeft, Web::UIEvents::Key_LeftParen }, | 
					
						
							|  |  |  |         { Qt::Key_ParenRight, Web::UIEvents::Key_RightParen }, | 
					
						
							|  |  |  |         { Qt::Key_Percent, Web::UIEvents::Key_Percent }, | 
					
						
							|  |  |  |         { Qt::Key_Period, Web::UIEvents::Key_Period }, | 
					
						
							|  |  |  |         { Qt::Key_Plus, Web::UIEvents::Key_Plus }, | 
					
						
							|  |  |  |         { Qt::Key_Print, Web::UIEvents::Key_PrintScreen }, | 
					
						
							|  |  |  |         { Qt::Key_Q, Web::UIEvents::Key_Q }, | 
					
						
							|  |  |  |         { Qt::Key_Question, Web::UIEvents::Key_QuestionMark }, | 
					
						
							|  |  |  |         { Qt::Key_QuoteDbl, Web::UIEvents::Key_DoubleQuote }, | 
					
						
							|  |  |  |         { Qt::Key_QuoteLeft, Web::UIEvents::Key_Backtick }, | 
					
						
							|  |  |  |         { Qt::Key_R, Web::UIEvents::Key_R }, | 
					
						
							|  |  |  |         { Qt::Key_Return, Web::UIEvents::Key_Return }, | 
					
						
							|  |  |  |         { Qt::Key_Right, Web::UIEvents::Key_Right }, | 
					
						
							|  |  |  |         { Qt::Key_S, Web::UIEvents::Key_S }, | 
					
						
							|  |  |  |         { Qt::Key_ScrollLock, Web::UIEvents::Key_ScrollLock }, | 
					
						
							|  |  |  |         { Qt::Key_Semicolon, Web::UIEvents::Key_Semicolon }, | 
					
						
							|  |  |  |         { Qt::Key_Shift, Web::UIEvents::Key_LeftShift }, | 
					
						
							|  |  |  |         { Qt::Key_Slash, Web::UIEvents::Key_Slash }, | 
					
						
							|  |  |  |         { Qt::Key_Space, Web::UIEvents::Key_Space }, | 
					
						
							|  |  |  |         { Qt::Key_Super_L, Web::UIEvents::Key_Super }, | 
					
						
							|  |  |  |         { Qt::Key_Super_R, Web::UIEvents::Key_Super }, | 
					
						
							|  |  |  |         { Qt::Key_SysReq, Web::UIEvents::Key_SysRq }, | 
					
						
							|  |  |  |         { Qt::Key_T, Web::UIEvents::Key_T }, | 
					
						
							|  |  |  |         { Qt::Key_Tab, Web::UIEvents::Key_Tab }, | 
					
						
							|  |  |  |         { Qt::Key_U, Web::UIEvents::Key_U }, | 
					
						
							|  |  |  |         { Qt::Key_Underscore, Web::UIEvents::Key_Underscore }, | 
					
						
							|  |  |  |         { Qt::Key_Up, Web::UIEvents::Key_Up }, | 
					
						
							|  |  |  |         { Qt::Key_V, Web::UIEvents::Key_V }, | 
					
						
							|  |  |  |         { Qt::Key_W, Web::UIEvents::Key_W }, | 
					
						
							|  |  |  |         { Qt::Key_X, Web::UIEvents::Key_X }, | 
					
						
							|  |  |  |         { Qt::Key_Y, Web::UIEvents::Key_Y }, | 
					
						
							|  |  |  |         { Qt::Key_Z, Web::UIEvents::Key_Z }, | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (auto const& mapping : mappings) { | 
					
						
							|  |  |  |         if (event.key() == mapping.qt_key) | 
					
						
							|  |  |  |             return mapping.serenity_key; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-06-06 13:29:08 -06:00
										 |  |  |     return Web::UIEvents::Key_Invalid; | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-05 07:53:57 -05:00
										 |  |  | void WebContentView::keyPressEvent(QKeyEvent* event) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     enqueue_native_event(Web::KeyEvent::Type::KeyDown, *event); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void WebContentView::keyReleaseEvent(QKeyEvent* event) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     enqueue_native_event(Web::KeyEvent::Type::KeyUp, *event); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-12 14:06:41 +02:00
										 |  |  | void WebContentView::inputMethodEvent(QInputMethodEvent* event) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!event->commitString().isEmpty()) { | 
					
						
							|  |  |  |         QKeyEvent keyEvent(QEvent::KeyPress, 0, Qt::NoModifier, event->commitString()); | 
					
						
							|  |  |  |         keyPressEvent(&keyEvent); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     event->accept(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QVariant WebContentView::inputMethodQuery(Qt::InputMethodQuery) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return QVariant(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  | void WebContentView::mouseMoveEvent(QMouseEvent* event) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2024-07-02 16:48:57 +02:00
										 |  |  |     if (!m_tooltip_override) { | 
					
						
							|  |  |  |         if (QToolTip::isVisible()) | 
					
						
							|  |  |  |             QToolTip::hideText(); | 
					
						
							|  |  |  |         m_tooltip_hover_timer.start(600); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-07-02 14:16:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-05 07:53:57 -05:00
										 |  |  |     enqueue_native_event(Web::MouseEvent::Type::MouseMove, *event); | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void WebContentView::mousePressEvent(QMouseEvent* event) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2024-03-05 07:53:57 -05:00
										 |  |  |     enqueue_native_event(Web::MouseEvent::Type::MouseDown, *event); | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void WebContentView::mouseReleaseEvent(QMouseEvent* event) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2024-03-05 07:53:57 -05:00
										 |  |  |     enqueue_native_event(Web::MouseEvent::Type::MouseUp, *event); | 
					
						
							| 
									
										
										
										
											2022-11-08 02:00:24 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-05 07:53:57 -05:00
										 |  |  |     if (event->button() == Qt::MouseButton::BackButton) { | 
					
						
							| 
									
										
										
										
											2023-08-18 18:33:25 -04:00
										 |  |  |         if (on_navigate_back) | 
					
						
							|  |  |  |             on_navigate_back(); | 
					
						
							| 
									
										
										
										
											2024-03-05 07:53:57 -05:00
										 |  |  |     } else if (event->button() == Qt::MouseButton::ForwardButton) { | 
					
						
							| 
									
										
										
										
											2023-08-18 18:33:25 -04:00
										 |  |  |         if (on_navigate_forward) | 
					
						
							|  |  |  |             on_navigate_forward(); | 
					
						
							| 
									
										
										
										
											2022-11-08 02:00:24 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-12-15 17:46:09 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void WebContentView::wheelEvent(QWheelEvent* event) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2024-03-06 07:21:00 -05:00
										 |  |  |     if (event->modifiers().testFlag(Qt::ControlModifier)) { | 
					
						
							|  |  |  |         event->ignore(); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-05 07:53:57 -05:00
										 |  |  |     enqueue_native_event(Web::MouseEvent::Type::MouseWheel, *event); | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-13 15:55:10 +01:00
										 |  |  | void WebContentView::mouseDoubleClickEvent(QMouseEvent* event) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2024-03-05 07:53:57 -05:00
										 |  |  |     enqueue_native_event(Web::MouseEvent::Type::DoubleClick, *event); | 
					
						
							| 
									
										
										
										
											2023-05-13 15:55:10 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-07 17:40:04 +01:00
										 |  |  | void WebContentView::dragEnterEvent(QDragEnterEvent* event) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2024-08-17 14:47:28 -04:00
										 |  |  |     if (!event->mimeData()->hasUrls()) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     enqueue_native_event(Web::DragEvent::Type::DragStart, *event); | 
					
						
							|  |  |  |     event->acceptProposedAction(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void WebContentView::dragMoveEvent(QDragMoveEvent* event) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     enqueue_native_event(Web::DragEvent::Type::DragMove, *event); | 
					
						
							|  |  |  |     event->acceptProposedAction(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void WebContentView::dragLeaveEvent(QDragLeaveEvent*) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // QDragLeaveEvent does not contain any mouse position or button information.
 | 
					
						
							|  |  |  |     Web::DragEvent event {}; | 
					
						
							|  |  |  |     event.type = Web::DragEvent::Type::DragEnd; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     enqueue_input_event(AK::move(event)); | 
					
						
							| 
									
										
										
										
											2023-01-07 17:40:04 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void WebContentView::dropEvent(QDropEvent* event) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2024-08-17 14:47:28 -04:00
										 |  |  |     enqueue_native_event(Web::DragEvent::Type::Drop, *event); | 
					
						
							| 
									
										
										
										
											2023-01-07 17:40:04 +01:00
										 |  |  |     event->acceptProposedAction(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-11 11:38:03 +02:00
										 |  |  | void WebContentView::focusInEvent(QFocusEvent*) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2024-02-02 18:00:48 -07:00
										 |  |  |     client().async_set_has_focus(m_client_state.page_index, true); | 
					
						
							| 
									
										
										
										
											2022-10-11 11:38:03 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void WebContentView::focusOutEvent(QFocusEvent*) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2024-02-02 18:00:48 -07:00
										 |  |  |     client().async_set_has_focus(m_client_state.page_index, false); | 
					
						
							| 
									
										
										
										
											2022-10-11 11:38:03 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  | void WebContentView::paintEvent(QPaintEvent*) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QPainter painter(viewport()); | 
					
						
							| 
									
										
										
										
											2023-12-13 19:10:05 +01:00
										 |  |  |     painter.scale(1 / m_device_pixel_ratio, 1 / m_device_pixel_ratio); | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-14 18:57:14 +02:00
										 |  |  |     Gfx::Bitmap const* bitmap = nullptr; | 
					
						
							|  |  |  |     Gfx::IntSize bitmap_size; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (m_client_state.has_usable_bitmap) { | 
					
						
							|  |  |  |         bitmap = m_client_state.front_bitmap.bitmap.ptr(); | 
					
						
							| 
									
										
										
										
											2023-12-14 07:17:00 +01:00
										 |  |  |         bitmap_size = m_client_state.front_bitmap.last_painted_size.to_type<int>(); | 
					
						
							| 
									
										
										
										
											2023-05-14 18:57:14 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         bitmap = m_backup_bitmap.ptr(); | 
					
						
							| 
									
										
										
										
											2023-12-14 07:17:00 +01:00
										 |  |  |         bitmap_size = m_backup_bitmap_size.to_type<int>(); | 
					
						
							| 
									
										
										
										
											2023-05-14 18:57:14 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (bitmap) { | 
					
						
							| 
									
										
										
										
											2024-06-26 17:56:20 +02:00
										 |  |  |         QImage q_image(bitmap->scanline_u8(0), bitmap->width(), bitmap->height(), bitmap->pitch(), QImage::Format_RGB32); | 
					
						
							| 
									
										
										
										
											2023-05-14 18:57:14 +02:00
										 |  |  |         painter.drawImage(QPoint(0, 0), q_image, QRect(0, 0, bitmap_size.width(), bitmap_size.height())); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (bitmap_size.width() < width()) { | 
					
						
							|  |  |  |             painter.fillRect(bitmap_size.width(), 0, width() - bitmap_size.width(), bitmap->height(), palette().base()); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (bitmap_size.height() < height()) { | 
					
						
							|  |  |  |             painter.fillRect(0, bitmap_size.height(), width(), height() - bitmap_size.height(), palette().base()); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     painter.fillRect(rect(), palette().base()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void WebContentView::resizeEvent(QResizeEvent* event) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QAbstractScrollArea::resizeEvent(event); | 
					
						
							| 
									
										
										
										
											2024-06-03 17:53:55 +03:00
										 |  |  |     update_viewport_size(); | 
					
						
							| 
									
										
										
										
											2023-05-15 07:59:51 +02:00
										 |  |  |     handle_resize(); | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-30 23:38:19 +03:00
										 |  |  | void WebContentView::set_viewport_rect(Gfx::IntRect rect) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2024-06-03 17:53:55 +03:00
										 |  |  |     m_viewport_size = rect.size(); | 
					
						
							|  |  |  |     client().async_set_viewport_size(m_client_state.page_index, rect.size().to_type<Web::DevicePixels>()); | 
					
						
							| 
									
										
										
										
											2023-01-30 23:38:19 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-08 23:57:24 +03:00
										 |  |  | void WebContentView::set_window_size(Gfx::IntSize size) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2024-02-02 18:00:48 -07:00
										 |  |  |     client().async_set_window_size(m_client_state.page_index, size.to_type<Web::DevicePixels>()); | 
					
						
							| 
									
										
										
										
											2023-03-08 23:57:24 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void WebContentView::set_window_position(Gfx::IntPoint position) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2024-02-02 18:00:48 -07:00
										 |  |  |     client().async_set_window_position(m_client_state.page_index, position.to_type<Web::DevicePixels>()); | 
					
						
							| 
									
										
										
										
											2023-03-08 23:57:24 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-13 19:10:05 +01:00
										 |  |  | void WebContentView::set_device_pixel_ratio(double device_pixel_ratio) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     m_device_pixel_ratio = device_pixel_ratio; | 
					
						
							| 
									
										
										
										
											2024-02-02 18:00:48 -07:00
										 |  |  |     client().async_set_device_pixels_per_css_pixel(m_client_state.page_index, m_device_pixel_ratio * m_zoom_level); | 
					
						
							| 
									
										
										
										
											2024-06-03 17:53:55 +03:00
										 |  |  |     update_viewport_size(); | 
					
						
							| 
									
										
										
										
											2023-12-13 19:10:05 +01:00
										 |  |  |     handle_resize(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-03 17:53:55 +03:00
										 |  |  | void WebContentView::update_viewport_size() | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-12-13 19:10:05 +01:00
										 |  |  |     auto scaled_width = int(viewport()->width() * m_device_pixel_ratio); | 
					
						
							|  |  |  |     auto scaled_height = int(viewport()->height() * m_device_pixel_ratio); | 
					
						
							| 
									
										
										
										
											2024-06-03 17:53:55 +03:00
										 |  |  |     Gfx::IntRect rect(0, 0, scaled_width, scaled_height); | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-30 23:38:19 +03:00
										 |  |  |     set_viewport_rect(rect); | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-12 14:39:53 +00:00
										 |  |  | void WebContentView::update_zoom() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2024-02-02 18:00:48 -07:00
										 |  |  |     client().async_set_device_pixels_per_css_pixel(m_client_state.page_index, m_device_pixel_ratio * m_zoom_level); | 
					
						
							| 
									
										
										
										
											2024-06-03 17:53:55 +03:00
										 |  |  |     update_viewport_size(); | 
					
						
							| 
									
										
										
										
											2023-01-12 14:39:53 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  | void WebContentView::showEvent(QShowEvent* event) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QAbstractScrollArea::showEvent(event); | 
					
						
							| 
									
										
										
										
											2024-02-02 18:00:48 -07:00
										 |  |  |     client().async_set_system_visibility_state(m_client_state.page_index, true); | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void WebContentView::hideEvent(QHideEvent* event) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QAbstractScrollArea::hideEvent(event); | 
					
						
							| 
									
										
										
										
											2024-02-02 18:00:48 -07:00
										 |  |  |     client().async_set_system_visibility_state(m_client_state.page_index, false); | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-22 21:57:08 -04:00
										 |  |  | static Core::AnonymousBuffer make_system_theme_from_qt_palette(QWidget& widget, WebContentView::PaletteMode mode) | 
					
						
							| 
									
										
										
										
											2023-03-15 22:56:47 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     auto qt_palette = widget.palette(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-22 21:57:08 -04:00
										 |  |  |     auto theme_file = mode == WebContentView::PaletteMode::Default ? "Default"sv : "Dark"sv; | 
					
						
							| 
									
										
										
										
											2023-11-05 09:46:28 -05:00
										 |  |  |     auto theme_ini = MUST(Core::Resource::load_from_uri(MUST(String::formatted("resource://themes/{}.ini", theme_file)))); | 
					
						
							| 
									
										
										
										
											2023-12-16 17:49:34 +03:30
										 |  |  |     auto theme = Gfx::load_system_theme(theme_ini->filesystem_path().to_byte_string()).release_value_but_fixme_should_propagate_errors(); | 
					
						
							| 
									
										
										
										
											2023-11-05 09:46:28 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-15 22:56:47 +01:00
										 |  |  |     auto palette_impl = Gfx::PaletteImpl::create_with_anonymous_buffer(theme); | 
					
						
							|  |  |  |     auto palette = Gfx::Palette(move(palette_impl)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto translate = [&](Gfx::ColorRole gfx_color_role, QPalette::ColorRole qt_color_role) { | 
					
						
							|  |  |  |         auto new_color = Gfx::Color::from_argb(qt_palette.color(qt_color_role).rgba()); | 
					
						
							|  |  |  |         palette.set_color(gfx_color_role, new_color); | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     translate(Gfx::ColorRole::ThreedHighlight, QPalette::ColorRole::Light); | 
					
						
							|  |  |  |     translate(Gfx::ColorRole::ThreedShadow1, QPalette::ColorRole::Mid); | 
					
						
							|  |  |  |     translate(Gfx::ColorRole::ThreedShadow2, QPalette::ColorRole::Dark); | 
					
						
							|  |  |  |     translate(Gfx::ColorRole::HoverHighlight, QPalette::ColorRole::Light); | 
					
						
							|  |  |  |     translate(Gfx::ColorRole::Link, QPalette::ColorRole::Link); | 
					
						
							|  |  |  |     translate(Gfx::ColorRole::VisitedLink, QPalette::ColorRole::LinkVisited); | 
					
						
							|  |  |  |     translate(Gfx::ColorRole::Button, QPalette::ColorRole::Button); | 
					
						
							|  |  |  |     translate(Gfx::ColorRole::ButtonText, QPalette::ColorRole::ButtonText); | 
					
						
							|  |  |  |     translate(Gfx::ColorRole::Selection, QPalette::ColorRole::Highlight); | 
					
						
							|  |  |  |     translate(Gfx::ColorRole::SelectionText, QPalette::ColorRole::HighlightedText); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-29 18:35:06 +02:00
										 |  |  |     palette.set_flag(Gfx::FlagRole::IsDark, is_using_dark_system_theme(widget)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-15 22:56:47 +01:00
										 |  |  |     return theme; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-22 21:57:08 -04:00
										 |  |  | void WebContentView::update_palette(PaletteMode mode) | 
					
						
							| 
									
										
										
										
											2023-03-15 22:56:47 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-02-02 18:00:48 -07:00
										 |  |  |     client().async_update_system_theme(m_client_state.page_index, make_system_theme_from_qt_palette(*this, mode)); | 
					
						
							| 
									
										
										
										
											2023-03-15 22:56:47 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-11 15:00:00 +12:00
										 |  |  | void WebContentView::update_screen_rects() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     auto screens = QGuiApplication::screens(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!screens.empty()) { | 
					
						
							|  |  |  |         Vector<Web::DevicePixelRect> screen_rects; | 
					
						
							|  |  |  |         for (auto const& screen : screens) { | 
					
						
							| 
									
										
										
										
											2024-05-29 22:37:39 +01:00
										 |  |  |             // NOTE: QScreen::geometry() returns the 'device-independent pixels', we multiply
 | 
					
						
							|  |  |  |             //       by the device pixel ratio to get the 'physical pixels' of the display.
 | 
					
						
							| 
									
										
										
										
											2024-05-11 15:00:00 +12:00
										 |  |  |             auto geometry = screen->geometry(); | 
					
						
							| 
									
										
										
										
											2024-05-29 22:37:39 +01:00
										 |  |  |             auto device_pixel_ratio = screen->devicePixelRatio(); | 
					
						
							|  |  |  |             screen_rects.append(Web::DevicePixelRect(geometry.x(), geometry.y(), geometry.width() * device_pixel_ratio, geometry.height() * device_pixel_ratio)); | 
					
						
							| 
									
										
										
										
											2024-05-11 15:00:00 +12:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // NOTE: The first item in QGuiApplication::screens is always the primary screen.
 | 
					
						
							|  |  |  |         //       This is not specified in the documentation but QGuiApplication::primaryScreen
 | 
					
						
							|  |  |  |         //       always returns the first item in the list if it isn't empty.
 | 
					
						
							|  |  |  |         client().async_update_screen_rects(m_client_state.page_index, screen_rects, 0); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-30 09:12:14 -07:00
										 |  |  | void WebContentView::initialize_client(WebView::ViewImplementation::CreateNewClient create_new_client) | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-01-30 09:12:14 -07:00
										 |  |  |     if (create_new_client == CreateNewClient::Yes) { | 
					
						
							|  |  |  |         m_client_state = {}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-17 18:44:39 -06:00
										 |  |  |         Optional<IPC::File> request_server_socket; | 
					
						
							| 
									
										
										
										
											2024-07-30 14:01:05 -04:00
										 |  |  |         if (WebView::Application::web_content_options().use_lagom_networking == WebView::UseLagomNetworking::Yes) { | 
					
						
							| 
									
										
										
										
											2024-04-15 17:39:48 -06:00
										 |  |  |             auto& protocol = static_cast<Ladybird::Application*>(QApplication::instance())->request_server_client; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // FIXME: Fail to open the tab, rather than crashing the whole application if this fails
 | 
					
						
							| 
									
										
										
										
											2024-04-17 18:44:39 -06:00
										 |  |  |             auto socket = connect_new_request_server_client(*protocol).release_value_but_fixme_should_propagate_errors(); | 
					
						
							|  |  |  |             request_server_socket = AK::move(socket); | 
					
						
							| 
									
										
										
										
											2024-04-15 17:39:48 -06:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-26 13:44:42 -06:00
										 |  |  |         auto image_decoder = static_cast<Ladybird::Application*>(QApplication::instance())->image_decoder_client(); | 
					
						
							|  |  |  |         auto image_decoder_socket = connect_new_image_decoder_client(*image_decoder).release_value_but_fixme_should_propagate_errors(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-30 09:12:14 -07:00
										 |  |  |         auto candidate_web_content_paths = get_paths_for_helper_process("WebContent"sv).release_value_but_fixme_should_propagate_errors(); | 
					
						
							| 
									
										
										
										
											2024-07-30 14:01:05 -04:00
										 |  |  |         auto new_client = launch_web_content_process(*this, candidate_web_content_paths, AK::move(image_decoder_socket), AK::move(request_server_socket)).release_value_but_fixme_should_propagate_errors(); | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-30 09:12:14 -07:00
										 |  |  |         m_client_state.client = new_client; | 
					
						
							| 
									
										
										
										
											2024-02-02 18:00:48 -07:00
										 |  |  |     } else { | 
					
						
							|  |  |  |         m_client_state.client->register_view(m_client_state.page_index, *this); | 
					
						
							| 
									
										
										
										
											2024-01-30 09:12:14 -07:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     m_client_state.client->on_web_content_process_crash = [this] { | 
					
						
							| 
									
										
										
										
											2023-04-24 18:02:29 +02:00
										 |  |  |         Core::deferred_invoke([this] { | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  |             handle_web_content_process_crash(); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-16 18:35:19 +03:00
										 |  |  |     m_client_state.client_handle = Web::Crypto::generate_random_uuid().release_value_but_fixme_should_propagate_errors(); | 
					
						
							| 
									
										
										
										
											2024-02-02 18:00:48 -07:00
										 |  |  |     client().async_set_window_handle(m_client_state.page_index, m_client_state.client_handle); | 
					
						
							| 
									
										
										
										
											2023-03-16 18:35:19 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-02 18:00:48 -07:00
										 |  |  |     client().async_set_device_pixels_per_css_pixel(m_client_state.page_index, m_device_pixel_ratio); | 
					
						
							| 
									
										
										
										
											2023-03-15 22:56:47 +01:00
										 |  |  |     update_palette(); | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-11 15:00:00 +12:00
										 |  |  |     update_screen_rects(); | 
					
						
							| 
									
										
										
										
											2023-03-16 08:50:22 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-30 14:01:05 -04:00
										 |  |  |     if (auto webdriver_content_ipc_path = WebView::Application::chrome_options().webdriver_content_ipc_path; webdriver_content_ipc_path.has_value()) | 
					
						
							|  |  |  |         client().async_connect_to_webdriver(m_client_state.page_index, *webdriver_content_ipc_path); | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-23 10:43:27 -04:00
										 |  |  | void WebContentView::update_cursor(Gfx::StandardCursor cursor) | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     switch (cursor) { | 
					
						
							| 
									
										
										
										
											2023-04-13 20:07:54 -04:00
										 |  |  |     case Gfx::StandardCursor::Hidden: | 
					
						
							|  |  |  |         setCursor(Qt::BlankCursor); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Gfx::StandardCursor::Arrow: | 
					
						
							|  |  |  |         setCursor(Qt::ArrowCursor); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Gfx::StandardCursor::Crosshair: | 
					
						
							|  |  |  |         setCursor(Qt::CrossCursor); | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  |         break; | 
					
						
							|  |  |  |     case Gfx::StandardCursor::IBeam: | 
					
						
							|  |  |  |         setCursor(Qt::IBeamCursor); | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2023-04-13 20:07:54 -04:00
										 |  |  |     case Gfx::StandardCursor::ResizeHorizontal: | 
					
						
							|  |  |  |         setCursor(Qt::SizeHorCursor); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Gfx::StandardCursor::ResizeVertical: | 
					
						
							|  |  |  |         setCursor(Qt::SizeVerCursor); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Gfx::StandardCursor::ResizeDiagonalTLBR: | 
					
						
							|  |  |  |         setCursor(Qt::SizeFDiagCursor); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Gfx::StandardCursor::ResizeDiagonalBLTR: | 
					
						
							|  |  |  |         setCursor(Qt::SizeBDiagCursor); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Gfx::StandardCursor::ResizeColumn: | 
					
						
							|  |  |  |         setCursor(Qt::SplitHCursor); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Gfx::StandardCursor::ResizeRow: | 
					
						
							|  |  |  |         setCursor(Qt::SplitVCursor); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Gfx::StandardCursor::Hand: | 
					
						
							|  |  |  |         setCursor(Qt::PointingHandCursor); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Gfx::StandardCursor::Help: | 
					
						
							|  |  |  |         setCursor(Qt::WhatsThisCursor); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Gfx::StandardCursor::Drag: | 
					
						
							|  |  |  |         setCursor(Qt::ClosedHandCursor); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Gfx::StandardCursor::DragCopy: | 
					
						
							|  |  |  |         setCursor(Qt::DragCopyCursor); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Gfx::StandardCursor::Move: | 
					
						
							|  |  |  |         setCursor(Qt::DragMoveCursor); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Gfx::StandardCursor::Wait: | 
					
						
							|  |  |  |         setCursor(Qt::BusyCursor); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Gfx::StandardCursor::Disallowed: | 
					
						
							|  |  |  |         setCursor(Qt::ForbiddenCursor); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Gfx::StandardCursor::Eyedropper: | 
					
						
							|  |  |  |     case Gfx::StandardCursor::Zoom: | 
					
						
							|  |  |  |         // FIXME: No corresponding Qt cursors, default to Arrow
 | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  |     default: | 
					
						
							|  |  |  |         setCursor(Qt::ArrowCursor); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-03 17:53:55 +03:00
										 |  |  | Web::DevicePixelSize WebContentView::viewport_size() const | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-06-03 17:53:55 +03:00
										 |  |  |     return m_viewport_size.to_type<Web::DevicePixels>(); | 
					
						
							| 
									
										
										
										
											2022-10-05 15:23:41 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2022-10-11 17:17:49 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-10 22:15:06 -04:00
										 |  |  | QPoint WebContentView::map_point_to_global_position(Gfx::IntPoint position) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return mapToGlobal(QPoint { position.x(), position.y() } / device_pixel_ratio()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-17 10:12:13 -04:00
										 |  |  | Gfx::IntPoint WebContentView::to_content_position(Gfx::IntPoint widget_position) const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2024-06-03 17:53:55 +03:00
										 |  |  |     return widget_position; | 
					
						
							| 
									
										
										
										
											2023-05-17 10:12:13 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Gfx::IntPoint WebContentView::to_widget_position(Gfx::IntPoint content_position) const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2024-06-03 17:53:55 +03:00
										 |  |  |     return content_position; | 
					
						
							| 
									
										
										
										
											2023-05-17 10:12:13 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-11 17:17:49 +02:00
										 |  |  | bool WebContentView::event(QEvent* event) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // NOTE: We have to implement event() manually as Qt's focus navigation mechanism
 | 
					
						
							|  |  |  |     //       eats all the Tab key presses by default.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (event->type() == QEvent::KeyPress) { | 
					
						
							|  |  |  |         keyPressEvent(static_cast<QKeyEvent*>(event)); | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (event->type() == QEvent::KeyRelease) { | 
					
						
							|  |  |  |         keyReleaseEvent(static_cast<QKeyEvent*>(event)); | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-03-15 22:56:47 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (event->type() == QEvent::PaletteChange) { | 
					
						
							|  |  |  |         update_palette(); | 
					
						
							|  |  |  |         return QAbstractScrollArea::event(event); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-05 07:53:57 -05:00
										 |  |  |     if (event->type() == QEvent::ShortcutOverride) { | 
					
						
							|  |  |  |         event->accept(); | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-11 17:17:49 +02:00
										 |  |  |     return QAbstractScrollArea::event(event); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2022-11-21 16:36:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-27 10:41:24 +01:00
										 |  |  | ErrorOr<String> WebContentView::dump_layout_tree() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2024-02-02 18:00:48 -07:00
										 |  |  |     return String::from_byte_string(client().dump_layout_tree(m_client_state.page_index)); | 
					
						
							| 
									
										
										
										
											2023-01-27 10:41:24 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2023-08-02 11:52:59 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-05 07:53:57 -05:00
										 |  |  | void WebContentView::enqueue_native_event(Web::MouseEvent::Type type, QSinglePointEvent const& event) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2024-06-03 17:53:55 +03:00
										 |  |  |     Web::DevicePixelPoint position = { event.position().x() * m_device_pixel_ratio, event.position().y() * m_device_pixel_ratio }; | 
					
						
							| 
									
										
										
										
											2024-03-05 07:53:57 -05:00
										 |  |  |     auto screen_position = Gfx::IntPoint { event.globalPosition().x() * m_device_pixel_ratio, event.globalPosition().y() * m_device_pixel_ratio }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-17 14:47:28 -04:00
										 |  |  |     auto button = get_button_from_qt_event(event.button()); | 
					
						
							|  |  |  |     auto buttons = get_buttons_from_qt_event(event.buttons()); | 
					
						
							|  |  |  |     auto modifiers = get_modifiers_from_qt_mouse_event(event.modifiers()); | 
					
						
							| 
									
										
										
										
											2024-03-05 07:53:57 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (button == 0 && (type == Web::MouseEvent::Type::MouseDown || type == Web::MouseEvent::Type::MouseUp)) { | 
					
						
							|  |  |  |         // We could not convert Qt buttons to something that LibWeb can recognize - don't even bother propagating this
 | 
					
						
							|  |  |  |         // to the web engine as it will not handle it anyway, and it will (currently) assert.
 | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int wheel_delta_x = 0; | 
					
						
							|  |  |  |     int wheel_delta_y = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-06 07:21:00 -05:00
										 |  |  |     if (type == Web::MouseEvent::Type::MouseWheel) { | 
					
						
							| 
									
										
										
										
											2024-03-05 07:53:57 -05:00
										 |  |  |         auto const& wheel_event = static_cast<QWheelEvent const&>(event); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (auto pixel_delta = -wheel_event.pixelDelta(); !pixel_delta.isNull()) { | 
					
						
							|  |  |  |             wheel_delta_x = pixel_delta.x(); | 
					
						
							|  |  |  |             wheel_delta_y = pixel_delta.y(); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             auto angle_delta = -wheel_event.angleDelta(); | 
					
						
							|  |  |  |             float delta_x = -static_cast<float>(angle_delta.x()) / 120.0f; | 
					
						
							|  |  |  |             float delta_y = static_cast<float>(angle_delta.y()) / 120.0f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             auto step_x = delta_x * static_cast<float>(QApplication::wheelScrollLines()) * m_device_pixel_ratio; | 
					
						
							|  |  |  |             auto step_y = delta_y * static_cast<float>(QApplication::wheelScrollLines()) * m_device_pixel_ratio; | 
					
						
							|  |  |  |             auto scroll_step_size = static_cast<float>(verticalScrollBar()->singleStep()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             wheel_delta_x = static_cast<int>(step_x * scroll_step_size); | 
					
						
							|  |  |  |             wheel_delta_y = static_cast<int>(step_y * scroll_step_size); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-03 17:53:55 +03:00
										 |  |  |     enqueue_input_event(Web::MouseEvent { type, position, screen_position.to_type<Web::DevicePixels>(), button, buttons, modifiers, wheel_delta_x, wheel_delta_y, nullptr }); | 
					
						
							| 
									
										
										
										
											2024-03-05 07:53:57 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-17 14:47:28 -04:00
										 |  |  | struct DragData : Web::ChromeInputData { | 
					
						
							|  |  |  |     explicit DragData(QDropEvent const& event) | 
					
						
							|  |  |  |         : urls(event.mimeData()->urls()) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QList<QUrl> urls; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void WebContentView::enqueue_native_event(Web::DragEvent::Type type, QDropEvent const& event) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Web::DevicePixelPoint position = { event.position().x() * m_device_pixel_ratio, event.position().y() * m_device_pixel_ratio }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto global_position = mapToGlobal(event.position()); | 
					
						
							|  |  |  |     auto screen_position = Gfx::IntPoint { global_position.x() * m_device_pixel_ratio, global_position.y() * m_device_pixel_ratio }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto button = get_button_from_qt_event(Qt::LeftButton); | 
					
						
							|  |  |  |     auto buttons = get_buttons_from_qt_event(event.buttons()); | 
					
						
							|  |  |  |     auto modifiers = get_modifiers_from_qt_mouse_event(event.modifiers()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Vector<Web::HTML::SelectedFile> files; | 
					
						
							|  |  |  |     OwnPtr<DragData> chrome_data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (type == Web::DragEvent::Type::DragStart) { | 
					
						
							|  |  |  |         VERIFY(event.mimeData()->hasUrls()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for (auto const& url : event.mimeData()->urls()) { | 
					
						
							|  |  |  |             auto file_path = ak_byte_string_from_qstring(url.toLocalFile()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (auto file = Web::HTML::SelectedFile::from_file_path(file_path); file.is_error()) | 
					
						
							|  |  |  |                 warnln("Unable to open file {}: {}", file_path, file.error()); | 
					
						
							|  |  |  |             else | 
					
						
							|  |  |  |                 files.append(file.release_value()); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } else if (type == Web::DragEvent::Type::Drop) { | 
					
						
							|  |  |  |         chrome_data = make<DragData>(event); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     enqueue_input_event(Web::DragEvent { type, position, screen_position.to_type<Web::DevicePixels>(), button, buttons, modifiers, AK::move(files), AK::move(chrome_data) }); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void WebContentView::finish_handling_drag_event(Web::DragEvent const& event) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (event.type != Web::DragEvent::Type::Drop) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto const& chrome_data = verify_cast<DragData>(*event.chrome_data); | 
					
						
							|  |  |  |     emit urls_dropped(chrome_data.urls); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-05 07:53:57 -05:00
										 |  |  | struct KeyData : Web::ChromeInputData { | 
					
						
							|  |  |  |     explicit KeyData(QKeyEvent const& event) | 
					
						
							|  |  |  |         : event(adopt_own(*event.clone())) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     NonnullOwnPtr<QKeyEvent> event; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void WebContentView::enqueue_native_event(Web::KeyEvent::Type type, QKeyEvent const& event) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     auto keycode = get_keycode_from_qt_keyboard_event(event); | 
					
						
							|  |  |  |     auto modifiers = get_modifiers_from_qt_keyboard_event(event); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto text = event.text(); | 
					
						
							|  |  |  |     auto code_point = text.isEmpty() ? 0u : event.text()[0].unicode(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto to_web_event = [&]() -> Web::KeyEvent { | 
					
						
							|  |  |  |         if (event.key() == Qt::Key_Backtab) { | 
					
						
							|  |  |  |             // Qt transforms Shift+Tab into a "Backtab", so we undo that transformation here.
 | 
					
						
							| 
									
										
										
										
											2024-06-06 13:29:08 -06:00
										 |  |  |             return { type, Web::UIEvents::KeyCode::Key_Tab, Web::UIEvents::Mod_Shift, '\t', make<KeyData>(event) }; | 
					
						
							| 
									
										
										
										
											2024-03-05 07:53:57 -05:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (event.key() == Qt::Key_Enter || event.key() == Qt::Key_Return) { | 
					
						
							|  |  |  |             // This ensures consistent behavior between systems that treat Enter as '\n' and '\r\n'
 | 
					
						
							| 
									
										
										
										
											2024-06-06 13:29:08 -06:00
										 |  |  |             return { type, Web::UIEvents::KeyCode::Key_Return, Web::UIEvents::Mod_Shift, '\n', make<KeyData>(event) }; | 
					
						
							| 
									
										
										
										
											2024-03-05 07:53:57 -05:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return { type, keycode, modifiers, code_point, make<KeyData>(event) }; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     enqueue_input_event(to_web_event()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void WebContentView::finish_handling_key_event(Web::KeyEvent const& key_event) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     auto& chrome_data = verify_cast<KeyData>(*key_event.chrome_data); | 
					
						
							|  |  |  |     auto& event = *chrome_data.event; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     switch (key_event.type) { | 
					
						
							|  |  |  |     case Web::KeyEvent::Type::KeyDown: | 
					
						
							|  |  |  |         QAbstractScrollArea::keyPressEvent(&event); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Web::KeyEvent::Type::KeyUp: | 
					
						
							|  |  |  |         QAbstractScrollArea::keyReleaseEvent(&event); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!event.isAccepted()) | 
					
						
							|  |  |  |         QApplication::sendEvent(parent(), &event); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-02 11:52:59 -06:00
										 |  |  | } |