199 lines
7.1 KiB
QML
199 lines
7.1 KiB
QML
// Copyright (C) 2016 The Qt Company Ltd.
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
|
|
|
|
import QtQuick
|
|
import QtQuick.Window
|
|
import QtQuick.VirtualKeyboard
|
|
|
|
/*!
|
|
\qmltype TraceInputArea
|
|
\inqmlmodule QtQuick.VirtualKeyboard.Components
|
|
\ingroup qmlclass
|
|
\ingroup qtvirtualkeyboard-components-qml
|
|
\inherits MultiPointTouchArea
|
|
\since QtQuick.VirtualKeyboard 2.0
|
|
|
|
\brief A specialized MultiPointTouchArea for collecting touch input data.
|
|
|
|
This type handles the trace interaction between the touch screen and the input engine.
|
|
|
|
The traces are rendered using the delegate from the
|
|
\l {KeyboardStyle::}{traceCanvasDelegate} property of the current
|
|
\l KeyboardStyle.
|
|
*/
|
|
|
|
MultiPointTouchArea {
|
|
id: traceInputArea
|
|
|
|
/*! Pattern recognition mode of this input area.
|
|
|
|
The default value is \l {InputEngine::patternRecognitionModes} {InputEngine.PatternRecognitionMode.None}.
|
|
*/
|
|
property int patternRecognitionMode: InputEngine.PatternRecognitionMode.None
|
|
|
|
/*! List of horizontal rulers in the input area.
|
|
|
|
The rulers are defined as a number of pixels from the top edge of the boundingBox.
|
|
|
|
Here is an example that demonstrates how to define rulers:
|
|
|
|
\code
|
|
horizontalRulers: [boundingBox.height / 3, boundingBox.height / 3 * 2]
|
|
verticalRulers: [boundingBox.width / 3, boundingBox.width / 3 * 2]
|
|
\endcode
|
|
*/
|
|
property var horizontalRulers
|
|
|
|
/*! List of vertical rulers in the input area.
|
|
|
|
The rulers are defined as a number of pixels from the left edge of the boundingBox.
|
|
*/
|
|
property var verticalRulers
|
|
|
|
/*! Bounding box for the trace input.
|
|
|
|
This property is readonly and is automatically updated based on the item size
|
|
and margins.
|
|
*/
|
|
readonly property rect boundingBox: (width > 0 && height > 0) ?
|
|
Qt.rect(traceInputArea.x + traceInputArea.anchors.leftMargin,
|
|
traceInputArea.y + traceInputArea.anchors.topMargin,
|
|
traceInputArea.width,
|
|
traceInputArea.height) :
|
|
Qt.rect(0, 0, 0, 0)
|
|
|
|
/*! Canvas type of this trace input area.
|
|
|
|
This property can be used to distinguish between different types of canvases.
|
|
For example, in full screen handwriting mode this property is set to \c "fullscreen", and
|
|
in keyboard handwriting mode this property is set to \c "keyboard".
|
|
*/
|
|
property string canvasType
|
|
|
|
property var __activeTraceCanvases: ({})
|
|
property var __traceCanvasList: ([])
|
|
property var __recycledTraceCanvasList: ([])
|
|
|
|
Component.onCompleted: {
|
|
for (var i = 0; i < 6; i++) {
|
|
__recycledTraceCanvasList.push(__createTraceCanvas())
|
|
}
|
|
}
|
|
|
|
function __getTraceCanvas() {
|
|
while (__recycledTraceCanvasList.length == 0 &&
|
|
__traceCanvasList.length >= 15 &&
|
|
!__traceCanvasList.shift().recycle()) {}
|
|
|
|
return __recycledTraceCanvasList.length > 0 ?
|
|
__recycledTraceCanvasList.pop() :
|
|
__createTraceCanvas()
|
|
}
|
|
|
|
function __createTraceCanvas() {
|
|
var traceCanvas = keyboard.style.traceCanvasDelegate.createObject(traceInputArea)
|
|
traceCanvas.onRecycle.connect(__onTraceCanvasRecycled)
|
|
traceCanvas.anchors.fill = traceCanvas.parent
|
|
return traceCanvas
|
|
}
|
|
|
|
function __onTraceCanvasRecycled(traceCanvas) {
|
|
var index = __traceCanvasList.findIndex(function(otherCanvas) {
|
|
return traceCanvas === otherCanvas
|
|
})
|
|
if (index !== -1) {
|
|
__traceCanvasList.splice(index, index + 1)
|
|
}
|
|
__recycledTraceCanvasList.push(traceCanvas)
|
|
}
|
|
|
|
property var __traceCaptureDeviceInfo:
|
|
({
|
|
channels: ['t'],
|
|
sampleRate: 60,
|
|
uniform: false,
|
|
latency: 0.0,
|
|
dpi: Screen.pixelDensity * 25.4
|
|
})
|
|
property var __traceScreenInfo:
|
|
({
|
|
boundingBox: traceInputArea.boundingBox,
|
|
horizontalRulers: traceInputArea.horizontalRulers,
|
|
verticalRulers: traceInputArea.verticalRulers,
|
|
canvasType: traceInputArea.canvasType
|
|
})
|
|
|
|
enabled: patternRecognitionMode !== InputEngine.PatternRecognitionMode.None && InputContext.inputEngine.patternRecognitionModes.indexOf(patternRecognitionMode) !== -1
|
|
|
|
onPressed: (touchPoints) => {
|
|
if (!keyboard.style.traceCanvasDelegate)
|
|
return
|
|
for (var i = 0; i < touchPoints.length; i++) {
|
|
var traceId = touchPoints[i].pointId
|
|
var trace = InputContext.inputEngine.traceBegin(traceId, patternRecognitionMode, __traceCaptureDeviceInfo, __traceScreenInfo)
|
|
if (trace) {
|
|
var traceCanvas = __getTraceCanvas()
|
|
if (traceCanvas) {
|
|
traceCanvas.trace = trace
|
|
var index = trace.addPoint(Qt.point(touchPoints[i].x, touchPoints[i].y))
|
|
if (trace.channels.indexOf('t') !== -1) {
|
|
var dt = new Date()
|
|
trace.setChannelData('t', index, dt.getTime())
|
|
}
|
|
__activeTraceCanvases[traceId] = traceCanvas
|
|
} else {
|
|
__activeTraceCanvases[traceId] = null
|
|
}
|
|
} else {
|
|
__activeTraceCanvases[traceId] = null
|
|
}
|
|
}
|
|
}
|
|
|
|
onUpdated: (touchPoints) => {
|
|
for (var i = 0; i < touchPoints.length; i++) {
|
|
var traceId = touchPoints[i].pointId
|
|
var traceCanvas = __activeTraceCanvases[traceId]
|
|
if (traceCanvas) {
|
|
var trace = traceCanvas.trace
|
|
var index = trace.addPoint(Qt.point(touchPoints[i].x, touchPoints[i].y))
|
|
if (trace.channels.indexOf('t') !== -1) {
|
|
var dt = new Date()
|
|
trace.setChannelData('t', index, dt.getTime())
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
onReleased: (touchPoints) => {
|
|
for (var i = 0; i < touchPoints.length; i++) {
|
|
var traceId = touchPoints[i].pointId
|
|
var traceCanvas = __activeTraceCanvases[traceId]
|
|
if (traceCanvas) {
|
|
if (traceCanvas.trace) {
|
|
traceCanvas.trace.final = true
|
|
InputContext.inputEngine.traceEnd(traceCanvas.trace)
|
|
}
|
|
__traceCanvasList.push(traceCanvas)
|
|
__activeTraceCanvases[traceId] = null
|
|
}
|
|
}
|
|
}
|
|
|
|
onCanceled: (touchPoints) => {
|
|
for (var i = 0; i < touchPoints.length; i++) {
|
|
var traceId = touchPoints[i].pointId
|
|
var traceCanvas = __activeTraceCanvases[traceId]
|
|
if (traceCanvas) {
|
|
if (traceCanvas.trace) {
|
|
traceCanvas.trace.final = true
|
|
traceCanvas.trace.canceled = true
|
|
InputContext.inputEngine.traceEnd(traceCanvas.trace)
|
|
}
|
|
__traceCanvasList.push(traceCanvas)
|
|
__activeTraceCanvases[traceId] = null
|
|
}
|
|
}
|
|
}
|
|
}
|