Skip to content

Commit e51e19e

Browse files
cortinicofacebook-github-bot
authored andcommitted
Add event listeners to Scheduler
Summary: Minimal set of changes to intercept events in external modules. Current intended use-case is for Reanimated to handle events for the Animated properties. Changelog: [Added] Add listeners to allow intercepting events in C++ core. Reviewed By: cipolleschi Differential Revision: D35312534 fbshipit-source-id: ec924b57fd0c0dabf7be7b886dbef23bf3170d6c
1 parent ceb0a54 commit e51e19e

File tree

7 files changed

+140
-1
lines changed

7 files changed

+140
-1
lines changed

ReactCommon/react/renderer/core/EventDispatcher.cpp

+21
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ EventDispatcher::EventDispatcher(
3636

3737
void EventDispatcher::dispatchEvent(RawEvent &&rawEvent, EventPriority priority)
3838
const {
39+
// Allows the event listener to interrupt default event dispatch
40+
if (eventListeners_.willDispatchEvent(rawEvent)) {
41+
return;
42+
}
3943
getEventQueue(priority).enqueueEvent(std::move(rawEvent));
4044
}
4145

@@ -46,6 +50,10 @@ void EventDispatcher::dispatchStateUpdate(
4650
}
4751

4852
void EventDispatcher::dispatchUniqueEvent(RawEvent &&rawEvent) const {
53+
// Allows the event listener to interrupt default event dispatch
54+
if (eventListeners_.willDispatchEvent(rawEvent)) {
55+
return;
56+
}
4957
asynchronousBatchedQueue_->enqueueUniqueEvent(std::move(rawEvent));
5058
}
5159

@@ -62,5 +70,18 @@ const EventQueue &EventDispatcher::getEventQueue(EventPriority priority) const {
6270
}
6371
}
6472

73+
void EventDispatcher::addListener(
74+
const std::shared_ptr<EventListener const> &listener) const {
75+
eventListeners_.addListener(listener);
76+
}
77+
78+
/*
79+
* Removes provided event listener to the event dispatcher.
80+
*/
81+
void EventDispatcher::removeListener(
82+
const std::shared_ptr<EventListener const> &listener) const {
83+
eventListeners_.removeListener(listener);
84+
}
85+
6586
} // namespace react
6687
} // namespace facebook

ReactCommon/react/renderer/core/EventDispatcher.h

+15
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include <react/renderer/core/BatchedEventQueue.h>
1111
#include <react/renderer/core/EventBeat.h>
12+
#include <react/renderer/core/EventListener.h>
1213
#include <react/renderer/core/EventPriority.h>
1314
#include <react/renderer/core/EventQueueProcessor.h>
1415
#include <react/renderer/core/StateUpdate.h>
@@ -52,13 +53,27 @@ class EventDispatcher {
5253
void dispatchStateUpdate(StateUpdate &&stateUpdate, EventPriority priority)
5354
const;
5455

56+
#pragma mark - Event listeners
57+
/*
58+
* Adds provided event listener to the event dispatcher.
59+
*/
60+
void addListener(const std::shared_ptr<EventListener const> &listener) const;
61+
62+
/*
63+
* Removes provided event listener to the event dispatcher.
64+
*/
65+
void removeListener(
66+
const std::shared_ptr<EventListener const> &listener) const;
67+
5568
private:
5669
EventQueue const &getEventQueue(EventPriority priority) const;
5770

5871
std::unique_ptr<UnbatchedEventQueue> synchronousUnbatchedQueue_;
5972
std::unique_ptr<BatchedEventQueue> synchronousBatchedQueue_;
6073
std::unique_ptr<UnbatchedEventQueue> asynchronousUnbatchedQueue_;
6174
std::unique_ptr<BatchedEventQueue> asynchronousBatchedQueue_;
75+
76+
mutable EventListenerContainer eventListeners_;
6277
};
6378

