wayland: various fixes and improvements

also added devices
This commit is contained in:
Vaxry 2024-06-21 15:49:28 +02:00
parent a7a8840400
commit d175f21619
6 changed files with 191 additions and 20 deletions

View file

@ -104,6 +104,7 @@ namespace Aquamarine {
} events;
Hyprutils::Memory::CSharedPointer<IAllocator> allocator;
bool ready = false;
private:
CBackend();

View file

@ -16,6 +16,8 @@ namespace Aquamarine {
class CWaylandBackend;
class CWaylandOutput;
typedef std::function<void(void)> FIdleCallback;
class CWaylandBuffer {
public:
CWaylandBuffer(Hyprutils::Memory::CSharedPointer<IBuffer> buffer_, Hyprutils::Memory::CWeakPointer<CWaylandBackend> backend_);
@ -55,6 +57,12 @@ namespace Aquamarine {
Hyprutils::Memory::CSharedPointer<CWaylandBuffer> wlBufferFromBuffer(Hyprutils::Memory::CSharedPointer<IBuffer> buffer);
void sendFrameAndSetCallback();
void onFrameDone();
// frame loop
bool frameScheduledWhileWaiting = false;
bool readyForFrameCallback = false; // true after attaching a buffer
bool frameScheduled = false;
struct {
std::vector<std::pair<Hyprutils::Memory::CWeakPointer<IBuffer>, Hyprutils::Memory::CSharedPointer<CWaylandBuffer>>> buffers;
@ -123,9 +131,10 @@ namespace Aquamarine {
//
Hyprutils::Memory::CWeakPointer<CBackend> backend;
std::vector<Hyprutils::Memory::CSharedPointer<CWaylandOutput>> outputs, scheduledFrames;
std::vector<Hyprutils::Memory::CSharedPointer<CWaylandOutput>> outputs;
std::vector<Hyprutils::Memory::CSharedPointer<CWaylandKeyboard>> keyboards;
std::vector<Hyprutils::Memory::CSharedPointer<CWaylandPointer>> pointers;
std::vector<FIdleCallback> idleCallbacks;
// pointer focus
Hyprutils::Memory::CWeakPointer<CWaylandOutput> focusedOutput;

View file

@ -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;
};
}

View file

@ -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);

View file

@ -103,6 +103,7 @@ bool Aquamarine::CBackend::start() {
if (!allocator)
return false;
ready = true;
for (auto& b : implementations) {
b->onReady();
}

View file

@ -88,7 +88,7 @@ int Aquamarine::CWaylandBackend::drmFD() {
void Aquamarine::CWaylandBackend::createOutput(const std::string& szName) {
auto o = outputs.emplace_back(SP<CWaylandOutput>(new CWaylandOutput(szName, self)));
o->self = o;
backend->events.newOutput.emit(SP<IOutput>(o));
idleCallbacks.emplace_back([this, o]() { backend->events.newOutput.emit(SP<IOutput>(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<CCWlPointer> 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<CCWlPointer> 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<CWaylandKeyboard>(makeShared<CCWlKeyboard>(waylandState.seat->sendGetKeyboard()), self));
backend->events.newKeyboard.emit(SP<IKeyboard>(k));
idleCallbacks.emplace_back([this, k]() { backend->events.newKeyboard.emit(SP<IKeyboard>(k)); });
} else if (!HAS_KEYBOARD && !keyboards.empty())
keyboards.clear();
if (HAS_POINTER && pointers.empty()) {
auto p = pointers.emplace_back(makeShared<CWaylandPointer>(makeShared<CCWlPointer>(waylandState.seat->sendGetPointer()), self));
backend->events.newPointer.emit(SP<IPointer>(p));
idleCallbacks.emplace_back([this, p]() { backend->events.newPointer.emit(SP<IPointer>(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<CWaylandBuffer> Aquamarine::CWaylandOutput::wlBufferFromBuffer(SP<IBuffer> bu
void Aquamarine::CWaylandOutput::sendFrameAndSetCallback() {
events.frame.emit();
if (waylandState.frameCallback)
frameScheduled = false;
if (waylandState.frameCallback || !readyForFrameCallback)
return;
waylandState.frameCallback = makeShared<CCWlCallback>(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<IBuffer> 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<IBuffer> buffer_, Hyprutils::Memory::CWeakPointer<CWaylandBackend> backend_) : buffer(buffer_), backend(backend_) {