Skip to content

Commit e706f3d

Browse files
committed
Use gesture_pan on macOS
The macOS built-in trackpad reports as GDK_SOURCE_MOUSE (not GDK_SOURCE_TOUCHPAD). The _scrolled routing condition required either GDK_SOURCE_TOUCHPAD or a device previously seen in a pinch event (_touchpad). On macOS, neither condition held before a pinch had been seen, so two-finger scroll events fell through to dt_view_manager_scrolled (image navigation) instead of gesture_pan (panning). A #ifdef GDK_WINDOWING_QUARTZ branch now routes all non-ctrl smooth scrolls to gesture_pan on macOS. Net result: On macOS, zoom via pinch works (was already working), and pan via two-finger swipe now works via gesture_pan. Combined pinch+pan simultaneously is not possible at the GDK level on macOS — NSEventTypeMagnify does not deliver the translational component; it must be done as sequential operations (zoom then pan).
1 parent 643493e commit e706f3d

2 files changed

Lines changed: 21 additions & 24 deletions

File tree

src/gui/gtk.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -778,9 +778,19 @@ static gboolean _scrolled(GtkWidget *widget,
778778
const gboolean is_known_gesture_device = (device == _touchpad);
779779
const gboolean is_smooth = event->direction == GDK_SCROLL_SMOOTH && !event->is_stop;
780780

781-
if(!ctrl_held
782-
&& (is_touchpad_source || is_known_gesture_device)
783-
&& is_smooth)
781+
#ifdef GDK_WINDOWING_QUARTZ
782+
// On macOS/Quartz, the built-in trackpad reports as GDK_SOURCE_MOUSE, not
783+
// GDK_SOURCE_TOUCHPAD. Route every non-ctrl smooth scroll to gesture_pan so
784+
// that two-finger panning works in views like darkroom (both standalone and
785+
// interleaved with a pinch-zoom gesture whose translational component macOS
786+
// delivers as a separate scroll stream).
787+
const gboolean route_as_pan = !ctrl_held && is_smooth;
788+
#else
789+
const gboolean route_as_pan = !ctrl_held
790+
&& (is_touchpad_source || is_known_gesture_device)
791+
&& is_smooth;
792+
#endif
793+
if(route_as_pan)
784794
{
785795
gdouble delta_x = 0.0, delta_y = 0.0;
786796
if(!dt_gui_get_scroll_deltas(event, &delta_x, &delta_y))
@@ -810,9 +820,9 @@ static gboolean _scrolled(GtkWidget *widget,
810820
{
811821
dt_print(DT_DEBUG_INPUT,
812822
"[touchpad] smooth scroll not routed as pan:"
813-
" ctrl=%d touchpad_source=%d known_gesture_dev=%d"
823+
" ctrl=%d touchpad_source=%d known_gesture_dev=%d route_as_pan=%d"
814824
" device='%s' source-type=%d",
815-
ctrl_held, is_touchpad_source, is_known_gesture_device,
825+
ctrl_held, is_touchpad_source, is_known_gesture_device, route_as_pan,
816826
device ? gdk_device_get_name(device) : "<none>",
817827
device ? (int)gdk_device_get_source(device) : -1);
818828
}

src/views/darkroom.c

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4208,19 +4208,12 @@ gboolean gesture_pinch(dt_view_t *self,
42084208
if(!dev) return FALSE;
42094209
(void)state;
42104210
static float pinch_begin_tscale = 0.0f;
4211-
#ifdef GDK_WINDOWING_QUARTZ
4212-
static double pinch_prev_x = 0.0, pinch_prev_y = 0.0;
4213-
#endif
42144211

42154212
if(phase == GDK_TOUCHPAD_GESTURE_PHASE_BEGIN)
42164213
{
42174214
pinch_begin_tscale =
42184215
dt_dev_get_zoom_scale(&dev->full, dev->full.zoom, 1 << dev->full.closeup, FALSE)
42194216
* dev->full.ppd;
4220-
#ifdef GDK_WINDOWING_QUARTZ
4221-
pinch_prev_x = x;
4222-
pinch_prev_y = y;
4223-
#endif
42244217
dt_print(DT_DEBUG_INPUT,
42254218
"[darkroom pinch] begin x=%.1f y=%.1f scale=%.6f state=0x%x"
42264219
" -> begin_tscale=%.6f ppd=%.2f",
@@ -4252,20 +4245,14 @@ gboolean gesture_pinch(dt_view_t *self,
42524245
return FALSE;
42534246
}
42544247

4255-
#ifdef GDK_WINDOWING_QUARTZ
4256-
// On macOS (GDK Quartz), NSEventTypeMagnify does not populate deltaX/deltaY,
4257-
// so GDK fills pinch->dx and pinch->dy with 0. Infer translation from the
4258-
// movement of the gesture focal point (midpoint between the two fingers).
4259-
const double eff_dx = x - pinch_prev_x;
4260-
const double eff_dy = y - pinch_prev_y;
4261-
#else
4248+
// On macOS (GDK Quartz), NSEventTypeMagnify never populates dx/dy and the
4249+
// gesture focal-point x/y is set once at phase=BEGIN and does not update
4250+
// during the gesture — so both approaches to infer translation are zero.
4251+
// Pan on macOS therefore arrives as a separate smooth-scroll stream which is
4252+
// routed to gesture_pan by _scrolled() in gtk.c.
4253+
// On other platforms (Wayland/X11), dx/dy carry the actual translational delta.
42624254
const double eff_dx = dx;
42634255
const double eff_dy = dy;
4264-
#endif
4265-
#ifdef GDK_WINDOWING_QUARTZ
4266-
pinch_prev_x = x;
4267-
pinch_prev_y = y;
4268-
#endif
42694256

42704257
if(eff_dx != 0.0 || eff_dy != 0.0)
42714258
{

0 commit comments

Comments
 (0)