@@ -45,6 +45,13 @@ import flameChartStyles from './flameChart.css.legacy.js';
4545import { DEFAULT_FONT_SIZE , getFontFamilyForCanvas } from './Font.js' ;
4646import { 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+
4855const 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