From a4d8294e7f978011bad30f5874689d09e43216cc Mon Sep 17 00:00:00 2001 From: Diego Iastrubni Date: Wed, 7 Sep 2022 21:52:25 +0300 Subject: [PATCH 1/2] Ladybird/UI: Context menu for links This patch implements a context menu for links. In the future, we could even check for the modifiers and open links in new windows, or private windows - but not today. --- BrowserWindow.cpp | 7 +++++++ BrowserWindow.h | 1 + Tab.cpp | 26 +++++++++++++++++++++++++- Utilities.cpp | 12 ++++++++++++ Utilities.h | 8 ++++++++ WebContentView.cpp | 10 ++++++---- WebContentView.h | 1 + 7 files changed, 60 insertions(+), 5 deletions(-) diff --git a/BrowserWindow.cpp b/BrowserWindow.cpp index 3c37f884b2d..275c1327797 100644 --- a/BrowserWindow.cpp +++ b/BrowserWindow.cpp @@ -291,9 +291,16 @@ void BrowserWindow::debug_request(String const& request, String const& argument) } void BrowserWindow::new_tab() +{ + new_tab_with_url({}); +} + +void BrowserWindow::new_tab_with_url(const QUrl &url) { auto tab = make(this, m_webdriver_fd_passing_socket); auto tab_ptr = tab.ptr(); + if (!url.isEmpty()) + tab->navigate(url.toString()); m_tabs.append(std::move(tab)); if (m_current_tab == nullptr) { diff --git a/BrowserWindow.h b/BrowserWindow.h index 252f58ec94e..e2a6ba4088a 100644 --- a/BrowserWindow.h +++ b/BrowserWindow.h @@ -32,6 +32,7 @@ public slots: void tab_title_changed(int index, QString const&); void tab_favicon_changed(int index, QIcon icon); void new_tab(); + void new_tab_with_url(QUrl const&); void close_tab(int index); void close_current_tab(); void open_next_tab(); diff --git a/Tab.cpp b/Tab.cpp index e8d1667fc4e..58863a75fe8 100644 --- a/Tab.cpp +++ b/Tab.cpp @@ -10,12 +10,16 @@ #include "Settings.h" #include "Utilities.h" #include -#include #include #include #include +#include +#include +#include +#include #include #include +#include extern String s_serenity_resource_root; extern Browser::Settings* s_settings; @@ -93,6 +97,26 @@ Tab::Tab(BrowserWindow* window, int webdriver_fd_passing_socket) m_back_action->setEnabled(m_history.can_go_back()); m_forward_action->setEnabled(m_history.can_go_forward()); }); + + QObject::connect(m_view, &WebContentView::link_content_menu, [this] (QPoint &local_position, const QUrl& url, unsigned ){ + auto global_position = this->mapToGlobal(local_position); + auto menu = QMenu(); + + auto *copy_link_action = new QAction(tr("&Copy Link")); + auto *open_link_in_tab_action = new QAction(tr("Open link in a &new tab")); + + menu.addAction(open_link_in_tab_action); + menu.addAction(copy_link_action); + auto res = menu.exec(global_position); + + if (res == copy_link_action) { + QClipboard *clipboard = QGuiApplication::clipboard(); + clipboard->setText(url.toString()); + } else if (res == open_link_in_tab_action){ + auto browser_window = static_cast(m_window); + browser_window->new_tab_with_url(url); + } + }); QObject::connect(m_location_edit, &QLineEdit::returnPressed, this, &Tab::location_edit_return_pressed); QObject::connect(m_view, &WebContentView::title_changed, this, &Tab::page_title_changed); QObject::connect(m_view, &WebContentView::favicon_changed, this, &Tab::page_favicon_changed); diff --git a/Utilities.cpp b/Utilities.cpp index 93bd83e2792..147c4511397 100644 --- a/Utilities.cpp +++ b/Utilities.cpp @@ -10,7 +10,9 @@ #include #include #include +#include #include +#include String s_serenity_resource_root; @@ -24,6 +26,16 @@ QString qstring_from_akstring(AK::String const& akstring) return QString::fromUtf8(akstring.characters(), akstring.length()); } +QUrl qurl_from_akurl(AK::URL const& akurl) +{ + return QUrl(qstring_from_akstring(akurl.to_string())); +} + +QPoint qpoint_from_intpoint(Gfx::IntPoint const& position) +{ + return QPoint(position.x(), position.y()); +} + void platform_init() { #ifdef AK_OS_ANDROID diff --git a/Utilities.h b/Utilities.h index 60132304c74..56bdfbf4958 100644 --- a/Utilities.h +++ b/Utilities.h @@ -6,11 +6,19 @@ #pragma once +#define AK_DONT_REPLACE_STD +#include +#include #include #include +#include +#include AK::String akstring_from_qstring(QString const&); QString qstring_from_akstring(AK::String const&); +QUrl qurl_from_akurl(AK::URL const& akurl); +QPoint qpoint_from_intpoint(Gfx::IntPoint const& position); + void platform_init(); extern String s_serenity_resource_root; diff --git a/WebContentView.cpp b/WebContentView.cpp index 1af4d2901e6..a1123ff7c72 100644 --- a/WebContentView.cpp +++ b/WebContentView.cpp @@ -834,11 +834,13 @@ void WebContentView::notify_server_did_request_context_menu(Badge, Gfx::IntPoint const& content_position, AK::URL const& url, String const&, unsigned) +void WebContentView::notify_server_did_request_link_context_menu(Badge, Gfx::IntPoint const& content_position, AK::URL const& url, String const&, unsigned modifiers) { - // FIXME - (void)content_position; - (void)url; + auto view_offset = QPoint(horizontalScrollBar()->value(), verticalScrollBar()->value()); + auto position_in_page = qpoint_from_intpoint(content_position); + auto position_in_view = position_in_page - view_offset; + auto qurl = qurl_from_akurl(url); + emit link_content_menu(position_in_view, qurl, modifiers); } void WebContentView::notify_server_did_request_image_context_menu(Badge, Gfx::IntPoint const& content_position, AK::URL const& url, String const&, unsigned, Gfx::ShareableBitmap const& bitmap) diff --git a/WebContentView.h b/WebContentView.h index f0c7ff7e062..5efe230dee0 100644 --- a/WebContentView.h +++ b/WebContentView.h @@ -175,6 +175,7 @@ class WebContentView final Gfx::IntRect maximize_window(); Gfx::IntRect minimize_window(); Gfx::IntRect fullscreen_window(); + void link_content_menu(QPoint &local_position, const QUrl&, unsigned modifiers); private: void request_repaint(); From efe79833de97bfa51dffd658164c1e3bcbfd270e Mon Sep 17 00:00:00 2001 From: Diego Iastrubni Date: Tue, 15 Nov 2022 13:27:48 +0200 Subject: [PATCH 2/2] META: run Clang format This was too noisy IMHO - all project got cleaned up. Will also force-close this PR: https://github.com/SerenityOS/ladybird/pull/76 --- BrowserWindow.cpp | 2 +- ConsoleGlobalObject.h | 1 - ConsoleWidget.h | 1 - SettingsDialog.cpp | 6 +++--- SettingsDialog.h | 6 +++--- Tab.cpp | 14 ++++++-------- TimerQt.cpp | 1 - Utilities.h | 4 ++-- WebContentView.h | 2 +- WebSocketClientManagerLadybird.cpp | 2 +- WebSocketClientManagerLadybird.h | 10 +++++----- 11 files changed, 22 insertions(+), 27 deletions(-) diff --git a/BrowserWindow.cpp b/BrowserWindow.cpp index 275c1327797..89cbc7fc20b 100644 --- a/BrowserWindow.cpp +++ b/BrowserWindow.cpp @@ -295,7 +295,7 @@ void BrowserWindow::new_tab() new_tab_with_url({}); } -void BrowserWindow::new_tab_with_url(const QUrl &url) +void BrowserWindow::new_tab_with_url(QUrl const& url) { auto tab = make(this, m_webdriver_fd_passing_socket); auto tab_ptr = tab.ptr(); diff --git a/ConsoleGlobalObject.h b/ConsoleGlobalObject.h index 29ecdf4de65..85923d6a4cc 100644 --- a/ConsoleGlobalObject.h +++ b/ConsoleGlobalObject.h @@ -39,7 +39,6 @@ class ConsoleGlobalObject final : public JS::GlobalObject { virtual JS::ThrowCompletionOr internal_delete(JS::PropertyKey const& name) override; virtual JS::ThrowCompletionOr> internal_own_property_keys() const override; - private: virtual void visit_edges(Visitor&) override; diff --git a/ConsoleWidget.h b/ConsoleWidget.h index 5dee51a5aea..7b2d0fb591c 100644 --- a/ConsoleWidget.h +++ b/ConsoleWidget.h @@ -35,7 +35,6 @@ class ConsoleWidget final : public QWidget { Function on_request_messages; private: - void request_console_messages(); void clear_output(); diff --git a/SettingsDialog.cpp b/SettingsDialog.cpp index 2ae7b60a89e..0a9e01ac3b2 100644 --- a/SettingsDialog.cpp +++ b/SettingsDialog.cpp @@ -4,8 +4,8 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include "Settings.h" #include "SettingsDialog.h" +#include "Settings.h" #include #include @@ -27,7 +27,7 @@ SettingsDialog::SettingsDialog(QMainWindow* window) QObject::connect(m_ok_button, &QPushButton::released, this, [this] { close(); }); - + setWindowTitle("Settings"); setFixedWidth(300); setLayout(m_layout); @@ -35,7 +35,7 @@ SettingsDialog::SettingsDialog(QMainWindow* window) setFocus(); } -void SettingsDialog::closeEvent(QCloseEvent *event) +void SettingsDialog::closeEvent(QCloseEvent* event) { save(); event->accept(); diff --git a/SettingsDialog.h b/SettingsDialog.h index 2bf829b85a6..710f2b84bc8 100644 --- a/SettingsDialog.h +++ b/SettingsDialog.h @@ -4,10 +4,10 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include #include -#include +#include #include +#include #include #pragma once @@ -16,7 +16,7 @@ class SettingsDialog : public QDialog { Q_OBJECT public: explicit SettingsDialog(QMainWindow* window); - + void save(); virtual void closeEvent(QCloseEvent*) override; diff --git a/Tab.cpp b/Tab.cpp index 58863a75fe8..1b6065988fa 100644 --- a/Tab.cpp +++ b/Tab.cpp @@ -10,13 +10,11 @@ #include "Settings.h" #include "Utilities.h" #include -#include -#include -#include #include #include #include #include +#include #include #include #include @@ -98,21 +96,21 @@ Tab::Tab(BrowserWindow* window, int webdriver_fd_passing_socket) m_forward_action->setEnabled(m_history.can_go_forward()); }); - QObject::connect(m_view, &WebContentView::link_content_menu, [this] (QPoint &local_position, const QUrl& url, unsigned ){ + QObject::connect(m_view, &WebContentView::link_content_menu, [this](QPoint& local_position, QUrl const& url, unsigned) { auto global_position = this->mapToGlobal(local_position); auto menu = QMenu(); - auto *copy_link_action = new QAction(tr("&Copy Link")); - auto *open_link_in_tab_action = new QAction(tr("Open link in a &new tab")); + auto* copy_link_action = new QAction(tr("&Copy Link")); + auto* open_link_in_tab_action = new QAction(tr("Open link in a &new tab")); menu.addAction(open_link_in_tab_action); menu.addAction(copy_link_action); auto res = menu.exec(global_position); if (res == copy_link_action) { - QClipboard *clipboard = QGuiApplication::clipboard(); + QClipboard* clipboard = QGuiApplication::clipboard(); clipboard->setText(url.toString()); - } else if (res == open_link_in_tab_action){ + } else if (res == open_link_in_tab_action) { auto browser_window = static_cast(m_window); browser_window->new_tab_with_url(url); } diff --git a/TimerQt.cpp b/TimerQt.cpp index d677e7ec730..3692a635e22 100644 --- a/TimerQt.cpp +++ b/TimerQt.cpp @@ -91,5 +91,4 @@ void TimerQt::set_single_shot(bool single_shot) m_timer->setSingleShot(single_shot); } - } diff --git a/Utilities.h b/Utilities.h index 56bdfbf4958..be65c57611e 100644 --- a/Utilities.h +++ b/Utilities.h @@ -7,11 +7,11 @@ #pragma once #define AK_DONT_REPLACE_STD +#include #include #include -#include -#include #include +#include #include AK::String akstring_from_qstring(QString const&); diff --git a/WebContentView.h b/WebContentView.h index 5efe230dee0..2d043ba60d2 100644 --- a/WebContentView.h +++ b/WebContentView.h @@ -175,7 +175,7 @@ class WebContentView final Gfx::IntRect maximize_window(); Gfx::IntRect minimize_window(); Gfx::IntRect fullscreen_window(); - void link_content_menu(QPoint &local_position, const QUrl&, unsigned modifiers); + void link_content_menu(QPoint& local_position, QUrl const&, unsigned modifiers); private: void request_repaint(); diff --git a/WebSocketClientManagerLadybird.cpp b/WebSocketClientManagerLadybird.cpp index 0e9be07fe87..1a086dfcf63 100644 --- a/WebSocketClientManagerLadybird.cpp +++ b/WebSocketClientManagerLadybird.cpp @@ -6,8 +6,8 @@ */ #include "WebSocketClientManagerLadybird.h" -#include "WebSocketLadybird.h" #include "WebSocketImplQt.h" +#include "WebSocketLadybird.h" namespace Ladybird { diff --git a/WebSocketClientManagerLadybird.h b/WebSocketClientManagerLadybird.h index 99c292054eb..58723e3571f 100644 --- a/WebSocketClientManagerLadybird.h +++ b/WebSocketClientManagerLadybird.h @@ -1,9 +1,9 @@ /* -* Copyright (c) 2022, Dex♪ -* Copyright (c) 2022, Andreas Kling -* -* SPDX-License-Identifier: BSD-2-Clause -*/ + * Copyright (c) 2022, Dex♪ + * Copyright (c) 2022, Andreas Kling + * + * SPDX-License-Identifier: BSD-2-Clause + */ #include #include