Skip to content

Commit

Permalink
Views with keyUpEvents/keyDownEvents set on them should form a stacki…
Browse files Browse the repository at this point in the history
…ng context (microsoft#14090)

* Key and mouse events require a stacking context

* Change files

* We dont need a stacking context to bubble JS events - but we do to modify the native handling of the events

* fix
  • Loading branch information
acoates-ms committed Dec 6, 2024
1 parent e0558c7 commit c0f878a
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 57 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "prerelease",
"comment": "Key and mouse events require a stacking context",
"packageName": "react-native-windows",
"email": "30809111+acoates-ms@users.noreply.github.com",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,7 @@
namespace facebook::react::HostPlatformViewTraitsInitializer {

inline bool formsStackingContext(ViewProps const &viewProps) {
// onFocus/onBlur are often just used for listening to bubbled events.
// Only Views which are marked as focusable can actually trigger the events, which will already avoid being collapsed.
constexpr decltype(WindowsViewEvents::bits) focusEventsMask = {
(1 << (int)WindowsViewEvents::Offset::Focus) & (1 << (int)WindowsViewEvents::Offset::Blur)};
return (viewProps.windowsEvents.bits & focusEventsMask).any() || viewProps.tooltip;
return !viewProps.keyDownEvents.empty() || !viewProps.keyUpEvents.empty() || viewProps.tooltip;
}

inline bool formsView(ViewProps const &viewProps) {
Expand Down
128 changes: 76 additions & 52 deletions vnext/src-win/Libraries/Components/View/View.windows.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,65 +134,89 @@ const View: React.AbstractComponent<
};
}

const _keyDown = (event: KeyEvent) => {
if (otherProps.keyDownEvents && event.isPropagationStopped() !== true) {
// $FlowFixMe - keyDownEvents was already checked to not be undefined
for (const el of otherProps.keyDownEvents) {
if (
event.nativeEvent.code === el.code &&
el.handledEventPhase === 3
) {
event.stopPropagation();
const _keyDown =
otherProps.keyDownEvents || otherProps.onKeyDown
? (event: KeyEvent) => {
if (
otherProps.keyDownEvents &&
event.isPropagationStopped() !== true
) {
// $FlowFixMe - keyDownEvents was already checked to not be undefined
for (const el of otherProps.keyDownEvents) {
if (
event.nativeEvent.code === el.code &&
el.handledEventPhase === 3
) {
event.stopPropagation();
}
}
}
otherProps.onKeyDown && otherProps.onKeyDown(event);
}
}
}
otherProps.onKeyDown && otherProps.onKeyDown(event);
};
: undefined;

const _keyUp = (event: KeyEvent) => {
if (otherProps.keyUpEvents && event.isPropagationStopped() !== true) {
// $FlowFixMe - keyDownEvents was already checked to not be undefined
for (const el of otherProps.keyUpEvents) {
if (
event.nativeEvent.code === el.code &&
el.handledEventPhase === 3
) {
event.stopPropagation();
const _keyUp =
otherProps.keyUpEvents || otherProps.onKeyUp
? (event: KeyEvent) => {
if (
otherProps.keyUpEvents &&
event.isPropagationStopped() !== true
) {
// $FlowFixMe - keyUpEvents was already checked to not be undefined
for (const el of otherProps.keyUpEvents) {
if (
event.nativeEvent.code === el.code &&
el.handledEventPhase === 3
) {
event.stopPropagation();
}
}
}
otherProps.onKeyUp && otherProps.onKeyUp(event);
}
}
}
otherProps.onKeyUp && otherProps.onKeyUp(event);
};
: undefined;

const _keyDownCapture = (event: KeyEvent) => {
if (otherProps.keyDownEvents && event.isPropagationStopped() !== true) {
// $FlowFixMe - keyDownEvents was already checked to not be undefined
for (const el of otherProps.keyDownEvents) {
if (
event.nativeEvent.code === el.code &&
el.handledEventPhase === 1
) {
event.stopPropagation();
const _keyDownCapture =
otherProps.keyDownEvents || otherProps.onKeyDownCapture
? (event: KeyEvent) => {
if (
otherProps.keyDownEvents &&
event.isPropagationStopped() !== true
) {
// $FlowFixMe - keyDownEvents was already checked to not be undefined
for (const el of otherProps.keyDownEvents) {
if (
event.nativeEvent.code === el.code &&
el.handledEventPhase === 1
) {
event.stopPropagation();
}
}
}
otherProps.onKeyDownCapture && otherProps.onKeyDownCapture(event);
}
}
}
otherProps.onKeyDownCapture && otherProps.onKeyDownCapture(event);
};
: undefined;

const _keyUpCapture = (event: KeyEvent) => {
if (otherProps.keyUpEvents && event.isPropagationStopped() !== true) {
// $FlowFixMe - keyDownEvents was already checked to not be undefined
for (const el of otherProps.keyUpEvents) {
if (
event.nativeEvent.code === el.code &&
el.handledEventPhase === 1
) {
event.stopPropagation();
const _keyUpCapture =
otherProps.keyUpEvents || otherProps.onKeyUpCapture
? (event: KeyEvent) => {
if (
otherProps.keyUpEvents &&
event.isPropagationStopped() !== true
) {
// $FlowFixMe - keyUpEvents was already checked to not be undefined
for (const el of otherProps.keyUpEvents) {
if (
event.nativeEvent.code === el.code &&
el.handledEventPhase === 1
) {
event.stopPropagation();
}
}
}
otherProps.onKeyUpCapture && otherProps.onKeyUpCapture(event);
}
}
}
otherProps.onKeyUpCapture && otherProps.onKeyUpCapture(event);
};
: undefined;

// [Windows
const _focusable = tabIndex !== undefined ? !tabIndex : focusable;
Expand Down

0 comments on commit c0f878a

Please sign in to comment.