Sonny's

I am no longer a member of the board of directors of the GNOME Foundation since May 2024. The process and decision shocked me. I know people are looking for answers, but I want to protect people involved and the project/foundation. It was never an interpersonal conflict for me.

I want to thank every member who entrusted me with their vote and share a little retrospective of my work under that hat.

I'm happy to report that both suggestions I proposed during my candidacy to engage the foundation/community with are already in effect.

Decentralizing GUADEC is part of the 5 years strategy plan under the objective Six

Create a more strategic, more inclusive, less expensive, more worldwide, and greener annual event for GNOME, with a central event at its core, and multiple, regional, worldwide local events on all continents happening in conjunction and unified through the core event. Under this model, GUADEC and regional events would be integrated into a more strategic framework.

While I cannot join – I'm happy to see people enjoying GUADEC in two large venues; Denver and Berlin. Thanks to the local teams.

Development funding is part of the 5 years strategy plan under the objective Four

Promote the GNOME Development Initiative (the “Initiative”) as our internal development project for core needs, such as security, IT infrastructure, transparency, usability, supply chain, GNOME.org; this takes the STF-funded project now launched and builds upon it into the future, making it a permanent part of the GNOME Foundation.

This is already in motion with the GNOME STF initiative. Please join (Berlin) or watch (recorded) the talk “GNOME STF Project” to learn more about it.

When it comes to supporting the community

And supporting the foundation

  • Helped Holly secure the Gimp fiscal sponsorship
  • Helped Holly develop the GNOME Development Initiative
  • Worked towards improving the relationship between the foundation and the community
  • Informed the board of several issues putting the project and/or organization at risk

I hope we can learn to address/solve dysfunctions and conflicts to create a healthier environment for everyone. That is now out of my hands / responsibilities, and I'll focus on positive things for the time being.

❤️

Sonny

Nightly

Workbench is now available on the GNOME nightly repository.

Please prefer Workbench from Flathub but if you're a GNOME contributor, Workbench nightly can come handy

flatpak remote-add --if-not-exists gnome-nightly https://nightly.gnome.org/gnome-nightly.flatpakrepo
flatpak install gnome-nightly re.sonny.Workbench.Devel

It is the first app on GitHub to be available on GNOME nightly. Thanks to Jordan Petridis and Bilal Elmoussaoui for the help.

GSoC

I'm very happy to announce that as of yesterday we are mentoring 2 students on Workbench.

Angelo Verlain (aka vixalien) is a student from Kigali, Rwanda. Angelo is already a GNOME Foundation member and made significant contributions including an audio player app “Decibels” that is being incubated to join GNOME core apps.

Bharat Tyagi is a student from Jaipur, India. Bharat made great contributions to Workbench during the GSoC contribution period, and I'm looking forward to seeing more of it. You can read their introduction here.

Angelo is working on TypeScript support in Workbench and GNOME.

Bharat is working on porting remaining demos to Vala, redesigning the Library and add code search to it.

Very happy working with both of them

International Workers' Day marks the release of Workbench 46.1

Download on Flathub

This new release comes with

Save/restore window state and dimensions for each session/project. I couldn't use the method defined in Saving and restoring state into GSettings because resizing manually with the mouse triggers a lot of blocking disk writes and cause the user action to appear sluggish. So I debounce the events and write to gsettings manually.

Find text in the current editor. The keyboard shortcut is Ctrl+F. This is a feature started by Sriyansh Shivam during their GSoC 2023 internship and finished by UrtsiSantsi. Thanks!

SVG Library entry. Gtk (via gdk-pixbuf) draws SVGs at their intrisic sizes (what is defined in the svg document). If you use different dimensions for example using GtkImage.pixel-size then it is the pixmap that gets upscaled resulting in pixelated / blurry images. This new Library entry showcases how to render an SVG at arbitrary dimensions using librsvg. We may need a better primitive in the future, if you need an SVG Paintable; GTK Demo contains an example. See also this conversation.

A screenshot of the "SVG" Library entry

Reveal In Files. This is a new option available in the menu that will reveal the session/project in Files. You can use it to add assets to your project and load them using workbench.resolve or as icons.

