mirror of https://github.com/godotengine/godot
Merge 42301f3d9b into 1ea6b0ccff
This commit is contained in:
commit
c49ff3e47f
|
|
@ -1588,8 +1588,21 @@ void WaylandThread::_wl_seat_on_capabilities(void *data, struct wl_seat *wl_seat
|
|||
|
||||
ERR_FAIL_NULL(ss);
|
||||
|
||||
// TODO: Handle touch.
|
||||
// Touch handling.
|
||||
if (capabilities & WL_SEAT_CAPABILITY_TOUCH) {
|
||||
if (!ss->wl_touch) {
|
||||
ss->cursor_surface = wl_compositor_create_surface(ss->registry->wl_compositor);
|
||||
wl_surface_commit(ss->cursor_surface);
|
||||
|
||||
ss->wl_touch = wl_seat_get_touch(wl_seat);
|
||||
wl_touch_add_listener(ss->wl_touch, &wl_touch_listener, ss);
|
||||
}
|
||||
} else {
|
||||
if (ss->wl_touch) {
|
||||
wl_touch_destroy(ss->wl_touch);
|
||||
ss->wl_touch = nullptr;
|
||||
}
|
||||
}
|
||||
// Pointer handling.
|
||||
if (capabilities & WL_SEAT_CAPABILITY_POINTER) {
|
||||
if (!ss->wl_pointer) {
|
||||
|
|
@ -1713,6 +1726,262 @@ void WaylandThread::_cursor_frame_callback_on_done(void *data, struct wl_callbac
|
|||
seat_state_update_cursor(ss);
|
||||
}
|
||||
|
||||
void WaylandThread::_wl_touch_on_down(void *data, struct wl_touch *wl_touch,
|
||||
uint32_t serial, uint32_t time, struct wl_surface *surface,
|
||||
int32_t id, wl_fixed_t x, wl_fixed_t y) {
|
||||
WindowState *ws = wl_surface_get_window_state(surface);
|
||||
if (!ws) {
|
||||
return;
|
||||
}
|
||||
|
||||
SeatState *ss = (SeatState *)data;
|
||||
ERR_FAIL_NULL(ss);
|
||||
|
||||
PointerData &pd = ss->pointer_data_buffer;
|
||||
|
||||
double scale = window_state_get_scale_factor(ws);
|
||||
Vector2 position = Vector2(wl_fixed_to_double(x), wl_fixed_to_double(y));
|
||||
|
||||
TouchData &bf = ss->touch_data_buffer;
|
||||
TouchPoint &td = bf.touchs[id];
|
||||
|
||||
td.relative = Vector2();
|
||||
td.position = position;
|
||||
td.time = time;
|
||||
td.double_tap = false;
|
||||
td.canceled = false;
|
||||
|
||||
if ((td.time - td.last_time) < 400 && (td.position * scale).distance_to(td.last_position * scale) < 5) {
|
||||
td.double_tap = true;
|
||||
}
|
||||
|
||||
td.last_position = position;
|
||||
td.last_time = time;
|
||||
td.pressed = true;
|
||||
td.is_activing = true;
|
||||
bf.touched_id = pd.pointed_id;
|
||||
bf.last_touched_id = pd.last_pointed_id;
|
||||
|
||||
DEBUG_LOG_WAYLAND_THREAD(vformat("Touch down in window %d, id: %d", ws->id, id));
|
||||
|
||||
if (wl_touch_get_version(wl_touch) < WL_TOUCH_FRAME_SINCE_VERSION) {
|
||||
_wl_touch_on_frame(data, wl_touch);
|
||||
}
|
||||
}
|
||||
|
||||
void WaylandThread::_wl_touch_on_up(void *data, struct wl_touch *wl_touch,
|
||||
uint32_t serial, uint32_t time, int32_t id) {
|
||||
SeatState *ss = (SeatState *)data;
|
||||
ERR_FAIL_NULL(ss);
|
||||
|
||||
TouchData &bf = ss->touch_data_buffer;
|
||||
|
||||
if (!bf.touchs.has(id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
WaylandThread *wayland_thread = ss->wayland_thread;
|
||||
ERR_FAIL_NULL(wayland_thread);
|
||||
WindowState *ws = nullptr;
|
||||
|
||||
if (bf.touched_id != DisplayServer::INVALID_WINDOW_ID) {
|
||||
ws = wayland_thread->window_get_state(bf.touched_id);
|
||||
ERR_FAIL_NULL(ws);
|
||||
}
|
||||
|
||||
if (ws == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
TouchPoint &td = bf.touchs[id];
|
||||
|
||||
td.relative = Vector2();
|
||||
td.pressed = false;
|
||||
td.is_activing = true;
|
||||
td.time = time;
|
||||
td.last_time = time;
|
||||
|
||||
DEBUG_LOG_WAYLAND_THREAD(vformat("Touch up in window %d, id: %d", ws->id, id));
|
||||
|
||||
if (wl_touch_get_version(wl_touch) < WL_TOUCH_FRAME_SINCE_VERSION) {
|
||||
_wl_touch_on_frame(data, wl_touch);
|
||||
}
|
||||
}
|
||||
|
||||
void WaylandThread::_wl_touch_on_motion(void *data, struct wl_touch *wl_touch,
|
||||
uint32_t time, int32_t id, wl_fixed_t x_w, wl_fixed_t y_w) {
|
||||
SeatState *ss = (SeatState *)data;
|
||||
ERR_FAIL_NULL(ss);
|
||||
|
||||
TouchData &bf = ss->touch_data_buffer;
|
||||
|
||||
if (!bf.touchs.has(id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
WaylandThread *wayland_thread = ss->wayland_thread;
|
||||
ERR_FAIL_NULL(wayland_thread);
|
||||
|
||||
TouchPoint &td = bf.touchs[id];
|
||||
|
||||
Vector2 position = Vector2(wl_fixed_to_double(x_w), wl_fixed_to_double(y_w));
|
||||
|
||||
WindowState *ws = nullptr;
|
||||
|
||||
if (bf.touched_id != DisplayServer::INVALID_WINDOW_ID) {
|
||||
ws = wayland_thread->window_get_state(bf.touched_id);
|
||||
ERR_FAIL_NULL(ws);
|
||||
}
|
||||
|
||||
if (ws == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
td.position = position;
|
||||
td.time = time;
|
||||
td.index = id;
|
||||
td.pressed = true;
|
||||
td.is_activing = true;
|
||||
|
||||
if (td.time != td.last_time) {
|
||||
td.relative = Vector2(td.position - td.last_position);
|
||||
}
|
||||
td.last_time = time;
|
||||
td.last_position = position;
|
||||
|
||||
DEBUG_LOG_WAYLAND_THREAD(vformat("Touch motion in window %d, id: %d", ws->id, id));
|
||||
|
||||
if (wl_touch_get_version(wl_touch) < WL_TOUCH_FRAME_SINCE_VERSION) {
|
||||
_wl_touch_on_frame(data, wl_touch);
|
||||
}
|
||||
}
|
||||
|
||||
void WaylandThread::_wl_touch_on_frame(void *data, struct wl_touch *wl_touch) {
|
||||
SeatState *ss = (SeatState *)data;
|
||||
ERR_FAIL_NULL(ss);
|
||||
|
||||
WaylandThread *wayland_thread = ss->wayland_thread;
|
||||
ERR_FAIL_NULL(wayland_thread);
|
||||
|
||||
TouchData &bf = ss->touch_data_buffer;
|
||||
|
||||
if (bf.touched_id != bf.last_touched_id) {
|
||||
if (bf.last_touched_id != DisplayServer::INVALID_WINDOW_ID) {
|
||||
Ref<WindowEventMessage> msg;
|
||||
msg.instantiate();
|
||||
msg->id = bf.last_touched_id;
|
||||
msg->event = DisplayServer::WINDOW_EVENT_MOUSE_EXIT;
|
||||
|
||||
wayland_thread->push_message(msg);
|
||||
}
|
||||
|
||||
if (bf.touched_id != DisplayServer::INVALID_WINDOW_ID) {
|
||||
Ref<WindowEventMessage> msg;
|
||||
msg.instantiate();
|
||||
msg->id = bf.touched_id;
|
||||
msg->event = DisplayServer::WINDOW_EVENT_MOUSE_ENTER;
|
||||
|
||||
wayland_thread->push_message(msg);
|
||||
}
|
||||
}
|
||||
|
||||
WindowState *ws = nullptr;
|
||||
|
||||
if (bf.touched_id != DisplayServer::INVALID_WINDOW_ID) {
|
||||
ws = ss->wayland_thread->window_get_state(bf.touched_id);
|
||||
ERR_FAIL_NULL(ws);
|
||||
} else if (bf.last_touched_id != DisplayServer::INVALID_WINDOW_ID) {
|
||||
ws = ss->wayland_thread->window_get_state(bf.last_touched_id);
|
||||
ERR_FAIL_NULL(ws);
|
||||
}
|
||||
|
||||
if (ws == nullptr) {
|
||||
bf.last_touched_id = bf.touched_id;
|
||||
return;
|
||||
}
|
||||
|
||||
double scale = window_state_get_scale_factor(ws);
|
||||
for (KeyValue<int32_t, TouchPoint> &pair : bf.touchs) {
|
||||
TouchPoint &td = pair.value;
|
||||
if (!td.is_activing) {
|
||||
continue;
|
||||
}
|
||||
td.is_activing = false;
|
||||
if (td.relative != Vector2()) {
|
||||
Ref<InputEventScreenDrag> ev;
|
||||
ev.instantiate();
|
||||
|
||||
ev->set_window_id(bf.touched_id);
|
||||
ev->set_position(td.position * scale);
|
||||
uint32_t time_delta = td.time - td.last_time;
|
||||
|
||||
ev->set_relative(td.relative * scale);
|
||||
ev->set_relative_screen_position(td.relative);
|
||||
ev->set_velocity(td.relative * scale / time_delta);
|
||||
ev->set_screen_velocity(td.relative / time_delta);
|
||||
|
||||
ev->set_index(td.index);
|
||||
|
||||
Ref<InputEventMessage> msg;
|
||||
msg.instantiate();
|
||||
msg->event = ev;
|
||||
wayland_thread->push_message(msg);
|
||||
} else {
|
||||
Ref<InputEventScreenTouch> ev;
|
||||
ev.instantiate();
|
||||
|
||||
ev->set_window_id(bf.touched_id);
|
||||
ev->set_pressed(td.pressed);
|
||||
ev->set_position(td.position * scale);
|
||||
ev->set_index(td.index);
|
||||
ev->set_double_tap(td.double_tap);
|
||||
td.double_tap = false;
|
||||
|
||||
Ref<InputEventMessage> msg;
|
||||
msg.instantiate();
|
||||
msg->event = ev;
|
||||
wayland_thread->push_message(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WaylandThread::_wl_touch_on_cancel(void *data, struct wl_touch *wl_touch) {
|
||||
SeatState *ss = (SeatState *)data;
|
||||
ERR_FAIL_NULL(ss);
|
||||
|
||||
WaylandThread *wayland_thread = ss->wayland_thread;
|
||||
ERR_FAIL_NULL(wayland_thread);
|
||||
|
||||
TouchData &bf = ss->touch_data_buffer;
|
||||
|
||||
for (KeyValue<int32_t, TouchPoint> &pair : bf.touchs) {
|
||||
TouchPoint &td = pair.value;
|
||||
if (td.is_activing == true) {
|
||||
td.canceled = true;
|
||||
td.is_activing = false;
|
||||
Ref<InputEventScreenTouch> ev;
|
||||
ev.instantiate();
|
||||
ev->set_pressed(false);
|
||||
ev->set_position(td.position);
|
||||
ev->set_index(td.index);
|
||||
ev->set_double_tap(td.double_tap);
|
||||
ev->set_canceled(td.canceled);
|
||||
ev->set_window_id(bf.touched_id);
|
||||
|
||||
Ref<InputEventMessage> msg;
|
||||
msg.instantiate();
|
||||
msg->event = ev;
|
||||
wayland_thread->push_message(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WaylandThread::_wl_touch_on_shape(void *data, struct wl_touch *wl_touch, int32_t id, wl_fixed_t major, wl_fixed_t minor) {
|
||||
}
|
||||
|
||||
void WaylandThread::_wl_touch_on_orientation(void *data, struct wl_touch *wl_touch, int32_t id, wl_fixed_t orientation) {
|
||||
}
|
||||
|
||||
void WaylandThread::_wl_pointer_on_enter(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y) {
|
||||
WindowState *ws = wl_surface_get_window_state(surface);
|
||||
if (!ws) {
|
||||
|
|
@ -3453,8 +3722,8 @@ void WaylandThread::window_state_update_size(WindowState *p_ws, int p_width, int
|
|||
bool using_fractional = p_ws->preferred_fractional_scale > 0;
|
||||
|
||||
// If neither is true we no-op.
|
||||
bool scale_changed = false;
|
||||
bool size_changed = false;
|
||||
bool scale_changed = true;
|
||||
bool size_changed = true;
|
||||
|
||||
if (p_ws->rect.size.width != p_width || p_ws->rect.size.height != p_height) {
|
||||
p_ws->rect.size.width = p_width;
|
||||
|
|
|
|||
|
|
@ -353,6 +353,28 @@ public:
|
|||
CONFINED,
|
||||
};
|
||||
|
||||
struct TouchPoint {
|
||||
Point2 position;
|
||||
Point2 last_position;
|
||||
|
||||
Vector2 relative;
|
||||
uint32_t index = 0;
|
||||
|
||||
uint32_t time = 0;
|
||||
uint32_t last_time = 0;
|
||||
|
||||
bool pressed = false;
|
||||
bool canceled = false;
|
||||
bool double_tap = false;
|
||||
bool is_activing = false;
|
||||
};
|
||||
|
||||
struct TouchData {
|
||||
AHashMap<int32_t, TouchPoint> touchs;
|
||||
DisplayServer::WindowID touched_id = DisplayServer::INVALID_WINDOW_ID;
|
||||
DisplayServer::WindowID last_touched_id = DisplayServer::INVALID_WINDOW_ID;
|
||||
};
|
||||
|
||||
struct PointerData {
|
||||
Point2 position;
|
||||
uint32_t motion_time = 0;
|
||||
|
|
@ -427,6 +449,10 @@ public:
|
|||
struct wl_seat *wl_seat = nullptr;
|
||||
uint32_t wl_seat_name = 0;
|
||||
|
||||
// Touch.
|
||||
struct wl_touch *wl_touch = nullptr;
|
||||
TouchData touch_data_buffer;
|
||||
|
||||
// Pointer.
|
||||
struct wl_pointer *wl_pointer = nullptr;
|
||||
|
||||
|
|
@ -671,6 +697,14 @@ private:
|
|||
|
||||
static void _cursor_frame_callback_on_done(void *data, struct wl_callback *wl_callback, uint32_t time_ms);
|
||||
|
||||
static void _wl_touch_on_down(void *data, struct wl_touch *wl_touch, uint32_t serial, uint32_t time, struct wl_surface *surface, int32_t id, wl_fixed_t x, wl_fixed_t y);
|
||||
static void _wl_touch_on_up(void *data, struct wl_touch *wl_touch, uint32_t serial, uint32_t time, int32_t id);
|
||||
static void _wl_touch_on_motion(void *data, struct wl_touch *wl_touch, uint32_t time, int32_t id, wl_fixed_t x_w, wl_fixed_t y_w);
|
||||
static void _wl_touch_on_frame(void *data, struct wl_touch *wl_touch);
|
||||
static void _wl_touch_on_cancel(void *data, struct wl_touch *wl_touch);
|
||||
static void _wl_touch_on_shape(void *data, struct wl_touch *wl_touch, int32_t id, wl_fixed_t major, wl_fixed_t minor);
|
||||
static void _wl_touch_on_orientation(void *data, struct wl_touch *wl_touch, int32_t id, wl_fixed_t orientation);
|
||||
|
||||
static void _wl_pointer_on_enter(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y);
|
||||
static void _wl_pointer_on_leave(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface);
|
||||
static void _wl_pointer_on_motion(void *data, struct wl_pointer *wl_pointer, uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y);
|
||||
|
|
@ -821,6 +855,16 @@ private:
|
|||
.done = _cursor_frame_callback_on_done,
|
||||
};
|
||||
|
||||
static constexpr struct wl_touch_listener wl_touch_listener = {
|
||||
.down = _wl_touch_on_down,
|
||||
.up = _wl_touch_on_up,
|
||||
.motion = _wl_touch_on_motion,
|
||||
.frame = _wl_touch_on_frame,
|
||||
.cancel = _wl_touch_on_cancel,
|
||||
.shape = _wl_touch_on_shape,
|
||||
.orientation = _wl_touch_on_orientation,
|
||||
};
|
||||
|
||||
static constexpr struct wl_pointer_listener wl_pointer_listener = {
|
||||
.enter = _wl_pointer_on_enter,
|
||||
.leave = _wl_pointer_on_leave,
|
||||
|
|
|
|||
Loading…
Reference in New Issue