Main View keybindings (#463)

* added all mainviews except session

* add session keybindings

* finished session keybindings

* organized by layer

* remove some webshare code and remove unused session cancel fn

* fixed checkkeypressed bug

* fixed kwargs, bug
This commit is contained in:
Cole Lashley 2024-03-18 23:41:45 -07:00 committed by GitHub
parent 901dcccaa5
commit 23fa1c3823
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 214 additions and 211 deletions

View File

@ -87,39 +87,48 @@
},
{
"command": "app:selectTab-1",
"keys": ["Cmd:1"]
"keys": ["Cmd:1"],
"commandStr":"/screen 1"
},
{
"command": "app:selectTab-2",
"keys": ["Cmd:2"]
"keys": ["Cmd:2"],
"commandStr":"/screen 2"
},
{
"command": "app:selectTab-3",
"keys": ["Cmd:3"]
"keys": ["Cmd:3"],
"commandStr":"/screen 3"
},
{
"command": "app:selectTab-4",
"keys": ["Cmd:4"]
"keys": ["Cmd:4"],
"commandStr":"/screen 4"
},
{
"command": "app:selectTab-5",
"keys": ["Cmd:5"]
"keys": ["Cmd:5"],
"commandStr":"/screen 5"
},
{
"command": "app:selectTab-6",
"keys": ["Cmd:6"]
"keys": ["Cmd:6"],
"commandStr":"/screen 6"
},
{
"command": "app:selectTab-7",
"keys": ["Cmd:7"]
"keys": ["Cmd:7"],
"commandStr":"/screen 7"
},
{
"command": "app:selectTab-8",
"keys": ["Cmd:8"]
"keys": ["Cmd:8"],
"commandStr":"/screen 8"
},
{
"command": "app:selectTab-9",
"keys": ["Cmd:9"]
"keys": ["Cmd:9"],
"commandStr":"/screen 9"
},
{
"command": "app:selectTabLeft",

View File

@ -5,6 +5,7 @@ import * as React from "react";
import * as mobxReact from "mobx-react";
import * as mobx from "mobx";
import { boundMethod } from "autobind-decorator";
import { If } from "tsx-control-statements/components";
import { GlobalModel, GlobalCommandRunner, RemotesModel, getApi } from "@/models";
import { Toggle, InlineSettingsTextEdit, SettingsError, Dropdown } from "@/common/elements";
import { commandRtnHandler, isBlank } from "@/util/util";
@ -13,6 +14,25 @@ import * as appconst from "@/app/appconst";
import "./clientsettings.less";
import { MainView } from "../common/elements/mainview";
class ClientSettingsKeybindings extends React.Component<{}, {}> {
componentDidMount() {
let clientSettingsViewModel = GlobalModel.clientSettingsViewModel;
let keybindManager = GlobalModel.keybindManager;
keybindManager.registerKeybinding("mainview", "clientsettings", "generic:cancel", (waveEvent) => {
clientSettingsViewModel.closeView();
return true;
});
}
componentWillUnmount() {
GlobalModel.keybindManager.unregisterDomain("clientsettings");
}
render() {
return null;
}
}
@mobxReact.observer
class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hoveredItemId: string }> {
errorMessage: OV<string> = mobx.observable.box(null, { name: "ClientSettings-errorMessage" });
@ -168,6 +188,9 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
return (
<MainView className="clientsettings-view" title="Client Settings" onClose={this.handleClose}>
<If condition={!isHidden}>
<ClientSettingsKeybindings></ClientSettingsKeybindings>
</If>
<div className="content">
<div className="settings-field">
<div className="settings-label">Term Font Size</div>

View File

@ -14,6 +14,25 @@ import * as util from "@/util/util";
import "./connections.less";
import { MainView } from "../common/elements/mainview";
class ConnectionsKeybindings extends React.Component<{}, {}> {
componentDidMount() {
let connectionViewModel = GlobalModel.connectionViewModel;
let keybindManager = GlobalModel.keybindManager;
keybindManager.registerKeybinding("mainview", "connections", "generic:cancel", (waveEvent) => {
connectionViewModel.closeView();
return true;
});
}
componentWillUnmount() {
GlobalModel.keybindManager.unregisterDomain("connections");
}
render() {
return null;
}
}
@mobxReact.observer
class ConnectionsView extends React.Component<{ model: RemotesModel }, { hoveredItemId: string }> {
tableRef: React.RefObject<any> = React.createRef();
@ -127,6 +146,9 @@ class ConnectionsView extends React.Component<{ model: RemotesModel }, { hovered
return (
<MainView className="connections-view" title="Connections" onClose={this.handleClose}>
<If condition={!isHidden}>
<ConnectionsKeybindings></ConnectionsKeybindings>
</If>
<table
className="connections-table"
cellSpacing="0"

View File

@ -169,6 +169,27 @@ class HistoryCmdStr extends React.Component<
}
}
class HistoryKeybindings extends React.Component<{}, {}> {
@boundMethod
componentDidMount() {
let historyViewModel = GlobalModel.historyViewModel;
let keybindManager = GlobalModel.keybindManager;
keybindManager.registerKeybinding("mainview", "history", "generic:cancel", (waveEvent) => {
historyViewModel.handleUserClose();
return true;
});
}
@boundMethod
componentWillUnmount() {
GlobalModel.keybindManager.unregisterDomain("history");
}
render() {
return null;
}
}
@mobxReact.observer
class HistoryView extends React.Component<{}, {}> {
tableRef: React.RefObject<any> = React.createRef();
@ -449,6 +470,9 @@ class HistoryView extends React.Component<{}, {}> {
return (
<MainView className="history-view" title="History" onClose={this.handleClose}>
<If condition={!isHidden}>
<HistoryKeybindings></HistoryKeybindings>
</If>
<div key="search" className="history-search">
<div className="main-search field">
<TextField

View File

@ -141,15 +141,6 @@ class MainSideBar extends React.Component<MainSideBarProps, {}> {
GlobalCommandRunner.connectionsView();
}
@boundMethod
handleWebSharingClick(): void {
if (GlobalModel.activeMainView.get() == "webshare") {
GlobalModel.showSessionView();
return;
}
GlobalModel.showWebShareView();
}
@boundMethod
handleSettingsClick(): void {
if (GlobalModel.activeMainView.get() == "clientsettings") {

View File

@ -7,6 +7,7 @@ import * as mobx from "mobx";
import cn from "classnames";
import dayjs from "dayjs";
import localizedFormat from "dayjs/plugin/localizedFormat";
import { If } from "tsx-control-statements/components";
import { GlobalModel } from "@/models";
import { CmdInput } from "./cmdinput/cmdinput";
import { ScreenView } from "./screen/screenview";
@ -17,6 +18,66 @@ import "./workspace.less";
dayjs.extend(localizedFormat);
class SessionKeybindings extends React.Component<{}, {}> {
componentDidMount() {
let keybindManager = GlobalModel.keybindManager;
keybindManager.registerKeybinding("mainview", "session", "app:toggleSidebar", (waveEvent) => {
GlobalModel.handleToggleSidebar();
return true;
});
keybindManager.registerKeybinding("mainview", "session", "app:newTab", (waveEvent) => {
GlobalModel.onNewTab();
return true;
});
keybindManager.registerKeybinding("mainview", "session", "app:closeCurrentTab", (waveEvent) => {
GlobalModel.onCloseCurrentTab();
return true;
});
for (let index = 1; index <= 9; index++) {
keybindManager.registerKeybinding("mainview", "session", "app:selectTab-" + index, null);
}
keybindManager.registerKeybinding("mainview", "session", "app:selectTabLeft", (waveEvent) => {
GlobalModel.onBracketCmd(-1);
return true;
});
keybindManager.registerKeybinding("mainview", "session", "app:selectTabRight", (waveEvent) => {
GlobalModel.onBracketCmd(1);
return true;
});
keybindManager.registerKeybinding("pane", "session", "app:selectLineAbove", (waveEvent) => {
GlobalModel.onMetaArrowUp();
return true;
});
keybindManager.registerKeybinding("pane", "session", "app:selectLineBelow", (waveEvent) => {
GlobalModel.onMetaArrowDown();
return true;
});
keybindManager.registerKeybinding("pane", "session", "app:restartCommand", (waveEvent) => {
GlobalModel.onRestartCommand();
return true;
});
keybindManager.registerKeybinding("pane", "session", "app:restartLastCommand", (waveEvent) => {
GlobalModel.onRestartLastCommand();
return true;
});
keybindManager.registerKeybinding("pane", "session", "app:focusSelectedLine", (waveEvent) => {
GlobalModel.onFocusSelectedLine();
return true;
});
keybindManager.registerKeybinding("pane", "session", "app:deleteActiveLine", (waveEvent) => {
return GlobalModel.handleDeleteActiveLine();
});
}
componentWillUnmount() {
GlobalModel.keybindManager.unregisterDomain("session");
}
render() {
return null;
}
}
@mobxReact.observer
class WorkspaceView extends React.Component<{}, {}> {
render() {
@ -47,6 +108,9 @@ class WorkspaceView extends React.Component<{}, {}> {
width: `${window.innerWidth - mainSidebarModel.getWidth()}px`,
}}
>
<If condition={!isHidden}>
<SessionKeybindings></SessionKeybindings>
</If>
<ScreenTabs key={"tabs-" + session.sessionId} session={session} />
<ErrorBoundary>
<ScreenView key={"screenview-" + session.sessionId} session={session} screen={activeScreen} />

View File

@ -359,59 +359,6 @@ function createMainWindow(clientData: ClientDataType | null): Electron.BrowserWi
if (input.type != "keyDown") {
return;
}
const mods = getMods(input);
if (checkKeyPressed(waveEvent, "Cmd:t")) {
win.webContents.send("t-cmd", mods);
e.preventDefault();
return;
}
if (checkKeyPressed(waveEvent, "Cmd:r")) {
e.preventDefault();
win.webContents.send("r-cmd", mods);
return;
}
if (checkKeyPressed(waveEvent, "Cmd:l")) {
win.webContents.send("l-cmd", mods);
e.preventDefault();
return;
}
if (checkKeyPressed(waveEvent, "Cmd:w")) {
e.preventDefault();
win.webContents.send("w-cmd", mods);
return;
}
if (checkKeyPressed(waveEvent, "Cmd:ArrowUp") || checkKeyPressed(waveEvent, "Cmd:ArrowDown")) {
if (checkKeyPressed(waveEvent, "Cmd:ArrowUp")) {
win.webContents.send("meta-arrowup");
} else {
win.webContents.send("meta-arrowdown");
}
e.preventDefault();
return;
}
if (checkKeyPressed(waveEvent, "Cmd:PageUp") || checkKeyPressed(waveEvent, "Cmd:PageDown")) {
if (checkKeyPressed(waveEvent, "Cmd:PageUp")) {
win.webContents.send("meta-pageup");
} else {
win.webContents.send("meta-pagedown");
}
e.preventDefault();
return;
}
if (input.code.startsWith("Digit") && input.meta && !input.control) {
const digitNum = parseInt(input.code.substring(5));
if (isNaN(digitNum) || digitNum < 1 || digitNum > 9) {
return;
}
e.preventDefault();
win.webContents.send("digit-cmd", { digit: digitNum }, mods);
}
if (checkKeyPressed(waveEvent, "Cmd:[") || checkKeyPressed(waveEvent, "Cmd:]")) {
const rel = checkKeyPressed(waveEvent, "Cmd:]") ? 1 : -1;
win.webContents.send("bracket-cmd", { relative: rel }, mods);
e.preventDefault();
return;
}
});
win.webContents.on("will-navigate", shNavHandler);
win.webContents.on("will-frame-navigate", shFrameNavHandler);

View File

@ -21,17 +21,7 @@ contextBridge.exposeInMainWorld("api", {
installAppUpdate: () => ipcRenderer.send("install-app-update"),
getAppUpdateStatus: () => ipcRenderer.sendSync("get-app-update-status"),
onAppUpdateStatus: (callback) => ipcRenderer.on("app-update-status", (_, val) => callback(val)),
onTCmd: (callback) => ipcRenderer.on("t-cmd", callback),
onLCmd: (callback) => ipcRenderer.on("l-cmd", callback),
onWCmd: (callback) => ipcRenderer.on("w-cmd", callback),
onRCmd: (callback) => ipcRenderer.on("r-cmd", callback),
onZoomChanged: (callback) => ipcRenderer.on("zoom-changed", callback),
onMetaArrowUp: (callback) => ipcRenderer.on("meta-arrowup", callback),
onMetaArrowDown: (callback) => ipcRenderer.on("meta-arrowdown", callback),
onMetaPageUp: (callback) => ipcRenderer.on("meta-pageup", callback),
onMetaPageDown: (callback) => ipcRenderer.on("meta-pagedown", callback),
onBracketCmd: (callback) => ipcRenderer.on("bracket-cmd", callback),
onDigitCmd: (callback) => ipcRenderer.on("digit-cmd", callback),
onMenuItemAbout: (callback) => ipcRenderer.on("menu-item-about", callback),
contextScreen: (screenOpts, position) => ipcRenderer.send("context-screen", screenOpts, position),
contextEditMenu: (position, opts) => ipcRenderer.send("context-editmenu", position, opts),

View File

@ -22,15 +22,6 @@ class ClientSettingsViewModel {
this.globalModel.activeMainView.set("clientsettings");
})();
}
handleDocKeyDown(e: any): void {
const waveEvent = adaptFromReactOrNativeKeyEvent(e);
if (checkKeyPressed(waveEvent, "Escape")) {
e.preventDefault();
this.closeView();
return;
}
}
}
export { ClientSettingsViewModel };

View File

@ -22,15 +22,6 @@ class ConnectionsViewModel {
this.globalModel.activeMainView.set("connections");
})();
}
handleDocKeyDown(e: any): void {
const waveEvent = adaptFromReactOrNativeKeyEvent(e);
if (checkKeyPressed(waveEvent, "Escape")) {
e.preventDefault();
this.closeView();
return;
}
}
}
export { ConnectionsViewModel };

View File

@ -290,13 +290,8 @@ class HistoryViewModel {
GlobalCommandRunner.historyView(this._getSearchParams(0, 0));
}
handleDocKeyDown(e: any): void {
const waveEvent = adaptFromReactOrNativeKeyEvent(e);
if (checkKeyPressed(waveEvent, "Escape")) {
e.preventDefault();
this.closeView();
return;
}
handleUserClose() {
this.closeView();
}
showHistoryView(data: HistoryViewDataType): void {

View File

@ -177,18 +177,8 @@ class Model {
}
return fontSize;
});
getApi().onTCmd(this.onTCmd.bind(this));
getApi().onLCmd(this.onLCmd.bind(this));
getApi().onWCmd(this.onWCmd.bind(this));
getApi().onRCmd(this.onRCmd.bind(this));
getApi().onZoomChanged(this.onZoomChanged.bind(this));
getApi().onMenuItemAbout(this.onMenuItemAbout.bind(this));
getApi().onMetaArrowUp(this.onMetaArrowUp.bind(this));
getApi().onMetaArrowDown(this.onMetaArrowDown.bind(this));
getApi().onMetaPageUp(this.onMetaPageUp.bind(this));
getApi().onMetaPageDown(this.onMetaPageDown.bind(this));
getApi().onBracketCmd(this.onBracketCmd.bind(this));
getApi().onDigitCmd(this.onDigitCmd.bind(this));
getApi().onWaveSrvStatusChange(this.onWaveSrvStatusChange.bind(this));
getApi().onAppUpdateStatus(this.onAppUpdateStatus.bind(this));
document.addEventListener("keydown", this.docKeyDownHandler.bind(this));
@ -383,12 +373,6 @@ class Model {
})();
}
showWebShareView(): void {
mobx.action(() => {
this.activeMainView.set("webshare");
})();
}
getBaseHostPort(): string {
if (this.isDev) {
return appconst.DevServerEndpoint;
@ -471,6 +455,22 @@ class Model {
// nothing for now
}
handleToggleSidebar() {
const activeScreen = this.getActiveScreen();
if (activeScreen != null) {
const isSidebarOpen = activeScreen.isSidebarOpen();
if (isSidebarOpen) {
GlobalCommandRunner.screenSidebarClose();
} else {
GlobalCommandRunner.screenSidebarOpen();
}
}
}
handleDeleteActiveLine(): boolean {
return this.deleteActiveLine();
}
docKeyDownHandler(e: KeyboardEvent) {
const waveEvent = adaptFromReactOrNativeKeyEvent(e);
if (isModKeyPress(e)) {
@ -493,47 +493,8 @@ class Model {
this.modalsModel.popModal();
return;
}
this.keybindManager.processKeyEvent(e, waveEvent);
if (this.activeMainView.get() == "history") {
this.historyViewModel.handleDocKeyDown(e);
}
if (this.activeMainView.get() == "connections") {
this.connectionViewModel.handleDocKeyDown(e);
}
if (this.activeMainView.get() == "clientsettings") {
this.clientSettingsViewModel.handleDocKeyDown(e);
} else {
if (checkKeyPressed(waveEvent, "Escape")) {
e.preventDefault();
if (this.activeMainView.get() == "webshare") {
this.showSessionView();
return;
}
const inputModel = this.inputModel;
inputModel.toggleInfoMsg();
if (inputModel.inputMode.get() != null) {
inputModel.resetInputMode();
}
return;
}
if (this.activeMainView.get() == "session" && checkKeyPressed(waveEvent, "Cmd:Ctrl:s")) {
e.preventDefault();
const activeScreen = this.getActiveScreen();
if (activeScreen != null) {
const isSidebarOpen = activeScreen.isSidebarOpen();
if (isSidebarOpen) {
GlobalCommandRunner.screenSidebarClose();
} else {
GlobalCommandRunner.screenSidebarOpen();
}
}
}
if (checkKeyPressed(waveEvent, "Cmd:d")) {
const ranDelete = this.deleteActiveLine();
if (ranDelete) {
e.preventDefault();
}
}
if (this.keybindManager.processKeyEvent(e, waveEvent)) {
return;
}
}
@ -562,7 +523,7 @@ class Model {
return true;
}
onWCmd(e: any, mods: KeyModsType) {
onCloseCurrentTab() {
if (this.activeMainView.get() != "session") {
return;
}
@ -582,7 +543,7 @@ class Model {
});
}
onRCmd(e: any, mods: KeyModsType) {
onRestartLastCommand() {
if (this.activeMainView.get() != "session") {
return;
}
@ -590,17 +551,22 @@ class Model {
if (activeScreen == null) {
return;
}
if (mods.shift) {
// restart last line
GlobalCommandRunner.lineRestart("E", true);
} else {
// restart selected line
const selectedLine = activeScreen.selectedLine.get();
if (selectedLine == null || selectedLine == 0) {
return;
}
GlobalCommandRunner.lineRestart(String(selectedLine), true);
GlobalCommandRunner.lineRestart("E", true);
}
onRestartCommand() {
if (this.activeMainView.get() != "session") {
return;
}
const activeScreen = this.getActiveScreen();
if (activeScreen == null) {
return;
}
const selectedLine = activeScreen.selectedLine.get();
if (selectedLine == null || selectedLine == 0) {
return;
}
GlobalCommandRunner.lineRestart(String(selectedLine), true);
}
onZoomChanged(): void {
@ -700,7 +666,7 @@ class Model {
return rtn;
}
onTCmd(e: any, mods: KeyModsType) {
onNewTab() {
GlobalCommandRunner.createNewScreen();
}
@ -722,7 +688,7 @@ class Model {
}
}
onLCmd(e: any, mods: KeyModsType) {
onFocusSelectedLine() {
const screen = this.getActiveScreen();
if (screen != null) {
GlobalCommandRunner.screenSetFocus("cmd");
@ -787,26 +753,19 @@ class Model {
})();
}
onMetaPageUp(): void {
GlobalCommandRunner.screenSelectLine("-1");
}
onMetaPageDown(): void {
GlobalCommandRunner.screenSelectLine("+1");
}
onMetaArrowUp(): void {
GlobalCommandRunner.screenSelectLine("-1");
}
onMetaArrowDown(): void {
console.log("meta arrow down?");
GlobalCommandRunner.screenSelectLine("+1");
}
onBracketCmd(e: any, arg: { relative: number }, mods: KeyModsType) {
if (arg.relative == 1) {
onBracketCmd(relative: number) {
if (relative == 1) {
GlobalCommandRunner.switchScreen("+");
} else if (arg.relative == -1) {
} else if (relative == -1) {
GlobalCommandRunner.switchScreen("-");
}
}
@ -1373,7 +1332,7 @@ class Model {
type: "fecmd",
metacmd: "eval",
args: [cmdStr],
kwargs: null,
kwargs: {},
uicontext: this.getUIContext(),
interactive: interactive,
rawstr: cmdStr,

10
src/types/custom.d.ts vendored
View File

@ -905,18 +905,8 @@ declare global {
installAppUpdate: () => void;
getAppUpdateStatus: () => AppUpdateStatusType;
onAppUpdateStatus: (callback: (status: AppUpdateStatusType) => void) => void;
onTCmd: (callback: (mods: KeyModsType) => void) => void;
onLCmd: (callback: (mods: KeyModsType) => void) => void;
onRCmd: (callback: (mods: KeyModsType) => void) => void;
onWCmd: (callback: (mods: KeyModsType) => void) => void;
onZoomChanged: (callback: () => void) => void;
onMenuItemAbout: (callback: () => void) => void;
onMetaArrowUp: (callback: () => void) => void;
onMetaArrowDown: (callback: () => void) => void;
onMetaPageUp: (callback: () => void) => void;
onMetaPageDown: (callback: () => void) => void;
onBracketCmd: (callback: (event: any, arg: { relative: number }, mods: KeyModsType) => void) => void;
onDigitCmd: (callback: (event: any, arg: { digit: number }, mods: KeyModsType) => void) => void;
contextScreen: (screenOpts: { screenId: string }, position: { x: number; y: number }) => void;
contextEditMenu: (position: { x: number; y: number }, opts: ContextMenuOpts) => void;
onWaveSrvStatusChange: (callback: (status: boolean, pid: number) => void) => void;

View File

@ -129,7 +129,6 @@ class KeybindManager {
return true;
}
let curCommand = commandsList.shift();
console.log("running: ", curCommand);
let prtn = this.globalModel.submitRawCommand(curCommand, false, false);
prtn.then((rtn) => {
if (!rtn.success) {
@ -174,18 +173,17 @@ class KeybindManager {
return false;
}
processKeyEvent(nativeEvent: any, event: WaveKeyboardEvent) {
processKeyEvent(nativeEvent: any, event: WaveKeyboardEvent): boolean {
let modalLevel = this.levelMap.get("modal");
if (modalLevel.length != 0) {
// console.log("processing modal");
// special case when modal keybindings are present
let shouldReturn = this.processLevel(nativeEvent, event, modalLevel);
if (shouldReturn) {
return;
return true;
}
let systemLevel = this.levelMap.get("system");
this.processLevel(nativeEvent, event, systemLevel);
return;
return this.processLevel(nativeEvent, event, systemLevel);
}
for (let index = this.levelArray.length - 1; index >= 0; index--) {
let curLevel = this.levelArray[index];
@ -198,9 +196,10 @@ class KeybindManager {
}
let shouldReturn = this.processLevel(nativeEvent, event, curKeybindsArray);
if (shouldReturn) {
return;
return true;
}
}
return false;
}
keybindingAlreadyAdded(level: string, domain: string, keybinding: string) {
@ -358,6 +357,7 @@ function parseKeyDescription(keyDescription: string): KeyPressDecl {
for (let key of keys) {
if (key == "Cmd") {
rtn.mods.Cmd = true;
rtn.mods.Meta = true;
} else if (key == "Shift") {
rtn.mods.Shift = true;
} else if (key == "Ctrl") {
@ -398,24 +398,31 @@ function parseKey(key: string): { key: string; type: string } {
return { key: key, type: KeyTypeKey };
}
function notMod(keyPressMod, eventMod) {
if (keyPressMod != true) {
keyPressMod = false;
}
return (keyPressMod && !eventMod) || (eventMod && !keyPressMod);
}
function checkKeyPressed(event: WaveKeyboardEvent, keyDescription: string): boolean {
let keyPress = parseKeyDescription(keyDescription);
if (keyPress.mods.Option && !event.option) {
if (notMod(keyPress.mods.Option, event.option)) {
return false;
}
if (keyPress.mods.Cmd && !event.cmd) {
if (notMod(keyPress.mods.Cmd, event.cmd)) {
return false;
}
if (keyPress.mods.Shift && !event.shift) {
if (notMod(keyPress.mods.Shift, event.shift)) {
return false;
}
if (keyPress.mods.Ctrl && !event.control) {
if (notMod(keyPress.mods.Ctrl, event.control)) {
return false;
}
if (keyPress.mods.Alt && !event.alt) {
if (notMod(keyPress.mods.Alt, event.alt)) {
return false;
}
if (keyPress.mods.Meta && !event.meta) {
if (notMod(keyPress.mods.Meta, event.meta)) {
return false;
}
let eventKey = "";