summaryrefslogtreecommitdiff
path: root/src/protocols/core/Seat.cpp
diff options
context:
space:
mode:
authorVaxry <vaxry@vaxry.net>2024-06-17 16:07:32 +0200
committerVaxry <vaxry@vaxry.net>2024-06-17 16:07:32 +0200
commit785d0628876a4782759b13c25fa644c12f340356 (patch)
tree5f0cdb824763ad7c035d2b23fe0b58e15a090450 /src/protocols/core/Seat.cpp
parent1360677478e867034713e5d43d7a8a8f6bf1343d (diff)
seat: track pressed pointer buttons
releases them on leave, unless there is a dnd going on
Diffstat (limited to 'src/protocols/core/Seat.cpp')
-rw-r--r--src/protocols/core/Seat.cpp26
1 files changed, 26 insertions, 0 deletions
diff --git a/src/protocols/core/Seat.cpp b/src/protocols/core/Seat.cpp
index be05955c..f578292a 100644
--- a/src/protocols/core/Seat.cpp
+++ b/src/protocols/core/Seat.cpp
@@ -1,5 +1,6 @@
#include "Seat.hpp"
#include "Compositor.hpp"
+#include "DataDevice.hpp"
#include "../../devices/IKeyboard.hpp"
#include "../../managers/SeatManager.hpp"
#include "../../config/ConfigValue.hpp"
@@ -128,6 +129,18 @@ void CWLPointerResource::sendLeave() {
if (!owner || !currentSurface)
return;
+ // release all buttons unless we have a dnd going on in which case
+ // the events shall be lost.
+ if (!PROTO::data->dndActive()) {
+ timespec now;
+ clock_gettime(CLOCK_MONOTONIC, &now);
+ for (auto& b : pressedButtons) {
+ sendButton(now.tv_sec * 1000 + now.tv_nsec / 1000000, b, WL_POINTER_BUTTON_STATE_RELEASED);
+ }
+ }
+
+ pressedButtons.clear();
+
resource->sendLeave(g_pSeatManager->nextSerial(owner.lock()), currentSurface->getResource().get());
currentSurface.reset();
listeners.destroySurface.reset();
@@ -144,6 +157,19 @@ void CWLPointerResource::sendButton(uint32_t timeMs, uint32_t button, wl_pointer
if (!owner || !currentSurface)
return;
+ if (state == WL_POINTER_BUTTON_STATE_RELEASED && std::find(pressedButtons.begin(), pressedButtons.end(), button) == pressedButtons.end()) {
+ LOGM(ERR, "sendButton release on a non-pressed button");
+ return;
+ } else if (state == WL_POINTER_BUTTON_STATE_PRESSED && std::find(pressedButtons.begin(), pressedButtons.end(), button) != pressedButtons.end()) {
+ LOGM(ERR, "sendButton press on a non-pressed button");
+ return;
+ }
+
+ if (state == WL_POINTER_BUTTON_STATE_RELEASED)
+ std::erase(pressedButtons, button);
+ else if (state == WL_POINTER_BUTTON_STATE_PRESSED)
+ pressedButtons.emplace_back(button);
+
resource->sendButton(g_pSeatManager->nextSerial(owner.lock()), timeMs, button, state);
}