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:
parent
826b9742e9
commit
5c39795b88
3 changed files with 85 additions and 54 deletions
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue