@@ -4669,90 +4669,73 @@ GtkEventController *(dt_gui_connect_scroll)(GtkWidget *widget,
46694669}
46704670
46714671typedef void (* scroll_handler_t )(GtkEventControllerScroll * , gdouble , gdouble , gpointer );
4672+ static gdouble _scroll_discrete_dx = 0.0 ;
4673+ static gdouble _scroll_discrete_dy = 0.0 ;
4674+ static const char * _scroll_discrete_real_handler_key = "real-scroll-discrete-handler" ;
46724675
4673- #ifdef GDK_WINDOWING_QUARTZ
4674- typedef struct _scroll_handler_proxy_t
4675- {
4676- scroll_handler_t scroll_callback_real ;
4677- gpointer scroll_data_real ;
4678- gboolean smooth_scroll ;
4679- gdouble cur_dx ;
4680- gdouble cur_dy ;
4681- } _scroll_handler_proxy_t ;
4682-
4683- static void _scroll_discrete_begin (GtkEventControllerScroll * self ,
4684- _scroll_handler_proxy_t * h )
4685- {
4686- // scroll-begin is generated by events from trackpoint or touchpad
4687- h -> smooth_scroll = TRUE;
4688- h -> cur_dx = h -> cur_dy = 0.0 ;
4689- }
4690-
4691- static void _scroll_discrete_end (GtkEventControllerScroll * self ,
4692- _scroll_handler_proxy_t * h )
4693- {
4694- h -> smooth_scroll = FALSE;
4695- }
4696-
4697- static void _scroll_discrete_proxy (GtkEventControllerScroll * self ,
4698- gdouble dx ,
4699- gdouble dy ,
4700- _scroll_handler_proxy_t * h )
4676+ static void _scroll_discrete_proxy (GtkEventControllerScroll * controller ,
4677+ gdouble dx ,
4678+ gdouble dy ,
4679+ gpointer user_data )
47014680{
4702- // Even though the event controller has already accumulated smooth
4703- // scroll events to discrete dx/dy, MacOS smooth scrolling events
4704- // are too fast so scale them down via another accumulating stage.
4705- // For GTK3, we handled this via dt_gui_get_scroll_unit_deltas(),
4706- // but to be GTK4 ready, use this code, which is heavily modeled on
4707- // GTK's gtk_event_controller_scroll_handle_event()
4708- if (h -> smooth_scroll )
4681+ GdkEvent * event = gtk_get_current_event ();
4682+ if (!event ) return ;
4683+ if (gdk_event_get_event_type (event ) == GDK_SCROLL
4684+ && event -> scroll .direction == GDK_SCROLL_SMOOTH
4685+ // avoid double counting real and emulated events when receiving smooth scrolls
4686+ && !gdk_event_get_pointer_emulated (event ))
47094687 {
4710- h -> cur_dx += dx / DT_UI_SCROLL_SMOOTH_DELTA_SCALE ;
4711- h -> cur_dy += dy / DT_UI_SCROLL_SMOOTH_DELTA_SCALE ;
4688+ // MacOS scrolling is apparently distance-based, so can produce a
4689+ // range of large/small deltas. For GTK3, we accumulating &
4690+ // attenuating via dt_gui_get_scroll_unit_deltas(). For GTK4-ready
4691+ // "scroll" events, work as discrete scrolling implemented in
4692+ // gtk_event_controller_scroll_handle_event() but also attenuate
4693+ #ifdef GDK_WINDOWING_QUARTZ
4694+ const double scale = 0.25 ;
4695+ const double compression = 0.7 ;
4696+ #else
4697+ const double scale = 0.95 ;
4698+ const double compression = 0.9 ;
4699+ #endif
4700+ _scroll_discrete_dx += copysign (pow (fabs (dx ), compression ), dx * scale );
4701+ _scroll_discrete_dy += copysign (pow (fabs (dy ), compression ), dy * scale );
47124702 dx = dy = 0.0 ;
4713- if (fabs (h -> cur_dx ) >= 1.0 )
4703+ if (fabs (_scroll_discrete_dx ) >= 1.0 )
47144704 {
4715- int steps = trunc (h -> cur_dx );
4716- h -> cur_dx -= steps ;
4705+ int steps = trunc (_scroll_discrete_dx );
4706+ _scroll_discrete_dx -= steps ;
47174707 dx = steps ;
47184708 }
4719- if (fabs (h -> cur_dy ) >= 1.0 )
4709+ if (fabs (_scroll_discrete_dy ) >= 1.0 )
47204710 {
4721- int steps = trunc (h -> cur_dy );
4722- h -> cur_dy -= steps ;
4711+ int steps = trunc (_scroll_discrete_dy );
4712+ _scroll_discrete_dy -= steps ;
47234713 dy = steps ;
47244714 }
47254715 }
47264716 if (dx != 0.0 || dy != 0.0 )
4727- h -> scroll_callback_real (self , dx , dy , h -> scroll_data_real );
4717+ {
4718+ scroll_handler_t real_handler =
4719+ g_object_get_data (G_OBJECT (controller ), _scroll_discrete_real_handler_key );
4720+ real_handler (controller , dx , dy , user_data );
4721+ }
4722+ gdk_event_free (event );
47284723}
4729- #endif
47304724
47314725GtkEventController * (dt_gui_connect_scroll_discrete )(GtkWidget * widget ,
47324726 GtkEventControllerScrollFlags flags ,
47334727 GCallback scroll_callback ,
4734- gpointer data )
4728+ gpointer user_data )
47354729{
4736- // on macOS, set up a proxy to scale smooth scroll deltas
4737- #ifdef GDK_WINDOWING_QUARTZ
4738- _scroll_handler_proxy_t * const h = dt_calloc1_align_type (_scroll_handler_proxy_t );
4739- h -> scroll_callback_real = (scroll_handler_t )scroll_callback ;
4740- h -> scroll_data_real = data ;
4730+ // Use proxy, not GTK discrete scrolling, to attenuate. We could use
4731+ // GTK discrete scrolling for non-MacOS, but it makes it hard to
4732+ // test if a chunk of code is particular to one OS.
47414733 GtkEventController * controller =
4742- dt_gui_connect_scroll (widget ,
4743- flags | GTK_EVENT_CONTROLLER_SCROLL_DISCRETE ,
4744- _scroll_discrete_proxy ,
4745- h );
4746- g_object_weak_ref (G_OBJECT (widget ), (GWeakNotify ) dt_free_align_ptr , h );
4747- g_signal_connect (controller , "scroll-begin" , G_CALLBACK (_scroll_discrete_begin ), h );
4748- g_signal_connect (controller , "scroll-end" , G_CALLBACK (_scroll_discrete_end ), h );
4734+ dt_gui_connect_scroll (widget , flags & ~GTK_EVENT_CONTROLLER_SCROLL_DISCRETE ,
4735+ _scroll_discrete_proxy , user_data );
4736+ g_object_set_data (G_OBJECT (controller ),
4737+ _scroll_discrete_real_handler_key , scroll_callback );
47494738 return controller ;
4750- #else
4751- return dt_gui_connect_scroll (widget ,
4752- flags | GTK_EVENT_CONTROLLER_SCROLL_DISCRETE ,
4753- (scroll_handler_t )scroll_callback ,
4754- data );
4755- #endif
47564739}
47574740
47584741
0 commit comments