~eliasnaur/gio

0f51cb9084c2cddbd3e1165e2d5cc82fb4f884a5 — Elias Naur 10 months ago fc5689e
app: [macOS] don't miss pointer presses

We used to track the pressed pointer buttons through the global function
[NSEvent pressedMouseButtons]. However, it's possible that at the time a pointer
press event is delivered, the pointer button is up again. To ensure a consistent
view of the pointer press state, track it through the buttonNumber property on
delivered events.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2 files changed, 15 insertions(+), 15 deletions(-)

M app/os_macos.go
M app/os_macos.m
M app/os_macos.go => app/os_macos.go +14 -14
@@ 242,8 242,9 @@ type window struct {
	displayLink *displayLink
	// redraw is a single entry channel for making sure only one
	// display link redraw request is in flight.
	redraw chan struct{}
	cursor pointer.Cursor
	redraw      chan struct{}
	cursor      pointer.Cursor
	pointerBtns pointer.Buttons

	scale  float32
	config Config


@@ 502,20 503,29 @@ func gio_onText(view, cstr C.CFTypeRef) {
}

//export gio_onMouse
func gio_onMouse(view, evt C.CFTypeRef, cdir C.int, cbtns C.NSUInteger, x, y, dx, dy C.CGFloat, ti C.double, mods C.NSUInteger) {
func gio_onMouse(view, evt C.CFTypeRef, cdir C.int, cbtn C.NSInteger, x, y, dx, dy C.CGFloat, ti C.double, mods C.NSUInteger) {
	w := mustView(view)
	t := time.Duration(float64(ti)*float64(time.Second) + .5)
	xf, yf := float32(x)*w.scale, float32(y)*w.scale
	dxf, dyf := float32(dx)*w.scale, float32(dy)*w.scale
	pos := f32.Point{X: xf, Y: yf}
	var btn pointer.Buttons
	switch cbtn {
	case 0:
		btn = pointer.ButtonPrimary
	case 1:
		btn = pointer.ButtonSecondary
	}
	var typ pointer.Type
	switch cdir {
	case C.MOUSE_MOVE:
		typ = pointer.Move
	case C.MOUSE_UP:
		typ = pointer.Release
		w.pointerBtns &^= btn
	case C.MOUSE_DOWN:
		typ = pointer.Press
		w.pointerBtns |= btn
		act, ok := w.w.ActionAt(pos)
		if ok && w.config.Mode != Fullscreen {
			switch act {


@@ 529,21 539,11 @@ func gio_onMouse(view, evt C.CFTypeRef, cdir C.int, cbtns C.NSUInteger, x, y, dx
	default:
		panic("invalid direction")
	}
	var btns pointer.Buttons
	if cbtns&(1<<0) != 0 {
		btns |= pointer.ButtonPrimary
	}
	if cbtns&(1<<1) != 0 {
		btns |= pointer.ButtonSecondary
	}
	if cbtns&(1<<2) != 0 {
		btns |= pointer.ButtonTertiary
	}
	w.w.Event(pointer.Event{
		Type:      typ,
		Source:    pointer.Mouse,
		Time:      t,
		Buttons:   btns,
		Buttons:   w.pointerBtns,
		Position:  pos,
		Scroll:    f32.Point{X: dxf, Y: dyf},
		Modifiers: convertMods(mods),

M app/os_macos.m => app/os_macos.m +1 -1
@@ 61,7 61,7 @@ static void handleMouse(NSView *view, NSEvent *event, int typ, CGFloat dx, CGFlo
	}
	// Origin is in the lower left corner. Convert to upper left.
	CGFloat height = view.bounds.size.height;
	gio_onMouse((__bridge CFTypeRef)view, (__bridge CFTypeRef)event, typ, [NSEvent pressedMouseButtons], p.x, height - p.y, dx, dy, [event timestamp], [event modifierFlags]);
	gio_onMouse((__bridge CFTypeRef)view, (__bridge CFTypeRef)event, typ, event.buttonNumber, p.x, height - p.y, dx, dy, [event timestamp], [event modifierFlags]);
}

@interface GioView : NSView <CALayerDelegate,NSTextInputClient>