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>
openSUSE Build Service is sponsored by