Previously the 'device independent pixels' (which consider scaling)
were used, and then scaling would be applied again when calculating the
screen width for CSS.
It previously resided in LibWebView to hide the details of launching a
singleton process. That functionality now lives in LibCore. By moving
this to Ladybird, we will be able to register the process with the task
manager.
This will be needed to collect statistics from processes that do not
have anything to do with LibWebView. The ProcessInfo structure must be
virtual to allow callers to add application-specific information.
Sometimes I like to play around with running Ladybird tests using full
blown Ladybird instead of just headless browser to interactively mess
around with the test page. One problem with this is that the internals
object is not exposed in this mode.
This commit supports this usecase by adding an option to specifically
expose the internals object without needing to run headless-browser
in test mode.
When launched with the new --enable-idl-tracing option, we now log
every call to web platform APIs declared via IDL, along with the
arguments passed.
This can be very helpful when trying to figure out what a site is
doing, especially if it's not doing what you'd expect.
When running with --log-all-js-exceptions, we will print the message
and backtrace for every single JS exception that is thrown, not just
the ones nobody caught.
This can sometimes be very helpful in debugging sites that swallow
important exceptions.
Before this change we had to keep session history on browser side to
calculate a url for back/forward/reload action.
Now, with a mature enough implementation of navigation algorithms from
the specification, there is no need to use
history on the browser side to calculate navigation URLs because:
- Traversable navigable owns session history that is aware of all
navigations, including those initiated by History API and Navigation
API
- TraversableNavigable::traverse_the_history_by_delta() uses
traversable's history to calculate the next URL based on delta, so
there is no need for UI to keep sesion history.
In the future, we will likely want to add a way to pull session history
from WebContent to make it browsable from the UI.
The previous name was extremely misleading, because the call is used for
pushing or replacing new session history entry on chrome side instead of
only changing URL.
Instead of treating reloading as a regular navigation by using
load_url(), now we invoke a navigable reloading algorithm implemented
from the spec.
Now both reloading triggered from UI and location.reload() will use the
same code path.
On macOS, it's not trivial to get a Mach task port for your children.
This implementation registers the chrome process as a well-known
service with launchd based on its pid, and lets each child process
send over a reference to its mach_task_self() back to the chrome.
We'll need this Mach task port right to get process statistics.
Currently the `<select>` dropdown IPC uses the option value attr to
find which option is selected. This won't work when options don't
have values or when multiple options have the same value. Also the
`SelectItem` contained so weird recursive structures that are
impossible to create with HTML. So I refactored `SelectItem` as a
variant, and gave the options a unique id. The id is send back to
`HTMLSelectElement` so it can find out exactly which option element
is selected.
This adds a button on the right side of the location bar to create a new
tab.
Ideally, we would actually use QTabWidget::setCornerWidget to put this
button in the tab bar. But it is surprisingly difficult to make that
look nice on all platforms. Even if we ignore macOS, the CSS to make the
button look right on KDE Plasma may not work well on Gnome. So for now,
this location next to the location bar is horizontally the same that it
would be in the tab bar at least.
We currently do this already when the last tab is closed via the ctrl-W
shortcut. Move the logic for this to BrowserWindow::close_tab so that we
also close the window when the tab is closed via its close button.
By default, Qt will grow the width of a tab button to fit the title text
of the tab. For long titles or file:// URLs, this looks rather bad. This
sets a min/max tab width to prevent such infinite growth.
To do this, we have to subclass both QTabWidget and QTabBar, because the
functions to be called/overridden are protected.
If the left-hand side of the tab is already occupied with an audio state
button, we would add a second button to the right-hand side. Prevent
that by checking if the occupant is our audio state button.
On Serenity, it's not trivial to extract the peer pid from a socket that
is created by SystemServer and then passed to a forked service process.
This patch adds an API to let the WebContent process notify the UI
directly, which makes the WebContent process show up in the Serenity
port's TaskManagerWidget. It seems that we will need to do something of
this sort in order to properly gather metrics on macOS as well, due to
the way that self mach ports work.
This implementation uses a really basic WebView to update stats once
a second. In the future it might make more sense to both move the
details into LibWebView, and to create a native widget for each platform
to remove the overhead of having an extra WebView.
On macOS, the "close tab" button is on the left, so we should place the
audio state button on the right to avoid conflict. Rather than an OS
ifdef, we do this by detecting if the left side is occupied.
We were errantly always referring to the active tab when the audio play
state changed, and when clicking a tab's audio state button, by way of
BrowserWindow::view().
It turns out we also can't copy / rely on the tab index provided to the
signal in any asynchronous context. If the tabs are rearranged, so are
their indices. Instead, capture a pointer to the tab of interest - this
should be safe as we wouldn't be able to click a tab's audio button if
that tab no longer exists.
With this change, we can click the audio button from any tab in the Qt
chrome, and re-arrange tabs at will. The AppKit and Serenity chromes do
not have this issue.
We already display a speaker icon on tabs which are playing audio. This
allows the user to click that icon to mute the tab, at which point the
icon is replaced with a muted speaker icon.
We would previously hide the icon when audio stopped playing. We now do
this only if the tab isn't muted. If it is muted, the muted speaker icon
remains on the tab so that the page isn't stuck in a muted state.
We already display a speaker icon on tabs which are playing audio. This
allows the user to click that icon to mute the tab, at which point the
icon is replaced with a muted speaker icon.
We would previously hide the icon when audio stopped playing. We now do
this only if the tab isn't muted. If it is muted, the muted speaker icon
remains on the tab so that the page isn't stuck in a muted state.
When audio begins playing, add a button as an accessory view with a
speaker icon to indicate which tab is playing audio. This button is
currently disabled, but in the future may be used to mute the tab.
When audio begins playing, add a button to the left of the favicon with
a speaker icon to indicate which tab is playing audio. This button is
currently disabled, but in the future may be used to mute the tab.
This ensures we consistently show a favicon and that we update the title
to at least display the page URL when there isn't a <title> tag. We
would otherwise continue displaying the previous page's title.
The path we were using is no longer correct, and we've been silently
dropping this error. Use Core::Resource instead, which we use for most
other Ladybird resources. This would have made it much more obvious that
emoji were not installed with the application.
This URL library ends up being a relatively fundamental base library of
the system, as LibCore depends on LibURL.
This change has two main benefits:
* Moving AK back more towards being an agnostic library that can
be used between the kernel and userspace. URL has never really fit
that description - and is not used in the kernel.
* URL _should_ depend on LibUnicode, as it needs punnycode support.
However, it's not really possible to do this inside of AK as it can't
depend on any external library. This change brings us a little closer
to being able to do that, but unfortunately we aren't there quite
yet, as the code generators depend on LibCore.
These are standalone applications meant to be run by the user directly,
as opposed to other libexec processes which are programmatically forked
by the browser. To do this, we simply remove these processes from the
`ladybird_helper_processes` list. We must also explicitly list the
dependencies for these processes.
For Ninja Multi-Config, Xcode and Visual Studio, the way we set up our
output directories would result in exectuables that can't run from the
build directory. Add the same sauce that we added to Jakt to insert
``$<CONFIG>`` where appropriate.
The code to convert a Gfx::IntPoint to a QPoint adjusted for the device
pixel ratio is a bit of a mouthful, and will be needed outside of Tab,
so move it to a helper that can be reused.
After ea682207d0, we need Userland/
included directly in these application executables. This only impacts
the build with Ladybird/CMakeLists.txt as the top level CMakeLists, as
the Lagom/ directory includes Userland/ globally.
It's no change in application behavior to have these objects owned by
the function-scope static map in Protocol.cpp, while allowing us to
remove some ugly FIXMEs from time immemorial.
The AppKit chrome currently handles all input events before selectively
forwarding those events to WebContent. This means that WebContent does
not see events like cmd+c.
Here, we make use of LibWebView's input handling and wait for LibWebView
to inform the chrome that it should handle the event itself.
The Qt chrome currently handles all input events before selectively
forwarding those events to WebContent. This means that WebContent does
not see events like ctrl+c.
Here, we make use of LibWebView's input handling and wait for LibWebView
to inform the chrome that it should handle the event itself.
It aligns better with the Filesystem Heirarchy Standard[1] to put our
program-specific helper programs that are not intended to be executed by
the user of the application in $prefix/libexec or in whatever the
packager sets as the CMake equivalent. Namely, on Debian systems this
should be /usr/lib/Ladybird or similar.
[1] https://refspecs.linuxfoundation.org/FHS_3.0/fhs-3.0.html#usrlibexec
Now we will only load resources from $build/share/Lagom. On macOS, we
load from the bundle directory Contents/Resources instead. This
simplifies the commands and environment variables needed to execute
Ladybird from the build directory, and makes our install setup less
awkward for distributions and packagers.
Don't put them in bin/ and then copy them to the bundle dir later, as
this means that they only get updated in the bundle directory if the
Ladybird binary itself needs updated. Which is not a fun workflow if you
are working on WPT and want to hack on the WebDriver binary.
QUrl::toString reverses the Unicode->ASCII conversion that already
occurred here. The text of m_location_edit is already in the format we
expect, so let's just convert QString->AK::URL directly, instead of
taking the detour QString->QUrl->AK::URL
Some Wayland compositors have support of fractional-scale-v1 protocol.
The protocol allows compositor to announce a preferred fractional scale
on a per-wl_surface basis. Qt forwards these Wayland events to an
application using a usual DevicePixelRatioChange event. However, in
contrast to the other platforms, this DevicePixelRatioChange event is
issued directly on widgets and not screens. Additionally, the exact
fractional scale is stored in QWindow object and not the current screen.
Note that in theory it is possible to obtain per-screen fractional
scaling on Wayland by interpolating data provided by wl_output and
xdg_output events but qtwayland does not do that.
If fractional-scale-v1 is not available, qtwayland will still fire
per-Widget DevicePixelRatioChange events, but, obviously, with the
per-screen possibly larger ceiled scaling.
This whole thing makes handling DPI changes on Wayland really simple.
All we need to do is to intercept DevicePixelRatioChange events firing
on QWindow objects and call the old device_pixel_ratio_changed handler
with the window's devicePixelRatio(). The only caveat here is not forget
to always set QWidget's parent before calling devicePixelRatio() on it.
Previously, on systems where pressing Enter would generate "\r\n", only
the '\r' character was being sent to the event handler. This change
ensures consistent behavior across platforms regardless of their native
line ending characters.
The IPC layer between chromes and LibWeb now understands that multiple
top level traversables can live in each WebContent process.
This largely mechanical change adds a billion page_id/page_index
arguments to make sure that pages that end up opening new WebViews
through mechanisms like window.open() still work properly with those
extra windows.