feat(wayland): touch, with the first finger standing in for the pointer
The seat's wl_touch was never bound, so a touchscreen could not drive a window at all. Every finger is now reported through onTouchDown, onTouchMove, onTouchUp and onTouchCancel (TouchPoint: the compositor's id and the position in physical pixels). The first finger down also enters the window — Device::focusedWindow and the pointer serial the clipboard needs — presses the left button, moves it and releases it when it lifts, so an application written for a pointer works on a phone as it is.
This commit is contained in:
parent
b16f1e99d5
commit
aed6142cce
5 changed files with 104 additions and 0 deletions
|
|
@ -546,12 +546,82 @@ void Device::TickKeyRepeats() {
|
|||
}
|
||||
}
|
||||
|
||||
// The first finger stands in for the pointer: it enters the window (so the
|
||||
// clipboard has a serial and Device::focusedWindow a window), presses the
|
||||
// left button, moves it and releases it. Every finger is also reported as
|
||||
// such, in physical pixels.
|
||||
void Device::touch_down(void*, wl_touch*, std::uint32_t serial, std::uint32_t, wl_surface* surface, std::int32_t id, wl_fixed_t x, wl_fixed_t y) {
|
||||
Window* window = nullptr;
|
||||
for (Window* candidate : windows) {
|
||||
if (candidate->surface == surface) window = candidate;
|
||||
}
|
||||
if (window == nullptr) return;
|
||||
touchWindow = window;
|
||||
window->lastPointerSerial_ = serial;
|
||||
const Vector<float, 2> pos = Vector<float, 2>(wl_fixed_to_double(x), wl_fixed_to_double(y)) * window->scale;
|
||||
touchPositions[id] = { pos.x, pos.y };
|
||||
window->onTouchDown.Invoke({ id, pos });
|
||||
if (window->primaryTouchId < 0) {
|
||||
window->primaryTouchId = id;
|
||||
focusedWindow = window;
|
||||
window->currentMousePos = pos;
|
||||
window->mouseLeftHeld = true;
|
||||
window->onMouseLeftClick.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
void Device::touch_up(void*, wl_touch*, std::uint32_t, std::uint32_t, std::int32_t id) {
|
||||
if (touchWindow == nullptr) return;
|
||||
Window* window = touchWindow;
|
||||
const auto at = touchPositions.find(id);
|
||||
const Vector<float, 2> pos = at == touchPositions.end() ? window->currentMousePos : Vector<float, 2>(at->second.first, at->second.second);
|
||||
touchPositions.erase(id);
|
||||
window->onTouchUp.Invoke({ id, pos });
|
||||
if (id == window->primaryTouchId) {
|
||||
window->primaryTouchId = -1;
|
||||
window->mouseLeftHeld = false;
|
||||
window->onMouseLeftRelease.Invoke();
|
||||
}
|
||||
if (touchPositions.empty()) touchWindow = nullptr;
|
||||
}
|
||||
|
||||
void Device::touch_motion(void*, wl_touch*, std::uint32_t, std::int32_t id, wl_fixed_t x, wl_fixed_t y) {
|
||||
if (touchWindow == nullptr) return;
|
||||
Window* window = touchWindow;
|
||||
const Vector<float, 2> pos = Vector<float, 2>(wl_fixed_to_double(x), wl_fixed_to_double(y)) * window->scale;
|
||||
touchPositions[id] = { pos.x, pos.y };
|
||||
window->onTouchMove.Invoke({ id, pos });
|
||||
if (id == window->primaryTouchId) {
|
||||
window->currentMousePos = pos;
|
||||
window->onMouseMove.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
void Device::touch_frame(void*, wl_touch*) {}
|
||||
|
||||
void Device::touch_cancel(void*, wl_touch*) {
|
||||
if (touchWindow == nullptr) return;
|
||||
Window* window = touchWindow;
|
||||
touchPositions.clear();
|
||||
touchWindow = nullptr;
|
||||
if (window->primaryTouchId >= 0) {
|
||||
window->primaryTouchId = -1;
|
||||
window->mouseLeftHeld = false;
|
||||
window->onMouseLeftRelease.Invoke();
|
||||
}
|
||||
window->onTouchCancel.Invoke();
|
||||
}
|
||||
|
||||
void Device::seat_handle_capabilities(void* data, wl_seat* seat, uint32_t capabilities) {
|
||||
seat = seat;
|
||||
if (capabilities & WL_SEAT_CAPABILITY_POINTER) {
|
||||
wl_pointer* pointer = wl_seat_get_pointer(seat);
|
||||
wl_pointer_add_listener(pointer, &pointer_listener, nullptr);
|
||||
}
|
||||
if ((capabilities & WL_SEAT_CAPABILITY_TOUCH) && wlTouch == nullptr) {
|
||||
wlTouch = wl_seat_get_touch(seat);
|
||||
wl_touch_add_listener(wlTouch, &touch_listener, nullptr);
|
||||
}
|
||||
if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) {
|
||||
wl_keyboard* keyboard = wl_seat_get_keyboard(seat);
|
||||
wl_keyboard_add_listener(keyboard, &keyboard_listener, nullptr);
|
||||
|
|
|
|||
|
|
@ -557,6 +557,10 @@ Window::~Window() {
|
|||
std::erase(Device::windows, this);
|
||||
if (Device::focusedWindow == this) Device::focusedWindow = nullptr;
|
||||
if (Device::keyboardWindow == this) Device::keyboardWindow = nullptr;
|
||||
if (Device::touchWindow == this) {
|
||||
Device::touchWindow = nullptr;
|
||||
Device::touchPositions.clear();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in a new issue