Import icons into your projects. Using the “Reveal In Files” option you can now add custom icons to your projects. It's just a matter of dropping the files in the right folder. See the “Using Icons” Library entry.

A screenshot of the "Using Icons" Library entry

Workbench included an Icon Library and icon-development-kit for a while but in an effort to simplify Workbench and since we already have an Icon Library app, I decided to remove both in favor of per project icons.

I'm quite happy with the developer experience there and I hope we can provide something similar in the future to move beyond GtkIconTheme. We probably need to keep icon-name as suggested in Updates from inside GTK but I'd be very interested supporting relative paths in GTK Builder. Thankefully we already have GResource to allow for something like

Gtk.Image {
  src: "./smile-symbolic.svg";
}

7 new Library entries ported to Vala

  • Radio Buttons
  • Switch
  • Revealer
  • Styling with CSS
  • Separator
  • Level Bars
  • Link Button

Also

  • “Animation” Library entry ported to Python
  • Split “List View Widget” Library entry into “List View” and “Grid View”
  • Fix Vala and Rust extensions detection on “Run”
  • List editor shortcuts in Shortcuts

Thank you contributors and GSoC applicants.

Retro; the customizable clock widget is now available on Flathub in v2

Download on Flathub

This new release comes with

Support both 12h and 24h clock format. It follows GNOME Date & Time preference while being sandboxed thanks to libportal new API for the settings portal.

Energy usage has been improved by using a more efficient method to get the time and by making use of the magic GtkWindow.suspended property to stop updating the clock when the window is not visible.

Better support for round clocks. The new GTK renderer fixed the visual glitch on transparent corners caused by large border radius. Retro now restores window dimensions and disables the border radius on maximize to make it look good, no matter the shape.

Controls have been moved to a floating header bar to stay out of the way and prevent interference with customizations.

There are further improvements to do, but I decided to publish early because Retro was using GNOME 43 runtime which is end-of-life and I have limited time to spend on it.

Help welcome https://github.com/sonnyp/Retro/issues

Thanks to Gio.ListModel it is surprisingly simple to use a Gtk.ListBox as a vertical list of tabs for an Adw.TabView.

The benefit over using a simple Gtk.Stack is that Adw.TabView supports standard shortcuts for switching view.

Here is a GJS example that should translate well to other languages. You can try this directly in Workbench.

// This snippet goes into Workbench UI Blueprint

using Gtk 4.0;
using Adw 1;

Box {
  Gtk.ScrolledWindow {
    width-request: 200;
    Gtk.ListBox list_box {
      selection-mode: browse;
    }
  }
   
  Gtk.Separator {}
  
  Adw.TabView tab_view {}
}
// This snippet goes into Workbench Code JavaScript

import Gtk from "gi://Gtk?version=4.0";
import Adw from "gi://Adw?version=1";

import GObject from "gi://GObject";

Gtk.init();

const tab_view = workbench.builder.get_object("tab_view");
const list_box = workbench.builder.get_object("list_box");

// Create a binding between the Gtk.ListBox and the Adw.TabView

list_box.bind_model(
  tab_view.pages,
  // This function will be called for every new Adw.TabPage
  (tab_page) => {
    return buildTabRow(tab_page);
  },
);

list_box.connect("row-selected", (self, row) => {
  tab_view.set_selected_page(row.tab_page);
});

tab_view.connect("notify::selected-page", (self, page) => {
  list_box.select_row(tab_view.selected_page.list_box_row);
});

// Add some Adw.TabPage and let the binding do the rest

for (let i = 1; i < 11; i++) {
  const title = `hello ${i}`;
  const tab_page = tab_view.append(
    new Adw.StatusPage({
      title,
      hexpand: true,
    }),
  );
  tab_page.title = title;
}

// You probably should use a custom widget
// but this will do it for the purpose of this example

function buildTabRow(tab_page) {
  const list_box_row = new Gtk.ListBoxRow({
    selectable: true,
  });
  list_box_row.tab_page = tab_page;
  const label = new Gtk.Label();
  list_box_row.set_child(label);

  tab_page.list_box_row = list_box_row;

  tab_page.bind_property(
    "title",
    label,
    "label",
    GObject.BindingFlags.SYNC_CREATE,
  );

  return list_box_row;
}

Enter your email to subscribe to updates.