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
|
// Counting mouse clicks, so that a second one on the same spot means
// something different from the first.
package editor
import (
"time"
"codeberg.org/turbo-editors/turbo-core/buffer"
)
// doubleClickWithin is how long after a press a second one on the same cell
// still counts as a double click.
//
// Four hundred milliseconds is what most desktops settle on. Shorter and a
// deliberate double click made with an unhurried hand is read as two separate
// ones; longer and two unrelated clicks in the same place — which happens all
// the time while reading — start selecting words nobody asked for.
const doubleClickWithin = 400 * time.Millisecond
// click is where and when a press landed, and how many have landed in a row.
type click struct {
at buffer.Position
when time.Time
count int
}
// countClick records a press and returns how many presses in a row have now
// landed on the same cell: 1 for a fresh click, 2 for a double click.
//
// The cell has to be the same, not merely near: a press one column over is a
// different word, and selecting the first one because the pointer drifted is
// worse than not selecting at all.
func (v *View) countClick(at buffer.Position) int {
now := v.now()
if v.lastClick.count > 0 &&
v.lastClick.at == at &&
now.Sub(v.lastClick.when) <= doubleClickWithin {
v.lastClick.count++
} else {
v.lastClick.count = 1
}
v.lastClick.at = at
v.lastClick.when = now
return v.lastClick.count
}
// SetClock replaces the clock two clicks are timed against.
//
// Only a test has any business calling this. A double click measured against
// the real clock is a test that passes or fails by how fast the machine is.
//
// view.SetClock(func() time.Time { return moment })
func (v *View) SetClock(now func() time.Time) { v.now = now }
|