Skip to content

Fix exposure adjustment when scrolling over the scopes#20832

Open
kofa73 wants to merge 1 commit intodarktable-org:masterfrom
kofa73:fix-exposure-black-point-correction-when-scrolling-over-scope
Open

Fix exposure adjustment when scrolling over the scopes#20832
kofa73 wants to merge 1 commit intodarktable-org:masterfrom
kofa73:fix-exposure-black-point-correction-when-scrolling-over-scope

Conversation

@kofa73
Copy link
Copy Markdown
Contributor

@kofa73 kofa73 commented Apr 19, 2026

Fixes 3c8a77a#commitcomment-182858683

  • scrolling up/down over the scopes should brighten/darken the image: increase/decrease exposure OR decrease/increase black level correction (lift/crushe shadows) in the exposure module
  • dragging right/left (or up/down, depending on the scope's orientation) already moves the scope display in the direction of the drag (so no change in this PR): right/up: increase exposure or lift shadows; left/down: decrease exposure/crush shadows

@dtorop, do you agree?

@dtorop
Copy link
Copy Markdown
Contributor

dtorop commented Apr 19, 2026

Something I've pondered, and interested to see you're thinking this over as well.

dragging right/left (or up/down, depending on the scope's orientation) already moves the scope display in the direction of the drag (so no change in this PR): right/up: increase exposure or lift shadows; left/down: decrease exposure/crush shadows

Agreed!

scrolling up/down over the scopes should brighten/darken the image: increase/decrease exposure OR decrease/increase black level correction (lift/crushe shadows) in the exposure module

I see positive delta_y when I scroll up. But this is with "natural scrolling" on (via KDE or Gnome), which is flipping the scroll direction. @kofa73: Curious if you have natural scrolling on/off?

Yet worse, the behavior of scrolling black point compensation in scopes doesn't align with scrolling in the exposure module: Scrolling up over the exposure slider darkens the image yet scrolling up over the black point compensation slider lightens the image (as it turns down black point compensation). (And part of the problem is that scrolling up on a bauhaus control, counterintuitively, decreases it.)

I'm at a loss about what to do:

  1. match scrolling behavior to relevant bauhaus sliders
  2. or make scrolling anywhere in the scope consistently make the image lighter/darker

If 2), do we make it work intuitively for people with natural scrolling on or off?

Even more so, I'm a bit skeptical in general of whether most experienced users even scroll the scope to control exposure. Nor whether the exposure and black point compensation are the ideal controls to expose through the scope.

Regarding 3c8a77a, relevant changes:

3c8a77a#diff-7284cf3747c23a8aa6fecf62230ec131c80d417acaa37d4988fc4c01cc35fc5dL479-R500

3c8a77a#diff-3d57f965bae5282fe29b95c5dad50e2dc6d22beb284d61ea4ae1e1fe0674a22aL841-L842

3c8a77a#diff-3d57f965bae5282fe29b95c5dad50e2dc6d22beb284d61ea4ae1e1fe0674a22aR843-R844

Previously _eventbox_scroll_callback() would flip scroll direction if scrolling over black point compensation, then _exposure_proxy_handle_event() would flip the scroll direction again, resulting in no change.

Then 06f2ded added horizontal scrolling support...

@kofa73
Copy link
Copy Markdown
Contributor Author

kofa73 commented Apr 19, 2026

I see positive delta_y when I scroll up. But this is with "natural scrolling" on (via KDE or Gnome), which is flipping the scroll direction. @kofa73: Curious if you have natural scrolling on/off?

Nope:
image

But elsewhere scroll behaves as expected, e.g. scroll up to increase circle size when creating a drawn mask. A counterexample is rotate and perspective, see #20833

@kofa73
Copy link
Copy Markdown
Contributor Author

kofa73 commented Apr 19, 2026

Even more so, I'm a bit skeptical in general of whether most experienced users even scroll the scope to control exposure.

I certainly do, it's the quickest and simplest way to adjust exposure (for me). I don't adjust blacks that way, but exposure, all the time.

Yet worse, the behavior of scrolling black point compensation in scopes doesn't align with scrolling in the exposure module: Scrolling up over the exposure slider darkens the image yet scrolling up over the black point compensation slider lightens the image (as it turns down black point compensation). (And part of the problem is that scrolling up on a bauhaus control, counterintuitively, decreases it.)

I think it's OK and intuitive that scrolling up / down on a slider increases / decreases the value -- you see the slider's indicator move in the expected direction. Here, it is counter-intuitive, in a way, that increasing black level correction darkens the image, but at least the slider moves in the desired direction.

Scrolling over the histogram (scopes) is also intuitive and understandable, in its own way. I scroll there exactly because I don't open the exposure module, so the sliders are not visible.

@dtorop
Copy link
Copy Markdown
Contributor

dtorop commented Apr 19, 2026

But elsewhere scroll behaves as expected, e.g. scroll up to increase circle size when creating a drawn mask.

Here with natural scrolling, an upward scroll will:

  • decreases the size of a drawn mask
  • reduces exposure over the scope
  • reduces bauhaus slider values

A counterexample is rotate and perspective, see #20833

Which part of rotate-and-perspective does scrolling control? I see there is a "scrolled()" routine in ashift.c, but don't even know how to trigger it!

My settings:

image image

My question would be do we prioritize the right feel for "regular" or inverted (natural) scrolling?

I asked AI, which told me that in GTK understands scrolling deltas to be where content goes, not where the user's fingers have gone. It said to interpret an "up" or negative delta_y to mean "content goes up" or "increase". In which case your patch is correct.

But what to do about delta_x? Do we flip that as well?

@dtorop
Copy link
Copy Markdown
Contributor

dtorop commented Apr 19, 2026

whether most experienced users even scroll the scope to control exposure.

I certainly do, it's the quickest and simplest way to adjust exposure (for me). I don't adjust blacks that way, but exposure, all the time.

Glad to know!

I think it's OK and intuitive that scrolling up / down on a slider increases / decreases the value -- you see the slider's indicator move in the expected direction. Here, it is counter-intuitive, in a way, that increasing black level correction darkens the image, but at least the slider moves in the desired direction.

Makes sense.

Scrolling over the histogram (scopes) is also intuitive and understandable, in its own way. I scroll there exactly because I don't open the exposure module, so the sliders are not visible.

Likewise, makes sense. Part of the rationale of #20684 was to identify that scopes is its own widget, and should have internally consistent behavior rather than pass its events to bauhaus widgets.

@kofa73
Copy link
Copy Markdown
Contributor Author

kofa73 commented Apr 19, 2026

Which part of rotate-and-perspective does scrolling control?

Right or left click to exclude / include:
image

Docs:

You can manually change the status of line segments: Left-Click on a line to select it (turn the color to green or blue) and Right-click to deselect it (turn the color to red or yellow). If you keep the mouse button pressed, you can use a sweeping action to select/deselect multiple lines in a row. The size of the select/deselect brush can be changed with the mouse wheel. Hold down the Shift key and keep the left or right mouse button pressed while dragging to select or deselect all lines in the chosen rectangular area.
(https://docs.darktable.org/usermanual/development/en/module-reference/processing-modules/rotate-perspective/#automatically-detect-structure)

@dtorop
Copy link
Copy Markdown
Contributor

dtorop commented Apr 19, 2026

Which part of rotate-and-perspective does scrolling control?

Right or left click to exclude / include

Ah! So with natural scrolling:

Here with natural scrolling, an upward scroll here will:

  • decrease the size of a drawn mask
  • reduce exposure over the scope
  • reduce bauhaus slider values
  • increase the size of the select/deselect brush in rotate & perspective

@kofa73
Copy link
Copy Markdown
Contributor Author

kofa73 commented Apr 20, 2026

We have:

  • dy > 0 — scroll down (wheel rolled toward user).
  • dy < 0 — scroll up (wheel rolled away from user).
  • dx > 0 — scroll right (horizontal wheel / touchpad).
  • dx < 0 — scroll left.

In src/bauhaus/bauhaus.c, the function _widget_scroll() calculates int delta = dx + dy;, and calls _slider_add_step(widget, - delta, event->scroll.state, force);

So, if dx = 0 and dy < 0 (scrolling up / 'away from user'), -delta is positive, and the slider's value increases.
Weirdly, scrolling right will decrease the slider value, moving its indicator knob to the left. I think that's another bug (I never tried that before, only now, when I checked the code).

And I've just discovered (how come I never realised this?!) that scrolling up / down decreases / increases the size of the adjustment circles in e.g. contrast equalizer and denoise (profiled). It seems only the drawn masks honour the scroll up = increase size convention (and sliders also behave according to scroll up = increase value).

The last complication is the 'natural' scrolling (which, using the mouse, I find completely unnatural, but that's a question of taste), which inverts up/down and left/right.

@TurboGit : I think this warrants a more thorough review. The current scroll behaviour seems to be very inconsistent (see above -- scroll vs selection circles vs drawn mask shapes).

@dtorop
Copy link
Copy Markdown
Contributor

dtorop commented Apr 21, 2026

In src/bauhaus/bauhaus.c, the function _widget_scroll() calculates int delta = dx + dy;, and calls _slider_add_step(widget, - delta, event->scroll.state, force);

Perhaps a bit of a hack, but also seems to work well enough? Looks like it goes back at least to dd12b70.

The last complication is the 'natural' scrolling (which, using the mouse, I find completely unnatural, but that's a question of taste), which inverts up/down and left/right.

Though I'm a natural scrolling user, given that it inverts the normal OS behavior, should we design for consistent "unnatural" behavior, and folks like me with flipped scrolling will see the panels scroll/up down in an intuitive way but will have to live with everything else being flipped? In which case:

  • dy > 0 — scroll down (wheel rolled toward user) or decrease
  • dy < 0 — scroll up (wheel rolled away from user) or increase
  • dx > 0 — scroll right (horizontal wheel / touchpad) or increase
  • dx < 0 — scroll left or decrease

It's a bit backwards as increase is either dy < 0 or dx > 0, but is this at least user-visible consistent?

Besides ironing out inconsistencies, perhaps comments would help for the future, e.g.:

modified   src/gui/gtk.h
@@ -221,7 +221,9 @@ gboolean dt_gui_ignore_scroll(GdkEventScroll *event);
 /* Return requested scroll delta(s) from event. If delta_x or delta_y
  * is NULL, do not return that delta. Return TRUE if requested deltas
  * can be retrieved. Handles both GDK_SCROLL_UP/DOWN/LEFT/RIGHT and
- * GDK_SCROLL_SMOOTH style scroll events. */
+ * GDK_SCROLL_SMOOTH style scroll events. A negative delta_x represent
+ * a leftward scroll or decrease in value. A negative delta_y
+ * represents an upward scroll or increase in value. */
 gboolean dt_gui_get_scroll_deltas(const GdkEventScroll *event, gdouble *delta_x, gdouble *delta_y);
 /* Same as above, except accumulate smooth scrolls deltas of < 1 and
  * only set deltas and return TRUE once scrolls accumulate to >= 1.
@@ -575,6 +577,9 @@ GtkEventController *(dt_gui_connect_motion)(GtkWidget *widget,
   ASSERT_FUNC_TYPE(leave, void(*)(GtkEventControllerMotion *, __typeof__(data))), \
   dt_gui_connect_motion(GTK_WIDGET(widget), G_CALLBACK(motion), G_CALLBACK(enter), G_CALLBACK(leave), (data)))
 
+/* For the callback, a negative delta_x represent a leftward scroll or
+ * decrease in value. A negative delta_y represents an upward scroll
+ * or increase in value. */
 GtkEventController *(dt_gui_connect_scroll)(GtkWidget *widget,
 					    GtkEventControllerScrollFlags flags,
                                             GCallback scroll,

@kofa73
Copy link
Copy Markdown
Contributor Author

kofa73 commented Apr 21, 2026

See #20843

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants