Skip to content

Commit

Permalink
chore(web): hardware keyboard interface now attaches its handlers
Browse files Browse the repository at this point in the history
  • Loading branch information
jahorton committed May 16, 2023
1 parent a363fd3 commit cec2aa3
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 43 deletions.
54 changes: 44 additions & 10 deletions web/src/app/browser/src/hardwareEventKeyboard.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { Codes, DeviceSpec, KeyEvent, KeyMapping, Keyboard, KeyboardProcessor, ManagedPromise } from '@keymanapp/keyboard-processor';
import { Codes, DeviceSpec, KeyEvent, KeyMapping, Keyboard, KeyboardProcessor } from '@keymanapp/keyboard-processor';

import { HardKeyboard } from 'keyman/engine/main';
import { eventOutputTarget } from 'keyman/engine/attachment';
import { DomEventTracker } from 'keyman/engine/events';
import { eventOutputTarget, outputTargetForElement } from 'keyman/engine/attachment';

import ContextManager from './contextManager.js';
import { nestedInstanceOf } from '../../../../build/engine/element-wrappers/obj/utils.js';
import DesignIFrame from '../../../../build/engine/element-wrappers/obj/designIFrame.js';

type KeyboardState = {
activeKeyboard: Keyboard,
Expand Down Expand Up @@ -234,6 +236,7 @@ export default class HardwareEventKeyboard extends HardKeyboard {
// - `doModifierPress()` - for modifier updates on key-up.
private readonly processor: KeyboardProcessor;
private readonly contextManager: ContextManager;
private domEventTracker = new DomEventTracker();

private swallowKeypress: boolean = false;

Expand All @@ -245,12 +248,37 @@ export default class HardwareEventKeyboard extends HardKeyboard {

const page = contextManager.page;

page.on('enabled', (elem) => {
const eventTracker = this.domEventTracker;

page.on('enabled', (Pelem) => {
const target = outputTargetForElement(Pelem);

if(!(target instanceof DesignIFrame)) {
// These need to be on the actual input element, as otherwise the keyboard will disappear on touch.
eventTracker.attachDOMEvent(Pelem, 'keypress', this._KeyPress);
eventTracker.attachDOMEvent(Pelem, 'keydown', this._KeyDown);
eventTracker.attachDOMEvent(Pelem, 'keyup', this._KeyUp);
} else {
const Lelem = target.getElement().contentDocument;
eventTracker.attachDOMEvent(Lelem.body,'keydown', this._KeyDown);
eventTracker.attachDOMEvent(Lelem.body,'keypress', this._KeyPress);
eventTracker.attachDOMEvent(Lelem.body,'keyup', this._KeyUp);
}
});

page.off('disabled', (elem) => {
page.off('disabled', (Pelem) => {
const target = outputTargetForElement(Pelem);

if(!(target instanceof DesignIFrame)) {
eventTracker.detachDOMEvent(Pelem, 'keypress', this._KeyPress);
eventTracker.detachDOMEvent(Pelem, 'keydown', this._KeyDown);
eventTracker.detachDOMEvent(Pelem, 'keyup', this._KeyUp);
} else {
const Lelem = target.getElement().contentDocument;
eventTracker.detachDOMEvent(Lelem.body,'keydown', this._KeyDown);
eventTracker.detachDOMEvent(Lelem.body,'keypress', this._KeyPress);
eventTracker.detachDOMEvent(Lelem.body,'keyup', this._KeyUp);
}
});
}

Expand Down Expand Up @@ -440,19 +468,21 @@ export default class HardwareEventKeyboard extends HardKeyboard {
*
* END FIXME / comment
*/
let resultCapture: { keystrokeValid?: boolean } = {};
let resultCapture: { preventDefaultKeystroke?: boolean } = {};

// Should only be run if `keystrokeValid` is required by the following conditional block.
// If it isn't - that is, swallowKeypress == true, we swallow the keypress instead
// by _not_ evaluating it during this pass.
// Should only be run if `preventDefaultKeystroke` is required by the following conditional
// block. If it isn't - that is, swallowKeypress == true, we want to swallow that keypress
// interpretation as well by _not_ evaluating it during this pass.
if(!this.swallowKeypress) {
// is synchronous
this.emit('keyEvent', Levent, (result, error) => {
resultCapture.keystrokeValid = !!result;
resultCapture.preventDefaultKeystroke = !!result;
})
}

if(this.swallowKeypress || resultCapture.keystrokeValid) {
// If we actively prevented a keystroke or if we processed one successfully,
// prevent the browser from producing its default text output for the event.
if(this.swallowKeypress || resultCapture.preventDefaultKeystroke) {
this.swallowKeypress = false;
if(e && e.preventDefault) {
e.preventDefault();
Expand All @@ -464,4 +494,8 @@ export default class HardwareEventKeyboard extends HardKeyboard {
this.swallowKeypress = false;
return true;
}

shutdown() {
this.domEventTracker.shutdown();
}
}
1 change: 1 addition & 0 deletions web/src/app/browser/src/keymanEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,5 +174,6 @@ export class KeymanEngine extends KeymanEngineBase<ContextManager, HardwareEvent
this.contextManager.shutdown();
this.osk?.shutdown();
this.core.languageProcessor.shutdown();
this.hardKeyboard.shutdown();
}
}
38 changes: 5 additions & 33 deletions web/src/engine/attachment/src/pageContextAttachment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,42 +25,14 @@ type SortableInput = {
};

interface EventMap {
/***
* For anything attached but (design-mode) iframes...
```
// This block: has to do with keystroke processing.
// These need to be on the actual input element, as otherwise the keyboard will disappear on touch.
Pelem.onkeypress = this.getHandlers(Pelem)._KeyPress;
Pelem.onkeydown = this.getHandlers(Pelem)._KeyDown;
Pelem.onkeyup = this.getHandlers(Pelem)._KeyUp;
```
*
* For design-mode iframes:
```
// This block: has to do with keystroke processing.
util.attachDOMEvent(Lelem.body,'keydown', this.getHandlers(Pelem)._KeyDown);
util.attachDOMEvent(Lelem.body,'keypress', this.getHandlers(Pelem)._KeyPress);
util.attachDOMEvent(Lelem.body,'keyup', this.getHandlers(Pelem)._KeyUp);
```
/**
* For any elements being attached or being re-enabled after having been disabled.
*/
'enabled': (obj: HTMLElement) => void;

/***
* For anything attached but (design-mode) iframes...
```
// This block: has to do with keystroke processing.
Pelem.onkeypress = null;
Pelem.onkeydown = null;
Pelem.onkeyup = null;
```
*
* For design-mode iframes:
```
// This block: has to do with keystroke processing.
util.detachDOMEvent(Lelem.body,'keydown', this.getHandlers(Pelem)._KeyDown);
util.detachDOMEvent(Lelem.body,'keypress', this.getHandlers(Pelem)._KeyPress);
util.detachDOMEvent(Lelem.body,'keyup', this.getHandlers(Pelem)._KeyUp);
```
/**
* For any elements being detached, disabled, or selectively not being attached due
* being pre-marked for a disabled state.
*/
'disabled': (obj: HTMLElement) => void;
}
Expand Down

0 comments on commit cec2aa3

Please sign in to comment.