diff --git a/src/lib/menu/menu-trigger.ts b/src/lib/menu/menu-trigger.ts index 0555ed61791..88b5112d919 100644 --- a/src/lib/menu/menu-trigger.ts +++ b/src/lib/menu/menu-trigger.ts @@ -454,7 +454,9 @@ export class MatMenuTrigger implements AfterContentInit, OnDestroy { /** Handles mouse presses on the trigger. */ _handleMousedown(event: MouseEvent): void { if (!isFakeMousedownFromScreenReader(event)) { - this._openedByMouse = true; + // Since right or middle button clicks won't trigger the `click` event, + // we shouldn't consider the menu as opened by mouse in those cases. + this._openedByMouse = event.button === 0; // Since clicking on the trigger won't close the menu if it opens a sub-menu, // we should prevent focus from moving onto it via click to avoid the diff --git a/src/lib/menu/menu.spec.ts b/src/lib/menu/menu.spec.ts index c1f18c6ae05..70eb2e4131a 100644 --- a/src/lib/menu/menu.spec.ts +++ b/src/lib/menu/menu.spec.ts @@ -208,7 +208,7 @@ describe('MatMenu', () => { fixture.detectChanges(); const triggerEl = fixture.componentInstance.triggerEl.nativeElement; - dispatchFakeEvent(triggerEl, 'mousedown'); + dispatchMouseEvent(triggerEl, 'mousedown'); triggerEl.click(); fixture.detectChanges(); patchElementFocus(triggerEl); @@ -222,6 +222,31 @@ describe('MatMenu', () => { focusMonitor.stopMonitoring(triggerEl); })); + it('should set proper focus origin when right clicking on trigger, before opening by keyboard', + fakeAsync(() => { + const fixture = createComponent(SimpleMenu, [], [FakeIcon]); + fixture.detectChanges(); + const triggerEl = fixture.componentInstance.triggerEl.nativeElement; + + patchElementFocus(triggerEl); + focusMonitor.monitor(triggerEl, false); + + // Trigger a fake right click. + dispatchEvent(triggerEl, createMouseEvent('mousedown', 50, 100, 2)); + + // A click without a left button mousedown before it is considered a keyboard open. + triggerEl.click(); + fixture.detectChanges(); + + fixture.componentInstance.trigger.closeMenu(); + fixture.detectChanges(); + tick(500); + fixture.detectChanges(); + + expect(triggerEl.classList).toContain('cdk-program-focused'); + focusMonitor.stopMonitoring(triggerEl); + })); + it('should close the menu when pressing ESCAPE', fakeAsync(() => { const fixture = createComponent(SimpleMenu, [], [FakeIcon]); fixture.detectChanges(); @@ -347,7 +372,7 @@ describe('MatMenu', () => { const triggerEl = fixture.componentInstance.triggerEl.nativeElement; - dispatchFakeEvent(triggerEl, 'mousedown'); + dispatchMouseEvent(triggerEl, 'mousedown'); triggerEl.click(); fixture.detectChanges(); tick(500);