Skip to content

Commit 48973b4

Browse files
jackfranklinDevtools-frontend LUCI CQ
authored andcommitted
RPP: fix context menu on events firing with keyboard
This CL fixes a bug where we used the wrong index to know where to fire the context menu. See the comments in the code for the full description. Fixed: 375349233 Change-Id: Ib6715da0f361bd17b35b42d068be2652932d26d7 Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/5961998 Auto-Submit: Jack Franklin <[email protected]> Reviewed-by: Alina Varkki <[email protected]> Commit-Queue: Jack Franklin <[email protected]>
1 parent 2592f94 commit 48973b4

File tree

1 file changed

+34
-12
lines changed

1 file changed

+34
-12
lines changed

front_end/ui/legacy/components/perf_ui/FlameChart.ts

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,13 @@ import flameChartStyles from './flameChart.css.legacy.js';
4545
import {DEFAULT_FONT_SIZE, getFontFamilyForCanvas} from './Font.js';
4646
import {type Calculator, TimelineGrid} from './TimelineGrid.js';
4747

48+
/**
49+
* Set as the `details` value on the fake context menu event we dispatch to
50+
* trigger a context menu on an event on a keyboard space key press.
51+
{@see onContextMenu} for more details and explanation.
52+
*/
53+
const KEYBOARD_FAKED_CONTEXT_MENU_DETAIL = -1;
54+
4855
const UIStrings = {
4956
/**
5057
*@description Aria alert used to notify the user when an event has been selected because they tabbed into a group.
@@ -1364,19 +1371,32 @@ export class FlameChart extends Common.ObjectWrapper.eventMixin<EventTypes, type
13641371
this.#buildEnterEditModeContextMenu(event);
13651372
}
13661373

1367-
if (this.highlightedEntryIndex === -1) {
1368-
// If the user has not selected an individual entry, we do not show any
1369-
// context menu, so finish here.
1374+
// The user can create context menus in two ways:
1375+
// 1. they right click and a contextMenu event is dispatched from the
1376+
// browser. This event will be trusted.
1377+
// 2. they press "space" on the keyboard and we dispatch the event
1378+
// ourselves from {@see triggerContextMenuFromKeyPress}.
1379+
// To enable us to differentiate, we set the detail property
1380+
// [https://developer.mozilla.org/en-US/docs/Web/API/UIEvent/detail] to a
1381+
// specific number (-1) for our faked context menu event. We can do this
1382+
// because the detail property is never natively set to a negative number.
1383+
// The reason this is important is because the highlightedEntryIndex is
1384+
// only updated when the mouse moves, so if the user is navigating +
1385+
// triggering menus via the keyboard, it will not be updated, and we should
1386+
// use the selectedEntryIndex.
1387+
const isFakedFromKeyboardPress = event.detail === KEYBOARD_FAKED_CONTEXT_MENU_DETAIL;
1388+
const entryIndexToUse = isFakedFromKeyboardPress ? this.selectedEntryIndex : this.highlightedEntryIndex;
1389+
1390+
if (entryIndexToUse === -1) {
13701391
return;
13711392
}
13721393

1373-
// Update the selected index to match the highlighted index, which
1374-
// represents the entry under the cursor where the user has right clicked
1375-
// to trigger a context menu.
1376-
this.dispatchEventToListeners(Events.ENTRY_INVOKED, this.highlightedEntryIndex);
1377-
this.setSelectedEntry(this.highlightedEntryIndex);
1378-
// Update the selected group as well.
1379-
this.#selectGroup(groupIndex);
1394+
if (!isFakedFromKeyboardPress) {
1395+
this.dispatchEventToListeners(Events.ENTRY_INVOKED, entryIndexToUse);
1396+
this.setSelectedEntry(entryIndexToUse);
1397+
// Update the selected group as well.
1398+
this.#selectGroup(groupIndex);
1399+
}
13801400

13811401
// Build the context menu for right clicking individual entries.
13821402
// The context menu only applies if the user is hovering over an individual
@@ -1457,7 +1477,9 @@ export class FlameChart extends Common.ObjectWrapper.eventMixin<EventTypes, type
14571477
const x = this.chartViewport.timeToPosition(startTime) + boundingRect.left;
14581478
const y = this.levelToOffset(level) - this.getScrollOffset() + boundingRect.top;
14591479

1460-
const event = new MouseEvent('contextmenu', {clientX: x, clientY: y});
1480+
// Set the `detail` key so in the context menu handler we can differentiate
1481+
// between a keyboard invoked context menu and a mouse invoked one.
1482+
const event = new MouseEvent('contextmenu', {clientX: x, clientY: y, detail: KEYBOARD_FAKED_CONTEXT_MENU_DETAIL});
14611483
this.canvas.dispatchEvent(event);
14621484
}
14631485

@@ -1467,8 +1489,8 @@ export class FlameChart extends Common.ObjectWrapper.eventMixin<EventTypes, type
14671489
}
14681490

14691491
if (e.key === ' ' && this.selectedEntryIndex > -1) {
1470-
this.#triggerContextMenuFromKeyPress();
14711492
// If the user has an event selected, and there is a selected entry, then we open the context menu at this event.
1493+
this.#triggerContextMenuFromKeyPress();
14721494
}
14731495

14741496
let eventHandled = this.handleSelectionNavigation(e);

0 commit comments

Comments
 (0)