Passing the browser command line and executable path to every WebContent
process just in case we load about:version always felt a bit weird. We
now use the WebUI framework to load this information on demand.
In commit b9c6263408, I had forgotten we
had this wrapper script to handle the eval magic for us. We just need
to forward the --clang-only argument to the underlying python script.
Add the complete browser UI:
- BrowserWindow: AdwHeaderBar with navigation, tab management via
AdwTabView/AdwTabBar, find-in-page, fullscreen, zoom, D-Bus
single-instance with open/activate handlers
- Tab: WebContentView lifecycle, ViewImplementation callbacks for
title, URL, favicon, cursor, tooltips, dialogs, window management
- LadybirdBrowserWindow: GtkBuilder template widget with toolbar,
tab bar, find bar, devtools banner, and hamburger menu
- LadybirdLocationEntry: URL entry with autocomplete, domain
highlighting, and security icon
- Menu: GAction-based context menus and application menu with
keyboard accelerators
- Dialogs: JS alert/confirm/prompt (AdwAlertDialog), color picker,
file picker, select dropdown, download save dialog, toast
- GtkBuilder .ui resources for browser window, location entry
completions, and list popovers
Updates Application and main.cpp to create browser windows and
handle D-Bus activation from remote instances.
Add the core infrastructure for the GTK frontend:
- EventLoopImplementationGtk: GLib main loop integration with
Core::EventLoop, timers, notifiers, and signal handling
- GObjectPtr RAII wrapper for GObject lifecycle management
- Application subclass with AdwApplication and D-Bus registration
- Minimal main.cpp entry point
The application starts and runs the event loop but does not yet
open any windows.
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.
Restore the active tab's remembered focus widget when switching tabs.
If the tab has no remembered focused child, fall back to the web
view so keyboard scrolling works immediately in tabs opened from
links.
This keeps the existing new-tab location bar behavior while making
background-opened pages respond to keyboard inputs as soon as they
are activated.
Synthesize an extra AutocompleteSuggestion at the top of the Search
Suggestions section whenever there is a configured search engine and
the typed query is not URL-shaped.
Use the query as the row's primary text, carry a "Search with <engine>"
subtitle, and render that subtitle in the AppKit and Qt popups so the
explicit search fallback stays visible and readable even when history
fills the list.
Replace the old QCompleter-based popup with a custom list that renders
AutocompleteSuggestion rows with titles/URLs/section headers/favicons.
Parent the popup inside the window so it does not steal focus, route
keyboard and mouse activation through WebView::Autocomplete, and add
inline completion with backspace suppression and top-row selection.
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.
The bytecode interpreter only needed the running execution context,
but still threaded a separate Interpreter object through both the C++
and asm entry points. Move that state and the bytecode execution
helpers onto VM instead, and teach the asm generator and slow paths to
use VM directly.
Qt does not use IOCP's in their underlying Windows event loop
implementation; however, QWinEventNotifier allows us to register a wait
on a process handle that has SYNCHRONIZE access rights. This means an
event will be signalled when that process terminates which emits the
QWinEventNotifier::activated signal.
Co-authored-by: Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
This page renders the bookmarks as a tree and hook context menu events
up to the UI's bookmarks bar context menus to allow editing bookmarks.
Users can also drag-and-drop bookmark items around.
Generalize the backing store sharing abstraction into SharedImage, which
represents shared GPU memory independently of Skia and can be used to
share memory between different processes or different GPU contexts.
AppKit doesn't need the bookmarks bar reorganization that Qt needed to
handle more mouse events. But let's rename these member fields to match
what they are now called in Qt.
In addition to Ctrl+PageDown and Ctrl+PageUp, also support Ctrl+Tab and
Ctrl+Shift+Tab to switch between browser tabs. This is the common
behavior in other browsers.
Unfortunately, the NSMenu-based bookmarks implementation cannot support
context menus within arbitrary folders. The NSMenu consumes the right-
click events during its own menu tracking, and we are not able to see
those events from our interface.
This patch replaces the NSMenu for folders with a custom NSPopup. This
implementation makes it much easier to handle context menus.
This allows us to get rid of the annoying Build/.../Lagom directory
and helps to deduplicate a bunch of logic while also drastically
simplifying everything.
This is largely based of off the work done by Andrew Kaster in #5918.
Having this toggle makes much more sense, especially if there will be
more UIs in the future.
Co-authored-by: Andrew Kaster <andrew@ladybird.org>
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.
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.
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.
Changing Ctrl+click to a secondary click is incorrect. It prevents
sites from using Ctrl+click themselves. Instead, just maybe open the
context menu in mousedown for primary clicks with Ctrl pressed.
Fixes the autofire shortcut not working in the Humble Mozilla Bundle's
asm.js FTL.
This moves normal/double/triple click checking into WebContent, the
client only has to send a click count in order to activate a double
or triple click in the content. This means that the AppKit UI will no
longer fire multiple double clicks when clicking in place more than 3
times. This matches the behavior of other browsers on macOS.
We will now also fire the click event regardless of whether a dblclick
event will follow, as the spec requires.
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.