diff --git a/UI/Qt/BrowserWindow.cpp b/UI/Qt/BrowserWindow.cpp index 485d0d112a..5cd33dd7d4 100644 --- a/UI/Qt/BrowserWindow.cpp +++ b/UI/Qt/BrowserWindow.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -242,6 +243,7 @@ BrowserWindow::BrowserWindow(Vector const& initial_urls, IsPopupWindow setWindowIcon(app_icon()); qApp->installEventFilter(this); update_window_corners(); + update_window_border(); update_tabs_display(); @@ -979,6 +981,7 @@ void BrowserWindow::update_window_decoration_state() } update_menu_bar_visibility(); + update_window_border(); } void BrowserWindow::toggle_window_maximized() @@ -1317,6 +1320,7 @@ void BrowserWindow::changeEvent(QEvent* event) update_menu_bar_window_control_icons(); m_tabs_container->update_window_button_icons(); update_window_corners(); + update_window_border(); QWindowStateChangeEvent* stateChangeEvent = static_cast(event); bool was_fullscreen = stateChangeEvent->oldState() & Qt::WindowFullScreen; @@ -1357,6 +1361,39 @@ void BrowserWindow::update_window_corners() #endif } +bool BrowserWindow::should_draw_window_border() const +{ +#if defined(AK_OS_MACOS) + // macOS frameless windows already get rounded corners and a native shadow, so a painted border would clash. + return false; +#else + return windowFlags().testFlag(Qt::FramelessWindowHint) && !isFullScreen() && !isMaximized(); +#endif +} + +void BrowserWindow::update_window_border() +{ + auto border_width = should_draw_window_border() ? 1 : 0; + setContentsMargins(border_width, border_width, border_width, border_width); + update(); +} + +void BrowserWindow::paintEvent(QPaintEvent* event) +{ + QMainWindow::paintEvent(event); + + if (!should_draw_window_border()) + return; + + QPainter painter(this); + auto color = ChromeStyle::chrome_window_outline(palette()); + auto frame = rect(); + painter.fillRect(QRect(frame.left(), frame.top(), frame.width(), 1), color); + painter.fillRect(QRect(frame.left(), frame.bottom(), frame.width(), 1), color); + painter.fillRect(QRect(frame.left(), frame.top(), 1, frame.height()), color); + painter.fillRect(QRect(frame.right(), frame.top(), 1, frame.height()), color); +} + void BrowserWindow::moveEvent(QMoveEvent* event) { QWidget::moveEvent(event); diff --git a/UI/Qt/BrowserWindow.h b/UI/Qt/BrowserWindow.h index 1b88b37be0..0785016be2 100644 --- a/UI/Qt/BrowserWindow.h +++ b/UI/Qt/BrowserWindow.h @@ -153,6 +153,7 @@ private: virtual void resizeEvent(QResizeEvent*) override; virtual void changeEvent(QEvent* event) override; virtual void moveEvent(QMoveEvent*) override; + virtual void paintEvent(QPaintEvent*) override; virtual void wheelEvent(QWheelEvent*) override; virtual void closeEvent(QCloseEvent*) override; @@ -170,6 +171,8 @@ private: void update_resize_cursor(QPoint const&); void clear_resize_cursor(); void update_window_corners(); + bool should_draw_window_border() const; + void update_window_border(); template void for_each_tab(Callback&& callback) diff --git a/UI/Qt/ChromeStyle.cpp b/UI/Qt/ChromeStyle.cpp index 297e1fd3a5..fc8bc31baf 100644 --- a/UI/Qt/ChromeStyle.cpp +++ b/UI/Qt/ChromeStyle.cpp @@ -203,6 +203,17 @@ QColor chrome_border(QPalette const& palette) return mix(dark ? chrome_surface(palette) : chrome_background(palette), material_color_anchors(dark).border, 0.22); } +QColor chrome_window_outline(QPalette const& palette) +{ + auto dark = is_dark(palette); + if (dark) + return chrome_border(palette); + + // The window outline has to hold up against arbitrary backdrops behind the window, not just our own chrome + // surfaces, so in light mode it is mixed further toward the border anchor than chrome_border(). + return mix(chrome_background(palette), material_color_anchors(false).border, 0.5); +} + QColor chrome_accent(QPalette const& palette) { return palette.color(QPalette::Highlight); diff --git a/UI/Qt/ChromeStyle.h b/UI/Qt/ChromeStyle.h index 6245a4a280..aeac46745e 100644 --- a/UI/Qt/ChromeStyle.h +++ b/UI/Qt/ChromeStyle.h @@ -25,6 +25,7 @@ QColor chrome_control_border(QPalette const&); QColor chrome_active_tab_surface_top(QPalette const&); QColor chrome_active_tab_surface_bottom(QPalette const&); QColor chrome_border(QPalette const&); +QColor chrome_window_outline(QPalette const&); QColor chrome_accent(QPalette const&); QColor chrome_muted_text(QPalette const&);