Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
application.h
Go to the documentation of this file.
1/* The application's GUI: the window it owns, the panels in it, the theme it wears, and the
2 * process of bringing all of that up and taking it down.
3 *
4 * This is the half of the old gui/gtk.c that is genuinely about *this* application. The other
5 * half -- containers, labels, popovers, notebooks, dialogs, resizable panes -- was toolkit
6 * code that merely happened to live here, and now lives in widgets/ with no way back to any
7 * of this. The file is no longer called gtk.c partly because that name described its
8 * accidental contents rather than its purpose, and partly because a gtk.h of our own, two
9 * directories away from the system <gtk/gtk.h>, is a trap nobody needs -- as the first
10 * attempt at this rewrite proved by matching that path with a sloppy pattern.
11 */
12
13/*
14 This file is part of darktable,
15 Copyright (C) 2009-2014 johannes hanika.
16 Copyright (C) 2010-2011, 2013 Henrik Andersson.
17 Copyright (C) 2011 Robert Bieber.
18 Copyright (C) 2011-2019 Tobias Ellinghaus.
19 Copyright (C) 2011, 2015 Ulrich Pegelow.
20 Copyright (C) 2012, 2014, 2019-2022 Aldric Renaudin.
21 Copyright (C) 2012 Richard Wonka.
22 Copyright (C) 2013, 2015, 2018-2022 Pascal Obry.
23 Copyright (C) 2013-2016, 2020 Roman Lebedev.
24 Copyright (C) 2013 Simon Spannagel.
25 Copyright (C) 2014 Mikhail Trishchenkov.
26 Copyright (C) 2014-2016, 2019 parafin.
27 Copyright (C) 2015, 2017 Jérémy Rosen.
28 Copyright (C) 2015 Pedro Côrte-Real.
29 Copyright (C) 2016-2017 Peter Budai.
30 Copyright (C) 2017-2018 Dan Torop.
31 Copyright (C) 2017-2018 Matthieu Moy.
32 Copyright (C) 2018 Heiko Bauke.
33 Copyright (C) 2018 Rikard Öxler.
34 Copyright (C) 2019-2020, 2022-2023, 2025 Aurélien PIERRE.
35 Copyright (C) 2019 Kevin Daudt.
36 Copyright (C) 2020 Bill Ferguson.
37 Copyright (C) 2020-2022 Chris Elston.
38 Copyright (C) 2020-2022 Diederik Ter Rahe.
39 Copyright (C) 2020 Hanno Schwalm.
40 Copyright (C) 2020 Harold le Clément de Saint-Marcq.
41 Copyright (C) 2020 Hubert Kowalski.
42 Copyright (C) 2020 Mark-64.
43 Copyright (C) 2020-2021 Philippe Weyland.
44 Copyright (C) 2021 Ralf Brown.
45 Copyright (C) 2022 luzpaz.
46 Copyright (C) 2022 Martin Bařinka.
47 Copyright (C) 2022 Nicolas Auffray.
48 Copyright (C) 2023 Luca Zulberti.
49 Copyright (C) 2025 Alynx Zhou.
50 Copyright (C) 2026 Guillaume Stutin.
51
52 darktable is free software: you can redistribute it and/or modify
53 it under the terms of the GNU General Public License as published by
54 the Free Software Foundation, either version 3 of the License, or
55 (at your option) any later version.
56
57 darktable is distributed in the hope that it will be useful,
58 but WITHOUT ANY WARRANTY; without even the implied warranty of
59 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
60 GNU General Public License for more details.
61
62 You should have received a copy of the GNU General Public License
63 along with darktable. If not, see <http://www.gnu.org/licenses/>.
64*/
65
66#ifndef DT_GUI_APPLICATION_H
67#define DT_GUI_APPLICATION_H
68
69/* Only what the declarations below need, and nothing else -- a header that includes more
70 * becomes an invisible supply line for its consumers (see CLAUDE.md, "A header includes only
71 * what its own declarations need"). Audited symbol by symbol:
72 * paths.h PATH_MAX, for the gtkrc member
73 * dtpthread.h dt_pthread_mutex_t, likewise a member -- it used to arrive transitively
74 * window_manager dt_ui_t, dt_ui_container_t, dt_ui_panel_t in the panel signatures
75 * accelerators dt_accels_t, and dt_accels_new_action_shortcut() for the macros below
76 * gtk.h GtkWidget, GtkGrid, GtkMenu, cairo_surface_t, cairo_filter_t, PangoLayout
77 * stdint.h int32_t
78 * glib_utils.h, macros.h, mem_alloc.h and dtgtk/thumbtable.h were here for code that has
79 * since moved to widgets/; nothing declared here uses them. */
80#include "system/dtpthread.h"
81#include "common/paths.h"
82#include "gui/window_manager.h"
84
85#include <gtk/gtk.h>
86#include <stdint.h>
87
88
89
90#ifdef __cplusplus
91extern "C" {
92#endif
93
94/* --- Moved from darktable.h: GUI-flavored helpers belong to the GUI layer, and
95 * the orchestrator header must not export GTK/Pango API to the whole application. --- */
96
97/* Application-wide GUI singleton accessor: declared here by the owning lib, implemented by
98 * the orchestrator (darktable.c, next to dt_pixelpipe_cache_get_global()). It binds
99 * this header's macros and inline helpers to the `dt_gui_get_global()` instance without importing
100 * darktable.h into every GUI translation unit. */
101struct dt_gui_gtk_t;
102struct dt_gui_gtk_t *dt_gui_get_global(void);
103
104/* Sub-handles of the GUI singleton, and the two window lookups that dominate its use.
105 * The census behind doc/globals-migration.md showed dt_gui_get_global() is not one dependency
106 * but three -- the dt_ui_t handle, the write-once accelerator registry, and gtk.c's own
107 * scroll/DPI state -- so expose the first two directly instead of making every caller
108 * walk the application struct. dt_ui_main_window()/dt_ui_center() were called with the
109 * very same argument at 178 sites; these give them a name. */
110struct dt_ui_t *dt_gui_get_ui(void);
111struct dt_accels_t *dt_gui_get_accels(void);
113
118void dt_gui_set_themes(GList *themes);
120
121/* Pixel scaling - two intents, chosen by the *destination sink* (not by platform).
122 * See doc/gui.md "Pixel scaling" for the full rationale.
123 *
124 * DT_UI_SCALE_UI: logical-px GUI sinks (gtk_widget_set_size_request, window default
125 * size, anything fed to a GTK widget geometry setter). GTK already multiplies these
126 * by the integer scale-factor (ppd) at render time, so we must NOT pre-apply ppd here;
127 * we only add the font/UI zoom carried by dpi_factor (the X11 Xft.dpi path).
128 *
129 * DT_UI_SCALE_DEVICE: raw device-pixel buffers (cairo image surfaces, pixbuf-at-size,
130 * mouse hit-test radii). The toolkit does not auto-scale these, so we carry both the
131 * UI zoom (dpi_factor) and the integer scale-factor (ppd) ourselves.
132 *
133 * Input values are device-independent pixels at the 96 DPI baseline. */
134// DT_UI_SCALE_* / DT_PIXEL_APPLY_DPI* now come from widgets/widget_settings.h
135
136/* Deprecated spellings kept so the existing call sites keep compiling. Prefer the
137 * intent-named macros above in new code. */
138
139/* Spacing between children widgets within Gtk boxes/grids/flowboxes cannot be set from
140 * CSS (margins/paddings on the children would recess the ones sitting on the container
141 * edges relative to the inner ones). GTK exposes a "spacing" property for this, but only
142 * from code - so it is centralized here, in ONE place, for the whole app.
143 *
144 * It is expressed as a fraction of 1em (the resolved root font size, cached in
145 * dt_gui_get_global()->em by dt_gui_update_em()), so the inner gutters scale with the user's
146 * font size exactly like the em-based margins/paddings in ansel.css. 0.625em == 10px at
147 * the 16px reference font. Because the font's point->px conversion already folds in the
148 * screen DPI, this needs NO DT_PIXEL_APPLY_DPI on top.
149 *
150 * Falls back to the 10px reference before the GUI exists or before gui->em has
151 * been resolved. Standalone dialogs may run after gtk_init() but before the
152 * main Ansel GUI allocation when startup needs user input. */
153// DT_GUI_BOX_SPACING now comes from widgets/widget_settings.h
154
155typedef struct dt_gui_widgets_t
156{
157 /* left panel */
158 GtkGrid *panel_left; // panel grid 3 rows, top,center,bottom and file on center
161
162typedef struct dt_gui_gtk_t
163{
164
166
168
172
173 int32_t center_tooltip; // 0 = no tooltip, 1 = new tooltip, 2 = old tooltip
174
175 struct {
178 float velocity[2];
180 gboolean enabled;
183
184 // Culling mode is a special case of collection filter that is restricted to user selection
185 gboolean culling_mode;
186
187 // Track if the current selection has pushed on the backup copy
188 // see common/selection.h:dt_selection_push()
189
190 // Global accelerators for main menu, needed for GtkMenu mnemonics.
192
194
196
197 // Resolved root font size (1em) in device-independent px, read from the active
198 // theme/font by dt_gui_update_em(). Drives DT_GUI_BOX_SPACING so inner gutters
199 // track the font size like em-based CSS margins. 0.0 until first resolved.
200 double em;
201
202
203 struct {
204 gboolean is_dragging;
205 gboolean is_painting;
207
208 int icon_size; // size of top panel icons
209
210 // store which gtkrc we loaded:
212
213 GtkWidget *scroll_to[2]; // one for left, one for right
214 GtkWidget *scroll_to_header_once; // one-shot: module expander that should scroll to its header once
215
216
217 // scrolling focus
218 // This emulates the same feature as Gtk focus, but to capture scrolling events
219
220 cairo_filter_t filter_image; // filtering used for all modules expect darkroom
221 cairo_filter_t dr_filter_image; // filtering used in the darkroom
222
223 // Export popup window
224 struct {
226 GtkWidget *module;
228 struct {
230 GtkWidget *module;
232
233 dt_pthread_mutex_t mutex;
235
236
237
238
239
240
241
242// call class function to add or remove CSS classes (need to be set on top of this file as first function is used in this file)
243
246void dt_gui_gtk_quit();
247void dt_gui_store_last_preset(const char *name);
249
257void dt_ui_panel_show(dt_ui_t *ui, const dt_ui_panel_t, gboolean show, gboolean write);
261void dt_ui_notify_user();
263gboolean dt_ui_panel_visible(dt_ui_t *ui, const dt_ui_panel_t);
273// capitalize strings. Because grammar says sentences start with a capital,
274// and typography says it makes it easier to extract the structure of the text.
275
276#define dt_accels_new_global_action(a, b, c, d, e, f, g) dt_accels_new_action_shortcut(dt_gui_get_global()->accels, a, b, dt_gui_get_global()->accels->global_accels, c, d, e, f, FALSE, g)
277
278// dt_accels_new_darkroom_action() now lives in widgets/accelerators.h
279
280#define dt_accels_new_lighttable_action(a, b, c, d, e, f, g) dt_accels_new_action_shortcut(dt_gui_get_global()->accels, a, b, dt_gui_get_global()->accels->lighttable_accels, c, d, e, f, FALSE, g)
281
282#define dt_accels_new_map_action(a, b, c, d, e, f, g) dt_accels_new_action_shortcut(dt_gui_get_global()->accels, a, b, dt_gui_get_global()->accels->map_accels, c, d, e, f, FALSE, g)
283
284#define dt_accels_new_print_action(a, b, c, d, e, f, g) dt_accels_new_action_shortcut(dt_gui_get_global()->accels, a, b, dt_gui_get_global()->accels->print_accels, c, d, e, f, FALSE, g)
285
286#define dt_accels_new_slideshow_action(a, b, c, d, e, f, g) dt_accels_new_action_shortcut(dt_gui_get_global()->accels, a, b, dt_gui_get_global()->accels->slideshow_accels, c, d, e, f, FALSE, g)
287
288#define dt_accels_new_darkroom_locked_action(a, b, c, d, e, f, g) dt_accels_new_action_shortcut(dt_gui_get_global()->accels, a, b, dt_gui_get_global()->accels->darkroom_accels, c, d, e, f, TRUE, g)
289
290
291void dt_gui_add_help_link(GtkWidget *widget, char *link);
292
293// load a CSS theme
294void dt_gui_load_theme(const char *theme);
295
296// reload GUI scalings
298
299// Recompute the cached 1em size (dt_gui_get_global()->em) from the main window's resolved
300// font. Call after the theme/font or the screen DPI changes. Also re-applies the standard
301// inter-child spacing (DT_GUI_BOX_SPACING) to existing containers so the change is live.
302void dt_gui_update_em(void);
303
304// Set a PangoLayout's resolution to the screen DPI for crisp cairo-drawn text. Use this
305// instead of hand-writing pango_cairo_context_set_resolution(..., dt_gui_get_global()->dpi).
307
308// Apply the system's text-rendering options (anti-aliasing, hinting, subpixel order,
309// hint-metrics/kerning) to a Cairo context, sourced from @p widget's Pango context (the same
310// settings native GTK widgets use). Call on any off-screen/scratch Cairo surface before drawing
311// text so it matches the rest of the UI instead of Cairo's defaults. @p widget may be NULL (falls
312// back to the main window, then the screen). Pair with dt_gui_set_pango_resolution() for the DPI.
313
314
315
316
317// Give back the focus to the main/center widget, either
318// image in darkroom or thumbtable in lighttable
320
321#ifdef __cplusplus
322}
323#endif
324
325#endif // DT_GUI_APPLICATION_H
326
327// clang-format off
328// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
329// vim: shiftwidth=2 expandtab tabstop=2 cindent
330// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
331// clang-format on
Handle default and user-set shortcuts (accelerators)
GtkWidget * dt_gui_main_window(void)
void dt_ui_container_foreach(dt_ui_t *ui, const dt_ui_container_t c, GtkCallback callback)
calls a callback on all children widgets from container
struct dt_accels_t * dt_gui_get_accels(void)
void dt_ui_container_destroy_children(dt_ui_t *ui, const dt_ui_container_t c)
destroy all child widgets from container
struct dt_ui_t * dt_gui_get_ui(void)
gboolean dt_ui_panel_visible(dt_ui_t *ui, const dt_ui_panel_t)
get visible state of panel
Definition display.c:215
void dt_gui_load_theme(const char *theme)
int dt_gui_gtk_write_config()
void dt_gui_store_last_preset(const char *name)
void dt_configure_ppd_dpi(dt_gui_gtk_t *gui)
GtkWidget * dt_gui_center_widget(void)
void dt_gui_gtk_quit()
void dt_ui_toggle_panels_visibility(dt_ui_t *ui)
toggle view of panels eg. collapse/expands to previous view state
Definition display.c:116
struct dt_gui_gtk_t * dt_gui_get_global(void)
Definition darktable.c:523
void dt_gui_add_help_link(GtkWidget *widget, char *link)
void dt_ui_notify_user()
draw user's attention
void dt_ui_panel_show(dt_ui_t *ui, const dt_ui_panel_t, gboolean show, gboolean write)
shows/hide a panel
Definition display.c:128
int dt_gui_gtk_init(dt_gui_gtk_t *gui)
void dt_gui_refocus_center()
void dt_gui_set_themes(GList *themes)
Definition darktable.c:563
void dt_gui_set_pango_resolution(PangoLayout *layout)
GList * dt_gui_get_themes(void)
Definition darktable.c:558
void dt_gui_gtk_run(dt_gui_gtk_t *gui)
void dt_ui_container_focus_widget(dt_ui_t *ui, const dt_ui_container_t c, GtkWidget *w)
gives a widget focus in the container
void dt_gui_update_em(void)
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
Definition colorspaces.h:98
#define PATH_MAX
Definition paths.h:45
const char * name
Definition pdf.h:90
struct dt_gui_gtk_t::@33 export_popup
gboolean block_normal_pan
gboolean is_dragging
int32_t center_tooltip
cairo_surface_t * surface
dt_accels_t * accels
GtkMenu * presets_popup_menu
gboolean is_painting
double dpi_factor
dt_ui_t * ui
GtkWidget * scroll_to[2]
dt_pthread_mutex_t mutex
gboolean culling_mode
struct dt_gui_gtk_t::@31 pan_edge
cairo_filter_t dr_filter_image
gint64 last_time_us
gboolean enabled
GtkWidget * scroll_to_header_once
guint timeout_source
struct dt_gui_gtk_t::@32 mouse
float velocity[2]
char gtkrc[PATH_MAX]
GtkWidget * window
struct dt_view_t * view
cairo_filter_t filter_image
char * last_preset
struct dt_gui_gtk_t::@34 styles_popup
dt_gui_widgets_t widgets
GList * input_devices
GtkGrid * panel_right
GtkGrid * panel_left
dt_ui_container_t
dt_ui_panel_t