From a92b9a7e3418d13367c6c2ce0ee018006187092b Mon Sep 17 00:00:00 2001 From: Sam Atkins Date: Fri, 29 May 2026 16:09:15 +0100 Subject: [PATCH] UI/Qt: Put DevTools banner in its own widget, not a status bar Using the status bar for this meant that the "DevTools is enabled on port X" message would get overwritten whenever the user hovered over a menu item. We don't otherwise use or need a status bar, so replace it with an explicit banner widget that's only used for this purpose. Keep the existing styling so it looks the same as before. --- UI/Qt/BrowserWindow.cpp | 34 ++++++++++++---------- UI/Qt/BrowserWindow.h | 2 ++ UI/Qt/CMakeLists.txt | 1 + UI/Qt/ChromeStyle.cpp | 11 +++---- UI/Qt/ChromeStyle.h | 2 +- UI/Qt/DevToolsBanner.cpp | 62 ++++++++++++++++++++++++++++++++++++++++ UI/Qt/DevToolsBanner.h | 37 ++++++++++++++++++++++++ 7 files changed, 128 insertions(+), 21 deletions(-) create mode 100644 UI/Qt/DevToolsBanner.cpp create mode 100644 UI/Qt/DevToolsBanner.h diff --git a/UI/Qt/BrowserWindow.cpp b/UI/Qt/BrowserWindow.cpp index 610565eef2..7dba90baf7 100644 --- a/UI/Qt/BrowserWindow.cpp +++ b/UI/Qt/BrowserWindow.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #if defined(AK_OS_MACOS) # include @@ -46,10 +47,10 @@ #include #include #include -#include #include #include #include +#include #include #include #include @@ -472,7 +473,20 @@ BrowserWindow::BrowserWindow(Vector const& initial_urls, IsPopupWindow m_tabs_container->set_new_tab_action(m_new_tab_action); - setCentralWidget(m_tabs_container); + auto* main_widget = new QWidget(this); + auto* main_layout = new QVBoxLayout(main_widget); + main_layout->setContentsMargins(0, 0, 0, 0); + main_layout->setSpacing(0); + main_layout->addWidget(m_tabs_container, 1); + + m_devtools_banner = new DevToolsBanner(main_widget); + connect(m_devtools_banner, &DevToolsBanner::disable_requested, this, [] { + MUST(WebView::Application::the().toggle_devtools_enabled()); + }); + m_devtools_banner->hide(); + main_layout->addWidget(m_devtools_banner); + + setCentralWidget(main_widget); setContextMenuPolicy(Qt::PreventContextMenu); if (browser_options.devtools_port.has_value()) @@ -510,23 +524,13 @@ void BrowserWindow::update_bookmarks_bar_display(bool show_bookmarks_bar) void BrowserWindow::on_devtools_enabled() { - statusBar()->setObjectName("LadybirdStatusBar"); - statusBar()->setStyleSheet(ChromeStyle::status_bar_style_sheet(current_tab()->palette())); - - auto* disable_button = new QPushButton("Disable", this); - - connect(disable_button, &QPushButton::clicked, this, []() { - MUST(WebView::Application::the().toggle_devtools_enabled()); - }); - - statusBar()->addPermanentWidget(disable_button); - - statusBar()->showMessage(qformatted("DevTools is enabled on port {}", WebView::Application::browser_options().devtools_port)); + m_devtools_banner->set_port(WebView::Application::browser_options().devtools_port.value_or(0)); + m_devtools_banner->show(); } void BrowserWindow::on_devtools_disabled() { - setStatusBar(nullptr); + m_devtools_banner->hide(); } Tab& BrowserWindow::new_tab_from_url(URL::URL const& url, Web::HTML::ActivateTab activate_tab) diff --git a/UI/Qt/BrowserWindow.h b/UI/Qt/BrowserWindow.h index 61d248ca2f..292829020f 100644 --- a/UI/Qt/BrowserWindow.h +++ b/UI/Qt/BrowserWindow.h @@ -30,6 +30,7 @@ namespace Ladybird { class Tab; class WebContentView; class BrowserWindow; +class DevToolsBanner; class ExitFullscreenButton : public QPushButton { Q_OBJECT @@ -200,6 +201,7 @@ private: TabWidget* m_tabs_container { nullptr }; Tab* m_current_tab { nullptr }; + DevToolsBanner* m_devtools_banner { nullptr }; QMenu* m_hamburger_menu { nullptr }; QMenu* m_bookmarks_menu { nullptr }; diff --git a/UI/Qt/CMakeLists.txt b/UI/Qt/CMakeLists.txt index 7b4cfb585c..6cdbaf00a9 100644 --- a/UI/Qt/CMakeLists.txt +++ b/UI/Qt/CMakeLists.txt @@ -17,6 +17,7 @@ target_sources(ladybird PRIVATE BookmarksBar.cpp BrowserWindow.cpp ChromeStyle.cpp + DevToolsBanner.cpp EventLoopImplementationQt.cpp EventLoopImplementationQtEventTarget.cpp FindInPageWidget.cpp diff --git a/UI/Qt/ChromeStyle.cpp b/UI/Qt/ChromeStyle.cpp index 0ce22f8058..a8261815a8 100644 --- a/UI/Qt/ChromeStyle.cpp +++ b/UI/Qt/ChromeStyle.cpp @@ -712,7 +712,7 @@ QWidget#LadybirdFindInPageBar QLabel {{ background, surface, hover, pressed, border, control_border, accent, text, muted); } -QString status_bar_style_sheet(QPalette const& palette) +QString devtools_banner_style_sheet(QPalette const& palette) { auto background = style_sheet_color(chrome_background(palette)); auto border = style_sheet_color(chrome_border(palette)); @@ -722,22 +722,23 @@ QString status_bar_style_sheet(QPalette const& palette) auto text = style_sheet_color(chrome_text(palette)); return qformatted(R"( -QWidget#LadybirdStatusBar {{ +QWidget#LadybirdDevToolsBanner {{ background: {0}; border-top: 1px solid {1}; }} -QWidget#LadybirdStatusBar QPushButton {{ +QWidget#LadybirdDevToolsBanner QLabel, +QWidget#LadybirdDevToolsBanner QPushButton {{ background: transparent; color: {5}; }} -QWidget#LadybirdStatusBar QPushButton:hover {{ +QWidget#LadybirdDevToolsBanner QPushButton:hover {{ background: {3}; border-color: {2}; }} -QWidget#LadybirdStatusBar QPushButton:pressed {{ +QWidget#LadybirdDevToolsBanner QPushButton:pressed {{ background: {4}; border-color: {2}; }} diff --git a/UI/Qt/ChromeStyle.h b/UI/Qt/ChromeStyle.h index a35b85b9d1..6245a4a280 100644 --- a/UI/Qt/ChromeStyle.h +++ b/UI/Qt/ChromeStyle.h @@ -35,7 +35,7 @@ QString menu_bar_style_sheet(QPalette const&); QString location_edit_style_sheet(QPalette const&); QString bookmarks_bar_style_sheet(QPalette const&); QString find_in_page_style_sheet(QPalette const&); -QString status_bar_style_sheet(QPalette const&); +QString devtools_banner_style_sheet(QPalette const&); QString tab_widget_style_sheet(QPalette const&); QString autocomplete_popup_style_sheet(QPalette const&); diff --git a/UI/Qt/DevToolsBanner.cpp b/UI/Qt/DevToolsBanner.cpp new file mode 100644 index 0000000000..4f26ef0f1e --- /dev/null +++ b/UI/Qt/DevToolsBanner.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2026-present, the Ladybird developers. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include + +namespace Ladybird { + +DevToolsBanner::DevToolsBanner(QWidget* parent) + : QWidget(parent) +{ + setObjectName("LadybirdDevToolsBanner"); + setAttribute(Qt::WA_StyledBackground); + setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + update_chrome_style(); + + auto* layout = new QHBoxLayout(this); + layout->setContentsMargins(12, 3, 12, 3); + layout->setSpacing(6); + + m_label = new QLabel(this); + layout->addWidget(m_label); + layout->addStretch(); + + auto* disable_button = new QPushButton("Disable", this); + connect(disable_button, &QPushButton::clicked, this, &DevToolsBanner::disable_requested); + layout->addWidget(disable_button); +} + +void DevToolsBanner::set_port(u16 port) +{ + m_label->setText(qformatted("DevTools is enabled on port {}", port)); +} + +bool DevToolsBanner::event(QEvent* event) +{ + if (event->type() == QEvent::PaletteChange) + update_chrome_style(); + + return QWidget::event(event); +} + +void DevToolsBanner::update_chrome_style() +{ + if (m_is_updating_chrome_style) + return; + + m_is_updating_chrome_style = true; + setStyleSheet(ChromeStyle::devtools_banner_style_sheet(palette())); + m_is_updating_chrome_style = false; +} + +} diff --git a/UI/Qt/DevToolsBanner.h b/UI/Qt/DevToolsBanner.h new file mode 100644 index 0000000000..fef0090db7 --- /dev/null +++ b/UI/Qt/DevToolsBanner.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2026-present, the Ladybird developers. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +#include + +class QLabel; + +namespace Ladybird { + +class DevToolsBanner final : public QWidget { + Q_OBJECT + +public: + explicit DevToolsBanner(QWidget* parent = nullptr); + + void set_port(u16 port); + +signals: + void disable_requested(); + +private: + virtual bool event(QEvent*) override; + + void update_chrome_style(); + + QLabel* m_label { nullptr }; + bool m_is_updating_chrome_style { false }; +}; + +}