abouttreesummaryrefslogcommitdiff
path: root/srcs/juloo.keyboard2/Pointers.java
diff options
context:
space:
mode:
authorJules Aguillon2024-05-02 19:31:48 +0200
committerGitHub2024-05-02 19:31:48 +0200
commit0f11a884185b832496fa5374ff03cfe61b91f9fb (patch)
tree7084c4dbadf517ea876bc4c0c3eb886b37038095 /srcs/juloo.keyboard2/Pointers.java
parent82e0840568655c8d71f2ac0c0ac5b1c18ef17845 (diff)
downloadunexpected-keyboard-0f11a884185b832496fa5374ff03cfe61b91f9fb.tar.gz
unexpected-keyboard-0f11a884185b832496fa5374ff03cfe61b91f9fb.zip
More precise and faster spacebar slider (#593)
* Make slider speed independent from swipe distance Swipe distances other than the default resulted in a slider that were not easy to control. * refactor: Add class Pointers.Sliding It holds the states and the code needed to make the slider work. 'Pointer.sliding' is set to [null] when sliding is not in progress. The implementation is changed not to depend on [downX] and [dx] but instead use the pointer's [x] coordinate directly. * Move the cursor further for faster slides In sliding mode, compute the speed of the pointer and use it to increase at which the cursor moves. * refactor: Separate kind for cursor movement keys This allows to define a key that moves the cursor more than one position at a time. This will be used to avoid lag during fast slider movements. * Reduce lag when sliding quickly on the spacebar Avoid sending key events in a loop while sliding quickly in a cursor movement key. Key of kind Cursor_move are "multiplied", meaning a single key event represents a movement of more than one position, reducing the number of key events sent. This is only for cursor move keys.
Diffstat (limited to 'srcs/juloo.keyboard2/Pointers.java')
-rw-r--r--srcs/juloo.keyboard2/Pointers.java133
1 files changed, 97 insertions, 36 deletions
diff --git a/srcs/juloo.keyboard2/Pointers.java b/srcs/juloo.keyboard2/Pointers.java
index 4a1c2d0..4d6ff9a 100644
--- a/srcs/juloo.keyboard2/Pointers.java
+++ b/srcs/juloo.keyboard2/Pointers.java
@@ -139,7 +139,7 @@ public final class Pointers implements Handler.Callback
if (ptr.hasFlagsAny(FLAG_P_SLIDING))
{
clearLatched();
- onTouchUp_sliding(ptr);
+ ptr.sliding.onTouchUp(ptr);
return;
}
stopKeyRepeat(ptr);
@@ -248,6 +248,11 @@ public final class Pointers implements Handler.Callback
Pointer ptr = getPtr(pointerId);
if (ptr == null)
return;
+ if (ptr.hasFlagsAny(FLAG_P_SLIDING))
+ {
+ ptr.sliding.onTouchMove(ptr, x);
+ return;
+ }
// The position in a IME windows is clampled to view.
// For a better up swipe behaviour, set the y position to a negative value when clamped.
@@ -255,12 +260,6 @@ public final class Pointers implements Handler.Callback
float dx = x - ptr.downX;
float dy = y - ptr.downY;
- if (ptr.hasFlagsAny(FLAG_P_SLIDING))
- {
- onTouchMove_sliding(ptr, dx);
- return;
- }
-
float dist = Math.abs(dx) + Math.abs(dy);
Integer direction;
if (dist < _config.swipe_dist_px)
@@ -290,7 +289,7 @@ public final class Pointers implements Handler.Callback
(newValue.equals(ptr.key.getKeyValue(5))
|| newValue.equals(ptr.key.getKeyValue(6))))
{
- startSliding(ptr, dy);
+ startSliding(ptr, x);
}
_handler.onPointerDown(newValue, true);
}
@@ -425,34 +424,11 @@ public final class Pointers implements Handler.Callback
// Sliding
- void startSliding(Pointer ptr, float initial_dy)
+ void startSliding(Pointer ptr, float x)
{
stopKeyRepeat(ptr);
ptr.flags |= FLAG_P_SLIDING;
- ptr.sliding_count = (int)(initial_dy / _config.slide_step_px);
- }
-
- /** Handle a sliding pointer going up. Latched modifiers are not cleared to
- allow easy adjustments to the cursors. The pointer is cancelled. */
- void onTouchUp_sliding(Pointer ptr)
- {
- removePtr(ptr);
- _handler.onPointerFlagsChanged(false);
- }
-
- /** Handle move events for sliding pointers. [dx] is distance travelled from
- [downX]. */
- void onTouchMove_sliding(Pointer ptr, float dx)
- {
- int count = (int)(dx / _config.slide_step_px);
- if (count == ptr.sliding_count)
- return;
- int key_index = (count < ptr.sliding_count) ? 5 : 6;
- KeyValue newValue = _handler.modifyKey(ptr.key.keys[key_index], ptr.modifiers);
- ptr.sliding_count = count;
- ptr.value = newValue;
- if (newValue != null)
- _handler.onPointerHold(newValue, ptr.modifiers);
+ ptr.sliding = new Sliding(x);
}
/** Return the [FLAG_P_*] flags that correspond to pressing [kv]. */
@@ -489,8 +465,8 @@ public final class Pointers implements Handler.Callback
public int flags;
/** Identify timeout messages. */
public int timeoutWhat;
- /** Number of event already caused by sliding. */
- public int sliding_count;
+ /** [null] when not in sliding mode. */
+ public Sliding sliding;
public Pointer(int p, KeyboardData.Key k, KeyValue v, float x, float y, Modifiers m)
{
@@ -503,7 +479,7 @@ public final class Pointers implements Handler.Callback
modifiers = m;
flags = (v == null) ? 0 : pointer_flags_of_kv(v);
timeoutWhat = -1;
- sliding_count = 0;
+ sliding = null;
}
public boolean hasFlagsAny(int has)
@@ -512,6 +488,91 @@ public final class Pointers implements Handler.Callback
}
}
+ public final class Sliding
+ {
+ /** Accumulated distance since last event. */
+ float d = 0.f;
+ /** The slider speed changes depending on the pointer speed. */
+ float speed = 1.f;
+ /** Coordinate of the last move. */
+ float last_x;
+ /** [System.currentTimeMillis()] at the time of the last move. */
+ long last_move_ms;
+
+ public Sliding(float x)
+ {
+ last_x = x;
+ last_move_ms = System.currentTimeMillis();
+ }
+
+ static final float SPEED_SMOOTHING = 0.7f;
+ /** Avoid absurdly large values. */
+ static final float SPEED_MAX = 4.f;
+
+ public void onTouchMove(Pointer ptr, float x)
+ {
+ d += (x - last_x) * speed / _config.slide_step_px;
+ update_speed(x);
+ // Send an event when [abs(d)] exceeds [1].
+ int d_ = (int)d;
+ if (d_ != 0)
+ {
+ d -= d_;
+ int key_index = (d_ < 0) ? 5 : 6;
+ ptr.value = _handler.modifyKey(ptr.key.keys[key_index], ptr.modifiers);
+ send_key(ptr, Math.abs(d_));
+ }
+ }
+
+ /** Handle a sliding pointer going up. Latched modifiers are not
+ cleared to allow easy adjustments to the cursors. The pointer is
+ cancelled. */
+ public void onTouchUp(Pointer ptr)
+ {
+ removePtr(ptr);
+ _handler.onPointerFlagsChanged(false);
+ }
+
+ /** Send the pressed key [n] times. */
+ void send_key(Pointer ptr, int n)
+ {
+ if (ptr.value == null)
+ return;
+ // Avoid looping if possible to avoid lag while sliding fast
+ KeyValue multiplied = multiply_key(ptr.value, n);
+ if (multiplied != null)
+ _handler.onPointerHold(multiplied, ptr.modifiers);
+ else
+ for (int i = 0; i < n; i++)
+ _handler.onPointerHold(ptr.value, ptr.modifiers);
+ }
+
+ /** Return a key performing the same action as [kv] but [n] times. Returns
+ [null] if [kv] cannot be multiplied. */
+ KeyValue multiply_key(KeyValue kv, int n)
+ {
+ switch (kv.getKind())
+ {
+ case Cursor_move:
+ return KeyValue.cursorMoveKey(kv.getCursorMove() * n);
+ }
+ return null;
+ }
+
+ /** [speed] is computed from the elapsed time and distance traveled
+ between two move events. Exponential smoothing is used to smooth out
+ the noise. Sets [last_move_ms] and [last_x]. */
+ void update_speed(float x)
+ {
+ long now = System.currentTimeMillis();
+ float instant_speed = Math.min(SPEED_MAX,
+ Math.abs(x - last_x) / (float)(now - last_move_ms) + 1.f);
+ speed = speed + (instant_speed - speed) * SPEED_SMOOTHING;
+ last_move_ms = now;
+ last_x = x;
+ }
+ }
+
/** Represent modifiers currently activated.
Sorted in the order they should be evaluated. */
public static final class Modifiers