Linux Platform Guide

The Linux backend uses GTK3 (C) for all native widgets, with Cairo for custom drawing. It is written in pure C and compiled with GCC, providing a native Linux experience that integrates with GNOME, XFCE, KDE, and other GTK-compatible desktop environments.

Backend Statistics
LanguageC
Lines of code~7,300
HB_FUNC functions~132
Native APIGTK3 (GtkWidget, GtkFixed)
DrawingCairo / Pango
Scintilla5.6.1 (shared library)
Supported DistrosUbuntu, Debian, Fedora, openSUSE, Arch, etc.

Architecture Overview

graph TB A["Harbour .prg"] --> B["hbbuilder.ch
#xcommand preprocessor"] B --> C["TForm, TControl
Harbour OOP classes"] C --> D["HB_FUNC Bridge
~132 functions"] D --> E["GTK3 Backend
C / GtkWidget"] E --> F["GTK Widgets
GtkButton, GtkEntry, etc."] E --> G["Cairo / Pango
Custom drawing"] E --> H["Scintilla 5.6.1
Shared lib"] style A fill:#58a6ff,stroke:#388bfd,color:#0d1117 style B fill:#8b5cf6,stroke:#7c3aed,color:#fff style C fill:#f59e0b,stroke:#d97706,color:#0d1117 style D fill:#f59e0b,stroke:#d97706,color:#0d1117 style E fill:#e95420,stroke:#c34113,color:#fff style F fill:#e95420,stroke:#c34113,color:#fff style G fill:#e95420,stroke:#c34113,color:#fff style H fill:#555,stroke:#333,color:#fff

Native Window Creation

Every HarbourBuilder form is a GtkWindow with a GtkFixed container for absolute-positioned child controls. The backend creates GTK widgets and stores their pointers in a handle table:

// gtk3_backend.c - Creating a form window
HB_FUNC( UI_FORMNEW )
{
   const char * cTitle = hb_parc( 1 );
   gint nWidth  = hb_parni( 2 );
   gint nHeight = hb_parni( 3 );

   GtkWidget * window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
   gtk_window_set_title( GTK_WINDOW( window ), cTitle );
   gtk_window_set_default_size( GTK_WINDOW( window ), nWidth, nHeight );
   gtk_window_set_position( GTK_WINDOW( window ), GTK_WIN_POS_NONE );

   // Use GtkFixed for absolute positioning of child controls
   GtkWidget * fixed = gtk_fixed_new();
   gtk_container_add( GTK_CONTAINER( window ), fixed );

   // Store handle in Harbour-side object table
   hb_retnint( (gintptr) window );
}

Controls map to GTK3 widgets:

HarbourBuilder ControlGTK3 Widget
Buttongtk_button_new_with_label()
Labelgtk_label_new()
Editgtk_entry_new()
Memogtk_text_view_new() (in GtkScrolledWindow)
CheckBoxgtk_check_button_new_with_label()
Radiogtk_radio_button_new_with_label()
ComboBoxgtk_combo_box_text_new()
ListBoxgtk_list_box_new() (in GtkScrolledWindow)
GroupBoxgtk_frame_new()
ProgressBargtk_progress_bar_new()
Slider/TrackBargtk_scale_new_with_range()
Imagegtk_image_new_from_file()
TabControlgtk_notebook_new()
TreeViewgtk_tree_view_new() (in GtkScrolledWindow)
Timerg_timeout_add()
StatusBargtk_statusbar_new()
ToolBargtk_toolbar_new()

Event Handling (g_signal)

The GTK3 backend uses GObject's signal system (g_signal_connect()) to connect native widget events to Harbour event handlers:

// gtk3_backend.c - Signal-based event binding
HB_FUNC( UI_ONEVENT )
{
   gint nHandle = hb_parnint( 1 );
   gint nEventId = hb_parnint( 2 );
   PHB_ITEM pBlock = hb_param( 3, HB_IT_BLOCK );

   GtkWidget * widget = GTK_WIDGET( GetHandlePtr( nHandle ) );

   // Store the Harbour code block
   StoreEventBlock( nHandle, nEventId, pBlock );

   // Connect the GTK signal to our dispatch function
   switch( nEventId )
   {
      case EVENT_CLICK:
         g_signal_connect( widget, "clicked",
                           G_CALLBACK( on_clicked_signal ),
                           GINT_TO_POINTER( nHandle ) );
         break;

      case EVENT_CHANGE:
         g_signal_connect( widget, "changed",
                           G_CALLBACK( on_changed_signal ),
                           GINT_TO_POINTER( nHandle ) );
         break;

      case EVENT_KEYDOWN:
         g_signal_connect( widget, "key-press-event",
                           G_CALLBACK( on_key_signal ),
                           GINT_TO_POINTER( nHandle ) );
         break;

      case EVENT_MOUSEDOWN:
         g_signal_connect( widget, "button-press-event",
                           G_CALLBACK( on_mouse_signal ),
                           GINT_TO_POINTER( nHandle ) );
         break;

      // ... additional signal connections
   }
}

// Signal callback dispatches to Harbour
static void on_clicked_signal( GtkWidget * widget, gpointer user_data )
{
   gint nHandle = GPOINTER_TO_INT( user_data );
   FireEvent( nHandle, EVENT_CLICK );
}

Dark Mode

GTK3 dark mode is controlled via GTK settings:

// gtk3_backend.c - Dark theme setup
void SetupDarkTheme( void )
{
   GtkSettings * settings = gtk_settings_get_default();

   // Check system theme preference
   gboolean prefer_dark = IsSystemDarkMode();

   g_object_set( settings,
                 "gtk-application-prefer-dark-theme",
                 prefer_dark,
                 NULL );
}
System theme detection

On GNOME, the system theme is read from org.gnome.desktop.interface gtk-theme via gsettings. The backend checks this at startup and sets gtk-application-prefer-dark-theme accordingly. On other desktop environments, the GTK settings daemon provides the same information through the standard GTK settings API.

Scintilla Integration

On Linux, Scintilla 5.6.1 is built as a shared library:

FileTypePurpose
libscintilla.soShared libraryScintilla core editing component
liblexilla.soShared libraryLexer library

Scintilla is loaded with dlopen() and dlsym() at runtime. The GTK Scintilla widget (ScintillaObject) is embedded in the code editor tab:

// Loading Scintilla on Linux
void * hSci = dlopen( "libscintilla.so", RTLD_LAZY );
if( !hSci ) {
   fprintf( stderr, "Failed to load Scintilla: %s\n", dlerror() );
   return;
}

// Creating the Scintilla GTK widget
ScintillaObject * sci = scintilla_new();
gtk_container_add( GTK_CONTAINER( editor_scrolled ), GTK_WIDGET( sci ) );
scintilla_send_message( sci, SCI_SETLEXER, SCLEX_CPP, 0 );

Build Process

Prerequisites

  1. GCC compiler:
    sudo apt install gcc g++
  2. GTK3 development libraries:
    sudo apt install libgtk-3-dev
  3. Harbour 3.2+ — Install from your distro's package manager or build from source:
    sudo apt install harbour
    Or clone from github.com/harbour/core.

Build Script (build_linux.sh)

The script performs these steps:

  1. Check prerequisites — Verifies that GCC and GTK3 headers are available.
  2. Build Scintilla — Compiles Scintilla and Lexilla shared libraries from source.
  3. Compile Harbour source — Runs the Harbour compiler on the IDE source files.
  4. Compile the backend — Compiles gtk3_backend.c with GCC.
  5. Link — Links everything together with GTK3, Cairo, Pango, and the Harbour runtime.
# build_linux.sh - Typical build session on Ubuntu/Debian
# Install dependencies
sudo apt update
sudo apt install libgtk-3-dev gcc g++ harbour

# Build
cd HarbourBuilder/samples
./build_linux.sh

# Run
../bin/hbbuilder_linux
Distro packages

On Fedora: sudo dnf install gtk3-devel gcc harbour
On Arch: sudo pacman -S gtk3 harbour harbour-contrib
On openSUSE: sudo zypper install gtk3-devel harbour

Compilation Details

# Manual compilation (what build_linux.sh does internally)
# 1. Compile Harbour source to C
harbour hbbuilder.prg -n -q -gc1

# 2. Compile C backend
gcc -O2 -c gtk3_backend.c \
    $(pkg-config --cflags gtk+-3.0) \
    -I$HBDIR/include \
    -I./include

# 3. Compile Harbour-generated C code
gcc -O2 -c hbbuilder.c \
    -I$HBDIR/include

# 4. Link
gcc -o hbbuilder_linux hbbuilder.o gtk3_backend.o \
    $(pkg-config --libs gtk+-3.0) \
    -lcairo -lpango-1.0 \
    -lscintilla -llexilla \
    -L$HBDIR/lib -lharbour \
    -ldl -lm

Platform-Specific Features

FeatureLinux Implementation
File dialogsgtk_file_chooser_dialog_new() with GtkFileChooserNative
Font dialogGtkFontChooserDialog
Color dialogGtkColorChooserDialog
Message dialogsGtkMessageDialog
Clipboardgtk_clipboard_get() / gtk_clipboard_set_text()
Drag and dropGTK drag-and-drop API (gtk_drag_dest_set())
System trayGtkStatusIcon / AppIndicator (depending on DE)
Dark modegtk-application-prefer-dark-theme GTK setting
Desktop integration.desktop file, MIME types, icon themes
PrintingGtkPrintOperation

Known Limitations

Dependencies

Package/LibraryPurpose
libgtk-3-devGTK3 headers and libraries (widgets, windows, events)
libcairo2-devCairo 2D graphics library (custom drawing)
libpango1.0-devPango text layout and rendering
libglib2.0-devGLib utility functions (timers, signals, memory)
libgdk-pixbuf2.0-devImage loading and manipulation
libscintilla.soCode editing component (shared library)
liblexilla.soLexer component (shared library)
libharbourHarbour runtime
-ldlDynamic loading (dlopen/dlsym for Scintilla)
-lmMath library

On This Page

Getting Started Component Palette IDE Features Tutorials Reference Platforms Architecture Overview Native Window Creation Event Handling (g_signal) Dark Mode Scintilla Integration Build Process Prerequisites Build Script (build_linux.sh) Compilation Details Platform-Specific Features Known Limitations Dependencies