Skip to content

Commit

Permalink
core: improve gesture and touch focus APIs (#2451)
Browse files Browse the repository at this point in the history
This makes the hold action way more useful, and also fixes
double/triple/etc tap gestures.
  • Loading branch information
ammen99 authored Aug 27, 2024
1 parent 4985fa1 commit 80d6bcc
Show file tree
Hide file tree
Showing 9 changed files with 58 additions and 60 deletions.
2 changes: 1 addition & 1 deletion metadata/extra-gestures.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<option name="move_delay" type="int">
<_short>Start moving after</_short>
<_long>Amount of time in milliseconds to hold fingers before starting interactive move of the view.</_long>
<default>500</default>
<default>750</default>
<min>1</min>
<max>10000</max>
</option>
Expand Down
73 changes: 28 additions & 45 deletions plugins/single_plugins/extra-gestures.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ namespace wf
using namespace touch;
class extra_gestures_plugin_t : public per_output_plugin_instance_t
{
std::unique_ptr<gesture_t> touch_and_hold_move;
std::unique_ptr<gesture_t> tap_to_close;
gesture_t touch_and_hold_move;
gesture_t tap_to_close;

wf::option_wrapper_t<int> move_fingers{"extra-gestures/move_fingers"};
wf::option_wrapper_t<int> move_delay{"extra-gestures/move_delay"};
Expand All @@ -33,11 +33,9 @@ class extra_gestures_plugin_t : public per_output_plugin_instance_t
build_touch_and_hold_move();
move_fingers.set_callback([=] () { build_touch_and_hold_move(); });
move_delay.set_callback([=] () { build_touch_and_hold_move(); });
wf::get_core().add_touch_gesture({touch_and_hold_move});

build_tap_to_close();
close_fingers.set_callback([=] () { build_tap_to_close(); });
wf::get_core().add_touch_gesture({tap_to_close});
}

/**
Expand Down Expand Up @@ -71,23 +69,15 @@ class extra_gestures_plugin_t : public per_output_plugin_instance_t

void build_touch_and_hold_move()
{
if (touch_and_hold_move)
{
wf::get_core().rem_touch_gesture({touch_and_hold_move});
}

auto touch_down = std::make_unique<wf::touch_action_t>(move_fingers, true);
touch_down->set_move_tolerance(50);
touch_down->set_duration(100);

auto hold = std::make_unique<wf::hold_action_t>(move_delay);
hold->set_move_tolerance(100);

std::vector<std::unique_ptr<gesture_action_t>> actions;
actions.emplace_back(std::move(touch_down));
actions.emplace_back(std::move(hold));
touch_and_hold_move = std::make_unique<gesture_t>(std::move(actions),
[=] ()
wf::get_core().rem_touch_gesture(&touch_and_hold_move);

touch_and_hold_move = wf::touch::gesture_builder_t()
.action(touch_action_t(move_fingers, true)
.set_move_tolerance(50)
.set_duration(100))
.action(hold_action_t(move_delay)
.set_move_tolerance(100))
.on_completed([=] ()
{
execute_view_action([] (wayfire_view view)
{
Expand All @@ -96,38 +86,31 @@ class extra_gestures_plugin_t : public per_output_plugin_instance_t
wf::get_core().default_wm->move_request(toplevel);
}
});
});
}).build();

wf::get_core().add_touch_gesture(&touch_and_hold_move);
}

void build_tap_to_close()
{
if (tap_to_close)
{
wf::get_core().rem_touch_gesture({tap_to_close});
}

auto touch_down = std::make_unique<wf::touch_action_t>(close_fingers, true);
touch_down->set_move_tolerance(50);
touch_down->set_duration(150);

auto touch_up = std::make_unique<wf::touch_action_t>(close_fingers, false);
touch_up->set_move_tolerance(50);
touch_up->set_duration(150);

std::vector<std::unique_ptr<gesture_action_t>> actions;
actions.emplace_back(std::move(touch_down));
actions.emplace_back(std::move(touch_up));
tap_to_close = std::make_unique<gesture_t>(std::move(actions),
[=] ()
{
execute_view_action([] (wayfire_view view) { view->close(); });
});
wf::get_core().rem_touch_gesture(&tap_to_close);

tap_to_close = wf::touch::gesture_builder_t()
.action(touch_action_t(close_fingers, true)
.set_move_tolerance(50)
.set_duration(150))
.action(touch_action_t(close_fingers, false)
.set_move_tolerance(50)
.set_duration(150))
.on_completed([=] () { execute_view_action([] (wayfire_view view) { view->close(); }); })
.build();
wf::get_core().add_touch_gesture(&tap_to_close);
}

void fini() override
{
wf::get_core().rem_touch_gesture({touch_and_hold_move});
wf::get_core().rem_touch_gesture({tap_to_close});
wf::get_core().rem_touch_gesture(&touch_and_hold_move);
wf::get_core().rem_touch_gesture(&tap_to_close);
}
};
}
Expand Down
2 changes: 1 addition & 1 deletion src/api/wayfire/core.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ class compositor_core_t : public wf::object_base_t, public signal::provider_t
/**
* @return The surface which has touch focus, or null if none.
*/
virtual wf::scene::node_ptr get_touch_focus() = 0;
virtual wf::scene::node_ptr get_touch_focus(int finger_id = 0) = 0;

/** @return The view whose surface is cursor focus */
wayfire_view get_cursor_focus_view();
Expand Down
2 changes: 1 addition & 1 deletion src/api/wayfire/plugin.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ class plugin_interface_t
using wayfire_plugin_load_func = wf::plugin_interface_t * (*)();

/** The version of Wayfire's API/ABI */
constexpr uint32_t WAYFIRE_API_ABI_VERSION = 2024'06'19;
constexpr uint32_t WAYFIRE_API_ABI_VERSION = 2024'08'26;

/**
* Each plugin must also provide a function which returns the Wayfire API/ABI
Expand Down
2 changes: 1 addition & 1 deletion src/core/core-impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class compositor_core_impl_t : public compositor_core_t
const wf::touch::gesture_state_t& get_touch_state() override;

wf::scene::node_ptr get_cursor_focus() override;
wf::scene::node_ptr get_touch_focus() override;
wf::scene::node_ptr get_touch_focus(int finger_id) override;

void add_touch_gesture(
nonstd::observer_ptr<wf::touch::gesture_t> gesture) override;
Expand Down
4 changes: 2 additions & 2 deletions src/core/core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -388,9 +388,9 @@ wayfire_view wf::compositor_core_t::get_view_at(wf::pointf_t point)
return isec ? node_to_view(isec->node->shared_from_this()) : nullptr;
}

wf::scene::node_ptr wf::compositor_core_impl_t::get_touch_focus()
wf::scene::node_ptr wf::compositor_core_impl_t::get_touch_focus(int finger_id)
{
return seat->priv->touch->get_focus();
return seat->priv->touch->get_focus(finger_id);
}

wayfire_view wf::compositor_core_t::get_touch_focus_view()
Expand Down
30 changes: 23 additions & 7 deletions src/core/seat/touch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,21 @@
#include "wayfire/util.hpp"
#include "wayfire/output-layout.hpp"

class touch_timer_adapter_t : public wf::touch::timer_interface_t
{
public:
wf::wl_timer<false> timer;
void set_timeout(uint32_t msec, std::function<void()> handler)
{
timer.set_timeout(msec, handler);
}

void reset()
{
timer.disconnect();
}
};

wf::touch_interface_t::touch_interface_t(wlr_cursor *cursor, wlr_seat *seat,
input_surface_selector_t surface_at)
{
Expand Down Expand Up @@ -129,6 +144,7 @@ wf::scene::node_ptr wf::touch_interface_t::get_focus(int finger_id) const
void wf::touch_interface_t::add_touch_gesture(
nonstd::observer_ptr<touch::gesture_t> gesture)
{
gesture->set_timer(std::make_unique<touch_timer_adapter_t>());
this->gestures.emplace_back(gesture);
}

Expand Down Expand Up @@ -322,14 +338,15 @@ class multi_action_t : public gesture_action_t
bool pinch;
double threshold;
bool last_pinch_was_pinch_in = false;
double move_tolerance = 1e9;

uint32_t target_direction = 0;
int32_t cnt_fingers = 0;

action_status_t update_state(const gesture_state_t& state,
const gesture_event_t& event) override
{
if (event.time - this->start_time > this->get_duration())
if (event.type == wf::touch::EVENT_TYPE_TIMEOUT)
{
return wf::touch::ACTION_STATUS_CANCELLED;
}
Expand All @@ -355,7 +372,7 @@ class multi_action_t : public gesture_action_t

if (this->pinch)
{
if (glm::length(state.get_center().delta()) >= get_move_tolerance())
if (glm::length(state.get_center().delta()) >= move_tolerance)
{
return ACTION_STATUS_CANCELLED;
}
Expand Down Expand Up @@ -384,8 +401,7 @@ class multi_action_t : public gesture_action_t

for (auto& finger : state.fingers)
{
if (finger.second.get_incorrect_drag_distance(this->target_direction) >
this->get_move_tolerance())
if (finger.second.get_incorrect_drag_distance(this->target_direction) > this->move_tolerance)
{
return ACTION_STATUS_CANCELLED;
}
Expand Down Expand Up @@ -471,19 +487,19 @@ void wf::touch_interface_t::add_default_gestures()
auto swipe = std::make_unique<multi_action_t>(false,
0.75 * MAX_SWIPE_DISTANCE / sensitivity);
swipe->set_duration(GESTURE_BASE_DURATION * sensitivity);
swipe->set_move_tolerance(SWIPE_INCORRECT_DRAG_TOLERANCE * sensitivity);
swipe->move_tolerance = SWIPE_INCORRECT_DRAG_TOLERANCE * sensitivity;

const double pinch_thresh = 1.0 + (PINCH_THRESHOLD - 1.0) / sensitivity;
auto pinch = std::make_unique<multi_action_t>(true, pinch_thresh);
pinch->set_duration(GESTURE_BASE_DURATION * 1.5 * sensitivity);
pinch->set_move_tolerance(PINCH_INCORRECT_DRAG_TOLERANCE * sensitivity);
pinch->move_tolerance = PINCH_INCORRECT_DRAG_TOLERANCE * sensitivity;

// Edge swipe needs a quick release to be considered edge swipe
auto edge_swipe = std::make_unique<multi_action_t>(false,
MAX_SWIPE_DISTANCE / sensitivity);
auto edge_release = std::make_unique<wf::touch::touch_action_t>(1, false);
edge_swipe->set_duration(GESTURE_BASE_DURATION * sensitivity);
edge_swipe->set_move_tolerance(SWIPE_INCORRECT_DRAG_TOLERANCE * sensitivity);
edge_swipe->move_tolerance = SWIPE_INCORRECT_DRAG_TOLERANCE * sensitivity;
// The release action needs longer duration to handle the case where the
// gesture is actually longer than the max distance.
edge_release->set_duration(GESTURE_BASE_DURATION * 1.5 * sensitivity);
Expand Down
1 change: 0 additions & 1 deletion src/core/seat/touch.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#include <wayfire/touch/touch.hpp>
#include "wayfire/scene-input.hpp"
#include "wayfire/util.hpp"
#include "wayfire/view.hpp"
#include <wayfire/signal-definitions.hpp>

// TODO: tests
Expand Down
2 changes: 1 addition & 1 deletion subprojects/wf-touch

0 comments on commit 80d6bcc

Please sign in to comment.