Skip to content

Commit 1a612d1

Browse files
committed
Merge branch 'zephylac-feature/mouse_support'
2 parents 8fa6629 + d7cecb1 commit 1a612d1

File tree

4 files changed

+133
-16
lines changed

4 files changed

+133
-16
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ It's also possible to [manually install](https://github.com/go-flutter-desktop/g
4949
- <kbd>Right</kbd> <kbd>ctrl-Right</kbd> <kbd>ctrl-shift-Right</kbd>
5050
- <kbd>Backspace</kbd> <kbd>ctrl-Backspace</kbd> <kbd>Delete</kbd>
5151
- Mouse-over/hovering
52+
- Mouse-buttons
5253
- RawKeyboard events (through `RawKeyEventDataLinux` regardless of the platform)
5354

5455
Are you missing a feature? [Open an issue!](https://github.com/go-flutter-desktop/go-flutter/issues/new)

embedder/embedder.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,16 @@ const (
143143
PointerPhaseHover PointerPhase = C.kHover
144144
)
145145

146+
// PointerButtonMouse corresponds to the C.enum describing the mouse buttons.
147+
type PointerButtonMouse int64
148+
149+
// Values representing the mouse buttons.
150+
const (
151+
PointerButtonMousePrimary PointerButtonMouse = C.kFlutterPointerButtonMousePrimary
152+
PointerButtonMouseSecondary PointerButtonMouse = C.kFlutterPointerButtonMouseSecondary
153+
PointerButtonMouseMiddle PointerButtonMouse = C.kFlutterPointerButtonMouseMiddle
154+
)
155+
146156
// PointerSignalKind corresponds to the C.enum describing signal kind of the mouse pointer.
147157
type PointerSignalKind int32
148158

@@ -152,6 +162,15 @@ const (
152162
PointerSignalKindScroll PointerSignalKind = C.kFlutterPointerSignalKindScroll
153163
)
154164

165+
// PointerDeviceKind corresponds to the C.enum describing device kind of the mouse pointer.
166+
type PointerDeviceKind int32
167+
168+
// Values representing the pointer signal kind.
169+
const (
170+
PointerDeviceKindMouse PointerDeviceKind = C.kFlutterPointerDeviceKindMouse
171+
PointerDeviceKindTouch PointerDeviceKind = C.kFlutterPointerDeviceKindTouch
172+
)
173+
155174
// PointerEvent represents the position and phase of the mouse at a given time.
156175
type PointerEvent struct {
157176
Phase PointerPhase
@@ -161,6 +180,7 @@ type PointerEvent struct {
161180
SignalKind PointerSignalKind
162181
ScrollDeltaX float64
163182
ScrollDeltaY float64
183+
Buttons PointerButtonMouse
164184
}
165185

166186
// SendPointerEvent is used to send an PointerEvent to the Flutter engine.
@@ -171,8 +191,10 @@ func (flu *FlutterEngine) SendPointerEvent(event PointerEvent) Result {
171191
y: C.double(event.Y),
172192
timestamp: C.size_t(event.Timestamp),
173193
signal_kind: (C.FlutterPointerSignalKind)(event.SignalKind),
194+
device_kind: (C.FlutterPointerDeviceKind)(PointerDeviceKindMouse),
174195
scroll_delta_x: C.double(event.ScrollDeltaX),
175196
scroll_delta_y: C.double(event.ScrollDeltaY),
197+
buttons: C.int64_t(event.Buttons),
176198
}
177199
cPointerEvent.struct_size = C.size_t(unsafe.Sizeof(cPointerEvent))
178200

embedder/embedder.h

Lines changed: 57 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -280,14 +280,57 @@ typedef struct {
280280
// The phase of the pointer event.
281281
typedef enum {
282282
kCancel,
283+
// The pointer, which must have been down (see kDown), is now up.
284+
//
285+
// For touch, this means that the pointer is no longer in contact with the
286+
// screen. For a mouse, it means the last button was released. Note that if
287+
// any other buttons are still pressed when one button is released, that
288+
// should be sent as a kMove rather than a kUp.
283289
kUp,
290+
// The pointer, which must have been been up, is now down.
291+
//
292+
// For touch, this means that the pointer has come into contact with the
293+
// screen. For a mouse, it means a button is now pressed. Note that if any
294+
// other buttons are already pressed when a new button is pressed, that should
295+
// be sent as a kMove rather than a kDown.
284296
kDown,
297+
// The pointer moved while down.
298+
//
299+
// This is also used for changes in button state that don't cause a kDown or
300+
// kUp, such as releasing one of two pressed buttons.
285301
kMove,
302+
// The pointer is now sending input to Flutter. For instance, a mouse has
303+
// entered the area where the Flutter content is displayed.
304+
//
305+
// A pointer should always be added before sending any other events.
286306
kAdd,
307+
// The pointer is no longer sending input to Flutter. For instance, a mouse
308+
// has left the area where the Flutter content is displayed.
309+
//
310+
// A removed pointer should no longer send events until sending a new kAdd.
287311
kRemove,
312+
// The pointer moved while up.
288313
kHover,
289314
} FlutterPointerPhase;
290315

316+
// The device type that created a pointer event.
317+
typedef enum {
318+
kFlutterPointerDeviceKindMouse = 1,
319+
kFlutterPointerDeviceKindTouch,
320+
} FlutterPointerDeviceKind;
321+
322+
// Flags for the |buttons| field of |FlutterPointerEvent| when |device_kind|
323+
// is |kFlutterPointerDeviceKindMouse|.
324+
typedef enum {
325+
kFlutterPointerButtonMousePrimary = 1 << 0,
326+
kFlutterPointerButtonMouseSecondary = 1 << 1,
327+
kFlutterPointerButtonMouseMiddle = 1 << 2,
328+
kFlutterPointerButtonMouseBack = 1 << 3,
329+
kFlutterPointerButtonMouseForward = 1 << 4,
330+
// If a mouse has more than five buttons, send higher bit shifted values
331+
// corresponding to the button number: 1 << 5 for the 6th, etc.
332+
} FlutterPointerMouseButtons;
333+
291334
// The type of a pointer signal.
292335
typedef enum {
293336
kFlutterPointerSignalKindNone,
@@ -307,6 +350,14 @@ typedef struct {
307350
FlutterPointerSignalKind signal_kind;
308351
double scroll_delta_x;
309352
double scroll_delta_y;
353+
// The type of the device generating this event.
354+
// Backwards compatibility note: If this is not set, the device will be
355+
// treated as a mouse, with the primary button set for |kDown| and |kMove|.
356+
// If set explicitly to |kFlutterPointerDeviceKindMouse|, you must set the
357+
// correct buttons.
358+
FlutterPointerDeviceKind device_kind;
359+
// The buttons currently pressed, if any.
360+
int64_t buttons;
310361
} FlutterPointerEvent;
311362

312363
struct _FlutterPlatformMessageResponseHandle;
@@ -322,11 +373,10 @@ typedef struct {
322373
// The response handle on which to invoke
323374
// |FlutterEngineSendPlatformMessageResponse| when the response is ready. This
324375
// field is ignored for messages being sent from the embedder to the
325-
// framework. If the embedder ever receives a message with a non-null response
326-
// handle, that handle must always be used with a
327-
// |FlutterEngineSendPlatformMessageResponse| call. If not, this is a memory
328-
// leak. It is not safe to send multiple responses on a single response
329-
// object.
376+
// framework. |FlutterEngineSendPlatformMessageResponse| must be called for
377+
// all messages received by the embedder. Failure to call
378+
// |FlutterEngineSendPlatformMessageResponse| will cause a memory leak. It is
379+
// not safe to send multiple responses on a single response object.
330380
const FlutterPlatformMessageResponseHandle* response_handle;
331381
} FlutterPlatformMessage;
332382

@@ -432,7 +482,7 @@ typedef struct {
432482
size_t struct_size;
433483
// The unique custom action or action override ID.
434484
int32_t id;
435-
// For overriden standard actions, corresponds to the
485+
// For overridden standard actions, corresponds to the
436486
// |FlutterSemanticsAction| to override.
437487
FlutterSemanticsAction override_action;
438488
// The user-readable name of this custom semantics action.
@@ -785,4 +835,4 @@ FlutterEngineResult FlutterEngineRunTask(FlutterEngine engine,
785835
} // extern "C"
786836
#endif
787837

788-
#endif // FLUTTER_EMBEDDER_H_
838+
#endif // FLUTTER_EMBEDDER_H_

glfw.go

Lines changed: 53 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ type windowManager struct {
2424
pointerPhase embedder.PointerPhase
2525
pixelsPerScreenCoordinate float64
2626
pointerCurrentlyAdded bool
27+
pointerButton embedder.PointerButtonMouse
2728
}
2829

2930
func newWindowManager() *windowManager {
@@ -51,6 +52,7 @@ func (m *windowManager) sendPointerEvent(window *glfw.Window, phase embedder.Poi
5152
X: x * m.pixelsPerScreenCoordinate,
5253
Y: y * m.pixelsPerScreenCoordinate,
5354
Timestamp: time.Now().UnixNano() / int64(time.Millisecond),
55+
Buttons: m.pointerButton,
5456
}
5557

5658
flutterEnginePointer := *(*uintptr)(window.GetUserPointer())
@@ -65,6 +67,21 @@ func (m *windowManager) sendPointerEvent(window *glfw.Window, phase embedder.Poi
6567
}
6668
}
6769

70+
func (m *windowManager) sendPointerEventButton(window *glfw.Window, phase embedder.PointerPhase) {
71+
x, y := window.GetCursorPos()
72+
event := embedder.PointerEvent{
73+
Phase: phase,
74+
X: x * m.pixelsPerScreenCoordinate,
75+
Y: y * m.pixelsPerScreenCoordinate,
76+
Timestamp: time.Now().UnixNano() / int64(time.Millisecond),
77+
SignalKind: embedder.PointerSignalKindNone,
78+
Buttons: m.pointerButton,
79+
}
80+
flutterEnginePointer := *(*uintptr)(window.GetUserPointer())
81+
flutterEngine := (*embedder.FlutterEngine)(unsafe.Pointer(flutterEnginePointer))
82+
flutterEngine.SendPointerEvent(event)
83+
}
84+
6885
func (m *windowManager) sendPointerEventScroll(window *glfw.Window, xDelta, yDelta float64) {
6986
x, y := window.GetCursorPos()
7087
event := embedder.PointerEvent{
@@ -75,6 +92,7 @@ func (m *windowManager) sendPointerEventScroll(window *glfw.Window, xDelta, yDel
7592
SignalKind: embedder.PointerSignalKindScroll,
7693
ScrollDeltaX: xDelta,
7794
ScrollDeltaY: yDelta,
95+
Buttons: m.pointerButton,
7896
}
7997

8098
flutterEnginePointer := *(*uintptr)(window.GetUserPointer())
@@ -97,22 +115,48 @@ func (m *windowManager) glfwCursorPosCallback(window *glfw.Window, x, y float64)
97115
m.sendPointerEvent(window, m.pointerPhase, x, y)
98116
}
99117

100-
func (m *windowManager) glfwMouseButtonCallback(window *glfw.Window, key glfw.MouseButton, action glfw.Action, mods glfw.ModifierKey) {
101-
if key == glfw.MouseButton1 {
102-
x, y := window.GetCursorPos()
103-
104-
if action == glfw.Press {
105-
m.sendPointerEvent(window, embedder.PointerPhaseDown, x, y)
106-
m.pointerPhase = embedder.PointerPhaseMove
118+
func (m *windowManager) handleButtonPhase(window *glfw.Window, action glfw.Action, buttons embedder.PointerButtonMouse) {
119+
if action == glfw.Press {
120+
m.pointerButton |= buttons
121+
// If only one button is pressed then each bits of buttons will be equals
122+
// to m.pointerButton.
123+
if m.pointerButton == buttons {
124+
m.sendPointerEventButton(window, embedder.PointerPhaseDown)
125+
} else {
126+
// if any other buttons are already pressed when a new button is pressed,
127+
// the engine is expecting a Move phase instead of a Down phase.
128+
m.sendPointerEventButton(window, embedder.PointerPhaseMove)
107129
}
130+
m.pointerPhase = embedder.PointerPhaseMove
131+
}
108132

109-
if action == glfw.Release {
110-
m.sendPointerEvent(window, embedder.PointerPhaseUp, x, y)
133+
if action == glfw.Release {
134+
m.pointerButton ^= buttons
135+
// If all button are released then m.pointerButton is cleared
136+
if m.pointerButton == 0 {
137+
m.sendPointerEventButton(window, embedder.PointerPhaseUp)
111138
m.pointerPhase = embedder.PointerPhaseHover
139+
} else {
140+
// if any other buttons are still pressed when one button is released
141+
// the engine is expecting a Move phase instead of a Up phase.
142+
m.sendPointerEventButton(window, embedder.PointerPhaseMove)
112143
}
113144
}
114145
}
115146

147+
func (m *windowManager) glfwMouseButtonCallback(window *glfw.Window, key glfw.MouseButton, action glfw.Action, mods glfw.ModifierKey) {
148+
switch key {
149+
case glfw.MouseButtonLeft:
150+
m.handleButtonPhase(window, action, embedder.PointerButtonMousePrimary)
151+
case glfw.MouseButtonRight:
152+
m.handleButtonPhase(window, action, embedder.PointerButtonMouseSecondary)
153+
case glfw.MouseButtonMiddle:
154+
m.handleButtonPhase(window, action, embedder.PointerButtonMouseMiddle)
155+
default:
156+
m.handleButtonPhase(window, action, 1<<uint(key))
157+
}
158+
}
159+
116160
func (m *windowManager) glfwScrollCallback(window *glfw.Window, xoff float64, yoff float64) {
117161
const scrollModifier = -50
118162
m.sendPointerEventScroll(window, xoff*scrollModifier, yoff*scrollModifier)

0 commit comments

Comments
 (0)