diff --git a/src/develop/masks.h b/src/develop/masks.h index 786a1a80dbfd..a5281bcf023c 100644 --- a/src/develop/masks.h +++ b/src/develop/masks.h @@ -603,6 +603,10 @@ gboolean dt_masks_events_mouse_scrolled(struct dt_iop_module_t *module, const float y, const gboolean up, const uint32_t state); +// Return TRUE if scrolling over the center view should adjust the visible +// mask (size/border/opacity) instead of zoom/pan. Returns FALSE while drawing +// a path, since path creation has no scroll-adjustable parameter. +gboolean dt_masks_scroll_over_mask(void); void dt_masks_events_post_expose(const struct dt_iop_module_t *module, cairo_t *cr, const int32_t width, diff --git a/src/develop/masks/masks.c b/src/develop/masks/masks.c index 031eb52e104e..23ce8ce7f929 100644 --- a/src/develop/masks/masks.c +++ b/src/develop/masks/masks.c @@ -1225,12 +1225,27 @@ gboolean dt_masks_events_button_pressed(dt_iop_module_t *module, if(form->functions) return form->functions->button_pressed(module, pzx, pzy, pressure, which, type, state, form, 0, gui, 0) - || which == 3; // swallow right-clicks even when not handled so - // right-drag rotate is disabled when forms - // visible + || which == 3; // swallow right-clicks so right-drag rotate is disabled return FALSE; } +gboolean dt_masks_scroll_over_mask(void) +{ + const dt_masks_form_t *form = darktable.develop->form_visible; + const dt_masks_form_gui_t *gui = darktable.develop->form_gui; + if(!form || !gui) + return FALSE; + + // During shape creation, scroll adjusts size/border and stays over the mask. + // Paths/polygons are built node by node and do not use scroll here. + if(gui->creation) + return !(form->type & DT_MASKS_PATH); + + // Otherwise form_visible is the group. group_edited is the active sub-form or + // -1 when none. Scroll should count only when a sub-form is active. + return gui->group_edited >= 0; +} + gboolean dt_masks_events_mouse_scrolled(dt_iop_module_t *module, const float pzx, const float pzy, @@ -1250,8 +1265,7 @@ gboolean dt_masks_events_mouse_scrolled(dt_iop_module_t *module, if(gui) { - // for brush, the opacity is the density of the masks, do not - // update opacity here for the brush. + // Do not update brush opacity here; it is mask density. if(gui->creation && dt_modifier_is(state, GDK_CONTROL_MASK)) { float opacity = dt_conf_get_float("plugins/darkroom/masks/opacity"); diff --git a/src/views/darkroom.c b/src/views/darkroom.c index c0ad91aee15b..0ad5215b4af8 100644 --- a/src/views/darkroom.c +++ b/src/views/darkroom.c @@ -4217,12 +4217,14 @@ gboolean gesture_pan(dt_view_t *self, (void)state; if(!dev) return FALSE; - // Mask editing (brush etc.) uses scroll for tool parameters. + // If pointer is over an active mask, let scroll go to the mask handler; + // otherwise allow two-finger scroll to pan the image. if(dev->form_visible - && !darktable.develop->darkroom_skip_mouse_events) + && !darktable.develop->darkroom_skip_mouse_events + && dt_masks_scroll_over_mask()) { dt_print(DT_DEBUG_INPUT, - "[darkroom pan] ignored: mask form active"); + "[darkroom pan] ignored: pointer over active mask"); return FALSE; }