{"@attributes":{"version":"2.0"},"channel":{"title":"Planet Igalia WebKit","link":"https:\/\/planet.igalia.com\/webkit","language":"en","description":"Planet Igalia WebKit - https:\/\/planet.igalia.com\/webkit","item":[{"title":"Igalia WebKit Team: WebKit Igalia Periodical #61","guid":"https:\/\/blogs.igalia.com\/webkit\/blog\/2026\/wip-61\/","link":"https:\/\/blogs.igalia.com\/webkit\/blog\/2026\/wip-61\/","description":"\n<p>Update on what happened in WebKit in the week from March 23 to March 30.<\/p>\n<p>\nThis week comes with a mixed bag of new features, incremental improvements,\nand a new release with the ever important security issue fixes. Also: more\nblog posts!\n<\/p>\n<h2 id=\"cross-port-cat\">Cross-Port \ud83d\udc31<\/h2>\n  <div class=\"wip-item\">\n<p><a rel=\"external\" href=\"https:\/\/commits.webkit.org\/309558@main\">Implemented<\/a> initial support for\n<code>closedby=any<\/code> on dialog elements, which adds light dismiss behaviour. This is\nbehind the <code>ClosedbyAttributeEnabled<\/code> feature flag.<\/p>\n  <\/div>\n  <div class=\"wip-item\">\n<p><a rel=\"external\" href=\"https:\/\/commits.webkit.org\/309802@main\">Added<\/a> the remaining values for the\nexperimental <code>closedby<\/code> attribute implementation.<\/p>\n  <\/div>\n  <div class=\"wip-item\">\n<p><a rel=\"external\" href=\"https:\/\/commits.webkit.org\/310070@main\">MiniBrowser now has<\/a> a\n<code>--profile-dir=DIR<\/code> command line option that can be used to specify a custom\ndirectory where website data and cache can be stored, to test, for example,\nbehavior in a clean session.<\/p>\n  <\/div>\n<h3 id=\"multimedia-movie-camera\">Multimedia \ud83c\udfa5<\/h3>\n<div class=\"wip-description\">\n<p>GStreamer-based multimedia support for WebKit, including (but not limited to)\nplayback, capture, WebAudio, WebCodecs, and WebRTC.<\/p>\n<\/div>\n  <div class=\"wip-item\">\n<p>Video decoding limits had been enforced on <code>HTMLMediaElement.canPlayType()<\/code> so\nfar, but <a rel=\"external\" href=\"https:\/\/bugs.webkit.org\/show_bug.cgi?id=310192\">they are now also enforced in MediaCapabilities\nqueries<\/a>.<\/p>\n  <\/div>\n<h3 id=\"graphics-frame-photo\">Graphics \ud83d\uddbc\ufe0f<\/h3>\n  <div class=\"wip-item\">\n<p><a rel=\"external\" href=\"https:\/\/commits.webkit.org\/310220@main\">Fixed<\/a> several OpenGL state\nrestoration bugs in <code>BitmapTexture<\/code> . These could cause a mismatch between the\nGL state assumed by Skia and the actual one, leading to rendering artifacts\nwith certain GPU drivers and configurations.<\/p>\n  <\/div>\n  <div class=\"wip-item\">\n<p>The <code>SKIA_DEBUG<\/code> CMake option <a rel=\"external\" href=\"https:\/\/commits.webkit.org\/310215@main\">has been\nenabled<\/a> for <code>Debug<\/code> builds, enabling\nSkia's internal assertions, debug logging, and consistency checks (e.g. bounds\nchecking, resource key diagnostics). It remains off by default for <code>Release<\/code>\nand <code>RelWithDebInfo<\/code> builds, and can still be explicitly configured via\n<code>-DSKIA_DEBUG=ON|OFF<\/code>.<\/p>\n  <\/div>\n<h2 id=\"wpe-webkit-pager\">WPE WebKit \ud83d\udcdf<\/h2>\n<h3 id=\"wpe-platform-api-jigsaw\">WPE Platform API \ud83e\udde9<\/h3>\n<div class=\"wip-description\">\n<p>New, modern platform API that supersedes usage of libwpe and WPE backends.<\/p>\n<\/div>\n  <div class=\"wip-item\">\n<p>The new <code>WPE_SETTING_OVERLAY_SCROLLBARS<\/code> setting <a rel=\"external\" href=\"https:\/\/commits.webkit.org\/309811@main\">is now\navailable<\/a>, and disabling it will use a\nmore traditional, always visible scrollbar style.<\/p>\n  <\/div>\n<h2 id=\"releases-package\">Releases \ud83d\udce6\ufe0f<\/h2>\n  <div class=\"wip-item\">\n<p>A new <code>USE_GSTREAMER<\/code> build option <a rel=\"external\" href=\"https:\/\/commits.webkit.org\/309883@main\">may now be\nused<\/a> to toggle the features that\nrequire GStreamer at once. This can be used to effectively disable all\nmultimedia support, which previously needed toggling four CMake options.<\/p>\n  <\/div>\n  <div class=\"wip-item\">\n<p><a rel=\"external\" href=\"https:\/\/webkitgtk.org\/2026\/03\/27\/webkitgtk2.52.1-released.html\">WebKitGTK\n2.52.1<\/a> and\n<a rel=\"external\" href=\"https:\/\/wpewebkit.org\/release\/wpewebkit-2.52.1.html\">WPE WebKit 2.52.1<\/a> have\nbeen released. On top of a small corrections typical of the first point\nreleases in a new stable series, this one includes a number of fixes for\nsecurity issues, and it is a recommended update. The corresponding security\nadvisory, <code>WSA-2026-0002<\/code>\n(<a rel=\"external\" href=\"https:\/\/webkitgtk.org\/security\/WSA-2026-0002.html\">GTK<\/a>,\n<a rel=\"external\" href=\"https:\/\/wpewebkit.org\/security\/WSA-2026-0002.html\">WPE<\/a>) has been published as\nwell.<\/p>\n  <\/div>\n<h2 id=\"community-events-handshake\">Community &amp; Events \ud83e\udd1d<\/h2>\n  <div class=\"wip-item\">\n<p>Sim\u00f3n Pena wrote a blog post showing <a rel=\"external\" href=\"https:\/\/simonpena.com\/blog\/2026\/03\/20\/getting-started-with-wpe-webkit\/\">how to create a minimal WPE\nlauncher<\/a>,\nwhich uses a Fedora Podman container with pre-built WPE WebKit libraries and a\nlauncher with barely 10 lines of code to display a web view. This complements\nKate Lee's <a rel=\"external\" href=\"https:\/\/blogs.igalia.com\/klee\/building-a-custom-html-context-menu-with-the-new-wpeplatform-api\/\">custom HTML context menu blog\npost<\/a>\nfrom last week.<\/p>\n  <\/div>\n<div class=\"wip-end\">\n<p>That\u2019s all for this week!<\/p>\n<\/div>        ","pubDate":"Mon, 30 Mar 2026 21:46:57 +0000"},{"title":"Igalia WebKit Team: WebKit Igalia Periodical #60","guid":"https:\/\/blogs.igalia.com\/webkit\/blog\/2026\/wip-60\/","link":"https:\/\/blogs.igalia.com\/webkit\/blog\/2026\/wip-60\/","description":"\n<p>Update on what happened in WebKit in the week from March 10 to March 18.<\/p>\n<p>\nThe big ticket item in this week's update are the 2.52.0 releases, which\ninclude the work from the last six-month development period, and come with\na security advisory. Meanwhile, WPE-Android also gets a release, and a number\nof featured blog posts.\n<\/p>\n<h2 id=\"wpe-webkit-pager\">WPE WebKit \ud83d\udcdf<\/h2>\n  <div class=\"wip-item\">\n<p>Last week we <a rel=\"external\" href=\"https:\/\/commits.webkit.org\/309047@main\">added support<\/a> to WPE\nMiniBrowser to load <a rel=\"external\" href=\"https:\/\/wpewebkit.org\/reference\/2.52.0\/wpe-webkit-2.0\/class.Settings.html\">settings<\/a> from a key file. This extended the existing\n<code>--config-file=FILE<\/code> feature, which previously only loaded WPEPlatform\nsettings under the <code>[wpe-platform]<\/code> group. Now the feature uses\n<a rel=\"external\" href=\"https:\/\/wpewebkit.org\/reference\/2.52.0\/wpe-webkit-2.0\/method.Settings.apply_from_key_file.html\">webkit_settings_apply_from_key_file()<\/a>\nto load properties such as <code>user-agent<\/code> or <code>enable-developer-extras<\/code>\nfrom the <code>[websettings]<\/code> group as well.<\/p>\n  <\/div>\n<h2 id=\"releases-package\">Releases \ud83d\udce6\ufe0f<\/h2>\n  <div class=\"wip-item\">\n<p><a rel=\"external\" href=\"https:\/\/webkitgtk.org\/2026\/03\/18\/webkitgtk2.52.0-released.html\">WebKitGTK\n2.52.0<\/a> and\n<a rel=\"external\" href=\"https:\/\/wpewebkit.org\/release\/wpewebkit-2.52.0.html\">WPE WebKit 2.52.0<\/a> are\nnow available. These include the results of the effort made by the team during\nthe last six months, including rendering improvements and performance\noptimizations, better security for WebRTC, a more complete WebXR\nimplementation, and a second preview of the WPEPlatform API for the WPE\nport\u2014among many other changes.<\/p>\n<p>More information about the changes and improvements brought by these major\nreleases can be found at the <a rel=\"external\" href=\"https:\/\/webkitgtk.org\/2026\/03\/18\/webkitgtk-2.52-highlights.html\">blog post about WebKitGTK\n2.52<\/a>, and the\n<a rel=\"external\" href=\"https:\/\/wpewebkit.org\/blog\/2026-03-18-wpewebkit-2.52.html\">corresponding one for WPE WebKit\n2.52<\/a>.<\/p>\n<p>Accompanying these releases there is security advisory <code>WSA-2026-0001<\/code>\n(<a rel=\"external\" href=\"https:\/\/webkitgtk.org\/security\/WSA-2026-0001.html\">GTK<\/a>,\n<a rel=\"external\" href=\"https:\/\/wpewebkit.org\/security\/WSA-2026-0001.html\">WPE<\/a>), with information\nabout solved security issues. As usual, we encourage everybody to use the most\nrecent versions where such issues are known to be fixed.<\/p>\n<p>Bug reports are always welcome <a rel=\"external\" href=\"https:\/\/bugs.webkit.org\/\">at the WebKit\nBugzilla<\/a>.<\/p>\n  <\/div>\n  <div class=\"wip-item\">\n<p><a rel=\"external\" href=\"https:\/\/github.com\/Igalia\/wpe-android\/releases\/tag\/v0.3.3\">WPE Android 0.3.3<\/a> has been released, and prebuilt packages are available <a rel=\"external\" href=\"https:\/\/central.sonatype.com\/artifact\/org.wpewebkit.wpeview\/wpeview\/\">at the Maven Central repository<\/a>. This is a maintenance release which updates the included WPE WebKit version to 2.50.6 and libsoup to 3.6.6, both of which include security fixes.<\/p>\n  <\/div>\n<h2 id=\"community-events-handshake\">Community &amp; Events \ud83e\udd1d<\/h2>\n  <div class=\"wip-item\">\n<p>Kate Lee wrote a <a rel=\"external\" href=\"https:\/\/blogs.igalia.com\/klee\/building-a-custom-html-context-menu-with-the-new-wpeplatform-api\/\">very interesting blog\npost<\/a>\nshowing how to create a small application using the WPEPlatform API to\ndemonstrate one of its newly available features: the Context Menu API. It is\nrendered entirely as an HTML overlay, enabling richer and more portable context\nmenu implementations.<\/p>\n  <\/div>\n  <div class=\"wip-item\">\n<p>WebXR support for WebKitGTK and WPE has been reworked and aligned with the\nmodern multi-process architecture, using OpenXR to enable XR device integration\non Linux and Android. Sergio Villar <a rel=\"external\" href=\"https:\/\/blogs.igalia.com\/svillar\/post\/webkitgtk-wpe-webxr\/\">wrote a blog post that explains all the\nwork done<\/a> in the\nlast months around it.<\/p>\n  <\/div>\n<div class=\"wip-end\">\n<p>That\u2019s all for this week!<\/p>\n<\/div>        ","pubDate":"Wed, 18 Mar 2026 19:46:56 +0000"},{"title":"WPE WebKit Blog: WPE WebKit 2.52 highlights","guid":"https:\/\/wpewebkit.org\/blog\/2026-03-18-wpewebkit-2.52.html","link":"https:\/\/wpewebkit.org\/blog\/2026-03-18-wpewebkit-2.52.html","description":"\n<p>The WebKit team at Igalia is happy to announce a new release series of WPE WebKit. This is a summary of the most noteworthy changes from the latest release cycle.<\/p>\n<h2 id=\"graphics-improvements\" tabindex=\"-1\">Graphics improvements<\/h2>\n<p>WPE\u2019s graphics support has seen numerous improvements with a positive impact in rendering performance, resource usage, and better rendering. Let\u2019s have a look at some of the most significant changes:<\/p>\n<ul>\n<li>Compute the layers tile size, using a different strategy depending on whether GPU rendering is enabled. This optimizes resource usage depending on both hardware and software rendering mode.<\/li>\n<li>WPE now uses run-loop observers to properly schedule layer flushing and composition, which results in snappier and better performing rendering and animation.<\/li>\n<li>2D-canvas acceleration has now improved performance, as operations are recorded for batched replay.<\/li>\n<li>Text rendering has better performance too.<\/li>\n<li>In non-composite mode, it\u2019s now also possible to use damage propagation.<\/li>\n<li>Asynchronous scrolling has also seen performance improvements.<\/li>\n<\/ul>\n<p>On top of this, as usual, many rendering issues have been fixed, making this release of WPE one of the best in terms of graphics support.<\/p>\n<h2 id=\"multimedia-improvements\" tabindex=\"-1\">Multimedia improvements<\/h2>\n<h3 id=\"webrtc\" tabindex=\"-1\">WebRTC<\/h3>\n<p>When using <code>GstWebRTC<\/code>, WebRTC network access has been moved to the network process. This also requires librice, and building with the CMake <code>USE_LIBRICE<\/code> option. When this is enabled, it is still possible to choose the older libnice-based implementation at runtime by setting <code>WEBKIT_GST_DISABLE_WEBRTC_NETWORK_SANDBOX=1<\/code> in the environment.<\/p>\n<p>Having WebRTC network access in the network process is a security improvement, as it reduces the surface of attack in other more sensitive processes.<\/p>\n<h3 id=\"other-multimedia-improvements\" tabindex=\"-1\">Other multimedia improvements<\/h3>\n<ul>\n<li>Videos with BT2100-PQ colorspace are now tone-mapped to SDR, ensuring colours do not appear washed out.<\/li>\n<li>Support for the <a href=\"https:\/\/w3c.github.io\/mediacapture-output\/\">Audio Output Devices API<\/a>, which allows Web content to enumerate audio devices and decide which one to use for output. This feature is disabled by default, and may be previewed using the <code>ExposeSpeakers<\/code>, <code>ExposeSpeakersWithoutMicrophone<\/code>, and <code>PerElementSpeakerSelection<\/code> <a href=\"https:\/\/wpewebkit.org\/reference\/2.52.0\/wpe-webkit-2.0\/struct.Feature.html\">feature flags<\/a>.<\/li>\n<li>Many code improvements to the GStreamer backend that will result in a more stable multimedia experience.<\/li>\n<\/ul>\n<h2 id=\"webxr\" tabindex=\"-1\">WebXR<\/h2>\n<p>WebXR support through OpenXR has seen substantial development this cycle:<\/p>\n<ul>\n<li>New API has been added in order to support <a href=\"https:\/\/wpewebkit.org\/reference\/2.52.0\/wpe-webkit-2.0\/class.XRPermissionRequest.html\">WebXR session permissions<\/a>, <a href=\"https:\/\/wpewebkit.org\/reference\/2.52.0\/wpe-webkit-2.0\/method.WebView.is_immersive_mode_enabled.html\">querying whether a session is active<\/a> and <a href=\"https:\/\/wpewebkit.org\/reference\/2.52.0\/wpe-webkit-2.0\/method.WebView.leave_immersive_mode.html\">requesting to leave a session<\/a>.<\/li>\n<li>Support for <a href=\"https:\/\/www.w3.org\/TR\/webxr-hand-input-1\/\">WebXR Hand Input module<\/a> has been added for ports using OpenXR.<\/li>\n<li>Support for <a href=\"https:\/\/www.w3.org\/TR\/webxr-hit-test-1\/\">WebXR Hit Test Module<\/a> is added with <em>testable<\/em> status, so it can be enabled at runtime (<code>--features=+WebXRHitTestModule<\/code>) or at build time passing <code>-DENABLE_WEBXR_HIT_TEST=ON<\/code>.<\/li>\n<\/ul>\n<h2 id=\"api-changes\" tabindex=\"-1\">API Changes<\/h2>\n<h3 id=\"the-future-of-the-wpe-api\" tabindex=\"-1\">The future of the WPE API<\/h3>\n<p>The traditional <code>libwpe<\/code>-based API remains in WPE for this release cycle, but we are planning to sunset it starting with the following one (2.54). This applies to <a href=\"https:\/\/github.com\/Igalia\/cog\">Cog<\/a>, which is no longer in active development and won\u2019t have any more stable releases beyond the 0.18.x series. While both <code>libwpe<\/code> and Cog will remain available, we encourage developers to transition to the new WPEPlatform API, which will be considered stable by then.<\/p>\n<p>This means that it is the perfect time to test the WPEPlatform API and provide feedback, as it\u2019s still possible to make changes to it to better suit users\u2019 needs.<\/p>\n<h3 id=\"wpeplatform-api-changes\" tabindex=\"-1\">WPEPlatform API changes<\/h3>\n<p>New platform APIs include:<\/p>\n<ul>\n<li><a href=\"https:\/\/wpewebkit.org\/reference\/2.52.0\/wpe-platform-2.0\/method.Display.create_toplevel.html\"><code>wpe_display_create_toplevel()<\/code><\/a>. This way it\u2019s possible to create a toplevel using the common API which allows the inspector to work when the application is handling toplevels.<\/li>\n<li>A new <a href=\"https:\/\/wpewebkit.org\/reference\/2.52.0\/wpe-platform-2.0\/signal.Display.disconnected.html\"><code>WPEDisplay::disconnected<\/code><\/a> signal has been added, which allows platform implementations to notify when the native display gets \u201cdisconnected\u201d and thus no longer usable. Applications can handle it to attempt recovery, or to know when they may free resources.<\/li>\n<li>A new <a href=\"https:\/\/wpewebkit.org\/reference\/2.52.0\/wpe-platform-2.0\/signal.View.buffers-changed.html\"><code>WPEView::buffers-changed<\/code><\/a> signal, alongside the associated <a href=\"https:\/\/wpewebkit.org\/reference\/2.52.0\/wpe-platform-2.0\/vfunc.View.buffers_changed.html\"><code>WPEViewClass.buffers_changed<\/code><\/a> virtual function, have been added. These may be used to know in advance which graphics buffers will be used for rendering the content for a given web view. This feature is mainly useful for platform implementations which may need to perform additional setup in advance, before updated web view contents are provided in the buffers configured by WebKit.<\/li>\n<li>Two new functions, <a href=\"https:\/\/wpewebkit.org\/reference\/2.52.0\/wpe-platform-2.0\/method.ClipboardContent.get_text.html\"><code>wpe_clipboard_content_get_text()<\/code><\/a> and <a href=\"https:\/\/wpewebkit.org\/reference\/2.52.0\/wpe-platform-2.0\/method.ClipboardContent.get_bytes.html\"><code>wpe_clipboard_content_get_bytes()<\/code><\/a>, allow applications to obtain the contents held in the clipboard.<\/li>\n<\/ul>\n<p>The public API has received the following changes, which might require changes to existing platform implementations:<\/p>\n<ul>\n<li>Multiple callbacks are now supported for <code>WPEScreenSyncObserver<\/code>, the API has changed from <code>wpe_screen_sync_observer_set_callback()<\/code> to a pair of <a href=\"https:\/\/wpewebkit.org\/reference\/2.52.0\/wpe-platform-2.0\/method.ScreenSyncObserver.add_callback.html\"><code>wpe_screen_sync_observer_add_callback()<\/code><\/a>\/<a href=\"https:\/\/wpewebkit.org\/reference\/2.52.0\/wpe-platform-2.0\/method.ScreenSyncObserver.remove_callback.html\"><code>_remove_callback()<\/code><\/a> functions. The functions to start\/stop the observer are no longer available, and instead the observer will be activated automatically when there are one or more callbacks attached to it.<\/li>\n<\/ul>\n<p>The WPEPlatform API can now be used on Android.<\/p>\n<h3 id=\"legacy-api\" tabindex=\"-1\">Legacy API<\/h3>\n<p>The legacy <code>libwpe<\/code>-based API can be disabled at build time, by toggling the <code>ENABLE_WPE_LEGACY_API<\/code> CMake option. This allows removal of uneeded code when an application is exclusively using the new WPEPlatform API.<\/p>\n<h3 id=\"new-webkit-api\" tabindex=\"-1\">New WebKit API<\/h3>\n<ul>\n<li><a href=\"https:\/\/wpewebkit.org\/reference\/2.52.0\/wpe-webkit-2.0\/class.Image.html\">WebKitImage<\/a>, an image abstraction that is used when taking snapshots of webviews.<\/li>\n<li><a href=\"https:\/\/wpewebkit.org\/reference\/2.52.0\/wpe-webkit-2.0\/method.WebView.get_snapshot.html\">webkit_webview_get_snapshot()<\/a> and <a href=\"https:\/\/wpewebkit.org\/reference\/2.52.0\/wpe-webkit-2.0\/method.WebView.get_snapshot_finish.html\">webkit_webview_get_snapshot_finish()<\/a> can be used to fetch a snapshot of a webview contents.<\/li>\n<\/ul>\n<h2 id=\"web-standards-support\" tabindex=\"-1\">Web Standards support<\/h2>\n<p>As usual, this list is not exhaustive as WebKit continuously progresses in its support for new standards. Some of the highlights for this release are:<\/p>\n<ul>\n<li><a href=\"https:\/\/www.w3.org\/TR\/largest-contentful-paint\/\">Largest Contentful Paint<\/a> is now enabled.<\/li>\n<li>Pointer and Touch Events now use more precise fractional coordinates.<\/li>\n<li>The <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Fetch_API\">Fetch API<\/a> now accepts local connections.<\/li>\n<li>The <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Navigation_API\">Navigation API<\/a> is now enabled.<\/li>\n<li>The <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/PerformanceEventTiming\">Event Timing API<\/a> is now enabled.<\/li>\n<li>The <a href=\"https:\/\/drafts.csswg.org\/css-values-5\/#random\">CSS random() function<\/a> (in draft status) is now available.<\/li>\n<li><a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/CSS\/field-sizing\">CSS field-sizing<\/a> is now available.<\/li>\n<li>The <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Keyboard\/lock\">Keyboard lock API<\/a> is now available.<\/li>\n<li>The <a href=\"https:\/\/html.spec.whatwg.org\/multipage\/browsers.html#the-origin-interface\">Origin API<\/a> is now available.<\/li>\n<li>The <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Streams_API\">Readable Byte Streams API<\/a> is now available.<\/li>\n<li>Enabled CSS grid-lanes (a.k.a. Masonry layout), part of <a href=\"https:\/\/www.w3.org\/TR\/css-grid-3\/\">CSS Grid Layout Module Level 3<\/a>.<\/li>\n<\/ul>\n<h2 id=\"other-notes\" tabindex=\"-1\">Other notes<\/h2>\n<p>The Flatpak-based development SDK has been removed. Developers are encouraged to use the\n<a href=\"https:\/\/github.com\/Igalia\/webkit-container-sdk\"><strong>WebKit Container SDK<\/strong><\/a> instead.<\/p>        ","pubDate":"Wed, 18 Mar 2026 00:00:00 +0000"},{"title":"Sergio Villar: Implementing WebXR in WebKit for WPE","guid":"https:\/\/blogs.igalia.com\/svillar\/post\/wpe-webxr\/","link":"https:\/\/blogs.igalia.com\/svillar\/post\/wpe-webxr\/","description":"\n<p>Since 2022, my main focus has been working on the <a href=\"https:\/\/wolvic.com\">Wolvic browser<\/a>, still the only open source WebXR-capable browser for Android\/AOSP devices (Meta, Pico, Huawei, Lenovo, Lynx, HTC&hellip;) out there. That&rsquo;s an effort that continues to this day (although to a <a href=\"https:\/\/wolvic.com\/blog\/next-steps\/\">much lesser extent nowadays<\/a>). In early 2025, as a consequence of all that work in XR on the web, an opportunity emerged to implement WebXR support in WebKit for the WPE port, and we decided to take it.<\/p>        ","pubDate":"Tue, 17 Mar 2026 08:46:59 +0000"},{"title":"Kate Lee: Building a Custom HTML Context Menu with the New WPEPlatform API","guid":"https:\/\/blogs.igalia.com\/klee\/building-a-custom-html-context-menu-with-the-new-wpeplatform-api\/","link":"https:\/\/blogs.igalia.com\/klee\/building-a-custom-html-context-menu-with-the-new-wpeplatform-api\/","description":"\n<p><a href=\"https:\/\/wpewebkit.org\/\">WPE WebKit<\/a> is a WebKit port optimized for embedded devices \u2014 think set-top boxes, digital signage, kiosk displays, and in-vehicle infotainment systems. It is developed by <a href=\"https:\/\/www.igalia.com\/\">Igalia<\/a> and powers web experiences on millions of devices worldwide, from set-top boxes to smart TVs and beyond.<\/p>\n<p>WPE WebKit has recently introduced a <strong>brand-new platform API called WPEPlatform<\/strong>, which replaces the legacy <code>libwpe<\/code> + <code>wpebackend-fdo<\/code> stack. In this post, I will walk you through building a minimal WPE browser launcher using <strong>only the new WPEPlatform API<\/strong>, and demonstrate one of its newly available features: the <strong>Context Menu API<\/strong> \u2014 rendered entirely as an HTML overlay.<\/p>\n<h2 id=\"why-a-new-api\" tabindex=\"-1\">Why a New API? <a class=\"header-anchor\" href=\"https:\/\/blogs.igalia.com\/klee\/building-a-custom-html-context-menu-with-the-new-wpeplatform-api\/\">#<\/a><\/h2>\n<p>The legacy stack (<code>libwpe<\/code> + <code>wpebackend-fdo<\/code> + Cog platform plugins) had several pain points: nested Wayland compositor complexity, dependency on Mesa\u2019s now-deprecated <code>EGL_WL_bind_wayland_display<\/code> extension, rigid C function-pointer tables, and platform code scattered across three libraries.<\/p>\n<p>The <strong>new WPEPlatform API<\/strong> replaces all of this with a single, clean <a href=\"https:\/\/docs.gtk.org\/gobject\/\">GObject<\/a>-based layer \u2014 providing automatic backend creation, DMA-BUF direct buffer sharing, unified window management (fullscreen, maximize, resize, title), and easy language bindings via GObject Introspection.<\/p>\n<blockquote>\n<p><strong>Timeline<\/strong>: The stable release of WPEPlatform is planned for <strong>September 2026<\/strong>. At that point, the legacy API will be officially deprecated. We strongly recommend new projects to adopt the WPEPlatform API from the start.<\/p>\n<\/blockquote>\n<h2 id=\"wpeplatform-launcher-a-minimal-browser-in-250-lines\" tabindex=\"-1\">WPEPlatform Launcher: A Minimal Browser in ~250 Lines <a class=\"header-anchor\" href=\"https:\/\/blogs.igalia.com\/klee\/building-a-custom-html-context-menu-with-the-new-wpeplatform-api\/\">#<\/a><\/h2>\n<p>To demonstrate the new API, I built <strong>WPEPlatformLauncher<\/strong> \u2014 a minimal but functional WPE WebKit browser that uses only the WPEPlatform API. No legacy <code>libwpe<\/code>, no <code>wpebackend-fdo<\/code>, no Cog \u2014 just the new API.<\/p>\n<p>The full source code is available at:\n<strong><a href=\"https:\/\/github.com\/kate-k-lee\/WebKit\/commit\/aed6402b267475f79ae7a8d417d18239b53be651\">kate-k-lee\/WebKit@aed6402<\/a><\/strong><\/p>\n<h3 id=\"how-simple-is-it\" tabindex=\"-1\">How Simple Is It? <a class=\"header-anchor\" href=\"https:\/\/blogs.igalia.com\/klee\/building-a-custom-html-context-menu-with-the-new-wpeplatform-api\/\">#<\/a><\/h3>\n<p>Here is the core of the launcher \u2014 creating a WebView with the new API:<\/p>\n<pre class=\"language-cpp\" tabindex=\"0\"><code class=\"language-cpp\"><span class=\"token comment\">\/* WPEPlatform backend is created automatically \u2014 no manual setup needed *\/<\/span><br \/><span class=\"token keyword\">auto<\/span><span class=\"token operator\">*<\/span> webView <span class=\"token operator\">=<\/span> <span class=\"token function\">WEBKIT_WEB_VIEW<\/span><span class=\"token punctuation\">(<\/span><span class=\"token function\">g_object_new<\/span><span class=\"token punctuation\">(<\/span>WEBKIT_TYPE_WEB_VIEW<span class=\"token punctuation\">,<\/span><br \/>    <span class=\"token string\">\"web-context\"<\/span><span class=\"token punctuation\">,<\/span> webContext<span class=\"token punctuation\">,<\/span><br \/>    <span class=\"token string\">\"network-session\"<\/span><span class=\"token punctuation\">,<\/span> networkSession<span class=\"token punctuation\">,<\/span><br \/>    <span class=\"token string\">\"settings\"<\/span><span class=\"token punctuation\">,<\/span> settings<span class=\"token punctuation\">,<\/span><br \/>    <span class=\"token string\">\"user-content-manager\"<\/span><span class=\"token punctuation\">,<\/span> userContentManager<span class=\"token punctuation\">,<\/span><br \/>    <span class=\"token keyword\">nullptr<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/><br \/><span class=\"token comment\">\/* Get the WPEPlatform view \u2014 this is where the new API shines *\/<\/span><br \/><span class=\"token keyword\">auto<\/span><span class=\"token operator\">*<\/span> wpeView <span class=\"token operator\">=<\/span> <span class=\"token function\">webkit_web_view_get_wpe_view<\/span><span class=\"token punctuation\">(<\/span>webView<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/><span class=\"token keyword\">auto<\/span><span class=\"token operator\">*<\/span> toplevel <span class=\"token operator\">=<\/span> <span class=\"token function\">wpe_view_get_toplevel<\/span><span class=\"token punctuation\">(<\/span>wpeView<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/><br \/><span class=\"token comment\">\/* Window management: fullscreen, resize, title \u2014 all built-in *\/<\/span><br \/><span class=\"token function\">wpe_toplevel_fullscreen<\/span><span class=\"token punctuation\">(<\/span>toplevel<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/><span class=\"token function\">wpe_toplevel_resize<\/span><span class=\"token punctuation\">(<\/span>toplevel<span class=\"token punctuation\">,<\/span> <span class=\"token number\">1920<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token number\">1080<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/><span class=\"token function\">wpe_toplevel_set_title<\/span><span class=\"token punctuation\">(<\/span>toplevel<span class=\"token punctuation\">,<\/span> <span class=\"token string\">\"WPEPlatform Launcher\"<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/><br \/><span class=\"token comment\">\/* Input events: just connect a GObject signal *\/<\/span><br \/><span class=\"token function\">g_signal_connect<\/span><span class=\"token punctuation\">(<\/span>wpeView<span class=\"token punctuation\">,<\/span> <span class=\"token string\">\"event\"<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token function\">G_CALLBACK<\/span><span class=\"token punctuation\">(<\/span>onViewEvent<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span> webView<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/code><\/pre>\n<p>Compare this with the legacy API, which required:<\/p>\n<ol>\n<li>Manually creating a <code>WPEToolingBackends::ViewBackend<\/code><\/li>\n<li>Wrapping it in a <code>WebKitWebViewBackend<\/code> with a destroy callback<\/li>\n<li>Creating a C++ <code>InputClient<\/code> class and registering it<\/li>\n<li>Having no window management (no maximize, minimize, title, etc.)<\/li>\n<\/ol>\n<p>The new API handles backend creation, display detection, and input forwarding automatically.<\/p>\n<h3 id=\"keyboard-shortcuts\" tabindex=\"-1\">Keyboard Shortcuts <a class=\"header-anchor\" href=\"https:\/\/blogs.igalia.com\/klee\/building-a-custom-html-context-menu-with-the-new-wpeplatform-api\/\">#<\/a><\/h3>\n<p>Handling keyboard events is straightforward with the WPEPlatform event system:<\/p>\n<pre class=\"language-cpp\" tabindex=\"0\"><code class=\"language-cpp\"><span class=\"token keyword\">static<\/span> gboolean <span class=\"token function\">onViewEvent<\/span><span class=\"token punctuation\">(<\/span>WPEView<span class=\"token operator\">*<\/span> view<span class=\"token punctuation\">,<\/span> WPEEvent<span class=\"token operator\">*<\/span> event<span class=\"token punctuation\">,<\/span> WebKitWebView<span class=\"token operator\">*<\/span> webView<span class=\"token punctuation\">)<\/span><br \/><span class=\"token punctuation\">{<\/span><br \/>    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token function\">wpe_event_get_event_type<\/span><span class=\"token punctuation\">(<\/span>event<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">!=<\/span> WPE_EVENT_KEYBOARD_KEY_DOWN<span class=\"token punctuation\">)<\/span><br \/>        <span class=\"token keyword\">return<\/span> FALSE<span class=\"token punctuation\">;<\/span><br \/><br \/>    <span class=\"token keyword\">auto<\/span> modifiers <span class=\"token operator\">=<\/span> <span class=\"token function\">wpe_event_get_modifiers<\/span><span class=\"token punctuation\">(<\/span>event<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>    <span class=\"token keyword\">auto<\/span> keyval <span class=\"token operator\">=<\/span> <span class=\"token function\">wpe_event_keyboard_get_keyval<\/span><span class=\"token punctuation\">(<\/span>event<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/><br \/>    <span class=\"token comment\">\/* Ctrl+Q: Quit *\/<\/span><br \/>    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">(<\/span>modifiers <span class=\"token operator\">&amp;<\/span> WPE_MODIFIER_KEYBOARD_CONTROL<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&amp;&amp;<\/span> keyval <span class=\"token operator\">==<\/span> WPE_KEY_q<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>        <span class=\"token function\">g_application_quit<\/span><span class=\"token punctuation\">(<\/span><span class=\"token function\">g_application_get_default<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>        <span class=\"token keyword\">return<\/span> TRUE<span class=\"token punctuation\">;<\/span><br \/>    <span class=\"token punctuation\">}<\/span><br \/><br \/>    <span class=\"token comment\">\/* F11: Toggle fullscreen via WPEToplevel *\/<\/span><br \/>    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>keyval <span class=\"token operator\">==<\/span> WPE_KEY_F11<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>        <span class=\"token keyword\">auto<\/span><span class=\"token operator\">*<\/span> toplevel <span class=\"token operator\">=<\/span> <span class=\"token function\">wpe_view_get_toplevel<\/span><span class=\"token punctuation\">(<\/span>view<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token function\">wpe_toplevel_get_state<\/span><span class=\"token punctuation\">(<\/span>toplevel<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&amp;<\/span> WPE_TOPLEVEL_STATE_FULLSCREEN<span class=\"token punctuation\">)<\/span><br \/>            <span class=\"token function\">wpe_toplevel_unfullscreen<\/span><span class=\"token punctuation\">(<\/span>toplevel<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>        <span class=\"token keyword\">else<\/span><br \/>            <span class=\"token function\">wpe_toplevel_fullscreen<\/span><span class=\"token punctuation\">(<\/span>toplevel<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>        <span class=\"token keyword\">return<\/span> TRUE<span class=\"token punctuation\">;<\/span><br \/>    <span class=\"token punctuation\">}<\/span><br \/><br \/>    <span class=\"token keyword\">return<\/span> FALSE<span class=\"token punctuation\">;<\/span><br \/><span class=\"token punctuation\">}<\/span><\/code><\/pre>\n<h2 id=\"html-based-context-menu-solving-the-no-native-ui-challenge\" tabindex=\"-1\">HTML-Based Context Menu: Solving the \u201cNo Native UI\u201d Challenge <a class=\"header-anchor\" href=\"https:\/\/blogs.igalia.com\/klee\/building-a-custom-html-context-menu-with-the-new-wpeplatform-api\/\">#<\/a><\/h2>\n<p>WPE WebKit is designed for embedded environments where there is <strong>no native UI toolkit<\/strong> \u2014 no GTK, no Qt. This means features like context menus (right-click menus) that desktop browsers take for granted need to be implemented by the application.<\/p>\n<p>The approach: <strong>intercept WebKit\u2019s <code>context-menu<\/code> signal, read the menu items, and render them as an HTML\/CSS overlay<\/strong> injected into the page DOM.<\/p>\n<h3 id=\"the-architecture\" tabindex=\"-1\">The Architecture <a class=\"header-anchor\" href=\"https:\/\/blogs.igalia.com\/klee\/building-a-custom-html-context-menu-with-the-new-wpeplatform-api\/\">#<\/a><\/h3>\n<pre><code>User right-clicks\n  \u2192 WebKit emits &quot;context-menu&quot; signal\n  \u2192 onContextMenu() handler:\n      1. Reads menu items via webkit_context_menu_get_items()\n      2. Gets position via webkit_context_menu_get_position()\n      3. Builds JavaScript that creates DOM elements\n      4. Injects via webkit_web_view_evaluate_javascript()\n      5. Returns TRUE (suppresses default menu)\n\nUser clicks a menu item\n  \u2192 JS: window.webkit.messageHandlers.contextMenuAction.postMessage(actionId)\n  \u2192 C: onContextMenuAction() receives the action ID\n      \u2192 Executes: webkit_web_view_go_back(), execute_editing_command(&quot;Copy&quot;), etc.\n\nUser clicks outside the menu\n  \u2192 JS: overlay click handler removes the DOM elements\n<\/code><\/pre>\n<h3 id=\"reading-context-menu-items\" tabindex=\"-1\">Reading Context Menu Items <a class=\"header-anchor\" href=\"https:\/\/blogs.igalia.com\/klee\/building-a-custom-html-context-menu-with-the-new-wpeplatform-api\/\">#<\/a><\/h3>\n<p>The Context Menu API provides everything we need:<\/p>\n<pre class=\"language-cpp\" tabindex=\"0\"><code class=\"language-cpp\"><span class=\"token keyword\">static<\/span> gboolean <span class=\"token function\">onContextMenu<\/span><span class=\"token punctuation\">(<\/span>WebKitWebView<span class=\"token operator\">*<\/span> webView<span class=\"token punctuation\">,<\/span><br \/>    WebKitContextMenu<span class=\"token operator\">*<\/span> contextMenu<span class=\"token punctuation\">,<\/span> gpointer <span class=\"token comment\">\/* event *\/<\/span><span class=\"token punctuation\">,<\/span><br \/>    WebKitHitTestResult<span class=\"token operator\">*<\/span> hitTestResult<span class=\"token punctuation\">,<\/span> gpointer<span class=\"token punctuation\">)<\/span><br \/><span class=\"token punctuation\">{<\/span><br \/>    <span class=\"token comment\">\/* Save hit test result for link-related actions *\/<\/span><br \/>    savedHitTestResult <span class=\"token operator\">=<\/span> <span class=\"token function\">WEBKIT_HIT_TEST_RESULT<\/span><span class=\"token punctuation\">(<\/span><span class=\"token function\">g_object_ref<\/span><span class=\"token punctuation\">(<\/span>hitTestResult<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/><br \/>    <span class=\"token comment\">\/* Iterate through menu items *\/<\/span><br \/>    GList<span class=\"token operator\">*<\/span> items <span class=\"token operator\">=<\/span> <span class=\"token function\">webkit_context_menu_get_items<\/span><span class=\"token punctuation\">(<\/span>contextMenu<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>    <span class=\"token keyword\">for<\/span> <span class=\"token punctuation\">(<\/span>GList<span class=\"token operator\">*<\/span> l <span class=\"token operator\">=<\/span> items<span class=\"token punctuation\">;<\/span> l<span class=\"token punctuation\">;<\/span> l <span class=\"token operator\">=<\/span> l<span class=\"token operator\">-><\/span>next<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>        <span class=\"token keyword\">auto<\/span><span class=\"token operator\">*<\/span> item <span class=\"token operator\">=<\/span> <span class=\"token function\">WEBKIT_CONTEXT_MENU_ITEM<\/span><span class=\"token punctuation\">(<\/span>l<span class=\"token operator\">-><\/span>data<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/><br \/>        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token function\">webkit_context_menu_item_is_separator<\/span><span class=\"token punctuation\">(<\/span>item<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>            <span class=\"token comment\">\/* Render as a horizontal line *\/<\/span><br \/>            <span class=\"token keyword\">continue<\/span><span class=\"token punctuation\">;<\/span><br \/>        <span class=\"token punctuation\">}<\/span><br \/><br \/>        <span class=\"token keyword\">const<\/span> <span class=\"token keyword\">char<\/span><span class=\"token operator\">*<\/span> title <span class=\"token operator\">=<\/span> <span class=\"token function\">webkit_context_menu_item_get_title<\/span><span class=\"token punctuation\">(<\/span>item<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>        <span class=\"token keyword\">auto<\/span> action <span class=\"token operator\">=<\/span> <span class=\"token function\">webkit_context_menu_item_get_stock_action<\/span><span class=\"token punctuation\">(<\/span>item<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>        <span class=\"token comment\">\/* Build HTML element with title and action ID *\/<\/span><br \/>    <span class=\"token punctuation\">}<\/span><br \/><br \/>    <span class=\"token comment\">\/* Get position for menu placement *\/<\/span><br \/>    gint posX <span class=\"token operator\">=<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">,<\/span> posY <span class=\"token operator\">=<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">;<\/span><br \/>    <span class=\"token function\">webkit_context_menu_get_position<\/span><span class=\"token punctuation\">(<\/span>contextMenu<span class=\"token punctuation\">,<\/span> <span class=\"token operator\">&amp;<\/span>posX<span class=\"token punctuation\">,<\/span> <span class=\"token operator\">&amp;<\/span>posY<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/><br \/>    <span class=\"token keyword\">return<\/span> TRUE<span class=\"token punctuation\">;<\/span> <span class=\"token comment\">\/* Suppress default menu *\/<\/span><br \/><span class=\"token punctuation\">}<\/span><\/code><\/pre>\n<h3 id=\"the-html-menu-dark-theme-for-embedded\" tabindex=\"-1\">The HTML Menu: Dark Theme for Embedded <a class=\"header-anchor\" href=\"https:\/\/blogs.igalia.com\/klee\/building-a-custom-html-context-menu-with-the-new-wpeplatform-api\/\">#<\/a><\/h3>\n<p>The context menu is rendered with a dark theme CSS, designed for embedded\/kiosk displays:<\/p>\n<pre class=\"language-css\" tabindex=\"0\"><code class=\"language-css\"><span class=\"token selector\">#__wpe_ctx_menu<\/span> <span class=\"token punctuation\">{<\/span><br \/>    <span class=\"token property\">position<\/span><span class=\"token punctuation\">:<\/span> fixed<span class=\"token punctuation\">;<\/span><br \/>    <span class=\"token property\">min-width<\/span><span class=\"token punctuation\">:<\/span> 180px<span class=\"token punctuation\">;<\/span><br \/>    <span class=\"token property\">background<\/span><span class=\"token punctuation\">:<\/span> #2b2b2b<span class=\"token punctuation\">;<\/span><br \/>    <span class=\"token property\">border<\/span><span class=\"token punctuation\">:<\/span> 1px solid #505050<span class=\"token punctuation\">;<\/span><br \/>    <span class=\"token property\">border-radius<\/span><span class=\"token punctuation\">:<\/span> 6px<span class=\"token punctuation\">;<\/span><br \/>    <span class=\"token property\">padding<\/span><span class=\"token punctuation\">:<\/span> 4px 0<span class=\"token punctuation\">;<\/span><br \/>    <span class=\"token property\">box-shadow<\/span><span class=\"token punctuation\">:<\/span> 0 8px 24px <span class=\"token function\">rgba<\/span><span class=\"token punctuation\">(<\/span>0<span class=\"token punctuation\">,<\/span>0<span class=\"token punctuation\">,<\/span>0<span class=\"token punctuation\">,<\/span>0.4<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>    <span class=\"token property\">font-family<\/span><span class=\"token punctuation\">:<\/span> system-ui<span class=\"token punctuation\">,<\/span> sans-serif<span class=\"token punctuation\">;<\/span><br \/>    <span class=\"token property\">font-size<\/span><span class=\"token punctuation\">:<\/span> 13px<span class=\"token punctuation\">;<\/span><br \/>    <span class=\"token property\">color<\/span><span class=\"token punctuation\">:<\/span> #e0e0e0<span class=\"token punctuation\">;<\/span><br \/><span class=\"token punctuation\">}<\/span><br \/><br \/><span class=\"token selector\">.__wpe_ctx_item:hover<\/span> <span class=\"token punctuation\">{<\/span><br \/>    <span class=\"token property\">background<\/span><span class=\"token punctuation\">:<\/span> #0060df<span class=\"token punctuation\">;<\/span><br \/>    <span class=\"token property\">color<\/span><span class=\"token punctuation\">:<\/span> #ffffff<span class=\"token punctuation\">;<\/span><br \/><span class=\"token punctuation\">}<\/span><\/code><\/pre>\n<h3 id=\"handling-actions-via-script-message-handler\" tabindex=\"-1\">Handling Actions via Script Message Handler <a class=\"header-anchor\" href=\"https:\/\/blogs.igalia.com\/klee\/building-a-custom-html-context-menu-with-the-new-wpeplatform-api\/\">#<\/a><\/h3>\n<p>Communication between the HTML menu and the C application uses WebKit\u2019s script message handler mechanism:<\/p>\n<pre class=\"language-cpp\" tabindex=\"0\"><code class=\"language-cpp\"><span class=\"token comment\">\/* Register message handler *\/<\/span><br \/><span class=\"token keyword\">auto<\/span><span class=\"token operator\">*<\/span> ucm <span class=\"token operator\">=<\/span> <span class=\"token function\">webkit_user_content_manager_new<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/><span class=\"token function\">webkit_user_content_manager_register_script_message_handler<\/span><span class=\"token punctuation\">(<\/span><br \/>    ucm<span class=\"token punctuation\">,<\/span> <span class=\"token string\">\"contextMenuAction\"<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">nullptr<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/><span class=\"token function\">g_signal_connect<\/span><span class=\"token punctuation\">(<\/span>ucm<span class=\"token punctuation\">,<\/span> <span class=\"token string\">\"script-message-received::contextMenuAction\"<\/span><span class=\"token punctuation\">,<\/span><br \/>    <span class=\"token function\">G_CALLBACK<\/span><span class=\"token punctuation\">(<\/span>onContextMenuAction<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">nullptr<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/code><\/pre>\n<pre class=\"language-javascript\" tabindex=\"0\"><code class=\"language-javascript\"><span class=\"token comment\">\/\/ In the generated HTML menu item:<\/span><br \/>item<span class=\"token punctuation\">.<\/span><span class=\"token function\">addEventListener<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">'click'<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">function<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>    window<span class=\"token punctuation\">.<\/span>webkit<span class=\"token punctuation\">.<\/span>messageHandlers<span class=\"token punctuation\">.<\/span>contextMenuAction<span class=\"token punctuation\">.<\/span><span class=\"token function\">postMessage<\/span><span class=\"token punctuation\">(<\/span>actionId<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/><span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/code><\/pre>\n<pre class=\"language-cpp\" tabindex=\"0\"><code class=\"language-cpp\"><span class=\"token comment\">\/* Handle the action in C *\/<\/span><br \/><span class=\"token keyword\">static<\/span> <span class=\"token keyword\">void<\/span> <span class=\"token function\">onContextMenuAction<\/span><span class=\"token punctuation\">(<\/span>WebKitUserContentManager<span class=\"token operator\">*<\/span><span class=\"token punctuation\">,<\/span> JSCValue<span class=\"token operator\">*<\/span> value<span class=\"token punctuation\">,<\/span> gpointer<span class=\"token punctuation\">)<\/span><br \/><span class=\"token punctuation\">{<\/span><br \/>    <span class=\"token keyword\">int<\/span> actionId <span class=\"token operator\">=<\/span> <span class=\"token function\">jsc_value_to_int32<\/span><span class=\"token punctuation\">(<\/span>value<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/><br \/>    <span class=\"token keyword\">switch<\/span> <span class=\"token punctuation\">(<\/span>actionId<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>    <span class=\"token keyword\">case<\/span> WEBKIT_CONTEXT_MENU_ACTION_RELOAD<span class=\"token operator\">:<\/span><br \/>        <span class=\"token function\">webkit_web_view_reload<\/span><span class=\"token punctuation\">(<\/span>webView<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>        <span class=\"token keyword\">break<\/span><span class=\"token punctuation\">;<\/span><br \/>    <span class=\"token keyword\">case<\/span> WEBKIT_CONTEXT_MENU_ACTION_COPY<span class=\"token operator\">:<\/span><br \/>        <span class=\"token function\">webkit_web_view_execute_editing_command<\/span><span class=\"token punctuation\">(<\/span>webView<span class=\"token punctuation\">,<\/span> <span class=\"token string\">\"Copy\"<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>        <span class=\"token keyword\">break<\/span><span class=\"token punctuation\">;<\/span><br \/>    <span class=\"token keyword\">case<\/span> WEBKIT_CONTEXT_MENU_ACTION_OPEN_LINK<span class=\"token operator\">:<\/span><br \/>        <span class=\"token function\">webkit_web_view_load_uri<\/span><span class=\"token punctuation\">(<\/span>webView<span class=\"token punctuation\">,<\/span><br \/>            <span class=\"token function\">webkit_hit_test_result_get_link_uri<\/span><span class=\"token punctuation\">(<\/span>savedHitTestResult<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>        <span class=\"token keyword\">break<\/span><span class=\"token punctuation\">;<\/span><br \/>    <span class=\"token comment\">\/* ... more actions ... *\/<\/span><br \/>    <span class=\"token punctuation\">}<\/span><br \/><span class=\"token punctuation\">}<\/span><\/code><\/pre>\n<h2 id=\"demo\" tabindex=\"-1\">Demo <a class=\"header-anchor\" href=\"https:\/\/blogs.igalia.com\/klee\/building-a-custom-html-context-menu-with-the-new-wpeplatform-api\/\">#<\/a><\/h2>\n<p>Here is the WPEPlatformLauncher in action, showing the HTML context menu with various actions:<\/p>\n<img src=\"https:\/\/blogs.igalia.com\/klee\/blog\/wpeplatform-launcher-context-menu\/context-menu-demo.gif\" alt=\"WPEPlatformLauncher context menu demo\" \/>\n<p><em>Right-clicking shows the HTML context menu. Clicking \u201cReload\u201d triggers an actual page reload.<\/em><\/p>\n<img src=\"https:\/\/blogs.igalia.com\/klee\/blog\/wpeplatform-launcher-context-menu\/context-menu-link-demo.gif\" alt=\"Context menu on a link\" \/>\n<p><em>Right-clicking a link shows link-specific actions like \u201cOpen Link\u201d and \u201cCopy Link Address\u201d.<\/em><\/p>\n<h2 id=\"building-and-running\" tabindex=\"-1\">Building and Running <a class=\"header-anchor\" href=\"https:\/\/blogs.igalia.com\/klee\/building-a-custom-html-context-menu-with-the-new-wpeplatform-api\/\">#<\/a><\/h2>\n<p>I built and ran the WPEPlatformLauncher inside a container using the <a href=\"https:\/\/github.com\/Igalia\/webkit-container-sdk\">WebKit Container SDK<\/a>, which provides a pre-configured development environment with all the dependencies needed to build WPE WebKit.<\/p>\n<p>The WPEPlatformLauncher integrates into the WebKit build system:<\/p>\n<pre class=\"language-bash\" tabindex=\"0\"><code class=\"language-bash\"><span class=\"token comment\"># Build WPE WebKit with the launcher<\/span><br \/>Tools\/Scripts\/build-webkit <span class=\"token parameter variable\">--wpe<\/span> <span class=\"token parameter variable\">--release<\/span><br \/><br \/><span class=\"token comment\"># Run<\/span><br \/>.\/WebKitBuild\/WPE\/Release\/bin\/WPEPlatformLauncher https:\/\/wpewebkit.org<br \/><br \/><span class=\"token comment\"># Run in fullscreen (kiosk mode)<\/span><br \/>.\/WebKitBuild\/WPE\/Release\/bin\/WPEPlatformLauncher <span class=\"token parameter variable\">--fullscreen<\/span> https:\/\/your-app.com<\/code><\/pre>\n<p>The full source is a single <code>main.cpp<\/code> file (~600 lines including the context menu), integrated into the WebKit tree alongside MiniBrowser:<\/p>\n<pre><code>WebKit\/Tools\/\n\u251c\u2500\u2500 MiniBrowser\/wpe\/          \u2190 Existing (supports both old + new API)\n\u251c\u2500\u2500 WPEPlatformLauncher\/      \u2190 New (WPEPlatform API only)\n\u2502   \u251c\u2500\u2500 main.cpp\n\u2502   \u2514\u2500\u2500 CMakeLists.txt\n\u2514\u2500\u2500 PlatformWPE.cmake         \u2190 Modified to add WPEPlatformLauncher\n<\/code><\/pre>\n<h2 id=\"summary\" tabindex=\"-1\">Summary <a class=\"header-anchor\" href=\"https:\/\/blogs.igalia.com\/klee\/building-a-custom-html-context-menu-with-the-new-wpeplatform-api\/\">#<\/a><\/h2>\n<p>The new <strong>WPEPlatform API<\/strong> makes building WPE WebKit applications significantly simpler:<\/p>\n<ul>\n<li><strong>No manual backend setup<\/strong> \u2014 the platform is detected and configured automatically<\/li>\n<li><strong>GObject-based<\/strong> \u2014 signals, properties, and ref counting instead of C function pointers<\/li>\n<li><strong>DMA-BUF direct sharing<\/strong> \u2014 no dependency on Mesa\u2019s deprecated EGL extensions<\/li>\n<li><strong>Unified window management<\/strong> \u2014 fullscreen, maximize, minimize, resize, and title<\/li>\n<li><strong>Language binding friendly<\/strong> \u2014 works with Python, JavaScript, and more via GObject Introspection<\/li>\n<\/ul>\n<p>For embedded browser developers building kiosk UIs, set-top box interfaces, or digital signage with WPE WebKit \u2014 now is the time to adopt the new API. The stable release is coming in September 2026, and the legacy stack (<code>libwpe<\/code>, <code>wpebackend-fdo<\/code>, Cog) will be deprecated at that point.<\/p>\n<h2 id=\"resources\" tabindex=\"-1\">Resources <a class=\"header-anchor\" href=\"https:\/\/blogs.igalia.com\/klee\/building-a-custom-html-context-menu-with-the-new-wpeplatform-api\/\">#<\/a><\/h2>\n<ul>\n<li><a href=\"https:\/\/wpewebkit.org\/\">WPE WebKit official site<\/a><\/li>\n<li><a href=\"https:\/\/wpewebkit.org\/reference\/2.51.92\/wpe-webkit-2.0\/index.html\">WPE WebKit API Reference (2.51.92)<\/a><\/li>\n<li><a href=\"https:\/\/wpewebkit.org\/reference\/2.51.92\/wpe-webkit-2.0\/class.ContextMenu.html\">WebKitContextMenu API Reference<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/kate-k-lee\/WebKit\/commit\/aed6402b267475f79ae7a8d417d18239b53be651\">WPEPlatformLauncher source code<\/a><\/li>\n<li><a href=\"https:\/\/www.igalia.com\/project\/wpe\">Igalia \u2014 WPE WebKit<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/Igalia\/cog\">Cog \u2014 WPE launcher (legacy)<\/a><\/li>\n<\/ul>        ","pubDate":"Mon, 16 Mar 2026 00:00:00 +0000"},{"title":"Igalia WebKit Team: WebKit Igalia Periodical #59","guid":"https:\/\/blogs.igalia.com\/webkit\/blog\/2026\/wip-59\/","link":"https:\/\/blogs.igalia.com\/webkit\/blog\/2026\/wip-59\/","description":"\n<p>Update on what happened in WebKit in the week from March 2 to March 9.<\/p>\n<p>\nAs part of this week's handful of news, WebKitGTK and WPE WebKit\nnow have support for Gamepad's \"VibationActuator\" property, the\nvideo decoding limit is now configurable at runtime in addition\nto build time, and an interesting fix that makes WebKit render\nfonts like other browsers by making it blend text incorrectly (!).\n<\/p>\n<h2 id=\"cross-port-cat\">Cross-Port \ud83d\udc31<\/h2>\n  <div class=\"wip-item\">\n<p>Using <code>libmanette<\/code>'s <em>rumble<\/em> support, enabled <a rel=\"external\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Gamepad\/vibrationActuator\">Gamepad <em>VibrationActuator<\/em><\/a> for <a rel=\"external\" href=\"https:\/\/commits.webkit.org\/308799@main\">WebKitGTK<\/a> and <a rel=\"external\" href=\"https:\/\/commits.webkit.org\/308792@main\">WPE WebKit<\/a>.<\/p>\n<p>With these changes, <a rel=\"external\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/GamepadHapticActuator\/playEffect\">playEffect()<\/a> can be used to play <em>dual-rumble<\/em> vibration effects.<\/p>\n  <\/div>\n<h3 id=\"multimedia-movie-camera\">Multimedia \ud83c\udfa5<\/h3>\n<div class=\"wip-description\">\n<p>GStreamer-based multimedia support for WebKit, including (but not limited to) playback, capture, WebAudio, WebCodecs, and WebRTC.<\/p>\n<\/div>\n  <div class=\"wip-item\">\n<p><code>VIDEO_DECODING_LIMIT<\/code> is now <a rel=\"external\" href=\"https:\/\/bugs.webkit.org\/show_bug.cgi?id=308969\">configurable at runtime<\/a>, in addition to build time. That will allow vendors that share a single binary build on different platforms to fine-tune their needs without a rebuild.<\/p>\n  <\/div>\n<h3 id=\"graphics-frame-photo\">Graphics \ud83d\uddbc\ufe0f<\/h3>\n  <div class=\"wip-item\">\n<p>Landed <a rel=\"external\" href=\"https:\/\/github.com\/WebKit\/WebKit\/pull\/59880\">a change<\/a> that tweaks the text rendering done with Skia. With this change, the text looks more natural now - just like in other browsers. However, this is done by blending text incorrectly as a compromise.<\/p>\n  <\/div>\n<h2 id=\"releases-package\">Releases \ud83d\udce6\ufe0f<\/h2>\n  <div class=\"wip-item\">\n<p>One more set of release candidates for the upcoming stable branch,\n<a rel=\"external\" href=\"https:\/\/webkitgtk.org\/2026\/03\/06\/webkitgtk2.51.93-released.html\">WebKitGTK 2.51.93<\/a> and\n<a rel=\"external\" href=\"https:\/\/wpewebkit.org\/release\/wpewebkit-2.51.93.html\">WPE WebKit 2.51.93<\/a>,\nhave been published. For those interested in previewing the upcoming 2.52.x\nseries this release is expected to be quite stable. Reporting <a rel=\"external\" href=\"https:\/\/bugs.webkit.org\/\">issues in Bugzilla<\/a> are,\nas usual, more than welcome.<\/p>\n  <\/div>\n<div class=\"wip-end\">\n<p>That\u2019s all for this week!<\/p>\n<\/div>        ","pubDate":"Mon, 09 Mar 2026 20:02:33 +0000"},{"title":"Igalia WebKit Team: WebKit Igalia Periodical #58","guid":"https:\/\/blogs.igalia.com\/webkit\/blog\/2026\/wip-58\/","link":"https:\/\/blogs.igalia.com\/webkit\/blog\/2026\/wip-58\/","description":"\n<p>Update on what happened in WebKit in the week from February 23 to March 2.<\/p>\n<p>\nThis installment of the periodical brings news about support\nfor Qualcomm qtivdec2 and qtivenc2 on GStreamer, GPU texture\natlas creation and replay substitution, enhancement of the scroll\ngesture in WPE, and two new releases: WebKitGTK 2.51.92 and WPE\nWebKit 2.51.92.\n<\/p>\n<h2 id=\"cross-port-cat\">Cross-Port \ud83d\udc31<\/h2>\n<h3 id=\"multimedia-movie-camera\">Multimedia \ud83c\udfa5<\/h3>\n<div class=\"wip-description\">\n<p>GStreamer-based multimedia support for WebKit, including (but not limited to) playback, capture, WebAudio, WebCodecs, and WebRTC.<\/p>\n<\/div>\n  <div class=\"wip-item\">\n<p>Work on adding support for the Qualcomm GStreamer qtivdec2 and qtivenc2 elements is on-going<\/p>\n  <\/div>\n<h3 id=\"graphics-frame-photo\">Graphics \ud83d\uddbc\ufe0f<\/h3>\n  <div class=\"wip-item\">\n<p><a rel=\"external\" href=\"https:\/\/commits.webkit.org\/308458@main\">Implemented GPU texture atlas creation and replay substitution<\/a> in the Skia painting engine on GTK\/WPE. After recording, raster images are packed into GPU atlases via <code>BitmapTexture<\/code>, with two upload paths: an optimized DMA-buf path that memory-maps GPU buffers and dispatches uploading to a dedicated worker thread, and a synchronous GL fallback using <code>BitmapTexture::updateContents()<\/code>. Atlas uploads are synchronized across workers using a countdown-latch fence. During replay, <code>SkiaReplayCanvas<\/code> intercepts raster image draws and substitutes them with atlas texture draws, mapping source coordinates into atlas space.<\/p>\n  <\/div>\n<h2 id=\"wpe-webkit-pager\">WPE WebKit \ud83d\udcdf<\/h2>\n<h3 id=\"wpe-platform-api-jigsaw\">WPE Platform API \ud83e\udde9<\/h3>\n<div class=\"wip-description\">\n<p>New, modern platform API that supersedes usage of libwpe and WPE backends.<\/p>\n<\/div>\n  <div class=\"wip-item\">\n<p>The recent WPE WebKit 2.51.92 release is the first one to have its <a rel=\"external\" href=\"https:\/\/wpewebkit.org\/reference\/2.51.92\/wpe-platform-2.0\/\">WPEPlatform documentation online<\/a>, but it was not included in the tarball. This issue <a rel=\"external\" href=\"https:\/\/commits.webkit.org\/308408@main\">has been corrected<\/a> and tarballs for future releases  will also include this documentation.<\/p>\n  <\/div>\n  <div class=\"wip-item\">\n<p>Scrolling using touch input with WPEPlatform would result in scrolling faster when more than one touch point was in effect. The gesture detector <a rel=\"external\" href=\"https:\/\/commits.webkit.org\/308271@main\">has been fixed<\/a> to make scrolling have always a consistent speed.<\/p>\n  <\/div>\n<h2 id=\"releases-package\">Releases \ud83d\udce6\ufe0f<\/h2>\n  <div class=\"wip-item\">\n<p>The third \u2014and likely the last\u2014 release candidates for the upcoming stable branch, <a rel=\"external\" href=\"https:\/\/webkitgtk.org\/2026\/02\/27\/webkitgtk2.51.92-released.html\">WebKitGTK 2.51.92<\/a> and <a rel=\"external\" href=\"https:\/\/wpewebkit.org\/release\/wpewebkit-2.51.92.html\">WPE WebKit 2.51.92<\/a>, have been published. For those interested in previewing the upcoming 2.52.x series this release is expected to be quite stable; but there might be still some rough edges. Reporting <a rel=\"external\" href=\"https:\/\/bugs.webkit.org\/\">issues in Bugzilla<\/a> are, as usual, more than welcome.<\/p>\n  <\/div>\n<div class=\"wip-end\">\n<p>That\u2019s all for this week!<\/p>\n<\/div>        ","pubDate":"Mon, 02 Mar 2026 20:11:00 +0000"},{"title":"Igalia WebKit Team: WebKit Igalia Periodical #57","guid":"https:\/\/blogs.igalia.com\/webkit\/blog\/2026\/wip-57\/","link":"https:\/\/blogs.igalia.com\/webkit\/blog\/2026\/wip-57\/","description":"\n<p>Update on what happened in WebKit in the week from February 9 to February 23.<\/p>\n<p>\nIn this week we have a nice fix for video streams timestamps, a fix\nfor a PDF rendering regression, support for rendering video buffers\nprovided by Qualcomm video decoders, and a fix for a font selection\nissue. Also notable we had a new WPE Android release, and the libsoup\n3.6.6 release.\n<\/p>\n<h2 id=\"cross-port-cat\">Cross-Port \ud83d\udc31<\/h2>\n  <div class=\"wip-item\">\n<p>Added a <a rel=\"external\" href=\"https:\/\/commits.webkit.org\/307348@main\">new <code>webkit_feature_list_find()<\/code> convenience function<\/a> to the public API, which searches for a <a rel=\"external\" href=\"https:\/\/webkitgtk.org\/reference\/webkitgtk\/2.51.91\/struct.Feature.html\">WebKitFeature<\/a> given its identifier.<\/p>\n  <\/div>\n<h3 id=\"multimedia-movie-camera\">Multimedia \ud83c\udfa5<\/h3>\n<div class=\"wip-description\">\n<p>GStreamer-based multimedia support for WebKit, including (but not limited to) playback, capture, WebAudio, WebCodecs, and WebRTC.<\/p>\n<\/div>\n  <div class=\"wip-item\">\n<p><a rel=\"external\" href=\"https:\/\/commits.webkit.org\/307359@main\">Opportunistically fix decoding timestamps to prevent deletion of preexisting samples when PTS doesn't conflict<\/a>, fixing potential glitches when inserting videos (eg: ad insertion).<\/p>\n  <\/div>\n<h3 id=\"graphics-frame-photo\">Graphics \ud83d\uddbc\ufe0f<\/h3>\n  <div class=\"wip-item\">\n<p><a rel=\"external\" href=\"https:\/\/commits.webkit.org\/308033@main\">Fixed<\/a> a <a rel=\"external\" href=\"https:\/\/bugs.webkit.org\/show_bug.cgi?id=306621\">PDF rendering regression<\/a> caused by the canvas 2D operation recording feature, where switching between the recording canvas and the GPU surface canvas failed to preserve the full save\/restore nesting, clip stack, and transparency layer state. Replaced the fragile state-copying approach with a state replay mechanism in GraphicsContextSkia that tracks the full sequence of save restore, clip, and transparency layer operations, then reconstructs the exact nesting on the target canvas when flushing a recording.<\/p>\n  <\/div>\n  <div class=\"wip-item\">\n<p><a rel=\"external\" href=\"https:\/\/commits.webkit.org\/307174@main\">Added support<\/a> for rendering video buffers provided by Qualcomm hardware-accelerated decoders, with aid from the <a rel=\"external\" href=\"https:\/\/registry.khronos.org\/OpenGL\/extensions\/EXT\/EXT_YUV_target.txt\">EXT_YUV_target<\/a> OpenGL extension.<\/p>\n  <\/div>\n  <div class=\"wip-item\">\n<p><a rel=\"external\" href=\"https:\/\/commits.webkit.org\/307565@main\">Fixed<\/a> the font selection issue that the system fallback font cache mixed up different font styles.<\/p>\n  <\/div>\n<h2 id=\"releases-package\">Releases \ud83d\udce6\ufe0f<\/h2>\n  <div class=\"wip-item\">\n<p><a rel=\"external\" href=\"https:\/\/github.com\/Igalia\/wpe-android\/releases\/tag\/v0.3.2\">WPE Android 0.3.2<\/a> has been released, and prebuilt packages are available <a rel=\"external\" href=\"https:\/\/central.sonatype.com\/artifact\/org.wpewebkit.wpeview\/wpeview\/\">at the Maven Central repository<\/a>. This is a stable maintenance release which updates WPE WebKit to 2.50.5, which is the most recent stable release.<\/p>\n  <\/div>\n  <div class=\"wip-item\">\n<p><a rel=\"external\" href=\"https:\/\/gitlab.gnome.org\/GNOME\/libsoup\/-\/releases\/3.6.6\">libsoup 3.6.6<\/a> has been released with numerous bug and security fixes.<\/p>\n  <\/div>\n<div class=\"wip-end\">\n<p>That\u2019s all for this week!<\/p>\n<\/div>        ","pubDate":"Mon, 23 Feb 2026 19:52:49 +0000"},{"title":"Igalia WebKit Team: WebKit Igalia Periodical #56","guid":"https:\/\/blogs.igalia.com\/webkit\/blog\/2026\/wip-56\/","link":"https:\/\/blogs.igalia.com\/webkit\/blog\/2026\/wip-56\/","description":"\n<p>Update on what happened in WebKit in the week from February 2 to February 9.<\/p>\n<p>\nThe main event this week was FOSDEM (pun intended), which included\npresentations related to WebKit; but also we got a batch of stable\nand development releases, asynchronous scrolling work, OpenGL\nlogging, cleanups, and improving the inspector for the WPE work.\n<\/p>\n<h2 id=\"cross-port-cat\">Cross-Port \ud83d\udc31<\/h2>\n<h3 id=\"graphics-frame-photo\">Graphics \ud83d\uddbc\ufe0f<\/h3>\n  <div class=\"wip-item\">\n<p>While asynchronous scrolling for mouse wheel events was already supported,\nscrollbar layers were still being painted on the main thread. This has been\n<a rel=\"external\" href=\"https:\/\/commits.webkit.org\/306838@main\">changed<\/a> to paint scrollbars on the\nscrolling thread instead, which avoids scrollbars to \u201clag\u201d behind scrolled\ncontent.<\/p>\n  <\/div>\n  <div class=\"wip-item\">\n<p><a rel=\"external\" href=\"https:\/\/commits.webkit.org\/306987@main\">Fixed<\/a> flickering caused by the\ncombination of damage tracking and asynchronous scrolling for mouse wheel\nevents.<\/p>\n  <\/div>\n  <div class=\"wip-item\">\n<p>It is now possible to <a rel=\"external\" href=\"https:\/\/commits.webkit.org\/306778@main\">enable debug logging for OpenGL\ncontexts<\/a> using the new <code>GLContext<\/code> log\nchannel, which takes advantage of the message events produced by the\n<a rel=\"external\" href=\"https:\/\/wikis.khronos.org\/opengl\/Debug_Output\">widespread KHR_debug\nextension<\/a>.<\/p>\n<p>Figuring out the exact location inside WebKit that triggered an OpenGL issue\nmay still be challenging with this aid, and therefore <a rel=\"external\" href=\"https:\/\/commits.webkit.org\/306862@main\">a backtrace will be\nappended<\/a> in case of errors to help\npinpoint the source, when the log channel is enabled at the \u201cdebug\u201d level with\n<code>GLContext=debug<\/code>.<\/p>\n  <\/div>\n  <div class=\"wip-item\">\n<p>Configuring the build with <code>USE_SKIA=OFF<\/code> to make WebKit use the\n<a rel=\"external\" href=\"https:\/\/cairographics.org\/\">Cairo<\/a> graphics library <a rel=\"external\" href=\"https:\/\/commits.webkit.org\/306343@main\">is no longer\nsupported<\/a>. Using\n<a rel=\"external\" href=\"https:\/\/skia.org\">Skia<\/a> has been the default <a rel=\"external\" href=\"https:\/\/blogs.igalia.com\/carlosgc\/2024\/09\/27\/graphics-improvements-in-webkitgtk-and-wpewebkit-2-46\/\">since  late\n2024<\/a>,\nand after two full years the 2.54.0 release (due in September 2026)\nwill be the first one where the choice is no longer possible.<\/p>\n  <\/div>\n<h2 id=\"webkitgtk-desktop\">WebKitGTK \ud83d\udda5\ufe0f<\/h2>\n  <div class=\"wip-item\">\n<p>The \u201con demand\u201d hardware acceleration policy has been rarely used lately, and\nthus support for it has been <a rel=\"external\" href=\"https:\/\/commits.webkit.org\/306855@main\">removed<\/a>.\nNote that this affects only the GTK port when built with GTK 3\u2014the option never\nexisted when using GTK 4.<\/p>\n<p>Existing GTK 3 applications that use\n<code>WEBKIT_HARDWARE_ACCELERATION_POLICY_ON_DEMAND<\/code> will continue to work and do\n<strong>not<\/strong> need rebuilding: they will be promoted to use the \u201calways enabled\u201d policy\nstarting with WebKitGTK 2.54.0 (due in September 2026).<\/p>\n  <\/div>\n<h2 id=\"wpe-webkit-pager\">WPE WebKit \ud83d\udcdf<\/h2>\n  <div class=\"wip-item\">\n<p>The Web Inspector <a rel=\"external\" href=\"https:\/\/commits.webkit.org\/306914@main\">has received\nsupport<\/a> for saving data to local\nfiles, allowing things such as saving page resources or exporting the network\nsession to a <a rel=\"external\" href=\"https:\/\/en.wikipedia.org\/wiki\/HAR_(file_format)\">HAR archive<\/a>.<\/p>\n<p>Note that using the Web Inspector locally is supported when using the\nWPEPlatform API, and the keyboard shortcut <kbd title=\"Control + Shift + I\">Ctrl+Shift+I<\/kbd> may be used to bring it up.<\/p>\n  <\/div>\n<h2 id=\"releases-package\">Releases \ud83d\udce6\ufe0f<\/h2>\n  <div class=\"wip-item\">\n<p><a rel=\"external\" href=\"https:\/\/webkitgtk.org\/2026\/02\/09\/webkitgtk2.50.5-released.html\">WebKitGTK\n2.50.5<\/a> and\n<a rel=\"external\" href=\"https:\/\/wpewebkit.org\/release\/wpewebkit-2.50.5.html\">WPE WebKit 2.50.5<\/a> have\nbeen released. These are stable maintenance releases that improves stability,\ncorrect bugs, and fixes small rendering issues.<\/p>\n<p>The second release candidates for the upcoming stable branch, <a rel=\"external\" href=\"https:\/\/webkitgtk.org\/2026\/02\/06\/webkitgtk2.51.91-released.html\">WebKitGTK\n2.51.91<\/a> and\n<a rel=\"external\" href=\"https:\/\/wpewebkit.org\/release\/wpewebkit-2.51.91.html\">WPE WebKit 2.51.91<\/a>,\nhave been published as well. Those using those to preview the upcoming 2.52.x\nseries are encouraged to provide <a rel=\"external\" href=\"https:\/\/bugs.webkit.org\/\">bug reports in\nBugzilla<\/a> for any issue they may experience.<\/p>\n  <\/div>\n<h2 id=\"community-events-handshake\">Community &amp; Events \ud83e\udd1d<\/h2>\n  <div class=\"wip-item\">\n<p>We have published a <a rel=\"external\" href=\"https:\/\/blogs.igalia.com\/compilers\/2026\/02\/02\/implementing-the-temporal-proposal-in-javascriptcore\/\">blog\npost<\/a>\non our work implementing the\n<a rel=\"external\" href=\"https:\/\/tc39.es\/proposal-temporal\/docs\/\">Temporal<\/a> proposal in JavaScriptCore,\nWebKit's JavaScript engine.<\/p>\n  <\/div>\n  <div class=\"wip-item\">\n<p>This year's edition of <a rel=\"external\" href=\"https:\/\/fosdem.org\/2026\/\">FOSDEM<\/a> took place in\nBrussels between January 31st and February 1st, and featured a number of\nsessions related to WebKitGTK and WPE:<\/p>\n<ul>\n<li><a rel=\"external\" href=\"https:\/\/fosdem.org\/2026\/schedule\/event\/8ZL9BZ-web-platform-on-linux-devices-with-webkit\/\">The Web Platform on Linux devices with WebKit: where are we\nnow?<\/a>,\nby Mario S\u00e1nchez, is a good introduction-level talk about the GTK and WPE\nWebKit ports.<\/li>\n<li><a rel=\"external\" href=\"https:\/\/fosdem.org\/2026\/schedule\/event\/KMMLGM-webrtc_support_in_webkitgtk_and_wpewebkit_with_gstreamer_current_status_and_plan\/\">WebRTC support in WebKitGTK and WPEWebKit with GStreamer: Current status and\nplans<\/a>\nby Philippe Normand. Exactly what it says on the tin.<\/li>\n<li><a rel=\"external\" href=\"https:\/\/fosdem.org\/2026\/schedule\/event\/NJM3KB-mathml-core\/\">Interop and MathML\nCore<\/a> by Eri\nPazos, about the ongoing effort to improve how different Web engines handle\nMathML\u2014including WebKit!<\/li>\n<\/ul>\n<p>The videos for the talks are already available, too.<\/p>\n  <\/div>\n<div class=\"wip-end\">\n<p>That\u2019s all for this week!<\/p>\n<\/div>        ","pubDate":"Mon, 09 Feb 2026 23:21:30 +0000"},{"title":"Igalia WebKit Team: WebKit Igalia Periodical #55","guid":"https:\/\/blogs.igalia.com\/webkit\/blog\/2026\/wip-55\/","link":"https:\/\/blogs.igalia.com\/webkit\/blog\/2026\/wip-55\/","description":"\n<p>Update on what happened in WebKit in the week from January 26 to February 2.<\/p>\n<p>\nA calm week for sure! The highlight this week is the fix for scrolling not starting when the main thread is blocked.\n<\/p>\n<h2 id=\"cross-port-cat\">Cross-Port \ud83d\udc31<\/h2>\n<h3 id=\"graphics-frame-photo\">Graphics \ud83d\uddbc\ufe0f<\/h3>\n  <div class=\"wip-item\">\n<p><a rel=\"external\" href=\"https:\/\/commits.webkit.org\/306396@main\">Fixed<\/a> the problem of wheel event async scrolling doesn't start while the main thread is blocked. This should make WebKit feel more responsive even on heavier websites.<\/p>\n  <\/div>\n<div class=\"wip-end\">\n<p>That\u2019s all for this week!<\/p>\n<\/div>        ","pubDate":"Mon, 02 Feb 2026 20:11:18 +0000"},{"title":"Igalia WebKit Team: WebKit Igalia Periodical #54","guid":"https:\/\/blogs.igalia.com\/webkit\/blog\/2026\/wip-54\/","link":"https:\/\/blogs.igalia.com\/webkit\/blog\/2026\/wip-54\/","description":"\n<p>Update on what happened in WebKit in the week from January 19 to January 26.<\/p>\n<p>\nThe main event this week has been the creation of the branch for the upcoming stable series, accompanied by the first release candidate before 2.52.0. But there's more: the WPE port gains hyphenation support and the ability to notify of graphics buffer changes; both ports get graphics fixes and a couple of new Web features, and WPE-Android also gets a new stable release.\n<\/p>\n<h2 id=\"cross-port-cat\">Cross-Port \ud83d\udc31<\/h2>\n  <div class=\"wip-item\">\n<p><a rel=\"external\" href=\"https:\/\/commits.webkit.org\/305917@main\">Implemented<\/a> support for the <code>:open<\/code>\npseudo-class on dialog and details elements. This is currently behind the\n<code>OpenPseudoClass<\/code> feature flag.<\/p>\n  <\/div>\n  <div class=\"wip-item\">\n<p><a rel=\"external\" href=\"https:\/\/commits.webkit.org\/306152@main\">Implemented<\/a> the <code>source<\/code> property for\n<code>ToggleEvent<\/code>. This can be used to run code dependent on the triggering element\nin response to a popover or dialog toggle.<\/p>\n  <\/div>\n<h3 id=\"graphics-frame-photo\">Graphics \ud83d\uddbc\ufe0f<\/h3>\n  <div class=\"wip-item\">\n<p><a rel=\"external\" href=\"https:\/\/commits.webkit.org\/306119@main\">Fixed<\/a> the rendering glitches with\nwheel event asynchronous scrolling, which occurred when the page was scrolled\nto areas not covered by tiles while the main thread was blocked.<\/p>\n  <\/div>\n<h2 id=\"wpe-webkit-pager\">WPE WebKit \ud83d\udcdf<\/h2>\n  <div class=\"wip-item\">\n<p>Support for\n<a rel=\"external\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/CSS\/Reference\/Properties\/hyphens\">hyphenation<\/a>\nhas been <a rel=\"external\" href=\"https:\/\/commits.webkit.org\/305816@main\">added to WPE<\/a>. This requires\n<code>libhyphen<\/code> and can be disabled at build-time with the <code>USE_LIBHYPHEN=OFF<\/code>\nCMake option.<\/p>\n  <\/div>\n<h3 id=\"wpe-platform-api-jigsaw\">WPE Platform API \ud83e\udde9<\/h3>\n<div class=\"wip-description\">\n<p>New, modern platform API that supersedes usage of libwpe and WPE backends.<\/p>\n<\/div>\n  <div class=\"wip-item\">\n<p>WPEPlatform <a rel=\"external\" href=\"https:\/\/commits.webkit.org\/306008@main\">gained support<\/a> to notify\nchanges in the configuration of graphics buffers allocated to render the\ncontents of a web view, either by handling the <code>WPEView::buffers-changed<\/code>\nsignal or by overriding the <code>WPEViewClass.buffers_changed<\/code> virtual function.\nThis feature is mainly useful for platform implementations which may need to\nperform additional setup in advance, before updated web view contents are\nprovided in the buffers configured by WebKit.<\/p>\n  <\/div>\n<h2 id=\"releases-package\">Releases \ud83d\udce6\ufe0f<\/h2>\n  <div class=\"wip-item\">\n<p><a rel=\"external\" href=\"https:\/\/github.com\/Igalia\/wpe-android\/releases\/tag\/v0.3.1\">WPE-Android 0.3.0<\/a>\nhas been released, and prebuilt packages are available <a rel=\"external\" href=\"https:\/\/central.sonatype.com\/artifact\/org.wpewebkit.wpeview\/wpeview\/\">at the Maven Central\nrepository<\/a>.\nThe main change in this this version is the update to WPE WebKit 2.50.4, which\nis the most recent stable release.<\/p>\n  <\/div>\n  <div class=\"wip-item\">\n<p><a rel=\"external\" href=\"https:\/\/github.com\/WebKit\/WebKit\/commits\/webkitglib\/2.52\">A new branch has been\ncreated<\/a> for the\nupcoming 2.52.x stable release series of the GTK and WPE WebKit ports. The\nfirst release candidates from this branch, <a rel=\"external\" href=\"https:\/\/webkitgtk.org\/2026\/01\/23\/webkitgtk2.51.90-released.html\">WebKitGTK\n2.51.90<\/a> and\n<a rel=\"external\" href=\"https:\/\/wpewebkit.org\/release\/wpewebkit-2.51.90.html\">WPE WebKit 2.51.90<\/a> are\nnow available. Testing and <a rel=\"external\" href=\"https:\/\/bugs.webkit.org\">issue reports in Bugzilla<\/a>\nare welcome to help with stabilization before the first stable release, which\nis planned for mid-March.<\/p>\n  <\/div>\n<div class=\"wip-end\">\n<p>That\u2019s all for this week!<\/p>\n<\/div>        ","pubDate":"Mon, 26 Jan 2026 21:00:55 +0000"},{"title":"Enrique Oca\u00f1a: Igalia Multimedia contributions in 2025","guid":"https:\/\/eocanha.org\/blog\/?p=701","link":"https:\/\/eocanha.org\/blog\/2026\/01\/26\/igalia-multimedia-contributions-in-2025\/","description":"\n<p>Now that 2025 is over, it&#8217;s time to look back and feel proud of the path we&#8217;ve walked. Last year has been really exciting in terms of contributions to GStreamer and WebKit for the Igalia Multimedia team.<\/p>\n\n\n\n<p>With more than 459 contributions along the year, we&#8217;ve been one of the top contributors to the GStreamer project, in areas like Vulkan Video, GstValidate, VA, GStreamer Editing Services, WebRTC or H.266 support.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/eocanha.org\/blog\/wp-content\/uploads\/2026\/01\/gstreamer-contributions.jpg\"><img width=\"943\" height=\"530\" src=\"https:\/\/eocanha.org\/blog\/wp-content\/uploads\/2026\/01\/gstreamer-contributions.jpg\" alt=\"Pie chart of Igalia's contributions to different areas of the GStreamer project:\nother (30%)\nvulkan (24%)\nvalidate (7%)\nva (6%)\nges (4%)\nwebrtc (3%)\nh266parse (3%)\npython (3%)\ndots-viewer (3%)\ntests (2%)\ndocs (2%)\ndevtools (2%)\nwebrtcbin (1%)\ntracers (1%)\nqtdemux (1%)\ngst (1%)\nci (1%)\ny4menc (1%)\nvideorate (1%)\ngl (1%)\nalsa (1%)\" class=\"wp-image-706\" \/><\/a><figcaption>Igalia&#8217;s contributions to the GStreamer project<\/figcaption><\/figure>\n\n\n\n<p>In Vulkan Video we&#8217;ve worked on the VP9 video decoder, and cooperated with other contributors to push the AV1 decoder as well. There&#8217;s now an H.264 base class for video encoding that is designed to support general hardware-accelerated processing.<\/p>\n\n\n\n<p>GStreaming Editing Services, the framework to build video editing applications, has gained time remapping support, which now allows to include fast\/slow motion effects in the videos. Video transformations (scaling, cropping, rounded corners, etc) are now hardware-accelerated thanks to the addition of new Skia-based GStreamer elements and integration with OpenGL. Buffer pool tuning and pipeline improvements have helped to optimize memory usage and performance, enabling the edition of 4K video at 60 frames per second. Much of this work to improve and ensure quality in GStreamer Editing Services has also brought improvements in the GstValidate testing framework, which will be useful for other parts of GStreamer.<\/p>\n\n\n\n<p>Regarding H.266 (VVC), full playback support (with decoders such as <code>vvdec<\/code> and <code>avdec_h266<\/code>, demuxers and muxers for Matroska, MP4 and TS, and parsers for the <code>vvc1<\/code> and <code>vvi1<\/code> formats) is now available in GStreamer 1.26 thanks to Igalia&#8217;s work. This allows user applications such as the WebKitGTK web browser to leverage the hardware accelerated decoding provided by VAAPI to play H.266 video using GStreamer.<\/p>\n\n\n\n<p>Igalia has also been one of the top contributors to GStreamer Rust, with 43 contributions. Most of the commits there have been related to Vulkan Video.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/eocanha.org\/blog\/wp-content\/uploads\/2026\/01\/gstreamer-rs-contributions.jpg\"><img width=\"943\" height=\"530\" src=\"https:\/\/eocanha.org\/blog\/wp-content\/uploads\/2026\/01\/gstreamer-rs-contributions.jpg\" alt=\"Pie chart of Igalia's contributions to different areas of the GStreamer Rust project:\nvulkan (28%)\nother (26%)\ngstreamer (12%)\nci (12%)\ntracer (7%)\nvalidate (5%)\nges (7%)\nexamples (5%)\" class=\"wp-image-708\" \/><\/a><figcaption>Igalia&#8217;s contributions to the GStreamer Rust project<\/figcaption><\/figure>\n\n\n\n<p>In addition to GStreamer, the team also has a strong presence in WebKit, where we leverage our GStreamer knowledge to implement many features of the web engine related to multimedia. From the 1739 contributions to the WebKit project done last year by Igalia, the Multimedia team has made 323 of them. Nearly one third of those have been related to generic multimedia playback, and the rest have been on areas such as WebRTC, MediaStream, MSE, WebAudio, a new Quirks system to provide adaptations for specific hardware multimedia platforms at runtime, WebCodecs or MediaRecorder.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/eocanha.org\/blog\/wp-content\/uploads\/2026\/01\/webkit-contributions.jpg\"><img width=\"943\" height=\"530\" src=\"https:\/\/eocanha.org\/blog\/wp-content\/uploads\/2026\/01\/webkit-contributions.jpg\" alt=\"Pie chart of Igalia's contributions to different areas of the WebKit project:\nGeneric Gstreamer work (33%)\nWebRTC (20%)\nRegression bugfixing (9%)\nOther (7%)\nMSE (6%)\nBuildStream SDK (4%)\nMediaStream (3%)\nWPE platform (3%)\nWebAudio (3%)\nWebKitGTK platform (2%)\nQuirks (2%)\nMediaRecorder (2%)\nEME (2%)\nGlib (1%)\nWTF (1%)\nWebCodecs (1%)\nGPUProcess (1%)\nStreams (1%) \" class=\"wp-image-709\" \/><\/a><figcaption>Igalia Multimedia Team&#8217;s contributions to different areas of the WebKit project<\/figcaption><\/figure>\n\n\n\n<p>We&#8217;re happy about what we&#8217;ve achieved along the year and look forward to maintaining this success and bringing even more exciting features and contributions in 2026.<\/p>        ","pubDate":"Mon, 26 Jan 2026 09:34:37 +0000"},{"title":"Igalia WebKit Team: WebKit Igalia Periodical #53","guid":"https:\/\/blogs.igalia.com\/webkit\/blog\/2026\/wip-53\/","link":"https:\/\/blogs.igalia.com\/webkit\/blog\/2026\/wip-53\/","description":"\n<p>Update on what happened in WebKit in the week from December 26 to January 19.<\/p>\n<p>\nWe're back! The first periodical of 2026 brings you performance optimizations, improvements to the memory footprint calculation, new APIs, the removal of the legacy Qt5 WPE backend, and as always, progress on JSC's Temporal implementation.\n<\/p>\n<h2 id=\"cross-port-cat\">Cross-Port \ud83d\udc31<\/h2>\n  <div class=\"wip-item\">\n<p>The memory footprint calculation mechanism <a rel=\"external\" href=\"https:\/\/github.com\/WebKit\/WebKit\/pull\/56493\">has been unified<\/a> across GTK, JSC, and WPE ports. Therefore, the expensive <code>\/proc\/self\/smaps<\/code> is not used anymore and the WPE uses <code>\/proc\/self\/statm<\/code> with extra cache now to prevent frequent file reading.<\/p>\n  <\/div>\n  <div class=\"wip-item\">\n<p><a rel=\"external\" href=\"https:\/\/commits.webkit.org\/305444@main\">Added<\/a> a new <code>webkit_context_menu_get_position()<\/code> function to the API that allows obtaining the pointer coordinates, relative to the web view origin, at the moment when a context menu was triggered.<\/p>\n<p>Additionally, behaviour of context menus <a rel=\"external\" href=\"https:\/\/commits.webkit.org\/305461@main\">has been made more consistent<\/a> between the GTK and WPE ports, and handling of <code>GAction<\/code> objects attached to menu items has been <a rel=\"external\" href=\"https:\/\/commits.webkit.org\/305267@main\">rewritten<\/a> and <a rel=\"external\" href=\"https:\/\/commits.webkit.org\/305504@main\">improved<\/a> with the goal of better supporting context menus in the WPE port.<\/p>\n  <\/div>\n<h3 id=\"javascriptcore-fish\">JavaScriptCore \ud83d\udc1f<\/h3>\n<div class=\"wip-description\">\n<p>The built-in JavaScript\/ECMAScript engine for WebKit, also known as JSC or SquirrelFish.<\/p>\n<\/div>\n  <div class=\"wip-item\">\n<p>In JavaScriptCore's implementation of Temporal, <a rel=\"external\" href=\"https:\/\/github.com\/WebKit\/WebKit\/pull\/56210\/\">fixed a bug<\/a> in <code>Temporal.PlainTime.from<\/code> that read options in the wrong order, which caused a test262 test to fail.<\/p>\n  <\/div>\n  <div class=\"wip-item\">\n<p>In JavaScriptCore's implementation of Temporal, <a rel=\"external\" href=\"https:\/\/github.com\/WebKit\/WebKit\/pull\/56460\">fixed several bugs<\/a> in <code>PlainYearMonth<\/code> methods and enabled all <code>PlainYearMonth<\/code> tests that don't depend on the <code>Intl<\/code> object. This completes the implementation of Temporal <code>PlainYearMonth<\/code> objects in JSC.<\/p>\n  <\/div>\n<h3 id=\"graphics-frame-photo\">Graphics \ud83d\uddbc\ufe0f<\/h3>\n  <div class=\"wip-item\">\n<p>In WebKit's Skia graphics backend, <a rel=\"external\" href=\"https:\/\/commits.webkit.org\/304898@main\">fixed GrDirectContext management<\/a> for GPU resources. Operations on GPU-backed resources must use the context that created them, not the current thread's context. The fix stores <code>GrDirectContext<\/code> at creation time for <code>NativeImage<\/code> and uses <code>surface-&gt;recordingContext()-&gt;asDirectContext()<\/code> for SkSurface, correcting multiple call sites that previously used the shared display's context incorrectly.<\/p>\n  <\/div>\n  <div class=\"wip-item\">\n<p>Damage propagation <a rel=\"external\" href=\"https:\/\/github.com\/WebKit\/WebKit\/pull\/55697\">has been added<\/a> to the recently-added, non-composited mode in WPE.<\/p>\n  <\/div>\n  <div class=\"wip-item\">\n<p>In WebKit's Skia graphics backend for GTK\/WPE, <a rel=\"external\" href=\"https:\/\/commits.webkit.org\/305273@main\">added canvas 2D operation recording<\/a> for GPU-accelerated rendering. Instead of executing drawing commands immediately, operations are recorded into an <code>SkPicture<\/code> and replayed in batch when the canvas contents are needed, reducing GPU state change overhead for workloads with many small drawing operations, improving the MotionMark <em>Canvas Lines<\/em> performance on embedded devices with low-end tiled GPUs.<\/p>\n  <\/div>\n<h2 id=\"wpe-webkit-pager\">WPE WebKit \ud83d\udcdf<\/h2>\n  <div class=\"wip-item\">\n<p>Due to Qt5 not receiving maintenance since mid-2025, the WPE Qt5 binding that used the legacy libwpe API <a rel=\"external\" href=\"https:\/\/commits.webkit.org\/305824@main\">has been removed<\/a> from the tree. The Qt6 binding <a rel=\"external\" href=\"https:\/\/github.com\/WebKit\/WebKit\/tree\/main\/Source\/WebKit\/UIProcess\/API\/wpe\/qt6\">remains part of the source tree<\/a>, which is a better alternative that allows using supported Qt versions, and is built atop the new WPEPlatform API, making it a future-proof option. The WPE Qt API may be enabled when configuring the build with CMake, using the <code>ENABLE_WPE_QT_API<\/code> option.<\/p>\n  <\/div>\n<h3 id=\"wpe-platform-api-jigsaw\">WPE Platform API \ud83e\udde9<\/h3>\n<div class=\"wip-description\">\n<p>New, modern platform API that supersedes usage of libwpe and WPE backends.<\/p>\n<\/div>\n  <div class=\"wip-item\">\n<p>The <code>WPEScreenSyncObserver<\/code> class has been improved to <a rel=\"external\" href=\"https:\/\/commits.webkit.org\/305509@main\">support multiple callbacks<\/a>. Instead of a single callback set with <code>wpe_screen_sync_observer_set_callback()<\/code>, clients of the API can now use <code>wpe_screen_sync_observer_add_callback()<\/code> and <code>wpe_screen_sync_observer_remove_callback()<\/code>. The observer will be paused automatically when there are no callbacks attached to it.<\/p>\n  <\/div>\n<div class=\"wip-end\">\n<p>That\u2019s all for this week!<\/p>\n<\/div>        ","pubDate":"Mon, 19 Jan 2026 19:25:32 +0000"},{"title":"Igalia WebKit Team: WebKit Igalia Periodical #52","guid":"https:\/\/blogs.igalia.com\/webkit\/blog\/2025\/wip-52\/","link":"https:\/\/blogs.igalia.com\/webkit\/blog\/2025\/wip-52\/","description":"\n<p>Update on what happened in WebKit in the week from December 16 to December 25.<\/p>\n<p>\nRight during the holiday season \ud83c\udf84, the last WIP installment of the year comes packed with new releases, a couple of functions added to the public API, cleanups, better timer handling, and improvements to MathML and WebXR support.\n<\/p>\n<h2 id=\"cross-port-cat\">Cross-Port \ud83d\udc31<\/h2>\n  <div class=\"wip-item\">\n<p><a rel=\"external\" href=\"https:\/\/github.com\/WebKit\/WebKit\/pull\/52066\">Landed support for <code>font-size: math<\/code><\/a>. Now\n<a rel=\"external\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/CSS\/Reference\/Properties\/math-depth\"><code>math-depth<\/code><\/a>\ncan automatically control the font size inside of <code>&lt;math&gt;<\/code> blocks, making\nscripts and nested content smaller to improve readability and presentation.<\/p>\n  <\/div>\n  <div class=\"wip-item\">\n<p>Two new functions <a rel=\"external\" href=\"https:\/\/commits.webkit.org\/304810@main\">have been added<\/a> to\nthe public API:<\/p>\n<ul>\n<li>\n<p><code>webkit_context_menu_item_get_gaction_target()<\/code> to obtain the <code>GVariant<\/code>\nassociated with a context menu item created from a <code>GAction<\/code>.<\/p>\n<\/li>\n<li>\n<p><code>webkit_context_menu_item_get_title()<\/code> may be used to obtain\nthe title of a context menu item.<\/p>\n<\/li><\/ul><\/div>\n<div class=\"wip-item\">\n<\/div>\n\n<p><a rel=\"external\" href=\"https:\/\/commits.webkit.org\/304553@main\">Improved timers<\/a>, by making some of\nthem use the <a rel=\"external\" href=\"https:\/\/lwn.net\/Articles\/251413\/\">timerfd API<\/a>. This reduces\ntimer \u201clateness\u201d\u2014the amount of time elapsed between the configured trigger\ntime, and the effective one\u2014, which in turn improves the perceived smoothness\nof animations thanks to steadier frame delivery timings. Systems where the\n<code>timerfd_create<\/code> and <code>timerfd_settime<\/code> functions are not available will\ncontinue working as before.<\/p>\n  \n  <div class=\"wip-item\">\n<p>On the WebXR front, support <a rel=\"external\" href=\"https:\/\/commits.webkit.org\/304631@main\">was added<\/a>\nfor  <code>XR_TRACKABLE_TYPE_DEPTH_ANDROID<\/code> through the <code>XR_ANDROID_trackables<\/code>\nextension, which allows reporting depth information for elements that take part\nin hit testing.<\/p>\n  <\/div>\n<h3 id=\"graphics-frame-photo\">Graphics \ud83d\uddbc\ufe0f<\/h3>\n  <div class=\"wip-item\">\n<p>Landed <a rel=\"external\" href=\"https:\/\/github.com\/WebKit\/WebKit\/pull\/54518\">a change<\/a> that implements\nnon-composited page rendering in the WPE port. This new mode is disabled by\ndefault, and may be activated by disabling the <code>AcceleratedCompositing<\/code> runtime\npreference. In such case, the frames are rendered using a simplified code path\nthat does not involve the internal WebKit compositor. Therefore it may offer a\nbetter performance in some specific cases on constrained embedded devices.<\/p>\n  <\/div>\n  <div class=\"wip-item\">\n<p>Since version 2.10.2, the <a rel=\"external\" href=\"https:\/\/freetype.org\">FreeType<\/a> library can be built\nwith direct support for loading fonts in the\n<a rel=\"external\" href=\"https:\/\/www.w3.org\/TR\/WOFF2\/\">WOFF2<\/a> format. Until now, the WPE and GTK WebKit\nports used <a rel=\"external\" href=\"https:\/\/github.com\/google\/woff2\">libwoff2<\/a> in an intermediate step\nto convert those fonts on-the-fly before handing them to FreeType for\nrendering. The CMake build system will now <a rel=\"external\" href=\"https:\/\/commits.webkit.org\/304864@main\">detect when FreeType supports WOFF2\ndirectly<\/a> and skip the conversion step.\nThis way, in systems which provide a suitable version of FreeType, <code>libwoff2<\/code>\nwill no longer be needed.<\/p>\n  <\/div>\n<h2 id=\"wpe-webkit-pager\">WPE WebKit \ud83d\udcdf<\/h2>\n<h3 id=\"wpe-platform-api-jigsaw\">WPE Platform API \ud83e\udde9<\/h3>\n<div class=\"wip-description\">\n<p>New, modern platform API that supersedes usage of libwpe and WPE backends.<\/p>\n<\/div>\n  <div class=\"wip-item\">\n<p>The legacy libwpe-based API <a rel=\"external\" href=\"https:\/\/commits.webkit.org\/304671@main\">can now be disabled at build\ntime<\/a>, by toggling the\n<code>ENABLE_WPE_LEGACY_API<\/code> CMake option. This allows removal of uneeded code when\nan application is exclusively using the new WPEPlatform API.<\/p>\n  <\/div>\n<h3 id=\"wpe-android-robot\">WPE Android <a rel=\"external\" href=\"https:\/\/github.com\/Igalia\/wpe-android\">\u2197<\/a>  \ud83e\udd16<\/h3>\n<div class=\"wip-description\">\n<p>Adaptation of WPE WebKit targeting the Android operating system.<\/p>\n<\/div>\n  <div class=\"wip-item\">\n<p><a rel=\"external\" href=\"https:\/\/developer.android.com\/ndk\/reference\/group\/a-hardware-buffer\">AHardwareBuffer<\/a>\nis <a rel=\"external\" href=\"https:\/\/commits.webkit.org\/304567@main\">now supported<\/a> as backing for\naccelerated graphics surfaces that can be shared across processes. This is the\nlast piece of the puzzle to use WPEPlatform on Android without involving\nexpensive operations to copy rendered frames back-and-forth between GPU and\nsystem memory.<\/p>\n  <\/div>\n<h2 id=\"releases-package\">Releases \ud83d\udce6\ufe0f<\/h2>\n  <div class=\"wip-item\">\n<p><a rel=\"external\" href=\"https:\/\/webkitgtk.org\/2025\/12\/16\/webkitgtk2.50.4-released.html\">WebKitGTK\n2.50.4<\/a> and\n<a rel=\"external\" href=\"https:\/\/wpewebkit.org\/release\/wpewebkit-2.50.4.html\">WPE WebKit 2.50.4<\/a> have\nbeen released. These stable releases include a number of important patches for\nsecurity issues, and we urge users and distributors to update to this release\nif they have not yet done it. An accompanying security advisory,\n<code>WSA-2025-0010<\/code>, has been published\n(<a rel=\"external\" href=\"https:\/\/webkitgtk.org\/security\/WSA-2025-0010.html\">GTK<\/a>,\n<a rel=\"external\" href=\"https:\/\/wpewebkit.org\/security\/WSA-2025-0010.html\">WPE<\/a>).<\/p>\n<p>Development releases of <a rel=\"external\" href=\"https:\/\/webkitgtk.org\/2025\/12\/19\/webkitgtk2.51.4-released.html\">WebKitGTK\n2.51.4<\/a> and\n<a rel=\"external\" href=\"https:\/\/wpewebkit.org\/release\/wpewebkit-2.51.4.html\">WPE WebKit 2.51.4<\/a> are\navailable as well, and may be used to preview upcoming features. As usual, bug\nreports are <a rel=\"external\" href=\"https:\/\/bugs.webkit.org\">welcome in Bugzilla<\/a>.<\/p>\n  <\/div>\n<h2 id=\"community-events-handshake\">Community &amp; Events \ud83e\udd1d<\/h2>\n  <div class=\"wip-item\">\n<p>Pawe\u0142 Lampe has published a <a rel=\"external\" href=\"https:\/\/blogs.igalia.com\/plampe\/wpe-performance-considerations-pre-rendering\/\">blog\npost<\/a>\nthat discusses various pre-rendering techniques useful in the context of using\nWPE on embedded devices.<\/p>\n  <\/div>\n<div class=\"wip-end\">\n<p>That\u2019s all for this week!<\/p>\n<\/div>        ","pubDate":"Thu, 25 Dec 2025 18:26:43 +0000"},{"title":"Pawel Lampe: WPE performance considerations: pre-rendering","guid":"https:\/\/blogs.igalia.com\/plampe\/wpe-performance-considerations-pre-rendering\/","link":"https:\/\/blogs.igalia.com\/plampe\/wpe-performance-considerations-pre-rendering\/","description":"\n<p>This article is a continuation of the series on <strong>WPE performance considerations<\/strong>. While the <a href=\"https:\/\/blogs.igalia.com\/plampe\/wpe-performance-considerations-dom-tree\/\">previous article<\/a> touched upon fairly low-level aspects of the DOM tree overhead,\nthis one focuses on more high-level problems related to managing the application\u2019s workload over time. Similarly to before, the considerations and conclusions made in this blog post are strongly related to web applications\nin the context of embedded devices, and hence the techniques presented should be used with extra care (and benchmarking) if one would like to apply those on desktop-class devices.<\/p>\n<h2 id=\"the-workload\" tabindex=\"-1\">The workload <a class=\"header-anchor\" href=\"https:\/\/blogs.igalia.com\/plampe\/wpe-performance-considerations-pre-rendering\/\">#<\/a><\/h2>\n<p>Typical web applications on embedded devices have their workloads distributed over time in various ways. In practice, however, the workload distributions can usually be fitted into one of the following categories:<\/p>\n<ol>\n<li><strong>Idle applications with occasional updates<\/strong> - the applications that present static content and are updated at very low intervals. As an example, one can think of some static dashboard that presents static content and switches\nthe page every, say, 60 seconds - such as e.g. a static departures\/arrivals dashboard on the airport.<\/li>\n<li><strong>Idle applications with frequent updates<\/strong> - the applications that present static content yet are updated frequently (or are presenting some dynamic content, such as animations occasionally). In that case, one can imagine a similar\nairport departures\/arrivals dashboard, yet with the animated page scrolling happening quite frequently.<\/li>\n<li><strong>Active applications with occasional updates<\/strong> - the applications that present some dynamic content (animations, multimedia, etc.), yet with major updates happening very rarely. An example one can think of in this case is an application\nplaying video along with presenting some metadata about it, and switching between other videos every few minutes.<\/li>\n<li><strong>Active applications with frequent updates<\/strong> - the applications that present some dynamic content and change the surroundings quite often. In this case, one can think of a stock market dashboard continuously animating the charts\nand updating the presented real-time statistics very frequently.<\/li>\n<\/ol>\n<p>Such workloads can be well demonstrated on charts plotting the browser\u2019s CPU usage over time:<\/p>\n<center>\n<source type=\"image\/avif\"><source type=\"image\/webp\"><img alt=\"Typical web application workloads.\" src=\"https:\/\/blogs.igalia.com\/plampe\/img\/obgL44nHKc-1385.png\" width=\"1385\" height=\"360\" \/>\n<\/source><\/source><\/center>\n<p>As long as the peak workload (due to updates) is small, no negative effects are perceived by the end user. However, when the peak workload is significant, some negative effects may start getting noticeable.<\/p>\n<p>In case of applications from groups (1) and (2) mentioned above, a significant peak workload may not be a problem at all. As long as there are no continuous visual changes and no interaction is allowed during updates, the end-user\nis unable to notice that the browser was not responsive or missed some frames for some period of time. In such cases, the application designer does not need to worry much about the workload.<\/p>\n<p>In other cases, especially the ones involving applications from groups (3) and (4) mentioned above, the significant peak workload may lead to visual stuttering, as any processing making the browser busy for longer than 16.6 milliseconds\nwill lead to lost frames. In such cases, the workload has to be managed in a way that the peaks are reduced either by optimizing them or distributing them over time.<\/p>\n<h4 id=\"first-step-optimization\" tabindex=\"-1\">First step: optimization <a class=\"header-anchor\" href=\"https:\/\/blogs.igalia.com\/plampe\/wpe-performance-considerations-pre-rendering\/\">#<\/a><\/h4>\n<p>The first step to addressing the peak workload is usually optimization. Modern web platform gives a full variety of tools to optimize all the stages of web application processing done by the browser. The usual process of optimization is a\n2-step cycle starting with measuring the bottlenecks and followed by fixing them. In the process, the usual improvements involve:<\/p>\n<ul>\n<li>using CSS containment,<\/li>\n<li>using shadow DOM,<\/li>\n<li>promoting certain parts of the DOM to layers and manipulating them with transforms,<\/li>\n<li>parallelizing the work with workers\/worklets,<\/li>\n<li>using the <code>visibility<\/code> CSS property to separate painting from layout,<\/li>\n<li>optimizing the application itself (JavaScript code, the structure of the DOM, the architecture of the application),<\/li>\n<li>etc.<\/li>\n<\/ul>\n<h4 id=\"second-step-pre-rendering\" tabindex=\"-1\">Second step: pre-rendering <a class=\"header-anchor\" href=\"https:\/\/blogs.igalia.com\/plampe\/wpe-performance-considerations-pre-rendering\/\">#<\/a><\/h4>\n<p>Unfortunately, in practice, it\u2019s not uncommon that even very well optimized applications still have too much of a peak workload for the constrained embedded devices they\u2019re used on. In such cases, the last resort solution is\n<strong>pre-rendering<\/strong>. As long as it\u2019s possible from the application business-logic perspective, having at least some web page content pre-rendered is very helpful in situations when workload has to be managed, as <strong>pre-rendering<\/strong>\nallows the web application designer to choose the precise moment when the content should actually be rendered and how it should be done. With that, it\u2019s possible to establish a proper trade-off between reduction in peak workload and\nthe amount of extra memory used for storing the pre-rendered contents.<\/p>\n<h2 id=\"pre-rendering-techniques\" tabindex=\"-1\">Pre-rendering techniques <a class=\"header-anchor\" href=\"https:\/\/blogs.igalia.com\/plampe\/wpe-performance-considerations-pre-rendering\/\">#<\/a><\/h2>\n<p>Nowadays, the web platform provides at lest a few widely-adapted APIs that provide means for the application to perform various kinds of pre-rendering. Also, due to the ways the browsers are implemented, some APIs can be purposely misused\nto provide pre-rendering techniques not necessarily supported by the specification. However, in the pursuit of good trade-offs, all the possibilities should be taken into account.<\/p>\n<p>Before jumping into particular pre-rendering techniques, it\u2019s necessary to emphasize that the <strong>pre-rendering<\/strong> term used in this article refers to the actual rendering being done earlier than it\u2019s visually presented. In that\nsense, the resource is rasterized to some intermediate form when desired and then just composited by the browser engine\u2019s compositor later.<\/p>\n<h4 id=\"pre-rendering-offline\" tabindex=\"-1\">Pre-rendering offline <a class=\"header-anchor\" href=\"https:\/\/blogs.igalia.com\/plampe\/wpe-performance-considerations-pre-rendering\/\">#<\/a><\/h4>\n<p>The most basic (and limited at the same time) pre-rendering technique is one that involves rendering offline i.e. before the browser even starts. In that case, the first limitation is that the content to be rendered must be known\nbeforehand. If that\u2019s the case, the rendering can be done in any way, and the result may be captured as e.g. raster or vector image (depending on the desired trade-off). However, the other problem is that such a rendering is usually out of\nthe given web application scope and thus requires extra effort. Moreover, depending on the situation, the amount of extra memory used, the longer web application startup (due to loading the pre-rendered resources), and the processing\npower required to composite a given resource, it may not always be trivial to obtain the desired gains.<\/p>\n<h4 id=\"pre-rendering-using-canvas\" tabindex=\"-1\">Pre-rendering using canvas <a class=\"header-anchor\" href=\"https:\/\/blogs.igalia.com\/plampe\/wpe-performance-considerations-pre-rendering\/\">#<\/a><\/h4>\n<p>The first group of actual pre-rendering techniques happening during web application runtime is related to <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Canvas_API\">Canvas<\/a> and\n<a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/OffscreenCanvas\">OffscreenCavas<\/a>. Those APIs are really useful as they offer great flexibility in terms of usage and are usually very performant.\nHowever, in this case, the natural downside is the lack of support for rendering the DOM inside the canvas. Moreover, canvas has a very limited support for painting text \u2014 unlike the DOM, where\nCSS has a significant amount of features related to it. Interestingly, there\u2019s an ongoing proposal called <a href=\"https:\/\/github.com\/WICG\/html-in-canvas\">HTML-in-Canvas<\/a> that could resolve those limitations\nto some degree. In fact, Blink has a functioning prototype of it already. However, it may take a while before the spec is mature and widely adopted by other browser engines.<\/p>\n<p>When it comes to actual usage of canvas APIs for pre-rendering, the possibilities are numerous, and there are even more of them when combined with processing using <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Web_Workers_API\">workers<\/a>.\nThe most popular ones are as follows:<\/p>\n<ul>\n<li>rendering to an invisible canvas and showing it later,<\/li>\n<li>rendering to a canvas detached from the DOM and attaching it later,<\/li>\n<li>rendering to an invisible\/detached canvas and producing an image out of it to be shown later,<\/li>\n<li>rendering to an offscreen canvas and producing an image out of it to be shown later.<\/li>\n<\/ul>\n<p>When combined with workers, some of the above techniques may be used in the worker threads with the rendered artifacts transferred to the main for presentation purposes. In that case, one must be careful with\nthe transfer itself, as some objects may get serialized, which is very costly. To avoid that, it\u2019s recommended to use <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Web_Workers_API\/Transferable_objects\">transferable objects<\/a>\nand always perform a proper benchmarking to make sure the transfer is not involving serialization in the particular case.<\/p>\n<p>While the use of canvas APIs is usually very straightforward, one must be aware of two extra caveats.<\/p>\n<p>First of all, in the case of many techniques mentioned above, there is no guarantee that the browser will perform actual rasterization at the given point in time. To ensure the rasterization is triggered, it\u2019s usually\nnecessary to enforce it using e.g. a dummy readback (<code>getImageData()<\/code>).<\/p>\n<p>Finally, one should be aware that the usage of canvas comes with some overhead. Therefore, creating many canvases or creating them often, may lead to performance problems that could outweigh the gains from the\npre-rendering itself.<\/p>\n<h4 id=\"pre-rendering-using-eventually-invisible-layers\" tabindex=\"-1\">Pre-rendering using eventually-invisible layers <a class=\"header-anchor\" href=\"https:\/\/blogs.igalia.com\/plampe\/wpe-performance-considerations-pre-rendering\/\">#<\/a><\/h4>\n<p>The second group of pre-rendering techniques happening during web application runtime is limited to the DOM rendering and comes out of a combination of purposeful spec misuse and tricking the browser engine into making it rasterizing\non demand. As one can imagine, this group of techniques is very much browser-engine-specific. Therefore, it should always be backed by proper benchmarking of all the use cases on the target browsers and target hardware.<\/p>\n<p>In principle, all the techniques of this kind consist of 3 parts:<\/p>\n<ol>\n<li>Enforcing the content to be pre-rendered being placed on a separate layer backed by an actual buffer internally in the browser,<\/li>\n<li>Tricking the browser\u2019s compositor into thinking that the layer needs to be rasterized right away,<\/li>\n<li>Ensuring the layer won\u2019t be composited eventually.<\/li>\n<\/ol>\n<p>When all the elements are combined together, the browser engine will allocate an internal buffer (e.g. texture) to back the given DOM fragment, it will process that fragment (style recalc, layout), and rasterize it right away. It will do so\nas it will not have enough information to allow delaying the rasterization of the layer (as e.g. in case of <code>display: none<\/code>). Then, when the compositing time comes, the layer will turn out to be invisible in practice\ndue to e.g. being occluded, clipped, etc. This way, the rasterization will happen right away, but the results will remain invisible until a later time when the layer is made visible.<\/p>\n<p>In practice, the following approaches can be used to trigger the above behavior:<\/p>\n<ul>\n<li>for <strong>(1)<\/strong>, the CSS properties such as <code>will-change: transform<\/code>, <code>z-index<\/code>, <code>position: fixed<\/code>, <code>overflow: hidden<\/code> etc. can be used depending on the browser engine,<\/li>\n<li>for <strong>(2)<\/strong> and <strong>(3)<\/strong>, the CSS properties such as <code>opacity: 0<\/code>, <code>overflow: hidden<\/code>, <code>contain: strict<\/code> etc. can be utilized, again, depending on the browser engine.<\/li>\n<\/ul>\n<h5>The scrolling trick<\/h5>\n<p>While the above CSS properties allow for various combinations, in case of WPE WebKit in the context of embedded devices (tested on <strong>NXP i.MX8M Plus<\/strong>), the combination that has proven to yield the best performance benefits turns\nout to be a simple approach involving <code>overflow: hidden<\/code> and scrolling. The example of such an approach is explained below.<\/p>\n<p>Suppose the goal of the application is to update a big table with numbers once every N frames \u2014 like in the following demo:\n<a href=\"https:\/\/scony.github.io\/web-examples\/text\/random-numbers-bursting-in-table.html?cs=20&rs=20&if=59\">random-numbers-bursting-in-table.html?cs=20&amp;rs=20&amp;if=59<\/a><\/p>\n<center>\n<source type=\"image\/avif\"><source type=\"image\/webp\"><img alt=\"Bursting numbers demo.\" src=\"https:\/\/blogs.igalia.com\/plampe\/img\/0PwhZK5P7T-654.png\" width=\"654\" height=\"653\" \/>\n<\/source><\/source><\/center>\n<p>With the number of idle frames (<code>if<\/code>) set to 59, the idea is that the application does nothing significant for the 59 frames, and then every 60th frame it updates all the numbers in the table.<\/p>\n<p>As one can imagine, on constrained embedded devices, such an approach leads to a very heavy workload during every 60th frame and hence to lost frames and unstable application\u2019s FPS.<\/p>\n<p>As long as the numbers are available earlier than every 60th frame, the above application is a perfect example where pre-rendering could be used to reduce the peak workload.<\/p>\n<p>To simulate that, the 3 variants of the approach involving the <strong>scrolling trick<\/strong> were prepared for comparison with the above:<\/p>\n<ul>\n<li><a href=\"https:\/\/scony.github.io\/web-examples\/text\/random-numbers-bursting-in-table-prerendered-1.html?cs=20&rs=20&if=59\">random-numbers-bursting-in-table-prerendered-1.html?cs=20&amp;rs=20&amp;if=59<\/a><\/li>\n<li><a href=\"https:\/\/scony.github.io\/web-examples\/text\/random-numbers-bursting-in-table-prerendered-2.html?cs=20&rs=20&if=59\">random-numbers-bursting-in-table-prerendered-2.html?cs=20&amp;rs=20&amp;if=59<\/a><\/li>\n<li><a href=\"https:\/\/scony.github.io\/web-examples\/text\/random-numbers-bursting-in-table-prerendered-3.html?cs=20&rs=20&if=59\">random-numbers-bursting-in-table-prerendered-3.html?cs=20&amp;rs=20&amp;if=59<\/a><\/li>\n<\/ul>\n<p>In the above demos, the idea is that each cell with a number becomes a scrollable container with 2 numbers actually \u2014 one above the other. In that case, because <code>overflow: hidden<\/code> is set, only one of the numbers is visible while the\nother is hidden \u2014 depending on the current scrolling:<\/p>\n<center>\n<source type=\"image\/avif\"><source type=\"image\/webp\"><img alt=\"Scrolling trick explained.\" src=\"https:\/\/blogs.igalia.com\/plampe\/img\/qFqjTXuuSo-611.png\" width=\"611\" height=\"348\" \/>\n<\/source><\/source><\/center>\n<p>With such a setup, it\u2019s possible to update the invisible numbers during <strong>idle<\/strong> frames without the user noticing. Due to how WPE WebKit accelerates the scrolling, changing the invisible\nnumbers, in practice, triggers the layout and rendering right away. Moreover, the actual rasterization to the buffer backing the scrollable container happens immediately (depending on the tiling settings), and hence the high cost of layout\nand text rasterization can be distributed. When the time comes, and all the numbers need to be updated, the scrollable containers can be just scrolled, which in that case turns out to be ~2 times faster than updating all the numbers in place.<\/p>\n<p>To better understand the above effect, it\u2019s recommended to compare the mark views from sysprof traces of the\n<a href=\"https:\/\/scony.github.io\/web-examples\/text\/random-numbers-bursting-in-table.html?cs=10&rs=10&if=11\">random-numbers-bursting-in-table.html?cs=10&amp;rs=10&amp;if=11<\/a> and\n<a href=\"https:\/\/scony.github.io\/web-examples\/text\/random-numbers-bursting-in-table-prerendered-1.html?cs=10&rs=10&if=11\">random-numbers-bursting-in-table-prerendered-1.html?cs=10&amp;rs=10&amp;if=11<\/a> demos:<\/p>\n<center>\n<source type=\"image\/avif\"><source type=\"image\/webp\"><img alt=\"Sysprof from basic demo.\" src=\"https:\/\/blogs.igalia.com\/plampe\/img\/NVtyG7e_K1-2363.png\" width=\"2363\" height=\"1169\" \/>\n<\/source><\/source><\/center>\n<br \/><br \/><br \/>\n<center>\n<source type=\"image\/avif\"><source type=\"image\/webp\"><img alt=\"Sysprof from pre-rendering demo.\" src=\"https:\/\/blogs.igalia.com\/plampe\/img\/6du_zbm-hI-2363.png\" width=\"2363\" height=\"1172\" \/>\n<\/source><\/source><\/center>\n<p>While the first sysprof trace shows very little processing during 11 idle frames and a big chunk of processing (21 ms) every 12th frame, the second sysprof trace shows how the distribution of load looks. In\nthat case, the amount of work during 11 idle frames is much bigger (yet manageable), but at the same time, the formerly big chunk of processing every 12th frame is reduced almost 2 times (to 11 ms). Therefore, the overall\nframe rate in the application is much better.<\/p>\n<h5>Results<\/h5>\n<p>Despite the above improvement speaking for itself, it\u2019s worth summarizing the improvement with the benchmarking results of the above demos obtained from the <strong>NXP i.MX8M Plus<\/strong> and presenting the application\u2019s average\nframes per second (FPS):<\/p>\n<center>\n<source type=\"image\/avif\"><source type=\"image\/webp\"><img alt=\"Benchmarking results.\" src=\"https:\/\/blogs.igalia.com\/plampe\/img\/YqNYgMaEpQ-1104.png\" width=\"1104\" height=\"204\" \/>\n<\/source><\/source><\/center>\n<p>Clearly, the positive impact of pre-rendering can be substantial depending on the conditions. In practice, when the rendered DOM fragment is more complex, the trick such as above can yield even better results.\nHowever, due to how tiling works, the effect can be minimized if the content to be pre-rendered spans multiple tiles. In that case, the browser may defer rasterization until the tiles are actually needed. Therefore,\nthe above needs to be used with care and always with proper benchmarking.<\/p>\n<h2 id=\"conclusions\" tabindex=\"-1\">Conclusions <a class=\"header-anchor\" href=\"https:\/\/blogs.igalia.com\/plampe\/wpe-performance-considerations-pre-rendering\/\">#<\/a><\/h2>\n<p>As demonstrated in the above sections, when it comes to pre-rendering the contents to distribute the web application workload over time, the web platform gives both the official APIs to do it, as well as unofficial\nmeans through purposeful misuse of APIs and exploitation of browser engine implementations. While this article hasn\u2019t covered all the possibilities available, the above should serve as a good initial read with some easy-to-try\nsolutions that may yield surprisingly good results. However, as some of the ideas mentioned above are very much browser-engine-specific, they should be used with extra care and with the limitations (lack of portability)\nin mind.<\/p>\n<p>As the web platform constantly evolves, the pool of pre-rendering techniques and tricks should keep evolving as well. Also, as more and more web applications are used on embedded devices, more pressure should be\nput on the specification, which should yield more APIs targeting the low-end devices in the future. With that in mind, it\u2019s recommended for the readers to stay up-to-date with the latest specification and\nperhaps even to get involved if some interesting use cases would be worth introducing new APIs.<\/p>        ","pubDate":"Fri, 19 Dec 2025 00:00:00 +0000"},{"title":"Igalia WebKit Team: WebKit Igalia Periodical #51","guid":"https:\/\/blogs.igalia.com\/webkit\/blog\/2025\/wip-51\/","link":"https:\/\/blogs.igalia.com\/webkit\/blog\/2025\/wip-51\/","description":"\n<p>Update on what happened in WebKit in the week from December 8 to December 15.<\/p>\n<p>\nIn this end-of-year special have a new GMallocString helper that makes\nmanagement of malloc-based strings more efficient, development releases,\nand a handful of advancements on JSC's implementation of Temporal, in\nparticular the PlainYearMonth class.\n<\/p>\n<h2 id=\"cross-port-cat\">Cross-Port \ud83d\udc31<\/h2>\n  <div class=\"wip-item\">\n<p>Added <a rel=\"external\" href=\"https:\/\/github.com\/WebKit\/WebKit\/pull\/55162\">GMallocString<\/a> class to WTF to adopt UTF8 C strings and make them WebKit first class citizens efficiently (no copies). Applied in GStreamer code together with <a rel=\"external\" href=\"https:\/\/github.com\/WebKit\/WebKit\/pull\/51259\">other improvements by using CStringView<\/a>. Fixed other <a rel=\"external\" href=\"https:\/\/github.com\/WebKit\/WebKit\/pull\/54312\">two<\/a> <a rel=\"external\" href=\"https:\/\/github.com\/WebKit\/WebKit\/pull\/54762\">bugs<\/a> about string management.<\/p>\n  <\/div>\n<h3 id=\"javascriptcore-fish\">JavaScriptCore \ud83d\udc1f<\/h3>\n<div class=\"wip-description\">\n<p>The built-in JavaScript\/ECMAScript engine for WebKit, also known as JSC or SquirrelFish.<\/p>\n<\/div>\n  <div class=\"wip-item\">\n<p>In JavaScriptCore's implementation of Temporal, <a rel=\"external\" href=\"https:\/\/github.com\/WebKit\/WebKit\/pull\/55153\">added the <code>with<\/code> method for <code>PlainYearMonth<\/code> objects<\/a>, as well as <a rel=\"external\" href=\"https:\/\/github.com\/WebKit\/WebKit\/pull\/55076\">the <code>equals<\/code>, <code>compare<\/code>, and <code>valueOf<\/code> methods<\/a>, <a rel=\"external\" href=\"https:\/\/github.com\/WebKit\/WebKit\/pull\/54800\">and also the <code>from<\/code> method<\/a>. Also <a rel=\"external\" href=\"https:\/\/github.com\/WebKit\/WebKit\/pull\/55201\">implemented the <code>toPlainDate<\/code> method for PlainYearMonth objects<\/a>.<\/p>\n  <\/div>\n<h2 id=\"releases-package\">Releases \ud83d\udce6\ufe0f<\/h2>\n  <div class=\"wip-item\">\n<p>Development releases of <a rel=\"external\" href=\"https:\/\/webkitgtk.org\/2025\/12\/09\/webkitgtk2.51.3-released.html\">WebKitGTK 2.51.3<\/a>\nand <a rel=\"external\" href=\"https:\/\/wpewebkit.org\/release\/wpewebkit-2.51.3.html\">WPE WebKit 2.51.3<\/a>\nare now available. These include a number of API additions and new features,\nand are intended to allow interested parties to test those in advance, prior\nto the next stable release series. As usual, bug reports are\n<a rel=\"external\" href=\"https:\/\/bugs.webkit.org\/\">welcome in Bugzilla<\/a>.<\/p>\n  <\/div>\n<div class=\"wip-end\">\n<p>That\u2019s all for this week!<\/p>\n<\/div>        ","pubDate":"Mon, 15 Dec 2025 19:58:42 +0000"},{"title":"Igalia WebKit Team: WebKit Igalia Periodical #50","guid":"https:\/\/blogs.igalia.com\/webkit\/blog\/2025\/wip-50\/","link":"https:\/\/blogs.igalia.com\/webkit\/blog\/2025\/wip-50\/","description":"\n<p>Update on what happened in WebKit in the week from December 1 to December 8.<\/p>\n<p>\nIn this edition of the periodical we have further advancements on\nthe Temporal implementation, support for Vivante super-tiled format,\nand an adaptation of the DMA-BUF formats code to the Android port.\n<\/p>\n<h2 id=\"cross-port-cat\">Cross-Port \ud83d\udc31<\/h2>\n<h3 id=\"javascriptcore-fish\">JavaScriptCore \ud83d\udc1f<\/h3>\n<div class=\"wip-description\">\n<p>The built-in JavaScript\/ECMAScript engine for WebKit, also known as JSC or SquirrelFish.<\/p>\n<\/div>\n  <div class=\"wip-item\">\n<p><a rel=\"external\" href=\"https:\/\/github.com\/WebKit\/WebKit\/pull\/54717\">Implemented<\/a> the <code>toString<\/code>, <code>toJSON<\/code>, and <code>toLocaleString<\/code> methods for <code>PlainYearMonth<\/code> objects in JavaScriptCore's implementation of Temporal.<\/p>\n  <\/div>\n<h3 id=\"graphics-frame-photo\">Graphics \ud83d\uddbc\ufe0f<\/h3>\n  <div class=\"wip-item\">\n<p><code>BitmapTexture<\/code> and <code>TextureMapper<\/code> <a rel=\"external\" href=\"https:\/\/commits.webkit.org\/303849@main\">were prepared<\/a> to handle textures where the logical size (e.g. 100\u00d7100) differs from the allocated size (e.g. 128\u00d7128) due to alignment requirements. This allowed <a rel=\"external\" href=\"https:\/\/commits.webkit.org\/303900@main\">to add support<\/a> for using memory-mapped GPU buffers in the Vivante super-tiled format available on i.MX platforms. Set <code>WEBKIT_SKIA_USE_VIVANTE_SUPER_TILED_TILE_TEXTURES=1<\/code> to activate at runtime.<\/p>\n  <\/div>\n<h2 id=\"wpe-webkit-pager\">WPE WebKit \ud83d\udcdf<\/h2>\n<h3 id=\"wpe-platform-api-jigsaw\">WPE Platform API \ud83e\udde9<\/h3>\n<div class=\"wip-description\">\n<p>New, modern platform API that supersedes usage of libwpe and WPE backends.<\/p>\n<\/div>\n  <div class=\"wip-item\">\n<p>The <code>WPEBufferDMABufFormats<\/code> class has been <a rel=\"external\" href=\"https:\/\/commits.webkit.org\/303891@main\">renamed<\/a> to <code>WPEBufferFormats<\/code>, as it can be used in situations where mechanisms other than DMA-BUF may be used for buffer sharing\u2014on Android targets <a rel=\"external\" href=\"https:\/\/developer.android.com\/ndk\/reference\/group\/a-hardware-buffer\">AHardwareBuffer<\/a> is used instead, for example. The naming change involved also <code>WPEBufferFormatsBuilder<\/code> (renamed from <code>WPEBufferDMABufFormatsBuilder<\/code>), and methods and signals in other classes that use these types. Other than the renames, there is no change in functionality.<\/p>\n  <\/div>\n<div class=\"wip-end\">\n<p>That\u2019s all for this week!<\/p>\n<\/div>        ","pubDate":"Mon, 08 Dec 2025 20:26:32 +0000"},{"title":"Enrique Oca\u00f1a: Meow: Process log text files as if you could make cat speak","guid":"https:\/\/eocanha.org\/blog\/?p=684","link":"https:\/\/eocanha.org\/blog\/2025\/12\/05\/meow-process-log-text-files-as-if-you-could-make-cat-speak\/","description":"\n<p>Some years ago I had mentioned <a href=\"https:\/\/eocanha.org\/blog\/2021\/05\/25\/gstreamer-webkit-debugging-by-using-external-tools-2-2\/\">some command line tools<\/a> I used to analyze and find useful information on GStreamer logs. I&#8217;ve been using them consistently along all these years, but some weeks ago I thought about unifying them in a single tool that could provide more flexibility in the mid term, and also as an excuse to unrust my Rust knowledge a bit. That&#8217;s how I wrote Meow, a tool to make <code>cat<\/code> speak (that is, to provide meaningful information).<\/p>\n\n\n\n<p>The idea is that you can <code>cat<\/code> a file through <code>meow<\/code> and apply the filters, like this:<\/p>\n\n\n\n<p><code>cat \/tmp\/log.txt | meow appsinknewsample n:V0 n:video ht: \\<br \/>  ft:-0:00:21.466607596 's:#([A-za-z][A-Za-z]*\/)*#'<\/code><\/p>\n\n\n\n<p>which means &#8220;select those lines that contain <code>appsinknewsample<\/code> (with case insensitive matching), but don&#8217;t contain <code>V0<\/code> nor <code>video<\/code> (that is, by exclusion, only that contain audio, probably because we&#8217;ve analyzed both and realized that we should focus on audio for our specific problem), highlight the different thread ids, only show those lines with timestamp lower than 21.46 sec, and change strings like <code>Source\/WebCore\/platform\/graphics\/gstreamer\/mse\/AppendPipeline.cpp<\/code> to become just <code>AppendPipeline.cpp<\/code>&#8220;, to get an output as shown in this terminal screenshot:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/eocanha.org\/blog\/wp-content\/uploads\/2025\/12\/image.png\"><img width=\"1024\" height=\"254\" src=\"https:\/\/eocanha.org\/blog\/wp-content\/uploads\/2025\/12\/image-1024x254.png\" alt=\"Screenshot of a terminal output showing multiple log lines. Some of them have the word \" \/><\/a><\/figure>\n\n\n\n<p>Cool, isn&#8217;t it? After all, I&#8217;m convinced that the answer to any GStreamer bug is always hidden in the logs (or will be, as soon as I add &#8220;<em>just a couple of log lines more, bro<\/em>&#8221; <img src=\"https:\/\/s.w.org\/images\/core\/emoji\/13.1.0\/72x72\/1f92d.png\" alt=\"\ud83e\udd2d\" class=\"wp-smiley\" \/>).<\/p>\n\n\n\n<p>Currently, meow supports this set of manipulation commands:<\/p>\n\n\n\n<ul><li><strong>Word filter and highlighting by regular expression<\/strong> (<code>fc:REGEX<\/code>, or just <code>REGEX<\/code>): Every expression will highlight its matched words in a different color.<\/li><li><strong>Filtering without highlighting<\/strong> (<code>fn:REGEX<\/code>): Same as <code>fc:<\/code>, but without highlighting the matched string. This is useful for those times when you want to match lines that have two expressions (<code>E1<\/code>, <code>E2<\/code>) but the highlighting would pollute the line too much. In those case you can use a regex such as <code>E1.*E2<\/code> and then highlight the subexpressions manually later with an <code>h:<\/code> rule.<\/li><li><strong>Negative filter<\/strong> (<code>n:REGEX<\/code>): Selects only the lines that don&#8217;t match the regex filter. No highlighting.<\/li><li><strong>Highlight with no filter<\/strong> (<code>h:REGEX<\/code>): Doesn&#8217;t discard any line, just highlights the specified regex.<\/li><li><strong>Substitution<\/strong> (<code>s:\/REGEX\/REPLACE<\/code>): Replaces one pattern for another. Any other delimiter character can be used instead of \/, it that&#8217;s more convenient to the user (for instance, using # when dealing with expressions to manipulate paths).<\/li><li><strong>Time filter<\/strong> (<code>ft:TIME-TIME<\/code>): Assuming the lines start with a GStreamer log timestamp, this filter selects only the lines between the target start and end time. Any of the time arguments (or both) can be omitted, but the <code>-<\/code> delimiter must be present. Specifying multiple time filters will generate matches that fit on any of the time ranges, but overlapping ranges can trigger undefined behaviour.<\/li><li><strong>Highlight threads<\/strong> (<code>ht:<\/code>): Assuming a GStreamer log, where the thread id appears as the third word in the line, highlights each thread in a different color.<\/li><\/ul>\n\n\n\n<p>The <code>REGEX<\/code> pattern is a regular expression. All the matches are case insensitive. When used for substitutions, capture groups can be defined as <code>(?<span class=\"has-inline-color has-medium-pink-color\">CAPTURE_NAME<\/span>REGEX)<\/code>.<\/p>\n\n\n\n<p>The <code>REPLACE<\/code>ment string is the text that the <code>REGEX<\/code> will be replaced by when doing substitutions. Text captured by a named capture group can be referred to by <code>${<span class=\"has-inline-color has-medium-pink-color\">CAPTURE_NAME<\/span>}<\/code>.<\/p>\n\n\n\n<p>The <code>TIME<\/code> pattern can be any sequence of numbers, <code>:<\/code> or <code>.<\/code> . Typically, it will be a GStreamer timestamp (eg: 0:01:10.881123150), but it can actually be any other numerical sequence. Times are compared lexicographically, so it&#8217;s important that all of them have the same string length.<\/p>\n\n\n\n<p>The filtering algorithm has a custom set of priorities for operations, so that they get executed in an intuitive order. For instance, a sequence of filter matching expressions (<code>fc:<\/code>, <code>fn:<\/code>) will have the same priority (that is, any of them will let a text line pass if it matches, not forbidding any of the lines already allowed by sibling expressions), while a negative filter will only be applied on the results left by the sequence of filters before it. Substitutions will be applied at their specific position (not before or after), and will therefore modify the line in a way that can alter the matching of subsequent filters. In general, the user doesn&#8217;t have to worry about any of this, because the rules are designed to generate the result that you would expect.<\/p>\n\n\n\n<p>Now some practical examples:<\/p>\n\n\n\n<p><strong>Example 1<\/strong>: Select lines with the word &#8220;one&#8221;, or the word &#8220;orange&#8221;, or a number, highlighting each pattern in a different color except the number, which will have no color:<br \/><br \/><code>$ cat file.txt | meow one fc:orange 'fn:[0-9][0-9]*'<br \/>000 <span class=\"has-inline-color has-medium-pink-color\">one<\/span> small <span class=\"has-inline-color has-yellow-color\">orange<\/span><br \/>005 <span class=\"has-inline-color has-medium-pink-color\">one<\/span> big <span class=\"has-inline-color has-yellow-color\">orange<\/span><\/code><\/p>\n\n\n\n<p><strong>Example 2<\/strong>: Assuming a pictures filename listing, select filenames not ending in &#8220;jpg&#8221; nor in &#8220;jpeg&#8221;, and rename the filename to &#8220;.bak&#8221;, preserving the extension at the end:<br \/><br \/><code>$ cat list.txt | meow  'n:jpe?g' \\<\/code><br \/><code>\u00a0<\/code>\u00a0\u00a0<code>'s:#^(?&lt;f>[^.]*)(?&lt;e>[.].*)$#${f}.bak${e}'<br \/>train.bak.png<br \/>sunset.bak.gif<\/code><\/p>\n\n\n\n<p><strong>Example 3<\/strong>: Only print the log lines with times between 0:00:24.787450146 and 0:00:24.790741865 or those at 0:00:30.492576587 or after, and highlight every thread in a different color:<br \/><br \/><code>$ cat log.txt | meow ft:0:00:24.787450146-0:00:24.790741865 \\<br \/>\u00a0<\/code>\u00a0\u00a0<code>ft:0:00:30.492576587- ht:<br \/>0:00:24.787450146 739 <span class=\"has-inline-color has-medium-pink-color\">0x1ee2320<\/span> DEBUG \u2026<br \/>0:00:24.790382735 739 <span class=\"has-inline-color has-yellow-color\">0x1f01598<\/span> INFO \u2026<br \/>0:00:24.790741865 739 <span class=\"has-inline-color has-medium-pink-color\">0x1ee2320<\/span> DEBUG \u2026<br \/>0:00:30.492576587 739 <span class=\"has-inline-color has-yellow-color\">0x1f01598<\/span> DEBUG \u2026<br \/>0:00:31.938743646 739 <span class=\"has-inline-color has-yellow-color\">0x1f01598<\/span> ERROR \u2026<\/code><\/p>\n\n\n\n<p>This is only the begining. I have great ideas for this new tool (as time allows), such as support for parenthesis (so the expressions can be grouped), or call stack indentation on logs generated by tracers, in a similar way to what Alicia&#8217;s <a href=\"https:\/\/github.com\/ntrrgc\/dotfiles\/blob\/master\/bin\/gst-log-indent-tracers\"><code>gst-log-indent-tracers<\/code> tool<\/a> does. I might also predefine some common expressions to use in regular expressions, such as the ones to match paths (so that the user doesn&#8217;t have to think about them and reinvent the wheel every time). Anyway, these are only ideas. Only time and hyperfocus slots will tell&#8230;<\/p>\n\n\n\n<p>By now, you can <a href=\"https:\/\/github.com\/eocanha\/meow\">find the source code on my github<\/a>. Meow! <img width=\"128\" height=\"128\" class=\"wp-image-698\" src=\"https:\/\/eocanha.org\/blog\/wp-content\/uploads\/2025\/12\/blobcat.png\" alt=\"\" \/><\/p>        ","pubDate":"Fri, 05 Dec 2025 11:16:07 +0000"}]}}