> On 20 May 2022, at 17:26, Sean Murphy via Interest <interest@qt-project.org> 
> wrote:
> 
> The subject mostly says it all - is there a way to change the modifier used 
> to allow horizontal scrolling with mousewheel?
> 
> By default it appears that Alt + mousewheel in a QScrollArea (and 
> QGraphicsView, etc.) scrolls horizontally, but I have a user that wants that 
> to be Shift + mouse wheel instead... Fine, I'll add some settings in my 
> Options dialog to allow users to customize which key modifiers do what, but 
> then I need to make it happen.
> 
> I think I can accomplish this by adding an event filter. The issue I see is 
> that the existing Alt + mousewheel behaves just like I want - scroll 
> direction sense is the way I want it, scroll size seems sensible for a single 
> mouse wheel bump, and I don't see anywhere in the API where I can query what 
> that scroll step size is to duplicate it.
> 
> Any tips/tricks? Ideally, could I just trap the users actual event, but then 
> turn around and send an Alt+mousewheel event to the widget? That way I get 
> the default scrolling behavior, but I'm just inserting a custom modifier 
> layer over the top?
> 
> Sean

Hi Sean,

The Alt modifier key being pressed while wheeling gets interpreted very far 
down in the Qt stack, when our various QPA plugins translate the native event 
into what ultimately becomes a QWheelEvent. Simply sending a synthesized wheel 
event with the Alt modifier set to the QWidget will not trigger this behavior, 
as that never exercises that QPA code.

What QAbstractScrollArea does by default is that it checks whether the 
angleDelta of the wheel event is mostly in the x- or mostly in the y-direction, 
and then sends the wheel event on to the respective scrollbar:


void QAbstractScrollArea::wheelEvent(QWheelEvent *e)
{
    Q_D(QAbstractScrollArea);
    if (qAbs(e->angleDelta().x()) > qAbs(e->angleDelta().y()))
        QCoreApplication::sendEvent(d->hbar, e);
    else
        QCoreApplication::sendEvent(d->vbar, e);
}


So, in subclasses of your QAbstractScrollArea widgets you could check whether 
the Shift key is pressed, and then construct a QWheelEvent into which you copy 
all the attributes from the original event, but transpose the angleDelta. Then 
send that event to the respective scroll bar (shift held while angleDelta.y > 
angleDelta.x -> horizontal scroll bar). Remember to accept/ignore the original 
event based on how your synthesized event came back (calling 
QEvent::setAccepted/isAccepted).

If you want to also disable the Alt modifier’s effect, then things get a bit 
trickier (if Alt is held, assume that the original event is flipped, so unflip 
it).

If you want this to be the UX for all your QAbstractScrollArea widgets, then 
you can install an event filter on the viewport of all of them. You could also 
try to override QApplication::notify, and call the parent class implementation 
with your flipped QWheelEvent. In that case, only apply your logic if the 
original event has the QEvent::spontaneous bit set. However, that will then 
also impact widgets such as a tab bar or a spinbox unless you use qobject_cast 
to verify that the receiver’s parent is a QAbstractScrollArea.

Lastly, you probably don’t want to do any of this when the original wheel event 
comes from a kinetic scrolling device (like a track pad), so check 
QWheelEvent::phase and only do this when it’s Qt::NoScrollPhase.

Volker

_______________________________________________
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest

Reply via email to