What will the future of Nautilus Annotations be? GtkWindow and get_file_items()

I am trying to port my Nautilus extensions to libnautilus-extension-4. The job was easily done with Nautilus Bluetooth (although now there is an independent issue with the bluetooth-sendto command, about which I will need to open a separate thread), but things get complicated with Nautilus Annotations (here is an old screencast of what the extension does).

There I need Nautilus’ window because I attach a dialog to it for annotating. The old interface provided it, but the new interface doesn’t (it was this commit by António Fernandes responsible for the change).

I believe Nautilus Annotations is a nice extension, It would be a pity to abandon it. But as things stand now it seems I have no choice (the commit explicitly says “We don’t want menu items to create their own windows in our process” – but that’s exactly what my extension does).

I had also other planned extensions that would attach their dialogs to Nautilus (I believe some nice ones!), and their future is also at stake with this change. The same goes for other extensions made by other programmers.

What will the future of Nautilus Annotations and other nice extensions be?

EDIT

@antoniof

António, just to outline how impacting this change is, even simply adding a “Do something” menu item that triggers a confirmation dialog that says “Are you sure you want to do something?” (“OK” / “Cancel”) has become impossible now.

Often when someone asks a question here the answer is “What problem are you trying to solve?”. So I would like to ask you the same question: What problem did this change (and more generally “de-GTK-izing the libnautilus-extensions API”) solve? Why should the libnautilus-extensions API make the GTK backend opaque? Does that solve a problem?

2 Likes

The problem it solves is the need to break extensions API every time we upgrade to a new version of GTK.

Indeed, the libnautilus-extensions API break this time would have been unnecessary if we had taken this step earlier. The goal is to make nautilus extensions more future proof. Namely, when we eventually move from GTK 4 to GTK 5, nautilus extensions should just keep working, because the API is GTK agnostic now.

Such confirmation dialogs are almost always bad practice in UI design.

But for the sake of example, we could just add a new extension API for extensions to ask nautilus to display such a dialog:

void nautilus_prompt_confirmation (const char *question, GAsyncReadyCallback callback, gpointer user_data); 
gboolean nautilus_prompt_confirmation_finish (GAsyncResult* result,  GError** error);

So, the need for a confirmation dialog would not be a reason for extensions to depend on GTK.

Let them be applications!

If it has got its own UI in its own window, then it’s already closer to being an application than an extension.

And the application could still ship a companion nautilus-extension. Just like the “Open in Terminal” extension doesn’t make the terminal part of nautilus, but spawns a separate application.

Hi António,

First of all thank you for your work on Nautilus. In the end I have found a trick and now the extension works fine on Nautilus 43. But the solution does feel a bit hacky.

I have tried to make the annotations window non-modal and non-transient, and the result is not as good – as it is now it is really ideal for me.

Even if you don’t pass a GtkWindow an extension might use GTK on its own, and in that case it will need to be ported anyway. Personally I find porting applications to newer version of GTK not too bad – I actually like the novelty. I understand that being GTK-free might feel “cleaner”, but in the real world as soon as an extension wants to do something a bit more articulate than launching an external app it will use GTK.

That for sure, and even with some priority. There are extensions that do destructive actions, like Nautilus Wipe for example. But even more “innocent” actions – like sharing a file – are not so innocent. I would definitely like to see a confirmation dialog before letting a file manager share my files on the internet.

So question dialogs. And also this would be a nice-to-have thing for the extensions :slightly_smiling_face:

The fact that it is an extension has prevented me to add a lot of useless features. I love its simplicity. It’s calming. And I already know that if I make an application out of it it will soon become full of futile functions.

Happy hacking!

―madmurphy

Thanks for your work in these cool extensions too!

The annotations editor doesn’t even look like a modal dialog, so why should it act like one? It’s a utility window, so it doesn’t have to be modal nor transient.

Indeed, that’s a wrong thing to do. Extensions shouldn’t peek into the internals of the application. Whatever is not exposed in the API is considered private.

Also, I plan to isolate extensions in a separate process (to avoid crashing the whole application if an extension crashes). Once this plan becomes a reality, this hack is not going to work anymore.

There are many extensions which do not use GTK. The API break would have been avoidable if libnautilus-extension didn’t depend on GTK.

While you may be happy to port your own extensions, there are many extensions that are not ported yet, and their authors may no longer be interested.

And in some cases, porting to a new version of GTK is quite hard. For instance, the PDF properties extension is not ported yet because it’s part of Evince. Evince is not ported to GTK4 yet and decoupling the extension code from the Evince code is a lot of work.

Another example: nautilus-dropbox is a rather important extension which isn’t ported yet. Many people have come to rely on it. So, the API break hurts users!

Depending on what this “something a bit more articulate” is, then either it’s something we could introduce new API for extensions to use, or it should be a new application.

Simple solution: just don’t add futile functions. Keep it simple. Make do one thing and do it well the mantra of your application.

