UI/Qt: Draw a border around frameless windows
When using client-side decorations, the window was a flat rectangle with no outline, so its edge disappeared against similarly colored backgrounds. Paint a 1px border in a new chrome window outline color and reserve a matching 1px contents margin so child widgets do not cover it. The outline color matches chrome_border() in dark mode, but is darker in light mode, since the window edge has to hold up against arbitrary backdrops behind the window rather than our own chrome surfaces. The border is skipped when the window is maximized or fullscreen, and on macOS, where frameless windows already get rounded corners and a native shadow.
This commit is contained in:
parent
8d4493a789
commit
b348f141d2
4 changed files with 52 additions and 0 deletions
|
|
@ -43,6 +43,7 @@
|
|||
#include <QMenuBar>
|
||||
#include <QMessageBox>
|
||||
#include <QMouseEvent>
|
||||
#include <QPainter>
|
||||
#include <QPlatformSurfaceEvent>
|
||||
#include <QPropertyAnimation>
|
||||
#include <QPushButton>
|
||||
|
|
@ -242,6 +243,7 @@ BrowserWindow::BrowserWindow(Vector<URL::URL> 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<QWindowStateChangeEvent*>(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);
|
||||
|
|
|
|||
|
|
@ -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<typename Callback>
|
||||
void for_each_tab(Callback&& callback)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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&);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue