#pragma once #include #include #include #include #include #include namespace ZShell::components { class WheelInverter : public QQuickItem { Q_OBJECT QML_ELEMENT Q_PROPERTY( QQuickItem* target READ target WRITE setTarget NOTIFY targetChanged) public: using QQuickItem::QQuickItem; QQuickItem* target() const { return m_target; } void setTarget(QQuickItem* target) { if (m_target == target) return; if (m_target) m_target->removeEventFilter(this); m_target = target; if (m_target) m_target->installEventFilter(this); emit targetChanged(); } protected: class InvertedWheelEvent : public QWheelEvent { public: using QWheelEvent::QWheelEvent; bool invertedByWheelInverter = true; }; bool eventFilter(QObject* watched, QEvent* event) override { if (watched != m_target || event->type() != QEvent::Wheel) return QQuickItem::eventFilter(watched, event); auto* wheel = static_cast(event); const bool inverted = dynamic_cast(wheel) != nullptr; if (inverted) return false; auto* window = m_target ? m_target->window() : nullptr; if (!window) { qInfo() << "[WheelInverter] no window"; return false; } const QPointF windowPos = window->mapFromGlobal(wheel->globalPosition()); auto* invertedEvent = new InvertedWheelEvent( windowPos, wheel->globalPosition(), -wheel->pixelDelta(), -wheel->angleDelta(), wheel->buttons(), wheel->modifiers(), wheel->phase(), wheel->inverted(), wheel->source(), wheel->pointingDevice()); invertedEvent->setTimestamp(wheel->timestamp()); QCoreApplication::postEvent(window, invertedEvent); return true; } signals: void targetChanged(); private: QPointer m_target; }; } // namespace ZShell::components