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~11,800
HB_FUNC functions~172
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. WebKit2GTK (optional, for TWebView):
    sudo apt install libwebkit2gtk-4.1-dev

    Without this package, TWebView controls display a placeholder. The build script auto-detects WebKit2GTK and enables it when available.

  4. 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 webkit2gtk4.1-devel gcc harbour
On Arch: sudo pacman -S gtk3 webkit2gtk-4.1 harbour harbour-contrib
On openSUSE: sudo zypper install gtk3-devel webkit2gtk3-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

WebView Support (WebKit2GTK)

The TWebView control provides an embedded web browser using WebKit2GTK. The build script automatically detects the library and enables it at compile time.

Installation

# Ubuntu / Debian
sudo apt install libwebkit2gtk-4.1-dev

# Fedora
sudo dnf install webkit2gtk4.1-devel

# Arch Linux
sudo pacman -S webkit2gtk-4.1

Build Detection

The build_linux.sh script automatically detects WebKit2GTK:

After installing the dev package, force a rebuild of the GTK3 backend:

rm -f source/gtk3_core.o
./build_linux.sh

You should see:

  WebKit2GTK 4.1 detected — WebView enabled

Supported Functions

Method / PropertyDescription
cUrlGet/set the current URL (navigates on set)
Navigate(cUrl)Load a URL
LoadHTML(cHtml)Load raw HTML content
GoBack()Navigate back in history
GoForward()Navigate forward in history
Reload()Reload the current page
Stop()Stop loading
GetUrl()Get the current URL
EvaluateJS(cScript)Execute JavaScript
CanGoBack()Returns .T. if back navigation is available
CanGoForward()Returns .T. if forward navigation is available

Example

// WebView in a form
@ 44, 0 WEBVIEW ::oWebView1 OF Self SIZE 800, 500 URL "https://harbour.github.io"

// Navigate programmatically
::oWebView1:Navigate( "https://github.com" )

// Execute JavaScript
::oWebView1:EvaluateJS( "document.title" )
Without WebKit2GTK

If the dev package is not installed, TWebView displays a static label reading "WebView (install libwebkit2gtk-4.1-dev)". All navigation methods become no-ops. The cUrl property still stores the URL for serialization.

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
libwebkit2gtk-4.1-devWebKit2GTK for TWebView (optional, auto-detected)
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 WebView Support Known Limitations Dependencies