Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
widget_settings.h
Go to the documentation of this file.
1/*
2 * This file is part of Ansel,
3 * Copyright (C) 2026 Aurélien PIERRE.
4 *
5 * Ansel is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * Ansel is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with Ansel. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#ifndef DT_WIDGETS_WIDGET_SETTINGS_H
20#define DT_WIDGETS_WIDGET_SETTINGS_H
21
22/* Only what the declarations below need: GtkWidget/GdkRGBA/cairo_t (gtk.h), pthread_t, and
23 * va_list. This header used to include gui/screen_metrics.h purely to re-export
24 * dt_cairo_image_surface_*() to ~45 consumers that never asked it for them -- a supply line
25 * nobody declared and nobody could see, which breaks somewhere unrelated the day it is
26 * tidied. Those files include screen_metrics.h themselves now. */
27#include <gtk/gtk.h>
28#include <pthread.h>
29#include <stdarg.h>
30
32
33/* Toolkit-wide state that widgets need and the application merely configures.
34 *
35 * These three used to be fields of dt_gui_gtk_t, which meant a widget had to reach the
36 * application global to read its own event mask. They are not application data -- a scroll
37 * mask, a "who owns scroll right now" register and a cairo filter are properties of the
38 * widget toolkit. Ownership moves here so widgets/ needs nothing from gui/.
39 *
40 * The application sets them once during GUI init; everything else reads them.
41 */
42
46
47/* Which widget currently owns scroll input.
48 *
49 * Ansel routes scroll to one widget at a time rather than letting it propagate: a slider
50 * under the pointer takes the wheel, and views clear the register when they change. */
53
55cairo_filter_t dt_widget_image_filter(void);
56void dt_widget_set_image_filter(cairo_filter_t filter);
57
58
59/* Widget-update suppression.
60 *
61 * Programmatic widget updates must not be mistaken for user input. Code wraps such updates
62 * in dt_gui_freeze_begin()/end() and every widget callback opens with
63 * `if(dt_gui_widgets_suppressed()) return;`.
64 *
65 * The depth counter used to live in dt_gui_gtk_t, which meant a widget had to reach the
66 * application global to find out whether it should ignore its own callback. */
67gboolean dt_gui_widgets_suppressed(void);
68
73void dt_widget_set_gui_thread(pthread_t thread);
74
83gboolean dt_widget_on_gui_thread(void);
84void dt_gui_freeze_begin_(const char *file, int line);
85void dt_gui_freeze_end_(const char *file, int line);
86void dt_gui_freeze_reset(void); // hard-reset depth to 0 (GUI init only)
87
88/* Bracket programmatic widget updates with these so the widget's own "value-changed" handler
89 * does not mistake them for user input. The scope-guard form ends the freeze automatically on
90 * every exit path, including an early return, which the raw pair leaks. */
91#define dt_gui_freeze_begin() dt_gui_freeze_begin_(__FILE__, __LINE__)
92#define dt_gui_freeze_end() dt_gui_freeze_end_(__FILE__, __LINE__)
93
94typedef struct { const char *file; int line; } dt_gui_freeze_token_t;
96{
97 dt_gui_freeze_end_(t->file, t->line);
98}
99#define DT_FREEZE_CAT_(a, b) a##b
100#define DT_FREEZE_CAT(a, b) DT_FREEZE_CAT_(a, b)
101#define dt_gui_widget_freeze() \
102 dt_gui_freeze_token_t DT_FREEZE_CAT(_dt_freeze_guard_, __LINE__) \
103 __attribute__((cleanup(dt_gui_freeze_release_))) = { __FILE__, __LINE__ }; \
104 dt_gui_freeze_begin_(__FILE__, __LINE__)
105
106/* Scroll deltas in discrete units, accumulating smooth-scroll fractions and discarding
107 * pointer-emulated duplicates. Pure GTK event arithmetic. */
108gboolean dt_gui_get_scroll_unit_deltas(const GdkEventScroll *event, int *delta_x, int *delta_y);
109gboolean dt_gui_get_scroll_unit_delta(const GdkEventScroll *event, int *delta);
110
113void dt_widget_set_scroll_reversed(gboolean reverse_x, gboolean reverse_y);
114
115/* The host's root window, used for things that exist before any widget does: resolving theme
116 * colours at toolkit init, and parenting a popup so Wayland compositors place it correctly.
117 * Unregistered: NULL, and callers fall back to screen defaults. */
118typedef GtkWidget *(*dt_widget_root_window_handler_t)(void);
121
122/* How wide the host would like `widget` to be naturally -- it knows which panel the widget
123 * sits in and how wide that panel is. Returns -1 when the host has no opinion, which is also
124 * what an unregistered handler reports. */
128
129/* Transient user-facing message ("that widget no longer exists"). How and where it is shown
130 * is the host's decision -- a toast, a status line, or nothing at all. Unregistered, the
131 * message is dropped. */
132typedef void (*dt_widget_message_handler_t)(const char *message);
134void dt_widget_message(const char *message);
135
136/* Pointer shape during widget interaction (a panel-handle drag wants a resize cursor).
137 * The host owns the window whose cursor changes, so it supplies the setter. Unregistered,
138 * the cursor is left alone. */
139typedef void (*dt_widget_cursor_handler_t)(GdkCursorType cursor);
141void dt_widget_set_cursor(GdkCursorType cursor);
142
143/* ------------------------------------------------------------------------------------------
144 * Diagnostics.
145 *
146 * A debug build prints straight to stdout; a release build compiles the call away. widgets/
147 * deliberately does not route diagnostics through the application: a logging system means a
148 * global flags word and a global stream, and reaching for either is what this module exists to
149 * avoid. Nothing is lost by keeping it local -- these messages describe widget internals, and
150 * whoever is reading them is running a debug build anyway.
151 * ------------------------------------------------------------------------------------------ */
152#ifdef _DEBUG
153void dt_widget_log(const char *format, ...) G_GNUC_PRINTF(1, 2);
154#define dt_widget_log_enabled() TRUE
155#else
156/* Release compiles the call away, but its arguments must still count as USED. A variable
157 * computed only to be logged draws -Wunused-variable in Release only -- and the tempting fix
158 * is to delete the variable, which in two cases here would have deleted a call that must
159 * still run (_call_shortcut_cclosure() dispatches the shortcut; gtk_widget_activate()
160 * activates the widget). Referencing the arguments from an unreachable branch keeps them
161 * used, and gets Release the same format-string checking Debug has. Nothing inside is
162 * evaluated -- exactly what a compiled-away log did before. */
163static inline void G_GNUC_PRINTF(1, 2) dt_widget_log_discard(const char *format, ...)
164{
165 (void)format;
166}
167#define dt_widget_log(...) do { if(FALSE) dt_widget_log_discard(__VA_ARGS__); } while(0)
168#define dt_widget_log_enabled() FALSE
169#endif
170
173gboolean dt_widget_debug_overlays(void);
175
176/* ------------------------------------------------------------------------------------------
177 * Per-widget persistence.
178 *
179 * A resizable panel remembers the height the user dragged it to; a collapsible section
180 * remembers whether they left it open. The key is supplied by whoever built the widget --
181 * widgets/ neither invents keys nor knows where they are stored, because a configuration
182 * system is application state reached through a global, which is exactly what this module
183 * exists to keep out of the toolkit.
184 *
185 * Unregistered, nothing is stored and every read reports "not set", so a widget falls back to
186 * its default size or its collapsed state. That is also the correct behaviour for any host
187 * that has no preferences to offer.
188 * ------------------------------------------------------------------------------------------ */
189typedef gboolean (*dt_widget_stored_int_getter_t)(const char *key, int *value);
190typedef void (*dt_widget_stored_int_setter_t)(const char *key, int value);
191typedef gboolean (*dt_widget_stored_bool_getter_t)(const char *key);
192typedef void (*dt_widget_stored_bool_setter_t)(const char *key, gboolean value);
193
198
200gboolean dt_widget_stored_int(const char *key, int *value);
201void dt_widget_store_int(const char *key, int value);
202
204gboolean dt_widget_stored_bool(const char *key);
205void dt_widget_store_bool(const char *key, gboolean value);
206
207/* Has the application loaded its CSS theme yet? Dialogs that can run during startup -- before
208 * any styling exists -- pad themselves by hand when it has not. */
209gboolean dt_widget_theme_loaded(void);
210void dt_widget_set_theme_loaded(gboolean loaded);
211
212/* Return keyboard focus to the application's main working area. A widget that swallows keys
213 * (a text entry) has to hand focus back when the user presses Escape, but which widget is
214 * "the main area" is the host's business -- the image in darkroom, the grid in lighttable.
215 * Unregistered, the request is dropped. */
218void dt_widget_refocus(void);
219
220/* A GtkNotebook the host registered an owner for has switched page. The host relays this on
221 * its own signal bus; widgets/ has no bus and no idea what the owner is. */
225
226/* Toolkit metrics: the UI zoom factor, the integer device scale, and the resolved root font
227 * size in pixels. Widgets scale themselves by these; the application computes them from the
228 * screen and the theme and pushes them here. They lived in dt_gui_gtk_t, which meant a widget
229 * had to reach the application global to size itself. */
231double dt_widget_dpi(void);
232void dt_widget_set_dpi(double dpi);
233
238gboolean dt_widget_metrics_probed(void);
239
240double dt_widget_dpi_factor(void);
242
243double dt_widget_ppd(void);
244void dt_widget_set_ppd(double ppd);
245
251
253double dt_widget_em_size(void);
254void dt_widget_set_em_size(double em);
255
258double dt_get_system_gui_ppd(GtkWidget *widget);
259
261GdkModifierType dt_key_modifier_state(void);
262
263/* Scale a 96-DPI-baseline value. UI: logical pixels GTK will scale further. DEVICE: raw
264 * device pixels for cairo surfaces and hit-tests, which GTK does not scale for us. */
265#define DT_UI_SCALE_UI(value) ((value) * dt_widget_dpi_factor())
266#define DT_UI_SCALE_DEVICE(value) ((value) * dt_widget_dpi_factor() * dt_widget_ppd())
267#define DT_PIXEL_APPLY_DPI(value) DT_UI_SCALE_UI(value)
268#define DT_PIXEL_APPLY_DPI_DPP(value) DT_UI_SCALE_DEVICE(value)
269
270/* Gutter between children of boxes/grids/flowboxes -- settable only from code, so it is
271 * centralised here for the whole app. Expressed as a fraction of 1em so it tracks the user's
272 * font size like the em-based margins in ansel.css. 0.625em == 10px at the 16px reference.
273 * The font's pt->px conversion already folds in DPI, so this needs no DPI scaling on top. */
274#define DT_GUI_EM_SIZE ((gint)dt_widget_em_size())
275#define DT_GUI_BOX_SPACING_EM 0.625
276#define DT_GUI_BOX_SPACING ((gint)(DT_GUI_EM_SIZE * DT_GUI_BOX_SPACING_EM + 0.5))
277
278/* Colour-label slots. These mirror the application's dt_colorlabels_enum, and gui/gtk.c
279 * carries a _Static_assert that they cannot drift apart -- that is the one place both
280 * headers are visible. Declaring them here keeps widgets/ free of application headers. */
281enum
282{
290
291/* The colour-label palette, as RGBA. Widgets paint colour labels; which colours those are is
292 * a theme decision the application supplies. Indices match dt_colorlabels_enum. */
293const GdkRGBA *dt_widget_colorlabel(int index);
294void dt_widget_set_colorlabels(const GdkRGBA *labels, int count);
295
296/* On the Quartz GDK backend, a physical Cmd keypress is reported through GDK_MOD2_MASK
297 * (see widgets/accelerators.h's DT_PRIMARY_MASK, which every accelerator *registration*
298 * already resolves to instead of GDK_CONTROL_MASK). Every mouse/keyboard interaction check
299 * in the codebase asks for GDK_CONTROL_MASK meaning "the platform's primary modifier", so
300 * that substitution is done once, here, rather than at each of the ~80 call sites. */
301static inline GdkModifierType dt_modifier_primary_mask(GdkModifierType desired_modifier_mask)
302{
303#ifdef GDK_WINDOWING_QUARTZ
306#endif
308}
309
310/* GDK_MOD2_MASK is the bit a real Cmd keypress produces, matched against for actual dispatch
311 * (dt_modifier_primary_mask() above) and the bit GTK's own gtk_accelerator_name() collapses to
312 * the portable "<Primary>" token for on Quartz (see widgets/accelerators.h's DT_PRIMARY_MASK
313 * doc comment) -- so it must stay what is stored and saved. But GTK's accelerator-label
314 * renderer (gtk_accelerator_get_label(), and anything built on it: GtkCellRendererAccel,
315 * GtkAccelLabel) only ever emits the "⌘" glyph for GDK_META_MASK, never GDK_MOD2_MASK, on any
316 * platform. This is the reverse, display-only swap: takes a mask meant for storage/matching
317 * and returns what to hand to a label/rendering function instead. Never store or match against
318 * this result -- GDK_META_MASK is not reliably present on mouse-sourced events, only real key
319 * events (see dt_modifier_is() above). */
320static inline GdkModifierType dt_accels_display_mods(GdkModifierType mods)
321{
322#ifdef GDK_WINDOWING_QUARTZ
323 if(mods & GDK_MOD2_MASK)
324 mods = (GdkModifierType)((mods & ~GDK_MOD2_MASK) | GDK_META_MASK);
325#endif
326 return mods;
327}
328
329/* Does `state` carry exactly `desired_modifier_mask`, ignoring lock/scroll bits? */
330static inline gboolean dt_modifier_is(GdkModifierType state, const GdkModifierType desired_modifier_mask)
331{
332 const GdkModifierType modifiers = gtk_accelerator_get_default_mod_mask();
333#ifdef GDK_WINDOWING_QUARTZ
334 // A real GDK_KEY_PRESS/RELEASE's state carries both GDK_MOD2_MASK and GDK_META_MASK for a
335 // single physical Cmd press (GDK's own virtual-modifier step adds GDK_META_MASK next to the
336 // real GDK_MOD2_MASK bit for every key event -- see _accels_keys_decode() in
337 // widgets/accelerators.c for the same dedup on the accelerator-dispatch path). Mouse/scroll
338 // events never carry GDK_META_MASK, so this is a no-op for the majority of this function's
339 // callers; it only matters for the callers that read a real GdkEventKey.state directly.
340 /* Cast, not a compound assignment: this header is included from C++ translation units
341 * too (iop/lens.cc, iop/tonemap.cc, imageio/format/exr.cc, ...), and in C++ the operand
342 * `~GDK_META_MASK` is an int, which cannot be assigned back into an enum. */
344 state = (GdkModifierType)(state & ~GDK_META_MASK);
345#endif
347}
348
349/* Does `state` carry AT LEAST `desired_modifier_mask`? Same arithmetic, weaker test. */
350static inline gboolean dt_modifiers_include(GdkModifierType state, const GdkModifierType desired_modifier_mask)
351{
352 const GdkModifierType modifiers = gtk_accelerator_get_default_mod_mask();
354#ifdef GDK_WINDOWING_QUARTZ
355 // See dt_modifier_is() just above, cast included.
357 state = (GdkModifierType)(state & ~GDK_META_MASK);
358#endif
359 return (state & (modifiers & wanted)) == wanted;
360}
361
362/* Scroll deltas as fractions, for consumers that want the raw smooth-scroll amount rather
363 * than the accumulated discrete units above. */
364gboolean dt_gui_get_scroll_deltas(const GdkEventScroll *event, gdouble *delta_x, gdouble *delta_y);
365gboolean dt_gui_get_scroll_delta(const GdkEventScroll *event, gdouble *delta);
366
367
368/* ------------------------------------------------------------------------------------------
369 * Theme palette.
370 *
371 * The colours widgets paint with are a theme decision the application resolves (from CSS, at
372 * dt_gui_load_theme() time) and pushes here. Widgets read them; they do not look them up.
373 * Storage lives here rather than in the application struct so that widgets/draw.h can be a
374 * leaf header -- it paints with DT_GUI_COLOR_BUTTON_FG and must not reach for gui/.
375 * ------------------------------------------------------------------------------------------ */
412
414GdkRGBA *dt_widget_colors(void);
415
419
420/* Overlay tint for shapes drawn over the image (mask outlines, guides, crop handles). A user
421 * preference the application resolves; widgets/draw.h paints with it. */
426
428void dt_widget_set_overlay_color(double red, double green, double blue, double contrast);
429
430/* Mouse hit-test radius in device pixels: the raw value, and the one clamped to stay usable
431 * for overlay selection at any zoom. The darkroom recomputes both when the zoom changes. */
432float dt_widget_mouse_radius(void);
434void dt_widget_set_mouse_radius(float radius, float clamped);
435
437#define DT_GUI_MOUSE_EFFECT_RADIUS dt_widget_mouse_radius_clamped()
438
439
440/* ------------------------------------------------------------------------------------------
441 * Call-site diagnostics for two GTK setters.
442 *
443 * GTK reports only its own assertion site when a non-widget reaches gtk_widget_queue_draw(),
444 * which says nothing about which Ansel code owned the bad pointer. In debug-capable builds
445 * both calls are rerouted through a wrapper that names the caller's file and line, so an
446 * ownership/lifetime bug points at the source line that queued the redraw. Toggle state
447 * changes are wrapped for the same reason: they usually precede a redraw, so catching the
448 * invalid object here surfaces the first error rather than the secondary redraw assertion.
449 * ------------------------------------------------------------------------------------------ */
450#ifdef _DEBUG
451void dt_gtk_widget_queue_draw_ext(GtkWidget *widget, const char *name, const char *file, const int line);
452#define dt_gtk_widget_queue_draw(widget) dt_gtk_widget_queue_draw_ext((GtkWidget *)(widget), #widget, __FILE__, __LINE__)
453#define gtk_widget_queue_draw(widget) dt_gtk_widget_queue_draw(widget)
454
455void dt_gtk_toggle_button_set_active_ext(GtkToggleButton *toggle_button, const char *name, const gboolean active,
456 const char *file, const int line);
457#define dt_gtk_toggle_button_set_active(toggle_button, active) \
458 dt_gtk_toggle_button_set_active_ext((GtkToggleButton *)(toggle_button), #toggle_button, active, __FILE__, __LINE__)
459#define gtk_toggle_button_set_active(toggle_button, active) \
460 dt_gtk_toggle_button_set_active(toggle_button, active)
461#else
462#define dt_gtk_widget_queue_draw(widget) gtk_widget_queue_draw(widget)
463#define dt_gtk_toggle_button_set_active(toggle_button, active) gtk_toggle_button_set_active(toggle_button, active)
464#endif
465
467
468#endif // DT_WIDGETS_WIDGET_SETTINGS_H
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
const int t
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
Definition colorspaces.h:98
const float delta
gboolean enabled
–doc was passed on the command line
GdkRGBA color[]
Definition geotagging.c:540
char * key
uint32_t width
Definition mipmap_cache.c:0
const float factor
Definition pdf.h:91
const char * name
Definition pdf.h:90
static const dt_aligned_pixel_simd_t value
Definition simd.h:144
const float uint32_t state[4]
void dt_widget_set_ppd(double ppd)
gboolean dt_gui_get_scroll_deltas(const GdkEventScroll *event, gdouble *delta_x, gdouble *delta_y)
GtkWidget * dt_widget_root_window(void)
float dt_widget_mouse_radius(void)
double dt_widget_ppd(void)
void(* dt_widget_refocus_handler_t)(void)
gboolean dt_gui_get_scroll_delta(const GdkEventScroll *event, gdouble *delta)
gboolean dt_gui_get_scroll_unit_deltas(const GdkEventScroll *event, int *delta_x, int *delta_y)
void dt_widget_set_colorlabels(const GdkRGBA *labels, int count)
@ DT_WIDGET_COLORLABEL_RED
@ DT_WIDGET_COLORLABEL_PURPLE
@ DT_WIDGET_COLORLABEL_COUNT
@ DT_WIDGET_COLORLABEL_YELLOW
@ DT_WIDGET_COLORLABEL_GREEN
@ DT_WIDGET_COLORLABEL_BLUE
void dt_widget_set_cursor_handler(dt_widget_cursor_handler_t handler)
gboolean(* dt_widget_stored_int_getter_t)(const char *key, int *value)
static gboolean dt_modifier_is(GdkModifierType state, const GdkModifierType desired_modifier_mask)
gboolean dt_gui_get_scroll_unit_delta(const GdkEventScroll *event, int *delta)
static GdkModifierType dt_accels_display_mods(GdkModifierType mods)
void dt_widget_set_debug_overlays(gboolean enabled)
void dt_widget_set_dpi_factor(double factor)
gboolean(* dt_widget_stored_bool_getter_t)(const char *key)
dt_gui_color_t
@ DT_GUI_COLOR_BG
@ DT_GUI_COLOR_DARKROOM_PREVIEW_BG
@ DT_GUI_COLOR_LIGHTTABLE_FONT
@ DT_GUI_COLOR_MAP_LOC_SHAPE_HIGH
@ DT_GUI_COLOR_LOG_FG
@ DT_GUI_COLOR_BRUSH_CURSOR
@ DT_GUI_COLOR_LAST
@ DT_GUI_COLOR_THUMBNAIL_FONT
@ DT_GUI_COLOR_THUMBNAIL_SELECTED_BG
@ DT_GUI_COLOR_MAP_COUNT_BG
@ DT_GUI_COLOR_LOG_BG
@ DT_GUI_COLOR_THUMBNAIL_SELECTED_BORDER
@ DT_GUI_COLOR_THUMBNAIL_OUTLINE
@ DT_GUI_COLOR_MAP_LOC_SHAPE_LOW
@ DT_GUI_COLOR_LIGHTTABLE_BG
@ DT_GUI_COLOR_BUTTON_FG
@ DT_GUI_COLOR_DARKROOM_BG
@ DT_GUI_COLOR_THUMBNAIL_BORDER
@ DT_GUI_COLOR_LIGHTTABLE_PREVIEW_BG
@ DT_GUI_COLOR_WARNING
@ DT_GUI_COLOR_MAP_COUNT_SAME_LOC
@ DT_GUI_COLOR_MAP_COUNT_DIFF_LOC
@ DT_GUI_COLOR_THUMBNAIL_BG
@ DT_GUI_COLOR_PREVIEW_HOVER_BORDER
@ DT_GUI_COLOR_FILMSTRIP_BG
@ DT_GUI_COLOR_BRUSH_TRACE
@ DT_GUI_COLOR_THUMBNAIL_SELECTED_FONT
@ DT_GUI_COLOR_THUMBNAIL_SELECTED_OUTLINE
@ DT_GUI_COLOR_THUMBNAIL_HOVER_BG
@ DT_GUI_COLOR_PRINT_BG
@ DT_GUI_COLOR_MAP_LOC_SHAPE_DEF
@ DT_GUI_COLOR_THUMBNAIL_HOVER_FONT
@ DT_GUI_COLOR_THUMBNAIL_HOVER_OUTLINE
void dt_widget_set_image_filter(cairo_filter_t filter)
void dt_widget_set_scroll_reversed(gboolean reverse_x, gboolean reverse_y)
void dt_widget_set_source_rgba(cairo_t *cr, dt_gui_color_t color, float opacity_coef)
gboolean dt_widget_stored_int(const char *key, int *value)
GdkRGBA * dt_widget_colors(void)
void dt_gui_freeze_reset(void)
void dt_widget_set_theme_loaded(gboolean loaded)
static void dt_gui_freeze_release_(dt_gui_freeze_token_t *t)
gint(* dt_widget_natural_width_handler_t)(GtkWidget *widget)
gboolean dt_widget_metrics_probed(void)
GtkWidget * dt_widget_scroll_focus(void)
void dt_widget_set_natural_width_handler(dt_widget_natural_width_handler_t handler)
gboolean dt_widget_on_gui_thread(void)
Is the calling thread the one that owns widget state?
void dt_widget_store_bool(const char *key, gboolean value)
void dt_gui_freeze_end_(const char *file, int line)
void dt_widget_set_root_window_handler(dt_widget_root_window_handler_t handler)
void dt_widget_set_em_size(double em)
void dt_widget_set_gui_thread(pthread_t thread)
GdkModifierType dt_key_modifier_state(void)
void dt_widget_set_dpi(double dpi)
void dt_widget_set_source_rgb(cairo_t *cr, dt_gui_color_t color)
gboolean dt_widget_debug_overlays(void)
void dt_widget_set_notebook_page_handler(dt_widget_notebook_page_handler_t handler)
void dt_widget_set_overlay_color(double red, double green, double blue, double contrast)
void(* dt_widget_stored_int_setter_t)(const char *key, int value)
gint dt_widget_min_panel_width(void)
void dt_widget_set_refocus_handler(dt_widget_refocus_handler_t handler)
const GdkRGBA * dt_widget_colorlabel(int index)
void dt_widget_set_scroll_focus(GtkWidget *widget)
static void G_GNUC_PRINTF(1, 2) dt_widget_log_discard(const char *format
double dt_get_system_gui_ppd(GtkWidget *widget)
float dt_widget_mouse_radius_clamped(void)
void dt_widget_set_storage_handlers(dt_widget_stored_int_getter_t get_int, dt_widget_stored_int_setter_t set_int, dt_widget_stored_bool_getter_t get_bool, dt_widget_stored_bool_setter_t set_bool)
void(* dt_widget_cursor_handler_t)(GdkCursorType cursor)
static GdkModifierType dt_modifier_primary_mask(GdkModifierType desired_modifier_mask)
gboolean dt_widget_stored_bool(const char *key)
void dt_widget_set_min_panel_width(gint width)
void dt_widget_set_message_handler(dt_widget_message_handler_t handler)
double dt_widget_dpi_factor(void)
void dt_widget_store_int(const char *key, int value)
G_BEGIN_DECLS GdkEventMask dt_widget_scroll_mask(void)
void dt_widget_refocus(void)
void(* dt_widget_notebook_page_handler_t)(gpointer owner)
gboolean dt_gui_widgets_suppressed(void)
cairo_filter_t dt_widget_image_filter(void)
#define dt_widget_log(...)
void dt_widget_notebook_page_changed(gpointer owner)
void dt_widget_set_mouse_radius(float radius, float clamped)
GtkWidget *(* dt_widget_root_window_handler_t)(void)
const dt_widget_overlay_color_t * dt_widget_overlay_color(void)
static gboolean dt_modifiers_include(GdkModifierType state, const GdkModifierType desired_modifier_mask)
void dt_widget_set_scroll_mask(GdkEventMask mask)
gint dt_widget_natural_width(GtkWidget *widget)
double dt_widget_dpi(void)
double dt_widget_em_size(void)
void dt_widget_message(const char *message)
void(* dt_widget_stored_bool_setter_t)(const char *key, gboolean value)
void(* dt_widget_message_handler_t)(const char *message)
void dt_widget_set_cursor(GdkCursorType cursor)
void dt_gui_freeze_begin_(const char *file, int line)
gboolean dt_widget_theme_loaded(void)