Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 107 additions & 0 deletions ReactCommon/react/renderer/components/view/macOS/KeyEvent.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#pragma once

#include <string>

namespace facebook::react {

/*
* Describes a request to handle a key input.
*/
struct HandledKey {
/**
* The key for the event aligned to https://www.w3.org/TR/uievents-key/.
*/
std::string key{};

/*
* A flag indicating if the alt key is pressed.
*/
std::optional<bool> altKey{};

/*
* A flag indicating if the control key is pressed.
*/
std::optional<bool> ctrlKey{};

/*
* A flag indicating if the shift key is pressed.
*/
std::optional<bool> shiftKey{};

/*
* A flag indicating if the meta key is pressed.
*/
std::optional<bool> metaKey{};
};

inline static bool operator==(const HandledKey &lhs, const HandledKey &rhs) {
return lhs.key == rhs.key && lhs.altKey == rhs.altKey && lhs.ctrlKey == rhs.ctrlKey &&
lhs.shiftKey == rhs.shiftKey && lhs.metaKey == rhs.metaKey;
}

/**
* Key event emitted by handled key events.
*/
struct KeyEvent {
/**
* The key for the event aligned to https://www.w3.org/TR/uievents-key/.
*/
std::string key{};

/*
* A flag indicating if the alt key is pressed.
*/
bool altKey{false};

/*
* A flag indicating if the control key is pressed.
*/
bool ctrlKey{false};

/*
* A flag indicating if the shift key is pressed.
*/
bool shiftKey{false};

/*
* A flag indicating if the meta key is pressed.
*/
bool metaKey{false};

/*
* A flag indicating if the caps lock key is pressed.
*/
bool capsLockKey{false};

/*
* A flag indicating if the key on the numeric pad is pressed.
*/
bool numericPadKey{false};

/*
* A flag indicating if the help key is pressed.
*/
bool helpKey{false};

/*
* A flag indicating if a function key is pressed.
*/
bool functionKey{false};
};

inline static bool operator==(const KeyEvent &lhs, const HandledKey &rhs) {
return lhs.key == rhs.key &&
(!rhs.altKey.has_value() || lhs.altKey == *rhs.altKey) &&
(!rhs.ctrlKey.has_value() || lhs.ctrlKey == *rhs.ctrlKey) &&
(!rhs.shiftKey.has_value() || lhs.shiftKey == *rhs.shiftKey) &&
(!rhs.metaKey.has_value() || lhs.metaKey == *rhs.metaKey);
}

} // namespace facebook::react
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#include "MacOSViewEventEmitter.h"

namespace facebook::react {

#pragma mark - Keyboard Events

static jsi::Value keyEventPayload(jsi::Runtime &runtime, KeyEvent const &event) {
auto payload = jsi::Object(runtime);
payload.setProperty(runtime, "key", jsi::String::createFromUtf8(runtime, event.key));
payload.setProperty(runtime, "ctrlKey", event.ctrlKey);
payload.setProperty(runtime, "shiftKey", event.shiftKey);
payload.setProperty(runtime, "altKey", event.altKey);
payload.setProperty(runtime, "metaKey", event.metaKey);
payload.setProperty(runtime, "capsLockKey", event.capsLockKey);
payload.setProperty(runtime, "numericPadKey", event.numericPadKey);
payload.setProperty(runtime, "helpKey", event.helpKey);
payload.setProperty(runtime, "functionKey", event.functionKey);
return payload;
};

void MacOSViewEventEmitter::onKeyDown(KeyEvent const &keyEvent) const {
dispatchEvent(
"keyDown",
[keyEvent](jsi::Runtime &runtime) { return keyEventPayload(runtime, keyEvent); },
EventPriority::AsynchronousBatched);
}

void MacOSViewEventEmitter::onKeyUp(KeyEvent const &keyEvent) const {
dispatchEvent(
"keyUp",
[keyEvent](jsi::Runtime &runtime) { return keyEventPayload(runtime, keyEvent); },
EventPriority::AsynchronousBatched);
}

static jsi::Value mouseEventPayload(jsi::Runtime &runtime, MouseEvent const &event) {
auto payload = jsi::Object(runtime);
payload.setProperty(runtime, "clientX", event.clientX);
payload.setProperty(runtime, "clientY", event.clientY);
payload.setProperty(runtime, "screenX", event.screenX);
payload.setProperty(runtime, "screenY", event.screenY);
payload.setProperty(runtime, "altKey", event.altKey);
payload.setProperty(runtime, "ctrlKey", event.ctrlKey);
payload.setProperty(runtime, "shiftKey", event.shiftKey);
payload.setProperty(runtime, "metaKey", event.metaKey);
return payload;
};

void MacOSViewEventEmitter::onMouseEnter(MouseEvent const &mouseEvent) const {
dispatchEvent(
"mouseEnter",
[mouseEvent](jsi::Runtime &runtime) { return mouseEventPayload(runtime, mouseEvent); },
EventPriority::AsynchronousBatched);
}

void MacOSViewEventEmitter::onMouseLeave(MouseEvent const &mouseEvent) const {
dispatchEvent(
"mouseLeave",
[mouseEvent](jsi::Runtime &runtime) { return mouseEventPayload(runtime, mouseEvent); },
EventPriority::AsynchronousBatched);
}

} // namespace facebook::react
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#pragma once