There is something that does not add up for me. Let us imagine a scenario in which when Nautilus was ported from GTK3 to GTK4 you had not “de-GTK-ized” the libnautilus-extension API (basically source-wise the API would have remained the same); and let’s call this scenario “A” – here an extension might have used GTK or not. Now let us imagine another scenario in which the libnautilus-extension API had always been “de-GTK-ized”, and let’s call this scenario “B”.

Case A1: The libnautilus-extension API still passes a GtkWindow, but now (GTK4) this refers to something different than with GTK3; however the extension never used GTK. Extension porting required: none.

Case A2: The libnautilus-extension API still passes a GtkWindow, but now (GTK4) this refers to something different than with GTK3; the extension does use GTK. Extension porting required: porting from GTK3 to GTK4 required.

Case B1: The libnautilus-extension API has always been “de-GTK-ized” (also version 3); the extension never used GTK. Extension porting required: none:

Case B2: The libnautilus-extension API has always been “de-GTK-ized” (also version 3); the extension however uses GTK on its own. Extension porting required: porting from GTK3 to GTK4 required.

How did the B scenario help avoiding extension porting?

The annotations editor is heavily embedded in Nautilus. Annotations add their typical emblem to the annotated files and create an annotation column in the file manager. Furthermore, all changes must be updated in real time (e.g. Ctrl+S saves the annotation currently open and updates emblems and column in real time). And finally, I want to add to the annotation window an emblem picker that lets select custom emblems in any amount. With that feature the extension will become as embedded to Nautilus as a property dialog. But, most importantly, the whole idea of “annotating” files makes sense only within a file manager, because annotations are metadata, not data.

GApplication and GtkApplicationWindow are hardly private – they are exposed by the GLib and GTK libraries and they are unique. I would agree with you instead if I started to peek into heavily nested widgets (those are indeed definitely private and the code would look horrible). But I still think it feels hacky especially because the current direction seems to be that of isolating the extensions more and more, while my solution represents a step in the opposite direction, or at least an attempt to stay still.

This would be the same error as before. If I want to create a separate process already now I can call g_spawn_async(). But I am not forced to do that (by the way, how do you move populating a menu into a separate process? If my extension adds a menu item named “Go to Mars” and my code waits for Mars’ close approach, even if it is in a separate process Nautilus will have to wait for Mars to approach Earth before showing the menu item).

It is exactly like when the libnautilus-extension API was still tied to GTK but people were still free to create extensions that did not depend on GTK – I also created three “GTK-free” extensions in the past…

In general, forcing developers to follow a path is hardly the right thing to do. Good developers will know when it is better to move the code to a separate process or not use GTK anyway.

This is a strange argument. If as you say that most extensions don’t use GTK, without your commit they would not have ended up broken with Nautilus 43. While the ones that use GTK would break in any case (see initial examples).

―madmurphy

Not true. In all cases listed, porting is always required, because the library soname has changed, the installation directory has changed, etc.

It avoids future API breaks (e.g. when nautilus is ported from GTK 4 to GTK 5 ). No porting will be required then.

This time around porting was unavoidable because libnautilus-extensions-3 depended on GTK 3. If that dependency didn’t exist, there would have been no need to break the compatibility of all extensions.

By “editor” I mean only the window through which the user can edit the text of the annotation.

Naturally, the rest of the extension makes sense to remain as an extension. Only the editor window should be taken out of process.

That’s not true. libnautilus-extension-3.0 depended on GTK 3. The dependency was always there, even if the extension did not use any GTK API.

I think this is where you are really confused.

As I wrote above, libnautilus-extension-3.0 depended on GTK3.

In practice, moving nautilus to GTK4 meant breaking compatibility with every extension, evem those which didn’t use any GTK API but still depended on it through libnautilus-extension-3.0

There was no way to avoid that.

Now there is a way to avoid it happening again in the future. And that’s what I did.

I think we must distinguish between source-compatibility and binary-compatibility. What matters to us is only source compatibility.

A very simple (non-GTK) extension of mine is Nautilus Bluetooth. These are the changes that were required to port it to libnautilus-extension 4. As you can see, they are very minimal and nothing has to do with GTK. That means that without the recent changes in the source (the header) of libnautilus-extension there would be no porting required.

That I mean by porting: a change in the source code of the extension and the need of an intervention of the author. No change would be needed in that case. Nautilus would use a newer version of GTK, but Nautilus Bluetooth wouldn’t care.

Of course the extension would still need to be recompiled, because binary compatibility would still break. But compiling packages is done all the time by distro maintainers or machines without much effort.

So I think my recap still holds: without the recent de-GTK-izification Nautilus Bluetooth would have worked with Nautilus 43 without interventions from me (with the exception of a small update in the build system). Many extensions are exactly like Nautilus Bluetooth.

―madmurphy

This is more like a side note, unrelated with the main point.

Strictly speaking, the PDF properties extension depends on Evince’s libdocument, which ideally should not depend on Gtk.

It would be ported if my PR was accepted :slight_smile:

That said, users can build the extension if they are able to follow the instructions

nautilus-dropbox actually does include gtk3, so it would have broke in Nautilus 43 regardless of the libnautilus API break.

Exactly. That is what I meant with my previous reply.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.