Skip to content

Adds support for XMP D&D in the darkroom.#21403

Open
masterpiga wants to merge 1 commit into
darktable-org:masterfrom
masterpiga:dnd_xmp
Open

Adds support for XMP D&D in the darkroom.#21403
masterpiga wants to merge 1 commit into
darktable-org:masterfrom
masterpiga:dnd_xmp

Conversation

@masterpiga

Copy link
Copy Markdown
Collaborator

Adds support for dropping .xmp sidecar files onto the darkroom to apply their edit history to the current image.

Fixes #21359.

Behavior

  • One sidecar: a dialog offers to replace the history of the current image, create a duplicate and apply the history to it (then switch to it), or cancel.
  • Multiple sidecars: a confirmation creates one duplicate per file, each with its history applied. Each duplicate is labelled with the sidecar's filename (via its version name) so the versions are easy to tell apart.

Drop hints While an external file drag hovers the darkroom, an overlay hint is shown on the center view ("drop XMP sidecar files here…") and on the filmstrip ("drop image files here…", the existing import target). Internal drags (thumbnail/module reordering) don't trigger it.

Screen.Recording.2026-06-23.at.08.34.33.mp4

Implementation notes

The change touches two files: src/views/darkroom.c (the feature) and src/common/history.c (a deadlock fix it exposed).

Drop target, scoped to the darkroom. The center drawing area is shared across views, so the text/uri-list drag destination and its handlers are registered in enter() and torn down in leave() rather than at construction — this keeps the behavior darkroom-only and avoids leaking handlers onto a widget other views reuse. Only external URIs are accepted, so dropping a filmstrip thumbnail on the canvas is unaffected. The drop is filtered to existing .xmp files; everything else is ignored.

Reuse over reinvention. The feature is mostly glue over existing machinery: dt_history_load_and_apply() to read a sidecar into an image's history, dt_image_duplicate() to spawn duplicates, and the Xmp.darktable.version_name metadata (the same per-duplicate caption the duplicate module writes) to label them. Applying to the current image relies on dt_history_load_and_apply()'s built-in darkroom reload; duplicates are non-current, so they don't reload and we switch to the single one explicitly so the result is visible.

Deadlock fix (history.c). dt_history_load_and_apply() grabbed the image-cache write lock and then, for the current darkroom image, called dt_dev_reload_history_items() while still holding it. The reload re-enters dt_image_cache_get() for the same image (e.g. from a module's reload_defaults), and that entry lock is non-recursive → hard hang. The fix moves the reload to after the cache lock is released. This was latent: existing callers (lighttable's "load sidecar file") only ever apply to non-current images, so the reload branch never fired — this PR is the first to apply a sidecar to the current darkroom image.

Drag hints without a global hook. We can't see the drag at the moment it starts (the app isn't focused yet), so the hint is driven by the drag-motion/drag-leave signals of the two drop targets (center + filmstrip thumbtable), which fire as soon as the pointer enters them. To distinguish a Finder drag from an internal reorder, we test gtk_drag_get_source_widget(context) == NULL — an in-app drag has a source widget, an external one doesn't. (An earlier attempt inspected the offered targets, but macOS's Quartz backend doesn't resolve those until drop time, so the hint never armed; the source-widget test is backend-agnostic and phase-agnostic.) A short timeout on drag-leave debounces the hand-off when the drag moves between the center and the filmstrip so the overlay doesn't flicker. The center hint is painted at the end of the view's expose(); the filmstrip hint via a draw-after handler on the thumbtable — so no changes to the shared thumbtable.c.

Smaller things. A shared _darkroom_dnd_dialog_new() builds the parented, centered, macOS-fullscreen-safe dialog used by both branches; the multi-duplicate loop is wrapped in one undo group (matching dt_history_load_and_apply_on_list) so the batch undoes in a single step; and batch results report how many succeeded.

Co-authored with Claude.

@masterpiga masterpiga added this to the 5.8 milestone Jun 23, 2026
@masterpiga masterpiga added feature: enhancement current features to improve difficulty: trivial some changes in a couple of functions scope: UI user interface and interactions scope: image processing correcting pixels labels Jun 23, 2026
@masterpiga

Copy link
Copy Markdown
Collaborator Author

@leonidas111 @TurboGit

@TurboGit

TurboGit commented Jul 3, 2026

Copy link
Copy Markdown
Member

Love this !

@TurboGit TurboGit added the documentation: pending a documentation work is required label Jul 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

difficulty: trivial some changes in a couple of functions documentation: pending a documentation work is required feature: enhancement current features to improve release notes: pending scope: image processing correcting pixels scope: UI user interface and interactions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature request: drag&drop XMP in darkroom view

2 participants