Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add pointer.Buttons to MouseClick events #25

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 20 additions & 16 deletions gesture/gesture.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ type Click struct {
clicks int
// pressed tracks whether the pointer is pressed.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this change to something like

// pressed tracks whether one or more buttons from the Buttons set is pressed.

?

pressed bool
// Buttons tracks which buttons are pressed.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't seem quite right. Did you mean

// Buttons specify the set of buttons to track. The zero value is equivalent to the
// primary button, not the empty set.

?

Ah, I see from the rest of your change that I wasn't clear enough in my description. What I meant by the Buttons field is that it should be set by the user from Click, not Click itself. The purpose of (the zero value of) Buttons is maintain the old behaviour where only the primary mouse button would be tracked. Users such as yourself that need to track other buttons can include them in Buttons.

Buttons pointer.Buttons
// entered tracks whether the pointer is inside the gesture.
entered bool
// pid is the pointer.ID.
Expand All @@ -53,6 +55,7 @@ type ClickEvent struct {
Position f32.Point
Source pointer.Source
Modifiers key.Modifiers
Buttons pointer.Buttons
// NumClicks records successive clicks occurring
// within a short duration of each other.
NumClicks int
Expand Down Expand Up @@ -131,7 +134,7 @@ func (c *Click) Hovered() bool {
return c.entered
}

// Pressed returns whether a pointer is pressing.
// Pressed returns whether a pointer is pressing the left mouse button.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"primary mouse button". Sorry for renaming the buttons while you're working on this change :)

func (c *Click) Pressed() bool {
return c.pressed
}
Expand All @@ -146,33 +149,34 @@ func (c *Click) Events(q event.Queue) []ClickEvent {
}
switch e.Type {
case pointer.Release:
if !c.pressed || c.pid != e.PointerID {
if c.pid != e.PointerID {
break
}
c.pressed = false
b := c.Buttons ^ e.Buttons // the released button
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you mean "buttons" in plural?

Use full comment sentences: // The released buttons.

c.pressed = e.Buttons&pointer.ButtonPrimary > 0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use "!=" for bitmask operations. A ">" looks like an ordered operation.

c.Buttons = e.Buttons
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Click shouldn't update its Buttons field. See my comment on the field above.

if c.entered {
if e.Time-c.clickedAt < doubleClickDuration {
c.clicks++
} else {
c.clicks = 1
}
c.clickedAt = e.Time
events = append(events, ClickEvent{Type: TypeClick, Position: e.Position, Source: e.Source, Modifiers: e.Modifiers, NumClicks: c.clicks})
events = append(events, ClickEvent{Type: TypeClick, Position: e.Position, Source: e.Source, Buttons: b, Modifiers: e.Modifiers, NumClicks: c.clicks})
} else {
events = append(events, ClickEvent{Type: TypeCancel})
events = append(events, ClickEvent{Type: TypeCancel, Buttons: b})
}
case pointer.Cancel:
wasPressed := c.pressed
c.pressed = false
b := e.Buttons ^ c.Buttons
wasPressed := c.Buttons.Contain(b)
c.pressed = e.Buttons&pointer.ButtonPrimary > 0
c.Buttons = e.Buttons
c.entered = false
if wasPressed {
events = append(events, ClickEvent{Type: TypeCancel})
events = append(events, ClickEvent{Type: TypeCancel, Buttons: b})
}
case pointer.Press:
if c.pressed {
break
}
if e.Source == pointer.Mouse && e.Buttons != pointer.ButtonPrimary {
if e.Source == pointer.Mouse && e.Buttons == c.Buttons {
break
}
if !c.entered {
Expand All @@ -181,17 +185,17 @@ func (c *Click) Events(q event.Queue) []ClickEvent {
if c.pid != e.PointerID {
break
}
c.pressed = true
events = append(events, ClickEvent{Type: TypePress, Position: e.Position, Source: e.Source, Modifiers: e.Modifiers})
c.pressed = e.Buttons&pointer.ButtonPrimary > 0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

!=

events = append(events, ClickEvent{Type: TypePress, Position: e.Position, Source: e.Source, Buttons: e.Buttons, Modifiers: e.Modifiers})
case pointer.Leave:
if !c.pressed {
if !c.Buttons.Contain(c.Buttons ^ e.Buttons) {
c.pid = e.PointerID
}
if c.pid == e.PointerID {
c.entered = false
}
case pointer.Enter:
if !c.pressed {
if !c.Buttons.Contain(c.Buttons ^ e.Buttons) {
c.pid = e.PointerID
}
if c.pid == e.PointerID {
Expand Down
61 changes: 61 additions & 0 deletions gesture/gesture_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,21 @@ func TestMouseClicks(t *testing.T) {
100*time.Millisecond+doubleClickDuration+1),
clicks: []int{1, 1},
},
{
label: "left and right clicks mixed",
events: mouseMultiButtonClickEvents(
100*time.Millisecond,
100*time.Millisecond+doubleClickDuration*1+1,
100*time.Millisecond+doubleClickDuration*2+1,
100*time.Millisecond+doubleClickDuration*3+1,
100*time.Millisecond+doubleClickDuration*4+1,
100*time.Millisecond+doubleClickDuration*5+1,
100*time.Millisecond+doubleClickDuration*6+1,
100*time.Millisecond+doubleClickDuration*7+1,
100*time.Millisecond+doubleClickDuration*8+1,
),
clicks: []int{1, 1, 1, 1, 1, 1, 1, 1, 1},
},
} {
t.Run(tc.label, func(t *testing.T) {
var click Click
Expand Down Expand Up @@ -85,3 +100,49 @@ func filterMouseClicks(events []ClickEvent) []ClickEvent {
}
return clicks
}

func mouseMultiButtonClickEvents(times ...time.Duration) []event.Event {
events := make([]event.Event, 0)
numSecondaryClick := 0
numPrimaryClick := 0
for i, _ := range times {
if i%2 == 0 {
press := pointer.Event{
Type: pointer.Press,
Source: pointer.Mouse,
Buttons: pointer.ButtonPrimary,
}
numPrimaryClick++
events = append(events, press)
} else {
press := pointer.Event{
Type: pointer.Press,
Source: pointer.Mouse,
Buttons: pointer.ButtonSecondary,
}
numSecondaryClick++
events = append(events, press)
}
}
i := 0
for ; i < numPrimaryClick; i++ {
release := pointer.Event{
Type: pointer.Release,
Source: pointer.Mouse,
Buttons: pointer.ButtonPrimary,
Time: times[i],
}
events = append(events, release)
}
for ; i < numSecondaryClick+numPrimaryClick; i++ {
release := pointer.Event{
Type: pointer.Release,
Source: pointer.Mouse,
Buttons: pointer.ButtonSecondary,
Time: times[i],
}

events = append(events, release)
}
return events
}