One of the larger refactorings that recently landed in GTK master is re-doing the entry hierarchy. This post is summarizing what has changed, and why we think things are better this way.
Entries in GTK 3
Lets start by looking at how things are in GTK 3.
GtkEntry is the basic class here. It implements the GtkEditable interface. GtkSpinButton is a subclass of GtkEntry. Over the years, more things were added. GtkEntry gained support for entry completion, and for embedding icons, and for displaying progress. And we added another subclass, GtkSearchEntry.
Some problems with this approach are immediately apparent. gtkentry.c is more than 11100 lines of code. It it not only very hard to add more features to this big codebase, it is also hard to subclass it – and that is the only way to create your own entries, since all the single-line text editing functionality is inside GtkEntry.
The GtkEditable interface is really old – it has been around since before GTK 2. Unfortunately, it has not really been successful as an interface – GtkEntry is the only implementation, and it uses the interface functions internally in a confusing way.
Entries in GTK 4
Now lets look at how things are looking in GTK master.
The first thing we’ve done is to move the core text editing functionality of GtkEntry into a new widget called GtkText. This is basically an entry minus all the extras, like icons, completion and progress.
We’ve made the GtkEditable interface more useful, by adding some more common functionality (like width-chars and max-width-chars) to it, and made GtkText implement it. We also added helper APIs to make it easy to delegate a GtkEditable implementation to another object.
The ‘complex’ entry widgets (GtkEntry, GtkSpinButton, GtkSearchEntry) are now all composite widgets, which contain a GtkText child, and delegate their GtkEditable implementation to this child.
Finally, we added a new GtkPasswordEntry widget, which takes over the corresponding functionality that GtkEntry used to have, such as showing a Caps Lock warning
or letting the user peek at the content.
Why is this better?
One of the main goals of this refactoring was to make it easier to create custom entry widgets outside GTK.
In the past, this required subclassing GtkEntry, and navigating a complex maze of vfuncs to override. Now, you can just add a GtkText widget, delegate your GtkEditable implementation to it, and have a functional entry widget with very little effort.
And you have a lot of flexibility in adding fancy things around the GtkText component. As an example, we’ve added a tagged entry to gtk4-demo that can now be implemented easily outside GTK itself.
Will this affect you when porting from GTK 3?
There are a few possible gotcha’s to keep in mind while porting code to this new style of doing entries.
GtkSearchEntry and GtkSpinButton are no longer derived from GtkEntry. If you see runtime warnings about casting from one of these classes to GtkEntry, you most likely need to switch to using GtkEditable APIs.
GtkEntry and other complex entry widgets are no longer focusable – the focus goes to the contained GtkText instead. But gtk_widget_grab_focus() will still work, and move the focus the right place. It is unlikely that you are affected by this.
The Caps Lock warning functionality has been removed from GtkEntry. If you were using a GtkEntry with visibility==FALSE for passwords, you should just switch to GtkPasswordEntry.
If you are using a GtkEntry for basic editing functionality and don’t need any of the extra entry functionality, you should consider using a GtkText instead.
Is GtkText or GtkPasswordEntry or a custom subclass on top of GtkText now able to support a multi-line password entry somehow?
@Mart: No, GtkText is still a single-line text entry, and GtkPasswordEntry uses GtkText.
Can you guys keep your websites up to date a bit?
Nothing is up to date correctly on gnome.org and gtk.org even more!
That’s frustrating when following the progress and the projects look like dead/dirty management.
A bit of perfectionism never hurts!
It looks that editable label widget is easier to be implemented?
Will it coming in GTK4?