22using System . Threading . Tasks ;
33using AsyncAwaitBestPractices ;
44using Avalonia . Controls ;
5+ using Avalonia . Controls . Primitives ;
6+ using Avalonia . Input ;
7+ using Avalonia . Interactivity ;
8+ using Avalonia . VisualTree ;
59using CommunityToolkit . Mvvm . Input ;
610using FluentAvalonia . UI . Controls ;
711using Microsoft . Extensions . DependencyInjection ;
812using StabilityMatrix . Avalonia . Services ;
913using StabilityMatrix . Avalonia . ViewModels . Base ;
1014using StabilityMatrix . Avalonia . ViewModels . Dialogs ;
15+ using StabilityMatrix . Core . Helper ;
1116using StabilityMatrix . Core . Models ;
1217
1318namespace StabilityMatrix . Avalonia . Controls ;
@@ -17,6 +22,66 @@ public partial class FADownloadableComboBox : FAComboBox
1722{
1823 protected override Type StyleKeyOverride => typeof ( FAComboBox ) ;
1924
25+ private Popup ? dropDownPopup ;
26+ private IDisposable ? openSubscription ;
27+
28+ protected override void OnApplyTemplate ( TemplateAppliedEventArgs e )
29+ {
30+ base . OnApplyTemplate ( e ) ;
31+
32+ CleanupSubscription ( ) ;
33+ DropDownOpened -= OnDropDownOpenedHandler ;
34+ DropDownClosed -= OnDropDownClosedHandler ;
35+
36+ // Template part name is "Popup" per FAComboBox.properties.cs (s_tpPopup = "Popup")
37+ dropDownPopup = e . NameScope . Find < Popup > ( "Popup" ) ;
38+
39+ DropDownOpened += OnDropDownOpenedHandler ;
40+ DropDownClosed += OnDropDownClosedHandler ;
41+ }
42+
43+ private void OnDropDownOpenedHandler ( object ? sender , EventArgs e )
44+ {
45+ CleanupSubscription ( ) ;
46+
47+ if ( dropDownPopup ? . Child is not Control popupChild )
48+ return ;
49+
50+ var scrollViewer = popupChild . GetVisualDescendants ( ) . OfType < ScrollViewer > ( ) . FirstOrDefault ( ) ;
51+
52+ if ( scrollViewer == null )
53+ return ;
54+
55+ // On Unix-like systems, overlay popups share the same TopLevel visual root as the main window.
56+ // FAComboBox.OnPopupOpened adds a TopLevel tunnel handler that marks all wheel eventsas handled while the dropdown is open,
57+ // which inadvertently blocks scroll-wheelevents in popup menus in Inference model cards.
58+ // Resetting e.Handled on the ScrollViewer's tunnel phase counters this.
59+ if ( ! Compat . IsUnix )
60+ return ;
61+
62+ openSubscription = scrollViewer . AddDisposableHandler (
63+ PointerWheelChangedEvent ,
64+ static ( _ , ev ) =>
65+ {
66+ if ( ev . Handled )
67+ ev . Handled = false ;
68+ } ,
69+ RoutingStrategies . Tunnel ,
70+ handledEventsToo : true
71+ ) ;
72+ }
73+
74+ private void OnDropDownClosedHandler ( object ? sender , EventArgs e )
75+ {
76+ CleanupSubscription ( ) ;
77+ }
78+
79+ private void CleanupSubscription ( )
80+ {
81+ openSubscription ? . Dispose ( ) ;
82+ openSubscription = null ;
83+ }
84+
2085 static FADownloadableComboBox ( )
2186 {
2287 SelectionChangedEvent . AddClassHandler < FADownloadableComboBox > (
0 commit comments