When working on Glib/GTK, there are several points one should consider, to keep the code in shape.

Good habits

  • Use the G_DECLARE_* macros in the header when declaring object and interface types

  • Use a private structure for all instance data
    • Either use the G_DEFINE_WITH_PRIVATE macro, or use G_ADD_PRIVATE with G_DEFINE_WITH_CODE when defining object types

  • Public functions need to be annotated with the GDK_AVAILABLE_IN_X_Y macros in their respective header file

  • Private functions that can be used from multiple compilation units should go into the private header of the class they refer to
  • Private functions that are only used from a single compilation unit should be marked as static and not start with an underscore

  • Always use inline documentation for new public types, functions, and macros
  • Add Since: tags pointing to the next stable release when adding API
  • Instead of multiple GTK_FOO (widget) casts, declare GtkFoo *foo = GTK_FOO (widget); once

  • Always include config.h, and always include it first
  • Check that your commit doesn't introduce warnings
  • Use the versioned macros for marking deprecated API in headers: GDK_DEPRECATED_IN_X_Y, GDK_DEPRECATED_IN_X_Y_FOR()

  • Every new public header must have an unconditional single-include guard, preferably using #pragma once

  • Keep the inclusions in the global headers (gdk.h, gtk.h, etc) sorted alphabetically.

Coding Style

  • GTK coding style

  • GTK is pretty much kept GNU style, with a few exceptions. While the maintainers are not religious over stylistic issues, it is good to maintain consistent habits.

  • Avoid trailing whitespace, check your editor settings
    • Suggestion: enable a pre-commit hook in Git to avoid committing unnecessary trailing whitespace, for instance: here.

  • Use two spaces for indentation
    • Use real spaces. Do not change the length of the tab character in your editor to 2 spaces

  • When breaking conditions, use trailing boolean operators:
    •    if (you_need_to_break_this ||
             the_line_was_too_long)
           {
             ...
  • Use GtkFoo *bar_foo = GTK_FOO (bar) instead of GtkFoo *foo_bar = GTK_FOO (bar)

Quality of Implementation

Widgets in GTK are supposed to be general-purpose and high-quality, and are expected to be well-behaved in areas such as the following:

  • Documentation
    • GTK-Doc annotation for public functions, types, enumerations and macros
    • Internal documentation for data types and functions
    • Introspection annotations
  • Themability, including
    • Colors
    • Fonts
    • Sizes
  • Binding-friendlyness, including
    • full property support
    • trivial _new() functions
    • introspection annotations
    • vector-based variant for each variadic arguments function
  • GtkBuilder support

  • Internationalization, including
    • Translations
    • Input methods
    • RTL flipping
  • Accessibility, including
    • ATK interface
    • Key navigation
  • Platform support, including
    • Respecting GTK settings where appropriate
    • Use GdkModifierIntent when handling events

  • Multi-monitor awareness when positioning popups
  • DND support, where appropriate
  • Examples of usage
    • gtk3-demo
    • gtk3-widget-factory
  • Tests

Classes

  • Every signal handler, unless discussed, should have a default handler in the class vtable
    • If the class vtable is running out of padding, and after discussing it, pass 0 to the class_offset argument of g_signal_new(). If you need to override the class handler in a sub-class, use g_signal_override_class_handler() (available since GLib >= 2.18) or g_signal_override_class_closure().

Be binding friendly

Take a look at these notes: Writing bindingable APIs

Projects/GTK/BestPractices (last edited 2021-08-06 14:52:15 by AndyHolmes)