Commit graph

51 commits

Author SHA1 Message Date
Andreas Kling
7b6e94a445 UI/Qt: Add tab hover previews
Show a delayed preview popup when hovering background tabs. Build the
thumbnail from the cached front or backup WebContent bitmap so chrome
does not need a fresh screenshot request or WebContent repaint on hover.

Tie the popup to the tab hover lifecycle and hide it on current-tab
hovers, tab presses, drags, layout changes, and tab strip exits.
2026-06-11 13:09:32 +02:00
Timothy Flynn
85c7620805 UI/Qt: Collapse hover-expanded vertical tabs after leaving window
When collapsed vertical tabs are expanded on hover, the collapse check
used QCursor::pos() against the vertical tabs rect. On some platforms,
after the cursor leaves the browser window entirely, that position can
remain at the last in-window coordinate, so the tabs stay expanded.
2026-06-04 22:16:16 +01:00
Timothy Flynn
80554dc914 LibWebView+UI/Qt: Move the vertical tab width to LibWebView settings
Let's store this alongside all other vertical tab settings.
2026-06-03 18:14:12 -04:00
Timothy Flynn
1d36fc2997 UI/Qt: Let fullscreen content occupy the whole window
Hide fullscreen chrome at the TabWidget level instead of hiding the
current tab's toolbar child directly. This lets the toolbar container
and reserved verticaltabs space stop contributing to layout while
fullscreen content is shown.

Also keep the exit fullscreen button above native web content on macOS
and center it using the fullscreen screen geometry rather than a
potentially stale parent widget size.
2026-06-03 13:39:11 -04:00
Timothy Flynn
e18cd253f0 UI/Qt: Add an advanced setting to enable server-side decorations
This adds a setting to disable our custom window decorations and let the
system's window server paint the window instead.
2026-06-03 17:30:26 +01:00
Andreas Kling
530c71a2c1 UI/Qt: Put vertical tabs below bookmarks bar
Anchor the vertical tab sidebar to the full toolbar container height so
it starts below the bookmarks bar when that bar is visible. This keeps
the navigation toolbar and bookmarks bar unified, with the separator at
the content edge.

Update the sidebar geometry whenever the toolbar container resizes so
toggling the bookmarks bar moves the vertical tab chrome immediately.
2026-06-03 12:10:39 +02:00
Andreas Kling
78887566f1 UI/Qt: Align horizontal New Tab spacing with tabs
Bring horizontal tab cards one pixel closer together and make the
horizontal New Tab button a square with the same height as tabs.
Remove the layout gap between the tab bar and New Tab button so the
painted card gap matches the gap between adjacent tabs.
2026-06-03 02:53:37 +02:00
Andreas Kling
15eec69341 UI/Qt: Use tab card styling for horizontal New Tab
Use the same icon-only card-shaped New Tab button in horizontal tab mode
that collapsed vertical tabs use. This keeps the New Tab affordance in
the same visual language as the tab cards instead of using a standard
flat tool button.
2026-06-03 02:53:37 +02:00
Andreas Kling
e783e99861 UI/Qt: Tighten horizontal tab card spacing
Bring horizontal tab card visuals one pixel closer together by reducing
the painted card inset by half a pixel on each side. Keep vertical tab
geometry unchanged.
2026-06-03 02:53:37 +02:00
Andreas Kling
a1bb958419 UI/Qt: Remove obsolete vertical toolbar layout branch
Vertical tab mode always keeps the toolbar in the full-width chrome row.
Remove the older split path that could place the toolbar in the page
column, and simplify the window-control visibility checks around that
single layout model.
2026-06-03 02:53:37 +02:00
Andreas Kling
456d94cb5b UI/Qt: Align vertical tab chrome across platforms
Use the full-width toolbar layout for vertical tabs on every platform.
Also use the same collapsed vertical tabs width everywhere so collapsed
tab shapes remain square.
2026-06-03 02:53:37 +02:00
Andreas Kling
f03b675c2a UI/Qt: Keep vertical tab overlays native only on macOS
Make the vertical tab overlay column and resize handle native only on
macOS. This preserves stacking over native web views there without
breaking input routing on non-macOS platforms.
2026-06-03 02:53:37 +02:00
Andreas Kling
a310091402 UI/Qt: Avoid native churn while resizing chrome
Do not clear the Qt window mask from the non-macOS corner update path.
The custom rounded-corner implementation is macOS-only, so the Linux
resize path should not touch native mask state on every resize event.

