diff --git a/web/src/engine/osk/src/keyboard-layout/oskKey.ts b/web/src/engine/osk/src/keyboard-layout/oskKey.ts index 3d364a9549..fa74b27cfe 100644 --- a/web/src/engine/osk/src/keyboard-layout/oskKey.ts +++ b/web/src/engine/osk/src/keyboard-layout/oskKey.ts @@ -176,10 +176,21 @@ export default abstract class OSKKey { * @returns font size as a style string */ getIdealFontSize(vkbd: VisualKeyboard, text: string, style: {height?: string, fontFamily?: string, fontSize: string}, override?: boolean): string { - let buttonStyle = getComputedStyle(this.btn); + let buttonStyle: typeof style & {width?: string} = getComputedStyle(this.btn); let keyWidth = parseFloat(buttonStyle.width); let emScale = 1; + // Among other things, ensures we use SpecialOSK styling for special key text. + // It's set on the key-span, not on the button. + const localFont = this.label?.style.fontFamily; + if(localFont) { + buttonStyle = { + fontFamily: localFont, + fontSize: buttonStyle.fontSize, + height: buttonStyle.height + } + } + const originalSize = getFontSizeStyle(style.fontSize || '1em'); // Not yet available; it'll be handled in a later layout pass. @@ -334,7 +345,9 @@ export default abstract class OSKKey { // space bar may not define the text span! if(this.label) { if(!this.label.classList.contains('kmw-spacebar-caption')) { - this.label.style.fontSize = this.getIdealFontSize(vkbd, this.keyText, this.btn.style); + // Do not use `this.keyText` - it holds *___* codes for special keys, not the actual glyph! + const keyCapText = this.label.textContent; + this.label.style.fontSize = this.getIdealFontSize(vkbd, keyCapText, this.btn.style); } else { // Remove any custom setting placed on it before recomputing its inherited style info. this.label.style.fontSize = ''; diff --git a/web/src/engine/osk/src/views/oskView.ts b/web/src/engine/osk/src/views/oskView.ts index 2dc50e6cd1..4f0d6c7504 100644 --- a/web/src/engine/osk/src/views/oskView.ts +++ b/web/src/engine/osk/src/views/oskView.ts @@ -116,6 +116,14 @@ export interface EventMap { pointerinteraction: (promise: Promise) => void; } +export function getResourcePath(config: Configuration) { + let resourcePathExt = 'osk/'; + if(config.isEmbedded) { + resourcePathExt = ''; + } + return `${config.pathConfig.resources}/${resourcePathExt}` +} + export default abstract class OSKView extends EventEmitter implements MinimalCodesInterface, KeyEventSourceInterface { @@ -710,12 +718,10 @@ export default abstract class OSKView // Install the default OSK stylesheets - but don't have it managed by the keyboard-specific stylesheet manager. // We wish to maintain kmwosk.css whenever keyboard-specific styles are reset/removed. // Temp-hack: embedded products prefer their stylesheet, etc linkages without the /osk path component. - let subpath = 'osk/'; - if(this.config.isEmbedded) { - subpath = ''; - } + const resourcePath = getResourcePath(this.config); + for(let sheetFile of OSKView.STYLESHEET_FILES) { - const sheetHref = `${this.config.pathConfig.resources}/${subpath}${sheetFile}`; + const sheetHref = `${resourcePath}${sheetFile}`; this.uiStyleSheetManager.linkExternalSheet(sheetHref); } @@ -801,6 +807,8 @@ export default abstract class OSKView private _GenerateVisualKeyboard(keyboard: Keyboard, keyboardMetadata: KeyboardProperties): VisualKeyboard { let device = this.targetDevice; + const resourcePath = getResourcePath(this.config); + // Root element sets its own classes, one of which is 'kmw-osk-inner-frame'. let vkbd = new VisualKeyboard({ keyboard: keyboard, @@ -811,7 +819,12 @@ export default abstract class OSKView styleSheetManager: this.kbdStyleSheetManager, pathConfig: this.config.pathConfig, embeddedGestureConfig: this.config.embeddedGestureConfig, - isEmbedded: this.config.isEmbedded + isEmbedded: this.config.isEmbedded, + specialFont: { + family: 'SpecialOSK', + files: [`${resourcePath}/keymanweb-osk.ttf`], + path: '' // Not actually used. + } }); vkbd.on('keyevent', (keyEvent, callback) => this.emit('keyevent', keyEvent, callback)); diff --git a/web/src/engine/osk/src/visualKeyboard.ts b/web/src/engine/osk/src/visualKeyboard.ts index e07ba634f8..56875b0b59 100644 --- a/web/src/engine/osk/src/visualKeyboard.ts +++ b/web/src/engine/osk/src/visualKeyboard.ts @@ -100,6 +100,11 @@ export interface VisualKeyboardConfiguration extends CommonConfiguration { * want to remove that one when swapping keyboards. */ styleSheetManager: StylesheetManager; + + /** + * A promise for loading of the font used by special keys. + */ + specialFont?: InternalKeyboardFont; } interface BoundingRect { @@ -1352,6 +1357,10 @@ export default class VisualKeyboard extends EventEmitter implements Ke this.styleSheetManager.addStyleSheetForFont(kfd, this.fontRootPath, this.device.OS); this.styleSheetManager.addStyleSheetForFont(ofd, this.fontRootPath, this.device.OS); + if(this.config.specialFont) { + this.styleSheetManager.addStyleSheetForFont(this.config.specialFont, '', this.device.OS); + } + // Build the style string to USE the fonts and append (or replace) the font style sheet // Note: Some browsers do not download the font-face font until it is applied, // so must apply style before testing for font availability diff --git a/web/src/resources/osk/kmwosk.css b/web/src/resources/osk/kmwosk.css index d0b9980d21..8544b75e5b 100644 --- a/web/src/resources/osk/kmwosk.css +++ b/web/src/resources/osk/kmwosk.css @@ -7,13 +7,6 @@ kmwosk.css: main CSS for keymanweb on-screen keyboard and other objects. */ -@font-face { - font-family: SpecialOSK; - font-style: normal; - font-weight: normal; - src: url('keymanweb-osk.ttf') format('truetype'); -} - /* kmw-key-square applies only to OSK key elements, kmw-key-square-ex applies only to popup key elements */ /* Common key-layout properties (all form factor + OS combinations) */ @@ -340,7 +333,16 @@ /* Vertical centering of text labels on keys */ .kmw-key {text-align:center; white-space:nowrap;} .kmw-key::before {content:'.'; display:inline-block; height:100%; vertical-align:middle; max-width:0px; visibility:hidden;} -.kmw-key span {display:inline-block} +.kmw-key span { + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + display: flex; + align-items: center; + justify-content: center; +} .desktop .kmw-osk-frame{position:absolute;width:auto;height:auto;left:0;top:0;display:none;margin:0;padding:0; @@ -494,8 +496,8 @@ .phone .kmw-key-shift, .phone .kmw-key-shift-on{font-size:0.7em !important;} /* Set special font and style for modifier and special key images */ -body div.kmw-key-shift span.kmw-key-text {font-family:SpecialOSK !important;font-size:1em !important;} -body div.kmw-key-shift-on span.kmw-key-text {font-family:SpecialOSK !important;font-size:1em !important;} +body div.kmw-key-shift span.kmw-key-text {font-family:SpecialOSK !important;font-size:1em;} +body div.kmw-key-shift-on span.kmw-key-text {font-family:SpecialOSK !important;font-size:1em;} #kmw-popup-keys div.kmw-key-shift span.kmw-key-text {font-family:SpecialOSK !important;} #kmw-keytip { @@ -779,7 +781,7 @@ div.android div.kmw-keytip-cap { .kmw-alert-text{margin:10px;white-space:default;font-family:Arial,sans-serif;} /* Note: font size gets overwritten in source code! */ -.kmw-spacebar-caption{font:1em Arial !important;color:rgba(0,0,0,0.25);} +.kmw-spacebar-caption{font-family: Arial !important;color:rgba(0,0,0,0.25);} /* Probably best to make this its own CSS that can be optionally included? */ @media (prefers-color-scheme: dark) {