Skip to content

Commit a633350

Browse files
committed
Merge branch 'feature/implement-scrolling'
2 parents eae922f + 35139c6 commit a633350

File tree

6 files changed

+189
-32
lines changed

6 files changed

+189
-32
lines changed

application.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -181,8 +181,9 @@ func (a *Application) Run() error {
181181
a.window.SetCharCallback(defaultTextinputPlugin.glfwCharCallback)
182182

183183
a.window.SetCursorEnterCallback(m.glfwCursorEnterCallback)
184-
a.window.SetMouseButtonCallback(m.glfwMouseButtonCallback)
185184
a.window.SetCursorPosCallback(m.glfwCursorPosCallback)
185+
a.window.SetMouseButtonCallback(m.glfwMouseButtonCallback)
186+
a.window.SetScrollCallback(m.glfwScrollCallback)
186187
defer a.engine.Shutdown()
187188

188189
for !a.window.ShouldClose() {

embedder/embedder.go

+26-9
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
package embedder
22

3-
// #include "flutter_embedder.h"
3+
// #include "embedder.h"
44
// FlutterEngineResult runFlutter(void *user_data, FlutterEngine *engine, FlutterProjectArgs * Args,
55
// const char *const * vmArgs, int nVmAgrs);
66
// char** makeCharArray(int size);
77
// void setArrayString(char **a, char *s, int n);
8+
// const int32_t kFlutterSemanticsNodeIdBatchEnd = -1;
9+
// const int32_t kFlutterSemanticsCustomActionIdBatchEnd = -1;
810
import "C"
911
import (
1012
"fmt"
@@ -141,21 +143,36 @@ const (
141143
PointerPhaseHover PointerPhase = C.kHover
142144
)
143145

146+
// PointerSignalKind corresponds to the C.enum describing signal kind of the mouse pointer.
147+
type PointerSignalKind int32
148+
149+
// Values representing the pointer signal kind.
150+
const (
151+
PointerSignalKindNone PointerSignalKind = C.kFlutterPointerSignalKindNone
152+
PointerSignalKindScroll PointerSignalKind = C.kFlutterPointerSignalKindScroll
153+
)
154+
144155
// PointerEvent represents the position and phase of the mouse at a given time.
145156
type PointerEvent struct {
146-
Phase PointerPhase
147-
Timestamp int64
148-
X float64
149-
Y float64
157+
Phase PointerPhase
158+
Timestamp int64
159+
X float64
160+
Y float64
161+
SignalKind PointerSignalKind
162+
ScrollDeltaX float64
163+
ScrollDeltaY float64
150164
}
151165

152166
// SendPointerEvent is used to send an PointerEvent to the Flutter engine.
153167
func (flu *FlutterEngine) SendPointerEvent(event PointerEvent) Result {
154168
cPointerEvent := C.FlutterPointerEvent{
155-
phase: (C.FlutterPointerPhase)(event.Phase),
156-
x: C.double(event.X),
157-
y: C.double(event.Y),
158-
timestamp: C.size_t(event.Timestamp),
169+
phase: (C.FlutterPointerPhase)(event.Phase),
170+
x: C.double(event.X),
171+
y: C.double(event.Y),
172+
timestamp: C.size_t(event.Timestamp),
173+
signal_kind: (C.FlutterPointerSignalKind)(event.SignalKind),
174+
scroll_delta_x: C.double(event.ScrollDeltaX),
175+
scroll_delta_y: C.double(event.ScrollDeltaY),
159176
}
160177
cPointerEvent.struct_size = C.size_t(unsafe.Sizeof(cPointerEvent))
161178

embedder/flutter_embedder.h renamed to embedder/embedder.h

+132-15
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,9 @@ typedef enum {
9898
// A request that the node should be dismissed.
9999
kFlutterSemanticsActionDismiss = 1 << 18,
100100
// Move the cursor forward by one word.
101-
kFlutterSemanticsActionMoveCursorForwardByWordIndex = 1 << 19,
101+
kFlutterSemanticsActionMoveCursorForwardByWord = 1 << 19,
102102
// Move the cursor backward by one word.
103-
kFlutterSemanticsActionMoveCursorBackwardByWordIndex = 1 << 20,
103+
kFlutterSemanticsActionMoveCursorBackwardByWord = 1 << 20,
104104
} FlutterSemanticsAction;
105105

106106
// The set of properties that may be associated with a semantics node.
@@ -277,6 +277,7 @@ typedef struct {
277277
double pixel_ratio;
278278
} FlutterWindowMetricsEvent;
279279

280+
// The phase of the pointer event.
280281
typedef enum {
281282
kCancel,
282283
kUp,
@@ -287,6 +288,12 @@ typedef enum {
287288
kHover,
288289
} FlutterPointerPhase;
289290

291+
// The type of a pointer signal.
292+
typedef enum {
293+
kFlutterPointerSignalKindNone,
294+
kFlutterPointerSignalKindScroll,
295+
} FlutterPointerSignalKind;
296+
290297
typedef struct {
291298
// The size of this struct. Must be sizeof(FlutterPointerEvent).
292299
size_t struct_size;
@@ -297,6 +304,9 @@ typedef struct {
297304
// An optional device identifier. If this is not specified, it is assumed that
298305
// the embedder has no multitouch capability.
299306
int32_t device;
307+
FlutterPointerSignalKind signal_kind;
308+
double scroll_delta_x;
309+
double scroll_delta_y;
300310
} FlutterPointerEvent;
301311

302312
struct _FlutterPlatformMessageResponseHandle;
@@ -333,7 +343,8 @@ typedef struct {
333343

334344
// |FlutterSemanticsNode| ID used as a sentinel to signal the end of a batch of
335345
// semantics node updates.
336-
// const int32_t kFlutterSemanticsNodeIdBatchEnd = -1;
346+
FLUTTER_EXPORT
347+
extern const int32_t kFlutterSemanticsNodeIdBatchEnd;
337348

338349
// A node that represents some semantic data.
339350
//
@@ -404,7 +415,8 @@ typedef struct {
404415

405416
// |FlutterSemanticsCustomAction| ID used as a sentinel to signal the end of a
406417
// batch of semantics custom action updates.
407-
// const int32_t kFlutterSemanticsCustomActionIdBatchEnd = -1;
418+
FLUTTER_EXPORT
419+
extern const int32_t kFlutterSemanticsCustomActionIdBatchEnd;
408420

409421
// A custom semantics action, or action override.
410422
//
@@ -437,6 +449,52 @@ typedef void (*FlutterUpdateSemanticsCustomActionCallback)(
437449
const FlutterSemanticsCustomAction* /* semantics custom action */,
438450
void* /* user data */);
439451

452+
typedef struct _FlutterTaskRunner* FlutterTaskRunner;
453+
454+
typedef struct {
455+
FlutterTaskRunner runner;
456+
uint64_t task;
457+
} FlutterTask;
458+
459+
typedef void (*FlutterTaskRunnerPostTaskCallback)(
460+
FlutterTask /* task */,
461+
uint64_t /* target time nanos */,
462+
void* /* user data */);
463+
464+
// An interface used by the Flutter engine to execute tasks at the target time
465+
// on a specified thread. There should be a 1-1 relationship between a thread
466+
// and a task runner. It is undefined behavior to run a task on a thread that is
467+
// not associated with its task runner.
468+
typedef struct {
469+
// The size of this struct. Must be sizeof(FlutterTaskRunnerDescription).
470+
size_t struct_size;
471+
void* user_data;
472+
// May be called from any thread. Should return true if tasks posted on the
473+
// calling thread will be run on that same thread.
474+
//
475+
// This field is required.
476+
BoolCallback runs_task_on_current_thread_callback;
477+
// May be called from any thread. The given task should be executed by the
478+
// embedder on the thread associated with that task runner by calling
479+
// |FlutterEngineRunTask| at the given target time. The system monotonic clock
480+
// should be used for the target time. The target time is the absolute time
481+
// from epoch (NOT a delta) at which the task must be returned back to the
482+
// engine on the correct thread. If the embedder needs to calculate a delta,
483+
// |FlutterEngineGetCurrentTime| may be called and the difference used as the
484+
// delta.
485+
//
486+
// This field is required.
487+
FlutterTaskRunnerPostTaskCallback post_task_callback;
488+
} FlutterTaskRunnerDescription;
489+
490+
typedef struct {
491+
// The size of this struct. Must be sizeof(FlutterCustomTaskRunners).
492+
size_t struct_size;
493+
// Specify the task runner for the thread on which the |FlutterEngineRun| call
494+
// is made.
495+
const FlutterTaskRunnerDescription* platform_task_runner;
496+
} FlutterCustomTaskRunners;
497+
440498
typedef struct {
441499
// The size of this struct. Must be sizeof(FlutterProjectArgs).
442500
size_t struct_size;
@@ -539,14 +597,34 @@ typedef struct {
539597
// Flutter application (such as compiled shader programs used by Skia).
540598
// This is optional. The string must be NULL terminated.
541599
const char* persistent_cache_path;
542-
// A callback that gets invoked by the engine when it attempts to wait for
543-
// a platform vsync event. The engine will give the platform a baton that
544-
// needs to be returned back to the engine via |FlutterEngineOnVsync|. All
545-
// vsync operations must occur on the thread that made the call to
546-
// |FlutterEngineRun|. All batons must be retured to the engine before
547-
// initializing a |FlutterEngineShutdown|. Not doing the same will result in a
548-
// memory leak.
600+
601+
// If true, we'll only read the existing cache, but not write new ones.
602+
bool is_persistent_cache_read_only;
603+
604+
// A callback that gets invoked by the engine when it attempts to wait for a
605+
// platform vsync event. The engine will give the platform a baton that needs
606+
// to be returned back to the engine via |FlutterEngineOnVsync|. All batons
607+
// must be retured to the engine before initializing a
608+
// |FlutterEngineShutdown|. Not doing the same will result in a memory leak.
609+
// While the call to |FlutterEngineOnVsync| must occur on the thread that made
610+
// the call to |FlutterEngineRun|, the engine will make this callback on an
611+
// internal engine-managed thread. If the components accessed on the embedder
612+
// are not thread safe, the appropriate re-threading must be done.
549613
VsyncCallback vsync_callback;
614+
615+
// The name of a custom Dart entrypoint. This is optional and specifying a
616+
// null or empty entrypoint makes the engine look for a method named "main" in
617+
// the root library of the application.
618+
//
619+
// Care must be taken to ensure that the custom entrypoint is not tree-shaken
620+
// away. Usually, this is done using the `@pragma('vm:entry-point')`
621+
// decoration.
622+
const char* custom_dart_entrypoint;
623+
624+
// Typically the Flutter engine create and manages its internal threads. This
625+
// optional argument allows for the specification of task runner interfaces to
626+
// event loops managed by the embedder on threads it creates.
627+
const FlutterCustomTaskRunners* custom_task_runners;
550628
} FlutterProjectArgs;
551629

552630
FLUTTER_EXPORT
@@ -635,7 +713,21 @@ FlutterEngineResult FlutterEngineDispatchSemanticsAction(
635713
size_t data_length);
636714

637715
// Notify the engine that a vsync event occurred. A baton passed to the
638-
// platform via the vsync callback must be returned.
716+
// platform via the vsync callback must be returned. This call must be made on
717+
// the thread on which the call to |FlutterEngineRun| was made.
718+
//
719+
// |frame_start_time_nanos| is the point at which the vsync event occurred or
720+
// will occur. If the time point is in the future, the engine will wait till
721+
// that point to begin its frame workload. The system monotonic clock is used as
722+
// the timebase.
723+
//
724+
// |frame_target_time_nanos| is the point at which the embedder anticipates the
725+
// next vsync to occur. This is a hint the engine uses to schedule Dart VM
726+
// garbage collection in periods in which the various threads are most likely to
727+
// be idle. For example, for a 60Hz display, embedders should add 16.6 * 1e6 to
728+
// the frame time field. The system monotonic clock is used as the timebase.
729+
//
730+
// That frame timepoints are in nanoseconds.
639731
FLUTTER_EXPORT
640732
FlutterEngineResult FlutterEngineOnVsync(FlutterEngine engine,
641733
intptr_t baton,
@@ -646,24 +738,49 @@ FlutterEngineResult FlutterEngineOnVsync(FlutterEngine engine,
646738
// the timeline is unavailable or disabled, this has no effect. Must be
647739
// balanced with an duration end event (via
648740
// |FlutterEngineTraceEventDurationEnd|) with the same name on the same thread.
649-
// Can be called on any thread.
741+
// Can be called on any thread. Strings passed into the function will NOT be
742+
// copied when added to the timeline. Only string literals may be passed in.
650743
FLUTTER_EXPORT
651744
void FlutterEngineTraceEventDurationBegin(const char* name);
652745

653746
// A profiling utility. Logs a trace duration end event to the timeline. If the
654747
// timeline is unavailable or disabled, this has no effect. This call must be
655748
// preceded by a trace duration begin call (via
656749
// |FlutterEngineTraceEventDurationBegin|) with the same name on the same
657-
// thread. Can be called on any thread.
750+
// thread. Can be called on any thread. Strings passed into the function will
751+
// NOT be copied when added to the timeline. Only string literals may be passed
752+
// in.
658753
FLUTTER_EXPORT
659754
void FlutterEngineTraceEventDurationEnd(const char* name);
660755

661756
// A profiling utility. Logs a trace duration instant event to the timeline. If
662757
// the timeline is unavailable or disabled, this has no effect. Can be called
663-
// on any thread.
758+
// on any thread. Strings passed into the function will NOT be copied when added
759+
// to the timeline. Only string literals may be passed in.
664760
FLUTTER_EXPORT
665761
void FlutterEngineTraceEventInstant(const char* name);
666762

763+
// Posts a task onto the Flutter render thread. Typically, this may be called
764+
// from any thread as long as a |FlutterEngineShutdown| on the specific engine
765+
// has not already been initiated.
766+
FLUTTER_EXPORT
767+
FlutterEngineResult FlutterEnginePostRenderThreadTask(FlutterEngine engine,
768+
VoidCallback callback,
769+
void* callback_data);
770+
771+
// Get the current time in nanoseconds from the clock used by the flutter
772+
// engine. This is the system monotonic clock.
773+
FLUTTER_EXPORT
774+
uint64_t FlutterEngineGetCurrentTime();
775+
776+
// Inform the engine to run the specified task. This task has been given to
777+
// the engine via the |FlutterTaskRunnerDescription.post_task_callback|. This
778+
// call must only be made at the target time specified in that callback. Running
779+
// the task before that time is undefined behavior.
780+
FLUTTER_EXPORT
781+
FlutterEngineResult FlutterEngineRunTask(FlutterEngine engine,
782+
const FlutterTask* task);
783+
667784
#if defined(__cplusplus)
668785
} // extern "C"
669786
#endif

embedder/embedder_helper.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
#include <stdlib.h>
33

4-
#include "flutter_embedder.h"
4+
#include "embedder.h"
55

66
// C proxy definitions. These are implemented in Go.
77
bool proxy_make_current(void *user_data);

embedder/embedder_proxy.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package embedder
22

3-
// #include "flutter_embedder.h"
3+
// #include "embedder.h"
44
import "C"
55
import (
66
"unsafe"

glfw.go

+27-5
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,6 @@ func newWindowManager() *windowManager {
3232
}
3333
}
3434

35-
// GLFW callbacks to the Flutter Engine
36-
func (m *windowManager) glfwCursorPosCallback(window *glfw.Window, x, y float64) {
37-
m.sendPointerEvent(window, m.pointerPhase, x, y)
38-
}
39-
4035
func (m *windowManager) sendPointerEvent(window *glfw.Window, phase embedder.PointerPhase, x, y float64) {
4136
// synthesize an PointerPhaseAdd if the pointer isn't already added
4237
if !m.pointerCurrentlyAdded && phase != embedder.PointerPhaseAdd {
@@ -69,6 +64,24 @@ func (m *windowManager) sendPointerEvent(window *glfw.Window, phase embedder.Poi
6964
}
7065
}
7166

67+
func (m *windowManager) sendPointerEventScroll(window *glfw.Window, xDelta, yDelta float64) {
68+
x, y := window.GetCursorPos()
69+
event := embedder.PointerEvent{
70+
Phase: m.pointerPhase,
71+
X: x * m.pixelsPerScreenCoordinate,
72+
Y: y * m.pixelsPerScreenCoordinate,
73+
Timestamp: time.Now().UnixNano() / int64(time.Millisecond),
74+
SignalKind: embedder.PointerSignalKindScroll,
75+
ScrollDeltaX: xDelta,
76+
ScrollDeltaY: yDelta,
77+
}
78+
79+
flutterEnginePointer := *(*uintptr)(window.GetUserPointer())
80+
flutterEngine := (*embedder.FlutterEngine)(unsafe.Pointer(flutterEnginePointer))
81+
82+
flutterEngine.SendPointerEvent(event)
83+
}
84+
7285
func (m *windowManager) glfwCursorEnterCallback(window *glfw.Window, entered bool) {
7386
x, y := window.GetCursorPos()
7487
if entered {
@@ -79,6 +92,10 @@ func (m *windowManager) glfwCursorEnterCallback(window *glfw.Window, entered boo
7992
}
8093
}
8194

95+
func (m *windowManager) glfwCursorPosCallback(window *glfw.Window, x, y float64) {
96+
m.sendPointerEvent(window, m.pointerPhase, x, y)
97+
}
98+
8299
func (m *windowManager) glfwMouseButtonCallback(window *glfw.Window, key glfw.MouseButton, action glfw.Action, mods glfw.ModifierKey) {
83100
if key == glfw.MouseButton1 {
84101
x, y := window.GetCursorPos()
@@ -95,6 +112,11 @@ func (m *windowManager) glfwMouseButtonCallback(window *glfw.Window, key glfw.Mo
95112
}
96113
}
97114

115+
func (m *windowManager) glfwScrollCallback(window *glfw.Window, xoff float64, yoff float64) {
116+
const scrollModifier = -50
117+
m.sendPointerEventScroll(window, xoff*scrollModifier, yoff*scrollModifier)
118+
}
119+
98120
// glfwRefreshCallback is called when the window needs a reresh, this
99121
// can occur when the window is resized, was covered by another window, etc.
100122
// When forcedPixelratio is zero, the forcedPixelratio communicated to the

0 commit comments

Comments
 (0)