Also make dynamic property updates idempotent for tab chrome widgets.
Vertical tab resize and hover updates now only repolish when a property
actually changes, and avoid reapplying unchanged New Tab button text,
style, and size.
2026-06-03 02:53:37 +02:00
Andreas Kling
be2cbc0f07 UI/Qt: Simplify browser chrome layout
Remove dead vertical-tab separator and sidebar traffic-light paths from
the unified chrome layout. Keep the toolbar stack owned by TabWidget so
layout changes no longer move each tab toolbar in and out of its page.
Share the vertical New Tab button setup between initial layout and
hover expansion, and keep window-control sizing helpers private.
2026-06-03 02:53:37 +02:00
Andreas Kling
4f314b0aa0 UI/Qt: Unify browser chrome layout
Treat the toolbar, tab strip, and vertical sidebar as one browser
chrome surface. Add an explicit layout policy for platform window
controls and sidebar widths. This lets macOS use left-side traffic
lights while other platforms keep right-side custom controls.

Keep the macOS toolbar stable in vertical-tabs mode. Traffic lights and
navigation controls stay in the top row, and the sidebar sits below it.
Draw chrome/content separators explicitly so the content edge remains
clear without adding seams inside the chrome surface.

Retune tab, toolbar, and omnibox styling for the unified chrome. Tabs
use card-like selected states, quiet inactive states, and matching
horizontal and vertical geometry.

Make hover-expanded vertical tabs draw as a chrome overlay so the web
content does not relayout. Keep the overlay above native web views and
route macOS window drags through AppKit events for reliable dragging
from custom chrome.
2026-06-03 02:53:37 +02:00
Timothy Flynn
a6e67d58ea UI/Qt: Draw tab close and audio state icons on collapsed tabs
We previously just hid this icons as a future TODO. We now draw a tab
close icon on hover in the upper-left corner of the tab, and an audio
state icon when audio is playing on the lower-right corner. Just like
expanded tabs, the audio state icon is interactable and may be used to
mute the page.
2026-06-02 21:55:14 +02:00
Timothy Flynn
caf6e526b6 UI/Qt: Make the new tab button consistent for all vertical tab modes
The new tab button would jump around a bit when switching between
collapsed and expanded vertical tabs. This is easier to notice when
expand-on-hover is enabled.

We now:
* Consistently draw the separator above the new tab button.
* Draw the new tab icon with a consistent icon size and placement.
2026-06-02 07:57:05 -04:00
Timothy Flynn
3b46b0bf09 UI/Qt: Add a setting to expand collapsed vertical tabs on hover
This as a pesudo third mode to vertical tabs. Now when the vertical tabs
are collapsed, users can enable a setting that will expand the vertical
tab area on hover. Unlike full expansion, the hovered vertical tab area
will cover the web content area to avoid pushing the web content area
around.
2026-06-02 07:57:05 -04:00
Timothy Flynn
62e514e8ed UI/Qt: Restore horizontal tab widths after turning off vertical tabs
After commit a7e68ef, When switching from vertical tabs to horizontal
tabs, the QTabBar could keep its stale narrow vertical width. This made
horizontal tabs render too small and, with multiple tabs, caused scroll
buttons to appear even though there was enough room in the tab strip.

Make the horizontal tab bar width explicit from the same available-width
calculation used for tab size hints.
2026-06-01 14:35:44 +02:00
Timothy Flynn
fde052136b UI/Qt: Remove no longer needed new tab polish/unpolish invocations
These were needed before commit 24e767a in order to propagate dynamic
property changes to Qt's CSS engine (for the verticalTabsExpanded
property). We now handle this in C++, so these calls aren't needed.
2026-06-01 14:35:44 +02:00
Timothy Flynn
188eb09d2e UI/Qt: Remove redundant layout clearing invocations
These layouts were cleared just before entering these functions.
2026-06-01 14:35:44 +02:00
Timothy Flynn
374dedf398 UI/Qt: Remove redundant TabWidget visibility updates
This is handled by the call to update_tab_chrome_visibility just below.
2026-06-01 14:35:44 +02:00
Timothy Flynn
e463d92bc0 UI/Qt: Remove unnecessary update to toolbar buttons for vertical tabs
Commits a7e68ef and 24e767a shuffled things around in that they ended up
performing manual updates to the toolbar buttons in order to update the
collapse/expand vertical tabs button. However, this isn't needed - that
button's state is totally controlled by LibWebView already (through the
WebView::Action infrastructure).
2026-06-01 14:35:44 +02:00
Andreas Kling
587abbcc6f UI/Qt: Give expanded vertical tabs more width
Reduce the horizontal margins and shape inset used by expanded vertical
tabs so the sidebar content uses more of the available space. Keep the
collapsed sidebar margin unchanged so icon-only tabs remain centered.

Share the expanded-tab geometry through helpers so painting, button
placement, and the new-tab button stay in sync.
2026-06-01 12:13:47 +02:00
Andreas Kling
3ea52a8447 UI/Qt: Avoid repaint loop in vertical tab bar
Move tab button geometry updates out of TabBar::paintEvent(). That path
mutates child widgets, and Qt schedules more updates for those buttons.
During painting, that can keep the tab bar dirty and churn CPU.

