File 1af56f57356b1e1ff02d9a18d24dd282b8db87ef.patch of Package cockpit
From 1af56f57356b1e1ff02d9a18d24dd282b8db87ef Mon Sep 17 00:00:00 2001
From: Jelle van der Waa <jvanderwaa@redhat.com>
Date: Thu, 5 Mar 2026 13:17:19 +0100
Subject: [PATCH] cockpit-client: upgrade to GTK 4 & WebKit 6
GTK 4 is available in all modern distributions and while GTK 3 will
still be supported until the release of GTK 5. It doesn't hurt to update
to GTK 4 already which should have better support for Wayland portals
Upgrading to GTK 4 moves us to WebKit 6.0 which should bring in
more modern JavaScript / CSS support.
The most notable API changes are:
* Sandboxing is now always enabled.
* Gtk.show_uri* is deprecated and replaced by by UriLauncher.
* The HeaderBar title now needs to be updated by the application.
* LibHandy is replaced by Adwaita
* WebKit.WebView is constructed in code now as the network_session
property cannot be set after the WebView is instantiated.
https://docs.gtk.org/gtk4/migrating-3to4.html
https://webkitgtk.org/reference/webkit2gtk/2.39.7/migrating-to-webkitgtk-6.0.html
---
src/client/cockpit-client | 53 +++++++++++-----------
src/client/cockpit-client.ui | 88 +++++++++---------------------------
2 files changed, 47 insertions(+), 94 deletions(-)
Index: cockpit-356/src/client/cockpit-client
===================================================================
--- cockpit-356.orig/src/client/cockpit-client
+++ cockpit-356/src/client/cockpit-client
@@ -17,21 +17,14 @@ import textwrap
import gi
-gi.require_version("Gtk", "3.0")
+gi.require_version("Gtk", "4.0")
from gi.repository import GLib, Gio, Gtk # noqa: I001, E402
-try:
- gi.require_version("WebKit2", "4.1")
- from gi.repository import WebKit2
-except (ValueError, ImportError):
- gi.require_version("WebKit2", "4.0")
- from gi.repository import WebKit2
-
-try:
- gi.require_version("Handy", "1")
- from gi.repository import Handy
-except (ValueError, ImportError):
- Handy = None
+gi.require_version("WebKit", "6.0")
+from gi.repository import WebKit # noqa: E402
+
+gi.require_version("Adw", "1")
+from gi.repository import Adw # noqa: E402
libexecdir = os.path.realpath(__file__ + '/..')
@@ -60,11 +53,15 @@ SET_PDEATHSIG = 1
@Gtk.Template(filename=f'{libexecdir}/cockpit-client.ui')
class CockpitClientWindow(Gtk.ApplicationWindow):
__gtype_name__ = 'CockpitClientWindow'
- webview = Gtk.Template.Child()
+ webview_container = Gtk.Template.Child()
+ title = Gtk.Template.Child()
def __init__(self, app, uri):
super().__init__(application=app)
+ self.webview = WebKit.WebView(network_session=app.network_session, vexpand=True, hexpand=True)
+ self.webview_container.append(self.webview)
+
self.add_action_entries([
('reload', self.reload),
('reload-bypass-cache', self.reload_bypass_cache),
@@ -84,6 +81,8 @@ class CockpitClientWindow(Gtk.Applicatio
history.connect('changed', self.history_changed)
self.history_changed()
+ self.webview.connect('notify::title', self.update_subtitle)
+
if app.no_ui:
self.set_titlebar(None)
self.webview.bind_property('title', self, 'title')
@@ -92,6 +91,10 @@ class CockpitClientWindow(Gtk.Applicatio
self.lookup_action('go-back').set_enabled(self.webview.can_go_back())
self.lookup_action('go-forward').set_enabled(self.webview.can_go_forward())
+ def update_subtitle(self, webview, *args):
+ title = webview.get_title() or "Loading..."
+ self.title.set_label(title)
+
def reload(self, *args):
self.webview.reload()
@@ -105,13 +108,13 @@ class CockpitClientWindow(Gtk.Applicatio
self.webview.go_forward()
def decide_policy(self, _view, decision, decision_type):
- if decision_type == WebKit2.PolicyDecisionType.NEW_WINDOW_ACTION:
+ if decision_type == WebKit.PolicyDecisionType.NEW_WINDOW_ACTION:
uri = decision.get_navigation_action().get_request().get_uri()
if uri.startswith('http://127'):
logging.error('warning: no support for pop-ups')
else:
- # We can't get the timestamp from the request, so use Gdk.CURRENT_TIME (== 0)
- Gtk.show_uri_on_window(self, uri, 0)
+ launcher = Gtk.UriLauncher.new(uri)
+ launcher.launch(self, None, None, None)
decision.ignore()
return True
@@ -165,13 +168,13 @@ class CockpitClientWindow(Gtk.Applicatio
uc_manager = self.webview.get_user_content_manager()
on_result_handler = uc_manager.connect(
"script-message-received::result",
- lambda _mgr, result: set_result(result.get_js_value().to_string()))
+ lambda _mgr, result: set_result(result.to_string()))
uc_manager.register_script_message_handler("result")
# wait for loads to complete, to avoid races and ensure that it did not fail
on_load_handler = self.webview.connect(
"load-changed",
- lambda webview, event: set_result("page-load") if event == WebKit2.LoadEvent.FINISHED else None)
+ lambda webview, event: set_result("page-load") if event == WebKit.LoadEvent.FINISHED else None)
self.webview.run_javascript(parameter.get_string(), None, run_js_ready, None)
@@ -194,8 +197,7 @@ class CockpitClient(Gtk.Application):
def do_startup(self):
Gtk.Application.do_startup(self)
- if Handy and hasattr(Handy, 'StyleManager'):
- Handy.StyleManager.get_default().set_color_scheme(Handy.ColorScheme.PREFER_LIGHT)
+ Adw.StyleManager.get_default().set_color_scheme(Adw.ColorScheme.PREFER_LIGHT)
# .add_action_entries() binding is broken for GApplication
# https://gitlab.gnome.org/GNOME/pygobject/-/issues/426
@@ -215,15 +217,12 @@ class CockpitClient(Gtk.Application):
self.set_accels_for_action("win.zoom::default", ["<Primary>0"])
self.set_accels_for_action("win.open-inspector", ["<Primary><Shift>i", "F12"])
- context = WebKit2.WebContext.get_default()
- data_manager = context.get_website_data_manager()
- data_manager.set_network_proxy_settings(WebKit2.NetworkProxyMode.NO_PROXY, None)
- context.set_sandbox_enabled(enabled=True)
- context.set_cache_model(WebKit2.CacheModel.DOCUMENT_VIEWER)
+ self.network_session = WebKit.NetworkSession.get_default()
+ self.network_session.set_proxy_settings(WebKit.NetworkProxyMode.NO_PROXY)
cookiesFile = os.path.join(get_user_state_dir(), "cockpit-client", "cookies.txt")
- cookies = context.get_cookie_manager()
- cookies.set_persistent_storage(cookiesFile, WebKit2.CookiePersistentStorage.TEXT)
+ cookie_manager = self.network_session.get_cookie_manager()
+ cookie_manager.set_persistent_storage(cookiesFile, WebKit.CookiePersistentStorage.TEXT)
self.uri = self.ws.start()
Index: cockpit-356/src/client/cockpit-client.ui
===================================================================
--- cockpit-356.orig/src/client/cockpit-client.ui
+++ cockpit-356/src/client/cockpit-client.ui
@@ -1,98 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- SPDX-License-Identifier: LGPL-2.1-or-later -->
-<!-- Generated with glade 3.38.2 -->
<interface>
- <requires lib="gtk+" version="3.24"/>
- <requires lib="webkit2gtk" version="2.28"/>
+ <requires lib="gtk" version="4.0"/>
<template class="CockpitClientWindow" parent="GtkApplicationWindow">
<property name="width-request">800</property>
<property name="height-request">600</property>
- <property name="can-focus">False</property>
<property name="default-width">1280</property>
<property name="default-height">800</property>
<child>
- <object class="WebKitWebView" type-func="webkit_web_view_get_type" id="webview">
- <property name="visible">True</property>
- <property name="can-focus">True</property>
- <child>
- <placeholder/>
- </child>
+ <object class="GtkBox" id="webview_container">
</object>
</child>
<child type="titlebar">
- <object class="GtkHeaderBar" id="headerbar">
- <property name="visible">True</property>
- <property name="can-focus">False</property>
- <property name="title" translatable="yes">Cockpit Client</property>
- <property name="subtitle" translatable="yes" bind-source="webview" bind-property="title">Loading...</property>
- <property name="show-close-button">True</property>
- <child>
- <object class="GtkButtonBox">
- <property name="visible">True</property>
- <property name="can-focus">False</property>
+ <object class="GtkHeaderBar">
+ <property name="title-widget">
+ <object class="GtkLabel" id="title">
+ <property name="label" translatable="yes">Cockpit Client</property>
+ <style>
+ <class name="title"/>
+ </style>
+ </object>
+ </property>
+ <child type="start">
+ <object class="GtkBox">
+ <property name="spacing">0</property>
<property name="homogeneous">True</property>
- <property name="layout-style">expand</property>
+ <style>
+ <class name="linked"/>
+ </style>
<child>
<object class="GtkButton">
- <property name="visible">True</property>
- <property name="can-focus">False</property>
- <property name="receives-default">True</property>
<property name="action-name">win.go-back</property>
- <property name="always-show-image">True</property>
- <child>
- <object class="GtkImage">
- <property name="visible">True</property>
- <property name="can-focus">False</property>
- <property name="icon-name">go-previous-symbolic</property>
- </object>
- </child>
+ <property name="icon-name">go-previous-symbolic</property>
</object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
</child>
<child>
<object class="GtkButton">
- <property name="visible">True</property>
- <property name="can-focus">False</property>
- <property name="receives-default">True</property>
<property name="action-name">win.go-forward</property>
- <property name="always-show-image">True</property>
- <child>
- <object class="GtkImage">
- <property name="visible">True</property>
- <property name="can-focus">False</property>
- <property name="icon-name">go-next-symbolic</property>
- </object>
- </child>
+ <property name="icon-name">go-next-symbolic</property>
</object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
</child>
</object>
</child>
- <child>
+ <child type="start">
<object class="GtkButton">
- <property name="visible">True</property>
- <property name="can-focus">True</property>
- <property name="receives-default">True</property>
<property name="action-name">win.reload</property>
- <child>
- <object class="GtkImage">
- <property name="visible">True</property>
- <property name="can-focus">False</property>
- <property name="icon-name">view-refresh-symbolic</property>
- </object>
- </child>
+ <property name="icon-name">view-refresh-symbolic</property>
</object>
- <packing>
- <property name="position">1</property>
- </packing>
</child>
</object>
</child>