material-web icon indicating copy to clipboard operation
material-web copied to clipboard

[mwc-menu] not catching key events when opened upon a right mouse click

Open vdegenne opened this issue 3 years ago • 3 comments

I am using the 0.25.3 version.

I have this logic on the main interface that implements a context menu on right click (very common thing in apps)

firstUpdated() {

  // Prevents Chrome context menu from opening on right click
  this.addEventListener('contextmenu', e=> e.preventDefault()) 

  // Opens menu on right click
  this.addEventListener('pointerdown', e => {
    if (e.button == 2) {
      document.body.click() // close all others menu
      // open menu at the pointer location (using e coords)
      // ...
    }
  })
  
  // Menu Hotkeys
  this.menu.addEventListener('keydown', e => {
    if (e.code == 'KeyS') {
      // execute command
    }
  })

}

When I right click on the interface the menu opens at the pointer location as expected. But when I try to press S to activate the hotkey, it doesn't work. If I change e.button == 2 to e.button == 0 and try with the left click it works, which means the right click is not initiating focus.

Could that be an issue with the element? or is this behavior caused by the way the browser is built, independent from this element?

vdegenne avatar Apr 30 '22 14:04 vdegenne

I can't find a temporary solution I tried this :

this.addEventListener('pointerdown', e =>{
  if (e.button === 2) {
    document.body.click() // close all others menu

    // Open menu at (e.x, e.y)

    // Virtual click?
    // this.menu.click()
    // this.dispatchEvent(new MouseEvent('pointerdown', {button: 0}))
    this.menu.dispatchEvent(new MouseEvent('pointerdown', {button: 0}))

    // Trying different blur?
    // this.menu.blur()
    // this.blur()

    // Clicking the non interactive list-item?
    // setTimeout(()=>(this.shadowRoot!.querySelector('[noninteractive]') as ListItem).click(), 200)
  }
}

No one works.

Could you let me know a plausible solution if you think of one? (without binding event handler to the window object)

Thanks

vdegenne avatar Apr 30 '22 15:04 vdegenne

NOTE : if I remove the property quick from the <mwc-menu> element, the hotkey works. 😕 ?

vdegenne avatar Apr 30 '22 15:04 vdegenne

I temporarily fixed this issue using

// @ts-ignore
setTimeout(()=>this.menu.listElement_.focus(), 0)

note 1 : this.menu.focus() instead didn't work. note 2 : I do not need this hack if not using quick note 3 : I also am not sure why I needed to use a timeout here (await on both the menu or the list didn't work too).

Hope that helps to start investigating the problem.

I think this is an embarrassing issue, when implementing a contextual menu one would need to be able to catch any keyboard events and avoid dispatching them in the rest of the DOM tree up to the window object, which may have more globally scoped app hotkeys, whether it is a left or a right click.

vdegenne avatar Apr 30 '22 16:04 vdegenne

Closing since this is old mwc, but let us know if this pattern still isn't working in M3

asyncliz avatar Aug 02 '23 16:08 asyncliz