Skip to content

Commit

Permalink
[Pressable] Mouse drags inside Pressable don't move the window (#1857)
Browse files Browse the repository at this point in the history
* [Pressable] mouseDrags inside a Pressable don't move the window

* Cleanup test code

* lint and update snapshots

* fix lint issue

* macOS tags + some more documentation
  • Loading branch information
Saadnajmi authored Jun 21, 2023
1 parent 06dc77f commit 11d573f
Show file tree
Hide file tree
Showing 11 changed files with 147 additions and 40 deletions.
62 changes: 59 additions & 3 deletions Libraries/Components/Pressable/Pressable.js
Original file line number Diff line number Diff line change
Expand Up @@ -196,12 +196,66 @@ type Props = $ReadOnly<{|
*/
validKeysUp?: ?Array<string>,

/**
* Specifies whether the view should receive the mouse down event when the
* containing window is in the background.
*
* @platform macos
*/
acceptsFirstMouse?: ?boolean,

/**
* Specifies whether clicking and dragging the view can move the window. This is useful
* to disable in Button like components like Pressable where mouse the user should still
* be able to click and drag off the view to cancel the click without accidentally moving the window.
*
* @platform macos
*/
mouseDownCanMoveWindow?: ?boolean,

/**
* Specifies whether system focus ring should be drawn when the view has keyboard focus.
*
* @platform macos
*/
enableFocusRing?: ?boolean,

/**
* Specifies the Tooltip for the Pressable.
* @platform macos
*/
tooltip?: ?string,

/**
* Fired when a file is dragged into the Pressable via the mouse.
*
* @platform macos
*/
onDragEnter?: (event: MouseEvent) => void,

/**
* Fired when a file is dragged out of the Pressable via the mouse.
*
* @platform macos
*/
onDragLeave?: (event: MouseEvent) => void,

/**
* Fired when a file is dropped on the Pressable via the mouse.
*
* @platform macos
*/
onDrop?: (event: MouseEvent) => void,

/**
* The types of dragged files that the Pressable will accept.
*
* Possible values for `draggedTypes` are:
*
* - `'fileUrl'`
*
* @platform macos
*/
draggedTypes?: ?DraggedTypesType,
// macOS]

Expand Down Expand Up @@ -250,8 +304,6 @@ type Props = $ReadOnly<{|
* LTI update could not be added via codemod */
function Pressable(props: Props, forwardedRef): React.Node {
const {
acceptsFirstMouse, // [macOS]
enableFocusRing, // [macOS]
accessible,
accessibilityState,
'aria-live': ariaLive,
Expand Down Expand Up @@ -282,6 +334,9 @@ function Pressable(props: Props, forwardedRef): React.Node {
onBlur,
onKeyDown,
onKeyUp,
acceptsFirstMouse,
mouseDownCanMoveWindow,
enableFocusRing,
// macOS]
pressRetentionOffset,
style,
Expand Down Expand Up @@ -322,7 +377,8 @@ function Pressable(props: Props, forwardedRef): React.Node {
const restPropsWithDefaults: React.ElementConfig<typeof View> = {
...restProps,
...android_rippleConfig?.viewProps,
acceptsFirstMouse: acceptsFirstMouse !== false && !disabled, // [macOS
acceptsFirstMouse: acceptsFirstMouse !== false && !disabled, // [macOS]
mouseDownCanMoveWindow: false, // [macOS]
enableFocusRing: enableFocusRing !== false && !disabled,
accessible: accessible !== false,
accessibilityViewIsModal:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ exports[`<Pressable /> should render as expected: should deep render when mocked
collapsable={false}
enableFocusRing={true}
focusable={true}
mouseDownCanMoveWindow={false}
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
Expand Down Expand Up @@ -64,6 +65,7 @@ exports[`<Pressable /> should render as expected: should deep render when not mo
collapsable={false}
enableFocusRing={true}
focusable={true}
mouseDownCanMoveWindow={false}
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
Expand Down Expand Up @@ -116,6 +118,7 @@ exports[`<Pressable disabled={true} /> should be disabled when disabled is true:
collapsable={false}
enableFocusRing={false}
focusable={false}
mouseDownCanMoveWindow={false}
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
Expand Down Expand Up @@ -156,6 +159,7 @@ exports[`<Pressable disabled={true} /> should be disabled when disabled is true:
collapsable={false}
enableFocusRing={false}
focusable={false}
mouseDownCanMoveWindow={false}
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
Expand Down Expand Up @@ -212,6 +216,7 @@ exports[`<Pressable disabled={true} accessibilityState={{}} /> should be disable
collapsable={false}
enableFocusRing={false}
focusable={false}
mouseDownCanMoveWindow={false}
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
Expand Down Expand Up @@ -252,6 +257,7 @@ exports[`<Pressable disabled={true} accessibilityState={{}} /> should be disable
collapsable={false}
enableFocusRing={false}
focusable={false}
mouseDownCanMoveWindow={false}
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
Expand Down Expand Up @@ -310,6 +316,7 @@ exports[`<Pressable disabled={true} accessibilityState={{checked: true}} /> shou
collapsable={false}
enableFocusRing={false}
focusable={false}
mouseDownCanMoveWindow={false}
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
Expand Down Expand Up @@ -350,6 +357,7 @@ exports[`<Pressable disabled={true} accessibilityState={{checked: true}} /> shou
collapsable={false}
enableFocusRing={false}
focusable={false}
mouseDownCanMoveWindow={false}
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
Expand Down Expand Up @@ -416,6 +424,7 @@ exports[`<Pressable disabled={true} accessibilityState={{disabled: false}} /> sh
collapsable={false}
enableFocusRing={false}
focusable={false}
mouseDownCanMoveWindow={false}
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
Expand Down Expand Up @@ -456,6 +465,7 @@ exports[`<Pressable disabled={true} accessibilityState={{disabled: false}} /> sh
collapsable={false}
enableFocusRing={false}
focusable={false}
mouseDownCanMoveWindow={false}
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
Expand Down
1 change: 1 addition & 0 deletions Libraries/Components/View/ReactNativeViewAttributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ const UIView = {
style: ReactNativeStyleAttributes,
// [macOS
acceptsFirstMouse: true,
mouseDownCanMoveWindow: true,
enableFocusRing: true,
focusable: true,
onMouseEnter: true,
Expand Down
1 change: 1 addition & 0 deletions Libraries/Components/View/ViewPropTypes.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ export type DraggedTypesType = DraggedType | DraggedType[];

export interface ViewPropsMacOS {
acceptsFirstMouse?: boolean | undefined;
mouseDownCanMoveWindow?: boolean | undefined;
enableFocusRing?: boolean | undefined;
onMouseEnter?: ((event: MouseEvent) => void) | undefined;
onMouseLeave?: ((event: MouseEvent) => void) | undefined;
Expand Down
17 changes: 13 additions & 4 deletions Libraries/Components/View/ViewPropTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -474,14 +474,14 @@ type IOSViewProps = $ReadOnly<{|
// [macOS
type MacOSViewProps = $ReadOnly<{|
/**
* Fired when a dragged element enters a valid drop target
* Fired when a file is dragged into the view via the mouse.
*
* @platform macos
*/
onDragEnter?: (event: MouseEvent) => void,

/**
* Fired when a dragged element leaves a valid drop target
* Fired when a file is dragged out of the view via the mouse.
*
* @platform macos
*/
Expand Down Expand Up @@ -509,14 +509,23 @@ type MacOSViewProps = $ReadOnly<{|
acceptsFirstMouse?: ?boolean,

/**
* Specifies whether focus ring should be drawn when the view has the first responder status.
* Specifies whether clicking and dragging the view can move the window. This is useful
* to disable in Button like components like Pressable where mouse the user should still
* be able to click and drag off the view to cancel the click without accidentally moving the window.
*
* @platform macos
*/
mouseDownCanMoveWindow?: ?boolean,

/**
* Specifies whether system focus ring should be drawn when the view has keyboard focus.
*
* @platform macos
*/
enableFocusRing?: ?boolean,

/**
* Enables Drag'n'Drop Support for certain types of dragged types
* The types of dragged files that the view will accept.
*
* Possible values for `draggedTypes` are:
*
Expand Down
1 change: 1 addition & 0 deletions Libraries/NativeComponent/BaseViewConfig.macos.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ const validAttributesForNonEventProps = {
tooltip: true,
validKeysDown: true,
validKeysUp: true,
mouseDownCanMoveWindow: true,
};

// Props for bubbling and direct events
Expand Down
3 changes: 3 additions & 0 deletions React/Base/RCTUIKit.h
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,9 @@ CGPathRef UIBezierPathCreateCGPathRef(UIBezierPath *path);
* containing window is in the background.
*/
@property (nonatomic, assign) BOOL acceptsFirstMouse;

@property (nonatomic, assign) BOOL mouseDownCanMoveWindow;

/**
* Specifies whether the view participates in the key view loop as user tabs through different controls
* This is equivalent to acceptsFirstResponder on mac OS.
Expand Down
10 changes: 10 additions & 0 deletions React/Base/macOS/RCTUIKit.m
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ @implementation RCTUIView
NSColor *_backgroundColor;
BOOL _clipsToBounds;
BOOL _userInteractionEnabled;
BOOL _mouseDownCanMoveWindow;
}

+ (NSSet<NSString *> *)keyPathsForValuesAffectingValueForKey:(NSString *)key
Expand Down Expand Up @@ -243,6 +244,7 @@ @implementation RCTUIView
self.wantsLayer = YES;
self->_userInteractionEnabled = YES;
self->_enableFocusRing = YES;
self->_mouseDownCanMoveWindow = YES;
}
return self;
}
Expand Down Expand Up @@ -288,6 +290,14 @@ - (void)viewDidMoveToWindow
[self didMoveToWindow];
}

- (BOOL)mouseDownCanMoveWindow{
return _mouseDownCanMoveWindow;
}

- (void)setMouseDownCanMoveWindow:(BOOL)mouseDownCanMoveWindow{
_mouseDownCanMoveWindow = mouseDownCanMoveWindow;
}

- (BOOL)isFlipped
{
return YES;
Expand Down
11 changes: 11 additions & 0 deletions React/Views/RCTView.m
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ @implementation RCTView {
#if TARGET_OS_OSX // [macOS
NSTrackingArea *_trackingArea;
BOOL _hasMouseOver;
BOOL _mouseDownCanMoveWindow;
#endif // macOS]
NSMutableDictionary<NSString *, NSDictionary *> *accessibilityActionsNameMap;
NSMutableDictionary<NSString *, NSDictionary *> *accessibilityActionsLabelMap;
Expand Down Expand Up @@ -176,6 +177,7 @@ - (instancetype)initWithFrame:(CGRect)frame
#if TARGET_OS_OSX // [macOS
_transform3D = CATransform3DIdentity;
_shadowColor = nil;
_mouseDownCanMoveWindow = YES;
#endif // macOS]

_backgroundColor = super.backgroundColor;
Expand Down Expand Up @@ -1505,6 +1507,15 @@ - (void)mouseExited:(NSEvent *)event
additionalData:nil];
}

- (BOOL)mouseDownCanMoveWindow{
return _mouseDownCanMoveWindow;
}

- (void)setMouseDownCanMoveWindow:(BOOL)mouseDownCanMoveWindow{
_mouseDownCanMoveWindow = mouseDownCanMoveWindow;
}


- (NSDictionary*)locationInfoFromEvent:(NSEvent*)event
{
NSPoint locationInWindow = event.locationInWindow;
Expand Down
5 changes: 5 additions & 0 deletions React/Views/RCTViewManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -427,12 +427,16 @@ - (RCTShadowView *)shadowView
view.acceptsFirstMouse = json ? [RCTConvert BOOL:json] : defaultView.acceptsFirstMouse;
}
}

RCT_EXPORT_VIEW_PROPERTY(mouseDownCanMoveWindow, BOOL)

RCT_CUSTOM_VIEW_PROPERTY(focusable, BOOL, RCTView)
{
if ([view respondsToSelector:@selector(setFocusable:)]) {
view.focusable = json ? [RCTConvert BOOL:json] : defaultView.focusable;
}
}

RCT_CUSTOM_VIEW_PROPERTY(enableFocusRing, BOOL, RCTView)
{
if ([view respondsToSelector:@selector(setEnableFocusRing:)]) {
Expand Down Expand Up @@ -525,6 +529,7 @@ - (RCTShadowView *)shadowView
RCT_EXPORT_VIEW_PROPERTY(onKeyUp, RCTDirectEventBlock) // macOS keyboard events
RCT_EXPORT_VIEW_PROPERTY(validKeysDown, NSArray<NSString*>)
RCT_EXPORT_VIEW_PROPERTY(validKeysUp, NSArray<NSString*>)

#endif // macOS]

#pragma mark - ShadowView properties
Expand Down
Loading

0 comments on commit 11d573f

Please sign in to comment.