Recently, there was a lot of action happening in Gtk+ git repository. It was the so called CSS Nodes, which supposely came to improve Gtk’s CSS features and other good things. If you want to know more about that, you can check these two great posts by Matthias Clasen: “A GTK+ update” and “CSS boxed in GTK+”. They, however, come with a downside: it needs some fixups from theme authors and developers too.
Since I just ported GNOME To Do and GNOME Calendar to this new model, and I had quite a hard time tracking down some issues, I decided to write this quick, small and incomplete guide for developers to port their applications to Gtk+ 3.19+.
Note: this is totally based on my personal experience porting the applications, so please, please, if you find any errors, report it and I’ll immediately fix.
The 3-step solution
In order to port your application codebase to Gtk+ 3.19+, there are 3 basic steps to follow:
- Replace gtk_widget_get_state_flags by gtk_style_context_get_state_flags
- Double check gtk_style_context_get* family of functions
- Add a CSS name (optional)
Lets check each step closely. I’m using Calendar’s port to use a CSS name as a case study here.
1. Replace gtk_widget_{get/set}_state_flags
Pretty self-explanatory title. An example (relevant section in bold letters):
GtkStyleContext *context; GtkStateFlags state_flags; context = gtk_widget_get_style_context (widget); state_flags = gtk_widget_get_state_flags (widget);
turns into
GtkStyleContext *context; GtkStateFlags state_flags; context = gtk_widget_get_style_context (widget); state_flags = gtk_style_context_get_state (context);
Since we’re now using GtkStyleContext API, the same is valid for gtk_widget_set_state_flags. You should use gtk_style_context_set_state instead.
2. Double check gtk_style_context_get*
Now the part the took most of my time to figure out how to fix. Obviously, if I had read Matthias’ blog post correctly, I would’ve done it way faster. While tracking down Calendar warning messages, they were coming from this function (among others):
gtk_style_context_get (context, GTK_STATE_FLAG_SELECTED, "font", &font_desc, NULL);
What’s wrong here? The issue is that we’re passing a state that can be different from the GtkStyleContext’s one.
To fix that, we simply have to set the GtkStyleContext’s state before calling the function, as demonstrated below:
gtk_style_context_save (context); gtk_style_context_set_state (context, GTK_STATE_FLAG_SELECTED); gtk_style_context_get (context, gtk_style_context_get_state (context), "font", &font_desc, NULL); gtk_style_context_restore (context);
Again, the relevant sections are bolded. Now, the last piece of this cake.
3. Add a CSS name (optional)
This one is quite easy. Instead of using the class type to match it, the widget sets a CSS name in the class_init function. Let’s check:
static void gcal_event_widget_class_init (GcalEventWidgetClass *klass) { GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); [...] gtk_widget_class_set_css_name (widget_class, "event-widget"); }
Now we have to update the theme file. In GNOME Calendar, the theme is stored in gtk-style.css:
GcalEventWidget { /* CSS properties */ }
event-widget { /* CSS properties */ }
Tada! It’s done. You now ported your widget to use a CSS name.
Conclusion
I reiterate that this is only my personal experience adjusting the widgets, and is prone to error. This is an ongoing work, so there may be changes after this guide is published (but I’ll try to keep this document updated).
Feel free to share your comments, ideas and rants 🙂
Leave a Reply