Skip to content

Commit 13f0565

Browse files
Brian Vaughnzhengjitf
authored andcommitted
Sceduling profiler: Added custom view cursors (facebook#21970)
1 parent 745956e commit 13f0565

File tree

10 files changed

+257
-55
lines changed

10 files changed

+257
-55
lines changed

packages/react-devtools-scheduling-profiler/src/CanvasPage.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -273,10 +273,16 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) {
273273
}, [width, height]);
274274

275275
const interactor = useCallback(interaction => {
276-
if (canvasRef.current === null) {
276+
const canvas = canvasRef.current;
277+
if (canvas === null) {
277278
return;
278279
}
279-
surfaceRef.current.handleInteraction(interaction);
280+
281+
const surface = surfaceRef.current;
282+
surface.handleInteraction(interaction);
283+
284+
canvas.style.cursor = surface.getCurrentCursor() || 'default';
285+
280286
// Defer drawing to canvas until React's commit phase, to avoid drawing
281287
// twice and to ensure that both the canvas and DOM elements managed by
282288
// React are in sync.

packages/react-devtools-scheduling-profiler/src/content-views/FlamechartView.js

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,13 @@ import type {
1212
FlamechartStackFrame,
1313
FlamechartStackLayer,
1414
} from '../types';
15-
import type {Interaction, MouseMoveInteraction, Rect, Size} from '../view-base';
15+
import type {
16+
Interaction,
17+
MouseMoveInteraction,
18+
Rect,
19+
Size,
20+
ViewRef,
21+
} from '../view-base';
1622

1723
import {
1824
ColorView,
@@ -240,7 +246,11 @@ class FlamechartStackLayerView extends View {
240246
/**
241247
* @private
242248
*/
243-
_handleMouseMove(interaction: MouseMoveInteraction) {
249+
_handleMouseMove(
250+
interaction: MouseMoveInteraction,
251+
activeViewRef: ViewRef,
252+
hoveredViewRef: ViewRef,
253+
) {
244254
const {_stackLayer, frame, _intrinsicSize, _onHover, visibleArea} = this;
245255
const {location} = interaction.payload;
246256
if (!_onHover || !rectContainsPoint(location, visibleArea)) {
@@ -259,6 +269,8 @@ class FlamechartStackLayerView extends View {
259269
const width = durationToWidth(duration, scaleFactor);
260270
const x = Math.floor(timestampToPosition(timestamp, scaleFactor, frame));
261271
if (x <= location.x && x + width >= location.x) {
272+
this.currentCursor = 'pointer';
273+
hoveredViewRef.current = this;
262274
_onHover(flamechartStackFrame);
263275
return;
264276
}
@@ -273,10 +285,16 @@ class FlamechartStackLayerView extends View {
273285
_onHover(null);
274286
}
275287

276-
handleInteraction(interaction: Interaction) {
288+
_didGrab: boolean = false;
289+
290+
handleInteraction(
291+
interaction: Interaction,
292+
activeViewRef: ViewRef,
293+
hoveredViewRef: ViewRef,
294+
) {
277295
switch (interaction.type) {
278296
case 'mousemove':
279-
this._handleMouseMove(interaction);
297+
this._handleMouseMove(interaction, activeViewRef, hoveredViewRef);
280298
break;
281299
}
282300
}

packages/react-devtools-scheduling-profiler/src/content-views/NativeEventsView.js

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,13 @@
88
*/
99

1010
import type {NativeEvent, ReactProfilerData} from '../types';
11-
import type {Interaction, MouseMoveInteraction, Rect, Size} from '../view-base';
11+
import type {
12+
Interaction,
13+
MouseMoveInteraction,
14+
Rect,
15+
Size,
16+
ViewRef,
17+
} from '../view-base';
1218

1319
import {
1420
durationToWidth,
@@ -72,7 +78,6 @@ export class NativeEventsView extends View {
7278
this._profilerData = profilerData;
7379

7480
this._performPreflightComputations();
75-
console.log(this._depthToNativeEvent);
7681
}
7782

7883
_performPreflightComputations() {
@@ -250,7 +255,11 @@ export class NativeEventsView extends View {
250255
/**
251256
* @private
252257
*/
253-
_handleMouseMove(interaction: MouseMoveInteraction) {
258+
_handleMouseMove(
259+
interaction: MouseMoveInteraction,
260+
activeViewRef: ViewRef,
261+
hoveredViewRef: ViewRef,
262+
) {
254263
const {frame, _intrinsicSize, onHover, visibleArea} = this;
255264
if (!onHover) {
256265
return;
@@ -279,6 +288,10 @@ export class NativeEventsView extends View {
279288
hoverTimestamp >= timestamp &&
280289
hoverTimestamp <= timestamp + duration
281290
) {
291+
this.currentCursor = 'pointer';
292+
293+
hoveredViewRef.current = this;
294+
282295
onHover(nativeEvent);
283296
return;
284297
}
@@ -288,10 +301,14 @@ export class NativeEventsView extends View {
288301
onHover(null);
289302
}
290303

291-
handleInteraction(interaction: Interaction) {
304+
handleInteraction(
305+
interaction: Interaction,
306+
activeViewRef: ViewRef,
307+
hoveredViewRef: ViewRef,
308+
) {
292309
switch (interaction.type) {
293310
case 'mousemove':
294-
this._handleMouseMove(interaction);
311+
this._handleMouseMove(interaction, activeViewRef, hoveredViewRef);
295312
break;
296313
}
297314
}

packages/react-devtools-scheduling-profiler/src/content-views/ReactEventsView.js

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,13 @@
88
*/
99

1010
import type {ReactEvent, ReactProfilerData} from '../types';
11-
import type {Interaction, MouseMoveInteraction, Rect, Size} from '../view-base';
11+
import type {
12+
Interaction,
13+
MouseMoveInteraction,
14+
Rect,
15+
Size,
16+
ViewRef,
17+
} from '../view-base';
1218

1319
import {
1420
positioningScaleFactor,
@@ -225,7 +231,11 @@ export class ReactEventsView extends View {
225231
/**
226232
* @private
227233
*/
228-
_handleMouseMove(interaction: MouseMoveInteraction) {
234+
_handleMouseMove(
235+
interaction: MouseMoveInteraction,
236+
activeViewRef: ViewRef,
237+
hoveredViewRef: ViewRef,
238+
) {
229239
const {frame, onHover, visibleArea} = this;
230240
if (!onHover) {
231241
return;
@@ -260,6 +270,8 @@ export class ReactEventsView extends View {
260270
timestamp - eventTimestampAllowance <= hoverTimestamp &&
261271
hoverTimestamp <= timestamp + eventTimestampAllowance
262272
) {
273+
this.currentCursor = 'pointer';
274+
hoveredViewRef.current = this;
263275
onHover(event);
264276
return;
265277
}
@@ -268,10 +280,14 @@ export class ReactEventsView extends View {
268280
onHover(null);
269281
}
270282

271-
handleInteraction(interaction: Interaction) {
283+
handleInteraction(
284+
interaction: Interaction,
285+
activeViewRef: ViewRef,
286+
hoveredViewRef: ViewRef,
287+
) {
272288
switch (interaction.type) {
273289
case 'mousemove':
274-
this._handleMouseMove(interaction);
290+
this._handleMouseMove(interaction, activeViewRef, hoveredViewRef);
275291
break;
276292
}
277293
}

packages/react-devtools-scheduling-profiler/src/content-views/ReactMeasuresView.js

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,13 @@
88
*/
99

1010
import type {ReactLane, ReactMeasure, ReactProfilerData} from '../types';
11-
import type {Interaction, MouseMoveInteraction, Rect, Size} from '../view-base';
11+
import type {
12+
Interaction,
13+
MouseMoveInteraction,
14+
Rect,
15+
Size,
16+
ViewRef,
17+
} from '../view-base';
1218

1319
import {
1420
durationToWidth,
@@ -250,7 +256,11 @@ export class ReactMeasuresView extends View {
250256
/**
251257
* @private
252258
*/
253-
_handleMouseMove(interaction: MouseMoveInteraction) {
259+
_handleMouseMove(
260+
interaction: MouseMoveInteraction,
261+
activeViewRef: ViewRef,
262+
hoveredViewRef: ViewRef,
263+
) {
254264
const {
255265
frame,
256266
_intrinsicSize,
@@ -300,6 +310,8 @@ export class ReactMeasuresView extends View {
300310
hoverTimestamp >= timestamp &&
301311
hoverTimestamp <= timestamp + duration
302312
) {
313+
this.currentCursor = 'pointer';
314+
hoveredViewRef.current = this;
303315
onHover(measure);
304316
return;
305317
}
@@ -308,10 +320,14 @@ export class ReactMeasuresView extends View {
308320
onHover(null);
309321
}
310322

311-
handleInteraction(interaction: Interaction) {
323+
handleInteraction(
324+
interaction: Interaction,
325+
activeViewRef: ViewRef,
326+
hoveredViewRef: ViewRef,
327+
) {
312328
switch (interaction.type) {
313329
case 'mousemove':
314-
this._handleMouseMove(interaction);
330+
this._handleMouseMove(interaction, activeViewRef, hoveredViewRef);
315331
break;
316332
}
317333
}

packages/react-devtools-scheduling-profiler/src/content-views/UserTimingMarksView.js

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,13 @@
88
*/
99

1010
import type {UserTimingMark} from '../types';
11-
import type {Interaction, MouseMoveInteraction, Rect, Size} from '../view-base';
11+
import type {
12+
Interaction,
13+
MouseMoveInteraction,
14+
Rect,
15+
Size,
16+
ViewRef,
17+
} from '../view-base';
1218

1319
import {
1420
positioningScaleFactor,
@@ -185,7 +191,11 @@ export class UserTimingMarksView extends View {
185191
/**
186192
* @private
187193
*/
188-
_handleMouseMove(interaction: MouseMoveInteraction) {
194+
_handleMouseMove(
195+
interaction: MouseMoveInteraction,
196+
activeViewRef: ViewRef,
197+
hoveredViewRef: ViewRef,
198+
) {
189199
const {frame, onHover, visibleArea} = this;
190200
if (!onHover) {
191201
return;
@@ -218,6 +228,8 @@ export class UserTimingMarksView extends View {
218228
timestamp - markTimestampAllowance <= hoverTimestamp &&
219229
hoverTimestamp <= timestamp + markTimestampAllowance
220230
) {
231+
this.currentCursor = 'pointer';
232+
hoveredViewRef.current = this;
221233
onHover(mark);
222234
return;
223235
}
@@ -226,10 +238,14 @@ export class UserTimingMarksView extends View {
226238
onHover(null);
227239
}
228240

229-
handleInteraction(interaction: Interaction) {
241+
handleInteraction(
242+
interaction: Interaction,
243+
activeViewRef: ViewRef,
244+
hoveredViewRef: ViewRef,
245+
) {
230246
switch (interaction.type) {
231247
case 'mousemove':
232-
this._handleMouseMove(interaction);
248+
this._handleMouseMove(interaction, activeViewRef, hoveredViewRef);
233249
break;
234250
}
235251
}

packages/react-devtools-scheduling-profiler/src/view-base/HorizontalPanAndZoomView.js

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import type {
1919
} from './useCanvasInteraction';
2020
import type {Rect} from './geometry';
2121
import type {ScrollState} from './utils/scrollState';
22+
import type {ViewRef} from './Surface';
2223

2324
import {Surface} from './Surface';
2425
import {View} from './View';
@@ -155,13 +156,39 @@ export class HorizontalPanAndZoomView extends View {
155156
this._setScrollState(newState);
156157
}
157158

158-
_handleMouseDown(interaction: MouseDownInteraction) {
159+
_handleMouseDown(
160+
interaction: MouseDownInteraction,
161+
activeViewRef: ViewRef,
162+
hoveredViewRef: ViewRef,
163+
) {
159164
if (rectContainsPoint(interaction.payload.location, this.frame)) {
160165
this._isPanning = true;
166+
167+
activeViewRef.current = this;
168+
169+
this.currentCursor = 'grabbing';
161170
}
162171
}
163172

164-
_handleMouseMove(interaction: MouseMoveInteraction) {
173+
_handleMouseMove(
174+
interaction: MouseMoveInteraction,
175+
activeViewRef: ViewRef,
176+
hoveredViewRef: ViewRef,
177+
) {
178+
const isHovered = rectContainsPoint(
179+
interaction.payload.location,
180+
this.frame,
181+
);
182+
if (isHovered) {
183+
hoveredViewRef.current = this;
184+
}
185+
186+
if (activeViewRef.current === this) {
187+
this.currentCursor = 'grabbing';
188+
} else if (isHovered) {
189+
this.currentCursor = 'grab';
190+
}
191+
165192
if (!this._isPanning) {
166193
return;
167194
}
@@ -173,10 +200,18 @@ export class HorizontalPanAndZoomView extends View {
173200
this._setStateAndInformCallbacksIfChanged(newState);
174201
}
175202

176-
_handleMouseUp(interaction: MouseUpInteraction) {
203+
_handleMouseUp(
204+
interaction: MouseUpInteraction,
205+
activeViewRef: ViewRef,
206+
hoveredViewRef: ViewRef,
207+
) {
177208
if (this._isPanning) {
178209
this._isPanning = false;
179210
}
211+
212+
if (activeViewRef.current === this) {
213+
activeViewRef.current = null;
214+
}
180215
}
181216

182217
_handleWheelPlain(interaction: WheelPlainInteraction) {
@@ -238,16 +273,20 @@ export class HorizontalPanAndZoomView extends View {
238273
this._setStateAndInformCallbacksIfChanged(newState);
239274
}
240275

241-
handleInteraction(interaction: Interaction) {
276+
handleInteraction(
277+
interaction: Interaction,
278+
activeViewRef: ViewRef,
279+
hoveredViewRef: ViewRef,
280+
) {
242281
switch (interaction.type) {
243282
case 'mousedown':
244-
this._handleMouseDown(interaction);
283+
this._handleMouseDown(interaction, activeViewRef, hoveredViewRef);
245284
break;
246285
case 'mousemove':
247-
this._handleMouseMove(interaction);
286+
this._handleMouseMove(interaction, activeViewRef, hoveredViewRef);
248287
break;
249288
case 'mouseup':
250-
this._handleMouseUp(interaction);
289+
this._handleMouseUp(interaction, activeViewRef, hoveredViewRef);
251290
break;
252291
case 'wheel-plain':
253292
this._handleWheelPlain(interaction);

0 commit comments

Comments
 (0)