6479
} // namespace react
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
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 "EventListener.h"
9+
10+
namespace facebook::react {
11+
12+
bool EventListenerContainer::willDispatchEvent(const RawEvent &event) {
13+
std::shared_lock<butter::shared_mutex> lock(mutex_);
14+
15+
bool handled = false;
16+
for (auto const &listener : eventListeners_) {
17+
handled = handled || listener->operator()(event);
18+
}
19+
return handled;
20+
}
21+
22+
void EventListenerContainer::addListener(
23+
const std::shared_ptr<EventListener const> &listener) {
24+
std::unique_lock<butter::shared_mutex> lock(mutex_);
25+
26+
eventListeners_.push_back(listener);
27+
}
28+
29+
void EventListenerContainer::removeListener(
30+
const std::shared_ptr<EventListener const> &listener) {
31+
std::unique_lock<butter::shared_mutex> lock(mutex_);
32+
33+
auto it = std::find(eventListeners_.begin(), eventListeners_.end(), listener);
34+
if (it != eventListeners_.end()) {
35+
eventListeners_.erase(it);
36+
}
37+
}
38+
39+
} // namespace facebook::react
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
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 <string>
11+
12+
#include <react/renderer/core/RawEvent.h>
13+
14+
#include <butter/mutex.h>
15+
16+
namespace facebook {
17+
namespace react {
18+
19+
/**
20+
* Listener for events dispatched to JS runtime.
21+
* Return `true` to interrupt default dispatch to JS event emitter, `false` to
22+
* pass through to default handlers.
23+
*/
24+
using EventListener = std::function<bool(const RawEvent &event)>;
25+
26+
class EventListenerContainer {
27+
public:
28+
/*
29+
* Invoke listeners in this container with the event.
30+
* Returns true if event was handled by the listener, false to continue
31+
* default dispatch.
32+
*/
33+
bool willDispatchEvent(const RawEvent &event);
34+
35+
void addListener(const std::shared_ptr<EventListener const> &listener);
36+
void removeListener(const std::shared_ptr<EventListener const> &listener);
37+
38+
private:
39+
butter::shared_mutex mutex_;
40+
std::vector<std::shared_ptr<EventListener const>> eventListeners_;
41+
};
42+
43+
} // namespace react
44+
} // namespace facebook

ReactCommon/react/renderer/scheduler/Scheduler.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -368,5 +368,19 @@ ContextContainer::Shared Scheduler::getContextContainer() const {
368368
return contextContainer_;
369369
}
370370

371+
void Scheduler::addEventListener(
372+
const std::shared_ptr<EventListener const> &listener) {
373+
if (eventDispatcher_->has_value()) {
374+
eventDispatcher_->value().addListener(listener);
375+
}
376+
}
377+
378+
void Scheduler::removeEventListener(
379+
const std::shared_ptr<EventListener const> &listener) {
380+
if (eventDispatcher_->has_value()) {
381+
eventDispatcher_->value().removeListener(listener);
382+
}
383+
}
384+
371385
} // namespace react
372386
} // namespace facebook

ReactCommon/react/renderer/scheduler/Scheduler.h

+6
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <react/renderer/components/root/RootComponentDescriptor.h>
1717
#include <react/renderer/core/ComponentDescriptor.h>
1818
#include <react/renderer/core/EventEmitter.h>
19+
#include <react/renderer/core/EventListener.h>
1920
#include <react/renderer/core/LayoutConstraints.h>
2021
#include <react/renderer/mounting/MountingOverrideDelegate.h>
2122
#include <react/renderer/scheduler/InspectorData.h>
@@ -107,6 +108,11 @@ class Scheduler final : public UIManagerDelegate {
107108
#pragma mark - ContextContainer
108109
ContextContainer::Shared getContextContainer() const;
109110

111+
#pragma mark - Event listeners
112+
void addEventListener(const std::shared_ptr<EventListener const> &listener);
113+
void removeEventListener(
114+
const std::shared_ptr<EventListener const> &listener);
115+
110116
private:
111117
friend class SurfaceHandler;
112118

packages/rn-tester/Podfile.lock

+1-1
Original file line numberDiff line numberDiff line change
@@ -942,6 +942,6 @@ SPEC CHECKSUMS:
942942
Yoga: 2854c07ffae3ed31bf7e1297d87d4aaa73db6640
943943
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a
944944

945-
PODFILE CHECKSUM: 22e00978a86d653e611654e52ad29190769af232
945+
PODFILE CHECKSUM: 2bf6f58f9311ff9b7a2195fe9ca589cf78abf099
946946

947947
COCOAPODS: 1.11.3

0 commit comments

Comments
 (0)