UI/Qt: Add optional rounded window corners on macOS
Add an advanced setting for rounded browser window corners. On macOS, Qt browser windows now use a layer-backed corner radius, and clear it when maximized, fullscreen, or the setting is disabled. Hide the setting from about:settings on other platforms for now since Qt does not expose a native antialiased window corner API there.
This commit is contained in:
parent
c4e8817246
commit
01973d1e5c
8 changed files with 115 additions and 1 deletions
|
|
@ -89,6 +89,14 @@ static Array<ConfigVariableDefinition, static_cast<size_t>(ConfigVariableID::Cou
|
|||
.default_value = JsonArray {},
|
||||
.array_element_type = JsonValue::Type::String,
|
||||
},
|
||||
{
|
||||
.id = ConfigVariableID::UseRoundedWindowCorners,
|
||||
.name = "ui.window.use_rounded_corners"sv,
|
||||
.title = "Use rounded window corners"sv,
|
||||
.description = "Clip browser windows to rounded corners."sv,
|
||||
.default_value = true,
|
||||
.array_element_type = {},
|
||||
},
|
||||
} };
|
||||
|
||||
ReadonlySpan<ConfigVariableDefinition const> config_variable_definitions()
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ enum class ConfigVariableID : u8 {
|
|||
ShowWebContentProcessIDInTabTitle,
|
||||
ShowAdvancedDebugMenu,
|
||||
ContentBlockerListPaths,
|
||||
UseRoundedWindowCorners,
|
||||
|
||||
Count,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
#include <AK/JsonArray.h>
|
||||
#include <AK/Platform.h>
|
||||
#include <LibURL/Parser.h>
|
||||
#include <LibWebView/Application.h>
|
||||
#include <LibWebView/SearchEngine.h>
|
||||
|
|
@ -32,6 +33,16 @@ static StringView config_variable_type_to_string(JsonValue::Type type)
|
|||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
static bool should_show_config_variable([[maybe_unused]] ConfigVariableID id)
|
||||
{
|
||||
#if !defined(AK_OS_MACOS)
|
||||
if (id == ConfigVariableID::UseRoundedWindowCorners)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SettingsUI::register_interfaces()
|
||||
{
|
||||
register_interface("loadFeatures"sv, [this](auto const&) {
|
||||
|
|
@ -127,6 +138,9 @@ void SettingsUI::load_current_settings()
|
|||
|
||||
JsonArray config_variables;
|
||||
for (auto const& variable : config_variable_definitions()) {
|
||||
if (!should_show_config_variable(variable.id))
|
||||
continue;
|
||||
|
||||
JsonObject variable_object;
|
||||
variable_object.set("name"sv, variable.name);
|
||||
variable_object.set("title"sv, variable.title);
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
*/
|
||||
|
||||
#include <AK/HashMap.h>
|
||||
#include <AK/Platform.h>
|
||||
#include <AK/RefPtr.h>
|
||||
#include <AK/StdLibExtras.h>
|
||||
#include <AK/TypeCasts.h>
|
||||
|
|
@ -19,6 +20,9 @@
|
|||
#include <UI/Qt/BrowserWindow.h>
|
||||
#include <UI/Qt/ChromeStyle.h>
|
||||
#include <UI/Qt/Icon.h>
|
||||
#if defined(AK_OS_MACOS)
|
||||
# include <UI/Qt/MacWindow.h>
|
||||
#endif
|
||||
#include <UI/Qt/Menu.h>
|
||||
#include <UI/Qt/Settings.h>
|
||||
#include <UI/Qt/StringUtils.h>
|
||||
|
|
@ -55,6 +59,9 @@ namespace Ladybird {
|
|||
static constexpr auto AUDIO_STATE_BUTTON_POSITION = QTabBar::LeftSide;
|
||||
static constexpr auto TAB_CLOSE_BUTTON_POSITION = QTabBar::RightSide;
|
||||
static constexpr auto WINDOW_DRAG_REGION_PROPERTY = "LadybirdWindowDragRegion";
|
||||
#if defined(AK_OS_MACOS)
|
||||
static constexpr qreal WINDOW_CORNER_RADIUS = 12.0;
|
||||
#endif
|
||||
|
||||
static bool should_use_screen_signal_for_dpi_changes()
|
||||
{
|
||||
|
|
@ -227,6 +234,7 @@ BrowserWindow::BrowserWindow(Vector<URL::URL> const& initial_urls, IsPopupWindow
|
|||
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||
setWindowIcon(app_icon());
|
||||
qApp->installEventFilter(this);
|
||||
update_window_corners();
|
||||
|
||||
update_tabs_display();
|
||||
|
||||
|
|
@ -1229,6 +1237,7 @@ void BrowserWindow::clear_resize_cursor()
|
|||
void BrowserWindow::resizeEvent(QResizeEvent* event)
|
||||
{
|
||||
QWidget::resizeEvent(event);
|
||||
update_window_corners();
|
||||
|
||||
for_each_tab([&](auto& tab) {
|
||||
tab.view().set_window_size({ width(), height() });
|
||||
|
|
@ -1244,6 +1253,7 @@ void BrowserWindow::changeEvent(QEvent* event)
|
|||
} else if (event->type() == QEvent::WindowStateChange) {
|
||||
update_menu_bar_window_control_icons();
|
||||
m_tabs_container->update_window_button_icons();
|
||||
update_window_corners();
|
||||
|
||||
QWindowStateChangeEvent* stateChangeEvent = static_cast<QWindowStateChangeEvent*>(event);
|
||||
bool was_fullscreen = stateChangeEvent->oldState() & Qt::WindowFullScreen;
|
||||
|
|
@ -1260,6 +1270,26 @@ void BrowserWindow::changeEvent(QEvent* event)
|
|||
QWidget::changeEvent(event);
|
||||
}
|
||||
|
||||
void BrowserWindow::config_variable_changed(WebView::ConfigVariableID variable)
|
||||
{
|
||||
if (variable == WebView::ConfigVariableID::UseRoundedWindowCorners)
|
||||
update_window_corners();
|
||||
}
|
||||
|
||||
void BrowserWindow::update_window_corners()
|
||||
{
|
||||
auto should_use_rounded_corners = WebView::Application::settings().config_variable_as_bool(WebView::ConfigVariableID::UseRoundedWindowCorners);
|
||||
auto should_round_window = should_use_rounded_corners && !isMaximized() && !isFullScreen();
|
||||
|
||||
#if defined(AK_OS_MACOS)
|
||||
clearMask();
|
||||
set_rounded_window_corners(*this, should_round_window, WINDOW_CORNER_RADIUS);
|
||||
#else
|
||||
clearMask();
|
||||
(void)should_round_window;
|
||||
#endif
|
||||
}
|
||||
|
||||
void BrowserWindow::moveEvent(QMoveEvent* event)
|
||||
{
|
||||
QWidget::moveEvent(event);
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include <LibWeb/HTML/ActivateTab.h>
|
||||
#include <LibWeb/HTML/AudioPlayState.h>
|
||||
#include <LibWebView/Forward.h>
|
||||
#include <LibWebView/Settings.h>
|
||||
#include <UI/Qt/Tab.h>
|
||||
#include <UI/Qt/TabBar.h>
|
||||
|
||||
|
|
@ -80,7 +81,9 @@ private:
|
|||
bool m_debounce { false };
|
||||
};
|
||||
|
||||
class BrowserWindow : public QMainWindow {
|
||||
class BrowserWindow
|
||||
: public QMainWindow
|
||||
, public WebView::SettingsObserver {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
|
@ -151,6 +154,7 @@ private:
|
|||
virtual void moveEvent(QMoveEvent*) override;
|
||||
virtual void wheelEvent(QWheelEvent*) override;
|
||||
virtual void closeEvent(QCloseEvent*) override;
|
||||
virtual void config_variable_changed(WebView::ConfigVariableID) override;
|
||||
|
||||
Tab& create_new_tab(Web::HTML::ActivateTab, Tab& parent, Optional<u64> page_index);
|
||||
void initialize_tab(Tab*);
|
||||
|
|
@ -161,6 +165,7 @@ private:
|
|||
Optional<Qt::CursorShape> resize_cursor_for_edges(Qt::Edges) const;
|
||||
void update_resize_cursor(QPoint const&);
|
||||
void clear_resize_cursor();
|
||||
void update_window_corners();
|
||||
|
||||
template<typename Callback>
|
||||
void for_each_tab(Callback&& callback)
|
||||
|
|
|
|||
|
|
@ -25,6 +25,12 @@ target_sources(ladybird PRIVATE
|
|||
ladybird.qrc
|
||||
)
|
||||
target_link_libraries(ladybird PRIVATE Qt::Core Qt::Gui Qt::Widgets)
|
||||
|
||||
if (APPLE)
|
||||
target_sources(ladybird PRIVATE MacWindow.mm)
|
||||
target_link_libraries(ladybird PRIVATE "-framework Cocoa" "-framework QuartzCore")
|
||||
endif()
|
||||
|
||||
create_ladybird_bundle(ladybird)
|
||||
|
||||
if (WIN32)
|
||||
|
|
|
|||
15
UI/Qt/MacWindow.h
Normal file
15
UI/Qt/MacWindow.h
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* Copyright (c) 2026-present, the Ladybird developers.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
class QWidget;
|
||||
|
||||
namespace Ladybird {
|
||||
|
||||
void set_rounded_window_corners(QWidget&, bool enabled, double radius);
|
||||
|
||||
}
|
||||
35
UI/Qt/MacWindow.mm
Normal file
35
UI/Qt/MacWindow.mm
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (c) 2026-present, the Ladybird developers.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <UI/Qt/MacWindow.h>
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
|
||||
namespace Ladybird {
|
||||
|
||||
void set_rounded_window_corners(QWidget& widget, bool enabled, double radius)
|
||||
{
|
||||
auto* view = reinterpret_cast<NSView*>(widget.winId());
|
||||
if (!view)
|
||||
return;
|
||||
|
||||
auto* window = view.window;
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
auto* content_view = window.contentView;
|
||||
if (!content_view)
|
||||
return;
|
||||
|
||||
content_view.wantsLayer = YES;
|
||||
content_view.layer.cornerRadius = enabled ? radius : 0.0;
|
||||
content_view.layer.masksToBounds = enabled ? YES : NO;
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in a new issue