Skip to content

v0.20.8

Latest

Choose a tag to compare

@github-actions github-actions released this 24 Aug 18:31
· 19 commits to main since this release

What's Changed

Fixed

  • Sidebar context menu did not open when it had no room below the pointer (issue #298) — the third and last cause behind this report, found after 0.20.7 fixed the two selection bugs: moving the main window higher up made the same right-click work, which is the signature of a popup that cannot be placed rather than a handler that never ran. A GtkPopover can never be smaller than its child, and the menu's child is a plain box of up to twenty rows and six separators — around 700 logical pixels. That was the popover's minimum height, so where neither anchoring below the pointer nor flipping above it left that much room, GTK had nowhere to put the surface and it never mapped: no menu, no error, nothing in the log. The menu now lives in a ScrolledWindow capped at two thirds of the monitor's height, which keeps room for the flip in either direction and scrolls whatever does not fit; a short menu is still allocated exactly as tall as its items, so nothing changes for a group or the empty-space menu. Keyboard navigation is unaffected — a ScrolledWindow scrolls to whichever item takes focus. Separately, a menu that closes within 300 ms of opening with no user interaction now says so at debug level whether or not it was holding the input grab; the existing message only covered the grab-less case, which is why both this and #299 arrived as "the menu just does not open" with nothing to go on.

  • Embedded mode on Web connections reverted to System, permanently (reported for 0.20.7)WebBrowserMode::Embedded only existed as an enum variant when the web-embedded feature was compiled in, so a build without it parsed a stored browser_mode = "embedded" as System. The connection then sat in memory as System, and because connections.toml is rewritten whole from that in-memory copy, the next save of any connection destroyed the choice for every Web bookmark in the file — and updating last_connected on a single connect is enough to trigger one. Nothing warned: the downgrade was logged at debug level and the rewrite not at all. This needs no exotic setup. rustconn-cli takes rustconn-core with default-features = false and never enables the feature, so a CLI built on its own did it too, and any distribution package built without WebKitGTK 6.0 does it to a configuration written by a Flatpak build that has it — the three can share one ~/.config/rustconn. All three modes now exist in every build, and the feature decides whether Embedded can be run rather than whether it can be stored: a build with no WebView opens the URL in the system browser and leaves the stored mode alone, saying so at info level instead of silently. Round-tripping "embedded" through save and load is now asserted in both feature configurations.

  • rustconn-cli --browser-mode embedded set the opposite of what it asked for — the same root cause seen from the CLI: "embedded" fell through to the compile-time default, which for this crate is System. Both rustconn-cli add and rustconn-cli update now store the mode that was requested.

  • Editing a Web connection reset its page zoom and its certificate exception — the Web page of the connection editor has a widget for six of WebConfig's eight fields, and build_web_config rebuilt the other two from literals: zoom_level: 1.0 and accept_invalid_certs: false. So changing a bookmark's URL threw away the zoom the embedded browser had persisted from its own zoom controls, and cleared a certificate exception that only rustconn-cli can set — neither of which the dialog ever showed, so there was nothing on screen to suggest either was at stake. Saving now starts from the config the dialog was populated with and overlays what the widgets know; a new connection has no such value and correctly gets the defaults. In the same function, the custom browser command and user agent were only written into their rows when the stored value was Some, so editing a connection that had neither left whatever the previously edited connection had in those rows — and saving adopted it. Both are now set unconditionally, empty string included.

  • Config writes fought each other inside a single processflock(2) is held per open file description, so two writes contend even within one process, and .lock covers the whole config directory. RustConn has four independent writers: three debounce workers (connections, groups, trash) and the history flusher on its own thread, plus synchronous save_settings calls from GTK callbacks. One connect starts two of those two-second debounces at the same instant, so they woke together and one found the lock taken — which is why "Waiting for another rustconn instance to release config lock…" appeared roughly two seconds after every connect with no other instance running. In-process writers now queue on a mutex, leaving the advisory lock to do the job it is actually for, and the message no longer names a cause it cannot observe. Three further problems in the same path: the wait was unbounded, so a lock genuinely held by another process could freeze the window forever from a GTK callback — it is now bounded and reports a timeout instead; save_toml_file_async was a second, hand-maintained copy of the write sequence that opened with a synchronous flock, parking a runtime worker and defeating the caller's tokio::time::timeout (a timer only fires when the future yields, and a future stuck in a syscall never does), so the write now goes to a blocking-pool thread through the same single code path as the synchronous version; and flush_persistence took each pending snapshot out of its channel before awaiting the write and then used ?, so one failure on connections.toml discarded that snapshot and returned before groups and trash were written at all — three files lost to one error, on the shutdown path, with a single log line to show for it. All three are now attempted, and each snapshot is cleared only once its write succeeds.

  • A single credential lookup opened 25 encrypted Secret Service sessionsLibSecretBackend connected separately for every field of a credential, and oo7::dbus::Service::new() performs a DH key exchange each time (~12 ms, one "Starting an encrypted Secret Service session" line apiece). One retrieve therefore cost five connections — an availability probe plus one per field — and because resolving a credential tries five different lookup keys, a single click spent ~330 ms opening 25 of them. Visible in any debug log as a wall of identical oo7 lines whenever a password was not found. Each operation now opens one connection and passes it down, and the availability probe is cached briefly: SecretManager probes every backend before every lookup, for an answer that cannot meaningfully change inside one resolution. Storing a credential drops from four connections to one as well.

  • Embedded RDP and VNC toolbars were barely readable on a light theme — the floating toolbar carried a fixed dark scrim (rgba(36, 36, 36, 0.85)) and no foreground colour, on the reasoning that it floats over a remote desktop whose colours are not ours. Its contents are ours and take their colour from the local theme regardless, so under a light theme Copy, Paste, Autotype and the toolbar's icon buttons were near-black text on a near-black bar; only Ctrl+Alt+Del stayed legible, because suggested-action brings its own colour pair. The embedded browser had already been split out of that shared rule one release earlier for the same reason — a light URL bar inside a dark bar — which was this defect showing a different symptom. All three toolbars now follow the local theme the way a header bar does, and a drop shadow rather than a contrasting fill is what separates the bar from the content underneath. VNC and SPICE share the class and are fixed with it.

Dependencies

  • Updated: h2 0.4.18→0.4.19, open 5.4.1→5.4.2, syn 3.0.3→3.0.4. Seventeen further crates sit behind their latest release but cannot move: they are held at -rc or exact versions by constraints elsewhere in the graph (the RustCrypto stack pinned through ironrdp, picky and sspi), so they need an upstream release rather than a lockfile change.

  • Audited, no change needed: every auto-resolving CLI download endpoint answered — kubectl 1.36.4, Tailscale 1.102.3, Teleport 18.10.0, Boundary 0.21.3, Hoop.dev 1.148.0, Bitwarden CLI 2026.8.0, 1Password CLI 2.39.0 — and TigerVNC, the only pinned CLI download, is current at 1.16.2.

Installation

Flatpak (Recommended)

flatpak install flathub io.github.totoshko88.RustConn

Snap

sudo snap install rustconn

Debian/Ubuntu (.deb from this release)

sudo dpkg -i rustconn_0.20.8_amd64.deb
sudo apt-get install -f  # Install dependencies if needed

Fedora (.rpm from this release)

sudo dnf install rustconn-0.20.8-1.fc44.x86_64.rpm

AppImage

chmod +x RustConn-0.20.8-x86_64.AppImage
./RustConn-0.20.8-x86_64.AppImage

macOS (Homebrew)

brew tap totoshko88/rustconn
brew install rustconn
open $(brew --prefix)/opt/rustconn/RustConn.app

All dependencies (GTK4, libadwaita, VTE, Adwaita icons) are installed automatically.
Requires macOS 13 (Ventura) or later.

OBS Repositories

Packages available at: https://build.opensuse.org/package/show/home:totoshko88:rustconn/rustconn

# Debian 13 (Trixie)
echo 'deb http://download.opensuse.org/repositories/home:/totoshko88:/rustconn/Debian_13/ /' \
  | sudo tee /etc/apt/sources.list.d/rustconn.list
curl -fsSL https://download.opensuse.org/repositories/home:/totoshko88:/rustconn/Debian_13/Release.key \
  | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/rustconn.gpg > /dev/null
sudo apt update && sudo apt install rustconn

# Ubuntu 24.04 LTS (Noble)
echo 'deb http://download.opensuse.org/repositories/home:/totoshko88:/rustconn/xUbuntu_24.04/ /' \
  | sudo tee /etc/apt/sources.list.d/rustconn.list
curl -fsSL https://download.opensuse.org/repositories/home:/totoshko88:/rustconn/xUbuntu_24.04/Release.key \
  | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/rustconn.gpg > /dev/null
sudo apt update && sudo apt install rustconn

# Ubuntu 26.04 LTS (Resolute)
echo 'deb http://download.opensuse.org/repositories/home:/totoshko88:/rustconn/xUbuntu_26.04/ /' \
  | sudo tee /etc/apt/sources.list.d/rustconn.list
curl -fsSL https://download.opensuse.org/repositories/home:/totoshko88:/rustconn/xUbuntu_26.04/Release.key \
  | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/rustconn.gpg > /dev/null
sudo apt update && sudo apt install rustconn

# Fedora 44
sudo dnf config-manager addrepo --from-repofile=https://download.opensuse.org/repositories/home:/totoshko88:/rustconn/Fedora_44/home:totoshko88:rustconn.repo
sudo dnf install rustconn

# Fedora 43
sudo dnf config-manager addrepo --from-repofile=https://download.opensuse.org/repositories/home:/totoshko88:/rustconn/Fedora_43/home:totoshko88:rustconn.repo
sudo dnf install rustconn

# openSUSE Tumbleweed
sudo zypper ar https://download.opensuse.org/repositories/home:/totoshko88:/rustconn/openSUSE_Tumbleweed/ rustconn
sudo zypper ref && sudo zypper in rustconn

# openSUSE Leap 16.0
sudo zypper ar https://download.opensuse.org/repositories/home:/totoshko88:/rustconn/openSUSE_Leap_16.0/ rustconn
sudo zypper ref && sudo zypper in rustconn

Arch Linux (AUR)

yay -S rustconn

FreeBSD (Ports)

pkg install rustconn

Full installation guide: https://github.com/totoshko88/RustConn/blob/main/docs/INSTALL.md