Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
slideshow.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2013-2016 johannes hanika.
4 Copyright (C) 2014, 2019-2021 Aldric Renaudin.
5 Copyright (C) 2014 Moritz Lipp.
6 Copyright (C) 2014 parafin.
7 Copyright (C) 2014-2016 Roman Lebedev.
8 Copyright (C) 2014-2017, 2019-2020 Tobias Ellinghaus.
9 Copyright (C) 2015 Edouard Gomez.
10 Copyright (C) 2015, 2019-2021 Pascal Obry.
11 Copyright (C) 2019-2020, 2022-2023, 2025-2026 Aurélien PIERRE.
12 Copyright (C) 2019 Denis Dyakov.
13 Copyright (C) 2019 Philippe Weyland.
14 Copyright (C) 2020 Hanno Schwalm.
15 Copyright (C) 2020 quovadit.
16 Copyright (C) 2021-2022 Diederik Ter Rahe.
17 Copyright (C) 2021 Ralf Brown.
18 Copyright (C) 2022 Martin Bařinka.
19 Copyright (C) 2024 Alynx Zhou.
20
21 darktable is free software: you can redistribute it and/or modify
22 it under the terms of the GNU General Public License as published by
23 the Free Software Foundation, either version 3 of the License, or
24 (at your option) any later version.
25
26 darktable is distributed in the hope that it will be useful,
27 but WITHOUT ANY WARRANTY; without even the implied warranty of
28 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 GNU General Public License for more details.
30
31 You should have received a copy of the GNU General Public License
32 along with darktable. If not, see <http://www.gnu.org/licenses/>.
33*/
34
35#include "common/darktable.h"
36#include "common/collection.h"
37#include "common/selection.h"
38#include "common/colorspaces.h"
39#include "common/debug.h"
40#include "common/dtpthread.h"
41#include "common/imageio.h"
43#include "control/conf.h"
44#include "control/control.h"
45#include "dtgtk/thumbtable.h"
46
47#include "gui/gtk.h"
48#include "views/view.h"
49#include "views/view_api.h"
50
51#include <gdk/gdkkeysyms.h>
52#include <stdint.h>
53
54DT_MODULE(1)
55
61
69
70typedef struct _slideshow_buf_t
71{
73 int32_t imgid;
74 int32_t rank;
75 gboolean invalidated;
77
83
84typedef struct dt_slideshow_t
85{
86 int32_t col_count;
87 uint32_t width, height;
89 GList *playlist;
90
91 // buffers
94
95 // state machine stuff for image transitions:
96 dt_pthread_mutex_t lock;
97
98 gboolean auto_advance;
99 int delay;
101
102 // some magic to hide the mouse pointer
105
106// fwd declare state machine mechanics:
108
110{
111 dt_slideshow_cache_t *tmp_cache = d->buf[S_LEFT].cache;
112
113 for(int k=S_LEFT; k<S_RIGHT; k++)
114 {
115 d->buf[k].cache = d->buf[k+1].cache;
116 d->buf[k].imgid = d->buf[k+1].imgid;
117 d->buf[k].rank = d->buf[k+1].rank;
118 d->buf[k].invalidated = d->buf[k+1].invalidated;
119 }
120 d->buf[S_RIGHT].invalidated = TRUE;
121 d->buf[S_RIGHT].imgid = UNKNOWN_IMAGE;
122 d->buf[S_RIGHT].rank = d->buf[S_CURRENT].rank + 1;
123 d->buf[S_RIGHT].cache = tmp_cache;
124}
125
127{
128 dt_slideshow_cache_t *tmp_cache = d->buf[S_RIGHT].cache;
129
130 for(int k=S_RIGHT; k>S_LEFT; k--)
131 {
132 d->buf[k].cache = d->buf[k-1].cache;
133 d->buf[k].imgid = d->buf[k-1].imgid;
134 d->buf[k].rank = d->buf[k-1].rank;
135 d->buf[k].invalidated = d->buf[k-1].invalidated;
136 }
137 d->buf[S_LEFT].invalidated = TRUE;
138 d->buf[S_LEFT].imgid = UNKNOWN_IMAGE;
139 d->buf[S_LEFT].rank = d->buf[S_CURRENT].rank - 1;
140 d->buf[S_LEFT].cache = tmp_cache;
141}
142
144{
145 d->delay = CLAMP(d->delay + value, 1, 60);
146 dt_conf_set_int("slideshow_delay", d->delay);
147}
148
149static int32_t _slideshow_get_imgid_from_rank(const dt_slideshow_t *d, const int32_t rank)
150{
151 if(rank < 0) return UNKNOWN_IMAGE;
152
153 if(d->playlist)
154 {
155 const GList *link = g_list_nth(d->playlist, rank);
156 return link ? GPOINTER_TO_INT(link->data) : UNKNOWN_IMAGE;
157 }
158
159 const gchar *query = dt_collection_get_query(darktable.collection);
160 if(IS_NULL_PTR(query)) return UNKNOWN_IMAGE;
161
162 int32_t id = 0;
163 sqlite3_stmt *stmt;
165 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, rank);
166 DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, 1);
167 if(sqlite3_step(stmt) == SQLITE_ROW) id = sqlite3_column_int(stmt, 0);
168 sqlite3_finalize(stmt);
169 return id;
170}
171
173{
174 dt_slideshow_buf_t *buffer = &d->buf[slot];
175 if(buffer->rank < 0 || buffer->rank >= d->col_count)
176 {
177 buffer->imgid = UNKNOWN_IMAGE;
178 buffer->invalidated = FALSE;
180 return DT_VIEW_SURFACE_KO;
181 }
182
183 const int32_t imgid = _slideshow_get_imgid_from_rank(d, buffer->rank);
184 if(imgid <= UNKNOWN_IMAGE)
185 {
186 buffer->imgid = UNKNOWN_IMAGE;
187 buffer->invalidated = TRUE;
189 return DT_VIEW_SURFACE_KO;
190 }
191
192 buffer->imgid = imgid;
193 const int width = MAX(2, (int)d->width);
194 const int height = MAX(2, (int)d->height);
195 const dt_view_surface_value_t res =
198 buffer->invalidated = (res != DT_VIEW_SURFACE_OK);
199 return res;
200}
201
202static gboolean auto_advance(gpointer user_data)
203{
204 dt_slideshow_t *d = (dt_slideshow_t *)user_data;
206 if(!d->auto_advance) return FALSE;
207
208 dt_pthread_mutex_lock(&d->lock);
212 const gboolean can_advance = d->buf[S_RIGHT].rank >= 0 && d->buf[S_RIGHT].rank < d->col_count
213 && !d->buf[S_RIGHT].invalidated && d->buf[S_RIGHT].cache->surface;
214 const gboolean at_end = d->buf[S_CURRENT].rank >= d->col_count - 1;
216
217 if(can_advance || at_end)
218 {
220 return FALSE;
221 }
222
223 /* Autoplay waits for the next slot surface instead of stepping onto an
224 * empty screen. Keep the right-hand prefetch alive and poll shortly until it
225 * lands, then the normal delayed cadence resumes from _step_state(). */
227 d->auto_advance_timeout = g_timeout_add(200, auto_advance, d);
228 return FALSE;
229}
230
238
239// state machine stepping
241{
242 dt_pthread_mutex_lock(&d->lock);
243
244 if(event == S_REQUEST_STEP)
245 {
246 if(d->buf[S_CURRENT].rank < d->col_count - 1)
247 {
248 shift_left(d);
249 if(!d->playlist)
250 {
251 d->buf[S_CURRENT].imgid = _slideshow_get_imgid_from_rank(d, d->buf[S_CURRENT].rank);
253 if(d->buf[S_CURRENT].imgid > UNKNOWN_IMAGE) dt_view_active_images_add(d->buf[S_CURRENT].imgid, FALSE);
254 }
255 d->buf[S_RIGHT].rank = d->buf[S_CURRENT].rank + 1;
256 d->buf[S_RIGHT].invalidated = d->buf[S_RIGHT].rank < d->col_count;
258 }
259 else
260 {
261 dt_control_log(_("end of images"));
262 d->auto_advance = FALSE;
263 }
264 }
265 else if(event == S_REQUEST_STEP_BACK)
266 {
267 if(d->buf[S_CURRENT].rank > 0)
268 {
269 shift_right(d);
270 if(!d->playlist)
271 {
272 d->buf[S_CURRENT].imgid = _slideshow_get_imgid_from_rank(d, d->buf[S_CURRENT].rank);
274 if(d->buf[S_CURRENT].imgid > UNKNOWN_IMAGE) dt_view_active_images_add(d->buf[S_CURRENT].imgid, FALSE);
275 }
276 d->buf[S_LEFT].rank = d->buf[S_CURRENT].rank - 1;
277 d->buf[S_LEFT].invalidated = d->buf[S_LEFT].rank >= 0;
279 }
280 else
281 {
282 dt_control_log(_("end of images. press any key to return to lighttable mode"));
283 d->auto_advance = FALSE;
284 }
285 }
286
288
289 if(d->auto_advance)
290 {
291 if(d->auto_advance_timeout > 0) g_source_remove(d->auto_advance_timeout);
292 d->auto_advance_timeout = g_timeout_add_seconds(d->delay, auto_advance, d);
293 }
294}
295
296// callbacks for a view module:
297
298const char *name(const dt_view_t *self)
299{
300 return _("slideshow");
301}
302
303uint32_t view(const dt_view_t *self)
304{
305 return DT_VIEW_SLIDESHOW;
306}
307
308void init(dt_view_t *self)
309{
310 self->data = calloc(1, sizeof(dt_slideshow_t));
311 dt_slideshow_t *lib = (dt_slideshow_t *)self->data;
312 dt_pthread_mutex_init(&lib->lock, 0);
313 for(int k = S_LEFT; k < S_SLOT_LAST; k++)
314 {
315 lib->buf[k].cache = &lib->cache[k];
316 lib->buf[k].imgid = UNKNOWN_IMAGE;
317 lib->buf[k].rank = -1;
318 lib->buf[k].invalidated = TRUE;
320 }
321}
322
323
325{
326 dt_slideshow_t *lib = (dt_slideshow_t *)self->data;
327 if(lib->mouse_timeout > 0) g_source_remove(lib->mouse_timeout);
328 if(lib->auto_advance_timeout > 0) g_source_remove(lib->auto_advance_timeout);
329 g_list_free(lib->incoming_selection);
330 g_list_free(lib->playlist);
331 for(int k = S_LEFT; k < S_SLOT_LAST; k++)
334 dt_free(self->data);
335}
336
338{
340 g_list_free(d->incoming_selection);
341 d->incoming_selection = dt_selection_get_list(darktable.selection);
342 if(!d->incoming_selection && dt_view_active_images_get_all())
343 d->incoming_selection = g_list_copy((GList *)dt_view_active_images_get_all());
344
345 if(d->incoming_selection || dt_collection_get_count(darktable.collection) != 0) return 0;
346
347 dt_control_log(_("there are no images in this collection"));
348 return 1;
349}
350
351void enter(dt_view_t *self)
352{
354
355 dt_control_change_cursor(GDK_BLANK_CURSOR);
356 d->mouse_timeout = 0;
357 d->auto_advance_timeout = 0;
358
361
366
367 // also hide arrows
369
371 GdkRectangle rect;
372
373 GdkDisplay *display = gtk_widget_get_display(window);
374 GdkMonitor *mon = gdk_display_get_monitor_at_window(display, gtk_widget_get_window(window));
375 gdk_monitor_get_geometry(mon, &rect);
376
377 dt_pthread_mutex_lock(&d->lock);
378
379 d->width = rect.width;
380 d->height = rect.height;
381
383 g_list_free(d->playlist);
384 d->playlist = NULL;
385 if(d->incoming_selection)
386 {
387 /* Slideshow keeps either the incoming selection list or a single current
388 * image as its working set while the global selection stays cleared. */
389 dt_view_active_images_set(d->incoming_selection, FALSE);
390 d->incoming_selection = NULL;
391 d->playlist = g_list_copy(dt_view_active_images_get_all());
392 }
393
394 d->col_count = d->playlist ? g_list_length(d->playlist) : dt_collection_get_count(darktable.collection);
395
396 for(int k = S_LEFT; k < S_SLOT_LAST; k++)
397 {
398 dt_view_image_surface_fetcher_invalidate(&d->cache[k].fetcher, &d->cache[k].surface);
399 d->buf[k].imgid = UNKNOWN_IMAGE;
400 d->buf[k].rank = -1;
401 d->buf[k].invalidated = TRUE;
402 }
403
404 if(d->playlist)
405 {
406 d->buf[S_CURRENT].rank = 0;
407 d->buf[S_CURRENT].imgid = GPOINTER_TO_INT(d->playlist->data);
408 }
409 else if(d->col_count > 0)
410 {
411 d->buf[S_CURRENT].rank = 0;
413 if(d->buf[S_CURRENT].imgid > UNKNOWN_IMAGE)
414 {
416 }
417 }
418
419 d->buf[S_LEFT].rank = d->buf[S_CURRENT].rank - 1;
420 d->buf[S_RIGHT].rank = d->buf[S_CURRENT].rank + 1;
421
422 d->auto_advance = FALSE;
423 d->delay = dt_conf_get_int("slideshow_delay");
425
427
430 dt_control_log(_("waiting to start slideshow"));
431}
432
433void leave(dt_view_t *self)
434{
436
437 if(d->mouse_timeout > 0) g_source_remove(d->mouse_timeout);
438 d->mouse_timeout = 0;
439 if(d->auto_advance_timeout > 0) g_source_remove(d->auto_advance_timeout);
440 d->auto_advance_timeout = 0;
441 dt_control_change_cursor(GDK_LEFT_PTR);
442 d->auto_advance = FALSE;
444
449 g_list_free(d->incoming_selection);
450 d->incoming_selection = NULL;
451 g_list_free(d->playlist);
452 d->playlist = NULL;
453 for(int k = S_LEFT; k < S_SLOT_LAST; k++)
454 {
455 dt_view_image_surface_fetcher_invalidate(&d->cache[k].fetcher, &d->cache[k].surface);
456 d->buf[k].imgid = UNKNOWN_IMAGE;
457 d->buf[k].rank = -1;
458 d->buf[k].invalidated = TRUE;
459 }
460}
461
462void expose(dt_view_t *self, cairo_t *cr, int32_t width, int32_t height, int32_t pointerx, int32_t pointery)
463{
464 // draw front buffer.
466
467 dt_pthread_mutex_lock(&d->lock);
468 cairo_paint(cr);
469 d->width = width;
470 d->height = height;
474
475 const dt_slideshow_buf_t *slot = &(d->buf[S_CURRENT]);
476 cairo_surface_t *surface = slot->cache->surface;
477 if(surface && slot->rank >= 0 && !slot->invalidated)
478 {
479 const int surface_width = cairo_image_surface_get_width(surface);
480 const int surface_height = cairo_image_surface_get_height(surface);
481 double sx = 1.0, sy = 1.0;
482 cairo_surface_get_device_scale(surface, &sx, &sy);
483 const double logical_width = surface_width / sx;
484 const double logical_height = surface_height / sy;
485 // cope with possible resize of the window
486 const float tr_width = (width < logical_width) ? 0.f : (width - logical_width) * .5f;
487 const float tr_height = (height < logical_height) ? 0.f : (height - logical_height) * .5f;
488
489 cairo_save(cr);
490 cairo_translate(cr, tr_width, tr_height);
491 cairo_set_source_surface(cr, surface, 0, 0);
492 cairo_pattern_set_filter(cairo_get_source(cr), darktable.gui->filter_image);
493 cairo_rectangle(cr, 0, 0, logical_width, logical_height);
494 cairo_fill(cr);
495 cairo_restore(cr);
496 }
497 else
498 {
500 }
502}
503
504int key_pressed(dt_view_t *self, GdkEventKey *event)
505{
506 if(!gtk_window_is_active(GTK_WINDOW(darktable.gui->ui->main_window))) return FALSE;
507
508 switch(event->keyval)
509 {
510 case GDK_KEY_Escape:
511 {
512 dt_ctl_switch_mode_to("lighttable");
513 return TRUE;
514 }
515 }
516
517 return 0;
518}
519
525static gboolean _slideshow_start_stop_accel(GtkAccelGroup *accel_group, GObject *accelerable, guint keyval,
526 GdkModifierType mods, gpointer user_data)
527{
528 dt_view_t *self = (dt_view_t *)user_data;
530 if(!d->auto_advance)
531 {
532 d->auto_advance = TRUE;
533 if(d->auto_advance_timeout > 0) g_source_remove(d->auto_advance_timeout);
534 d->auto_advance_timeout = g_timeout_add_seconds(d->delay, auto_advance, d);
535 dt_control_log(_("slideshow started"));
536 }
537 else
538 {
539 d->auto_advance = FALSE;
540 if(d->auto_advance_timeout > 0) g_source_remove(d->auto_advance_timeout);
541 d->auto_advance_timeout = 0;
542 dt_control_log(_("slideshow paused"));
543 }
544 return TRUE;
545}
546
551static gboolean _slideshow_slow_down_accel(GtkAccelGroup *accel_group, GObject *accelerable, guint keyval,
552 GdkModifierType mods, gpointer user_data)
553{
554 dt_view_t *self = (dt_view_t *)user_data;
556 _set_delay(d, 1);
557 dt_control_log(ngettext("slideshow delay set to %d second", "slideshow delay set to %d seconds", d->delay),
558 d->delay);
559 return TRUE;
560}
561
566static gboolean _slideshow_speed_up_accel(GtkAccelGroup *accel_group, GObject *accelerable, guint keyval,
567 GdkModifierType mods, gpointer user_data)
568{
569 dt_view_t *self = (dt_view_t *)user_data;
571 _set_delay(d, -1);
572 dt_control_log(ngettext("slideshow delay set to %d second", "slideshow delay set to %d seconds", d->delay),
573 d->delay);
574 return TRUE;
575}
576
581static gboolean _slideshow_step_forward_accel(GtkAccelGroup *accel_group, GObject *accelerable, guint keyval,
582 GdkModifierType mods, gpointer user_data)
583{
584 dt_view_t *self = (dt_view_t *)user_data;
586 if(d->auto_advance) dt_control_log(_("slideshow paused"));
587 d->auto_advance = FALSE;
588 if(d->auto_advance_timeout > 0) g_source_remove(d->auto_advance_timeout);
589 d->auto_advance_timeout = 0;
591 return TRUE;
592}
593
598static gboolean _slideshow_step_back_accel(GtkAccelGroup *accel_group, GObject *accelerable, guint keyval,
599 GdkModifierType mods, gpointer user_data)
600{
601 dt_view_t *self = (dt_view_t *)user_data;
603 if(d->auto_advance) dt_control_log(_("slideshow paused"));
604 d->auto_advance = FALSE;
605 if(d->auto_advance_timeout > 0) g_source_remove(d->auto_advance_timeout);
606 d->auto_advance_timeout = 0;
608 return TRUE;
609}
610
611static gboolean _hide_mouse(gpointer user_data)
612{
613 dt_view_t *self = (dt_view_t *)user_data;
615 d->mouse_timeout = 0;
616 dt_control_change_cursor(GDK_BLANK_CURSOR);
617 return FALSE;
618}
619
620
621void mouse_moved(dt_view_t *self, double x, double y, double pressure, int which)
622{
624
625 if(d->mouse_timeout > 0) g_source_remove(d->mouse_timeout);
626 else dt_control_change_cursor(GDK_LEFT_PTR);
627 d->mouse_timeout = g_timeout_add_seconds(1, _hide_mouse, self);
628}
629
630
631int button_released(dt_view_t *self, double x, double y, int which, uint32_t state)
632{
633 return 0;
634}
635
636
637int button_pressed(dt_view_t *self, double x, double y, double pressure, int which, int type, uint32_t state)
638{
640
641 if(which == 1)
643 else if(which == 3)
645 else
646 return 1;
647
648 return 0;
649}
650
652{
653 dt_accels_new_slideshow_action(_slideshow_start_stop_accel, self, N_("Slideshow/Actions"),
654 N_("Start and stop"), GDK_KEY_space, 0,
655 _("Toggles slideshow auto-advance"));
656 dt_accels_new_slideshow_action(_slideshow_slow_down_accel, self, N_("Slideshow/Actions"),
657 N_("Slow down"), GDK_KEY_Up, 0,
658 _("Increases the slideshow delay"));
659 dt_accels_new_slideshow_action(_slideshow_slow_down_accel, self, N_("Slideshow/Actions"),
660 N_("Slow down"), GDK_KEY_KP_Add, 0,
661 _("Increases the slideshow delay"));
662 dt_accels_new_slideshow_action(_slideshow_slow_down_accel, self, N_("Slideshow/Actions"),
663 N_("Slow down"), GDK_KEY_plus, 0,
664 _("Increases the slideshow delay"));
665 dt_accels_new_slideshow_action(_slideshow_speed_up_accel, self, N_("Slideshow/Actions"),
666 N_("Speed up"), GDK_KEY_Down, 0,
667 _("Decreases the slideshow delay"));
668 dt_accels_new_slideshow_action(_slideshow_speed_up_accel, self, N_("Slideshow/Actions"),
669 N_("Speed up"), GDK_KEY_KP_Subtract, 0,
670 _("Decreases the slideshow delay"));
671 dt_accels_new_slideshow_action(_slideshow_speed_up_accel, self, N_("Slideshow/Actions"),
672 N_("Speed up"), GDK_KEY_minus, 0,
673 _("Decreases the slideshow delay"));
674 dt_accels_new_slideshow_action(_slideshow_step_back_accel, self, N_("Slideshow/Actions"),
675 N_("Step back"), GDK_KEY_Left, 0,
676 _("Displays the previous image"));
678 N_("Step forward"), GDK_KEY_Right, 0,
679 _("Displays the next image"));
680}
681
682// clang-format off
683// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
684// vim: shiftwidth=2 expandtab tabstop=2 cindent
685// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
686// clang-format on
void dt_accels_connect_accels(dt_accels_t *accels)
Actually enable accelerators after having loaded user config.
void dt_accels_connect_active_group(dt_accels_t *accels, const gchar *group)
Connect the contextual active accels group to the window. Views can declare their own set of contextu...
void dt_accels_disconnect_active_group(dt_accels_t *accels)
Disconnect the contextual active accels group from the window.
#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
const gchar * dt_collection_get_query(const dt_collection_t *collection)
Definition collection.c:552
uint32_t dt_collection_get_count(const dt_collection_t *collection)
Definition collection.c:836
int type
char * name
void dt_conf_set_int(const char *name, int val)
int dt_conf_get_int(const char *name)
void dt_ctl_switch_mode_to(const char *mode)
Definition control.c:657
void dt_control_draw_busy_msg(cairo_t *cr, int width, int height)
Definition control.c:505
void dt_control_log(const char *msg,...)
Definition control.c:761
void dt_control_queue_redraw_center()
request redraw of center window. This redraws the center view within a gdk critical section to preven...
Definition control.c:861
void dt_control_queue_redraw()
request redraw of the workspace. This redraws the whole workspace within a gdk critical section to pr...
Definition control.c:856
#define dt_control_change_cursor(cursor)
Definition control.h:116
darktable_t darktable
Definition darktable.c:181
#define UNKNOWN_IMAGE
Definition darktable.h:182
#define DT_MODULE(MODVER)
Definition darktable.h:140
#define dt_free(ptr)
Definition darktable.h:456
static const dt_aligned_pixel_simd_t value
Definition darktable.h:577
#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
sqlite3 * dt_database_get(const dt_database_t *db)
Definition database.c:3646
#define DT_DEBUG_SQLITE3_PREPARE_V2(a, b, c, d, e)
Definition debug.h:107
#define DT_DEBUG_SQLITE3_BIND_INT(a, b, c)
Definition debug.h:115
void dt_ui_panel_show(dt_ui_t *ui, const dt_ui_panel_t p, gboolean show, gboolean write)
shows/hide a panel
Definition display.c:124
static int dt_pthread_mutex_unlock(dt_pthread_mutex_t *mutex) RELEASE(mutex) NO_THREAD_SAFETY_ANALYSIS
Definition dtpthread.h:374
static int dt_pthread_mutex_init(dt_pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr)
Definition dtpthread.h:359
static int dt_pthread_mutex_destroy(dt_pthread_mutex_t *mutex)
Definition dtpthread.h:379
static int dt_pthread_mutex_lock(dt_pthread_mutex_t *mutex) ACQUIRE(mutex) NO_THREAD_SAFETY_ANALYSIS
Definition dtpthread.h:364
void dt_gui_refocus_center()
Definition gtk.c:3234
GtkWidget * dt_ui_center(dt_ui_t *ui)
get the center drawable widget
#define dt_accels_new_slideshow_action(a, b, c, d, e, f, g)
Definition gtk.h:438
GtkWidget * dt_ui_main_window(dt_ui_t *ui)
get the main window widget
static const float x
float *const restrict const size_t k
GList * dt_selection_get_list(struct dt_selection_t *selection)
Definition selection.c:172
void dt_selection_select_list(struct dt_selection_t *selection, const GList *const l)
Definition selection.c:320
void dt_selection_clear(dt_selection_t *selection)
Definition selection.c:266
void init(dt_view_t *self)
Definition slideshow.c:308
static gboolean _slideshow_start_stop_accel(GtkAccelGroup *accel_group, GObject *accelerable, guint keyval, GdkModifierType mods, gpointer user_data)
Toggle slideshow auto-advance using the same stepping code path as manual navigation,...
Definition slideshow.c:525
static gboolean _slideshow_slow_down_accel(GtkAccelGroup *accel_group, GObject *accelerable, guint keyval, GdkModifierType mods, gpointer user_data)
Increase the slideshow delay and store it immediately so repeated keyboard adjustments persist across...
Definition slideshow.c:551
static gboolean _slideshow_step_forward_accel(GtkAccelGroup *accel_group, GObject *accelerable, guint keyval, GdkModifierType mods, gpointer user_data)
Advance the slideshow while keeping auto-advance and global actions synced with the image currently d...
Definition slideshow.c:581
void leave(dt_view_t *self)
Definition slideshow.c:433
dt_slideshow_slot_t
Definition slideshow.c:63
@ S_SLOT_LAST
Definition slideshow.c:67
@ S_CURRENT
Definition slideshow.c:65
@ S_RIGHT
Definition slideshow.c:66
@ S_LEFT
Definition slideshow.c:64
static int32_t _slideshow_get_imgid_from_rank(const dt_slideshow_t *d, const int32_t rank)
Definition slideshow.c:149
int button_pressed(dt_view_t *self, double x, double y, double pressure, int which, int type, uint32_t state)
Definition slideshow.c:637
static void shift_right(dt_slideshow_t *d)
Definition slideshow.c:126
void cleanup(dt_view_t *self)
Definition slideshow.c:324
dt_slideshow_event_t
Definition slideshow.c:57
@ S_REQUEST_STEP_BACK
Definition slideshow.c:59
@ S_REQUEST_STEP
Definition slideshow.c:58
static gboolean _slideshow_step_back_accel(GtkAccelGroup *accel_group, GObject *accelerable, guint keyval, GdkModifierType mods, gpointer user_data)
Step back in slideshow mode and keep the fullscreen image as the sole active image when the selection...
Definition slideshow.c:598
static gboolean auto_advance(gpointer user_data)
Definition slideshow.c:202
void expose(dt_view_t *self, cairo_t *cr, int32_t width, int32_t height, int32_t pointerx, int32_t pointery)
Definition slideshow.c:462
int key_pressed(dt_view_t *self, GdkEventKey *event)
Definition slideshow.c:504
static gboolean _hide_mouse(gpointer user_data)
Definition slideshow.c:611
void mouse_moved(dt_view_t *self, double x, double y, double pressure, int which)
Definition slideshow.c:621
uint32_t view(const dt_view_t *self)
Definition slideshow.c:303
int button_released(dt_view_t *self, double x, double y, int which, uint32_t state)
Definition slideshow.c:631
struct _slideshow_buf_t dt_slideshow_buf_t
static void _refresh_display(dt_slideshow_t *d)
Definition slideshow.c:231
void enter(dt_view_t *self)
Definition slideshow.c:351
static void _set_delay(dt_slideshow_t *d, int value)
Definition slideshow.c:143
static void _step_state(dt_slideshow_t *d, dt_slideshow_event_t event)
Definition slideshow.c:240
void gui_init(dt_view_t *self)
Definition slideshow.c:651
static gboolean _slideshow_speed_up_accel(GtkAccelGroup *accel_group, GObject *accelerable, guint keyval, GdkModifierType mods, gpointer user_data)
Decrease the slideshow delay and store it immediately so the current playback cadence matches the per...
Definition slideshow.c:566
static dt_view_surface_value_t _slideshow_request_slot(dt_slideshow_t *d, const dt_slideshow_slot_t slot)
Definition slideshow.c:172
int try_enter(dt_view_t *self)
Definition slideshow.c:337
static void shift_left(dt_slideshow_t *d)
Definition slideshow.c:109
struct _GtkWidget GtkWidget
Definition splash.h:29
const float uint32_t state[4]
static const char *const mon[12]
Definition strptime.c:99
gboolean invalidated
Definition slideshow.c:75
struct dt_slideshow_cache_t * cache
Definition slideshow.c:72
struct dt_gui_gtk_t * gui
Definition darktable.h:775
struct dt_collection_t * collection
Definition darktable.h:781
struct dt_selection_t * selection
Definition darktable.h:782
const struct dt_database_t * db
Definition darktable.h:779
dt_accels_t * accels
Definition gtk.h:194
dt_ui_t * ui
Definition gtk.h:164
cairo_filter_t filter_image
Definition gtk.h:230
dt_view_image_surface_fetcher_t fetcher
Definition slideshow.c:81
cairo_surface_t * surface
Definition slideshow.c:80
uint32_t height
Definition slideshow.c:87
int32_t col_count
Definition slideshow.c:86
uint32_t width
Definition slideshow.c:87
guint mouse_timeout
Definition slideshow.c:103
gboolean auto_advance
Definition slideshow.c:98
GList * playlist
Definition slideshow.c:89
dt_pthread_mutex_t lock
Definition slideshow.c:96
dt_slideshow_buf_t buf[S_SLOT_LAST]
Definition slideshow.c:92
GList * incoming_selection
Definition slideshow.c:88
guint auto_advance_timeout
Definition slideshow.c:100
dt_slideshow_cache_t cache[S_SLOT_LAST]
Definition slideshow.c:93
GtkWidget * main_window
Track one asynchronous Cairo surface fetch request for a GUI widget.
Definition view.h:117
GModule *void * data
Definition view.h:157
double width
#define MAX(a, b)
Definition thinplate.c:29
A widget to manage and display image thumbnails in Ansel's lighttable and filmstrip views.
@ DT_THUMBTABLE_ZOOM_FIT
Definition thumbtable.h:76
void dt_view_image_surface_fetcher_invalidate(dt_view_image_surface_fetcher_t *fetcher, cairo_surface_t **target)
Definition view.c:866
void dt_view_image_surface_fetcher_cleanup(dt_view_image_surface_fetcher_t *fetcher)
Definition view.c:842
void dt_view_image_surface_fetcher_init(dt_view_image_surface_fetcher_t *fetcher)
Definition view.c:831
dt_view_surface_value_t dt_view_image_get_surface_async(dt_view_image_surface_fetcher_t *fetcher, int32_t imgid, int width, int height, cairo_surface_t **target, GtkWidget *widget, int zoom)
Definition view.c:881
void dt_view_active_images_add(int32_t imgid, gboolean raise)
Definition view.c:1276
void dt_view_active_images_reset(gboolean raise)
Definition view.c:1267
GList * dt_view_active_images_get_all()
Definition view.c:1301
void dt_view_active_images_set(GList *images, gboolean raise)
Definition view.c:1312
@ DT_VIEW_SLIDESHOW
Definition view.h:80
dt_view_surface_value_t
Definition view.h:102
@ DT_VIEW_SURFACE_OK
Definition view.h:103
@ DT_VIEW_SURFACE_KO
Definition view.h:104
@ DT_UI_PANEL_TOP
@ DT_UI_PANEL_BOTTOM
@ DT_UI_PANEL_LEFT
@ DT_UI_PANEL_RIGHT