You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Before hand-rolling buffer, hash and lock plumbing to show a per-pixel value under the mouse cursor, check src/develop/preview_data.h — the framework already owns that case; see GUI_Threading.md.
Module Lifecycle
Key Functions to Implement
Function
Purpose
gui_init()
Create and configure all widgets (do NOT set values here)
gui_update()
Sync widget values from self->params (called when params change)
gui_changed()
Adjust UI based on current state (show/hide widgets, update labels)
gui_cleanup()
Free any manually allocated resources
change_image()
Clear GUI state describing the old image — an image switch keeps the base instance, so gui_cleanup() never runs for it; also where pipe-scheduled GUI updates are cancelled (details)
init_pipe()
Allocate piece->data — needed for a data_t larger than params_t, or one with sub-allocations (when the defaults suffice)
commit_params()
Transform the params argument it is handed — self->params normally, default_params on the pipe's defaults sync (details) — into processing-ready piece->data for process()
cleanup_pipe()
Free piece->data and any sub-allocations
color_picker_apply()
Handle color picker results (if using pickers)
reload_defaults()
Update defaults for different image types
init_global()
One-time setup per module type (OpenCL kernels, shared LUTs)
cleanup_global()
Free resources from init_global()
process_cl()
GPU (OpenCL) processing — optional, falls back to process()
tiling_callback()
Report memory requirements for tiled processing
Key Data Structures
Struct
Stored in
Purpose
params_t
self->params, database
User-facing parameters — controlled by UI widgets, serialized to database
data_t (optional)
piece->data
Processing-optimized version of params — precomputed LUTs, transformed values, runtime state. Built by commit_params(), consumed by process(). If not defined, piece->data is a plain copy of params_t. The default allocation is sized by params_t either way, so a larger data_t needs its own init_pipe().
gui_data_t
self->gui_data
Widget references and GUI-only state — exists only where the module has a GUI: the darkroom, plus a throw-away instance built at startup
Data Flow
gui_init() → Create widgets, configure ranges/formats [1]
↓
gui_update() ← Called when params change (image switch, history)
↓
gui_changed() ← Apply UI adjustments (show/hide, sensitivity) [2]
↓
User interacts with widget
↓
Auto-callback (from_params) or manual callback [3]
↓
self->params updated
↓
dt_dev_add_history_item() → commit_params() → process()
│ │ │
records params transforms params reads piece->data
to history stack into piece->data (data_t or params_t)
Do not call gui_update() from gui_init() — params may not be ready yet.
If your module implements gui_changed(), call gui_changed(self, NULL, NULL) at the end of gui_update(); the framework does not call it for you there.
On the _from_params route the framework calls your gui_changed() (if implemented) and records the history item. A manual callback does both itself.
See GUI.md for the full event flow and callback patterns, and GUI_Threading.md for thread safety.