Add mobile keyboard API (#21)

* fix page for mobile - minor changes.

* fix textarea overlay to hide caret and avodi zooming on mobiles.

* fix typo.

* show keyboard btn if is touch device.

* lint fix.

* add to API.

* mobile keybaord fix andorid blur.

* add mobile keybaord toggle.

* fix overlay.

* mobile keybaord, skip if not a touch device.
This commit is contained in:
Miroslav Šedivý
2023-01-27 19:21:42 +01:00
committed by GitHub
parent 5758350a78
commit dc2ef37e17
6 changed files with 116 additions and 13 deletions

View File

@ -20,6 +20,7 @@
:cursorDraw="inactiveCursorDrawFunction"
/>
<neko-overlay
ref="overlay"
v-show="!private_mode_enabled && state.connection.status != 'disconnected'"
:style="{ pointerEvents: state.control.locked ? 'none' : 'auto' }"
:wsControl="control"
@ -35,6 +36,7 @@
:inactiveCursors="state.settings.inactive_cursors && session.profile.sends_inactive_cursor"
@updateKeyboardModifiers="updateKeyboardModifiers($event)"
@uploadDrop="uploadDrop($event)"
@mobileKeyboardOpen="state.mobile_keyboard_open = $event"
/>
</div>
</div>
@ -102,6 +104,7 @@
@Ref('component') readonly _component!: HTMLElement
@Ref('container') readonly _container!: HTMLElement
@Ref('video') readonly _video!: HTMLVideoElement
@Ref('overlay') readonly _overlay!: Overlay
// fallback image for webrtc reconnections:
// chrome shows black screen when closing webrtc connection, that's why
@ -196,6 +199,7 @@
merciful_reconnect: false,
},
cursors: [],
mobile_keyboard_open: false,
} as NekoState
/////////////////////////////
@ -405,6 +409,22 @@
Vue.set(this.state.control, 'keyboard', { layout, variant })
}
public mobileKeyboardShow() {
this._overlay.mobileKeyboardShow()
}
public mobileKeyboardHide() {
this._overlay.mobileKeyboardHide()
}
public mobileKeyboardToggle() {
if (this.state.mobile_keyboard_open) {
this.mobileKeyboardHide()
} else {
this.mobileKeyboardShow()
}
}
public setCursorDrawFunction(fn?: CursorDrawFunction) {
Vue.set(this, 'cursorDrawFunction', fn)
}

View File

@ -33,8 +33,9 @@
bottom: 0;
width: 100%;
height: 100%;
font-size: 1px; /* chrome would not paste text if 0px */
font-size: 16px; /* at least 16px to avoid zooming on mobile */
resize: none; /* hide textarea resize corner */
caret-color: transparent; /* hide caret */
outline: 0;
border: 0;
color: transparent;
@ -116,6 +117,10 @@
return 'url(' + uri + ') ' + x + ' ' + y + ', default'
}
get isTouchDevice(): boolean {
return 'ontouchstart' in window || navigator.maxTouchPoints > 0
}
mounted() {
// register mouseup globally as user can release mouse button outside of overlay
window.addEventListener('mouseup', this.onMouseUp, true)
@ -373,7 +378,11 @@
}
onMouseEnter(e: MouseEvent) {
this._textarea.focus()
// focus opens the keyboard on mobile (only for android)
if (!this.isTouchDevice) {
this._textarea.focus()
}
this.focused = true
if (this.isControling) {
@ -629,5 +638,48 @@
this.wsControl.release()
}
}
//
// mobile keyboard
//
public kbdShow = false
public kbdOpen = false
public mobileKeyboardShow() {
// skip if not a touch device
if (!this.isTouchDevice) return
this.kbdShow = true
this.kbdOpen = false
this._textarea.focus()
window.visualViewport.addEventListener('resize', this.onVisualViewportResize)
this.$emit('mobileKeyboardOpen', true)
}
public mobileKeyboardHide() {
// skip if not a touch device
if (!this.isTouchDevice) return
this.kbdShow = false
this.kbdOpen = false
this.$emit('mobileKeyboardOpen', false)
window.visualViewport.removeEventListener('resize', this.onVisualViewportResize)
this._textarea.blur()
}
// visual viewport resize event is fired when keyboard is opened or closed
// android does not blur textarea when keyboard is closed, so we need to do it manually
onVisualViewportResize() {
if (!this.kbdShow) return
if (!this.kbdOpen) {
this.kbdOpen = true
} else {
this.mobileKeyboardHide()
}
}
}
</script>

View File

@ -11,6 +11,7 @@ export default interface State {
sessions: Record<string, Session>
settings: Settings
cursors: Cursors
mobile_keyboard_open: boolean
}
/////////////////////////////