While typing in the location bar, intermediate autocomplete updates
caused the highlighted suggestion to flicker.
These updates trigger on each keystroke and lead to unnecessary
selection changes.
Skip intermediate popup updates while it is visible and rely on final
results to update both suggestions and selection atomically.
Show web URLs without their scheme, a leading host www., or the
root slash while the location field is not being edited. Restore the
fully serialized URL while editing so the original scheme is preserved,
but keep mouse focus stable until release so clicks target the visible
text.
Keep the domain emphasis for shortened Qt location text by deriving the
highlight ranges from the serialized URL and remapping them to the
visible display form. Special URLs like about, data, and file remain
unchanged. Add LibWebView coverage for the shared display helper used by
both UI frontends.
Send hidden and visible system visibility updates from explicit tab
switch paths instead of relying only on widget show and hide events. Tab
containers can keep inactive web views mapped, which leaves documents
visible from WebContent's perspective and lets animated images keep
running in background tabs.
Use AppKit window occlusion state rather than the app-wide active tab.
That keeps still-visible background windows in the visible document
state. Avoid resending duplicate visibility updates from
ViewImplementation so existing widget visibility notifications remain
harmless.
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.
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.
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.
Tabs opened from links on AppKit can be created before their URL is
loaded. That left background open-url tabs with the location field as
their stored responder, so switching to them later restored address-bar
focus instead of web content focus.
Track each tab's preferred responder, restore it when AppKit makes
the tab key, and mark page-backed open-url tabs to prefer the web view.
Blank new-tab pages still keep the location field focused.
Render AutocompleteSuggestion rows with section headers, favicons,
titles, and secondary text in the child-window popup instead of just
plain strings.
Move the AppKit popup and inline completion onto the shared suggestion
model, and share the base64 PNG decoding helper with the application
menu icon loading path.
Replace the AppKit popover because it becomes key and steals focus from
the location field while suggestions are visible. Use a borderless
child window anchored to the toolbar item instead, and dismiss it on
resize or focus changes so the browser chrome stays predictable.
Teach LibWebView autocomplete to query HistoryStore before falling back
to remote engines and move the wiring out of the AppKit frontend.
Refine matching so scheme and www. boilerplate do not dominate results,
short title and substring queries stay quiet, and history tracing can
explain what the ranking code is doing.
We initially create the search field with no frame or size constraints.
The causes AppKit to log verbose warnings at start up. Here, we set an
intrinsic size initially, which becomes overridden once the window has
an actual size.
When an element is fullscreened, we now hide the application menu and
location bar. The user can hover over the top of the window to make
them show. When fullscreen is requested for the application directly
from the UI, we do not hide the location bar. This matches Safari's
behavior.
When the user focuses the address bar and presses Escape, the original
URL is now restored. Previously, the address bar would show whatever
text the user had typed, or be empty if they had cleared it.
Clicking outside the address bar keeps the typed text (matching
Chrome/Firefox behavior) — only Escape restores the original URL.
Fixes https://github.com/LadybirdBrowser/ladybird/issues/7264
When a new tab is created, the location bar should automatically
receive keyboard focus so users can immediately start typing a URL.
However, the onURLChange callback was stealing focus back to the
web view when loading the new tab page.
This fix:
1. Calls focusLocationToolbarItem when activating a new tab
2. Prevents onURLChange from stealing focus when loading the new
tab page URL
Fixes#1512
When trying to build Ladybird on macOS 14.3, it fails with the error:
```
No visible @interface for 'NSToolbar' declares the selector
'setAllowsDisplayModeCustomization:' (clang arc_may_not_respond)
```
This is caused by macOS < 15 not having the @interface definition for
in NSToolbar for setAllowsUserCustomization:(BOOL).
By dynamically calling the method, we can avoid the error altogether.
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.
On macOS Tahoe, it is now recommended to show menu item icons. We use
system symbols for this now. Symbols do not have constant variable names
and must be found via the SF Symbols app.
The symbols chosen here were to match Safari as close as possible.
By migrating the debug menu to LibWebView, the AppKit and Qt UIs are now
in sync - the AppKit UI was previously missing some actions.
Further, this inadvertently fixes bugs around applying debug settings to
new web views, especially across site-isolated processes. We were
previously not applying settings appropriately; this now "just works" in
the LibWebView infra.
This migrates all duplicated context menus from the UIs to LibWebView.
The context menu actions are now largely handled directly in LibWebView,
with some UI-specific callbacks added to display e.g. confirmation
dialogs.
Actions that only ever apply to a specific web view are stored on the
ViewImplementation itself. Actions that need to be dynamically applied
to the active web view are stored on the Application.
When we manually enter a new URL and hit enter, the web view gets
focused. But when the URL changes for other reasons, such as starting
Ladybird with a URL argument, the location field was still focused.
This is to prepare for custom search engines. If we use AK::format, it
would be trivial for a user (or bad actor) to come up with a template
search engine URL that ultimately crashes the browser due to internal
assertions in AK::format. For example:
https://example.com/crash={1}
Rather than coming up with a complicated pre-format validator, let's
just not use AK::format. Custom URLs will signify their template query
parameters with "%s". So we can do the same with our built-in engines.
When it comes time to format the URL, we will do a simple string
replacement.
This removes the old autoplay allowlist file in favor of the new site
setting. We still support the command-line flag to enable autoplay
globally, as this is needed for WPT.
This adds a WebView::Settings class to own persistent browser settings.
In this first pass, it now owns the new tab page URL and search engine
settings.
For simplicitly, we currently use a JSON format for these settings. They
are stored alongside the cookie database. As of this commit, the saved
JSON will have the form:
{
"newTabPageURL": "about:blank",
"searchEngine": {
"name": "Google"
}
}
(The search engine is an object to allow room for a future patch to
implement custom search engine URLs.)
For Qt, this replaces the management of these particular settings in the
Qt settings UI. We will have an internal browser page to control these
settings instead. In the future, we will want to port all settings to
this new class. We will also want to allow UI-specific settings (such as
whether the hamburger menu is displayed in Qt).