Skip to content

Commit 60b5119

Browse files
committed
Fix nudge and textbox creation
1 parent 5a9518f commit 60b5119

File tree

2 files changed

+21
-6
lines changed

2 files changed

+21
-6
lines changed

editor/src/input/input_preprocessor_message_handler.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,13 +114,18 @@ impl MessageHandler<InputPreprocessorMessage, ()> for InputPreprocessorMessageHa
114114
}
115115

116116
impl InputPreprocessorMessageHandler {
117-
fn translate_mouse_event(&mut self, new_state: MouseState, allow_first_button_down: bool, responses: &mut VecDeque<Message>) {
117+
fn translate_mouse_event(&mut self, mut new_state: MouseState, allow_first_button_down: bool, responses: &mut VecDeque<Message>) {
118118
for (bit_flag, key) in [(MouseKeys::LEFT, Key::Lmb), (MouseKeys::RIGHT, Key::Rmb), (MouseKeys::MIDDLE, Key::Mmb)] {
119119
// Calculate the intersection between the two key states
120120
let old_down = self.mouse.mouse_keys & bit_flag == bit_flag;
121121
let new_down = new_state.mouse_keys & bit_flag == bit_flag;
122-
if !old_down && new_down && (allow_first_button_down || self.mouse.mouse_keys != MouseKeys::NONE) {
123-
responses.push_back(InputMapperMessage::KeyDown(key).into());
122+
if !old_down && new_down {
123+
if allow_first_button_down || self.mouse.mouse_keys != MouseKeys::NONE {
124+
responses.push_back(InputMapperMessage::KeyDown(key).into());
125+
} else {
126+
// Required to stop a keyup being emitted for a keydown outside canvas
127+
new_state.mouse_keys ^= bit_flag;
128+
}
124129
}
125130
if old_down && !new_down {
126131
responses.push_back(InputMapperMessage::KeyUp(key).into());

frontend/src/io-managers/input.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@ export function createInputManager(editor: Editor, container: HTMLElement, dialo
3131

3232
let viewportPointerInteractionOngoing = false;
3333
let textInput = undefined as undefined | HTMLDivElement;
34+
let inCanvas = true;
35+
36+
const app = window.document.getElementById("app");
37+
app?.focus();
38+
app?.addEventListener("blur", () => {
39+
inCanvas = false;
40+
});
3441

3542
// Keyboard events
3643

@@ -66,7 +73,6 @@ export function createInputManager(editor: Editor, container: HTMLElement, dialo
6673
if (e.ctrlKey && e.shiftKey && key === "j") return false;
6774

6875
// Don't redirect tab or enter if not in canvas (to allow navigating elements)
69-
const inCanvas = e.target instanceof Element && e.target.closest("[data-canvas]");
7076
if (!inCanvas && ["tab", "enter", " ", "arrowdown", "arrowup", "arrowleft", "arrowright"].includes(key.toLowerCase())) return false;
7177

7278
// Redirect to the backend
@@ -113,6 +119,10 @@ export function createInputManager(editor: Editor, container: HTMLElement, dialo
113119
const inFloatingMenu = e.target instanceof Element && e.target.closest("[data-floating-menu-content]");
114120
if (!viewportPointerInteractionOngoing && inFloatingMenu) return;
115121

122+
const { target } = e;
123+
inCanvas = (target instanceof Element && target.closest("[data-canvas]")) instanceof Element && !targetIsTextField(window.document.activeElement);
124+
if (inCanvas) app?.focus();
125+
116126
const modifiers = makeKeyboardModifiersBitfield(e);
117127
editor.instance.on_mouse_move(e.clientX, e.clientY, e.buttons, modifiers);
118128
}
@@ -131,7 +141,7 @@ export function createInputManager(editor: Editor, container: HTMLElement, dialo
131141

132142
if (!inTextInput) {
133143
if (textInput) editor.instance.on_change_text(textInputCleanup(textInput.innerText));
134-
else if (inCanvas) viewportPointerInteractionOngoing = true;
144+
else viewportPointerInteractionOngoing = inCanvas instanceof Element;
135145
}
136146

137147
if (viewportPointerInteractionOngoing) {
@@ -246,7 +256,7 @@ export function createInputManager(editor: Editor, container: HTMLElement, dialo
246256
});
247257
}
248258

249-
function targetIsTextField(target: EventTarget | null): boolean {
259+
function targetIsTextField(target: EventTarget | HTMLElement | null): boolean {
250260
return target instanceof HTMLElement && (target.nodeName === "INPUT" || target.nodeName === "TEXTAREA" || target.isContentEditable);
251261
}
252262

0 commit comments

Comments
 (0)