Load the keyboard on-demand

Summary: No need to load the keyboard view as soon as wayland starts. It's not a simple UI and it often will be unused.

Test Plan: played with the keyboard, still worked

Reviewers: #kwin, davidedmundson

Reviewed By: #kwin, davidedmundson

Subscribers: davidedmundson, graesslin, kwin

Tags: #kwin

Differential Revision: https://phabricator.kde.org/D22430
This commit is contained in:
Aleix Pol 2019-08-01 17:20:20 +02:00
parent 826b9742e9
commit 5c39795b88
3 changed files with 85 additions and 54 deletions

View file

@ -18,47 +18,66 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
import QtQuick 2.0
import QtQuick.Window 2.0
import QtQuick.Controls 2.3
import QtQuick.VirtualKeyboard 2.1
import org.kde.kirigami 2.5 as Kirigami
Item {
Window {
id: window
property real adjustment: 0
property real adjustmentFactor: 0.0
InputPanel {
id: inputPanel
objectName: "inputPanel"
width: parent.width - parent.width * parent.adjustmentFactor
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
}
//NOTE: ToolButton for some reasons breaks the virtual keyboard loading on Plasma Mobile
Button {
id: resizeButton
visible: !Kirigami.Settings.isMobile //don't show on handheld devices
flat: true
display: AbstractButton.IconOnly
icon.name: "transform-scale"
icon.color: "white"
down: mouseArea.pressed
visible: false
anchors {
right: inputPanel.right
top: inputPanel.top
}
Loader {
anchors.fill: parent
MouseArea {
id: mouseArea
property real startPoint: 0
anchors.fill: parent
onPressed: {
startPoint = mouse.x;
}
onPositionChanged: {
window.adjustment -= (mouse.x - startPoint);
window.adjustmentFactor = Math.min(Math.max(window.adjustment / window.width, 0.0), 0.66);
startPoint = mouse.x;
sourceComponent: window.visible ? theKeyboard : null
Component {
id: theKeyboard
Item {
InputPanel {
id: inputPanel
readonly property real sideMargin: window.width * window.adjustmentFactor/2
anchors {
left: parent.left
right: parent.right
bottom: parent.bottom
leftMargin: sideMargin
rightMargin: sideMargin
}
}
//NOTE: ToolButton for some reasons breaks the virtual keyboard loading on Plasma Mobile
Button {
id: resizeButton
visible: !Kirigami.Settings.isMobile //don't show on handheld devices
flat: true
display: AbstractButton.IconOnly
icon.name: "transform-scale"
icon.color: "white"
down: mouseArea.pressed
anchors {
right: inputPanel.right
top: inputPanel.top
}
MouseArea {
id: mouseArea
property real startPoint: 0
anchors.fill: parent
onPressed: {
startPoint = mouse.x;
}
onPositionChanged: {
window.adjustment -= (mouse.x - startPoint);
window.adjustmentFactor = Math.min(Math.max(window.adjustment / window.width, 0.0), 0.66);
startPoint = mouse.x;
}
}
}
}
}
}

View file

@ -44,8 +44,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <QQmlContext>
#include <QQmlEngine>
#include <QQuickItem>
#include <QQuickView>
#include <QQuickWindow>
#include <QQmlApplicationEngine>
#include <QTimer>
// xkbcommon
#include <xkbcommon/xkbcommon.h>
@ -74,17 +74,20 @@ VirtualKeyboard::~VirtualKeyboard() = default;
void VirtualKeyboard::init()
{
// TODO: need a shared Qml engine
qCDebug(KWIN_VIRTUALKEYBOARD) << "Initializing window";
m_inputWindow.reset(new QQuickView(nullptr));
m_inputWindow->setFlags(Qt::FramelessWindowHint);
m_inputWindow->setGeometry(screens()->geometry(screens()->current()));
m_inputWindow->setResizeMode(QQuickView::SizeRootObjectToView);
m_inputWindow->setSource(QUrl::fromLocalFile(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral(KWIN_NAME "/virtualkeyboard/main.qml"))));
if (m_inputWindow->status() != QQuickView::Status::Ready) {
qCWarning(KWIN_VIRTUALKEYBOARD) << "window not ready yet";
const QUrl source = QUrl::fromLocalFile(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral(KWIN_NAME "/virtualkeyboard/main.qml")));
qCDebug(KWIN_VIRTUALKEYBOARD) << "Initializing window" << source;
QQmlApplicationEngine* engine = new QQmlApplicationEngine(this);
connect(engine, &QQmlEngine::warnings, this, [] (const QList<QQmlError> &warnings) { qCWarning(KWIN_VIRTUALKEYBOARD ) << warnings; });
engine->load(source);
if (engine->rootObjects().isEmpty()) {
qCWarning(KWIN_VIRTUALKEYBOARD) << "could not load the virtual keyboard";
m_inputWindow.reset();
return;
}
m_inputWindow.reset(qobject_cast<QQuickWindow*>(engine->rootObjects().constFirst()));
m_inputWindow->setFlags(Qt::FramelessWindowHint);
m_inputWindow->setProperty("__kwin_input_method", true);
if (waylandServer()) {
@ -137,18 +140,27 @@ void VirtualKeyboard::init()
m_waylandShowConnection = connect(t, &TextInputInterface::requestShowInputPanel, this, &VirtualKeyboard::show);
m_waylandHideConnection = connect(t, &TextInputInterface::requestHideInputPanel, this, &VirtualKeyboard::hide);
m_waylandSurroundingTextConnection = connect(t, &TextInputInterface::surroundingTextChanged, this,
[] {
[this] {
if (m_enabled) {
m_inputWindow->show();
}
qApp->inputMethod()->update(Qt::ImSurroundingText | Qt::ImCursorPosition | Qt::ImAnchorPosition);
}
);
m_waylandHintsConnection = connect(t, &TextInputInterface::contentTypeChanged, this,
[] {
[this] {
if (m_enabled) {
m_inputWindow->show();
}
qApp->inputMethod()->update(Qt::ImHints);
}
);
m_waylandResetConnection = connect(t, &TextInputInterface::requestReset, qApp->inputMethod(), &QInputMethod::reset);
m_waylandEnabledConnection = connect(t, &TextInputInterface::enabledChanged, this,
[] {
[this] {
if (m_enabled) {
m_inputWindow->show();
}
qApp->inputMethod()->update(Qt::ImQueryAll);
}
);
@ -185,19 +197,19 @@ void VirtualKeyboard::init()
}
);
m_inputWindow->setColor(Qt::transparent);
m_inputWindow->setMask(m_inputWindow->rootObject()->childrenRect().toRect());
connect(m_inputWindow->rootObject(), &QQuickItem::childrenRectChanged, m_inputWindow.data(),
m_inputWindow->setMask(m_inputWindow->contentItem()->childrenRect().toRect());
connect(m_inputWindow->contentItem(), &QQuickItem::childrenRectChanged, m_inputWindow.data(),
[this] {
if (!m_inputWindow) {
return;
}
m_inputWindow->setMask(m_inputWindow->rootObject()->childrenRect().toRect());
m_inputWindow->setMask(m_inputWindow->contentItem()->childrenRect().toRect());
}
);
connect(qApp->inputMethod(), &QInputMethod::visibleChanged, this, &VirtualKeyboard::updateInputPanelState);
connect(m_inputWindow->rootObject(), &QQuickItem::childrenRectChanged, this, &VirtualKeyboard::updateInputPanelState);
connect(m_inputWindow->contentItem(), &QQuickItem::childrenRectChanged, this, &VirtualKeyboard::updateInputPanelState);
}
void VirtualKeyboard::setEnabled(bool enabled)
@ -256,11 +268,11 @@ void VirtualKeyboard::updateInputPanelState()
m_inputWindow->setVisible(qApp->inputMethod()->isVisible());
if (qApp->inputMethod()->isVisible()) {
m_inputWindow->setMask(m_inputWindow->rootObject()->childrenRect().toRect());
m_inputWindow->setMask(m_inputWindow->contentItem()->childrenRect().toRect());
}
if (m_inputWindow->isVisible() && m_trackedClient && m_inputWindow->rootObject()) {
const QRect inputPanelGeom = m_inputWindow->rootObject()->childrenRect().toRect().translated(m_inputWindow->geometry().topLeft());
if (m_inputWindow->isVisible() && m_trackedClient && m_inputWindow) {
const QRect inputPanelGeom = m_inputWindow->contentItem()->childrenRect().toRect().translated(m_inputWindow->geometry().topLeft());
m_trackedClient->setVirtualKeyboardGeometry(inputPanelGeom);
@ -286,7 +298,7 @@ void VirtualKeyboard::show()
void VirtualKeyboard::hide()
{
if (m_inputWindow.isNull()) {
if (!m_inputWindow) {
return;
}
qApp->inputMethod()->hide();

View file

@ -27,7 +27,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <abstract_client.h>
class QQuickView;
class QQuickWindow;
class QTimer;
class QWindow;
class KStatusNotifierItem;
@ -60,7 +60,7 @@ private:
bool m_enabled = false;
KStatusNotifierItem *m_sni = nullptr;
QScopedPointer<QQuickView> m_inputWindow;
QScopedPointer<QQuickWindow> m_inputWindow;
QPointer<AbstractClient> m_trackedClient;
// If a surface loses focus immediately after being resized by the keyboard, don't react to it to avoid resize loops
QTimer *m_floodTimer;