Update buttons from layout, hover, and current-tab changes instead. Keep
hover bookkeeping in one helper, and skip widget mutators when they are
already in the desired state.
2026-06-01 12:13:47 +02:00
Andreas Kling
e0486ffba9 UI/Qt: Match new tab button font to tabs
Use the tab bar font for the Qt new-tab button so expanded
vertical tabs do not inherit smaller tool-button text on macOS.
2026-06-01 12:13:47 +02:00
Andreas Kling
044fc0c519 UI/Qt: Cache fallback tab icon
TabBar::paintEvent() drew a fresh globe icon for every tab without a
favicon. Creating a chrome icon renders several pixmaps for multiple
states and device pixel ratios, which is far too expensive for a paint
hot path.

Cache the fallback tab icon on TabBar and refresh it alongside the other
chrome icons when the palette changes.
2026-06-01 10:00:19 +02:00
Andreas Kling
24e767a06e UI/Qt: Polish vertical tab sidebar chrome
Refine vertical tab sidebar styling. Let inactive tabs sit on chrome.
Keep close buttons quiet. Align the New Tab row with tab rows.

Persist the expanded sidebar width and keep resizing bounded. Put the
resize hit area over the divider. Keep the collapsed rail fixed-width.
Avoid explicit mouse grabs while dragging.

Paint subtle sidebar dividers. Move the expand/collapse control into
the navigation toolbar. Tune the fallback globe and vertical-tabs icons.
2026-06-01 02:05:44 +02:00
Andreas Kling
a7e68ef1ae UI/Qt: Integrate window controls into vertical tab toolbar
Move custom window controls into the navigation toolbar while vertical
tabs are enabled. Remove the separate top row that only held them.

Mark empty toolbar space as draggable so the unified row acts like the
titlebar. Keep horizontal tab mode on the existing tab strip controls.
2026-06-01 02:05:44 +02:00
Timothy Flynn
a7b9ba5711 UI/Qt: Use a globe in place of missing tab favicons
Commit 16e218b7f6 removed the fallback
favicon in order to stop showing the Ladybird logo on these tabs. But
with collapsed vertical tabs, we would then render nothing. We now use
the already-existing globe chrome icon, which is tweaked here to look a
bit better when painted larger than it was previously.
2026-05-31 21:24:57 +02:00
Timothy Flynn
a7f1ed7a10 UI/Qt: Begin implementing vertical tab support
This implements an initial version of vertical tabs for the Qt UI. Users
may enable vertical tabs in about:settings. When enabled, a button is
added to the toolbar to expand/collapse the vertical tabs.

There is plenty more to do here. We will want to support expanding on
hover, drawing the close tab / audio button indicators on collapsed
vertical tabs, positioning the vetical tab bar, etc.
2026-05-31 21:24:57 +02:00
Andreas Kling
effedec392 UI/Qt: Refine compact chrome appearance
Normalize generated chrome icon weights and alignment, tune dark and
light chrome surface layering, and move the compact palette toward a
quieter neutral treatment. Keep the compact tab strip and toolbar
heights while making the toolbar, tab surfaces, omnibox, and navigation
cluster feel more balanced.

Use tonal dark-mode seams instead of bright separator lines, quiet the
resting omnibox border, and keep background tabs full-strength while
using shape and layering to distinguish the selected tab.
2026-05-31 19:20:59 +02:00
Andreas Kling
1516560bc6 UI/Qt: Tighten browser chrome spacing
Reduce the Qt tab strip, navigation toolbar, and location edit heights
so the combined chrome takes less vertical space while the toolbar
buttons keep comfortable 36 px targets. Keep glyph sizes unchanged and
use inset toolbar button styling so the painted hover surfaces feel
lighter than the clickable area.
2026-05-31 19:20:59 +02:00
Timothy Flynn
42c9fcf88f UI/Qt: Paint the dragged tab preview with some transparency
Makes it a bit easier to see where the tab is being dragged to.
2026-05-29 10:04:25 -04:00
Timothy Flynn
af410da20c UI/Qt: Paint the drag preview for all tabs
We attempted to paint a preview of the dragged tab, but this only worked
for the first tab. For other tabs, we were passing a negative offset to
QWidget::render, causing the preview to render transparently.
2026-05-29 10:04:25 -04:00
Timothy Flynn
763d194002 UI/Qt: Restore ability to close tabs with the middle mouse button
We were trying to handle this in TabWidget::event, but this mouse event
is now delivered to the child TabBar, where the event is accepted and
thus not propagated further.
2026-05-29 10:04:25 -04:00
Timothy Flynn
1677cea482 UI/Qt: Slightly enlarge a few toolbar icons
Render the new tab, close tab, and hamburger icons a bit larger. And
slightly separate the 3 horizontal hamburger lines.
2026-05-28 00:53:35 +02:00
Andreas Kling
576d46e6fa UI/Qt: Balance tab strip window control padding
Use matching top and right padding around the tab strip window controls
when the menu bar is hidden, while keeping the existing left spacing for
tabs and the resize edge.
2026-05-27 22:05:54 +02:00
Andreas Kling
770829a855 UI/Qt: Put window controls in visible menu bar
Add a menu bar corner widget for the frameless window controls when
the Qt menu bar is visible. Hide the tab strip controls in that mode
so the buttons stay at the top-right edge of the window, and remove
the separator below the menu bar so the chrome reads as one surface.

