After web content has focus on macOS, its native QRhiWidget can
remain the AppKit first responder even after Qt focuses the location
edit.
Make the top-level Qt content view first responder before focusing the
location edit so keyboard input returns to chrome.
Open the autocomplete popup when the location editor is focused
through the browser action, such as Cmd+L. Keep the selected URL text
intact by skipping inline completion for that explicit popup request.
Position the native popup again after its first show so Qt has realized
the tooltip window before the final placement, avoiding the brief macOS
Y-coordinate jump.
Show native history menus when users right-click or long-press
the back and forward toolbar buttons. Populate entries from the
UI-process session history mirror, using saved history titles and
favicons when available and falling back to the URL and globe icon
otherwise.
Share the Qt base64 PNG icon helper so bookmark menus and navigation
history menus render stored favicons consistently.
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.
Add fixed empty toolbar gaps on both sides of the location editor. This
slightly reduces the omnibox width and leaves reliable toolbar chrome
space next to it for window dragging.
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.
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).
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.
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.
Show active page zoom as a muted pill inside the right side of the
location edit whenever zoom differs from 100%. Keep it next to the
bookmark action and reserve text margin space so the URL cannot render
under the controls.
Clicking the pill activates the existing reset zoom action, returning
the page to 100% and hiding the indicator again.
Stop mirroring the tab favicon and loading spinner inside the omnibox.
The tab already owns that state, so the leading omnibox control now
reflects the action or warning relevant to the field.
HTTP pages show a compact Not secure pill, edited URL-like input shows
the globe, and edited search input shows the search icon. Current
non-HTTP pages leave the leading edge quiet so ordinary navigation does
not look like a security status surface.
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.
Draw the remaining Qt chrome icons through the existing generated icon
path instead of loading TinyVG resources. Add generated folder and
chevron icons for menus, the bookmarks bar, and find-in-page controls,
and use the generated globe icon for bookmarks without favicons.
Remove the Qt TinyVG icon engine and drop the unused TVG resources from
the Qt resource file.
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.
The browser process forwards the maximum frame rate to WebContent, but
the compositor process had no copy of that display timing metadata or
the display identity needed by compositor-local vsync.
Add one compositor control IPC message carrying the optional display ID
and refresh rate together, and store both values on each compositor
context.
Let application actions opt out of icon creation when created for
menus. Use that path for browser menus, tab context menus, and
WebView-backed popup menus.
Keep icon creation for toolbar and bookmarks bar actions, where the
same helper still provides visible button icons. Remove the icon setup
that is now only used by menu actions, and shrink popup menu item
padding now that there is no icon column.
The bookmarks bar sticks out a bit too much in its own container with
its own background color. This adds a common container for both bars
so that we can apply the background color gradient to that common
container. This naturally handles showing/hiding the bookmarks bar
gracefully.
This is never referenced outside the constructor; we don't need to store
a pointer to it. (I had accidentally removed it in a subsequent commit,
then realized we didn't need it anyways).
Track whether WebContent still needs a beforeunload check and let the
frontends immediately remove a tab or window when no prompt can be
shown. WebContent still receives the close request so pagehide, unload,
and cleanup steps can run.
When the visible view is removed immediately, keep detached ownership of
the WebContent page until it reports that the top-level traversable
closed. If no acknowledgement arrives, release detached ownership and
ask ProcessManager to shut down the unused WebContent process.
Keep late about:newtab load notifications from clearing hidden location
text after the user has started typing. Let LocationEdit own cursor
placement for normal URL display so load-start updates do not disturb
inline autocomplete selection.
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.
Refresh Qt chrome palettes from the current color scheme when the
application palette changes. Recompute autocomplete and location field
colors and repaint WebContent immediately so theme changes do not
require another interaction or restart.
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.
Register debug.process.show_web_content_process_id and use it to append
the active WebContent process ID to tab titles and tab tooltips in the
Qt, Gtk, and AppKit frontends.
Keep the stored page title unchanged so toggling the preference can
refresh each tab without waiting for a new title update.
This factory is only used by the UI. An upcoming commit will make it
depend on LibFileSystem. LibWeb currently does not link LibFileSystem,
and doing so would push LibWeb in the wrong direction (we should be
doing less file IO in LibWeb, not more).
Move keyboard focus to the web view when the user commits the
location field. Relying on URL-change callbacks is unreliable because
ViewImplementation::load() stores the requested URL before WebContent
reports it, so same-URL reports are suppressed before frontends can
perform their focus handoff.
Keep the new-tab page behavior unchanged: creating a blank tab still
focuses the location field until the user starts a navigation.
Show visible tab icons as loading while the focused location field
keeps its existing page-level loading state. Cache the favicon under the
spinner so each tab restores its page icon when loading finishes.
Reuse the Qt spinner drawing for the location field and tab strip, and
draw the AppKit spinner into the attributed tab title.
Use the leading icon in the location field as a contextual page
indicator. While a page is loading, the field shows an indeterminate
activity indicator. Once loading finishes, it shows the page favicon
when available and falls back to the generic page icon where the toolkit
has one.
Keep the GTK implementation aligned with the other frontends by using
that slot only for loading and favicon state, without a separate
security icon.
This keeps single-tab windows from losing all visual feedback when the
tab bar is hidden, without adding a fake progress bar.
Previously, if search was disabled, entering non-URL text would just
silently drop the search query (and on Qt, we would reload the current
URL). We now detect that the query did not result in a navigation and
load an error page instead, which directs the user to enable search.
The HamburgerMenu subclass overrode showEvent() to reposition the menu
using move() after QMenu::popup() had already shown it. On the first
open, rect().width() could return a stale value, causing the menu to
appear detached from the button and truncated to a single item. The
move() call also bypassed Qt's screen boundary adjustments.
Instead, we can replace the HamburgerMenu with a normal QMenu, and use a
custom HamburgerButton class for the menu's tool button. In this class,
we override mousePressEvent() to call popup() with the correct right-
aligned position before the menu is shown. This lets Qt manage sizing
and screen boundaries correctly.
This adds the following features to the Qt UI:
- An "exit fullscreen" button that displays when entering fullscreen
This will disappear after a certain amount of time. Moving the
cursor to the top of the screen will make it reappear.
- Switching tabs exits fullscreen
The look and feel of this is preliminary and should be expanded upon
in the future.
These IPC methods should be expanded in the future to allow WebContent
to specify what UI elements should be kept/removed, for example, the
navigation UI.
Clipboard handling largely has nothing to do with the individual web
views. Rather, we interact with the system clipboard at the application
level. So let's move these implementations to the Application.
This lets us avoid each UI needing to handle link clicks directly, and
lets actions stored in LibWebView avoid awkwardly going through the link
click callbacks to open URLs.