Skip to content

Commit ecc24a7

Browse files
authored
Fabric view props & events (#2364)
react-native-macos extends BaseViewProps and BaseViewEventEmitter with additional functionality (e.g., validKeysUp, focusable, onMouseEnter, etc.). This set of changes unblocks prop parsing and event capabilities for desktop specific behaviors in RCTViewComponentView.
1 parent a3f5c10 commit ecc24a7

File tree

9 files changed

+774
-0
lines changed

9 files changed

+774
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
#pragma once
5+
6+
#include <react/renderer/components/view/BaseTouch.h>
7+
8+
namespace facebook::react {
9+
10+
class HostPlatformTouch : public BaseTouch {
11+
public:
12+
/*
13+
* The button indicating which pointer is used.
14+
*/
15+
int button;
16+
17+
/*
18+
* The pointer type indicating the device type (e.g., mouse, pen, touch)
19+
*/
20+
std::string pointerType;
21+
22+
/*
23+
* A flag indicating if the alt key is pressed.
24+
*/
25+
bool altKey;
26+
27+
/*
28+
* A flag indicating if the control key is pressed.
29+
*/
30+
bool ctrlKey;
31+
32+
/*
33+
* A flag indicating if the shift key is pressed.
34+
*/
35+
bool shiftKey;
36+
37+
/*
38+
* A flag indicating if the shift key is pressed.
39+
*/
40+
bool metaKey;
41+
42+
/*
43+
* Windows-specific timestamp field. We can't use the shared BaseTouch
44+
* timestamp field beacuse it's a float and lacks sufficient resolution.
45+
*/
46+
double pointerTimestamp;
47+
};
48+
49+
inline static void setTouchPayloadOnObject(
50+
jsi::Object& object,
51+
jsi::Runtime& runtime,
52+
const HostPlatformTouch& touch) {
53+
object.setProperty(runtime, "locationX", touch.offsetPoint.x);
54+
object.setProperty(runtime, "locationY", touch.offsetPoint.y);
55+
object.setProperty(runtime, "pageX", touch.pagePoint.x);
56+
object.setProperty(runtime, "pageY", touch.pagePoint.y);
57+
object.setProperty(runtime, "screenX", touch.screenPoint.x);
58+
object.setProperty(runtime, "screenY", touch.screenPoint.y);
59+
object.setProperty(runtime, "identifier", touch.identifier);
60+
object.setProperty(runtime, "target", touch.target);
61+
object.setProperty(runtime, "timestamp", touch.pointerTimestamp);
62+
object.setProperty(runtime, "force", touch.force);
63+
object.setProperty(runtime, "button", touch.button);
64+
object.setProperty(runtime, "altKey", touch.altKey);
65+
object.setProperty(runtime, "ctrlKey", touch.ctrlKey);
66+
object.setProperty(runtime, "shiftKey", touch.shiftKey);
67+
object.setProperty(runtime, "metaKey", touch.metaKey);
68+
};
69+
70+
} // namespace facebook::react
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#include "HostPlatformViewEventEmitter.h"
9+
10+
namespace facebook::react {
11+
12+
#pragma mark - Keyboard Events
13+
14+
static jsi::Value keyEventPayload(
15+
jsi::Runtime& runtime,
16+
const KeyEvent& event) {
17+
auto payload = jsi::Object(runtime);
18+
payload.setProperty(
19+
runtime, "key", jsi::String::createFromUtf8(runtime, event.key));
20+
payload.setProperty(runtime, "ctrlKey", event.ctrlKey);
21+
payload.setProperty(runtime, "shiftKey", event.shiftKey);
22+
payload.setProperty(runtime, "altKey", event.altKey);
23+
payload.setProperty(runtime, "metaKey", event.metaKey);
24+
payload.setProperty(runtime, "capsLockKey", event.capsLockKey);
25+
payload.setProperty(runtime, "numericPadKey", event.numericPadKey);
26+
payload.setProperty(runtime, "helpKey", event.helpKey);
27+
payload.setProperty(runtime, "functionKey", event.functionKey);
28+
return payload;
29+
};
30+
31+
void HostPlatformViewEventEmitter::onKeyDown(const KeyEvent& keyEvent) const {
32+
dispatchEvent("keyDown", [keyEvent](jsi::Runtime& runtime) {
33+
return keyEventPayload(runtime, keyEvent);
34+
});
35+
}
36+
37+
void HostPlatformViewEventEmitter::onKeyUp(const KeyEvent& keyEvent) const {
38+
dispatchEvent("keyUp", [keyEvent](jsi::Runtime& runtime) {
39+
return keyEventPayload(runtime, keyEvent);
40+
});
41+
}
42+
43+
#pragma mark - Mouse Events
44+
45+
static jsi::Object mouseEventPayload(
46+
jsi::Runtime& runtime,
47+
const MouseEvent& event) {
48+
auto payload = jsi::Object(runtime);
49+
payload.setProperty(runtime, "clientX", event.clientX);
50+
payload.setProperty(runtime, "clientY", event.clientY);
51+
payload.setProperty(runtime, "screenX", event.screenX);
52+
payload.setProperty(runtime, "screenY", event.screenY);
53+
payload.setProperty(runtime, "altKey", event.altKey);
54+
payload.setProperty(runtime, "ctrlKey", event.ctrlKey);
55+
payload.setProperty(runtime, "shiftKey", event.shiftKey);
56+
payload.setProperty(runtime, "metaKey", event.metaKey);
57+
return payload;
58+
};
59+
60+
void HostPlatformViewEventEmitter::onMouseEnter(
61+
const MouseEvent& mouseEvent) const {
62+
dispatchEvent("mouseEnter", [mouseEvent](jsi::Runtime& runtime) {
63+
return mouseEventPayload(runtime, mouseEvent);
64+
});
65+
}
66+
67+
void HostPlatformViewEventEmitter::onMouseLeave(
68+
const MouseEvent& mouseEvent) const {
69+
dispatchEvent("mouseLeave", [mouseEvent](jsi::Runtime& runtime) {
70+
return mouseEventPayload(runtime, mouseEvent);
71+
});
72+
}
73+
74+
void HostPlatformViewEventEmitter::onDoubleClick(
75+
const MouseEvent& mouseEvent) const {
76+
dispatchEvent("doubleClick", [mouseEvent](jsi::Runtime& runtime) {
77+
return mouseEventPayload(runtime, mouseEvent);
78+
});
79+
}
80+
81+
#pragma mark - Drag and Drop Events
82+
83+
static jsi::Value dataTransferPayload(
84+
jsi::Runtime& runtime,
85+
const std::vector<DataTransferItem>& dataTransferItems) {
86+
auto filesArray = jsi::Array(runtime, dataTransferItems.size());
87+
auto itemsArray = jsi::Array(runtime, dataTransferItems.size());
88+
auto typesArray = jsi::Array(runtime, dataTransferItems.size());
89+
int i = 0;
90+
for (const auto& transferItem : dataTransferItems) {
91+
auto fileObject = jsi::Object(runtime);
92+
fileObject.setProperty(runtime, "name", transferItem.name);
93+
fileObject.setProperty(runtime, "type", transferItem.type);
94+
fileObject.setProperty(runtime, "uri", transferItem.uri);
95+
if (transferItem.size.has_value()) {
96+
fileObject.setProperty(runtime, "size", *transferItem.size);
97+
}
98+
if (transferItem.width.has_value()) {
99+
fileObject.setProperty(runtime, "width", *transferItem.width);
100+
}
101+
if (transferItem.height.has_value()) {
102+
fileObject.setProperty(runtime, "height", *transferItem.height);
103+
}
104+
filesArray.setValueAtIndex(runtime, i, fileObject);
105+
106+
auto itemObject = jsi::Object(runtime);
107+
itemObject.setProperty(runtime, "kind", transferItem.kind);
108+
itemObject.setProperty(runtime, "type", transferItem.type);
109+
itemsArray.setValueAtIndex(runtime, i, itemObject);
110+
111+
typesArray.setValueAtIndex(runtime, i, transferItem.type);
112+
i++;
113+
}
114+
115+
auto dataTransferObject = jsi::Object(runtime);
116+
dataTransferObject.setProperty(runtime, "files", filesArray);
117+
dataTransferObject.setProperty(runtime, "items", itemsArray);
118+
dataTransferObject.setProperty(runtime, "types", typesArray);
119+
120+
return dataTransferObject;
121+
}
122+
123+
static jsi::Value dragEventPayload(
124+
jsi::Runtime& runtime,
125+
const DragEvent& event) {
126+
auto payload = mouseEventPayload(runtime, event);
127+
auto dataTransferObject =
128+
dataTransferPayload(runtime, event.dataTransferItems);
129+
payload.setProperty(runtime, "dataTransfer", dataTransferObject);
130+
return payload;
131+
}
132+
133+
void HostPlatformViewEventEmitter::onDragEnter(
134+
const DragEvent& dragEvent) const {
135+
dispatchEvent("dragEnter", [dragEvent](jsi::Runtime& runtime) {
136+
return dragEventPayload(runtime, dragEvent);
137+
});
138+
}
139+
140+
void HostPlatformViewEventEmitter::onDragLeave(
141+
const DragEvent& dragEvent) const {
142+
dispatchEvent("dragLeave", [dragEvent](jsi::Runtime& runtime) {
143+
return dragEventPayload(runtime, dragEvent);
144+
});
145+
}
146+
147+
void HostPlatformViewEventEmitter::onDrop(const DragEvent& dragEvent) const {
148+
dispatchEvent("drop", [dragEvent](jsi::Runtime& runtime) {
149+
return dragEventPayload(runtime, dragEvent);
150+
});
151+
}
152+
153+
#pragma mark - Focus Events
154+
155+
void HostPlatformViewEventEmitter::onFocus() const {
156+
dispatchEvent("focus");
157+
}
158+
159+
void HostPlatformViewEventEmitter::onBlur() const {
160+
dispatchEvent("blur");
161+
}
162+
163+
} // namespace facebook::react
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#pragma once
9+
10+
#include <react/renderer/components/view/BaseViewEventEmitter.h>
11+
#include "KeyEvent.h"
12+
#include "MouseEvent.h"
13+
14+
namespace facebook::react {
15+
16+
class HostPlatformViewEventEmitter : public BaseViewEventEmitter {
17+
public:
18+
using BaseViewEventEmitter::BaseViewEventEmitter;
19+
20+
#pragma mark - Keyboard Events
21+
22+
void onKeyDown(const KeyEvent& keyEvent) const;
23+
void onKeyUp(const KeyEvent& keyEvent) const;
24+
25+
#pragma mark - Mouse Events
26+
27+
void onMouseEnter(const MouseEvent& mouseEvent) const;
28+
void onMouseLeave(const MouseEvent& mouseEvent) const;
29+
void onDoubleClick(const MouseEvent& mouseEvent) const;
30+
31+
#pragma mark - Drag and Drop Events
32+
33+
void onDragEnter(const DragEvent& dragEvent) const;
34+
void onDragLeave(const DragEvent& dragEvent) const;
35+
void onDrop(const DragEvent& dragEvent) const;
36+
37+
#pragma mark - Focus Events
38+
39+
void onFocus() const;
40+
void onBlur() const;
41+
};
42+
43+
} // namespace facebook::react
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#pragma once
9+
10+
#include <react/renderer/core/PropsParserContext.h>
11+
#include <react/renderer/core/propsConversions.h>
12+
#include <array>
13+
#include <bitset>
14+
#include <cmath>
15+
#include <optional>
16+
17+
namespace facebook::react {
18+
19+
struct HostPlatformViewEvents {
20+
std::bitset<32> bits{};
21+
22+
enum class Offset : std::size_t {
23+
// Keyboard Events
24+
KeyDown = 1,
25+
KeyUp = 2,
26+
27+
// Mouse Events
28+
MouseEnter = 3,
29+
MouseLeave = 4,
30+
DoubleClick = 5,
31+
};
32+
33+
constexpr bool operator[](const Offset offset) const {
34+
return bits[static_cast<std::size_t>(offset)];
35+
}
36+
37+
std::bitset<32>::reference operator[](const Offset offset) {
38+
return bits[static_cast<std::size_t>(offset)];
39+
}
40+
};
41+
42+
inline static bool operator==(
43+
const HostPlatformViewEvents& lhs,
44+
const HostPlatformViewEvents& rhs) {
45+
return lhs.bits == rhs.bits;
46+
}
47+
48+
inline static bool operator!=(
49+
const HostPlatformViewEvents& lhs,
50+
const HostPlatformViewEvents& rhs) {
51+
return lhs.bits != rhs.bits;
52+
}
53+
54+
static inline HostPlatformViewEvents convertRawProp(
55+
const PropsParserContext& context,
56+
const RawProps& rawProps,
57+
const HostPlatformViewEvents& sourceValue,
58+
const HostPlatformViewEvents& defaultValue) {
59+
HostPlatformViewEvents result{};
60+
using Offset = HostPlatformViewEvents::Offset;
61+
62+
result[Offset::KeyDown] = convertRawProp(
63+
context,
64+
rawProps,
65+
"onKeyDown",
66+
sourceValue[Offset::KeyDown],
67+
defaultValue[Offset::KeyDown]);
68+
result[Offset::KeyUp] = convertRawProp(
69+
context,
70+
rawProps,
71+
"onKeyUp",
72+
sourceValue[Offset::KeyUp],
73+
defaultValue[Offset::KeyUp]);
74+
75+
result[Offset::MouseEnter] = convertRawProp(
76+
context,
77+
rawProps,
78+
"onMouseEnter",
79+
sourceValue[Offset::MouseEnter],
80+
defaultValue[Offset::MouseEnter]);
81+
result[Offset::MouseLeave] = convertRawProp(
82+
context,
83+
rawProps,
84+
"onMouseLeave",
85+
sourceValue[Offset::MouseLeave],
86+
defaultValue[Offset::MouseLeave]);
87+
88+
result[Offset::DoubleClick] = convertRawProp(
89+
context,
90+
rawProps,
91+
"onDoubleClick",
92+
sourceValue[Offset::DoubleClick],
93+
defaultValue[Offset::DoubleClick]);
94+
95+
return result;
96+
}
97+
98+
} // namespace facebook::react

0 commit comments

Comments
 (0)