io/pointer,gesture: report right and middle mouse button events

Updates gio#60

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2019-11-09 16:34:00 +01:00
parent a0050ab79b
commit dc7f9bab23
10 changed files with 160 additions and 36 deletions
+3 -1
View File
@@ -106,6 +106,7 @@ public class GioView extends SurfaceView implements Choreographer.FrameCallback
event.getToolType(i),
event.getHistoricalX(i, j),
event.getHistoricalY(i, j),
event.getButtonState(),
time);
}
}
@@ -123,6 +124,7 @@ public class GioView extends SurfaceView implements Choreographer.FrameCallback
event.getToolType(i),
event.getX(i),
event.getY(i),
event.getButtonState(),
event.getEventTime());
}
return true;
@@ -214,7 +216,7 @@ public class GioView extends SurfaceView implements Choreographer.FrameCallback
static private native void onConfigurationChanged(long handle);
static private native void onWindowInsets(long handle, int top, int right, int bottom, int left);
static private native void onLowMemory();
static private native void onTouchEvent(long handle, int action, int pointerID, int tool, float x, float y, long time);
static private native void onTouchEvent(long handle, int action, int pointerID, int tool, float x, float y, int buttons, long time);
static private native void onKeyEvent(long handle, int code, int character, long time);
static private native void onFrameCallback(long handle, long nanos);
static private native boolean onBack(long handle);
+13 -1
View File
@@ -18,7 +18,7 @@ static void handleMouse(NSView *view, NSEvent *event, int typ, CGFloat dx, CGFlo
dx *= 10;
dy *= 10;
}
gio_onMouse((__bridge CFTypeRef)view, typ, p.x, p.y, dx, dy, [event timestamp]);
gio_onMouse((__bridge CFTypeRef)view, typ, [NSEvent pressedMouseButtons], p.x, p.y, dx, dy, [event timestamp]);
}
static CVReturn displayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp *inNow, const CVTimeStamp *inOutputTime, CVOptionFlags flagsIn, CVOptionFlags *flagsOut, void *displayLinkContext) {
@@ -79,6 +79,18 @@ CVDisplayLinkRef displayLink;
- (void)mouseUp:(NSEvent *)event {
handleMouse(self, event, GIO_MOUSE_UP, 0, 0);
}
- (void)middleMouseDown:(NSEvent *)event {
handleMouse(self, event, GIO_MOUSE_DOWN, 0, 0);
}
- (void)middletMouseUp:(NSEvent *)event {
handleMouse(self, event, GIO_MOUSE_UP, 0, 0);
}
- (void)rightMouseDown:(NSEvent *)event {
handleMouse(self, event, GIO_MOUSE_DOWN, 0, 0);
}
- (void)rightMouseUp:(NSEvent *)event {
handleMouse(self, event, GIO_MOUSE_UP, 0, 0);
}
- (void)mouseMoved:(NSEvent *)event {
handleMouse(self, event, GIO_MOUSE_MOVE, 0, 0);
}
+1 -1
View File
@@ -72,7 +72,7 @@ JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
},
{
.name = "onTouchEvent",
.signature = "(JIIIFFJ)V",
.signature = "(JIIIFFIJ)V",
.fnPtr = onTouchEvent
},
{
+12 -1
View File
@@ -386,7 +386,7 @@ func onKeyEvent(env *C.JNIEnv, class C.jclass, handle C.jlong, keyCode, r C.jint
}
//export onTouchEvent
func onTouchEvent(env *C.JNIEnv, class C.jclass, handle C.jlong, action, pointerID, tool C.jint, x, y C.jfloat, t C.jlong) {
func onTouchEvent(env *C.JNIEnv, class C.jclass, handle C.jlong, action, pointerID, tool C.jint, x, y C.jfloat, jbtns C.jint, t C.jlong) {
w := views[handle]
var typ pointer.Type
switch action {
@@ -402,6 +402,16 @@ func onTouchEvent(env *C.JNIEnv, class C.jclass, handle C.jlong, action, pointer
return
}
var src pointer.Source
var btns pointer.Buttons
if jbtns&C.AMOTION_EVENT_BUTTON_PRIMARY != 0 {
btns |= pointer.ButtonLeft
}
if jbtns&C.AMOTION_EVENT_BUTTON_SECONDARY != 0 {
btns |= pointer.ButtonRight
}
if jbtns&C.AMOTION_EVENT_BUTTON_TERTIARY != 0 {
btns |= pointer.ButtonMiddle
}
switch tool {
case C.AMOTION_EVENT_TOOL_TYPE_FINGER:
src = pointer.Touch
@@ -413,6 +423,7 @@ func onTouchEvent(env *C.JNIEnv, class C.jclass, handle C.jlong, action, pointer
w.callbacks.Event(pointer.Event{
Type: typ,
Source: src,
Buttons: btns,
PointerID: pointer.ID(pointerID),
Time: time.Duration(t) * time.Millisecond,
Position: f32.Point{X: float32(x), Y: float32(y)},
+12
View File
@@ -282,9 +282,21 @@ func (w *window) pointerEvent(typ pointer.Type, dx, dy float32, e js.Value) {
Y: dy * scale,
}
t := time.Duration(e.Get("timeStamp").Int()) * time.Millisecond
jbtns := e.Get("buttons").Int()
var btns pointer.Buttons
if jbtns&1 != 0 {
btns |= pointer.ButtonLeft
}
if jbtns&2 != 0 {
btns |= pointer.ButtonRight
}
if jbtns&4 != 0 {
btns |= pointer.ButtonMiddle
}
w.w.Event(pointer.Event{
Type: typ,
Source: pointer.Mouse,
Buttons: btns,
Position: pos,
Scroll: scroll,
Time: t,
+12 -1
View File
@@ -151,7 +151,7 @@ func gio_onText(view C.CFTypeRef, cstr *C.char) {
}
//export gio_onMouse
func gio_onMouse(view C.CFTypeRef, cdir C.int, x, y, dx, dy C.CGFloat, ti C.double) {
func gio_onMouse(view C.CFTypeRef, cdir C.int, cbtns C.NSUInteger, x, y, dx, dy C.CGFloat, ti C.double) {
var typ pointer.Type
switch cdir {
case C.GIO_MOUSE_MOVE:
@@ -163,6 +163,16 @@ func gio_onMouse(view C.CFTypeRef, cdir C.int, x, y, dx, dy C.CGFloat, ti C.doub
default:
panic("invalid direction")
}
var btns pointer.Buttons
if cbtns&(1<<0) != 0 {
btns |= pointer.ButtonLeft
}
if cbtns&(1<<1) != 0 {
btns |= pointer.ButtonRight
}
if cbtns&(1<<2) != 0 {
btns |= pointer.ButtonMiddle
}
t := time.Duration(float64(ti)*float64(time.Second) + .5)
viewDo(view, func(views viewMap, view C.CFTypeRef) {
w := views[view]
@@ -172,6 +182,7 @@ func gio_onMouse(view C.CFTypeRef, cdir C.int, x, y, dx, dy C.CGFloat, ti C.doub
Type: typ,
Source: pointer.Mouse,
Time: t,
Buttons: btns,
Position: f32.Point{X: x, Y: y},
Scroll: f32.Point{X: dx, Y: dy},
})
+23 -5
View File
@@ -106,8 +106,9 @@ type window struct {
steps image.Point
dist f32.Point
}
lastPos f32.Point
lastTouch f32.Point
pointerBtns pointer.Buttons
lastPos f32.Point
lastTouch f32.Point
fling struct {
yExtrapolation fling.Extrapolation
@@ -514,18 +515,32 @@ func gio_onPointerMotion(data unsafe.Pointer, p *C.struct_wl_pointer, t C.uint32
}
//export gio_onPointerButton
func gio_onPointerButton(data unsafe.Pointer, p *C.struct_wl_pointer, serial, t, button, state C.uint32_t) {
func gio_onPointerButton(data unsafe.Pointer, p *C.struct_wl_pointer, serial, t, wbtn, state C.uint32_t) {
w := winMap[p]
// From linux-event-codes.h.
const BTN_LEFT = 0x110
if button != BTN_LEFT {
const (
BTN_LEFT = 0x110
BTN_RIGHT = 0x111
BTN_MIDDLE = 0x112
)
var btn pointer.Buttons
switch wbtn {
case BTN_LEFT:
btn = pointer.ButtonLeft
case BTN_RIGHT:
btn = pointer.ButtonRight
case BTN_MIDDLE:
btn = pointer.ButtonMiddle
default:
return
}
var typ pointer.Type
switch state {
case 0:
w.pointerBtns &^= btn
typ = pointer.Release
case 1:
w.pointerBtns |= btn
typ = pointer.Press
}
w.flushScroll()
@@ -533,6 +548,7 @@ func gio_onPointerButton(data unsafe.Pointer, p *C.struct_wl_pointer, serial, t,
w.w.Event(pointer.Event{
Type: typ,
Source: pointer.Mouse,
Buttons: w.pointerBtns,
Position: w.lastPos,
Time: time.Duration(t) * time.Millisecond,
})
@@ -908,6 +924,7 @@ func (w *window) flushScroll() {
w.w.Event(pointer.Event{
Type: pointer.Move,
Source: pointer.Mouse,
Buttons: w.pointerBtns,
Position: w.lastPos,
Scroll: total,
Time: w.scroll.time,
@@ -929,6 +946,7 @@ func (w *window) onPointerMotion(x, y C.wl_fixed_t, t C.uint32_t) {
w.w.Event(pointer.Event{
Type: pointer.Move,
Position: w.lastPos,
Buttons: w.pointerBtns,
Source: pointer.Mouse,
Time: time.Duration(t) * time.Millisecond,
})
+49 -26
View File
@@ -56,13 +56,14 @@ type point struct {
}
type window struct {
hwnd syscall.Handle
hdc syscall.Handle
w Callbacks
width int
height int
stage system.Stage
dead bool
hwnd syscall.Handle
hdc syscall.Handle
w Callbacks
width int
height int
stage system.Stage
dead bool
pointerBtns pointer.Buttons
mu sync.Mutex
animating bool
@@ -139,6 +140,8 @@ const (
_WM_KEYUP = 0x0101
_WM_LBUTTONDOWN = 0x0201
_WM_LBUTTONUP = 0x0202
_WM_MBUTTONDOWN =0x0207
_WM_MBUTTONUP =0x0208
_WM_MOUSEMOVE = 0x0200
_WM_MOUSEWHEEL = 0x020A
_WM_PAINT = 0x000F
@@ -148,6 +151,8 @@ const (
_WM_SHOWWINDOW = 0x0018
_WM_SIZE = 0x0005
_WM_SYSKEYDOWN = 0x0104
_WM_RBUTTONDOWN =0x0204
_WM_RBUTTONUP = 0x0205
_WM_TIMER = 0x0113
_WM_UNICHAR = 0x0109
_WM_USER = 0x0400
@@ -313,15 +318,17 @@ func windowProc(hwnd syscall.Handle, msg uint32, wParam, lParam uintptr) uintptr
w.w.Event(cmd)
}
case _WM_LBUTTONDOWN:
setCapture(w.hwnd)
x, y := coordsFromlParam(lParam)
p := f32.Point{X: float32(x), Y: float32(y)}
w.w.Event(pointer.Event{
Type: pointer.Press,
Source: pointer.Mouse,
Position: p,
Time: getMessageTime(),
})
w.pointerButton(pointer.ButtonLeft, true, lParam)
case _WM_LBUTTONUP:
w.pointerButton(pointer.ButtonLeft, false, lParam)
case _WM_RBUTTONDOWN:
w.pointerButton(pointer.ButtonRight, true, lParam)
case _WM_RBUTTONUP:
w.pointerButton(pointer.ButtonRight, false, lParam)
case _WM_MBUTTONDOWN:
w.pointerButton(pointer.ButtonMiddle, true, lParam)
case _WM_MBUTTONUP:
w.pointerButton(pointer.ButtonMiddle, false, lParam)
case _WM_CANCELMODE:
w.w.Event(pointer.Event{
Type: pointer.Cancel,
@@ -330,16 +337,6 @@ func windowProc(hwnd syscall.Handle, msg uint32, wParam, lParam uintptr) uintptr
w.w.Event(key.FocusEvent{Focus: true})
case _WM_KILLFOCUS:
w.w.Event(key.FocusEvent{Focus: false})
case _WM_LBUTTONUP:
releaseCapture()
x, y := coordsFromlParam(lParam)
p := f32.Point{X: float32(x), Y: float32(y)}
w.w.Event(pointer.Event{
Type: pointer.Release,
Source: pointer.Mouse,
Position: p,
Time: getMessageTime(),
})
case _WM_MOUSEMOVE:
x, y := coordsFromlParam(lParam)
p := f32.Point{X: float32(x), Y: float32(y)}
@@ -367,6 +364,32 @@ func windowProc(hwnd syscall.Handle, msg uint32, wParam, lParam uintptr) uintptr
return defWindowProc(hwnd, msg, wParam, lParam)
}
func (w *window) pointerButton(btn pointer.Buttons, press bool, lParam uintptr) {
var typ pointer.Type
if press {
typ = pointer.Press
if w.pointerBtns == 0 {
setCapture(w.hwnd)
}
w.pointerBtns |= btn
} else {
typ = pointer.Release
w.pointerBtns &^= btn
if w.pointerBtns == 0 {
releaseCapture()
}
}
x, y := coordsFromlParam(lParam)
p := f32.Point{X: float32(x), Y: float32(y)}
w.w.Event(pointer.Event{
Type: typ,
Source: pointer.Mouse,
Position: p,
Buttons: w.pointerBtns,
Time: getMessageTime(),
})
}
func coordsFromlParam(lParam uintptr) (int, int) {
x := int(int16(lParam & 0xffff))
y := int(int16((lParam >> 16) & 0xffff))
+3
View File
@@ -128,6 +128,9 @@ func (c *Click) Events(q event.Queue) []ClickEvent {
if c.state == StatePressed || !e.Hit {
break
}
if e.Source == pointer.Mouse && e.Buttons != pointer.ButtonLeft {
break
}
c.state = StatePressed
events = append(events, ClickEvent{Type: TypePress, Position: e.Position, Source: e.Source})
case pointer.Move:
+32
View File
@@ -5,6 +5,7 @@ package pointer
import (
"encoding/binary"
"image"
"strings"
"time"
"gioui.org/f32"
@@ -27,6 +28,8 @@ type Event struct {
// Time is when the event was received. The
// timestamp is relative to an undefined base.
Time time.Duration
// Buttons are the set of pressed mouse buttons for this event.
Buttons Buttons
// Hit is set when the event was within the registered
// area for the handler. Hit can be false when a pointer
// was pressed within the hit area, and then dragged
@@ -86,6 +89,9 @@ type Priority uint8
// Source of an Event.
type Source uint8
// Buttons is a set of mouse buttons
type Buttons uint8
// Must match app/internal/input.areaKind
type areaKind uint8
@@ -116,6 +122,12 @@ const (
Grabbed
)
const (
ButtonLeft Buttons = 1 << iota
ButtonRight
ButtonMiddle
)
const (
areaRect areaKind = iota
areaEllipse
@@ -199,4 +211,24 @@ func (s Source) String() string {
}
}
// Contain reports whether the set b contains
// all of the buttons.
func (b Buttons) Contain(buttons Buttons) bool {
return b&buttons == buttons
}
func (b Buttons) String() string {
var strs []string
if b.Contain(ButtonLeft) {
strs = append(strs, "ButtonLeft")
}
if b.Contain(ButtonRight) {
strs = append(strs, "ButtonRight")
}
if b.Contain(ButtonMiddle) {
strs = append(strs, "ButtonMiddle")
}
return strings.Join(strs, "|")
}
func (Event) ImplementsEvent() {}