From d98515406245bbdcd940e38cb3c87453d2a8b70d Mon Sep 17 00:00:00 2001 From: Mark Stenglein Date: Mon, 6 Apr 2026 10:23:55 -0400 Subject: [PATCH] Fix keyring unlock blocking the Fyne event loop on startup (#900) GetServerPassword can block while the system keyring daemon shows its unlock dialog. Calling it synchronously on the Fyne main thread froze the event loop, causing Wayland compositors to hide the window. Move the keyring lookup into a goroutine and dispatch back to the Fyne thread to show the connecting dialog and attempt the connection. --- ui/controller/serverconnection.go | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/ui/controller/serverconnection.go b/ui/controller/serverconnection.go index 6d4b68e..eca2e6f 100644 --- a/ui/controller/serverconnection.go +++ b/ui/controller/serverconnection.go @@ -49,14 +49,24 @@ func (m *Controller) PromptForFirstServer() { // DoConnectToServerWorkflow does the workflow for connecting to the last active server on startup func (c *Controller) DoConnectToServerWorkflow(server *backend.ServerConfig) { - pass, err := c.App.ServerManager.GetServerPassword(server.ID) - if err != nil { - log.Printf("error getting password from keyring: %v", err) - c.PromptForLoginAndConnect() - return - } + // GetServerPassword may block on keyring unlock (showing a system dialog), + // so run it in a goroutine to avoid freezing the Fyne event loop. + go func() { + pass, err := c.App.ServerManager.GetServerPassword(server.ID) + if err != nil { + log.Printf("error getting password from keyring: %v", err) + fyne.Do(c.PromptForLoginAndConnect) + return + } - // try connecting to last used server - set up cancelable modal dialog + // Password retrieved; show the dialog and connect from the Fyne thread + fyne.Do(func() { + c.doConnectWithPassword(server, pass) + }) + }() +} + +func (c *Controller) doConnectWithPassword(server *backend.ServerConfig, pass string) { canceled := false ctx, cancel := context.WithCancel(context.Background()) dlg := dialog.NewCustom(lang.L("Connecting"), lang.L("Cancel"),