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.
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.
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”
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.
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;
}