Skip to content

Commit d6350e1

Browse files
authored
[0.71][Pressable] Mouse drags inside Pressable don't move the window (#1858)
* [Pressable] Mouse drags inside Pressable don't move the window * macOS tags + some more documentation
1 parent d500d05 commit d6350e1

File tree

11 files changed

+115
-8
lines changed

11 files changed

+115
-8
lines changed

Libraries/Components/Pressable/Pressable.js

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -196,12 +196,66 @@ type Props = $ReadOnly<{|
196196
*/
197197
validKeysUp?: ?Array<string>,
198198

199+
/**
200+
* Specifies whether the view should receive the mouse down event when the
201+
* containing window is in the background.
202+
*
203+
* @platform macos
204+
*/
199205
acceptsFirstMouse?: ?boolean,
206+
207+
/**
208+
* Specifies whether clicking and dragging the view can move the window. This is useful
209+
* to disable in Button like components like Pressable where mouse the user should still
210+
* be able to click and drag off the view to cancel the click without accidentally moving the window.
211+
*
212+
* @platform macos
213+
*/
214+
mouseDownCanMoveWindow?: ?boolean,
215+
216+
/**
217+
* Specifies whether system focus ring should be drawn when the view has keyboard focus.
218+
*
219+
* @platform macos
220+
*/
200221
enableFocusRing?: ?boolean,
222+
223+
/**
224+
* Specifies the Tooltip for the Pressable.
225+
* @platform macos
226+
*/
201227
tooltip?: ?string,
228+
229+
/**
230+
* Fired when a file is dragged into the Pressable via the mouse.
231+
*
232+
* @platform macos
233+
*/
202234
onDragEnter?: (event: MouseEvent) => void,
235+
236+
/**
237+
* Fired when a file is dragged out of the Pressable via the mouse.
238+
*
239+
* @platform macos
240+
*/
203241
onDragLeave?: (event: MouseEvent) => void,
242+
243+
/**
244+
* Fired when a file is dropped on the Pressable via the mouse.
245+
*
246+
* @platform macos
247+
*/
204248
onDrop?: (event: MouseEvent) => void,
249+
250+
/**
251+
* The types of dragged files that the Pressable will accept.
252+
*
253+
* Possible values for `draggedTypes` are:
254+
*
255+
* - `'fileUrl'`
256+
*
257+
* @platform macos
258+
*/
205259
draggedTypes?: ?DraggedTypesType,
206260
// macOS]
207261

@@ -250,8 +304,6 @@ type Props = $ReadOnly<{|
250304
* LTI update could not be added via codemod */
251305
function Pressable(props: Props, forwardedRef): React.Node {
252306
const {
253-
acceptsFirstMouse, // [macOS]
254-
enableFocusRing, // [macOS]
255307
accessible,
256308
accessibilityState,
257309
'aria-live': ariaLive,
@@ -282,6 +334,9 @@ function Pressable(props: Props, forwardedRef): React.Node {
282334
onBlur,
283335
onKeyDown,
284336
onKeyUp,
337+
acceptsFirstMouse,
338+
mouseDownCanMoveWindow,
339+
enableFocusRing,
285340
// macOS]
286341
pressRetentionOffset,
287342
style,
@@ -322,7 +377,8 @@ function Pressable(props: Props, forwardedRef): React.Node {
322377
const restPropsWithDefaults: React.ElementConfig<typeof View> = {
323378
...restProps,
324379
...android_rippleConfig?.viewProps,
325-
acceptsFirstMouse: acceptsFirstMouse !== false && !disabled, // [macOS
380+
acceptsFirstMouse: acceptsFirstMouse !== false && !disabled, // [macOS]
381+
mouseDownCanMoveWindow: false, // [macOS]
326382
enableFocusRing: enableFocusRing !== false && !disabled,
327383
accessible: accessible !== false,
328384
accessibilityViewIsModal:

Libraries/Components/Pressable/__tests__/__snapshots__/Pressable-test.js.snap

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ exports[`<Pressable /> should render as expected: should deep render when mocked
2424
collapsable={false}
2525
enableFocusRing={true}
2626
focusable={true}
27+
mouseDownCanMoveWindow={false}
2728
onBlur={[Function]}
2829
onClick={[Function]}
2930
onFocus={[Function]}
@@ -64,6 +65,7 @@ exports[`<Pressable /> should render as expected: should deep render when not mo
6465
collapsable={false}
6566
enableFocusRing={true}
6667
focusable={true}
68+
mouseDownCanMoveWindow={false}
6769
onBlur={[Function]}
6870
onClick={[Function]}
6971
onFocus={[Function]}
@@ -116,6 +118,7 @@ exports[`<Pressable disabled={true} /> should be disabled when disabled is true:
116118
collapsable={false}
117119
enableFocusRing={false}
118120
focusable={false}
121+
mouseDownCanMoveWindow={false}
119122
onBlur={[Function]}
120123
onClick={[Function]}
121124
onFocus={[Function]}
@@ -156,6 +159,7 @@ exports[`<Pressable disabled={true} /> should be disabled when disabled is true:
156159
collapsable={false}
157160
enableFocusRing={false}
158161
focusable={false}
162+
mouseDownCanMoveWindow={false}
159163
onBlur={[Function]}
160164
onClick={[Function]}
161165
onFocus={[Function]}
@@ -212,6 +216,7 @@ exports[`<Pressable disabled={true} accessibilityState={{}} /> should be disable
212216
collapsable={false}
213217
enableFocusRing={false}
214218
focusable={false}
219+
mouseDownCanMoveWindow={false}
215220
onBlur={[Function]}
216221
onClick={[Function]}
217222
onFocus={[Function]}
@@ -252,6 +257,7 @@ exports[`<Pressable disabled={true} accessibilityState={{}} /> should be disable
252257
collapsable={false}
253258
enableFocusRing={false}
254259
focusable={false}
260+
mouseDownCanMoveWindow={false}
255261
onBlur={[Function]}
256262
onClick={[Function]}
257263
onFocus={[Function]}
@@ -310,6 +316,7 @@ exports[`<Pressable disabled={true} accessibilityState={{checked: true}} /> shou
310316
collapsable={false}
311317
enableFocusRing={false}
312318
focusable={false}
319+
mouseDownCanMoveWindow={false}
313320
onBlur={[Function]}
314321
onClick={[Function]}
315322
onFocus={[Function]}
@@ -350,6 +357,7 @@ exports[`<Pressable disabled={true} accessibilityState={{checked: true}} /> shou
350357
collapsable={false}
351358
enableFocusRing={false}
352359
focusable={false}
360+
mouseDownCanMoveWindow={false}
353361
onBlur={[Function]}
354362
onClick={[Function]}
355363
onFocus={[Function]}
@@ -416,6 +424,7 @@ exports[`<Pressable disabled={true} accessibilityState={{disabled: false}} /> sh
416424
collapsable={false}
417425
enableFocusRing={false}
418426
focusable={false}
427+
mouseDownCanMoveWindow={false}
419428
onBlur={[Function]}
420429
onClick={[Function]}
421430
onFocus={[Function]}
@@ -456,6 +465,7 @@ exports[`<Pressable disabled={true} accessibilityState={{disabled: false}} /> sh
456465
collapsable={false}
457466
enableFocusRing={false}
458467
focusable={false}
468+
mouseDownCanMoveWindow={false}
459469
onBlur={[Function]}
460470
onClick={[Function]}
461471
onFocus={[Function]}

Libraries/Components/View/ReactNativeViewAttributes.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ const UIView = {
3737
style: ReactNativeStyleAttributes,
3838
// [macOS
3939
acceptsFirstMouse: true,
40+
mouseDownCanMoveWindow: true,
4041
enableFocusRing: true,
4142
focusable: true,
4243
onMouseEnter: true,

Libraries/Components/View/ViewPropTypes.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ export type DraggedTypesType = DraggedType | DraggedType[];
173173

174174
export interface ViewPropsMacOS {
175175
acceptsFirstMouse?: boolean | undefined;
176+
mouseDownCanMoveWindow?: boolean | undefined;
176177
enableFocusRing?: boolean | undefined;
177178
onMouseEnter?: ((event: MouseEvent) => void) | undefined;
178179
onMouseLeave?: ((event: MouseEvent) => void) | undefined;

Libraries/Components/View/ViewPropTypes.js

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -474,14 +474,14 @@ type IOSViewProps = $ReadOnly<{|
474474
// [macOS
475475
type MacOSViewProps = $ReadOnly<{|
476476
/**
477-
* Fired when a dragged element enters a valid drop target
477+
* Fired when a file is dragged into the view via the mouse.
478478
*
479479
* @platform macos
480480
*/
481481
onDragEnter?: (event: MouseEvent) => void,
482482

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

511511
/**
512-
* Specifies whether focus ring should be drawn when the view has the first responder status.
512+
* Specifies whether clicking and dragging the view can move the window. This is useful
513+
* to disable in Button like components like Pressable where mouse the user should still
514+
* be able to click and drag off the view to cancel the click without accidentally moving the window.
515+
*
516+
* @platform macos
517+
*/
518+
mouseDownCanMoveWindow?: ?boolean,
519+
520+
/**
521+
* Specifies whether system focus ring should be drawn when the view has keyboard focus.
513522
*
514523
* @platform macos
515524
*/
516525
enableFocusRing?: ?boolean,
517526

518527
/**
519-
* Enables Drag'n'Drop Support for certain types of dragged types
528+
* The types of dragged files that the view will accept.
520529
*
521530
* Possible values for `draggedTypes` are:
522531
*

Libraries/NativeComponent/BaseViewConfig.macos.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ const validAttributesForNonEventProps = {
5454
tooltip: true,
5555
validKeysDown: true,
5656
validKeysUp: true,
57+
mouseDownCanMoveWindow: true,
5758
};
5859

5960
// Props for bubbling and direct events

React/Base/RCTUIKit.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,9 @@ CGPathRef UIBezierPathCreateCGPathRef(UIBezierPath *path);
405405
* containing window is in the background.
406406
*/
407407
@property (nonatomic, assign) BOOL acceptsFirstMouse;
408+
409+
@property (nonatomic, assign) BOOL mouseDownCanMoveWindow;
410+
408411
/**
409412
* Specifies whether the view participates in the key view loop as user tabs through different controls
410413
* This is equivalent to acceptsFirstResponder on mac OS.

React/Base/macOS/RCTUIKit.m

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ @implementation RCTUIView
215215
NSColor *_backgroundColor;
216216
BOOL _clipsToBounds;
217217
BOOL _userInteractionEnabled;
218+
BOOL _mouseDownCanMoveWindow;
218219
}
219220

220221
+ (NSSet<NSString *> *)keyPathsForValuesAffectingValueForKey:(NSString *)key
@@ -243,6 +244,7 @@ @implementation RCTUIView
243244
self.wantsLayer = YES;
244245
self->_userInteractionEnabled = YES;
245246
self->_enableFocusRing = YES;
247+
self->_mouseDownCanMoveWindow = YES;
246248
}
247249
return self;
248250
}
@@ -288,6 +290,14 @@ - (void)viewDidMoveToWindow
288290
[self didMoveToWindow];
289291
}
290292

293+
- (BOOL)mouseDownCanMoveWindow{
294+
return _mouseDownCanMoveWindow;
295+
}
296+
297+
- (void)setMouseDownCanMoveWindow:(BOOL)mouseDownCanMoveWindow{
298+
_mouseDownCanMoveWindow = mouseDownCanMoveWindow;
299+
}
300+
291301
- (BOOL)isFlipped
292302
{
293303
return YES;

React/Views/RCTView.m

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ @implementation RCTView {
133133
#if TARGET_OS_OSX // [macOS
134134
NSTrackingArea *_trackingArea;
135135
BOOL _hasMouseOver;
136+
BOOL _mouseDownCanMoveWindow;
136137
#endif // macOS]
137138
NSMutableDictionary<NSString *, NSDictionary *> *accessibilityActionsNameMap;
138139
NSMutableDictionary<NSString *, NSDictionary *> *accessibilityActionsLabelMap;
@@ -172,6 +173,7 @@ - (instancetype)initWithFrame:(CGRect)frame
172173
#if TARGET_OS_OSX // [macOS
173174
_transform3D = CATransform3DIdentity;
174175
_shadowColor = nil;
176+
_mouseDownCanMoveWindow = YES;
175177
#endif // macOS]
176178

177179
_backgroundColor = super.backgroundColor;
@@ -1495,6 +1497,15 @@ - (void)mouseExited:(NSEvent *)event
14951497
additionalData:nil];
14961498
}
14971499

1500+
- (BOOL)mouseDownCanMoveWindow{
1501+
return _mouseDownCanMoveWindow;
1502+
}
1503+
1504+
- (void)setMouseDownCanMoveWindow:(BOOL)mouseDownCanMoveWindow{
1505+
_mouseDownCanMoveWindow = mouseDownCanMoveWindow;
1506+
}
1507+
1508+
14981509
- (NSDictionary*)locationInfoFromEvent:(NSEvent*)event
14991510
{
15001511
NSPoint locationInWindow = event.locationInWindow;

React/Views/RCTViewManager.m

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,12 +417,16 @@ - (RCTShadowView *)shadowView
417417
view.acceptsFirstMouse = json ? [RCTConvert BOOL:json] : defaultView.acceptsFirstMouse;
418418
}
419419
}
420+
421+
RCT_EXPORT_VIEW_PROPERTY(mouseDownCanMoveWindow, BOOL)
422+
420423
RCT_CUSTOM_VIEW_PROPERTY(focusable, BOOL, RCTView)
421424
{
422425
if ([view respondsToSelector:@selector(setFocusable:)]) {
423426
view.focusable = json ? [RCTConvert BOOL:json] : defaultView.focusable;
424427
}
425428
}
429+
426430
RCT_CUSTOM_VIEW_PROPERTY(enableFocusRing, BOOL, RCTView)
427431
{
428432
if ([view respondsToSelector:@selector(setEnableFocusRing:)]) {
@@ -511,6 +515,7 @@ - (RCTShadowView *)shadowView
511515
RCT_EXPORT_VIEW_PROPERTY(onKeyUp, RCTDirectEventBlock) // macOS keyboard events
512516
RCT_EXPORT_VIEW_PROPERTY(validKeysDown, NSArray<NSString*>)
513517
RCT_EXPORT_VIEW_PROPERTY(validKeysUp, NSArray<NSString*>)
518+
514519
#endif // macOS]
515520

516521
#pragma mark - ShadowView properties

0 commit comments

Comments
 (0)