From 6d5fd26503a9b48e2ebb910da5d78c6eba3c5c97 Mon Sep 17 00:00:00 2001 From: zhuyifei Date: Wed, 17 Apr 2024 15:22:47 +0800 Subject: [PATCH 1/4] [WIP]feat: support w3c deviceOrientationEvent - add device orientation Event in bridge --- bridge/CMakeLists.txt | 3 + bridge/bindings/qjs/binding_initializer.cc | 2 + bridge/bindings/qjs/wrapper_type_info.h | 1 + bridge/core/dom/events/event.cc | 4 ++ bridge/core/dom/events/event.h | 1 + bridge/core/events/dart_created_events.json5 | 1 + bridge/core/events/deviceorientation_event.cc | 66 +++++++++++++++++++ .../core/events/deviceorientation_event.d.ts | 11 ++++ bridge/core/events/deviceorientation_event.h | 55 ++++++++++++++++ .../events/deviceorientation_event_init.d.ts | 10 +++ bridge/core/events/event_type_names.json5 | 1 + webf/lib/src/dom/event.dart | 25 +++++++ 12 files changed, 180 insertions(+) create mode 100644 bridge/core/events/deviceorientation_event.cc create mode 100644 bridge/core/events/deviceorientation_event.d.ts create mode 100644 bridge/core/events/deviceorientation_event.h create mode 100644 bridge/core/events/deviceorientation_event_init.d.ts diff --git a/bridge/CMakeLists.txt b/bridge/CMakeLists.txt index 9be240c44b..02ebde6e93 100644 --- a/bridge/CMakeLists.txt +++ b/bridge/CMakeLists.txt @@ -337,6 +337,7 @@ if ($ENV{WEBF_JS_ENGINE} MATCHES "quickjs") core/events/message_event.cc core/events/animation_event.cc core/events/close_event.cc + core/events/deviceorientation_event.cc core/events/ui_event.cc core/events/focus_event.cc core/events/gesture_event.cc @@ -431,6 +432,8 @@ if ($ENV{WEBF_JS_ENGINE} MATCHES "quickjs") out/qjs_hashchange_event.cc out/qjs_hashchange_event_init.cc out/qjs_gesture_event_init.cc + out/qjs_deviceorientation_event.cc + out/qjs_deviceorientation_event_init.cc out/qjs_intersection_change_event.cc out/qjs_intersection_change_event_init.cc out/qjs_touch.cc diff --git a/bridge/bindings/qjs/binding_initializer.cc b/bridge/bindings/qjs/binding_initializer.cc index 8302f58453..64b2dfd526 100644 --- a/bridge/bindings/qjs/binding_initializer.cc +++ b/bridge/bindings/qjs/binding_initializer.cc @@ -33,6 +33,7 @@ #include "qjs_event_target.h" #include "qjs_focus_event.h" #include "qjs_gesture_event.h" +#include "qjs_deviceorientation_event.h" #include "qjs_hashchange_event.h" #include "qjs_html_all_collection.h" #include "qjs_html_anchor_element.h" @@ -120,6 +121,7 @@ void InstallBindings(ExecutingContext* context) { QJSFocusEvent::Install(context); QJSGestureEvent::Install(context); QJSHashchangeEvent::Install(context); + QJSDeviceorientationEvent::Install(context); QJSInputEvent::Install(context); QJSCustomEvent::Install(context); QJSMouseEvent::Install(context); diff --git a/bridge/bindings/qjs/wrapper_type_info.h b/bridge/bindings/qjs/wrapper_type_info.h index a77603ecfc..1f1828311d 100644 --- a/bridge/bindings/qjs/wrapper_type_info.h +++ b/bridge/bindings/qjs/wrapper_type_info.h @@ -33,6 +33,7 @@ enum { JS_CLASS_FOCUS_EVENT, JS_CLASS_GESTURE_EVENT, JS_CLASS_HASHCHANGE_EVENT, + JS_CLASS_DEVICEORIENTATION_EVENT, JS_CLASS_POP_STATE_EVENT, JS_CLASS_INTERSECTION_CHANGE_EVENT, JS_CLASS_KEYBOARD_EVENT, diff --git a/bridge/core/dom/events/event.cc b/bridge/core/dom/events/event.cc index 7b6ef8c407..0bbd7cc001 100644 --- a/bridge/core/dom/events/event.cc +++ b/bridge/core/dom/events/event.cc @@ -306,6 +306,10 @@ bool Event::IsHashChangeEvent() const { return false; } +bool Event::IsDeviceorientationEvent() const { + return false; +} + bool Event::IsIntersectionchangeEvent() const { return false; } diff --git a/bridge/core/dom/events/event.h b/bridge/core/dom/events/event.h index c5856cf7c3..9fa5f8de37 100644 --- a/bridge/core/dom/events/event.h +++ b/bridge/core/dom/events/event.h @@ -172,6 +172,7 @@ class Event : public ScriptWrappable { virtual bool IsPopstateEvent() const; virtual bool IsIntersectionchangeEvent() const; virtual bool IsHashChangeEvent() const; + virtual bool IsDeviceorientationEvent() const; // Drag events are a subset of mouse events. virtual bool IsDragEvent() const; diff --git a/bridge/core/events/dart_created_events.json5 b/bridge/core/events/dart_created_events.json5 index 0bce923918..abb3074b7c 100644 --- a/bridge/core/events/dart_created_events.json5 +++ b/bridge/core/events/dart_created_events.json5 @@ -38,6 +38,7 @@ ] }, "hashchange", + "deviceorientation", "input", { "class": "FocusEvent", diff --git a/bridge/core/events/deviceorientation_event.cc b/bridge/core/events/deviceorientation_event.cc new file mode 100644 index 0000000000..e63ce0ba39 --- /dev/null +++ b/bridge/core/events/deviceorientation_event.cc @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2024-present The WebF authors. All rights reserved. + */ + +#include "deviceorientation_event.h" +#include "qjs_device_orientation_event.h" + +namespace webf { + +DeviceorientationEvent* DeviceorientationEvent::Create(ExecutingContext* context, + const AtomicString& type, + ExceptionState& exception_state) { + return MakeGarbageCollected(context, type, exception_state); +} + +DeviceorientationEvent* DeviceorientationEvent::Create(ExecutingContext* context, + const AtomicString& type, + const std::shared_ptr& initializer, + ExceptionState& exception_state) { + return MakeGarbageCollected(context, type, initializer, exception_state); +} + +DeviceorientationEvent::DeviceorientationEvent(ExecutingContext* context, const AtomicString& type, ExceptionState& exception_state) + : Event(context, type) {} + +DeviceorientationEvent::DeviceorientationEvent(ExecutingContext* context, + const AtomicString& type, + const std::shared_ptr& initializer, + ExceptionState& exception_state) + : Event(context, type), + absolute_(initializer->hasAbsolute ? initializer->absolute()), + alpha_(initializer->hasAlpha() ? initializer->alpha() : 0.0), + beta_(initializer->hasBeta() ? initializer->beta() : 0.0), + gamma_(initializer->hasGamma() ? initializer->gamma() : 0.0) {} + +DeviceorientationEvent::DeviceorientationEvent(ExecutingContext* context, + const AtomicString& type, + NativeDeviceorientationEvent* native_orientation_event) + : Event(context, type, &native_orientation_event->native_event), + absolute_(native_orientation_event->absolute), + alpha_(native_orientation_event->alpha), + beta_(native_orientation_event->beta), + gamma_(native_orientation_event->gamma) { +} + +bool DeviceorientationEvent::IsDeviceorientationEvent() const { + return true; +} + +bool DeviceorientationEvent::absolute() const { + return absolute_; +} + +double DeviceorientationEvent::alpha() const { + return alpha_; +} + +double DeviceorientationEvent::beta() const { + return beta_; +} + +double DeviceorientationEvent::gamma() const { + return gamma_; +} + +} // namespace webf diff --git a/bridge/core/events/deviceorientation_event.d.ts b/bridge/core/events/deviceorientation_event.d.ts new file mode 100644 index 0000000000..cd8f162eb6 --- /dev/null +++ b/bridge/core/events/deviceorientation_event.d.ts @@ -0,0 +1,11 @@ +import {Event} from "../dom/events/event"; +import {DeviceorientationEventInit} from "./device_orientation_event_init"; + +interface DeviceorientationEvent extends Event { + readonly absolute: boolean; + readonly alpha: number; + readonly beta: number; + readonly gamma: number; + [key: string]: any; + new(type: string, init?: DeviceorientationEventInit): DeviceorientationEvent; +} diff --git a/bridge/core/events/deviceorientation_event.h b/bridge/core/events/deviceorientation_event.h new file mode 100644 index 0000000000..cf3e3ce6fb --- /dev/null +++ b/bridge/core/events/deviceorientation_event.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2024-present The WebF authors. All rights reserved. + */ + +#ifndef BRIDGE_CORE_EVENTS_GESTURE_EVENT_H_ +#define BRIDGE_CORE_EVENTS_GESTURE_EVENT_H_ + +#include "bindings/qjs/dictionary_base.h" +#include "bindings/qjs/source_location.h" +#include "core/dom/events/event.h" +#include "qjs_device_orientation_event_init.h" + +namespace webf { + +struct NativeDeviceorientationEvent; + +class DeviceorientationEvent : public Event { + DEFINE_WRAPPERTYPEINFO(); + + public: + using ImplType = DeviceorientationEvent*; + + static DeviceorientationEvent* Create(ExecutingContext* context, const AtomicString& type, ExceptionState& exception_state); + + static DeviceorientationEvent* Create(ExecutingContext* context, + const AtomicString& type, + const std::shared_ptr& initializer, + ExceptionState& exception_state); + + explicit DeviceorientationEvent(ExecutingContext* context, const AtomicString& type, ExceptionState& exception_state); + + explicit DeviceorientationEvent(ExecutingContext* context, + const AtomicString& type, + const std::shared_ptr& initializer, + ExceptionState& exception_state); + + explicit DeviceorientationEvent(ExecutingContext* context, const AtomicString& type, NativeDeviceorientationEvent* native_orientation_event); + + bool absolute() const; + double alpha() const; + double beta() const; + double gamma() const; + + bool IsDeviceorientationEvent() const override; + + private: + bool absolute_; + double alpha_; + double beta_; + double gamma_; +}; + +} // namespace webf + +#endif // BRIDGE_CORE_EVENTS_GESTURE_EVENT_H_ diff --git a/bridge/core/events/deviceorientation_event_init.d.ts b/bridge/core/events/deviceorientation_event_init.d.ts new file mode 100644 index 0000000000..d63fb59f9e --- /dev/null +++ b/bridge/core/events/deviceorientation_event_init.d.ts @@ -0,0 +1,10 @@ +import { EventInit } from "../dom/events/event_init"; + +// @ts-ignore +@Dictionary() +export interface DeviceorientationEventInit extends EventInit { + absolute?: boolean; + alpha?: number; + beta?: number; + gamma?: number; +} diff --git a/bridge/core/events/event_type_names.json5 b/bridge/core/events/event_type_names.json5 index 4185ec5f53..b3f9c2274a 100644 --- a/bridge/core/events/event_type_names.json5 +++ b/bridge/core/events/event_type_names.json5 @@ -224,6 +224,7 @@ "wheel", "zoom", "intersectionchange", + "deviceorientation", "gcopen" ] } diff --git a/webf/lib/src/dom/event.dart b/webf/lib/src/dom/event.dart index 35c065f6e4..5cf7848cd7 100644 --- a/webf/lib/src/dom/event.dart +++ b/webf/lib/src/dom/event.dart @@ -393,6 +393,31 @@ class MouseEvent extends UIEvent { } } +class DeviceOrientationEvent extends Event { + DeviceOrientationEvent(this.alpha, this.beta, this.gamma) : super(EVENT_DEVICE_ORIENTATION); + + final bool absolute = true; + final double alpha; + final double beta; + final double gamma; + + @override + Pointer toRaw([int extraLength = 0, bool isCustomEvent = false]) { + List methods = [ + doubleToUint64(alpha), + doubleToUint64(beta), + doubleToUint64(gamma) + ]; + Pointer rawEvent = super.toRaw(methods.length).cast(); + int currentStructSize = rawEvent.ref.length + methods.length; + Uint64List bytes = rawEvent.ref.bytes.asTypedList(currentStructSize); + bytes.setAll(rawEvent.ref.length, methods); + rawEvent.ref.length = currentStructSize; + + return rawEvent; + } +} + /// reference: https://developer.mozilla.org/en-US/docs/Web/API/GestureEvent class GestureEvent extends Event { final String state; From 7789f096703d7d5626b7647e7a46db5898788308 Mon Sep 17 00:00:00 2001 From: andycall Date: Thu, 18 Apr 2024 17:01:23 +0800 Subject: [PATCH 2/4] fix: fix compile issue. --- bridge/core/events/deviceorientation_event.cc | 5 +++-- bridge/core/events/deviceorientation_event.d.ts | 2 +- bridge/core/events/deviceorientation_event.h | 9 +++++---- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/bridge/core/events/deviceorientation_event.cc b/bridge/core/events/deviceorientation_event.cc index e63ce0ba39..40d2f61087 100644 --- a/bridge/core/events/deviceorientation_event.cc +++ b/bridge/core/events/deviceorientation_event.cc @@ -3,7 +3,8 @@ */ #include "deviceorientation_event.h" -#include "qjs_device_orientation_event.h" +#include "qjs_deviceorientation_event.h" +#include "qjs_deviceorientation_event_init.h" namespace webf { @@ -28,7 +29,7 @@ DeviceorientationEvent::DeviceorientationEvent(ExecutingContext* context, const std::shared_ptr& initializer, ExceptionState& exception_state) : Event(context, type), - absolute_(initializer->hasAbsolute ? initializer->absolute()), + absolute_(initializer->hasAbsolute() ? initializer->absolute() : 0.0), alpha_(initializer->hasAlpha() ? initializer->alpha() : 0.0), beta_(initializer->hasBeta() ? initializer->beta() : 0.0), gamma_(initializer->hasGamma() ? initializer->gamma() : 0.0) {} diff --git a/bridge/core/events/deviceorientation_event.d.ts b/bridge/core/events/deviceorientation_event.d.ts index cd8f162eb6..56bb355fa9 100644 --- a/bridge/core/events/deviceorientation_event.d.ts +++ b/bridge/core/events/deviceorientation_event.d.ts @@ -1,5 +1,5 @@ import {Event} from "../dom/events/event"; -import {DeviceorientationEventInit} from "./device_orientation_event_init"; +import {DeviceorientationEventInit} from "./deviceorientation_event_init"; interface DeviceorientationEvent extends Event { readonly absolute: boolean; diff --git a/bridge/core/events/deviceorientation_event.h b/bridge/core/events/deviceorientation_event.h index cf3e3ce6fb..b2166c1c42 100644 --- a/bridge/core/events/deviceorientation_event.h +++ b/bridge/core/events/deviceorientation_event.h @@ -2,17 +2,18 @@ * Copyright (C) 2024-present The WebF authors. All rights reserved. */ -#ifndef BRIDGE_CORE_EVENTS_GESTURE_EVENT_H_ -#define BRIDGE_CORE_EVENTS_GESTURE_EVENT_H_ +#ifndef BRIDGE_CORE_EVENTS_DEVICE_ORIENTATION_EVENT_H_ +#define BRIDGE_CORE_EVENTS_DEVICE_ORIENTATION_EVENT_H_ #include "bindings/qjs/dictionary_base.h" #include "bindings/qjs/source_location.h" #include "core/dom/events/event.h" -#include "qjs_device_orientation_event_init.h" +#include "qjs_deviceorientation_event_init.h" namespace webf { struct NativeDeviceorientationEvent; +class DeviceorientationEventInit; class DeviceorientationEvent : public Event { DEFINE_WRAPPERTYPEINFO(); @@ -52,4 +53,4 @@ class DeviceorientationEvent : public Event { } // namespace webf -#endif // BRIDGE_CORE_EVENTS_GESTURE_EVENT_H_ +#endif // BRIDGE_CORE_EVENTS_DEVICE_ORIENTATION_EVENT_H_ From 56820d389db633423b5b63b1b02d1f9af113e585 Mon Sep 17 00:00:00 2001 From: zhuyifei Date: Fri, 19 Apr 2024 10:16:40 +0800 Subject: [PATCH 3/4] feat: implement this device orientation Event on the dart side --- webf/lib/src/dom/event.dart | 1 + webf/lib/src/dom/window.dart | 48 ++++++++++++++++++++++++++++++++++++ webf/pubspec.yaml | 1 + 3 files changed, 50 insertions(+) diff --git a/webf/lib/src/dom/event.dart b/webf/lib/src/dom/event.dart index 5cf7848cd7..89a84f4786 100644 --- a/webf/lib/src/dom/event.dart +++ b/webf/lib/src/dom/event.dart @@ -69,6 +69,7 @@ const String EVENT_STATE_START = 'start'; const String EVENT_STATE_UPDATE = 'update'; const String EVENT_STATE_END = 'end'; const String EVENT_STATE_CANCEL = 'cancel'; +const String EVENT_DEVICE_ORIENTATION = 'deviceorientation'; mixin ElementEventMixin on ElementBase { AppearEventType _prevAppearState = AppearEventType.none; diff --git a/webf/lib/src/dom/window.dart b/webf/lib/src/dom/window.dart index f86f92b32f..ad0ee57f2a 100644 --- a/webf/lib/src/dom/window.dart +++ b/webf/lib/src/dom/window.dart @@ -2,8 +2,11 @@ * Copyright (C) 2019-2022 The Kraken authors. All rights reserved. * Copyright (C) 2022-present The WebF authors. All rights reserved. */ +import 'dart:math' as math; +import 'dart:async'; import 'dart:ui'; +import 'package:sensors_plus/sensors_plus.dart'; import 'package:webf/bridge.dart'; import 'package:webf/dom.dart'; import 'package:webf/foundation.dart'; @@ -117,6 +120,9 @@ class Window extends EventTarget { // Fired at the Document or element when the viewport or element is scrolled, respectively. document.documentElement?.addEventListener(eventType, handler, addEventListenerOptions: addEventListenerOptions); break; + case EVENT_DEVICE_ORIENTATION: + _registerGyroscope(); + break; } } @@ -127,6 +133,9 @@ class Window extends EventTarget { case EVENT_SCROLL: document.documentElement?.removeEventListener(eventType, handler); break; + case EVENT_DEVICE_ORIENTATION: + _unRegisterGyroscope(false); + break; } } @@ -135,4 +144,43 @@ class Window extends EventTarget { void focus() { // TODO } + + StreamSubscription? _gyroscopeStream; + void _registerGyroscope() { + _gyroscopeStream ??= gyroscopeEventStream().listen((GyroscopeEvent event) { + dispatchDeviceOrientationEvent(event.x, event.y, event.z); + }, + cancelOnError: true, + ); + } + + void _unRegisterGyroscope(bool dispose) { + if (dispose || !hasEventListener(EVENT_DEVICE_ORIENTATION)) { + _gyroscopeStream?.cancel(); + _gyroscopeStream = null; + } + } + + /// Convert gyroscope data obtained in Flutter into rotation angle in the Web + /// In the w3c standard: + /// alpha: A number representing the motion of the device around the z axis, express in degrees with values ranging from 0 (inclusive) to 360 (exclusive). + /// beta: A number representing the motion of the device around the x axis, expressed in degrees with values ranging from -180 (inclusive) to 180 (exclusive). + /// gamma: A number representing the motion of the device around the y axis, expressed in degrees with values ranging from -90 (inclusive) to 90 (exclusive). + void dispatchDeviceOrientationEvent(x, y, z) { + var xAxisAngle= math.atan2(y, z) * (180 / math.pi); // Angle of rotation around the X-axis + var yAxisAngle = math.atan2(-x, math.sqrt(y * y + z * z)) * (180 / math.pi); // Rotation angle around Y axis + var zAxisAngle = math.atan2(y, z) * (180 / math.pi); // Rotation angle around Z axis + var alpha = zAxisAngle + 180; + var beta = xAxisAngle; + var gamma = yAxisAngle; + if (hasEventListener(EVENT_DEVICE_ORIENTATION)) { + dispatchEvent(DeviceOrientationEvent(alpha, beta, gamma)); + } + } + + @override + void dispose() async { + _unRegisterGyroscope(true); + super.dispose(); + } } diff --git a/webf/pubspec.yaml b/webf/pubspec.yaml index 293ce0711f..cb866b35e1 100644 --- a/webf/pubspec.yaml +++ b/webf/pubspec.yaml @@ -25,6 +25,7 @@ dependencies: shared_preferences: 2.2.0 # No AndroidX used. archive: ^3.3.7 # Pure dart module. web_socket_channel: ^2.2.0 + sensors_plus: ^4.0.2 dev_dependencies: flutter_test: From a3b4c21784e78723c3c3195693ed7c5a307f4a6e Mon Sep 17 00:00:00 2001 From: zhuyifei Date: Fri, 19 Apr 2024 10:38:38 +0800 Subject: [PATCH 4/4] fix: miss param --- webf/lib/src/dom/event.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/webf/lib/src/dom/event.dart b/webf/lib/src/dom/event.dart index 89a84f4786..ffa9b4ac76 100644 --- a/webf/lib/src/dom/event.dart +++ b/webf/lib/src/dom/event.dart @@ -405,6 +405,7 @@ class DeviceOrientationEvent extends Event { @override Pointer toRaw([int extraLength = 0, bool isCustomEvent = false]) { List methods = [ + absolute ? 1 : 0, doubleToUint64(alpha), doubleToUint64(beta), doubleToUint64(gamma)