Lagrange v1.15: Preferences Redesign, Tab Reordering

v1.15 addresses some long-standing issues and feature requests, mainly related to tab management and multi-window behavior. The Preferences dialog has been redesigned and it now opens as a detached window. Tabs can be reordered and there is a new Window menu for desktop PC platforms.

Redesigned Preferences, now a detached window

The most noticeable change in this release is the new Preferences dialog.

Having Preferences be freely positioned naturally has the benefit that it's easier to see the effect of any changed settings since the view is unobstructed. The dialog also isn't artificially restricted to appear inside one UI root. This was an issue in split view mode, where the space available for the dialog could get too narrow. Now, it is clear that the dialog has application-level settings that are not specifically tied to any one window.

The reason why this wasn't done earlier is that top-level windows were expected to only be "main" windows, i.e., ones with a navbar and browser tabs. In v1.15, window bookkeeping was improved to allow for additional non-persistent, non-popup regular windows. This is another step on the multi-window journey that started in v1.11. The journey isn't quite complete, though: while I can now promote any widget to become a standalone window, these "extra" windows still aren't user-resizable. Once that is implemented in some future release, dialogs like the Upload Editor can be detached as well.

The `--prefs-sheet` command line option makes Preferences appear as an inline sheet like before. This may be preferred in some situations, e.g., on an older Raspberry Pi where it might take a moment to initialize a new OpenGL window.

New design

The way Preferences has evolved, with new settings being added in many releases over many months, has led to the dialog becoming rather inconsistent. For example, the "General" tab has accumulated all the settings that didn't have a suitable tab for them. There also wasn't that much space to add more tabs without making the dialog wider. The dialog is sized according to the contained pages, and it would be awkward if the dialog is wider than what is required. Multiple rows of tab buttons would be quite awkward as well, since then you'd have to be swapping the rows to keep the selected one in the bottom.

It made more sense to rethink things a bit and go with a solution that's pretty popular with multi-page dialogs: vertical tabs. This makes it easier to add new pages when needed without making the dialog wider, and eventually the list of tabs can be made scrollable.

With the design changing, this was a good time to rethink the organization of the tab pages. Of course, there isn't one correct way to organize these, but there should at least be some sort of internal consistency. The new tabs are roughly divided into three categories:

The big change is that the Fonts and Colors tabs have been dropped and replaced with one Page Style tab. The new Content tab has all settings related to page content and data handling, e.g., whether to view Markdown as source or styled Gemtext. This latter tab would also be a suitable place to add a GUI for managing content-filtering MIME hooks, if I decide to add such an interface in a future release.

If you've been using Lagrange for a while the changes here may require some getting used to. Alas, that is the case with all major UI changes. At least this new design should be more future-proof, and now there's also room to have a glanceable colored icon for each tab.

Reordering and moving tabs

By popular demand, document tabs can now be reordered. There are multiple ways to do this: you can just drag-and-drop a tab button with the mouse (within its tab bar), or use new keyboard shortcuts that shift the current tab left or right one step. The tab button context menu also has new actions: moving the tab left/right one step, moving the tab to the other side of a split view, and moving the tab to a new window.

This should cover most things that you'd want to do with tabs to reorganize them. However, there are a few restrictions, mostly due to the current limitations of the GUI toolkit. Firstly, drag-and-drop does not work across a split view or across windows. Secondly, you cannot move a tab into another window that already exists. And thirdly, there is no way to merge multiple windows back to a single one.

It's noteworthy that it took this long — until the 29th point release — to implement this feature. Tabs themselves have been available since v0.1. There are basically two factors at play: this is more of a nice-to-have than an essential feature, and there are some internal requirements that have been implemented gradually over the past couple of years. Now all the pieces are in place so the implementation was quite straightforward.

Window menu

Now in v1.15, PC platforms (e.g., Windows, Linux, *BSD) are getting a proper Window menu in the menu bar to manage the active window and its tabs, and switch between the open windows. On macOS, the app has always had a Window menu that's mostly updated by the operating system. A notable (albeit small) advantage of this menu is that it lets you duplicate tabs in a window where only a single tab is open. Tab duplication has thus far been only available in the tab context menu, and the tab bar is only visible if there are at least two tabs open.

TECHNICAL ASIDE: The Window menu is only available in the menu bar and not in the more compact hamburger menu. (The hamburger menu was the original menu implementation until the bar was added in v1.12.) There isn't enough room in the hamburger menu to add all the menu items, especially if there are multiple windows open with each of their titles listed. One solution would be to show the list of open windows in a dialog, but I reject that as clunky UX. A submenu is therefore needed. The problem is that the GUI toolkit doesn't currently support submenus, because a menu can be opened as a standalone popup window, and there is no support for opening a popup window from another popup. At some point I will likely get around to fixing this.

While working on the detached Preferences window and moving tabs between splits/windows, a few bugs were discovered and fixed:

Other improvements

Gopher menu styling

Preferences > Content has a new setting for controlling whether Gopher menus should use autodetected Gemtext styling. By default, the Gopher experience mimics that of Gemini, where preformatted ASCII art is in separate blocks and paragraph text has its own (variable-width) font. However, the autodetection doesn't always get it right. Menus with meticulously crafted ASCII may sometimes be misinterpreted.

Disabling the style autodetection makes all text lines equal in appearance. Then, also enabling monospace body text for Gopher (in the Page Style tab) will faithfully present the Gopher source text, with original whitespaces intact. This is what fans of classic Gopher will likely find optimal.

GTK dark theme property

A small detail for X11 users. Modern versions of GNOME/GTK allow choosing between a light and dark appearance for the desktop. When using the dark theme, all windows have a dark frame. However, when using the light theme, windows may still request a dark theme via an X11 window property. Lagrange will now set this property according to its current UI theme, so if you are using a light theme in GNOME but a dark theme in Lagrange, the app's window frame should now use the dark appearance, avoiding an inappropriate contrast between the window frame and contents.

If you are using Wayland, note that you likely will want to disable the new `ENABLE_X11_XLIB` CMake variable.

SDL's Wayland support is improving, but the latest version(s) of SDL may not be available on your particular distro without manual compilation.

Smaller details


While v1.15 has been desktop-focused, there is some work remaining to update the mobile ports with the latest code. Shouldn't be anything major, though. The biggest is perhaps tab drag-and-drop, but the code should mostly be in place already.

The 1.x series has been going for a while now. I've been thinking of a couple of larger changes that would warrant a new major version number. I'm not sure how long it'll take to implement them, so there may still be a small v1.16 while v2.0 is also being developed.

Native text rendering is one of the future work items that I've mentioned in previous release announcements. It is still being worked on. I've slowly been refactoring the text renderer to enable alternative implementations. After the TUI port (started in v1.13), the text renderer should now be in a good shape for this. The plan is to next write an implementation using Apple's Core Text, making it possible to properly use the system fonts (SF UI, etc.) on macOS and iOS/iPadOS. That would allow shipping the iOS version without any additional fonts installed, saving a few MBs. Using SF Symbols in the UI would also make the app look a lot more native and consistent.

📅 2023-01-21

🏷 Lagrange

CC-BY-SA 4.0

The original Gemtext version of this page can be accessed with a Gemini client: gemini://