#include <react/renderer/components/view/TouchEventEmitter.h>
#include <react/renderer/components/view/macOS/KeyEvent.h>
#include <react/renderer/components/view/macOS/MouseEvent.h>

namespace facebook::react {

class MacOSViewEventEmitter : public TouchEventEmitter {
public:
using TouchEventEmitter::TouchEventEmitter;

#pragma mark - Keyboard Events

void onKeyDown(KeyEvent const &keyEvent) const;
void onKeyUp(KeyEvent const &keyEvent) const;

#pragma mark - Mouse Events

void onMouseEnter(MouseEvent const &mouseEvent) const;
void onMouseLeave(MouseEvent const &mouseEvent) const;
};

} // namespace facebook::react
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#include "MacOSViewProps.h"

#include <react/renderer/components/view/macOS/conversions.h>
#include <react/renderer/core/CoreFeatures.h>
#include <react/renderer/core/propsConversions.h>

namespace facebook::react {

MacOSViewProps::MacOSViewProps(
const PropsParserContext &context,
const MacOSViewProps &sourceProps,
const RawProps &rawProps,
bool shouldSetRawProps)
: macOSViewEvents(
CoreFeatures::enablePropIteratorSetter ? sourceProps.macOSViewEvents
: convertRawProp(context, rawProps, sourceProps.macOSViewEvents, {})),
focusable(
CoreFeatures::enablePropIteratorSetter
? sourceProps.focusable
: convertRawProp(context, rawProps, "focusable", sourceProps.focusable, {})),
enableFocusRing(
CoreFeatures::enablePropIteratorSetter
? sourceProps.enableFocusRing
: convertRawProp(context, rawProps, "enableFocusRing", sourceProps.enableFocusRing, true)),
validKeysDown(
CoreFeatures::enablePropIteratorSetter
? sourceProps.validKeysDown
: convertRawProp(context, rawProps, "validKeysDown", sourceProps.validKeysDown, {})),
validKeysUp(
CoreFeatures::enablePropIteratorSetter
? sourceProps.validKeysUp
: convertRawProp(context, rawProps, "validKeysUp", sourceProps.validKeysUp, {})){};

#define VIEW_EVENT_CASE_MACOS(eventType, eventString) \
case CONSTEXPR_RAW_PROPS_KEY_HASH(eventString): { \
MacOSViewEvents defaultViewEvents{}; \
bool res = defaultViewEvents[eventType]; \
if (value.hasValue()) { \
fromRawValue(context, value, res); \
} \
macOSViewEvents[eventType] = res; \
return; \
}

void MacOSViewProps::setProp(
const PropsParserContext &context,
RawPropsPropNameHash hash,
const char *propName,
RawValue const &value) {
switch (hash) {
VIEW_EVENT_CASE_MACOS(MacOSViewEvents::Offset::KeyDown, "onKeyDown");
VIEW_EVENT_CASE_MACOS(MacOSViewEvents::Offset::KeyUp, "onKeyUp");
VIEW_EVENT_CASE_MACOS(MacOSViewEvents::Offset::MouseEnter, "onMouseEnter");
VIEW_EVENT_CASE_MACOS(MacOSViewEvents::Offset::MouseLeave, "onMouseLeave");
RAW_SET_PROP_SWITCH_CASE_BASIC(focusable, false);
RAW_SET_PROP_SWITCH_CASE_BASIC(enableFocusRing, true);
RAW_SET_PROP_SWITCH_CASE_BASIC(validKeysDown, {});
RAW_SET_PROP_SWITCH_CASE_BASIC(validKeysUp, {});
}
}

} // namespace facebook::react
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#pragma once

#include <react/renderer/components/view/macOS/KeyEvent.h>
#include <react/renderer/components/view/macOS/primitives.h>
#include <react/renderer/core/Props.h>
#include <react/renderer/core/PropsParserContext.h>

namespace facebook::react {

class MacOSViewProps {
public:
MacOSViewProps() = default;
MacOSViewProps(
const PropsParserContext &context,
const MacOSViewProps &sourceProps,
const RawProps &rawProps,
bool shouldSetRawProps = true);

void
setProp(
const PropsParserContext &context,
RawPropsPropNameHash hash,
const char *propName,
RawValue const &value);

MacOSViewEvents macOSViewEvents{};

bool focusable{false};
bool enableFocusRing{true};

std::optional<std::vector<HandledKey>> validKeysDown{};
std::optional<std::vector<HandledKey>> validKeysUp{};
};

} // namespace facebook::react
59 changes: 59 additions & 0 deletions ReactCommon/react/renderer/components/view/macOS/MouseEvent.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#pragma once

#include <react/renderer/graphics/Geometry.h>

namespace facebook::react {

/*
* Describes a mouse enter/leave event.
*/
struct MouseEvent {
/**
* Pointer horizontal location in target view.
*/
Float clientX{0};

/**
* Pointer vertical location in target view.
*/
Float clientY{0};

/**
* Pointer horizontal location in window.
*/
Float screenX{0};

/**
* Pointer vertical location in window.
*/
Float screenY{0};

/*
* A flag indicating if the alt key is pressed.
*/
bool altKey{false};

/*
* A flag indicating if the control key is pressed.
*/
bool ctrlKey{false};

/*
* A flag indicating if the shift key is pressed.
*/
bool shiftKey{false};

/*
* A flag indicating if the meta key is pressed.
*/
bool metaKey{false};
};

} // namespace facebook::react
Loading
Loading