aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOswald Buddenhagen <oswald.buddenhagen@gmx.de>2017-02-01 20:45:13 +0100
committerOswald Buddenhagen <oswald.buddenhagen@gmx.de>2017-02-01 20:45:13 +0100
commit18f37cf7410beb698855a38a1af458d51d64e3fe (patch)
treeeff75ee12b02288f7cf28dba20b684a1dbb81ce7
parente967e50805e50decd809236da314127cd425ef0b (diff)
parentad44e00c0d01dea15358b98865623e8f11f295a8 (diff)
Merge dev into 5.9v5.9.0-alpha1
-rw-r--r--.gitignore6
-rw-r--r--dist/changes-5.8.027
-rw-r--r--examples/virtualkeyboard/basic/basic-b2qt.qml14
-rw-r--r--examples/virtualkeyboard/basic/content/TextArea.qml4
-rw-r--r--src/virtualkeyboard/3rdparty/hunspell/hunspell.pro2
-rw-r--r--src/virtualkeyboard/3rdparty/lipi-toolkit/lipi-toolkit.pro3
-rw-r--r--src/virtualkeyboard/3rdparty/lipi-toolkit/projects/alphanumeric/alphanumeric.pro7
-rw-r--r--src/virtualkeyboard/3rdparty/lipi-toolkit/projects/demonumerals/demonumerals.pro7
-rw-r--r--src/virtualkeyboard/3rdparty/lipi-toolkit/projects/lipiengine.pro7
-rw-r--r--src/virtualkeyboard/3rdparty/lipi-toolkit/projects/projects.pro8
-rw-r--r--src/virtualkeyboard/3rdparty/lipi-toolkit/src/lipicommon.pri3
-rw-r--r--src/virtualkeyboard/3rdparty/t9write/t9write.pro1
-rw-r--r--src/virtualkeyboard/content/InputPanel.qml3
-rw-r--r--src/virtualkeyboard/content/components/AlternativeKeys.qml5
-rw-r--r--src/virtualkeyboard/content/components/BaseKey.qml3
-rw-r--r--src/virtualkeyboard/content/components/CharacterPreviewBubble.qml3
-rw-r--r--src/virtualkeyboard/content/components/Keyboard.qml65
-rw-r--r--src/virtualkeyboard/content/components/SelectionControl.qml27
-rw-r--r--src/virtualkeyboard/content/components/ShadowInputControl.qml138
-rw-r--r--src/virtualkeyboard/content/components/ShiftKey.qml4
-rw-r--r--src/virtualkeyboard/content/components/WordCandidatePopupList.qml6
-rw-r--r--src/virtualkeyboard/content/content.qrc1
-rw-r--r--src/virtualkeyboard/content/styles/default/style.qml20
-rw-r--r--src/virtualkeyboard/content/styles/retro/style.qml24
-rw-r--r--src/virtualkeyboard/doc/src/qtvirtualkeyboard-index.qdoc6
-rw-r--r--src/virtualkeyboard/inputcontext.cpp154
-rw-r--r--src/virtualkeyboard/inputcontext.h12
-rw-r--r--src/virtualkeyboard/platforminputcontext.cpp4
-rw-r--r--src/virtualkeyboard/plugin.cpp4
-rw-r--r--src/virtualkeyboard/settings.cpp19
-rw-r--r--src/virtualkeyboard/settings.h4
-rw-r--r--src/virtualkeyboard/shadowinputcontext.cpp253
-rw-r--r--src/virtualkeyboard/shadowinputcontext.h90
-rw-r--r--src/virtualkeyboard/shifthandler.cpp17
-rw-r--r--src/virtualkeyboard/shifthandler.h1
-rw-r--r--src/virtualkeyboard/styles/KeyPanel.qml2
-rw-r--r--src/virtualkeyboard/styles/KeyboardStyle.qml104
-rw-r--r--src/virtualkeyboard/styles/styles_plugin.cpp5
-rw-r--r--src/virtualkeyboard/tcinputmethod.cpp2
-rw-r--r--src/virtualkeyboard/virtualkeyboard.pro13
-rw-r--r--src/virtualkeyboard/virtualkeyboardsettings.cpp33
-rw-r--r--src/virtualkeyboard/virtualkeyboardsettings.h5
-rw-r--r--tests/auto/inputpanel/data/inputpanel/inputpanel.qml20
-rw-r--r--tests/auto/inputpanel/data/tst_inputpanel.qml170
44 files changed, 1194 insertions, 112 deletions
diff --git a/.gitignore b/.gitignore
index f20d3ee8..e87d9dff 100644
--- a/.gitignore
+++ b/.gitignore
@@ -30,4 +30,8 @@ qrc_*.cpp
Makefile*
*.html
*~
-.qmake.cache
+.qmake.*
+
+tst_*
+!tst_*.*
+tst_*.exe
diff --git a/dist/changes-5.8.0 b/dist/changes-5.8.0
new file mode 100644
index 00000000..68997532
--- /dev/null
+++ b/dist/changes-5.8.0
@@ -0,0 +1,27 @@
+Qt 5.8 introduces many new features and improvements as well as bugfixes
+over the 5.7.x series. For more details, refer to the online documentation
+included in this distribution. The documentation is also available online:
+
+ http://doc.qt.io/qt-5/index.html
+
+The Qt version 5.8 series is binary compatible with the 5.7.x series.
+Applications compiled for 5.7 will continue to run with 5.8.
+
+Some of the changes listed in this file include issue tracking numbers
+corresponding to tasks in the Qt Bug Tracker:
+
+ https://bugreports.qt.io/
+
+Each of these identifiers can be entered in the bug tracker to obtain more
+information about a particular change.
+
+****************************************************************************
+* New Features *
+****************************************************************************
+
+ - Added support for styles in any QML import path under the directory
+ QtQuick/VirtualKeyboard/Styles/<style>.
+ - Added API to support VKB selection handles.
+ - Added Romanian keyboard layout.
+ - Add new property InputContext.uppercase, which is set to
+ true when either InputContext.shift or InputContext.capsLock is true
diff --git a/examples/virtualkeyboard/basic/basic-b2qt.qml b/examples/virtualkeyboard/basic/basic-b2qt.qml
index 8d2727cd..7df2a0f6 100644
--- a/examples/virtualkeyboard/basic/basic-b2qt.qml
+++ b/examples/virtualkeyboard/basic/basic-b2qt.qml
@@ -29,7 +29,8 @@
import QtQuick 2.0
import QtQuick.Window 2.2
-import QtQuick.VirtualKeyboard 2.1
+import QtQuick.VirtualKeyboard 2.2
+import QtQuick.VirtualKeyboard.Settings 2.2
import "content"
Item {
@@ -80,7 +81,7 @@ Item {
double-click changes the availability of the full screen handwriting input.
*/
Item {
- z: 89
+ z: 99
visible: handwritingInputPanel.enabled && Qt.inputMethod.visible
anchors { left: parent.left; top: parent.top; right: parent.right; bottom: inputPanel.top; }
HandwritingModeButton {
@@ -104,7 +105,7 @@ Item {
*/
InputPanel {
id: inputPanel
- z: 99
+ z: 89
y: appContainer.height
anchors.left: parent.left
anchors.right: parent.right
@@ -126,6 +127,7 @@ Item {
from: ""
to: "visible"
reversible: true
+ enabled: !VirtualKeyboardSettings.fullScreenMode
ParallelAnimation {
NumberAnimation {
properties: "y"
@@ -141,5 +143,11 @@ Item {
}
AutoScroller {}
}
+
+ Binding {
+ target: VirtualKeyboardSettings
+ property: "fullScreenMode"
+ value: appContainer.height > 0 && (appContainer.width / appContainer.height) > (16.0 / 9.0)
+ }
}
}
diff --git a/examples/virtualkeyboard/basic/content/TextArea.qml b/examples/virtualkeyboard/basic/content/TextArea.qml
index 1b66a475..b9233710 100644
--- a/examples/virtualkeyboard/basic/content/TextArea.qml
+++ b/examples/virtualkeyboard/basic/content/TextArea.qml
@@ -68,8 +68,8 @@ TextBase {
cursorVisible: activeFocus
height: Math.max(implicitHeight, 60)
font.pixelSize: textArea.fontPixelSize
- selectionColor: Qt.rgba(1.0, 1.0, 1.0, 0.5)
- selectedTextColor: Qt.rgba(0.0, 0.0, 0.0, 0.8)
+ selectionColor: Qt.rgba(0, 0, 0, 0.15)
+ selectedTextColor: color
selectByMouse: true
anchors { left: parent.left; right: parent.right; margins: 12 }
}
diff --git a/src/virtualkeyboard/3rdparty/hunspell/hunspell.pro b/src/virtualkeyboard/3rdparty/hunspell/hunspell.pro
index 7df90098..bd5eccb3 100644
--- a/src/virtualkeyboard/3rdparty/hunspell/hunspell.pro
+++ b/src/virtualkeyboard/3rdparty/hunspell/hunspell.pro
@@ -16,7 +16,6 @@ SOURCES += \
src/hunspell/affentry.cxx \
src/hunspell/affixmgr.cxx \
src/hunspell/csutil.cxx \
- src/hunspell/dictmgr.cxx \
src/hunspell/filemgr.cxx \
src/hunspell/hashmgr.cxx \
src/hunspell/hunspell.cxx \
@@ -32,7 +31,6 @@ HEADERS += \
src/hunspell/atypes.hxx \
src/hunspell/baseaffix.hxx \
src/hunspell/csutil.hxx \
- src/hunspell/dictmgr.hxx \
src/hunspell/filemgr.hxx \
src/hunspell/hashmgr.hxx \
src/hunspell/htypes.hxx \
diff --git a/src/virtualkeyboard/3rdparty/lipi-toolkit/lipi-toolkit.pro b/src/virtualkeyboard/3rdparty/lipi-toolkit/lipi-toolkit.pro
index bd678b99..9593051a 100644
--- a/src/virtualkeyboard/3rdparty/lipi-toolkit/lipi-toolkit.pro
+++ b/src/virtualkeyboard/3rdparty/lipi-toolkit/lipi-toolkit.pro
@@ -1,5 +1,4 @@
TEMPLATE = subdirs
SUBDIRS += \
- src \
- projects
+ src
diff --git a/src/virtualkeyboard/3rdparty/lipi-toolkit/projects/alphanumeric/alphanumeric.pro b/src/virtualkeyboard/3rdparty/lipi-toolkit/projects/alphanumeric/alphanumeric.pro
deleted file mode 100644
index d65137db..00000000
--- a/src/virtualkeyboard/3rdparty/lipi-toolkit/projects/alphanumeric/alphanumeric.pro
+++ /dev/null
@@ -1,7 +0,0 @@
-TEMPLATE = aux
-
-cfg.files = config
-cfg.path = $$[QT_INSTALL_DATA]/qtvirtualkeyboard/lipi_toolkit/projects/alphanumeric
-INSTALLS += cfg
-
-!prefix_build: COPIES += cfg
diff --git a/src/virtualkeyboard/3rdparty/lipi-toolkit/projects/demonumerals/demonumerals.pro b/src/virtualkeyboard/3rdparty/lipi-toolkit/projects/demonumerals/demonumerals.pro
deleted file mode 100644
index a16edd28..00000000
--- a/src/virtualkeyboard/3rdparty/lipi-toolkit/projects/demonumerals/demonumerals.pro
+++ /dev/null
@@ -1,7 +0,0 @@
-TEMPLATE = aux
-
-cfg.files = config
-cfg.path = $$[QT_INSTALL_DATA]/qtvirtualkeyboard/lipi_toolkit/projects/demonumerals
-INSTALLS += cfg
-
-!prefix_build: COPIES += cfg
diff --git a/src/virtualkeyboard/3rdparty/lipi-toolkit/projects/lipiengine.pro b/src/virtualkeyboard/3rdparty/lipi-toolkit/projects/lipiengine.pro
deleted file mode 100644
index f9ad55a7..00000000
--- a/src/virtualkeyboard/3rdparty/lipi-toolkit/projects/lipiengine.pro
+++ /dev/null
@@ -1,7 +0,0 @@
-TEMPLATE = aux
-
-cfg.files += lipiengine.cfg
-cfg.path = $$[QT_INSTALL_DATA]/qtvirtualkeyboard/lipi_toolkit/projects
-INSTALLS += cfg
-
-!prefix_build: COPIES += cfg
diff --git a/src/virtualkeyboard/3rdparty/lipi-toolkit/projects/projects.pro b/src/virtualkeyboard/3rdparty/lipi-toolkit/projects/projects.pro
deleted file mode 100644
index 7109dc45..00000000
--- a/src/virtualkeyboard/3rdparty/lipi-toolkit/projects/projects.pro
+++ /dev/null
@@ -1,8 +0,0 @@
-TEMPLATE = subdirs
-
-SUBDIRS += \
- alphanumeric \
- demonumerals \
- lipiengine
-
-lipiengine.file = lipiengine.pro
diff --git a/src/virtualkeyboard/3rdparty/lipi-toolkit/src/lipicommon.pri b/src/virtualkeyboard/3rdparty/lipi-toolkit/src/lipicommon.pri
index df20b654..a1b770bb 100644
--- a/src/virtualkeyboard/3rdparty/lipi-toolkit/src/lipicommon.pri
+++ b/src/virtualkeyboard/3rdparty/lipi-toolkit/src/lipicommon.pri
@@ -4,6 +4,9 @@ CONFIG -= qt
CONFIG += exceptions
CONFIG += warn_off
+contains(QT_CONFIG, debug_and_release): CONFIG += debug_and_release
+contains(QT_CONFIG, build_all): CONFIG += build_all
+
INCLUDEPATH += $$PWD/include
load(qt_build_paths)
diff --git a/src/virtualkeyboard/3rdparty/t9write/t9write.pro b/src/virtualkeyboard/3rdparty/t9write/t9write.pro
index 8d6b4b91..05f723a7 100644
--- a/src/virtualkeyboard/3rdparty/t9write/t9write.pro
+++ b/src/virtualkeyboard/3rdparty/t9write/t9write.pro
@@ -19,3 +19,4 @@ load(qt_helper_lib)
# Needed for resources
CONFIG += qt
+QT = core
diff --git a/src/virtualkeyboard/content/InputPanel.qml b/src/virtualkeyboard/content/InputPanel.qml
index d2792fa9..f9d25a02 100644
--- a/src/virtualkeyboard/content/InputPanel.qml
+++ b/src/virtualkeyboard/content/InputPanel.qml
@@ -65,8 +65,10 @@ Item {
property alias keyboard: keyboard
SelectionControl {
+ objectName: "selectionControl"
x: -parent.x
y: -parent.y
+ enabled: active && !keyboard.fullScreenMode
}
implicitHeight: keyboard.height
@@ -79,5 +81,6 @@ Item {
MouseArea {
z: -1
anchors.fill: keyboard
+ enabled: active
}
}
diff --git a/src/virtualkeyboard/content/components/AlternativeKeys.qml b/src/virtualkeyboard/content/components/AlternativeKeys.qml
index 8801099c..a1fcfe14 100644
--- a/src/virtualkeyboard/content/components/AlternativeKeys.qml
+++ b/src/virtualkeyboard/content/components/AlternativeKeys.qml
@@ -36,7 +36,6 @@ Item {
property alias listView: listView
property int keyCode
property point origin
- property bool uppercased: keyboard.uppercased
signal clicked
z: 1
@@ -86,7 +85,7 @@ Item {
if (active && listView.currentIndex >= 0 && listView.currentIndex < listView.model.count) {
var activeKey = listView.model.get(listView.currentIndex)
InputContext.inputEngine.virtualKeyClick(keyCode, activeKey.text,
- uppercased ? Qt.ShiftModifier : 0)
+ InputContext.uppercase ? Qt.ShiftModifier : 0)
}
}
@@ -95,7 +94,7 @@ Item {
var alternativeKeys = key.effectiveAlternativeKeys
if (alternativeKeys.length > 0) {
for (var i = 0; i < alternativeKeys.length; i++) {
- listModel.append({ "text": uppercased ? alternativeKeys[i].toUpperCase() : alternativeKeys[i] })
+ listModel.append({ "text": InputContext.uppercase ? alternativeKeys[i].toUpperCase() : alternativeKeys[i] })
}
listView.width = keyboard.style.alternateKeysListItemWidth * listModel.count
listView.forceLayout()
diff --git a/src/virtualkeyboard/content/components/BaseKey.qml b/src/virtualkeyboard/content/components/BaseKey.qml
index 07989e01..5c686adf 100644
--- a/src/virtualkeyboard/content/components/BaseKey.qml
+++ b/src/virtualkeyboard/content/components/BaseKey.qml
@@ -29,6 +29,7 @@
import QtQuick 2.0
import QtQuick.Layouts 1.0
+import QtQuick.VirtualKeyboard 2.1
/*!
\qmltype BaseKey
@@ -203,7 +204,7 @@ Item {
By default, this property reflects the uppercase status of the keyboard.
*/
- property bool uppercased: keyboard.uppercased && !noModifier
+ property bool uppercased: InputContext.uppercase && !noModifier
/*! Sets the key panel delegate for the key.
diff --git a/src/virtualkeyboard/content/components/CharacterPreviewBubble.qml b/src/virtualkeyboard/content/components/CharacterPreviewBubble.qml
index 3a7490aa..1f9a05a2 100644
--- a/src/virtualkeyboard/content/components/CharacterPreviewBubble.qml
+++ b/src/virtualkeyboard/content/components/CharacterPreviewBubble.qml
@@ -28,6 +28,7 @@
****************************************************************************/
import QtQuick 2.0
+import QtQuick.VirtualKeyboard 2.1
Item {
property bool active
@@ -44,7 +45,7 @@ Item {
onActiveKeyChanged: {
if (activeKey && characterPreview.item !== null) {
- characterPreview.item.text = keyboard.uppercased ? activeKey.text.toUpperCase() : activeKey.text
+ characterPreview.item.text = InputContext.uppercase ? activeKey.text.toUpperCase() : activeKey.text
width = activeKey.width
height = activeKey.height
var position = keyboard.mapFromItem(activeKey, 0, 0)
diff --git a/src/virtualkeyboard/content/components/Keyboard.qml b/src/virtualkeyboard/content/components/Keyboard.qml
index 27d66d2a..2bd2ff2e 100644
--- a/src/virtualkeyboard/content/components/Keyboard.qml
+++ b/src/virtualkeyboard/content/components/Keyboard.qml
@@ -29,7 +29,8 @@
import QtQuick 2.0
import QtQuick.Layouts 1.0
-import QtQuick.VirtualKeyboard 2.1
+import QtQuick.Window 2.2
+import QtQuick.VirtualKeyboard 2.2
import QtQuick.VirtualKeyboard.Styles 2.1
import QtQuick.VirtualKeyboard.Settings 2.2
import Qt.labs.folderlistmodel 2.0
@@ -59,10 +60,10 @@ Item {
return "main"
}
property bool active: Qt.inputMethod.visible
- property bool uppercased: InputContext.shift
property bool handwritingMode
property bool fullScreenHandwritingMode
property bool symbolMode
+ property bool fullScreenMode: VirtualKeyboardSettings.fullScreenMode
property var defaultInputMethod: initDefaultInputMethod()
property var plainInputMethod: PlainInputMethod {}
property var customInputMethod: null
@@ -105,6 +106,10 @@ Item {
if (!isValidLocale(localeIndex) || VirtualKeyboardSettings.locale)
localeIndex = defaultLocaleIndex
}
+ onFullScreenModeChanged: {
+ wordCandidateView.disableAnimation = VirtualKeyboardSettings.fullScreenMode
+ keyboard.fullScreenMode = VirtualKeyboardSettings.fullScreenMode
+ }
}
onAvailableLocaleIndicesChanged: hideLanguagePopup()
onAvailableCustomLocaleIndicesChanged: hideLanguagePopup()
@@ -466,7 +471,10 @@ Item {
Binding {
target: InputContext
property: "keyboardRectangle"
- value: Qt.rect(keyboard.x, keyboard.y + wordCandidateView.currentYOffset, keyboard.width, keyboard.height - wordCandidateView.currentYOffset)
+ value: Qt.rect(keyboard.x,
+ keyboard.y + wordCandidateView.currentYOffset - (shadowInputControl.visible ? shadowInputControl.height : 0),
+ keyboard.width,
+ keyboard.height - wordCandidateView.currentYOffset + (shadowInputControl.visible ? shadowInputControl.height : 0))
when: keyboard.active && !InputContext.animating
}
Binding {
@@ -541,15 +549,58 @@ Item {
}
}
+ ShadowInputControl {
+ id: shadowInputControl
+ objectName: "shadowInputControl"
+ z: -3
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.bottom: wordCandidateView.top
+ height: (keyboard.parent.parent ? keyboard.parent.parent.height : Screen.height) -
+ keyboard.height - (wordCandidateView.visibleCondition ? wordCandidateView.height : 0)
+ visible: fullScreenMode && (shadowInputControlVisibleTimer.running || InputContext.animating)
+
+ Connections {
+ target: keyboard
+ onActiveChanged: {
+ if (keyboard.active)
+ shadowInputControlVisibleTimer.start()
+ else
+ shadowInputControlVisibleTimer.stop()
+ }
+ }
+
+ Timer {
+ id: shadowInputControlVisibleTimer
+ interval: 2147483647
+ repeat: true
+ }
+
+ MouseArea {
+ onPressed: keyboard.hideLanguagePopup()
+ anchors.fill: parent
+ enabled: languagePopupList.enabled
+ }
+ }
+
+ SelectionControl {
+ objectName: "fullScreenModeSelectionControl"
+ inputContext: InputContext.shadow
+ anchors.top: shadowInputControl.top
+ anchors.left: shadowInputControl.left
+ enabled: keyboard.enabled && fullScreenMode
+ }
+
ListView {
id: wordCandidateView
objectName: "wordCandidateView"
clip: true
z: -2
+ property bool disableAnimation: VirtualKeyboardSettings.fullScreenMode
property bool empty: true
- readonly property bool visibleCondition: (((!wordCandidateView.empty || wordCandidateViewAutoHideTimer.running) &&
+ readonly property bool visibleCondition: (((!wordCandidateView.empty || wordCandidateViewAutoHideTimer.running || shadowInputControl.visible) &&
InputContext.inputEngine.wordCandidateListVisibleHint) || VirtualKeyboardSettings.wordCandidateList.alwaysVisible) &&
- keyboard.active
+ (keyboard.active || shadowInputControl.visible)
readonly property real visibleYOffset: VirtualKeyboardSettings.wordCandidateList.alwaysVisible ? 0 : -height
readonly property real currentYOffset: visibleCondition || wordCandidateViewTransition.running ? visibleYOffset : 0
height: Math.round(style.selectionListHeight)
@@ -610,7 +661,7 @@ Item {
transitions: Transition {
id: wordCandidateViewTransition
to: "visible"
- enabled: !InputContext.animating && !VirtualKeyboardSettings.wordCandidateList.alwaysVisible
+ enabled: !InputContext.animating && !VirtualKeyboardSettings.wordCandidateList.alwaysVisible && !wordCandidateView.disableAnimation
reversible: true
ParallelAnimation {
NumberAnimation {
@@ -748,7 +799,7 @@ Item {
function click(key) {
if (key && key.enabled) {
if (!key.noKeyEvent)
- InputContext.inputEngine.virtualKeyClick(key.key, keyboard.uppercased ? key.text.toUpperCase() : key.text, keyboard.uppercased ? Qt.ShiftModifier : 0)
+ InputContext.inputEngine.virtualKeyClick(key.key, InputContext.uppercase ? key.text.toUpperCase() : key.text, InputContext.uppercase ? Qt.ShiftModifier : 0)
key.clicked()
}
}
diff --git a/src/virtualkeyboard/content/components/SelectionControl.qml b/src/virtualkeyboard/content/components/SelectionControl.qml
index a24c1116..125a8eb7 100644
--- a/src/virtualkeyboard/content/components/SelectionControl.qml
+++ b/src/virtualkeyboard/content/components/SelectionControl.qml
@@ -33,18 +33,19 @@ import QtQuick.VirtualKeyboard 2.1
Item {
id: root
property bool handleIsMoving: false
- visible: InputContext.selectionControlVisible || handleIsMoving
+ property var inputContext: InputContext
+ visible: enabled && (inputContext.selectionControlVisible || handleIsMoving) && !InputContext.animating
Loader {
id: anchorHandle
sourceComponent: keyboard.style.selectionHandle
- x: visible ? Qt.inputMethod.anchorRectangle.x - width/2 : 0
- y: visible ? Qt.inputMethod.anchorRectangle.y + Qt.inputMethod.anchorRectangle.height : 0
+ x: visible ? inputContext.anchorRectangle.x - width/2 : 0
+ y: visible ? inputContext.anchorRectangle.y + inputContext.anchorRectangle.height : 0
Behavior on opacity {
NumberAnimation { duration: 200 }
}
- opacity: InputContext.anchorRectIntersectsClipRect ? 1.0 : 0.0
+ opacity: inputContext.anchorRectIntersectsClipRect ? 1.0 : 0.0
MouseArea {
width: parent.width * 2
@@ -55,10 +56,10 @@ Item {
// The middle of a handle is mapped to the middle of the line above it
root.handleIsMoving = true
var xx = x + anchorHandle.x + mouse.x
- var yy = y + anchorHandle.y + mouse.y - (anchorHandle.height + Qt.inputMethod.anchorRectangle.height)/2
+ var yy = y + anchorHandle.y + mouse.y - (anchorHandle.height + inputContext.anchorRectangle.height)/2
var x2 = cursorHandle.x + cursorHandle.width/2
- var y2 = cursorHandle.y - Qt.inputMethod.cursorRectangle.height/2
- InputContext.setSelectionOnFocusObject(Qt.point(xx,yy), Qt.point(x2,y2))
+ var y2 = cursorHandle.y - inputContext.cursorRectangle.height/2
+ inputContext.setSelectionOnFocusObject(Qt.point(xx,yy), Qt.point(x2,y2))
}
onReleased: {
root.handleIsMoving = false
@@ -70,13 +71,13 @@ Item {
Loader {
id: cursorHandle
sourceComponent: keyboard.style.selectionHandle
- x: visible ? Qt.inputMethod.cursorRectangle.x - width/2 : 0
- y: visible ? Qt.inputMethod.cursorRectangle.y + Qt.inputMethod.cursorRectangle.height : 0
+ x: visible ? inputContext.cursorRectangle.x - width/2 : 0
+ y: visible ? inputContext.cursorRectangle.y + inputContext.cursorRectangle.height : 0
Behavior on opacity {
NumberAnimation { duration: 200 }
}
- opacity: InputContext.cursorRectIntersectsClipRect ? 1.0 : 0.0
+ opacity: inputContext.cursorRectIntersectsClipRect ? 1.0 : 0.0
MouseArea {
width: parent.width * 2
@@ -86,10 +87,10 @@ Item {
// we don't move the handles, the handles will move as the selection changes.
root.handleIsMoving = true
var xx = anchorHandle.x + anchorHandle.width/2
- var yy = anchorHandle.y - Qt.inputMethod.anchorRectangle.height/2
+ var yy = anchorHandle.y - inputContext.anchorRectangle.height/2
var x2 = x + cursorHandle.x + mouse.x
- var y2 = y + cursorHandle.y + mouse.y - (cursorHandle.height + Qt.inputMethod.cursorRectangle.height)/2
- InputContext.setSelectionOnFocusObject(Qt.point(xx, yy), Qt.point(x2, y2))
+ var y2 = y + cursorHandle.y + mouse.y - (cursorHandle.height + inputContext.cursorRectangle.height)/2
+ inputContext.setSelectionOnFocusObject(Qt.point(xx, yy), Qt.point(x2, y2))
}
onReleased: {
root.handleIsMoving = false
diff --git a/src/virtualkeyboard/content/components/ShadowInputControl.qml b/src/virtualkeyboard/content/components/ShadowInputControl.qml
new file mode 100644
index 00000000..b935d5c6
--- /dev/null
+++ b/src/virtualkeyboard/content/components/ShadowInputControl.qml
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.7
+import QtQuick.VirtualKeyboard 2.2
+import QtQuick.VirtualKeyboard.Settings 2.2
+
+Item {
+ id: control
+
+ enabled: keyboard.active && VirtualKeyboardSettings.fullScreenMode
+
+ MouseArea {
+ anchors.fill: parent
+ }
+
+ onXChanged: InputContext.shadow.updateSelectionProperties()
+ onYChanged: InputContext.shadow.updateSelectionProperties()
+
+ Loader {
+ sourceComponent: keyboard.style.fullScreenInputContainerBackground
+ anchors.fill: parent
+ Loader {
+ id: fullScreenInputBackground
+ sourceComponent: keyboard.style.fullScreenInputBackground
+ anchors.fill: parent
+ anchors.margins: keyboard.style.fullScreenInputMargins
+ z: 1
+ Flickable {
+ id: flickable
+ clip: true
+ z: 2
+ width: parent.width
+ height: parent.height
+ flickableDirection: Flickable.HorizontalFlick
+ interactive: contentWidth > width
+ contentWidth: shadowInput.width
+ onContentXChanged: InputContext.shadow.updateSelectionProperties()
+
+ function ensureVisible(rectangle) {
+ if (contentX >= rectangle.x)
+ contentX = rectangle.x
+ else if (contentX + width <= rectangle.x + rectangle.width)
+ contentX = rectangle.x + rectangle.width - width;
+ }
+
+ TextInput {
+ id: shadowInput
+ objectName: "shadowInput"
+ property bool blinkStatus: true
+ width: Math.max(flickable.width, implicitWidth)
+ height: implicitHeight
+ anchors.verticalCenter: parent.verticalCenter
+ leftPadding: keyboard.style.fullScreenInputPadding
+ rightPadding: keyboard.style.fullScreenInputPadding
+ activeFocusOnPress: false
+ font: keyboard.style.fullScreenInputFont
+ inputMethodHints: InputContext.inputMethodHints
+ cursorDelegate: keyboard.style.fullScreenInputCursor
+ passwordCharacter: keyboard.style.fullScreenInputPasswordCharacter
+ color: keyboard.style.fullScreenInputColor
+ selectionColor: keyboard.style.fullScreenInputSelectionColor
+ selectedTextColor: keyboard.style.fullScreenInputSelectedTextColor
+ echoMode: (InputContext.inputMethodHints & Qt.ImhHiddenText) ? TextInput.Password : TextInput.Normal
+ selectByMouse: true
+ onCursorPositionChanged: {
+ cursorSyncTimer.restart()
+ blinkStatus = true
+ cursorTimer.restart()
+ }
+ onSelectionStartChanged: cursorSyncTimer.restart()
+ onSelectionEndChanged: cursorSyncTimer.restart()
+ onCursorRectangleChanged: flickable.ensureVisible(cursorRectangle)
+
+ function getAnchorPosition() {
+ if (selectionStart == selectionEnd)
+ return cursorPosition
+ else if (selectionStart == cursorPosition)
+ return selectionEnd
+ else
+ return selectionStart
+ }
+
+ Timer {
+ id: cursorSyncTimer
+ interval: 0
+ onTriggered: {
+ var anchorPosition = shadowInput.getAnchorPosition()
+ if (anchorPosition !== InputContext.anchorPosition || shadowInput.cursorPosition !== InputContext.cursorPosition)
+ InputContext.forceCursorPosition(anchorPosition, shadowInput.cursorPosition)
+ }
+ }
+
+ Timer {
+ id: cursorTimer
+ interval: Qt.styleHints.cursorFlashTime / 2
+ repeat: true
+ running: true
+ onTriggered: shadowInput.blinkStatus = !shadowInput.blinkStatus
+ }
+ }
+ }
+ }
+ }
+
+ Binding {
+ target: InputContext.shadow
+ property: "inputItem"
+ value: shadowInput
+ when: VirtualKeyboardSettings.fullScreenMode
+ }
+}
diff --git a/src/virtualkeyboard/content/components/ShiftKey.qml b/src/virtualkeyboard/content/components/ShiftKey.qml
index b8424a5b..d7705d9f 100644
--- a/src/virtualkeyboard/content/components/ShiftKey.qml
+++ b/src/virtualkeyboard/content/components/ShiftKey.qml
@@ -48,9 +48,5 @@ BaseKey {
highlighted: InputContext.capsLock
functionKey: true
keyPanelDelegate: keyboard.style ? keyboard.style.shiftKeyPanel : undefined
- /*! \internal */
- property bool capsLock: InputContext.capsLock
- /*! \internal */
- property bool shift: InputContext.shift
onClicked: InputContext.shiftHandler.toggleShift()
}
diff --git a/src/virtualkeyboard/content/components/WordCandidatePopupList.qml b/src/virtualkeyboard/content/components/WordCandidatePopupList.qml
index 5057dfa8..7740cbf9 100644
--- a/src/virtualkeyboard/content/components/WordCandidatePopupList.qml
+++ b/src/virtualkeyboard/content/components/WordCandidatePopupList.qml
@@ -54,16 +54,16 @@ ListView {
Binding {
target: wordCandidatePopupList
property: "x"
- value: Qt.inputMethod.cursorRectangle.x -
+ value: Math.round(Qt.inputMethod.cursorRectangle.x -
(wordCandidatePopupList.currentItem ?
(wordCandidatePopupList.currentItem.hasOwnProperty("cursorAnchor") ?
- wordCandidatePopupList.currentItem.cursorAnchor : wordCandidatePopupList.currentItem.width) : 0)
+ wordCandidatePopupList.currentItem.cursorAnchor : wordCandidatePopupList.currentItem.width) : 0))
when: wordCandidatePopupList.visible
}
Binding {
target: wordCandidatePopupList
property: "y"
- value: wordCandidatePopupList.flipVertical ? Qt.inputMethod.cursorRectangle.y - wordCandidatePopupList.height : Qt.inputMethod.cursorRectangle.y + Qt.inputMethod.cursorRectangle.height
+ value: Math.round(wordCandidatePopupList.flipVertical ? Qt.inputMethod.cursorRectangle.y - wordCandidatePopupList.height : Qt.inputMethod.cursorRectangle.y + Qt.inputMethod.cursorRectangle.height)
when: wordCandidatePopupList.visible
}
orientation: ListView.Vertical
diff --git a/src/virtualkeyboard/content/content.qrc b/src/virtualkeyboard/content/content.qrc
index 20627466..431e4205 100644
--- a/src/virtualkeyboard/content/content.qrc
+++ b/src/virtualkeyboard/content/content.qrc
@@ -29,5 +29,6 @@
<file>components/WordCandidatePopupList.qml</file>
<file>components/LanguagePopupList.qml</file>
<file>components/SelectionControl.qml</file>
+ <file>components/ShadowInputControl.qml</file>
</qresource>
</RCC>
diff --git a/src/virtualkeyboard/content/styles/default/style.qml b/src/virtualkeyboard/content/styles/default/style.qml
index e02b749e..03f0344f 100644
--- a/src/virtualkeyboard/content/styles/default/style.qml
+++ b/src/virtualkeyboard/content/styles/default/style.qml
@@ -954,4 +954,24 @@ KeyboardStyle {
sourceSize.width: 20
source: resourcePrefix + "images/selectionhandle-bottom.svg"
}
+
+ fullScreenInputContainerBackground: Rectangle {
+ color: "#FFF"
+ }
+
+ fullScreenInputBackground: Rectangle {
+ color: "#FFF"
+ }
+
+ fullScreenInputMargins: Math.round(15 * scaleHint)
+
+ fullScreenInputPadding: Math.round(30 * scaleHint)
+
+ fullScreenInputCursor: Rectangle {
+ width: 1
+ color: "#000"
+ visible: parent.blinkStatus
+ }
+
+ fullScreenInputFont.pixelSize: 58 * scaleHint
}
diff --git a/src/virtualkeyboard/content/styles/retro/style.qml b/src/virtualkeyboard/content/styles/retro/style.qml
index 04e7ea81..a1cb3ffc 100644
--- a/src/virtualkeyboard/content/styles/retro/style.qml
+++ b/src/virtualkeyboard/content/styles/retro/style.qml
@@ -994,4 +994,28 @@ KeyboardStyle {
sourceSize.width: 20
source: resourcePrefix + "images/selectionhandle-bottom.svg"
}
+
+ fullScreenInputContainerBackground: Rectangle {
+ color: "#FFF"
+ }
+
+ fullScreenInputBackground: Rectangle {
+ color: "#FFF"
+ }
+
+ fullScreenInputMargins: Math.round(15 * scaleHint)
+
+ fullScreenInputPadding: Math.round(30 * scaleHint)
+
+ fullScreenInputCursor: Rectangle {
+ width: 1
+ color: "#000"
+ visible: parent.blinkStatus
+ }
+
+ fullScreenInputFont.pixelSize: 58 * scaleHint
+
+ fullScreenInputPasswordCharacter: "*"
+
+ fullScreenInputSelectionColor: "#B57C47"
}
diff --git a/src/virtualkeyboard/doc/src/qtvirtualkeyboard-index.qdoc b/src/virtualkeyboard/doc/src/qtvirtualkeyboard-index.qdoc
index ca19f825..91373b23 100644
--- a/src/virtualkeyboard/doc/src/qtvirtualkeyboard-index.qdoc
+++ b/src/virtualkeyboard/doc/src/qtvirtualkeyboard-index.qdoc
@@ -124,7 +124,7 @@
*/
/*!
-\qmlmodule QtQuick.VirtualKeyboard 2.0
+\qmlmodule QtQuick.VirtualKeyboard 2.2
\title Qt Virtual Keyboard QML Types
\ingroup qmlmodules
\brief Provides QML types for an input framework and a reference keyboard front
@@ -134,8 +134,8 @@ end.
import statements in your .qml file:
\code
- import QtQuick.VirtualKeyboard 2.0
- import QtQuick.VirtualKeyboard.Styles 2.0
+ import QtQuick.VirtualKeyboard 2.2
+ import QtQuick.VirtualKeyboard.Styles 2.2
import QtQuick.VirtualKeyboard.Settings 2.2
\endcode
diff --git a/src/virtualkeyboard/inputcontext.cpp b/src/virtualkeyboard/inputcontext.cpp
index 50255e6e..d069927b 100644
--- a/src/virtualkeyboard/inputcontext.cpp
+++ b/src/virtualkeyboard/inputcontext.cpp
@@ -31,6 +31,7 @@
#include "inputengine.h"
#include "shifthandler.h"
#include "platforminputcontext.h"
+#include "shadowinputcontext.h"
#include "virtualkeyboarddebug.h"
#include "enterkeyaction.h"
#include "settings.h"
@@ -70,7 +71,8 @@ public:
ReselectEventState = 0x1,
InputMethodEventState = 0x2,
KeyEventState = 0x4,
- InputMethodClickState = 0x8
+ InputMethodClickState = 0x8,
+ SyncShadowInputState = 0x10
};
Q_DECLARE_FLAGS(StateFlags, StateFlag)
@@ -87,6 +89,8 @@ public:
shift(false),
capsLock(false),
cursorPosition(0),
+ anchorPosition(0),
+ forceAnchorPosition(-1),
forceCursorPosition(-1),
inputMethodHints(Qt::ImhNone),
preeditText(),
@@ -116,6 +120,8 @@ public:
bool capsLock;
StateFlags stateFlags;
int cursorPosition;
+ int anchorPosition;
+ int forceAnchorPosition;
int forceCursorPosition;
Qt::InputMethodHints inputMethodHints;
QString preeditText;
@@ -131,6 +137,7 @@ public:
QSet<int> activeNavigationKeys;
#endif
QSet<quint32> activeKeys;
+ ShadowInputContext shadow;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(InputContextPrivate::StateFlags)
@@ -162,6 +169,7 @@ InputContext::InputContext(PlatformInputContext *parent) :
{
Q_D(InputContext);
d->inputContext = parent;
+ d->shadow.setInputContext(this);
if (d->inputContext) {
d->inputContext->setInputContext(this);
connect(d->inputContext, SIGNAL(focusObjectChanged()), SLOT(onInputItemChanged()));
@@ -225,6 +233,12 @@ bool InputContext::uppercase() const
return d->shift || d->capsLock;
}
+int InputContext::anchorPosition() const
+{
+ Q_D(const InputContext);
+ return d->anchorPosition;
+}
+
int InputContext::cursorPosition() const
{
Q_D(const InputContext);
@@ -247,29 +261,24 @@ void InputContext::setPreeditText(const QString &text, QList<QInputMethodEvent::
{
// Add default attributes
if (!text.isEmpty()) {
- bool containsTextFormat = false;
- for (QList<QInputMethodEvent::Attribute>::ConstIterator attribute = attributes.constBegin();
- attribute != attributes.constEnd(); attribute++) {
- if (attribute->type == QInputMethodEvent::TextFormat) {
- containsTextFormat = true;
- break;
- }
- }
- if (!containsTextFormat) {
+ if (!testAttribute(attributes, QInputMethodEvent::TextFormat)) {
QTextCharFormat textFormat;
textFormat.setUnderlineStyle(QTextCharFormat::SingleUnderline);
attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, 0, text.length(), textFormat));
}
} else {
- Q_D(InputContext);
- if (d->forceCursorPosition != -1)
- attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Selection, d->forceCursorPosition, 0, QVariant()));
- d->forceCursorPosition = -1;
+ addSelectionAttribute(attributes);
}
sendPreedit(text, attributes, replaceFrom, replaceLength);
}
+QList<QInputMethodEvent::Attribute> InputContext::preeditTextAttributes() const
+{
+ Q_D(const InputContext);
+ return d->preeditTextAttributes;
+}
+
QString InputContext::surroundingText() const
{
Q_D(const InputContext);
@@ -491,13 +500,11 @@ void InputContext::commit(const QString &text, int replaceFrom, int replaceLengt
VIRTUALKEYBOARD_DEBUG() << "InputContext::commit():" << text << replaceFrom << replaceLength;
bool preeditChanged = !d->preeditText.isEmpty();
d->preeditText.clear();
+ d->preeditTextAttributes.clear();
if (d->inputContext) {
QList<QInputMethodEvent::Attribute> attributes;
- if (d->forceCursorPosition != -1) {
- attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Selection, d->forceCursorPosition, 0, QVariant()));
- d->forceCursorPosition = -1;
- }
+ addSelectionAttribute(attributes);
QInputMethodEvent inputEvent(QString(), attributes);
inputEvent.setCommitString(text, replaceFrom, replaceLength);
d->stateFlags |= InputContextPrivate::InputMethodEventState;
@@ -524,13 +531,11 @@ void InputContext::clear()
Q_D(InputContext);
bool preeditChanged = !d->preeditText.isEmpty();
d->preeditText.clear();
+ d->preeditTextAttributes.clear();
if (d->inputContext) {
QList<QInputMethodEvent::Attribute> attributes;
- if (d->forceCursorPosition != -1) {
- attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Selection, d->forceCursorPosition, 0, QVariant()));
- d->forceCursorPosition = -1;
- }
+ addSelectionAttribute(attributes);
QInputMethodEvent event(QString(), attributes);
d->stateFlags |= InputContextPrivate::InputMethodEventState;
d->inputContext->sendEvent(&event);
@@ -576,6 +581,42 @@ void InputContext::setSelectionOnFocusObject(const QPointF &anchorPos, const QPo
QPlatformInputContext::setSelectionOnFocusObject(anchorPos, cursorPos);
}
+/*!
+ \internal
+*/
+void InputContext::forceCursorPosition(int anchorPosition, int cursorPosition)
+{
+ Q_D(InputContext);
+ if (!d->shadow.inputItem())
+ return;
+ if (!d->inputContext->m_visible)
+ return;
+ if (d->stateFlags.testFlag(InputContextPrivate::ReselectEventState))
+ return;
+ if (d->stateFlags.testFlag(InputContextPrivate::SyncShadowInputState))
+ return;
+
+ VIRTUALKEYBOARD_DEBUG() << "InputContext::forceCursorPosition():" << cursorPosition << "anchorPosition:" << anchorPosition;
+ if (!d->preeditText.isEmpty()) {
+ d->forceAnchorPosition = -1;
+ d->forceCursorPosition = cursorPosition;
+ if (cursorPosition > d->cursorPosition)
+ d->forceCursorPosition += d->preeditText.length();
+ d->inputEngine->update();
+ } else {
+ d->forceAnchorPosition = anchorPosition;
+ d->forceCursorPosition = cursorPosition;
+ setPreeditText("");
+ if (!d->inputMethodHints.testFlag(Qt::ImhNoPredictiveText) &&
+ cursorPosition > 0 && d->selectedText.isEmpty()) {
+ d->stateFlags |= InputContextPrivate::ReselectEventState;
+ if (d->inputEngine->reselect(cursorPosition, InputEngine::WordAtCursor))
+ d->stateFlags |= InputContextPrivate::InputMethodClickState;
+ d->stateFlags &= ~InputContextPrivate::ReselectEventState;
+ }
+ }
+}
+
bool InputContext::anchorRectIntersectsClipRect() const
{
Q_D(const InputContext);
@@ -594,6 +635,12 @@ bool InputContext::selectionControlVisible() const
return d->selectionControlVisible;
}
+ShadowInputContext *InputContext::shadow() const
+{
+ Q_D(const InputContext);
+ return const_cast<ShadowInputContext *>(&d->shadow);
+}
+
void InputContext::onInputItemChanged()
{
Q_D(InputContext);
@@ -630,16 +677,30 @@ void InputContext::sendPreedit(const QString &text, const QList<QInputMethodEven
if (d->inputContext) {
QInputMethodEvent event(text, attributes);
- if (replaceFrom != 0 || replaceLength > 0)
+ const bool replace = replaceFrom != 0 || replaceLength > 0;
+ if (replace)
event.setCommitString(QString(), replaceFrom, replaceLength);
d->stateFlags |= InputContextPrivate::InputMethodEventState;
d->inputContext->sendEvent(&event);
d->stateFlags &= ~InputContextPrivate::InputMethodEventState;
+
+ // Send also to shadow input if only attributes changed.
+ // In this case the update() may not be called, so the shadow
+ // input may be out of sync.
+ if (d->shadow.inputItem() && !replace && !text.isEmpty() &&
+ !textChanged && attributesChanged) {
+ VIRTUALKEYBOARD_DEBUG() << "InputContext::sendPreedit(shadow):" << text << replaceFrom << replaceLength;
+ event.setAccepted(true);
+ QGuiApplication::sendEvent(d->shadow.inputItem(), &event);
+ }
}
if (textChanged)
emit preeditTextChanged();
}
+
+ if (d->preeditText.isEmpty())
+ d->preeditTextAttributes.clear();
}
void InputContext::reset()
@@ -679,6 +740,7 @@ void InputContext::update(Qt::InputMethodQueries queries)
bool newInputMethodHints = inputMethodHints != d->inputMethodHints;
bool newSurroundingText = surroundingText != d->surroundingText;
bool newSelectedText = selectedText != d->selectedText;
+ bool newAnchorPosition = anchorPosition != d->anchorPosition;
bool newCursorPosition = cursorPosition != d->cursorPosition;
bool newAnchorRectangle = anchorRectangle != d->anchorRectangle;
bool newCursorRectangle = cursorRectangle != d->cursorRectangle;
@@ -699,6 +761,7 @@ void InputContext::update(Qt::InputMethodQueries queries)
d->inputMethodHints = inputMethodHints;
d->surroundingText = surroundingText;
d->selectedText = selectedText;
+ d->anchorPosition = anchorPosition;
d->cursorPosition = cursorPosition;
d->anchorRectangle = anchorRectangle;
d->cursorRectangle = cursorRectangle;
@@ -725,6 +788,9 @@ void InputContext::update(Qt::InputMethodQueries queries)
if (newSelectedText) {
emit selectedTextChanged();
}
+ if (newAnchorPosition) {
+ emit anchorPositionChanged();
+ }
if (newCursorPosition) {
emit cursorPositionChanged();
}
@@ -755,6 +821,12 @@ void InputContext::update(Qt::InputMethodQueries queries)
d->stateFlags |= InputContextPrivate::InputMethodClickState;
d->stateFlags &= ~InputContextPrivate::ReselectEventState;
}
+
+ if (!d->stateFlags.testFlag(InputContextPrivate::SyncShadowInputState)) {
+ d->stateFlags |= InputContextPrivate::SyncShadowInputState;
+ d->shadow.update(queries);
+ d->stateFlags &= ~InputContextPrivate::SyncShadowInputState;
+ }
}
void InputContext::invokeAction(QInputMethod::Action action, int cursorPosition)
@@ -822,6 +894,28 @@ bool InputContext::filterEvent(const QEvent *event)
return false;
}
+void InputContext::addSelectionAttribute(QList<QInputMethodEvent::Attribute> &attributes)
+{
+ Q_D(InputContext);
+ if (!testAttribute(attributes, QInputMethodEvent::Selection) && d->forceCursorPosition != -1) {
+ if (d->forceAnchorPosition != -1)
+ attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Selection, d->forceAnchorPosition, d->forceCursorPosition - d->forceAnchorPosition, QVariant()));
+ else
+ attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Selection, d->forceCursorPosition, 0, QVariant()));
+ }
+ d->forceAnchorPosition = -1;
+ d->forceCursorPosition = -1;
+}
+
+bool InputContext::testAttribute(const QList<QInputMethodEvent::Attribute> &attributes, QInputMethodEvent::AttributeType attributeType) const
+{
+ for (const QInputMethodEvent::Attribute &attribute : qAsConst(attributes)) {
+ if (attribute.type == attributeType)
+ return true;
+ }
+ return false;
+}
+
/*!
\qmlproperty bool InputContext::focus
@@ -876,6 +970,20 @@ bool InputContext::filterEvent(const QEvent *event)
*/
/*!
+ \qmlproperty int InputContext::anchorPosition
+ \since QtQuick.VirtualKeyboard 2.2
+
+ This property is changed when the anchor position changes.
+*/
+
+/*!
+ \property QtVirtualKeyboard::InputContext::anchorPosition
+ \brief the anchor position.
+
+ This property is changed when the anchor position changes.
+*/
+
+/*!
\qmlproperty int InputContext::cursorPosition
This property is changed when the cursor position changes.
diff --git a/src/virtualkeyboard/inputcontext.h b/src/virtualkeyboard/inputcontext.h
index 925745bd..3b0727e2 100644
--- a/src/virtualkeyboard/inputcontext.h
+++ b/src/virtualkeyboard/inputcontext.h
@@ -39,6 +39,7 @@
namespace QtVirtualKeyboard {
class PlatformInputContext;
+class ShadowInputContext;
class InputEngine;
class ShiftHandler;
class InputContextPrivate;
@@ -52,6 +53,7 @@ class InputContext : public QObject
Q_PROPERTY(bool shift READ shift WRITE setShift NOTIFY shiftChanged)
Q_PROPERTY(bool capsLock READ capsLock WRITE setCapsLock NOTIFY capsLockChanged)
Q_PROPERTY(bool uppercase READ uppercase NOTIFY uppercaseChanged)
+ Q_PROPERTY(int anchorPosition READ anchorPosition NOTIFY anchorPositionChanged)
Q_PROPERTY(int cursorPosition READ cursorPosition NOTIFY cursorPositionChanged)
Q_PROPERTY(Qt::InputMethodHints inputMethodHints READ inputMethodHints NOTIFY inputMethodHintsChanged)
Q_PROPERTY(QString preeditText READ preeditText WRITE setPreeditText NOTIFY preeditTextChanged)
@@ -70,6 +72,7 @@ class InputContext : public QObject
Q_PROPERTY(bool selectionControlVisible READ selectionControlVisible NOTIFY selectionControlVisibleChanged)
Q_PROPERTY(bool anchorRectIntersectsClipRect READ anchorRectIntersectsClipRect NOTIFY anchorRectIntersectsClipRectChanged)
Q_PROPERTY(bool cursorRectIntersectsClipRect READ cursorRectIntersectsClipRect NOTIFY cursorRectIntersectsClipRectChanged)
+ Q_PROPERTY(ShadowInputContext *shadow READ shadow CONSTANT)
public:
explicit InputContext(PlatformInputContext *parent = 0);
@@ -81,10 +84,12 @@ public:
bool capsLock() const;
void setCapsLock(bool enable);
bool uppercase() const;
+ int anchorPosition() const;
int cursorPosition() const;
Qt::InputMethodHints inputMethodHints() const;
QString preeditText() const;
void setPreeditText(const QString &text, QList<QInputMethodEvent::Attribute> attributes = QList<QInputMethodEvent::Attribute>(), int replaceFrom = 0, int replaceLength = 0);
+ QList<QInputMethodEvent::Attribute> preeditTextAttributes() const;
QString surroundingText() const;
QString selectedText() const;
QRectF anchorRectangle() const;
@@ -106,6 +111,7 @@ public:
bool selectionControlVisible() const;
bool anchorRectIntersectsClipRect() const;
bool cursorRectIntersectsClipRect() const;
+ ShadowInputContext *shadow() const;
Q_INVOKABLE void hideInputPanel();
Q_INVOKABLE void sendKeyClick(int key, const QString &text, int modifiers = 0);
@@ -120,6 +126,9 @@ public:
// For selection handles
Q_INVOKABLE void setSelectionOnFocusObject(const QPointF &anchorPos, const QPointF &cursorPos);
+ // For shadow input
+ Q_INVOKABLE void forceCursorPosition(int anchorPosition, int cursorPosition);
+
signals:
void focusChanged();
void focusEditorChanged();
@@ -127,6 +136,7 @@ signals:
void inputMethodHintsChanged();
void surroundingTextChanged();
void selectedTextChanged();
+ void anchorPositionChanged();
void cursorPositionChanged();
void anchorRectangleChanged();
void cursorRectangleChanged();
@@ -156,6 +166,8 @@ private:
void update(Qt::InputMethodQueries queries);
void invokeAction(QInputMethod::Action action, int cursorPosition);
bool filterEvent(const QEvent *event);
+ void addSelectionAttribute(QList<QInputMethodEvent::Attribute> &attributes);
+ bool testAttribute(const QList<QInputMethodEvent::Attribute> &attributes, QInputMethodEvent::AttributeType attributeType) const;
private:
friend class PlatformInputContext;
diff --git a/src/virtualkeyboard/platforminputcontext.cpp b/src/virtualkeyboard/platforminputcontext.cpp
index d9378195..6d555160 100644
--- a/src/virtualkeyboard/platforminputcontext.cpp
+++ b/src/virtualkeyboard/platforminputcontext.cpp
@@ -29,6 +29,7 @@
#include "platforminputcontext.h"
#include "inputcontext.h"
+#include "shadowinputcontext.h"
#include "abstractinputpanel.h"
#ifdef QT_VIRTUALKEYBOARD_DESKTOP
#include "desktopinputpanel.h"
@@ -181,6 +182,9 @@ QObject *PlatformInputContext::focusObject()
void PlatformInputContext::setFocusObject(QObject *object)
{
VIRTUALKEYBOARD_DEBUG() << "PlatformInputContext::setFocusObject():" << object;
+ Q_ASSERT(m_inputContext == 0 ||
+ m_inputContext->shadow()->inputItem() == 0 ||
+ m_inputContext->shadow()->inputItem() != object);
if (m_focusObject != object) {
if (m_focusObject)
m_focusObject->removeEventFilter(this);
diff --git a/src/virtualkeyboard/plugin.cpp b/src/virtualkeyboard/plugin.cpp
index 5349e735..73ddeabc 100644
--- a/src/virtualkeyboard/plugin.cpp
+++ b/src/virtualkeyboard/plugin.cpp
@@ -59,6 +59,7 @@
#include "enterkeyactionattachedtype.h"
#include "virtualkeyboardsettings.h"
#include "trace.h"
+#include "shadowinputcontext.h"
#if defined(QT_STATICPLUGIN)
#include <QtPlugin>
// This macro is similar to Q_IMPORT_PLUGIN, except it does not
@@ -182,6 +183,8 @@ QPlatformInputContext *QVirtualKeyboardPlugin::create(const QString &system, con
qmlRegisterType<EnterKeyAction>(pluginUri, 1, 0, "EnterKeyAction");
qmlRegisterType<EnterKeyAction>(pluginUri, 2, 0, "EnterKeyAction");
qmlRegisterType<Trace>(pluginUri, 2, 0, "Trace");
+ qRegisterMetaType<QtVirtualKeyboard::ShadowInputContext *>("ShadowInputContext*");
+ qmlRegisterUncreatableType<ShadowInputContext>(pluginUri, 2, 2, "ShadowInputContext", QLatin1String("Cannot create shadow input context"));
qmlRegisterSingletonType<VirtualKeyboardSettings>(pluginSettingsUri, 1, 0, "VirtualKeyboardSettings", VirtualKeyboardSettings::registerSettingsModule);
qmlRegisterSingletonType<VirtualKeyboardSettings>(pluginSettingsUri, 1, 1, "VirtualKeyboardSettings", VirtualKeyboardSettings::registerSettingsModule);
qmlRegisterSingletonType<VirtualKeyboardSettings>(pluginSettingsUri, 1, 2, "VirtualKeyboardSettings", VirtualKeyboardSettings::registerSettingsModule);
@@ -195,6 +198,7 @@ QPlatformInputContext *QVirtualKeyboardPlugin::create(const QString &system, con
qmlRegisterType(QUrl(path + QLatin1String("InputPanel.qml")), pluginUri, 1, 3, "InputPanel");
qmlRegisterType(QUrl(path + QLatin1String("InputPanel.qml")), pluginUri, 2, 0, "InputPanel");
qmlRegisterType(QUrl(path + QLatin1String("InputPanel.qml")), pluginUri, 2, 1, "InputPanel");
+ qmlRegisterType(QUrl(path + QLatin1String("InputPanel.qml")), pluginUri, 2, 2, "InputPanel");
qmlRegisterType(QUrl(path + QLatin1String("HandwritingInputPanel.qml")), pluginUri, 2, 0, "HandwritingInputPanel");
const QString componentsPath = path + QStringLiteral("components/");
qmlRegisterType(QUrl(componentsPath + QLatin1String("AlternativeKeys.qml")), pluginUri, 1, 0, "AlternativeKeys");
diff --git a/src/virtualkeyboard/settings.cpp b/src/virtualkeyboard/settings.cpp
index 85a0f3a2..259516aa 100644
--- a/src/virtualkeyboard/settings.cpp
+++ b/src/virtualkeyboard/settings.cpp
@@ -45,7 +45,8 @@ public:
layoutPath(),
wclAutoHideDelay(5000),
wclAlwaysVisible(false),
- wclAutoCommitWord(false)
+ wclAutoCommitWord(false),
+ fullScreenMode(false)
{}
QString style;
@@ -57,6 +58,7 @@ public:
int wclAutoHideDelay;
bool wclAlwaysVisible;
bool wclAutoCommitWord;
+ bool fullScreenMode;
};
static QScopedPointer<Settings> s_settingsInstance;
@@ -213,4 +215,19 @@ void Settings::setWclAutoCommitWord(bool wclAutoCommitWord)
}
}
+bool Settings::fullScreenMode() const
+{
+ Q_D(const Settings);
+ return d->fullScreenMode;
+}
+
+void Settings::setFullScreenMode(bool fullScreenMode)
+{
+ Q_D(Settings);
+ if (d->fullScreenMode != fullScreenMode) {
+ d->fullScreenMode = fullScreenMode;
+ emit fullScreenModeChanged();
+ }
+}
+
} // namespace QtVirtualKeyboard
diff --git a/src/virtualkeyboard/settings.h b/src/virtualkeyboard/settings.h
index 09e6bcb2..9d4684fa 100644
--- a/src/virtualkeyboard/settings.h
+++ b/src/virtualkeyboard/settings.h
@@ -75,6 +75,9 @@ public:
bool wclAutoCommitWord() const;
void setWclAutoCommitWord(bool wclAutoCommitWord);
+ bool fullScreenMode() const;
+ void setFullScreenMode(bool fullScreenMode);
+
signals:
void styleChanged();
void styleNameChanged();
@@ -85,6 +88,7 @@ signals:
void wclAutoHideDelayChanged();
void wclAlwaysVisibleChanged();
void wclAutoCommitWordChanged();
+ void fullScreenModeChanged();
};
} // namespace QtVirtualKeyboard
diff --git a/src/virtualkeyboard/shadowinputcontext.cpp b/src/virtualkeyboard/shadowinputcontext.cpp
new file mode 100644
index 00000000..b350e249
--- /dev/null
+++ b/src/virtualkeyboard/shadowinputcontext.cpp
@@ -0,0 +1,253 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "shadowinputcontext.h"
+#include "inputcontext.h"
+#include "virtualkeyboarddebug.h"
+
+#include <QtCore/private/qobject_p.h>
+#include <QGuiApplication>
+#include <QQuickItem>
+
+QT_BEGIN_NAMESPACE
+bool operator==(const QInputMethodEvent::Attribute &attribute1, const QInputMethodEvent::Attribute &attribute2);
+QT_END_NAMESPACE
+
+namespace QtVirtualKeyboard {
+
+class ShadowInputContextPrivate : public QObjectPrivate
+{
+public:
+ ShadowInputContextPrivate() :
+ QObjectPrivate(),
+ inputContext(0),
+ anchorRectIntersectsClipRect(false),
+ cursorRectIntersectsClipRect(false),
+ selectionControlVisible(false)
+ {
+ }
+
+ InputContext *inputContext;
+ QPointer<QObject> inputItem;
+ QString preeditText;
+ QList<QInputMethodEvent::Attribute> preeditTextAttributes;
+ QRectF anchorRectangle;
+ QRectF cursorRectangle;
+ bool anchorRectIntersectsClipRect;
+ bool cursorRectIntersectsClipRect;
+ bool selectionControlVisible;
+};
+
+ShadowInputContext::ShadowInputContext(QObject *parent) :
+ QObject(*new ShadowInputContextPrivate(), parent)
+{
+}
+
+void ShadowInputContext::setInputContext(InputContext *inputContext)
+{
+ Q_D(ShadowInputContext);
+ d->inputContext = inputContext;
+}
+
+QObject *ShadowInputContext::inputItem() const
+{
+ Q_D(const ShadowInputContext);
+ return d->inputItem.data();
+}
+
+void ShadowInputContext::setInputItem(QObject *inputItem)
+{
+ Q_D(ShadowInputContext);
+ if (d->inputItem != inputItem) {
+ d->inputItem = inputItem;
+ emit inputItemChanged();
+ update(Qt::ImQueryAll);
+ }
+}
+
+QRectF ShadowInputContext::anchorRectangle() const
+{
+ Q_D(const ShadowInputContext);
+ return d->anchorRectangle;
+}
+
+QRectF ShadowInputContext::cursorRectangle() const
+{
+ Q_D(const ShadowInputContext);
+ return d->cursorRectangle;
+}
+
+bool ShadowInputContext::anchorRectIntersectsClipRect() const
+{
+ Q_D(const ShadowInputContext);
+ return d->anchorRectIntersectsClipRect;
+}
+
+bool ShadowInputContext::cursorRectIntersectsClipRect() const
+{
+ Q_D(const ShadowInputContext);
+ return d->cursorRectIntersectsClipRect;
+}
+
+bool ShadowInputContext::selectionControlVisible() const
+{
+ Q_D(const ShadowInputContext);
+ return d->selectionControlVisible;
+}
+
+void ShadowInputContext::setSelectionOnFocusObject(const QPointF &anchorPos, const QPointF &cursorPos)
+{
+ Q_D(ShadowInputContext);
+ QObject *focus = d->inputItem;
+ if (!focus)
+ return;
+
+ QQuickItem *quickItem = qobject_cast<QQuickItem *>(d->inputItem);
+ bool success;
+ int anchor = queryFocusObject(Qt::ImCursorPosition, quickItem ? quickItem->mapFromScene(anchorPos) : anchorPos).toInt(&success);
+ if (success) {
+ int cursor = queryFocusObject(Qt::ImCursorPosition, quickItem ? quickItem->mapFromScene(cursorPos) : cursorPos).toInt(&success);
+ if (success) {
+ QList<QInputMethodEvent::Attribute> imAttributes;
+ imAttributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Selection, anchor, cursor - anchor, QVariant()));
+ QInputMethodEvent event(QString(), imAttributes);
+ QGuiApplication::sendEvent(QGuiApplication::focusObject(), &event);
+ }
+ }
+}
+
+void ShadowInputContext::updateSelectionProperties()
+{
+ Q_D(ShadowInputContext);
+ if (!d->inputItem)
+ return;
+
+ QInputMethodQueryEvent imQueryEvent(Qt::ImAnchorRectangle |
+ Qt::ImCursorRectangle |
+ Qt::ImInputItemClipRectangle);
+ QGuiApplication::sendEvent(d->inputItem, &imQueryEvent);
+ QQuickItem *quickItem = qobject_cast<QQuickItem *>(d->inputItem);
+ const QRectF anchorRect = imQueryEvent.value(Qt::ImAnchorRectangle).toRectF();
+ const QRectF cursorRect = imQueryEvent.value(Qt::ImCursorRectangle).toRectF();
+ const QRectF anchorRectangle = quickItem ? quickItem->mapRectToScene(anchorRect) : anchorRect;
+ const QRectF cursorRectangle = quickItem ? quickItem->mapRectToScene(cursorRect) : cursorRect;
+ const QRectF inputItemClipRect = imQueryEvent.value(Qt::ImInputItemClipRectangle).toRectF();
+ const bool anchorRectIntersectsClipRect = inputItemClipRect.intersects(anchorRect);
+ const bool cursorRectIntersectsClipRect = inputItemClipRect.intersects(cursorRect);
+ const bool selectionControlVisible = d->inputContext->selectionControlVisible();
+
+ const bool newAnchorRectangle = anchorRectangle != d->anchorRectangle;
+ const bool newCursorRectangle = cursorRectangle != d->cursorRectangle;
+ const bool newAnchorRectIntersectsClipRect = anchorRectIntersectsClipRect != d->anchorRectIntersectsClipRect;
+ const bool newCursorRectIntersectsClipRect = cursorRectIntersectsClipRect != d->cursorRectIntersectsClipRect;
+ const bool newSelectionControlVisible = selectionControlVisible != d->selectionControlVisible;
+
+ d->anchorRectangle = anchorRectangle;
+ d->cursorRectangle = cursorRectangle;
+ d->anchorRectIntersectsClipRect = anchorRectIntersectsClipRect;
+ d->cursorRectIntersectsClipRect = cursorRectIntersectsClipRect;
+ d->selectionControlVisible = selectionControlVisible;
+
+ if (newAnchorRectangle)
+ emit anchorRectangleChanged();
+ if (newCursorRectangle)
+ emit cursorRectangleChanged();
+ if (newAnchorRectIntersectsClipRect)
+ emit anchorRectIntersectsClipRectChanged();
+ if (newCursorRectIntersectsClipRect)
+ emit cursorRectIntersectsClipRectChanged();
+ if (newSelectionControlVisible)
+ emit selectionControlVisibleChanged();
+}
+
+void ShadowInputContext::update(Qt::InputMethodQueries queries)
+{
+ Q_UNUSED(queries)
+ Q_D(ShadowInputContext);
+ if (!d->inputItem)
+ return;
+
+ QInputMethodQueryEvent imQueryEvent(Qt::ImQueryInput);
+ QGuiApplication::sendEvent(d->inputItem, &imQueryEvent);
+
+ const QString surroundingText = imQueryEvent.value(Qt::ImSurroundingText).toString();
+ const int cursorPosition = imQueryEvent.value(Qt::ImCursorPosition).toInt();
+ const int anchorPosition = imQueryEvent.value(Qt::ImAnchorPosition).toInt();
+
+ const QString newSurroundingText = d->inputContext->surroundingText();
+ const int newCursorPosition = d->inputContext->cursorPosition();
+ const int newAnchorPosition = d->inputContext->anchorPosition();
+
+ bool updateSurroundingText = newSurroundingText != surroundingText;
+ bool updateSelection = newCursorPosition != cursorPosition || newAnchorPosition != anchorPosition;
+ if (updateSurroundingText || updateSelection) {
+ QList<QInputMethodEvent::Attribute> attributes;
+ attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Selection,
+ newAnchorPosition,
+ newCursorPosition - newAnchorPosition, QVariant()));
+ QInputMethodEvent inputEvent(QString(), attributes);
+ if (updateSurroundingText)
+ inputEvent.setCommitString(newSurroundingText, -cursorPosition, surroundingText.length());
+ QGuiApplication::sendEvent(d->inputItem, &inputEvent);
+ }
+
+ const QString newPreeditText = d->inputContext->preeditText();
+ const QList<QInputMethodEvent::Attribute> newPreeditAttributes = d->inputContext->preeditTextAttributes();
+ if (d->preeditText != newPreeditText || d->preeditTextAttributes != newPreeditAttributes) {
+ d->preeditText = newPreeditText;
+ d->preeditTextAttributes = newPreeditAttributes;
+ QInputMethodEvent inputEvent(d->preeditText, d->preeditTextAttributes);
+ QGuiApplication::sendEvent(d->inputItem, &inputEvent);
+ }
+
+ updateSelectionProperties();
+}
+
+QVariant ShadowInputContext::queryFocusObject(Qt::InputMethodQuery query, QVariant argument)
+{
+ Q_D(ShadowInputContext);
+ QVariant retval;
+ QObject *focusObject = d->inputItem;
+ if (!focusObject)
+ return retval;
+
+ bool newMethodWorks = QMetaObject::invokeMethod(focusObject, "inputMethodQuery",
+ Qt::DirectConnection,
+ Q_RETURN_ARG(QVariant, retval),
+ Q_ARG(Qt::InputMethodQuery, query),
+ Q_ARG(QVariant, argument));
+ if (newMethodWorks)
+ return retval;
+
+ QInputMethodQueryEvent queryEvent(query);
+ QCoreApplication::sendEvent(focusObject, &queryEvent);
+ return queryEvent.value(query);
+}
+
+} // namespace QtVirtualKeyboard
diff --git a/src/virtualkeyboard/shadowinputcontext.h b/src/virtualkeyboard/shadowinputcontext.h
new file mode 100644
index 00000000..1a2e0577
--- /dev/null
+++ b/src/virtualkeyboard/shadowinputcontext.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SHADOWINPUTCONTEXT_H
+#define SHADOWINPUTCONTEXT_H
+
+#include <QObject>
+#include <QPointer>
+#include <QMetaType>
+#include <QRectF>
+
+namespace QtVirtualKeyboard {
+
+class InputContext;
+class ShadowInputContextPrivate;
+
+class ShadowInputContext : public QObject
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(ShadowInputContext)
+ Q_DECLARE_PRIVATE(ShadowInputContext)
+ Q_PROPERTY(QObject *inputItem READ inputItem WRITE setInputItem NOTIFY inputItemChanged)
+ Q_PROPERTY(QRectF anchorRectangle READ anchorRectangle NOTIFY anchorRectangleChanged)
+ Q_PROPERTY(QRectF cursorRectangle READ cursorRectangle NOTIFY cursorRectangleChanged)
+ Q_PROPERTY(bool anchorRectIntersectsClipRect READ anchorRectIntersectsClipRect NOTIFY anchorRectIntersectsClipRectChanged)
+ Q_PROPERTY(bool cursorRectIntersectsClipRect READ cursorRectIntersectsClipRect NOTIFY cursorRectIntersectsClipRectChanged)
+ Q_PROPERTY(bool selectionControlVisible READ selectionControlVisible NOTIFY selectionControlVisibleChanged)
+
+ explicit ShadowInputContext(QObject *parent = 0);
+
+ void setInputContext(InputContext *inputContext);
+
+public:
+ QObject *inputItem() const;
+ void setInputItem(QObject *inputItem);
+ QRectF anchorRectangle() const;
+ QRectF cursorRectangle() const;
+ bool anchorRectIntersectsClipRect() const;
+ bool cursorRectIntersectsClipRect() const;
+ bool selectionControlVisible() const;
+
+ Q_INVOKABLE void setSelectionOnFocusObject(const QPointF &anchorPos, const QPointF &cursorPos);
+ Q_INVOKABLE void updateSelectionProperties();
+
+signals:
+ void inputItemChanged();
+ void anchorRectangleChanged();
+ void cursorRectangleChanged();
+ void anchorRectIntersectsClipRectChanged();
+ void cursorRectIntersectsClipRectChanged();
+ void selectionControlVisibleChanged();
+
+private:
+ void update(Qt::InputMethodQueries queries);
+ QVariant queryFocusObject(Qt::InputMethodQuery query, QVariant argument);
+
+private:
+ friend class InputContextPrivate;
+ friend class InputContext;
+};
+
+} // namespace QtVirtualKeyboard
+
+#endif // SHADOWINPUTCONTEXT_H
diff --git a/src/virtualkeyboard/shifthandler.cpp b/src/virtualkeyboard/shifthandler.cpp
index 486dea75..c40fd78e 100644
--- a/src/virtualkeyboard/shifthandler.cpp
+++ b/src/virtualkeyboard/shifthandler.cpp
@@ -48,6 +48,7 @@ public:
autoCapitalizationEnabled(false),
toggleShiftEnabled(false),
shiftChanged(false),
+ resetWhenVisible(false),
manualShiftLanguageFilter(QSet<QLocale::Language>() << QLocale::Arabic << QLocale::Persian << QLocale::Hindi << QLocale::Korean),
manualCapsInputModeFilter(QSet<InputEngine::InputMode>() << InputEngine::Cangjie << InputEngine::Zhuyin),
noAutoUppercaseInputModeFilter(QSet<InputEngine::InputMode>() << InputEngine::FullwidthLatin << InputEngine::Pinyin << InputEngine::Cangjie << InputEngine::Zhuyin),
@@ -61,6 +62,7 @@ public:
bool autoCapitalizationEnabled;
bool toggleShiftEnabled;
bool shiftChanged;
+ bool resetWhenVisible;
QLocale locale;
QTime timer;
const QSet<QLocale::Language> manualShiftLanguageFilter;
@@ -100,6 +102,7 @@ ShiftHandler::ShiftHandler(InputContext *parent) :
connect(d->inputContext, SIGNAL(shiftChanged()), SLOT(shiftChanged()));
connect(d->inputContext, SIGNAL(capsLockChanged()), SLOT(shiftChanged()));
connect(d->inputContext, SIGNAL(localeChanged()), SLOT(localeChanged()));
+ connect(qGuiApp->inputMethod(), SIGNAL(visibleChanged()), SLOT(inputMethodVisibleChanged()));
d->locale = QLocale(d->inputContext->locale());
}
}
@@ -255,6 +258,11 @@ void ShiftHandler::autoCapitalize()
void ShiftHandler::restart()
{
+ Q_D(ShiftHandler);
+ if (!qGuiApp->inputMethod()->isVisible()) {
+ d->resetWhenVisible = true;
+ return;
+ }
reset();
}
@@ -271,6 +279,15 @@ void ShiftHandler::localeChanged()
restart();
}
+void ShiftHandler::inputMethodVisibleChanged()
+{
+ Q_D(ShiftHandler);
+ if (d->resetWhenVisible && qGuiApp->inputMethod()->isVisible()) {
+ d->resetWhenVisible = false;
+ reset();
+ }
+}
+
void ShiftHandler::setAutoCapitalizationEnabled(bool enabled)
{
Q_D(ShiftHandler);
diff --git a/src/virtualkeyboard/shifthandler.h b/src/virtualkeyboard/shifthandler.h
index 4e63a946..c28a9581 100644
--- a/src/virtualkeyboard/shifthandler.h
+++ b/src/virtualkeyboard/shifthandler.h
@@ -69,6 +69,7 @@ private slots:
void restart();
void localeChanged();
void shiftChanged();
+ void inputMethodVisibleChanged();
private:
void setAutoCapitalizationEnabled(bool enabled);
diff --git a/src/virtualkeyboard/styles/KeyPanel.qml b/src/virtualkeyboard/styles/KeyPanel.qml
index 68bb0850..4e12b9a8 100644
--- a/src/virtualkeyboard/styles/KeyPanel.qml
+++ b/src/virtualkeyboard/styles/KeyPanel.qml
@@ -52,8 +52,6 @@ Item {
\li \c control.enabled Set to true when the key is enabled.
\li \c control.pressed Set to true when the key is currently pressed.
\li \c control.uppercased Set to true when the key is uppercased.
- \li \c control.capsLock Set to true when caps lock is enabled.
- \note Deprecated since 1.2. Use \l {InputContext::capsLock} {InputContext.capsLock} instead.
\endlist
*/
property Item control
diff --git a/src/virtualkeyboard/styles/KeyboardStyle.qml b/src/virtualkeyboard/styles/KeyboardStyle.qml
index 547aa8be..f0095146 100644
--- a/src/virtualkeyboard/styles/KeyboardStyle.qml
+++ b/src/virtualkeyboard/styles/KeyboardStyle.qml
@@ -44,7 +44,7 @@ import QtQuick 2.0
*/
QtObject {
- /*! The current size of the keyboard. */
+ /*! The current height of the keyboard. */
property real keyboardHeight
/*! The design width of the keyboard. */
@@ -53,8 +53,8 @@ QtObject {
/*! The design height of the keyboard. */
property real keyboardDesignHeight
- /*! The keyboard style scale hint. This value is determined by the
- physical size and the design size of the keyboard. All pixel
+ /*! The keyboard style scale hint. This value is determined by dividing
+ \l keyboardHeight by \l keyboardDesignHeight. All pixel
dimensions must be proportional to this value.
*/
readonly property real scaleHint: keyboardHeight / keyboardDesignHeight
@@ -426,4 +426,102 @@ QtObject {
\l {Integration Method}{application-based integration method}.
*/
property Component selectionHandle: null
+
+ /*!
+ \since QtQuick.VirtualKeyboard.Styles 2.2
+
+ This property holds the delegate for the background of the full screen
+ input container.
+ */
+ property Component fullScreenInputContainerBackground: null
+
+ /*!
+ \since QtQuick.VirtualKeyboard.Styles 2.2
+
+ This property holds the delegate for the background of the full screen
+ input.
+ */
+ property Component fullScreenInputBackground: null
+
+ /*!
+ \since QtQuick.VirtualKeyboard.Styles 2.2
+
+ This property holds the margins around the full screen input field.
+
+ The default value is \c 0.
+ */
+ property real fullScreenInputMargins: 0
+
+ /*!
+ \since QtQuick.VirtualKeyboard.Styles 2.2
+
+ This property holds the padding around the full screen input content.
+
+ The default value is \c 0.
+ */
+ property real fullScreenInputPadding: 0
+
+ /*!
+ \since QtQuick.VirtualKeyboard.Styles 2.2
+
+ This property holds the delegate for the cursor in the full screen input
+ field.
+
+ The delegate should toggle the visibility of the cursor according to
+ the \c {parent.blinkStatus} property defined for the full screen input
+ field. For example:
+
+ \code
+ fullScreenInputCursor: Rectangle {
+ width: 1
+ color: "#000"
+ visible: parent.blinkStatus
+ }
+ \endcode
+ */
+ property Component fullScreenInputCursor: null
+
+ /*!
+ \since QtQuick.VirtualKeyboard.Styles 2.2
+
+ This property holds the \c font for the full screen input field.
+ */
+ property font fullScreenInputFont
+
+ /*!
+ \since QtQuick.VirtualKeyboard.Styles 2.2
+
+ This property holds the password mask character for the full screen
+ input field.
+ */
+ property string fullScreenInputPasswordCharacter: "\u2022"
+
+ /*!
+ \since QtQuick.VirtualKeyboard.Styles 2.2
+
+ This property holds the text color for the full screen input field.
+
+ The default color is black.
+ */
+ property color fullScreenInputColor: "#000"
+
+ /*!
+ \since QtQuick.VirtualKeyboard.Styles 2.2
+
+ This property holds the selection color for the full screen input
+ field.
+
+ The default color is semi-transparent black.
+ */
+ property color fullScreenInputSelectionColor: Qt.rgba(0, 0, 0, 0.15)
+
+ /*!
+ \since QtQuick.VirtualKeyboard.Styles 2.2
+
+ This property holds the selected text color for the full screen input
+ field.
+
+ The default color is set to \l full screenInputColor.
+ */
+ property color fullScreenInputSelectedTextColor: fullScreenInputColor
}
diff --git a/src/virtualkeyboard/styles/styles_plugin.cpp b/src/virtualkeyboard/styles/styles_plugin.cpp
index d6e17f5c..9a73d728 100644
--- a/src/virtualkeyboard/styles/styles_plugin.cpp
+++ b/src/virtualkeyboard/styles/styles_plugin.cpp
@@ -34,7 +34,7 @@
#include <QtCore/QLibraryInfo>
/*!
- \qmlmodule QtQuick.VirtualKeyboard.Styles 2.0
+ \qmlmodule QtQuick.VirtualKeyboard.Styles 2.2
\title Qt Quick Virtual Keyboard Styles QML Types
\ingroup qmlmodules
@@ -44,7 +44,7 @@
import statements in your .qml file:
\code
- import QtQuick.VirtualKeyboard.Styles 2.0
+ import QtQuick.VirtualKeyboard.Styles 2.2
\endcode
*/
@@ -58,6 +58,7 @@ void QtVirtualKeyboardStylesPlugin::registerTypes(const char *uri)
qmlRegisterType(QUrl(path + QLatin1String("KeyboardStyle.qml")), uri, 1, 3, "KeyboardStyle");
qmlRegisterType(QUrl(path + QLatin1String("KeyboardStyle.qml")), uri, 2, 0, "KeyboardStyle");
qmlRegisterType(QUrl(path + QLatin1String("KeyboardStyle.qml")), uri, 2, 1, "KeyboardStyle");
+ qmlRegisterType(QUrl(path + QLatin1String("KeyboardStyle.qml")), uri, 2, 2, "KeyboardStyle");
qmlRegisterType(QUrl(path + QLatin1String("KeyIcon.qml")), uri, 1, 0, "KeyIcon");
qmlRegisterType(QUrl(path + QLatin1String("KeyIcon.qml")), uri, 2, 0, "KeyIcon");
qmlRegisterType(QUrl(path + QLatin1String("KeyPanel.qml")), uri, 1, 0, "KeyPanel");
diff --git a/src/virtualkeyboard/tcinputmethod.cpp b/src/virtualkeyboard/tcinputmethod.cpp
index 8a7a415a..6628ef7c 100644
--- a/src/virtualkeyboard/tcinputmethod.cpp
+++ b/src/virtualkeyboard/tcinputmethod.cpp
@@ -238,7 +238,7 @@ public:
// Compose back the text after the finals replacement.
input.clear();
for (int i = 0; i < decomposed.length(); ++i) {
- if (decomposed[i] != 0)
+ if (!decomposed[i].isNull())
input.append(decomposed[i]);
}
} else {
diff --git a/src/virtualkeyboard/virtualkeyboard.pro b/src/virtualkeyboard/virtualkeyboard.pro
index 6866f4ff..4f3ca694 100644
--- a/src/virtualkeyboard/virtualkeyboard.pro
+++ b/src/virtualkeyboard/virtualkeyboard.pro
@@ -33,7 +33,8 @@ SOURCES += platforminputcontext.cpp \
settings.cpp \
virtualkeyboardsettings.cpp \
trace.cpp \
- desktopinputselectioncontrol.cpp
+ desktopinputselectioncontrol.cpp \
+ shadowinputcontext.cpp
HEADERS += platforminputcontext.h \
inputcontext.h \
@@ -53,7 +54,8 @@ HEADERS += platforminputcontext.h \
virtualkeyboardsettings.h \
plugin.h \
trace.h \
- desktopinputselectioncontrol.h
+ desktopinputselectioncontrol.h \
+ shadowinputcontext.h
RESOURCES += \
content/styles/default/default_style.qrc \
@@ -164,7 +166,8 @@ t9write: LAYOUT_FILES += \
contains(CONFIG, lang-ro.*) {
LAYOUT_FILES += \
content/layouts/ro_RO/main.qml \
- content/layouts/ro_RO/symbols.qml \
+ content/layouts/ro_RO/symbols.qml
+t9write: LAYOUT_FILES += \
content/layouts/ro_RO/handwriting.qml
}
contains(CONFIG, lang-ru.*) {
@@ -323,6 +326,10 @@ lipi-toolkit {
win32: LIBS += Advapi32.lib
else: LIBS += -ldl
record-trace-input: DEFINES += QT_VIRTUALKEYBOARD_LIPI_RECORD_TRACE_INPUT
+ ltk_projects.files = $$PWD/3rdparty/lipi-toolkit/projects
+ ltk_projects.path = $$[QT_INSTALL_DATA]/qtvirtualkeyboard/lipi_toolkit
+ INSTALLS += ltk_projects
+ !prefix_build: COPIES += ltk_projects
}
t9write {
diff --git a/src/virtualkeyboard/virtualkeyboardsettings.cpp b/src/virtualkeyboard/virtualkeyboardsettings.cpp
index 92908730..12f85cc2 100644
--- a/src/virtualkeyboard/virtualkeyboardsettings.cpp
+++ b/src/virtualkeyboard/virtualkeyboardsettings.cpp
@@ -166,6 +166,7 @@ VirtualKeyboardSettings::VirtualKeyboardSettings(QQmlEngine *engine) :
connect(settings, SIGNAL(wclAutoHideDelayChanged()), &d->wordCandidateListSettings, SIGNAL(autoHideDelayChanged()));
connect(settings, SIGNAL(wclAlwaysVisibleChanged()), &d->wordCandidateListSettings, SIGNAL(alwaysVisibleChanged()));
connect(settings, SIGNAL(wclAutoCommitWordChanged()), &d->wordCandidateListSettings, SIGNAL(autoCommitWordChanged()));
+ connect(settings, SIGNAL(fullScreenModeChanged()), SIGNAL(fullScreenModeChanged()));
}
/*!
@@ -278,6 +279,16 @@ WordCandidateListSettings *VirtualKeyboardSettings::wordCandidateList() const
return const_cast<WordCandidateListSettings *>(&d->wordCandidateListSettings);
}
+bool VirtualKeyboardSettings::fullScreenMode() const
+{
+ return Settings::instance()->fullScreenMode();
+}
+
+void VirtualKeyboardSettings::setFullScreenMode(bool fullScreenMode)
+{
+ return Settings::instance()->setFullScreenMode(fullScreenMode);
+}
+
void VirtualKeyboardSettings::resetStyle()
{
Q_D(VirtualKeyboardSettings);
@@ -358,6 +369,28 @@ void VirtualKeyboardSettings::resetStyle()
*/
/*!
+ \qmlproperty bool VirtualKeyboardSettings::fullScreenMode
+ \since QtQuick.VirtualKeyboard.Settings 2.2
+
+ This property enables the fullscreen mode for the virtual keyboard.
+
+ In fullscreen mode, the virtual keyboard replicates the contents of the
+ focused input field to the fullscreen input field located at the top of the
+ keyboard.
+
+ For example, to activate the fullscreen mode when the screen aspect ratio
+ is greater than 16:9:
+
+ \code
+ Binding {
+ target: VirtualKeyboardSettings
+ property: "fullScreenMode"
+ value: (Screen.width / Screen.height) > (16.0 / 9.0)
+ }
+ \endcode
+*/
+
+/*!
\since QtQuick.VirtualKeyboard.Settings 2.2
\qmlpropertygroup QtQuick.VirtualKeyboard::VirtualKeyboardSettings::wordCandidateList
\qmlproperty int QtQuick.VirtualKeyboard::VirtualKeyboardSettings::wordCandidateList.autoHideDelay
diff --git a/src/virtualkeyboard/virtualkeyboardsettings.h b/src/virtualkeyboard/virtualkeyboardsettings.h
index da43d10e..ca61db2a 100644
--- a/src/virtualkeyboard/virtualkeyboardsettings.h
+++ b/src/virtualkeyboard/virtualkeyboardsettings.h
@@ -48,6 +48,7 @@ class VirtualKeyboardSettings : public QObject
Q_PROPERTY(QStringList availableLocales READ availableLocales NOTIFY availableLocalesChanged)
Q_PROPERTY(QStringList activeLocales READ activeLocales WRITE setActiveLocales NOTIFY activeLocalesChanged)
Q_PROPERTY(WordCandidateListSettings *wordCandidateList READ wordCandidateList CONSTANT)
+ Q_PROPERTY(bool fullScreenMode READ fullScreenMode WRITE setFullScreenMode NOTIFY fullScreenModeChanged)
public:
static QObject *registerSettingsModule(QQmlEngine *engine, QJSEngine *jsEngine);
@@ -72,6 +73,9 @@ public:
WordCandidateListSettings *wordCandidateList() const;
+ bool fullScreenMode() const;
+ void setFullScreenMode(bool fullScreenMode);
+
signals:
void styleChanged();
void styleNameChanged();
@@ -79,6 +83,7 @@ signals:
void availableLocalesChanged();
void activeLocalesChanged();
void layoutPathChanged();
+ void fullScreenModeChanged();
private:
void resetStyle();
diff --git a/tests/auto/inputpanel/data/inputpanel/inputpanel.qml b/tests/auto/inputpanel/data/inputpanel/inputpanel.qml
index 58264edb..d1b3cae6 100644
--- a/tests/auto/inputpanel/data/inputpanel/inputpanel.qml
+++ b/tests/auto/inputpanel/data/inputpanel/inputpanel.qml
@@ -29,7 +29,7 @@
import QtTest 1.0
import QtQuick 2.0
-import QtQuick.VirtualKeyboard 2.1
+import QtQuick.VirtualKeyboard 2.2
import QtQuick.VirtualKeyboard.Settings 2.2
import "handwriting.js" as Handwriting
import "utils.js" as Utils
@@ -67,9 +67,14 @@ InputPanel {
naviationHighlight.widthAnimation.running ||
naviationHighlight.heightAnimation.running
readonly property var wordCandidateView: Utils.findChildByProperty(keyboard, "objectName", "wordCandidateView", null)
- readonly property var selectionControl: Utils.findChild(inputPanel, null, function(obj, param) { return obj.hasOwnProperty("handleIsMoving")})
+ readonly property var shadowInputControl: Utils.findChildByProperty(keyboard, "objectName", "shadowInputControl", null)
+ readonly property var shadowInput: Utils.findChildByProperty(keyboard, "objectName", "shadowInput", null)
+ readonly property var selectionControl: Utils.findChildByProperty(inputPanel, "objectName", "selectionControl", null)
readonly property var anchorHandle: selectionControl.children[0]
readonly property var cursorHandle: selectionControl.children[1]
+ readonly property var fullScreenModeSelectionControl: Utils.findChildByProperty(inputPanel, "objectName", "fullScreenModeSelectionControl", null)
+ readonly property var fullScreenModeAnchorHandle: fullScreenModeSelectionControl.children[0]
+ readonly property var fullScreenModeCursorHandle: fullScreenModeSelectionControl.children[1]
readonly property bool wordCandidateListVisibleHint: InputContext.inputEngine.wordCandidateListVisibleHint
readonly property bool keyboardLayoutsAvailable: keyboard.availableLocaleIndices.length > 0 && keyboard.availableLocaleIndices.indexOf(-1) === -1
property alias keyboardLayoutsAvailableSpy: keyboardLayoutsAvailableSpy
@@ -85,6 +90,7 @@ InputPanel {
property alias wordCandidateListChangedSpy: wordCandidateListChangedSpy
property alias wordCandidateListVisibleSpy: wordCandidateListVisibleSpy
property alias shiftStateSpy: shiftStateSpy
+ property alias shadowInputControlVisibleSpy: shadowInputControlVisibleSpy
signal inputMethodResult(var text)
@@ -176,6 +182,12 @@ InputPanel {
signalName: "onShiftChanged"
}
+ SignalSpy {
+ id: shadowInputControlVisibleSpy
+ target: shadowInputControl
+ signalName: "onVisibleChanged"
+ }
+
function findChildByProperty(parent, propertyName, propertyValue, compareCb) {
var obj = null
if (parent === null)
@@ -226,6 +238,10 @@ InputPanel {
VirtualKeyboardSettings.wordCandidateList.autoCommitWord = wclAutoCommitWord
}
+ function setFullScreenMode(fullScreenMode) {
+ VirtualKeyboardSettings.fullScreenMode = fullScreenMode
+ }
+
function mapInputMode(inputModeName) {
if (inputModeName === "Latin")
return InputEngine.Latin
diff --git a/tests/auto/inputpanel/data/tst_inputpanel.qml b/tests/auto/inputpanel/data/tst_inputpanel.qml
index 756200d4..7d83d31d 100644
--- a/tests/auto/inputpanel/data/tst_inputpanel.qml
+++ b/tests/auto/inputpanel/data/tst_inputpanel.qml
@@ -81,6 +81,7 @@ Rectangle {
inputPanel.setWclAutoHideDelay(data !== undefined && data.hasOwnProperty("wclAutoHideDelay") ? data.wclAutoHideDelay : 5000)
inputPanel.setWclAlwaysVisible(data !== undefined && data.hasOwnProperty("wclAlwaysVisible") && data.wclAlwaysVisible)
inputPanel.setWclAutoCommitWord(data !== undefined && data.hasOwnProperty("wclAutoCommitWord") && data.wclAutoCommitWord)
+ inputPanel.setFullScreenMode(data !== undefined && data.hasOwnProperty("fullScreenMode") && data.fullScreenMode)
container.forceActiveFocus()
if (data !== undefined && data.hasOwnProperty("initText")) {
textInput.text = data.initText
@@ -183,7 +184,8 @@ Rectangle {
property var activeLocales: VirtualKeyboardSettings.activeLocales; \
property var wclAutoHideDelay: VirtualKeyboardSettings.wordCandidateList.autoHideDelay; \
property var wclAlwaysVisible: VirtualKeyboardSettings.wordCandidateList.alwaysVisible; \
- property var wclAutoCommitWord: VirtualKeyboardSettings.wordCandidateList.autoCommitWord }" },
+ property var wclAutoCommitWord: VirtualKeyboardSettings.wordCandidateList.autoCommitWord; \
+ property var fullScreenMode: VirtualKeyboardSettings.fullScreenMode; }" },
]
}
@@ -1648,5 +1650,171 @@ Rectangle {
else
verify(inputPanel.wordCandidateView.model.count >= 1)
}
+
+ function test_fullScreenModeActivation() {
+ prepareTest()
+
+ textInput.text = "Hello"
+
+ inputPanel.shadowInputControlVisibleSpy.clear()
+ inputPanel.setFullScreenMode(true)
+ waitForRendering(inputPanel)
+ inputPanel.shadowInputControlVisibleSpy.wait()
+
+ compare(inputPanel.shadowInput.text, textInput.text)
+
+ inputPanel.shadowInputControlVisibleSpy.clear()
+ inputPanel.setFullScreenMode(false)
+ waitForRendering(inputPanel)
+ inputPanel.shadowInputControlVisibleSpy.wait()
+ }
+
+ function test_fullScreenModeInput_data() {
+ return [
+ { fullScreenMode: true, initInputMethodHints: Qt.ImhNoPredictiveText, initText: "Hello ", inputSequence: "world", outputText: "Hello world" },
+ { fullScreenMode: true, initInputMethodHints: Qt.ImhNone, initText: "Hello ", inputSequence: "world", outputText: "Hello world" },
+ ]
+ }
+
+ function test_fullScreenModeInput(data) {
+ prepareTest(data)
+
+ for (var inputIndex in data.inputSequence) {
+ verify(inputPanel.virtualKeyClick(data.inputSequence[inputIndex]))
+ }
+ compare(inputPanel.shadowInput.text, textInput.text)
+ compare(inputPanel.shadowInput.cursorPosition, textInput.cursorPosition)
+ compare(inputPanel.shadowInput.preeditText, textInput.preeditText)
+
+ Qt.inputMethod.commit()
+ waitForRendering(inputPanel)
+ compare(textInput.text, data.outputText)
+ compare(inputPanel.shadowInput.text, textInput.text)
+ compare(inputPanel.shadowInput.cursorPosition, textInput.cursorPosition)
+ compare(inputPanel.shadowInput.preeditText, textInput.preeditText)
+ }
+
+ function test_fullScreenModeTextSelection_data() {
+ return [
+ { fullScreenMode: true, initText: "Hello world", select: function(){ textInput.selectAll() } },
+ { fullScreenMode: true, initText: "Hello world", initCursorPosition: 0, select: function(){ textInput.moveCursorSelection("Hello".length) } },
+ { fullScreenMode: true, initText: "Hello world", initCursorPosition: "Hello".length, select: function(){ textInput.moveCursorSelection(0) } }
+ ]
+ }
+
+ function test_fullScreenModeTextSelection(data) {
+ prepareTest(data)
+
+ data.select()
+ waitForRendering(textInput)
+ compare(inputPanel.shadowInput.text, textInput.text)
+ compare(inputPanel.shadowInput.cursorPosition, textInput.cursorPosition)
+ compare(inputPanel.shadowInput.selectedText, textInput.selectedText)
+ compare(inputPanel.shadowInput.selectionStart, textInput.selectionStart)
+ compare(inputPanel.shadowInput.selectionEnd, textInput.selectionEnd)
+ }
+
+ function test_fullScreenModeWordReselection_data() {
+ return [
+ { initText: "hello", clickPositions: [5], expectedPreeditText: "", expectedCursorPosition: 5, expectedText: "hello" },
+ { initText: "hello", clickPositions: [4], expectedPreeditText: "hello", expectedCursorPosition: 0, expectedText: "" },
+ { initText: "hello", clickPositions: [1], expectedPreeditText: "hello", expectedCursorPosition: 0, expectedText: "" },
+ { initText: "hello", clickPositions: [0], expectedPreeditText: "", expectedCursorPosition: 0, expectedText: "hello" },
+ { initText: "hello", clickPositions: [4, 3], expectedPreeditText: "hel", expectedCursorPosition: 0, expectedText: "lo" },
+ // 5
+ { initText: "hello", clickPositions: [4, 2], expectedPreeditText: "he", expectedCursorPosition: 0, expectedText: "llo" },
+ { initText: "hello", clickPositions: [4, 1], expectedPreeditText: "h", expectedCursorPosition: 0, expectedText: "ello" },
+ { initText: "hello", clickPositions: [4, 0], expectedPreeditText: "", expectedCursorPosition: 0, expectedText: "hello" },
+ { initText: "hello", clickPositions: [1, 2], expectedPreeditText: "he", expectedCursorPosition: 0, expectedText: "llo" },
+ { initText: "hello", clickPositions: [1, 2, 2], expectedPreeditText: "", expectedCursorPosition: 2, expectedText: "hello" },
+ // 10
+ { initText: "hello", clickPositions: [1, 5], expectedPreeditText: "", expectedCursorPosition: 5, expectedText: "hello" },
+ { initText: "hel-lo", clickPositions: [3], expectedPreeditText: "hel-lo", expectedCursorPosition: 0, expectedText: "" },
+ { initText: "hel-lo", clickPositions: [4], expectedPreeditText: "hel-lo", expectedCursorPosition: 0, expectedText: "" },
+ { initText: "hel-lo", clickPositions: [4, 4], expectedPreeditText: "", expectedCursorPosition: 4, expectedText: "hel-lo" },
+ { initText: "hel-lo", clickPositions: [5], expectedPreeditText: "hel-lo", expectedCursorPosition: 0, expectedText: "" },
+ // 15
+ { initText: "hel-lo", clickPositions: [5], initInputMethodHints: Qt.ImhNoPredictiveText, expectedPreeditText: "", expectedCursorPosition: 5, expectedText: "hel-lo" },
+ { initText: "isn'", clickPositions: [2], expectedPreeditText: "isn", expectedCursorPosition: 0, expectedText: "'" },
+ { initText: "isn't", clickPositions: [2], expectedPreeditText: "isn't", expectedCursorPosition: 0, expectedText: "" },
+ { initText: "-hello", clickPositions: [2], expectedPreeditText: "hello", expectedCursorPosition: 1, expectedText: "-" },
+ { initText: "aa http://www.example.com bb", clickPositions: [4], expectedPreeditText: "http", expectedCursorPosition: 3, expectedText: "aa ://www.example.com bb" },
+ // 20
+ { initText: "aa http://www.example.com bb", initInputMethodHints: Qt.ImhUrlCharactersOnly, clickPositions: [4], expectedPreeditText: "http://www.example.com", expectedCursorPosition: 3, expectedText: "aa bb" },
+ { initText: "aa username@example.com bb", clickPositions: [4], expectedPreeditText: "username", expectedCursorPosition: 3, expectedText: "aa @example.com bb" },
+ { initText: "aa username@example.com bb", initInputMethodHints: Qt.ImhEmailCharactersOnly, clickPositions: [4], expectedPreeditText: "username@example.com", expectedCursorPosition: 3, expectedText: "aa bb" },
+ ]
+ }
+
+ function test_fullScreenModeWordReselection(data) {
+ prepareTest(data)
+ inputPanel.setFullScreenMode(true)
+
+ var cursorRects = []
+ for (var i = 0; i < data.clickPositions.length; i++) {
+ var clickPos = inputPanel.shadowInput.positionToRectangle(data.clickPositions[i])
+ // Could this be a bug in TextInput; padding not accounted in positionToRectangle()?
+ clickPos.x += inputPanel.shadowInput.leftPadding
+ cursorRects.push(clickPos)
+ }
+
+ for (i = 0; i < data.clickPositions.length; i++) {
+ var cursorRect = cursorRects[i]
+ mousePress(inputPanel.shadowInput, cursorRect.x, cursorRect.y + cursorRect.height / 2, Qt.LeftButton, Qt.NoModifier, 20)
+ mouseRelease(inputPanel.shadowInput, cursorRect.x, cursorRect.y + cursorRect.height / 2, Qt.LeftButton, Qt.NoModifier, 20)
+ waitForRendering(inputPanel.shadowInput)
+ }
+
+ if (!inputPanel.wordCandidateListVisibleHint && inputPanel.preeditText !== data.expectedPreeditText)
+ expectFail("", "Prediction/spell correction not enabled")
+ compare(inputPanel.preeditText, data.expectedPreeditText)
+ compare(inputPanel.shadowInput.preeditText, data.expectedPreeditText)
+
+ if (!inputPanel.wordCandidateListVisibleHint && inputPanel.cursorPosition !== data.expectedCursorPosition)
+ expectFail("", "Prediction/spell correction not enabled")
+ compare(inputPanel.cursorPosition, data.expectedCursorPosition)
+ compare(inputPanel.shadowInput.cursorPosition, data.expectedCursorPosition)
+
+ if (!inputPanel.wordCandidateListVisibleHint && textInput.text !== data.expectedText)
+ expectFail("", "Prediction/spell correction not enabled")
+ compare(textInput.text, data.expectedText)
+ compare(inputPanel.shadowInput.text, data.expectedText)
+ }
+
+ function test_fullScreenModeSelectionHandles_data() {
+ return [
+ { fullScreenMode: true, initText: "Hello cruel world", selectionStart: 2, selectionEnd: 9, expectHandlesToBeVisible: true },
+ { fullScreenMode: true, initText: "Hello cruel world", selectionStart: 9, selectionEnd: 9, expectHandlesToBeVisible: false },
+ { fullScreenMode: true, initText: "Hello cruel world", selectionStart: 2, selectionEnd: 9, expectHandlesToBeVisible: true },
+ { fullScreenMode: true, initText: "Hello cruel world", selectionStart: 0, selectionEnd: 17, expectHandlesToBeVisible: true },
+ ]
+ }
+
+ function test_fullScreenModeSelectionHandles(data) {
+ prepareTest(data)
+ compare(inputPanel.cursorHandle.visible, false)
+ compare(inputPanel.anchorHandle.visible, false)
+ compare(inputPanel.fullScreenModeCursorHandle.visible, data.expectHandlesToBeVisible)
+ compare(inputPanel.fullScreenModeAnchorHandle.visible, data.expectHandlesToBeVisible)
+ if (data.expectHandlesToBeVisible) {
+ waitForRendering(inputPanel.fullScreenModeCursorHandle)
+ var cursorHandlePointsTo = Qt.point(inputPanel.fullScreenModeCursorHandle.x + inputPanel.fullScreenModeCursorHandle.width/2, inputPanel.fullScreenModeCursorHandle.y)
+ var anchorHandlePointsTo = Qt.point(inputPanel.fullScreenModeAnchorHandle.x + inputPanel.fullScreenModeAnchorHandle.width/2, inputPanel.fullScreenModeAnchorHandle.y)
+ var anchorRect = inputPanel.shadowInput.positionToRectangle(data.selectionStart)
+ var cursorRect = inputPanel.shadowInput.positionToRectangle(data.selectionEnd)
+ anchorRect = container.mapFromItem(inputPanel.shadowInput, anchorRect.x, anchorRect.y, anchorRect.width, anchorRect.height)
+ cursorRect = container.mapFromItem(inputPanel.shadowInput, cursorRect.x, cursorRect.y, cursorRect.width, cursorRect.height)
+ // Could this be a bug in TextInput; padding not accounted in positionToRectangle()?
+ anchorRect.x += inputPanel.shadowInput.leftPadding
+ cursorRect.x += inputPanel.shadowInput.leftPadding
+
+ compare(cursorHandlePointsTo.x, cursorRect.x)
+ compare(cursorHandlePointsTo.y, cursorRect.y + cursorRect.height)
+
+ compare(anchorHandlePointsTo.x, anchorRect.x)
+ compare(anchorHandlePointsTo.y, anchorRect.y + anchorRect.height)
+ }
+ }
+
}
}