Skip to content

Commit

Permalink
Merge pull request #10371 from keymanapp/fix/web/special-text-hints
Browse files Browse the repository at this point in the history
fix(web): use KMW OSK font for "**" special-text in key hints
  • Loading branch information
jahorton authored Jan 15, 2024
2 parents 779196e + 0bb5884 commit 0cb429d
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 42 deletions.
2 changes: 1 addition & 1 deletion web/src/engine/osk/src/input/gestures/browser/multitap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export default class Multitap implements GestureHandler {
const tapLookahead = (offset) => (this.tapIndex + offset) % this.multitaps.length;

const updatePreview = () => {
previewHost?.setMultitapHint(this.multitaps[tapLookahead(0)].text, this.multitaps[tapLookahead(1)].text);
previewHost?.setMultitapHint(this.multitaps[tapLookahead(0)], this.multitaps[tapLookahead(1)], vkbd);
}

source.on('complete', () => {
Expand Down
10 changes: 9 additions & 1 deletion web/src/engine/osk/src/keyboard-layout/gesturePreviewHost.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import EventEmitter from "eventemitter3";
import { KeyElement } from "../keyElement.js";
import { FlickNameCoordMap, OrderedFlickDirections } from "../input/gestures/browser/flick.js";
import { PhoneKeyTipOrientation } from "../input/gestures/browser/keytip.js";
import { default as VisualKeyboard } from "../visualKeyboard.js";
import { renameSpecialKey } from "./oskKey.js";

/**With edge lengths of 1, to keep flick-text invisible at the start, the
* hypotenuse for an inter-cardinal path is sqrt(2). To keep a perfect circle
Expand Down Expand Up @@ -130,10 +132,16 @@ export class GesturePreviewHost extends EventEmitter<EventMap> {
this.onCancel = handler;
}

public setMultitapHint(current: string, next: string) {
public setMultitapHint(currentSrc: ActiveKeyBase, nextSrc: ActiveKeyBase, vkbd?: VisualKeyboard) {
const current = renameSpecialKey(currentSrc.text, vkbd);
const next = renameSpecialKey(nextSrc.text, vkbd);

this.label.textContent = current;
this.hintLabel.textContent = next;

this.label.style.fontFamily = (current != currentSrc.text) ? 'SpecialOSK' : currentSrc.font ?? this.label.style.fontFamily;
this.hintLabel.style.fontFamily = (next != nextSrc.text) ? 'SpecialOSK' : nextSrc.font ?? this.hintLabel.style.fontFamily;

this.emit('startFade');

this.clearFlick();
Expand Down
19 changes: 13 additions & 6 deletions web/src/engine/osk/src/keyboard-layout/oskBaseKey.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ActiveKey, Codes, DeviceSpec } from '@keymanapp/keyboard-processor';
import { landscapeView } from 'keyman/engine/dom-utils';

import OSKKey from './oskKey.js';
import OSKKey, { renameSpecialKey } from './oskKey.js';
import { KeyData, KeyElement, link } from '../keyElement.js';
import OSKRow from './oskRow.js';
import VisualKeyboard from '../visualKeyboard.js';
Expand Down Expand Up @@ -78,7 +78,7 @@ export default class OSKBaseKey extends OSKKey {
for(bsn=0; bsn<bsk.length; bsn++) {
if(bsk[bsn]['sp'] == 1 || bsk[bsn]['sp'] == 2) {
var oldText=bsk[bsn]['text'];
bsk[bsn]['text']=this.renameSpecialKey(oldText, vkbd);
bsk[bsn]['text']=renameSpecialKey(oldText, vkbd);
}

// If a subkey doesn't have a defined layer property, copy it from the base key's layer by default.
Expand Down Expand Up @@ -120,7 +120,7 @@ export default class OSKBaseKey extends OSKKey {
}

// If a subkey array is defined, add an icon
const skIcon = this.generateHint();
const skIcon = this.generateHint(vkbd);
btn.appendChild(skIcon);

// Add text to button and button to placeholder div
Expand All @@ -134,7 +134,7 @@ export default class OSKBaseKey extends OSKKey {
return this.square = kDiv;
}

public generateHint(): HTMLDivElement {
public generateHint(vkbd: VisualKeyboard): HTMLDivElement {
// If a hint is defined, add an icon
const skIcon = document.createElement('div');
// Ensure that we use the keyboard's text font for hints.
Expand All @@ -145,7 +145,7 @@ export default class OSKBaseKey extends OSKKey {
return skIcon;
}

if(hintSpec.font) {
if(hintSpec.font && hintSpec.font != 'SpecialOSK') {
skIcon.style.fontFamily = hintSpec.font;
} else {
skIcon.classList.add('kmw-key-text');
Expand All @@ -161,11 +161,18 @@ export default class OSKBaseKey extends OSKKey {

// If the base key itself is the source of the hint text, we use `hint` directly.
// Otherwise, we present the source subkey's key cap as the hint.
const text = hintSpec == this.spec ? this.spec.hint : hintSpec.text;
const baseText = hintSpec == this.spec ? this.spec.hint : hintSpec.text
const text = renameSpecialKey(baseText, vkbd);
if(text == '\u2022') {
// The original, pre-17.0 longpress dot-hint used bold-face styling.
skIcon.style.fontWeight='bold';
}

if(baseText != text) {
// if the text is from a *Special* shorthand, always use our special-key OSK font.
skIcon.style.fontFamily = 'SpecialOSK';
}

skIcon.textContent = text;

return skIcon;
Expand Down
68 changes: 34 additions & 34 deletions web/src/engine/osk/src/keyboard-layout/oskKey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,39 @@ import buttonClassNames from '../buttonClassNames.js';
import { KeyElement } from '../keyElement.js';
import VisualKeyboard from '../visualKeyboard.js';

/**
* Replace default key names by special font codes for modifier keys
*
* @param {string} oldText
* @return {string}
**/
export function renameSpecialKey(oldText: string, vkbd: VisualKeyboard): string {
// If a 'special key' mapping exists for the text, replace it with its corresponding special OSK character.
switch(oldText) {
case '*ZWNJ*':
// Default ZWNJ symbol comes from iOS. We'd rather match the system defaults where
// possible / available though, and there's a different standard symbol on Android.
oldText = vkbd.device.OS == DeviceSpec.OperatingSystem.Android ?
'*ZWNJAndroid*' :
'*ZWNJiOS*';
break;
case '*Enter*':
oldText = vkbd.isRTL ? '*RTLEnter*' : '*LTREnter*';
break;
case '*BkSp*':
oldText = vkbd.isRTL ? '*RTLBkSp*' : '*LTRBkSp*';
break;
default:
// do nothing.
}

let specialCodePUA = 0XE000 + specialChars[oldText];

return specialChars[oldText] ?
String.fromCharCode(specialCodePUA) :
oldText;
}

export default abstract class OSKKey {
// Only set here to act as an alias for code built against legacy versions.
static readonly specialCharacters = specialChars;
Expand Down Expand Up @@ -260,39 +293,6 @@ export default abstract class OSKKey {
return key.proportionalWidth * vkbd.width;
}

/**
* Replace default key names by special font codes for modifier keys
*
* @param {string} oldText
* @return {string}
**/
protected renameSpecialKey(oldText: string, vkbd: VisualKeyboard): string {
// If a 'special key' mapping exists for the text, replace it with its corresponding special OSK character.
switch(oldText) {
case '*ZWNJ*':
// Default ZWNJ symbol comes from iOS. We'd rather match the system defaults where
// possible / available though, and there's a different standard symbol on Android.
oldText = vkbd.device.OS == DeviceSpec.OperatingSystem.Android ?
'*ZWNJAndroid*' :
'*ZWNJiOS*';
break;
case '*Enter*':
oldText = vkbd.isRTL ? '*RTLEnter*' : '*LTREnter*';
break;
case '*BkSp*':
oldText = vkbd.isRTL ? '*RTLBkSp*' : '*LTRBkSp*';
break;
default:
// do nothing.
}

let specialCodePUA = 0XE000 + specialChars[oldText];

return specialChars[oldText] ?
String.fromCharCode(specialCodePUA) :
oldText;
}

public get keyText(): string {
const spec = this.spec;
const DEFAULT_BLANK = '\xa0';
Expand Down Expand Up @@ -327,7 +327,7 @@ export default abstract class OSKKey {

// Add OSK key labels
let keyText = this.keyText;
let specialText = this.renameSpecialKey(keyText, vkbd);
let specialText = renameSpecialKey(keyText, vkbd);
if(specialText != keyText) {
// The keyboard wants to use the code for a special glyph defined by the SpecialOSK font.
keyText = specialText;
Expand Down

0 comments on commit 0cb429d

Please sign in to comment.