@@ -382,6 +382,31 @@ def poll(self, *args):
382382 callback (event , * args )
383383
384384 def add_event (self , event ):
385+ if (
386+ event .type == events .MOUSEWHEEL
387+ and self ._fifo
388+ and self ._fifo [- 1 ].type == events .MOUSEWHEEL
389+ ):
390+ # Sum, don't replace: unlike a motion sample (only the latest
391+ # position matters), every wheel delta has to count toward
392+ # the total scroll distance. Some backends (WinDisplay,
393+ # confirmed) emit far more wheel messages per physical
394+ # gesture than others (SDL) - without this, a fast scroll
395+ # queues faster than the "keep calling me until empty"
396+ # read-cycle mechanism can drain one at a time, and the
397+ # window stops responding for as long as scrolling continues.
398+ last = self ._fifo [- 1 ]
399+ self ._fifo [- 1 ] = events .Wheel (
400+ event .type ,
401+ event .flipped ,
402+ last .x + event .x ,
403+ last .y + event .y ,
404+ last .precise_x + event .precise_x ,
405+ last .precise_y + event .precise_y ,
406+ event .touch ,
407+ event .window ,
408+ )
409+ return
385410 if (
386411 event .type == events .MOUSEMOTION
387412 and self ._fifo
@@ -432,6 +457,10 @@ def _set_finger(self, finger_id, point):
432457 def __init__ (self , host_device , window_id = None ):
433458 self ._host_device = host_device
434459 self ._window_id = window_id
460+ # For QUIT below: the app that owns this HOST device (App.add_device
461+ # sets dev.app = self on every device it registers), so a window
462+ # close reaches the same app.request_quit() a script calls by hand.
463+ self ._app = getattr (host_device , "app" , None )
435464 self ._vd_pointer = self .VirtualDevice (self , POINTER )
436465 self ._vd_encoder = self .VirtualDevice (self , ENCODER )
437466 self ._vd_keypad = self .VirtualDevice (self , KEYPAD )
@@ -507,6 +536,15 @@ def _route(self, event):
507536 _wheel_navigate_cb (event )
508537 elif event .type in (events .KEYDOWN , events .KEYUP ):
509538 self ._vd_keypad .add_event (event )
539+ elif event .type == events .QUIT :
540+ # Window-close reaches here (e.g. windisplay.WinDisplay's
541+ # WM_CLOSE handler queues one) but nothing previously acted on
542+ # it: every LVGL indev is polled straight from LVGL's own read
543+ # timer, not from App.poll()'s loop, so App's own QUIT handling
544+ # never saw it — the event was silently dropped and the window
545+ # could not be closed at all.
546+ if self ._app is not None :
547+ self ._app .request_quit ()
510548
511549
512550class event_loop :
0 commit comments