Public and inspectable work

GTK on Linux: learning by building

A practical progression from a Python Flatpak utility, through C and GTK internals, to a security-conscious Rust application designed for the Xfce desktop.

Role
Creator and developer
Period
2026–present
Status
Active exploration and open-source work
Focus
GTK 3 / GTK 4, Rust, C17

Rebuilding my personal toolbox on Linux

I moved my home and work laptops to Fedora Linux in January 2026, using Cinnamon and Xfce across different machines. I value both desktops because they are fast, understandable, and easy to configure around the way I work.

On Windows, I had always reached for WinForms when I wanted a small application to solve a problem for myself. Moving to Linux created a useful new learning thread: understand GTK well enough to build the same kind of practical native desktop software, then explore how Python, C, and Rust each feel at that boundary.

This is current exploratory work rather than another flagship career project. It is here because it shows what is keeping my attention now: learning a different platform by making useful things, following the stack down when I need to understand it properly, and applying the same architecture and security habits I use in commercial systems.

GTK in brief

GTK is the open-source widget toolkit behind a large part of the Linux desktop. It provides the windows, controls, input, accessibility, theming, and application plumbing used by many native applications across environments including GNOME, Cinnamon, and Xfce.

The interesting part for me is that GTK is not tied to one language. Python makes it quick to get a useful interface running; C exposes the conventions and object model used by the platform itself; Rust offers native performance and direct GTK integration with a much stronger type and memory-safety model. Working through all three has made the trade-offs much more concrete than reading about them would have done.

Flatver: solve a real problem first

My first GTK application was Flatver, written in Python with GTK 4 and Libadwaita. A few Flatpak updates had broken applications I depended on, including Docker Desktop and Remmina, and I wanted a clear graphical way to inspect available versions, roll an application back, and prevent the known-working version from being immediately updated again.

Flatver lists installed Flatpak applications, reads their commit history, identifies the installed revision, deploys an earlier commit, and manages Flatpak masks. The interface performs the slower command-line work away from the GTK thread, and the project includes the desktop metadata, icon, manifest, and sandbox permissions needed to package the tool as a Flatpak itself.

Python was the pragmatic choice for a first attempt: it let me prove the workflow and become familiar with GTK without simultaneously learning its lowest-level APIs. The result is a useful application, but it also showed me that I wanted a clearer understanding of the platform underneath the bindings.

Learning the toolkit in C

I built parallel GTK 3 and GTK 4 playgrounds in C17 to learn the native model directly and to understand enough of the surrounding ecosystem to contribute to established Linux desktop projects.

They are structured experiments rather than tutorial snippets. Static layout lives in GtkBuilder .ui files, styling in SCSS, UI behaviour in dedicated C modules, and models, persistence, files, and HTTP work in a separate core. The examples cover GObject models, JSON-GLib serialisation, GIO-based file handling, file trees, asynchronous REST calls with libsoup, pagination, article details and comments, image loading, and both core and display-backed tests.

Maintaining equivalent GTK 3 and GTK 4 versions also exposed meaningful API differences: synchronous versus asynchronous dialogs and close flows, different widget composition patterns, and the practical cost of supporting applications at different points in the Linux desktop's evolution.

C gave me the direct understanding I wanted, and I enjoy working close to the platform. It also made the maintenance cost very visible. Even ordinary application concerns such as JSON data, HTTP responses, ownership, and error cleanup expand into a lot of code. That led naturally to the next experiment.

Rust as the balance I was looking for

Rust retains the native-code characteristics that matter for desktop and systems work while making ownership, lifetimes, errors, and state transitions explicit in the type system. For new GTK work, it feels like a strong balance between modern application structure and the performance and interoperability expected by the Linux desktop.

I am applying that approach in Xfce Profile Editor, an independent Rust/GTK 4 proposal for editing the current user's system-backed profile information. It is not an official Xfce component and it is still under active development, but it has already moved well beyond a throwaway experiment.

The visible form is intentionally small: profile image, name, phone numbers, and email. The interesting engineering sits behind it. Those values belong to different system services; some changes are available through AccountsService over D-Bus, while updating selected local account fields requires a privileged operation.

Rather than elevating the entire graphical application, the design uses a separate GTK-free helper behind a narrowly scoped Polkit action. The helper can update only the supported fields for the authenticated current user, validates the input again at the privilege boundary, preserves account fields the UI does not expose, invokes the system account tool without a shell, and verifies the result. Image work includes validation, normalisation, atomic persistence, AccountsService coordination, removal, camera discovery, and capture through an optional Linux camera feature.

The project carries forward the separation explored in C: GtkBuilder resources and SCSS own presentation; thin Rust UI modules connect state and signals; GTK-independent core modules own system access and data transformations. Meson provides the native build and installation path, Cargo handles the Rust workspace and tests, and user-facing text is ready for translation through gettext.

Where this work is now

This thread is still moving. Flatver solves a problem I had; the C repositories record deliberate platform learning; and the profile editor is a promising work in progress that still needs its remaining manual review and release work before I would call it finished.

That is why it sits at the end of this portfolio rather than ahead of larger commercial systems. Its value is different: it shows the curiosity to move onto an unfamiliar desktop stack, compare languages by building the same class of software, and turn a personal irritation or missing utility into concrete, inspectable engineering.

Why I include this work

  • Practical Linux desktop development across Python, C, and Rust rather than language exercises in isolation.
  • The ability to move from a quick useful tool into deeper platform learning and then apply those lessons to a more substantial design.
  • Native GUI architecture with GtkBuilder, GTK 3/4, GObject, asynchronous work, persistence, HTTP APIs, testing, packaging, and translation support.
  • Security-conscious handling of D-Bus services, Polkit authorisation, narrowly scoped privilege, input validation, and partial system failures.
  • A current interest in contributing useful software to the Xfce ecosystem, while being precise about what is exploratory, independent, and unfinished.