From d175f216196bddddfd60b1637cc5a8bac40f5214 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 21 Jun 2024 15:49:28 +0200 Subject: [PATCH] wayland: various fixes and improvements also added devices --- include/aquamarine/backend/Backend.hpp | 1 + include/aquamarine/backend/Wayland.hpp | 11 +- include/aquamarine/input/Input.hpp | 146 ++++++++++++++++++++++++- src/allocator/GBM.cpp | 2 +- src/backend/Backend.cpp | 1 + src/backend/Wayland.cpp | 50 ++++++--- 6 files changed, 191 insertions(+), 20 deletions(-) diff --git a/include/aquamarine/backend/Backend.hpp b/include/aquamarine/backend/Backend.hpp index 836d0c6..017239a 100644 --- a/include/aquamarine/backend/Backend.hpp +++ b/include/aquamarine/backend/Backend.hpp @@ -104,6 +104,7 @@ namespace Aquamarine { } events; Hyprutils::Memory::CSharedPointer allocator; + bool ready = false; private: CBackend(); diff --git a/include/aquamarine/backend/Wayland.hpp b/include/aquamarine/backend/Wayland.hpp index f2342af..6c2906c 100644 --- a/include/aquamarine/backend/Wayland.hpp +++ b/include/aquamarine/backend/Wayland.hpp @@ -16,6 +16,8 @@ namespace Aquamarine { class CWaylandBackend; class CWaylandOutput; + typedef std::function FIdleCallback; + class CWaylandBuffer { public: CWaylandBuffer(Hyprutils::Memory::CSharedPointer buffer_, Hyprutils::Memory::CWeakPointer backend_); @@ -55,6 +57,12 @@ namespace Aquamarine { Hyprutils::Memory::CSharedPointer wlBufferFromBuffer(Hyprutils::Memory::CSharedPointer buffer); void sendFrameAndSetCallback(); + void onFrameDone(); + + // frame loop + bool frameScheduledWhileWaiting = false; + bool readyForFrameCallback = false; // true after attaching a buffer + bool frameScheduled = false; struct { std::vector, Hyprutils::Memory::CSharedPointer>> buffers; @@ -123,9 +131,10 @@ namespace Aquamarine { // Hyprutils::Memory::CWeakPointer backend; - std::vector> outputs, scheduledFrames; + std::vector> outputs; std::vector> keyboards; std::vector> pointers; + std::vector idleCallbacks; // pointer focus Hyprutils::Memory::CWeakPointer focusedOutput; diff --git a/include/aquamarine/input/Input.hpp b/include/aquamarine/input/Input.hpp index ff46eb1..a9fd6f9 100644 --- a/include/aquamarine/input/Input.hpp +++ b/include/aquamarine/input/Input.hpp @@ -45,11 +45,25 @@ namespace Aquamarine { AQ_POINTER_AXIS_HORIZONTAL, }; + enum ePointerAxisSource { + AQ_POINTER_AXIS_SOURCE_WHEEL = 0, + AQ_POINTER_AXIS_SOURCE_FINGER, + AQ_POINTER_AXIS_SOURCE_CONTINUOUS, + AQ_POINTER_AXIS_SOURCE_TILT, + }; + + enum ePointerAxisRelativeDirection { + AQ_POINTER_AXIS_RELATIVE_IDENTICAL = 0, + AQ_POINTER_AXIS_RELATIVE_INVERTED, + }; + struct SMoveEvent { - Hyprutils::Math::Vector2D delta; + uint32_t timeMs = 0; + Hyprutils::Math::Vector2D delta, unaccel; }; struct SWarpEvent { + uint32_t timeMs = 0; Hyprutils::Math::Vector2D absolute; }; @@ -60,9 +74,54 @@ namespace Aquamarine { }; struct SAxisEvent { - uint32_t timeMs = 0; - ePointerAxis axis = AQ_POINTER_AXIS_VERTICAL; - double value = 0.0; + uint32_t timeMs = 0; + ePointerAxis axis = AQ_POINTER_AXIS_VERTICAL; + ePointerAxisSource source = AQ_POINTER_AXIS_SOURCE_WHEEL; + ePointerAxisRelativeDirection direction = AQ_POINTER_AXIS_RELATIVE_IDENTICAL; + double delta = 0.0, discrete = 0.0; + }; + + struct SSwipeBeginEvent { + uint32_t timeMs = 0; + uint32_t fingers = 0; + }; + + struct SSwipeUpdateEvent { + uint32_t timeMs = 0; + uint32_t fingers = 0; + Hyprutils::Math::Vector2D delta; + }; + + struct SSwipeEndEvent { + uint32_t timeMs = 0; + bool cancelled = false; + }; + + struct SPinchBeginEvent { + uint32_t timeMs = 0; + uint32_t fingers = 0; + }; + + struct SPinchUpdateEvent { + uint32_t timeMs = 0; + uint32_t fingers = 0; + Hyprutils::Math::Vector2D delta; + double scale = 1.0, rotation = 0.0; + }; + + struct SPinchEndEvent { + uint32_t timeMs = 0; + bool cancelled = false; + }; + + struct SHoldBeginEvent { + uint32_t timeMs = 0; + uint32_t fingers = 0; + }; + + struct SHoldEndEvent { + uint32_t timeMs = 0; + bool cancelled = false; }; struct { @@ -72,6 +131,85 @@ namespace Aquamarine { Hyprutils::Signal::CSignal button; Hyprutils::Signal::CSignal axis; Hyprutils::Signal::CSignal frame; + + Hyprutils::Signal::CSignal swipeBegin; + Hyprutils::Signal::CSignal swipeUpdate; + Hyprutils::Signal::CSignal swipeEnd; + + Hyprutils::Signal::CSignal pinchBegin; + Hyprutils::Signal::CSignal pinchUpdate; + Hyprutils::Signal::CSignal pinchEnd; + + Hyprutils::Signal::CSignal holdBegin; + Hyprutils::Signal::CSignal holdEnd; + } events; + }; + + class ITouch { + public: + virtual ~ITouch() { + events.destroy.emit(); + } + + virtual libinput_device* getLibinputHandle(); + virtual const std::string& getName() = 0; + + struct SDownEvent { + uint32_t timeMs = 0; + int32_t touchID = 0; + Hyprutils::Math::Vector2D pos; + }; + + struct SUpEvent { + uint32_t timeMs = 0; + int32_t touchID = 0; + }; + + struct SMotionEvent { + uint32_t timeMs = 0; + int32_t touchID = 0; + Hyprutils::Math::Vector2D pos; + }; + + struct SCancelEvent { + uint32_t timeMs = 0; + int32_t touchID = 0; + }; + + struct { + Hyprutils::Signal::CSignal destroy; + Hyprutils::Signal::CSignal move; + Hyprutils::Signal::CSignal down; + Hyprutils::Signal::CSignal up; + Hyprutils::Signal::CSignal cancel; + Hyprutils::Signal::CSignal frame; + } events; + }; + + class ITablet { + public: + // FIXME: + + struct { + Hyprutils::Signal::CSignal destroy; + } events; + }; + + class ITabletTool { + public: + // FIXME: + + struct { + Hyprutils::Signal::CSignal destroy; + } events; + }; + + class ITabletPad { + public: + // FIXME: + + struct { + Hyprutils::Signal::CSignal destroy; } events; }; } \ No newline at end of file diff --git a/src/allocator/GBM.cpp b/src/allocator/GBM.cpp index 5d76ab4..40d1609 100644 --- a/src/allocator/GBM.cpp +++ b/src/allocator/GBM.cpp @@ -48,7 +48,7 @@ Aquamarine::CGBMBuffer::CGBMBuffer(const SAllocatorBufferParams& params, Hypruti auto modName = drmGetFormatModifierName(attrs.modifier); allocator->backend->log( - AQ_LOG_ERROR, + AQ_LOG_DEBUG, std::format("GBM: Allocated a new buffer with size {} and format {} with modifier {}", attrs.size, fourccToName(attrs.format), modName ? modName : "Unknown")); free(modName); diff --git a/src/backend/Backend.cpp b/src/backend/Backend.cpp index 3aa009e..ddf1459 100644 --- a/src/backend/Backend.cpp +++ b/src/backend/Backend.cpp @@ -103,6 +103,7 @@ bool Aquamarine::CBackend::start() { if (!allocator) return false; + ready = true; for (auto& b : implementations) { b->onReady(); } diff --git a/src/backend/Wayland.cpp b/src/backend/Wayland.cpp index e228289..c16c4f3 100644 --- a/src/backend/Wayland.cpp +++ b/src/backend/Wayland.cpp @@ -88,7 +88,7 @@ int Aquamarine::CWaylandBackend::drmFD() { void Aquamarine::CWaylandBackend::createOutput(const std::string& szName) { auto o = outputs.emplace_back(SP(new CWaylandOutput(szName, self))); o->self = o; - backend->events.newOutput.emit(SP(o)); + idleCallbacks.emplace_back([this, o]() { backend->events.newOutput.emit(SP(o)); }); } int Aquamarine::CWaylandBackend::pollFD() { @@ -114,12 +114,13 @@ bool Aquamarine::CWaylandBackend::dispatchEvents() { } while (ret > 0); // dispatch frames - for (auto& f : scheduledFrames) { - f->events.frame.emit(); + if (backend->ready) { + for (auto& f : idleCallbacks) { + f(); + } + idleCallbacks.clear(); } - scheduledFrames.clear(); - return true; } @@ -189,7 +190,11 @@ Aquamarine::CWaylandPointer::CWaylandPointer(SP pointer_, Hyprutils Vector2D local = {wl_fixed_to_double(x), wl_fixed_to_double(y)}; local = local / size; + timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + events.warp.emit(SWarpEvent{ + .timeMs = (uint32_t)(now.tv_sec * 1000 + now.tv_nsec / 1000000), .absolute = local, }); }); @@ -219,7 +224,7 @@ Aquamarine::CWaylandPointer::CWaylandPointer(SP pointer_, Hyprutils events.axis.emit(SAxisEvent{ .timeMs = timeMs, .axis = axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL ? AQ_POINTER_AXIS_HORIZONTAL : AQ_POINTER_AXIS_VERTICAL, - .value = wl_fixed_to_double(value), + .delta = wl_fixed_to_double(value), }); }); @@ -241,13 +246,13 @@ void Aquamarine::CWaylandBackend::initSeat() { if (HAS_KEYBOARD && keyboards.empty()) { auto k = keyboards.emplace_back(makeShared(makeShared(waylandState.seat->sendGetKeyboard()), self)); - backend->events.newKeyboard.emit(SP(k)); + idleCallbacks.emplace_back([this, k]() { backend->events.newKeyboard.emit(SP(k)); }); } else if (!HAS_KEYBOARD && !keyboards.empty()) keyboards.clear(); if (HAS_POINTER && pointers.empty()) { auto p = pointers.emplace_back(makeShared(makeShared(waylandState.seat->sendGetPointer()), self)); - backend->events.newPointer.emit(SP(p)); + idleCallbacks.emplace_back([this, p]() { backend->events.newPointer.emit(SP(p)); }); } else if (!HAS_POINTER && !pointers.empty()) pointers.clear(); }); @@ -436,6 +441,8 @@ bool Aquamarine::CWaylandOutput::commit() { waylandState.surface->sendDamageBuffer(0, 0, INT32_MAX, INT32_MAX); waylandState.surface->sendCommit(); + readyForFrameCallback = true; + return true; } @@ -466,14 +473,24 @@ SP Aquamarine::CWaylandOutput::wlBufferFromBuffer(SP bu void Aquamarine::CWaylandOutput::sendFrameAndSetCallback() { events.frame.emit(); - if (waylandState.frameCallback) + frameScheduled = false; + if (waylandState.frameCallback || !readyForFrameCallback) return; waylandState.frameCallback = makeShared(waylandState.surface->sendFrame()); - waylandState.frameCallback->setDone([this](CCWlCallback* r, uint32_t ms) { + waylandState.frameCallback->setDone([this](CCWlCallback* r, uint32_t ms) { onFrameDone(); }); +} + +void Aquamarine::CWaylandOutput::onFrameDone() { + waylandState.frameCallback.reset(); + readyForFrameCallback = false; + + if (frameScheduledWhileWaiting) + sendFrameAndSetCallback(); + else events.frame.emit(); - waylandState.frameCallback.reset(); - }); + + frameScheduledWhileWaiting = false; } bool Aquamarine::CWaylandOutput::setCursor(Hyprutils::Memory::CSharedPointer buffer, const Hyprutils::Math::Vector2D& hotspot) { @@ -485,10 +502,15 @@ void Aquamarine::CWaylandOutput::moveCursor(const Hyprutils::Math::Vector2D& coo } void Aquamarine::CWaylandOutput::scheduleFrame() { - if (std::find(backend->scheduledFrames.begin(), backend->scheduledFrames.end(), self.lock()) != backend->scheduledFrames.end()) + if (frameScheduled) return; - backend->scheduledFrames.emplace_back(self.lock()); + frameScheduled = true; + + if (waylandState.frameCallback) + frameScheduledWhileWaiting = true; + else + backend->idleCallbacks.emplace_back([this]() { sendFrameAndSetCallback(); }); } Aquamarine::CWaylandBuffer::CWaylandBuffer(SP buffer_, Hyprutils::Memory::CWeakPointer backend_) : buffer(buffer_), backend(backend_) {