diff --git a/src/scripts/client/apply-access.lua b/src/scripts/client/apply-access.lua index 5b372b6e..c0d3da23 100644 --- a/src/scripts/client/apply-access.lua +++ b/src/scripts/client/apply-access.lua @@ -8,6 +8,14 @@ log = Log.open_topic ("s-client") +-- Advertise portal client gate support to the PW daemon. +-- This is set once on our own client at script load time +-- so PW's core_hello can detect that a capable session manager is +-- connected, regardless of which portal client is being processed. +Core.update_properties { + ["pipewire.access.portal.gate-supported"] = "true" +} + AsyncEventHook { name = "client/apply-access", after = { "client/find-config-access", "client/find-default-access" }, @@ -60,6 +68,40 @@ AsyncEventHook { client:attach_permission_manager (permission_manager) log:info (client, string.format ( "Attached permission manager to client '%s'", app_name)) + + -- Handle portal client gating/ungating. + -- The PW daemon gates portal clients on fd handoff + -- (when an app connects via the stolen fd) by removing + -- PW_PERM_R from PW_ID_CORE and setting the property + -- pipewire.access.portal.gated to true. This makes + -- the client busy so the daemon stops reading from the + -- socket until permissions are set up properly. + -- + -- two timing scenarios handled: + -- 1) gate is already set so ungate immediately. + -- 2) gate is set later (app connects after PermissionManager attached) + -- watch for the property change and ungate then. + local access = client:get_property ("pipewire.access") + if access == "portal" then + client:connect ("notify::properties", function (c) + local gated = c:get_property ("pipewire.access.portal.gated") + if gated == "true" then + c:update_permissions { [0] = "rwx" } + log:info (c, string.format ( + "Ungated portal client '%s' (via property change)", + app_name)) + end + end) + local gated = client:get_property ( + "pipewire.access.portal.gated") + if gated == "true" then + client:update_permissions { [0] = "rwx" } + log:info (client, string.format ( + "Ungated portal client '%s' (gate was already set)", + app_name)) + end + end + transition:advance () end) else