mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-01 07:35:40 +00:00
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:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
|
||||
},
|
||||
{
|
||||
.name = "onTouchEvent",
|
||||
.signature = "(JIIIFFJ)V",
|
||||
.signature = "(JIIIFFIJ)V",
|
||||
.fnPtr = onTouchEvent
|
||||
},
|
||||
{
|
||||
|
||||
@@ -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)},
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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},
|
||||
})
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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() {}
|
||||
|
||||
Reference in New Issue
Block a user