Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
navigation.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2009-2012, 2016, 2018 johannes hanika.
4 Copyright (C) 2010-2012 Henrik Andersson.
5 Copyright (C) 2012 Richard Wonka.
6 Copyright (C) 2012-2014, 2016-2017 Tobias Ellinghaus.
7 Copyright (C) 2013, 2015, 2019-2020 Aldric Renaudin.
8 Copyright (C) 2013 Josef Wells.
9 Copyright (C) 2013 Pascal de Bruijn.
10 Copyright (C) 2013-2016 Roman Lebedev.
11 Copyright (C) 2014 parafin.
12 Copyright (C) 2014-2015 Ulrich Pegelow.
13 Copyright (C) 2016 Asma.
14 Copyright (C) 2018 Maurizio Paglia.
15 Copyright (C) 2018-2021 Pascal Obry.
16 Copyright (C) 2018 rawfiner.
17 Copyright (C) 2018 Sam Smith.
18 Copyright (C) 2019 Alexis Mousset.
19 Copyright (C) 2019, 2023, 2025-2026 Aurélien PIERRE.
20 Copyright (C) 2019 Edgardo Hoszowski.
21 Copyright (C) 2019 yuri1969.
22 Copyright (C) 2020 Chris Elston.
23 Copyright (C) 2020 Hubert Kowalski.
24 Copyright (C) 2021 Dan Torop.
25 Copyright (C) 2021-2022 Diederik Ter Rahe.
26 Copyright (C) 2021 Hanno Schwalm.
27 Copyright (C) 2021 Paolo DePetrillo.
28 Copyright (C) 2022 Martin Bařinka.
29 Copyright (C) 2023 Alynx Zhou.
30 Copyright (C) 2025-2026 Guillaume Stutin.
31
32 darktable is free software: you can redistribute it and/or modify
33 it under the terms of the GNU General Public License as published by
34 the Free Software Foundation, either version 3 of the License, or
35 (at your option) any later version.
36
37 darktable is distributed in the hope that it will be useful,
38 but WITHOUT ANY WARRANTY; without even the implied warranty of
39 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
40 GNU General Public License for more details.
41
42 You should have received a copy of the GNU General Public License
43 along with darktable. If not, see <http://www.gnu.org/licenses/>.
44*/
45
46#include "bauhaus/bauhaus.h"
47#include "common/darktable.h"
48#include "common/debug.h"
49#include "common/image_cache.h"
50#include "control/conf.h"
51#include "control/control.h"
53#include "develop/develop.h"
54
55#include "gui/gtk.h"
56#include "libs/lib.h"
57#include "libs/lib_api.h"
58
59DT_MODULE(1)
60
61#define DT_NAVIGATION_INSET 5
62
63typedef struct dt_lib_navigation_t
64{
65 GtkWidget *area; // the drawing area (self->widget is the resizable wrapper around it)
67 int zoom_w, zoom_h; // size of the zoom button
68 cairo_surface_t *image_surface;
71
86
87
88/* expose function for navigation module */
89static gboolean _lib_navigation_draw_callback(GtkWidget *widget, cairo_t *crf, gpointer user_data);
90/* motion notify callback handler*/
91static gboolean _lib_navigation_motion_notify_callback(GtkWidget *widget, GdkEventMotion *event,
92 gpointer user_data);
93/* button press callback */
94static gboolean _lib_navigation_button_press_callback(GtkWidget *widget, GdkEventButton *event,
95 gpointer user_data);
96/* button release callback */
97static gboolean _lib_navigation_button_release_callback(GtkWidget *widget, GdkEventButton *event,
98 gpointer user_data);
99/* leave notify callback */
100static gboolean _lib_navigation_leave_notify_callback(GtkWidget *widget, GdkEventCrossing *event,
101 gpointer user_data);
102
103/* helper function for position set */
104static void _lib_navigation_set_position(struct dt_lib_module_t *self, double x, double y, int alloc_wd, int alloc_ht);
105
106const char *name(struct dt_lib_module_t *self)
107{
108 return _("navigation");
109}
110
111const char **views(dt_lib_module_t *self)
112{
113 static const char *v[] = {"darkroom", NULL};
114 return v;
115}
116
118{
120}
121
123{
124 return 0;
125}
126
128{
129 return 1001;
130}
131
132
133static void _lib_navigation_control_redraw_callback(gpointer instance, gpointer user_data)
134{
135 (void)instance;
136 dt_lib_module_t *self = (dt_lib_module_t *)user_data;
139}
140
141static void _lib_navigation_restart_cache_wait(gpointer user_data)
142{
143 dt_lib_module_t *self = (dt_lib_module_t *)user_data;
144 if(IS_NULL_PTR(self)) return;
147}
148
149static void _lib_navigation_history_resync_callback(gpointer instance, gpointer user_data)
150{
151 (void)instance;
152
153 dt_lib_module_t *self = (dt_lib_module_t *)user_data;
156 if(IS_NULL_PTR(d) || IS_NULL_PTR(dev) || IS_NULL_PTR(dev->preview_pipe)) return;
157
158 dt_dev_pixelpipe_cache_wait_set_owner(&d->preview_wait, "navigation-preview", self);
159 if(dt_dev_pixelpipe_cache_peek_gui(dev->preview_pipe, NULL, NULL, NULL, &d->preview_wait,
162}
163
164
166{
167 /* initialize ui widgets */
169 self->data = (void *)d;
170 d->image_surface = NULL;
171
172 /* create drawingarea */
173 d->area = gtk_drawing_area_new();
174 gtk_widget_set_events(d->area, GDK_EXPOSURE_MASK | GDK_ENTER_NOTIFY_MASK
175 | GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK
176 | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK);
177
178 /* connect callbacks */
179 gtk_widget_set_app_paintable(d->area, TRUE);
180 g_signal_connect(G_OBJECT(d->area), "draw", G_CALLBACK(_lib_navigation_draw_callback), self);
181 g_signal_connect(G_OBJECT(d->area), "button-press-event",
182 G_CALLBACK(_lib_navigation_button_press_callback), self);
183 g_signal_connect(G_OBJECT(d->area), "button-release-event",
185 g_signal_connect(G_OBJECT(d->area), "motion-notify-event",
187 g_signal_connect(G_OBJECT(d->area), "leave-notify-event",
188 G_CALLBACK(_lib_navigation_leave_notify_callback), self);
189
190 gtk_widget_set_name(GTK_WIDGET(d->area), "navigation-module");
191
192 /* make the navigation preview vertically resizable, persisting its height */
193 self->widget = dt_ui_resizable_drawing_area(d->area, "plugins/darkroom/navigation/height", 175, 100);
194
195 /* connect redraw callbacks to targeted preview cache publication and explicit redraw requests */
200
201 darktable.lib->proxy.navigation.module = self;
202}
203
205{
206 if(IS_NULL_PTR(self->data)) return;
208
209 /* disconnect from signal */
212 dt_dev_pixelpipe_cache_wait_cleanup(&d->preview_wait, "navigation-gui-cleanup");
213
214 if(!IS_NULL_PTR(d->image_surface)) cairo_surface_destroy(d->image_surface);
215 d->image_surface = NULL;
216
217 dt_free(self->data);
218}
219
221{
223 if(!IS_NULL_PTR(d->image_surface)) cairo_surface_destroy(d->image_surface);
224 d->image_surface = NULL;
225}
226
227static gboolean _lib_navigation_draw_callback(GtkWidget *widget, cairo_t *crf, gpointer user_data)
228{
229 dt_times_t start;
230 dt_get_times(&start);
231
233 dt_lib_module_t *self = (dt_lib_module_t *)user_data;
235
236 const gboolean has_preview_image = dt_dev_pixelpipe_is_backbufer_valid(dev->preview_pipe);
237
238 static uint64_t image_hash = -1;
239 static int wd = 0;
240 static int ht = 0;
241 static float scale = 1.f;
242 static int32_t imgid = UNKNOWN_IMAGE;
243
244 GtkAllocation allocation;
245 gtk_widget_get_allocation(widget, &allocation);
246 static int width = 0;
247 static int height = 0;
248 gboolean changed = (width != allocation.width) || (height != allocation.height);
249 width = allocation.width;
250 height = allocation.height;
251
252 cairo_surface_t *cst = dt_cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
253 cairo_t *cr = cairo_create(cst);
254 GtkStyleContext *context = gtk_widget_get_style_context(widget);
255 gtk_render_background(context, cr, 0, 0, allocation.width, allocation.height);
256 cairo_save(cr);
257
258 if(has_preview_image
259 && (!d->image_surface || image_hash != dt_dev_backbuf_get_hash(&dev->preview_pipe->backbuf) || changed))
260 {
261 if(d->image_surface) cairo_surface_destroy(d->image_surface);
262 d->image_surface = dt_cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
263
264 // Fetch the backbuffer. The preview pipe backbuffer already owns the cache keepalive ref:
265 // navigation only needs a short read-only critical section while it copies into its own cairo surface.
266 struct dt_pixel_cache_entry_t *cache_entry = NULL;
267 void *data = NULL;
268 dt_dev_pixelpipe_cache_wait_set_owner(&d->preview_wait, "navigation-preview", self);
269 if(!dt_dev_pixelpipe_cache_peek_gui(dev->preview_pipe, NULL, &data, &cache_entry, &d->preview_wait,
271 return TRUE;
272
274
275 wd = dev->preview_pipe->backbuf.width;
276 ht = dev->preview_pipe->backbuf.height;
277 scale = fminf(width / (float)wd, height / (float)ht);
278 const int stride = cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, wd);
279 cairo_surface_t *tmp_surface = cairo_image_surface_create_for_data(data, CAIRO_FORMAT_RGB24, wd, ht, stride);
280
281 image_hash = dt_dev_backbuf_get_hash(&dev->preview_pipe->backbuf);
282
283 cairo_t *cri = cairo_create(d->image_surface);
284 cairo_rectangle(cri, 0, 0, width, height);
285 cairo_translate(cri, width / 2., height / 2.);
286 cairo_scale(cri, scale, scale);
287 cairo_translate(cri, -wd / 2., -ht / 2.);
288 cairo_set_source_surface(cri, tmp_surface, 0, 0);
289 cairo_fill(cri);
290 cairo_surface_destroy(tmp_surface);
291 cairo_destroy(cri);
292
294
295 imgid = dev->image_storage.id;
296 }
297 else
298 {
299 wd = dev->roi.preview_width;
300 ht = dev->roi.preview_height;
301 }
302
303 if(d->image_surface && imgid == dev->image_storage.id)
304 {
305 cairo_rectangle(cr, 0, 0, width, height);
306 cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_NEAREST);
307 cairo_set_source_surface(cr, d->image_surface, 0, 0);
308 cairo_fill(cr);
309 }
310
311 cairo_translate(cr, width / 2., height / 2.);
312 cairo_scale(cr, scale, scale);
313 cairo_translate(cr, -wd / 2., -ht / 2.);
314
315 // Calculate the thickness in user space (not affected by scale)
316 double line_width = DT_PIXEL_APPLY_DPI(1);
317 {
318 double dx = line_width, dy = 0;
319 cairo_device_to_user_distance(cr, &dx, &dy);
320 line_width = dx;
321 }
322
323 // draw box where we are
324 if(dev->roi.scaling > 1.f)
325 {
326 // Add a dark overlay on the picture to make it fade
327 cairo_rectangle(cr, 0, 0, wd, ht);
328 cairo_set_source_rgba(cr, 0, 0, 0, 0.5);
329
330 // clip dimensions to navigation area
331 float boxw = 1, boxh = 1;
332 dt_dev_check_zoom_pos_bounds(dev, &(dev->roi.x), &(dev->roi.y), &boxw, &boxh);
333 const float roi_w = MIN(boxw * wd, wd);
334 const float roi_h = MIN(boxh * ht, ht);
335 const float roi_x = dev->roi.x * wd - roi_w * 0.5f;
336 const float roi_y = dev->roi.y * ht - roi_h * 0.5f;
337 cairo_rectangle(cr, roi_x - 1, roi_y - 1, roi_w + 2, roi_h + 2);
338
339 /* Use even–odd rule to punch the hole */
340 cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
341 cairo_fill(cr);
342
343 cairo_set_fill_rule(cr, CAIRO_FILL_RULE_WINDING);
344
345 // Paint the external border in black
346 cairo_set_source_rgb(cr, 0., 0., 0.);
347 cairo_set_line_width(cr, line_width);
348 cairo_stroke(cr);
349
350 // Paint the internal border in white
351 cairo_set_source_rgb(cr, 1., 1., 1.);
352 cairo_rectangle(cr, roi_x, roi_y, roi_w, roi_h);
353 cairo_stroke(cr);
354 }
355 else
356 {
357 // draw a simple border
358 cairo_set_source_rgb(cr, 1., 1., 1.);
359 cairo_set_line_width(cr, line_width);
360 cairo_rectangle(cr, 0.5, 0.5, wd - 1, ht - 1);
361 cairo_stroke(cr);
362 }
363
364 cairo_restore(cr);
365
366 /* Zoom % */
367 PangoLayout *layout;
368 PangoRectangle logic;
369 PangoFontDescription *desc = pango_font_description_copy_static(darktable.bauhaus->pango_font_desc);
370 pango_font_description_set_weight(desc, PANGO_WEIGHT_BOLD);
371 layout = pango_cairo_create_layout(cr);
372 const float fontsize = DT_PIXEL_APPLY_DPI(14);
373 pango_font_description_set_absolute_size(desc, fontsize * PANGO_SCALE);
374 pango_layout_set_font_description(layout, desc);
375
376 // translate to left bottom corner
377 cairo_translate(cr, 0, height);
378 cairo_set_source_rgba(cr, 1., 1., 1., 0.5);
379 cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND);
380
381 gchar *zoomline;
382 {
383 gchar *fit = NULL;
384 if(dev->roi.scaling == 1.f)
385 fit = g_strdup(_("Fit"));
386
387 zoomline = g_strdup_printf("%s %.0f%%", fit ? fit : "", dev->roi.scaling * dev->roi.natural_scale * 100);
388 if(fit)
389 {
390 dt_free(fit);
391 }
392 }
393
394 pango_layout_set_text(layout, zoomline, -1);
395 dt_free(zoomline);
396 pango_layout_get_pixel_extents(layout, NULL, &logic);
397 d->zoom_h = logic.height;
398 d->zoom_w = logic.width;
399 const double h = d->zoom_h;
400 const double w = d->zoom_w;
401 const int xp = width - w - h - logic.x;
402 const int yp = - logic.height;
403
404 cairo_move_to(cr, xp, yp);
405 cairo_save(cr);
406 cairo_set_line_width(cr, DT_PIXEL_APPLY_DPI(1));
407
408 GdkRGBA *color;
409 gtk_style_context_get(context, gtk_widget_get_state_flags(widget), "background-color", &color, NULL);
410
411 gdk_cairo_set_source_rgba(cr, color);
412 pango_cairo_layout_path(cr, layout);
413 cairo_stroke_preserve(cr);
414 cairo_set_source_rgb(cr, 0.8, 0.8, 0.8);
415 cairo_fill(cr);
416
417 cairo_restore(cr);
418
419 gdk_rgba_free(color);
420 pango_font_description_free(desc);
421 g_object_unref(layout);
422
423 const float arrow_h = fontsize;
424
425 /* draw the drop-down arrow for zoom menu */
426 cairo_move_to(cr, width - 0.95 * arrow_h, -0.9 * arrow_h - 2);
427 cairo_line_to(cr, width - 0.05 * arrow_h, -0.9 * arrow_h - 2);
428 cairo_line_to(cr, width - 0.5 * arrow_h, -0.1 * arrow_h - 2);
429 cairo_fill(cr);
430
431 /* blit memsurface into widget */
432 cairo_destroy(cr);
433 cairo_set_source_surface(crf, cst, 0, 0);
434 cairo_paint(crf);
435 cairo_surface_destroy(cst);
436
437 dt_show_times_f(&start, "[navigation]", "redraw");
438
439 return TRUE;
440}
441
442static void _lib_navigation_set_position(dt_lib_module_t *self, double x, double y, int alloc_wd, int alloc_ht)
443{
445 const dt_lib_navigation_t *d = (const dt_lib_navigation_t *)self->data;
446 if(!(dev && d->dragging && dev->roi.scaling > 1.f)) return;
447
448 // Compute size of navigation ROI in widget coordinates
449 int proc_wd, proc_ht;
450 dt_dev_get_processed_size(dev, &proc_wd, &proc_ht);
451 const float nav_img_scale = fminf(alloc_wd / (float)proc_wd, alloc_ht / (float)proc_ht);
452 const int nav_img_w = (int)((float)proc_wd * nav_img_scale);
453 const int nav_img_h = (int)((float)proc_ht * nav_img_scale);
454
455 // Correct widget coordinates for margins
456 float fx = x - (alloc_wd - nav_img_w) * 0.5f;
457 float fy = y - (alloc_ht - nav_img_h) * 0.5f;
458
459 // Convert widget coordinates to relative coordinates within navigation ROI
460 // and commit relative coordinates of the ROI center
461 fx /= (float)nav_img_w;
462 fy /= (float)nav_img_h;
463 dt_dev_check_zoom_pos_bounds(dev, &fx, &fy, NULL, NULL);
464
465 dev->roi.x = fx;
466 dev->roi.y = fy;
467
468 /* redraw myself */
469 gtk_widget_queue_draw(d->area);
470
471 /* redraw pipe */
473}
474
475static gboolean _lib_navigation_motion_notify_callback(GtkWidget *widget, GdkEventMotion *event,
476 gpointer user_data)
477{
478 dt_lib_module_t *self = (dt_lib_module_t *)user_data;
479 GtkAllocation allocation;
480 gtk_widget_get_allocation(widget, &allocation);
481 _lib_navigation_set_position(self, event->x, event->y, allocation.width, allocation.height);
482 return TRUE;
483}
484
486{
488 if(IS_NULL_PTR(dev)) return;
489
490 switch(zoom)
491 {
492 default:
493 dev->roi.scaling = dev->roi.natural_scale;
494 break;
495 case LIB_ZOOM_SMALL:
496 dev->roi.scaling = dev->roi.natural_scale * 0.33;
497 break;
498 case LIB_ZOOM_FIT:
499 dev->roi.scaling = dev->roi.natural_scale;
500 break;
501 case LIB_ZOOM_25:
502 dev->roi.scaling = 0.25;
503 break;
504 case LIB_ZOOM_33:
505 dev->roi.scaling = 0.33;
506 break;
507 case LIB_ZOOM_50:
508 dev->roi.scaling = 0.50;
509 break;
510 case LIB_ZOOM_100:
511 dev->roi.scaling = 1.;
512 break;
513 case LIB_ZOOM_200:
514 dev->roi.scaling = 2.;
515 break;
516 case LIB_ZOOM_400:
517 dev->roi.scaling = 4.;
518 break;
519 case LIB_ZOOM_800:
520 dev->roi.scaling = 8.;
521 break;
522 case LIB_ZOOM_1600:
523 dev->roi.scaling = 16.;
524 break;
525 }
526
527 // Actual pixelpipe scaling is dev->roi.scaling * dev->roi.natural_scale,
528 // where dev->roi.natural_scale ensures the image fits within the viewport.
529 dev->roi.scaling /= dev->roi.natural_scale;
530
531 dt_dev_check_zoom_pos_bounds(dev, &dev->roi.x, &dev->roi.y, NULL, NULL);
533}
534
535static void _zoom_preset_callback(GtkButton *button, gpointer user_data)
536{
537 _zoom_preset_change(GPOINTER_TO_INT(user_data));
538}
539
540static gboolean _lib_navigation_button_press_callback(GtkWidget *widget, GdkEventButton *event,
541 gpointer user_data)
542{
543 dt_lib_module_t *self = (dt_lib_module_t *)user_data;
545
546 GtkAllocation allocation;
547 gtk_widget_get_allocation(widget, &allocation);
548 int w = allocation.width;
549 int h = allocation.height;
550 if(event->x >= w - DT_NAVIGATION_INSET - d->zoom_h - d->zoom_w
551 && event->y >= h - DT_NAVIGATION_INSET - d->zoom_h)
552 {
553 // we show the zoom menu
554 GtkMenuShell *menu = GTK_MENU_SHELL(gtk_menu_new());
555 GtkWidget *item;
556
557 item = gtk_menu_item_new_with_label(_("Small"));
558 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(_zoom_preset_callback), GINT_TO_POINTER(LIB_ZOOM_SMALL));
559 gtk_menu_shell_append(menu, item);
560
561 item = gtk_menu_item_new_with_label(_("Fit to screen"));
562 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(_zoom_preset_callback), GINT_TO_POINTER(LIB_ZOOM_FIT));
563 gtk_menu_shell_append(menu, item);
564
565 item = gtk_menu_item_new_with_label(_("25%"));
566 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(_zoom_preset_callback), GINT_TO_POINTER(LIB_ZOOM_25));
567 gtk_menu_shell_append(menu, item);
568
569 item = gtk_menu_item_new_with_label(_("33%"));
570 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(_zoom_preset_callback), GINT_TO_POINTER(LIB_ZOOM_33));
571 gtk_menu_shell_append(menu, item);
572
573 item = gtk_menu_item_new_with_label(_("50%"));
574 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(_zoom_preset_callback), GINT_TO_POINTER(LIB_ZOOM_50));
575 gtk_menu_shell_append(menu, item);
576
577 item = gtk_menu_item_new_with_label(_("100%"));
578 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(_zoom_preset_callback), GINT_TO_POINTER(LIB_ZOOM_100));
579 gtk_menu_shell_append(menu, item);
580
581 item = gtk_menu_item_new_with_label(_("200%"));
582 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(_zoom_preset_callback), GINT_TO_POINTER(LIB_ZOOM_200));
583 gtk_menu_shell_append(menu, item);
584
585 item = gtk_menu_item_new_with_label(_("400%"));
586 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(_zoom_preset_callback), GINT_TO_POINTER(LIB_ZOOM_400));
587 gtk_menu_shell_append(menu, item);
588
589 item = gtk_menu_item_new_with_label(_("800%"));
590 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(_zoom_preset_callback), GINT_TO_POINTER(LIB_ZOOM_800));
591 gtk_menu_shell_append(menu, item);
592
593 item = gtk_menu_item_new_with_label(_("1600%"));
594 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(_zoom_preset_callback), GINT_TO_POINTER(LIB_ZOOM_1600));
595 gtk_menu_shell_append(menu, item);
596
597 dt_gui_menu_popup(GTK_MENU(menu), NULL, 0, 0);
598
599 return TRUE;
600 }
601
602 d->dragging = 1;
603 _lib_navigation_set_position(self, event->x, event->y, w, h);
604 return TRUE;
605}
606
607static gboolean _lib_navigation_button_release_callback(GtkWidget *widget, GdkEventButton *event,
608 gpointer user_data)
609{
610 dt_lib_module_t *self = (dt_lib_module_t *)user_data;
612 d->dragging = 0;
613
614 return TRUE;
615}
616
617static gboolean _lib_navigation_leave_notify_callback(GtkWidget *widget, GdkEventCrossing *event,
618 gpointer user_data)
619{
620 return TRUE;
621}
622
623// clang-format off
624// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
625// vim: shiftwidth=2 expandtab tabstop=2 cindent
626// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
627// clang-format on
#define TRUE
Definition ashift_lsd.c:162
#define FALSE
Definition ashift_lsd.c:158
int width
Definition bilateral.h:1
int height
Definition bilateral.h:1
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
char * name
void dt_control_queue_redraw_widget(GtkWidget *widget)
threadsafe request of redraw of specific widget. Use this function if you need to redraw a specific w...
Definition control.c:906
darktable_t darktable
Definition darktable.c:181
void dt_show_times_f(const dt_times_t *start, const char *prefix, const char *suffix,...)
Definition darktable.c:1594
#define UNKNOWN_IMAGE
Definition darktable.h:182
#define DT_MODULE(MODVER)
Definition darktable.h:140
#define dt_free(ptr)
Definition darktable.h:456
static void dt_get_times(dt_times_t *t)
Definition darktable.h:921
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
Definition darktable.h:281
void dt_dev_pixelpipe_cache_wait_cleanup(dt_dev_pixelpipe_cache_wait_t *wait, const char *reason)
Cancel one pending GUI cache wait request and clear its runtime state.
gboolean dt_dev_pixelpipe_is_backbufer_valid(dt_dev_pixelpipe_t *pipe)
void dt_dev_pixelpipe_change_zoom_main(dt_develop_t *dev)
void dt_dev_pixelpipe_cache_wait_set_owner(dt_dev_pixelpipe_cache_wait_t *wait, const char *owner_tag, gpointer owner_object)
Attach debug ownership metadata to one cache wait request.
gboolean dt_dev_pixelpipe_cache_peek_gui(dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, void **data, dt_pixel_cache_entry_t **cache_entry, dt_dev_pixelpipe_cache_wait_t *wait, dt_dev_pixelpipe_cache_ready_callback_t restart, gpointer restart_data)
void dt_dev_get_processed_size(const dt_develop_t *dev, int *procw, int *proch)
Definition develop.c:979
void dt_dev_check_zoom_pos_bounds(dt_develop_t *dev, float *dev_x, float *dev_y, float *box_w, float *box_h)
Ensure that the current ROI position is within allowed bounds .
Definition develop.c:944
void dt_gui_menu_popup(GtkMenu *menu, GtkWidget *button, GdkGravity widget_anchor, GdkGravity menu_anchor)
Definition gtk.c:2953
GtkWidget * dt_ui_resizable_drawing_area(GtkWidget *area, char *config_str, int default_height, int min_height)
Make a self-drawing widget (typically a GtkDrawingArea graph or scope) vertically resizable.
Definition gtk.c:2836
static cairo_surface_t * dt_cairo_image_surface_create(cairo_format_t format, int width, int height)
Definition gtk.h:316
#define DT_PIXEL_APPLY_DPI(value)
Definition gtk.h:90
static const float x
const float v
void gui_reset(dt_lib_module_t *self)
Definition navigation.c:220
static void _zoom_preset_callback(GtkButton *button, gpointer user_data)
Definition navigation.c:535
static void _lib_navigation_history_resync_callback(gpointer instance, gpointer user_data)
Definition navigation.c:149
static void _lib_navigation_restart_cache_wait(gpointer user_data)
Definition navigation.c:141
static void _lib_navigation_control_redraw_callback(gpointer instance, gpointer user_data)
Definition navigation.c:133
dt_lib_zoom_t
Definition navigation.c:73
@ LIB_ZOOM_100
Definition navigation.c:79
@ LIB_ZOOM_SMALL
Definition navigation.c:74
@ LIB_ZOOM_200
Definition navigation.c:80
@ LIB_ZOOM_33
Definition navigation.c:77
@ LIB_ZOOM_25
Definition navigation.c:76
@ LIB_ZOOM_400
Definition navigation.c:81
@ LIB_ZOOM_FIT
Definition navigation.c:75
@ LIB_ZOOM_50
Definition navigation.c:78
@ LIB_ZOOM_LAST
Definition navigation.c:84
@ LIB_ZOOM_1600
Definition navigation.c:83
@ LIB_ZOOM_800
Definition navigation.c:82
void gui_cleanup(dt_lib_module_t *self)
Definition navigation.c:204
static gboolean _lib_navigation_draw_callback(GtkWidget *widget, cairo_t *crf, gpointer user_data)
Definition navigation.c:227
static gboolean _lib_navigation_leave_notify_callback(GtkWidget *widget, GdkEventCrossing *event, gpointer user_data)
Definition navigation.c:617
static gboolean _lib_navigation_motion_notify_callback(GtkWidget *widget, GdkEventMotion *event, gpointer user_data)
Definition navigation.c:475
uint32_t container(dt_lib_module_t *self)
Definition navigation.c:117
static void _lib_navigation_set_position(struct dt_lib_module_t *self, double x, double y, int alloc_wd, int alloc_ht)
Definition navigation.c:442
static void _zoom_preset_change(dt_lib_zoom_t zoom)
Definition navigation.c:485
void gui_init(dt_lib_module_t *self)
Definition navigation.c:165
int position()
Definition navigation.c:127
const char ** views(dt_lib_module_t *self)
Definition navigation.c:111
int expandable(dt_lib_module_t *self)
Definition navigation.c:122
static gboolean _lib_navigation_button_press_callback(GtkWidget *widget, GdkEventButton *event, gpointer user_data)
Definition navigation.c:540
#define DT_NAVIGATION_INSET
Definition navigation.c:61
static gboolean _lib_navigation_button_release_callback(GtkWidget *widget, GdkEventButton *event, gpointer user_data)
Definition navigation.c:607
void dt_dev_pixelpipe_cache_rdlock_entry(dt_dev_pixelpipe_cache_t *cache, gboolean lock, dt_pixel_cache_entry_t *cache_entry)
Lock or release the read lock on the entry.
static uint64_t dt_dev_backbuf_get_hash(const dt_backbuf_t *backbuf)
#define DT_DEBUG_CONTROL_SIGNAL_DISCONNECT(ctlsig, cb, user_data)
Definition signal.h:368
@ DT_SIGNAL_HISTORY_RESYNC
This signal is raised once darkroom history has been resynchronized into all live pipelines....
Definition signal.h:209
@ DT_SIGNAL_CONTROL_NAVIGATION_REDRAW
This signal is raised when dt_control_navigation_redraw() is called. no param, no returned value.
Definition signal.h:278
#define DT_DEBUG_CONTROL_SIGNAL_CONNECT(ctlsig, signal, cb, user_data)
Definition signal.h:357
struct _GtkWidget GtkWidget
Definition splash.h:29
unsigned __int64 uint64_t
Definition strptime.c:75
struct dt_lib_t * lib
Definition darktable.h:771
struct dt_dev_pixelpipe_cache_t * pixelpipe_cache
Definition darktable.h:790
struct dt_control_signal_t * signals
Definition darktable.h:774
struct dt_bauhaus_t * bauhaus
Definition darktable.h:778
struct dt_develop_t * develop
Definition darktable.h:770
PangoFontDescription * pango_font_desc
Definition bauhaus.h:274
dt_backbuf_t backbuf
dt_image_t image_storage
Definition develop.h:259
int32_t preview_height
Definition develop.h:213
struct dt_dev_pixelpipe_t * preview_pipe
Definition develop.h:247
float scaling
Definition develop.h:193
struct dt_develop_t::@17 roi
int32_t preview_width
Definition develop.h:213
float natural_scale
Definition develop.h:224
int32_t id
Definition image.h:319
GModule *void * data
Definition lib.h:80
GtkWidget * widget
Definition lib.h:84
cairo_surface_t * image_surface
Definition navigation.c:68
dt_dev_pixelpipe_cache_wait_t preview_wait
Definition navigation.c:69
GtkWidget * area
Definition navigation.c:65
struct dt_lib_t::@61::@62 navigation
struct dt_lib_t::@61 proxy
void * data
#define MIN(a, b)
Definition thinplate.c:32
@ DT_UI_CONTAINER_PANEL_LEFT_TOP