From 4977ba13ed1e8f10ed2a9f227ab0a7ecf3440d0d Mon Sep 17 00:00:00 2001 From: Simon Lydell Date: Sun, 28 Apr 2024 14:22:32 +0200 Subject: [PATCH 1/4] Zoom with ctrl --- js/editor/main.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/js/editor/main.js b/js/editor/main.js index 5ece19b..ef6f09c 100644 --- a/js/editor/main.js +++ b/js/editor/main.js @@ -309,6 +309,8 @@ export class Editor extends PrimaryView { // Mouse wheel to zoom this.set_canvas_zoom(1); this.viewport_el.addEventListener('wheel', ev => { + if (!ev.ctrlKey) + return; // The delta is platform and hardware dependent and ultimately kind of useless, so just // treat each event as a click and hope for the best if (ev.deltaY === 0) From c99bb2122dcc69471916fe772454159b70ff11e1 Mon Sep 17 00:00:00 2001 From: Simon Lydell Date: Sun, 28 Apr 2024 14:23:33 +0200 Subject: [PATCH 2/4] Allow `+` as zoom-in hotkey --- js/editor/main.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/js/editor/main.js b/js/editor/main.js index ef6f09c..fdc5f61 100644 --- a/js/editor/main.js +++ b/js/editor/main.js @@ -210,7 +210,9 @@ export class Editor extends PrimaryView { else if (ev.key === '-') { this.zoom_by(-1); } - else if (ev.key === '=') { + // `=` because US keyboards have `+` on the same key as `=`, and `+` is shift-`=` + // `+` because many other keyboards have `+` on its own key, un-shifted, while `=` is shifted + else if (ev.key === '=' || ev.key === '+') { this.zoom_by(+1); } else if (ev.key === '1') { From d9c6a3b0e00d784c24f030e420c105e0a7d235ff Mon Sep 17 00:00:00 2001 From: Simon Lydell Date: Sun, 28 Apr 2024 14:24:01 +0200 Subject: [PATCH 3/4] Make zoom hotkeys zoom towards cursor --- js/editor/main.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/js/editor/main.js b/js/editor/main.js index fdc5f61..b278fa7 100644 --- a/js/editor/main.js +++ b/js/editor/main.js @@ -208,12 +208,18 @@ export class Editor extends PrimaryView { } } else if (ev.key === '-') { - this.zoom_by(-1); + if (this.mouse_coords) + this.zoom_by(-1, this.mouse_coords[0], this.mouse_coords[1]); + else + this.zoom_by(-1); } // `=` because US keyboards have `+` on the same key as `=`, and `+` is shift-`=` // `+` because many other keyboards have `+` on its own key, un-shifted, while `=` is shifted else if (ev.key === '=' || ev.key === '+') { - this.zoom_by(+1); + if (this.mouse_coords) + this.zoom_by(+1, this.mouse_coords[0], this.mouse_coords[1]); + else + this.zoom_by(+1); } else if (ev.key === '1') { this.set_canvas_zoom(1); From 166adac8de4cae7a4fc1f77ba0e970ee5d0092e7 Mon Sep 17 00:00:00 2001 From: Simon Lydell Date: Sun, 28 Apr 2024 15:10:35 +0200 Subject: [PATCH 4/4] Use cmd on macOS --- js/editor/keyboard.js | 6 ++++++ js/editor/main.js | 30 +++++++++++++++++++++++------- js/editor/mouseops.js | 3 ++- 3 files changed, 31 insertions(+), 8 deletions(-) create mode 100644 js/editor/keyboard.js diff --git a/js/editor/keyboard.js b/js/editor/keyboard.js new file mode 100644 index 0000000..2acdf4f --- /dev/null +++ b/js/editor/keyboard.js @@ -0,0 +1,6 @@ +export const isMac = /mac|iPhone|iPad|iPod/i.test(window.navigator.platform); + +// On macOS it’s more natural to use the Command key for shortcuts. +export function isCtrlKey(event) { + return isMac ? event.metaKey : event.ctrlKey; +} diff --git a/js/editor/main.js b/js/editor/main.js index b278fa7..039aefb 100644 --- a/js/editor/main.js +++ b/js/editor/main.js @@ -14,6 +14,7 @@ import * as util from '../util.js'; import * as dialogs from './dialogs.js'; import { TOOLS, TOOL_ORDER, TOOL_SHORTCUTS, PALETTE, SPECIAL_PALETTE_ENTRIES, SPECIAL_TILE_BEHAVIOR, TILE_DESCRIPTIONS, transform_direction_bitmask } from './editordefs.js'; import { SVGConnection, Selection } from './helpers.js'; +import { isCtrlKey, isMac } from './keyboard.js'; import * as mouseops from './mouseops.js'; import { TILES_WITH_PROPS } from './tile-overlays.js'; @@ -147,8 +148,23 @@ export class Editor extends PrimaryView { if (! this.active) return; - if (ev.ctrlKey) { - if (ev.key === 'a') { + if (isCtrlKey(ev)) { + // macOS is really weird: + // + // | Keys pressed | `ev.key` | + // |--------------|----------| + // | A | "a" | + // | shift+A | "A" | + // | cmd+A | "a" | + // | cmd+shift+A | "a" !!! | + // | ctrl+shift+A | "A" | + // + // For some reason, with cmd the key is always lowercase. + // So we have to check the letter key case insensitively, + // and then manually check if shift is pressed. + const key = ev.key.toLowerCase(); + + if (key === 'a' && !ev.shiftKey) { // Select all if (TOOLS[this.current_tool].affects_selection) { // If we're in the middle of using a selection tool, cancel it @@ -161,7 +177,7 @@ export class Editor extends PrimaryView { this.commit_undo(); } } - else if (ev.key === 'A') { + else if (ev.key === 'a' && ev.shiftKey) { // Deselect if (TOOLS[this.current_tool].affects_selection) { // If we're in the middle of using a selection tool, cancel it @@ -173,10 +189,10 @@ export class Editor extends PrimaryView { this.commit_undo(); } } - else if (ev.key === 'z') { + else if (key === 'z' && !ev.shiftKey) { this.undo(); } - else if (ev.key === 'Z' || ev.key === 'y') { + else if ((key === 'z' && ev.shiftKey) || (key === 'y' && !ev.shiftKey)) { this.redo(); } else { @@ -317,7 +333,7 @@ export class Editor extends PrimaryView { // Mouse wheel to zoom this.set_canvas_zoom(1); this.viewport_el.addEventListener('wheel', ev => { - if (!ev.ctrlKey) + if (!isCtrlKey(ev)) return; // The delta is platform and hardware dependent and ultimately kind of useless, so just // treat each event as a click and hope for the best @@ -410,7 +426,7 @@ export class Editor extends PrimaryView { tooltip.append(this.svg_icon('svg-icon-mouse2')); } else if (key) { - tooltip.append(mk('kbd', key)); + tooltip.append(mk('kbd', key === 'ctrl' && isMac ? 'cmd' : key)); } } diff --git a/js/editor/mouseops.js b/js/editor/mouseops.js index bd23cbe..a351780 100644 --- a/js/editor/mouseops.js +++ b/js/editor/mouseops.js @@ -8,6 +8,7 @@ import { mk, mk_svg, walk_grid } from '../util.js'; import { SPECIAL_TILE_BEHAVIOR } from './editordefs.js'; import { SVGConnection } from './helpers.js'; +import { isCtrlKey } from './keyboard.js'; import { TILES_WITH_PROPS } from './tile-overlays.js'; // TODO some minor grievances @@ -202,7 +203,7 @@ export class MouseOperation { } _update_modifiers(ev) { - this.ctrl = ev.ctrlKey; + this.ctrl = isCtrlKey(ev); this.shift = ev.shiftKey; this.alt = ev.altKey; }