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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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).
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.