-
-
Notifications
You must be signed in to change notification settings - Fork 46
/
Copy pathkeystroke_repeater.cpp
136 lines (109 loc) · 4.14 KB
/
keystroke_repeater.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#include "keystroke_repeater.hpp"
#include <chrono>
#include <mutex>
#include <random>
#include "interval_timer.hpp"
namespace
{
using namespace std::chrono ;
inline auto uniform_accelerate(float velocity, float ms) noexcept {
//hardcoded
constexpr auto MAX_ACCELERATION = 1.0f ;
constexpr auto MAX_VELOCITY = 1.0f ;
//ms -> s
auto t = ms / 1000 ;
auto delta_v = MAX_ACCELERATION * t ;
if(velocity + delta_v < MAX_VELOCITY) {
return velocity + delta_v ;
}
else {
return MAX_VELOCITY ;
}
}
inline auto compute_delta_t(const system_clock::time_point& start_time) noexcept {
return duration_cast<milliseconds>(system_clock::now() - start_time) ;
}
inline auto generate_uniform() {
static std::random_device seed_gen ;
static std::default_random_engine engine(seed_gen()) ;
static std::uniform_real_distribution<float> dist(0.0f, 1.0f) ;
return dist(engine) ;
}
//hardcoded
//constexpr auto WAIT_TIME_FOR_STARTING = 512ms;
constexpr auto REPEAT_SAMPLING_DELTA_US = 25'600 ;
constexpr auto INITIAL_VELOCITY = 0.000'1f ;
}
namespace vind
{
namespace util
{
struct KeyStrokeRepeater::Impl {
IntervalTimer timer_ ;
float v_ ;
system_clock::time_point start_time_ ;
milliseconds wait_time_ ;
std::mutex mtx_ ;
explicit Impl(int wait_time_for_starting_ms=512)
: timer_(REPEAT_SAMPLING_DELTA_US),
v_(INITIAL_VELOCITY),
start_time_(system_clock::now()),
wait_time_(wait_time_for_starting_ms),
mtx_()
{}
virtual ~Impl() noexcept = default ;
Impl(const Impl& rhs)
: timer_(rhs.timer_),
v_(rhs.v_),
start_time_(rhs.start_time_),
wait_time_(rhs.wait_time_),
mtx_()
{}
Impl& operator=(const Impl& rhs)
{
timer_ = rhs.timer_ ;
v_ = rhs.v_ ;
start_time_ = rhs.start_time_ ;
wait_time_ = rhs.wait_time_ ;
return *this ;
}
Impl(Impl&& rhs) = default ;
Impl& operator=(Impl&& rhs) = default ;
} ;
KeyStrokeRepeater::KeyStrokeRepeater(int wait_time_for_starting_ms)
: pimpl(std::make_unique<Impl>(wait_time_for_starting_ms))
{}
KeyStrokeRepeater::~KeyStrokeRepeater() noexcept = default ;
KeyStrokeRepeater::KeyStrokeRepeater(KeyStrokeRepeater&&) = default ;
KeyStrokeRepeater& KeyStrokeRepeater::operator=(KeyStrokeRepeater&&) = default ;
KeyStrokeRepeater::KeyStrokeRepeater(const KeyStrokeRepeater& rhs)
: pimpl(rhs.pimpl ? std::make_unique<Impl>(*(rhs.pimpl)) : std::make_unique<Impl>())
{}
KeyStrokeRepeater& KeyStrokeRepeater::operator=(const KeyStrokeRepeater& rhs) {
if(rhs.pimpl) *pimpl = *(rhs.pimpl) ;
return *this ;
}
void KeyStrokeRepeater::set_wait_time(int delta_ms) {
pimpl->wait_time_ = static_cast<milliseconds>(delta_ms) ;
}
int KeyStrokeRepeater::get_wait_time_ms() const noexcept {
return static_cast<int>(duration_cast<milliseconds>(pimpl->wait_time_).count()) ;
}
void KeyStrokeRepeater::reset() noexcept {
pimpl->v_ = INITIAL_VELOCITY ;
pimpl->start_time_ = system_clock::now() ;
}
bool KeyStrokeRepeater::is_passed() const {
std::lock_guard<std::mutex> scoped_lock(pimpl->mtx_) ;
auto dt = compute_delta_t(pimpl->start_time_) ;
if(dt < pimpl->wait_time_) return false ;
//sampling
if(!pimpl->timer_.is_passed()) return false ;
pimpl->v_ = uniform_accelerate(pimpl->v_, static_cast<float>(dt.count())) ;
if(pimpl->v_ < generate_uniform()) {
return false ;
}
return true ;
}
}
}