Use compact menu bar controls and keep the right padding tight so the
buttons align with the edge without changing the hidden-menu layout.
2026-05-27 22:05:54 +02:00
Andreas Kling
1c8223bffa UI/Qt: Add a shared window control button
Add a shared WindowControlButton for the frameless window controls. It
clears the pressed visual state when the pointer leaves during a press,
and restores it on re-entry.

Also reset transient button state around double-clicks so pressed
styling cannot get stuck after the window state changes.
2026-05-27 22:05:54 +02:00
Andreas Kling
14ac01b0ce UI/Qt: Refine chrome layout spacing
Keep active and hovered tabs on the same geometry while tightening the
surrounding chrome rhythm. Reduce tab and toolbar padding, shorten the
navigation toolbar and omnibox, center the new tab button, and enlarge
tab close buttons to match the refined tab sizing.
2026-05-26 15:20:59 +02:00
Tim Ledbetter
ee3960e425 UI/Qt: Detach dragged tabs dropped outside any tab bar to a new window
Previously, a tab would only detach into a new window when dropped
outside the source window entirely. Dropping a tab onto the content
area of any browser window would instead silently move it to the end of
that window's tab bar.

TabWidget now rejects tab drag events outside its tab bar row, and the
detach condition checks the tab bar row bounds rather than the full
window geometry. This means dropping a tab anywhere that is not a tab
bar row opens a new window at the cursor position.
2026-05-26 09:07:57 +02:00
Andreas Kling
3adeed9581 UI/Qt: Polish browser chrome appearance
Refine the material colors, tab integration, toolbar spacing, and
custom glyphs used by the Qt browser chrome. Keep the visual density
compact while making the controls feel clearer and less toolkit-like.
Mark the window opaque and show resize cursors for frameless chrome.
2026-05-26 01:18:51 +02:00
Andreas Kling
6aeec196f0 UI/Qt: Support dragging tabs between windows
Allow custom Qt tabs to be reordered, detached, and reparented to
other browser windows while preserving the existing tab state. Draw a
full-tab drag preview and keep tab drags from being interpreted as
frameless window moves.
2026-05-26 01:18:51 +02:00
Andreas Kling
328d89f3c1 UI/Qt: Draw custom browser window chrome
Add shared chrome styling helpers and use them to paint the Linux
browser tab strip and surrounding toolbar widgets. Make the browser
window frameless on Qt so the tabs, toolbar, and window controls can
share one integrated chrome surface.
2026-05-26 01:18:51 +02:00
Andreas Kling
b6b13e3bbd UI/Qt: Left-align browser tab titles
Use a small proxy style for the tab label control so QTabBar still
owns tab layout, scrolling, buttons, dragging, and native tab shapes.
Only the text draw flags change to use left alignment.
2026-05-20 09:37:44 +02:00
Timothy Flynn
0a3e2196c9 UI/Qt: Store the TabWidget parent directly on TabBar
The parent owner of the TabBar changes as it is added to layout objects
within other widgets. So the parent we set at the beginning is no longer
the parent when we right-click on a tab. We now just store the TabWidget
directly.
2026-03-22 18:36:36 -04:00
Timothy Flynn
7e3bb9d984 UI/Qt: Replace QTabWidget with a custom TabWidget composition
QTabWidget's built-in tab bar management made it difficult to properly
position the new tab button, and caused visual artifacts with the
separator line across themes.

Replace QTabWidget with a custom TabWidget that places a QTabBar
alongside an explicit new tab button. This us gives full control over
the tab bar row layout.
2026-03-18 18:39:53 -04:00
Timothy Flynn
a87c264088 UI/Qt: Add a couple of missing includes
These are currently being transitively included. This will no longer be
the case in a future patch.
2025-04-02 08:52:45 -04:00
Timothy Flynn
85b424464a AK+Everywhere: Rename verify_cast to as
Follow-up to fc20e61e72.
2025-01-21 11:34:06 -05:00