Skip to content

Commit

Permalink
Fix problems with window.menuBarVisbility 'compact' (#10626)
Browse files Browse the repository at this point in the history
- Adds option to remove `anchor` arg from context menus
- Preserve focus context when using side menus
  • Loading branch information
colin-grant-work authored Jan 21, 2022
1 parent 96ff4ee commit 4bf7a93
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 7 deletions.
2 changes: 1 addition & 1 deletion packages/core/src/browser/common-frontend-contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,7 @@ export class CommonFrontendContribution implements FrontendApplicationContributi
id: mainMenuId,
iconClass: 'codicon codicon-menu',
title: nls.localizeByDefault('Application Menu'),
menuPath: ['menubar'],
menuPath: MAIN_MENU_BAR,
order: 0,
});
} else {
Expand Down
20 changes: 15 additions & 5 deletions packages/core/src/browser/context-menu-renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,17 @@ export abstract class ContextMenuRenderer {
}

export interface RenderContextMenuOptions {
menuPath: MenuPath
anchor: Anchor
args?: any[]
onHide?: () => void
menuPath: MenuPath;
anchor: Anchor;
args?: any[];
/**
* Whether the anchor should be passed as an argument to the handlers of commands for this context menu.
* If true, the anchor will be appended to the list of arguments or passed as the only argument if no other
* arguments are supplied.
* Default is `true`.
*/
includeAnchorArg?: boolean;
onHide?: () => void;
}
export namespace RenderContextMenuOptions {
export function resolve(menuPathOrOptions: MenuPath | RenderContextMenuOptions, anchor?: Anchor, onHide?: () => void): RenderContextMenuOptions {
Expand All @@ -110,7 +117,10 @@ export namespace RenderContextMenuOptions {
menuPath = menuPathOrOptions.menuPath;
anchor = menuPathOrOptions.anchor;
onHide = menuPathOrOptions.onHide;
args = menuPathOrOptions.args ? [...menuPathOrOptions.args, anchor] : [anchor];
args = menuPathOrOptions.args ? menuPathOrOptions.args.slice() : [];
if (menuPathOrOptions.includeAnchorArg !== false) {
args.push(anchor);
}
}
return {
menuPath,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export class SidebarBottomMenuWidget extends SidebarMenuWidget {
const button = e.currentTarget.getBoundingClientRect();
this.contextMenuRenderer.render({
menuPath,
includeAnchorArg: false,
anchor: {
x: button.left + button.width,
y: button.top + button.height,
Expand Down
35 changes: 34 additions & 1 deletion packages/core/src/browser/shell/sidebar-menu-widget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,14 @@ export interface SidebarMenu {
@injectable()
export class SidebarMenuWidget extends ReactWidget {
protected readonly menus: SidebarMenu[];
/**
* The element that had focus when a menu rendered by this widget was activated.
*/
protected preservedContext: HTMLElement | undefined;
/**
* Flag indicating whether a context menu is open. While a context menu is open, the `preservedContext` should not be cleared.
*/
protected preservingContext = false;

@inject(ContextMenuRenderer)
protected readonly contextMenuRenderer: ContextMenuRenderer;
Expand All @@ -55,6 +63,7 @@ export class SidebarMenuWidget extends ReactWidget {
return;
}
this.menus.push(menu);
this.menus.sort((a, b) => a.order - b.order);
this.update();
}

Expand All @@ -69,24 +78,48 @@ export class SidebarMenuWidget extends ReactWidget {
}
}

protected readonly onMouseDown = () => {
const { activeElement } = document;
if (activeElement instanceof HTMLElement && !this.node.contains(activeElement)) {
this.preservedContext = activeElement;
}
};

protected readonly onMouseOut = () => {
if (!this.preservingContext) {
this.preservedContext = undefined;
}
};

protected onClick(e: React.MouseEvent<HTMLElement, MouseEvent>, menuPath: MenuPath): void {
this.preservingContext = true;
const button = e.currentTarget.getBoundingClientRect();
this.contextMenuRenderer.render({
menuPath,
includeAnchorArg: false,
anchor: {
x: button.left + button.width,
y: button.top,
},
onHide: () => {
this.preservingContext = false;
if (this.preservedContext) {
this.preservedContext.focus({ preventScroll: true });
this.preservedContext = undefined;
}
}
});
}

protected render(): React.ReactNode {
return <React.Fragment>
{this.menus.sort((a, b) => a.order - b.order).map(menu => <i
{this.menus.map(menu => <i
key={menu.id}
className={menu.iconClass}
title={menu.title}
onClick={e => this.onClick(e, menu.menuPath)}
onMouseDown={this.onMouseDown}
onMouseOut={this.onMouseOut}
/>)}
</React.Fragment>;
}
Expand Down

0 comments on commit 4bf7a93

Please sign in to comment.