fix(panels): the wheel moved whatever slider the pointer was over

The rig-panel sliders take a non-passive wheel listener and acted on
hover, so scrolling the panel fed the gesture to whichever control sat
under the cursor — RF power included, mid-QSO. An operator scrolling to
read the bottom of the panel could change his transmit power without
touching anything.

They now require focus, i.e. a deliberate click on that slider first.
Without it the event is left alone and the panel scrolls, which is what
the operator meant. Same fix on the Flex and Yaesu panels, which share
the pattern.

This is a fault in its own right. It is NOT an explanation for the
"transmit power moves since 0.22.8" report: that release changed nothing
in the Icom path, and this behaviour is older than it.
This commit is contained in:
2026-08-01 20:00:03 +02:00
parent 5777c119cb
commit acf73c73c7
4 changed files with 25 additions and 2 deletions
+4 -2
View File
@@ -4,11 +4,13 @@
"date": "", "date": "",
"en": [ "en": [
"Awards: the CW / Phone / Digital filter now applies to the whole award — bands, counts, confirmations and the contacts behind a cell — instead of only hiding rows from the reference list.", "Awards: the CW / Phone / Digital filter now applies to the whole award — bands, counts, confirmations and the contacts behind a cell — instead of only hiding rows from the reference list.",
"Yaesu and Kenwood: a new option lowers the DTR and RTS lines on connect, for interfaces that read either as PTT and keep the radio transmitting while OpsLog is open. Off by default — lowering them stops other interfaces transmitting at all." "Yaesu and Kenwood: a new option lowers the DTR and RTS lines on connect, for interfaces that read either as PTT and keep the radio transmitting while OpsLog is open. Off by default — lowering them stops other interfaces transmitting at all.",
"Rig panels: the mouse wheel only moves a slider you have clicked on first. Scrolling the panel used to change whatever control the pointer happened to be over — including transmit power."
], ],
"fr": [ "fr": [
"Diplômes : le filtre CW / Phonie / Numérique sapplique désormais à tout le diplôme — bandes, comptes, confirmations et QSO derrière une case — au lieu de masquer seulement des lignes de la liste des références.", "Diplômes : le filtre CW / Phonie / Numérique sapplique désormais à tout le diplôme — bandes, comptes, confirmations et QSO derrière une case — au lieu de masquer seulement des lignes de la liste des références.",
"Yaesu et Kenwood : une option abaisse les lignes DTR et RTS à la connexion, pour les interfaces qui les lisent comme PTT et laissent la radio en émission tant quOpsLog est ouvert. Désactivée par défaut — les abaisser empêche dautres interfaces d’émettre." "Yaesu et Kenwood : une option abaisse les lignes DTR et RTS à la connexion, pour les interfaces qui les lisent comme PTT et laissent la radio en émission tant quOpsLog est ouvert. Désactivée par défaut — les abaisser empêche dautres interfaces d’émettre.",
"Panneaux radio : la molette nagit que sur un curseur préalablement cliqué. Faire défiler le panneau modifiait le réglage survolé par le pointeur — y compris la puissance d’émission."
] ]
}, },
{ {
+7
View File
@@ -86,6 +86,13 @@ function Slider({ value, onChange, disabled, accent = '#16a34a', step = 1, max =
if (!el) return; if (!el) return;
const onWheel = (e: WheelEvent) => { const onWheel = (e: WheelEvent) => {
if (disRef.current) return; if (disRef.current) return;
// The wheel only acts on a slider the operator has DELIBERATELY taken
// hold of — one that has focus. Hovering was enough before, so scrolling
// the panel with the pointer anywhere over these controls silently moved
// whatever sat under it: an IC-7800 owner watched his transmit power
// change on its own. Without focus the event is left alone and the panel
// scrolls, which is what the gesture was for.
if (document.activeElement !== el) return;
e.preventDefault(); e.preventDefault();
const d = e.deltaY < 0 ? stepRef.current : -stepRef.current; const d = e.deltaY < 0 ? stepRef.current : -stepRef.current;
const nv = Math.max(0, Math.min(maxRef.current, valRef.current + d)); const nv = Math.max(0, Math.min(maxRef.current, valRef.current + d));
+7
View File
@@ -125,6 +125,13 @@ function Slider({ value, onChange, disabled, accent = '#2563eb', step = 1 }: {
if (!el) return; if (!el) return;
const onWheel = (e: WheelEvent) => { const onWheel = (e: WheelEvent) => {
if (disRef.current) return; if (disRef.current) return;
// The wheel only acts on a slider the operator has DELIBERATELY taken
// hold of — one that has focus. Hovering was enough before, so scrolling
// the panel with the pointer anywhere over these controls silently moved
// whatever sat under it: an IC-7800 owner watched his transmit power
// change on its own. Without focus the event is left alone and the panel
// scrolls, which is what the gesture was for.
if (document.activeElement !== el) return;
e.preventDefault(); e.preventDefault();
const d = e.deltaY < 0 ? stepRef.current : -stepRef.current; const d = e.deltaY < 0 ? stepRef.current : -stepRef.current;
const nv = Math.max(0, Math.min(100, valRef.current + d)); const nv = Math.max(0, Math.min(100, valRef.current + d));
+7
View File
@@ -149,6 +149,13 @@ function Slider({ value, onChange, disabled, accent = 'var(--primary)', min = 0,
if (!el) return; if (!el) return;
const onWheel = (e: WheelEvent) => { const onWheel = (e: WheelEvent) => {
if (disRef.current) return; if (disRef.current) return;
// The wheel only acts on a slider the operator has DELIBERATELY taken
// hold of — one that has focus. Hovering was enough before, so scrolling
// the panel with the pointer anywhere over these controls silently moved
// whatever sat under it: an IC-7800 owner watched his transmit power
// change on its own. Without focus the event is left alone and the panel
// scrolls, which is what the gesture was for.
if (document.activeElement !== el) return;
e.preventDefault(); e.preventDefault();
const nv = Math.max(minRef.current, Math.min(maxRef.current, valRef.current + (e.deltaY < 0 ? 1 : -1))); const nv = Math.max(minRef.current, Math.min(maxRef.current, valRef.current + (e.deltaY < 0 ? 1 : -1)));
if (nv !== valRef.current) cbRef.current(nv); if (nv !== valRef.current) cbRef.current(nv);