on xenial help sign in
Add global InputMethodManager to handle inputMethod across screens

This adds a global InputMethodManager to handle inputMethod across screens. This (c++ side) was made with to be comparable with the upcoming proper multiscreen support. This is a bit *hacky* for now, and should be cleaned up once proper multiscreen has landed. This is still less hacky then the existing hardcoded multiscreen/secondscreen things currently in unity8 so ¯\_(ツ)_/¯ This fixes: https://github.com/ubports/ubuntu-touch/issues/1096

commit1b30ec805d8b96d5e3a61852203d848cade15c11 authorMarius Gripsgard <marius@ubports.com> dateThu 19 Dec 2019, 01:59 (7 years ago) parenta6aac8d
8 files changed+133−3
plugins/WindowManager/CMakeLists.txt+1 plugins/WindowManager/InputMethodManager.cpp+56 plugins/WindowManager/InputMethodManager.h+55 plugins/WindowManager/TopLevelWindowModel.cpp+3 plugins/WindowManager/WindowManagerPlugin.cpp+9 qml/Components/InputMethod.qml+2−1 qml/OrientedShell.qml+7−1 qml/Shell.qml−1
plugins/WindowManager/CMakeLists.txt+1
@@ -4,6 +4,7 @@ set(WINDOWMANAGER_SRC
44 Window.cpp
55 WindowManagerPlugin.cpp
66 WindowMargins.cpp
7+ InputMethodManager.cpp
78 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationInfoInterface.h
89 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/Mir.h
910 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirSurfaceInterface.h
plugins/WindowManager/InputMethodManager.cppnew file+56
@@ -0,0 +1,56 @@
1+/*
2+ * Copyright (C) 2019 UBports Foundation.
3+ * Author(s) Marius Gripsgard <marius@ubports.com>
4+ *
5+ * This program is free software: you can redistribute it and/or modify it under
6+ * the terms of the GNU Lesser General Public License version 3, as published by
7+ * the Free Software Foundation.
8+ *
9+ * This program is distributed in the hope that it will be useful, but WITHOUT
10+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
11+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12+ * Lesser General Public License for more details.
13+ *
14+ * You should have received a copy of the GNU Lesser General Public License
15+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
16+ */
17+
18+#include "InputMethodManager.h"
19+#include <QDebug>
20+
21+#include <unity/shell/application/MirSurfaceInterface.h>
22+
23+// local
24+#include "Window.h"
25+
26+Q_LOGGING_CATEGORY(INPUTMETHODMANAGER, "InputMethodManager", QtInfoMsg)
27+#define DEBUG_MSG qCDebug(INPUTMETHODMANAGER).nospace().noquote() << __func__
28+
29+namespace unityapi = unity::shell::application;
30+
31+InputMethodManager *InputMethodManager::instance()
32+{
33+ static InputMethodManager* inputMethod(new InputMethodManager());
34+ return inputMethod;
35+}
36+
37+InputMethodManager::InputMethodManager()
38+{
39+}
40+
41+void InputMethodManager::setWindow(Window* window)
42+{
43+ if (window == m_inputMethodWindow) {
44+ return;
45+ }
46+
47+ DEBUG_MSG << "(" << window << ")";
48+
49+ m_inputMethodWindow = window;
50+ Q_EMIT surfaceChanged(surface());
51+}
52+
53+unityapi::MirSurfaceInterface* InputMethodManager::surface() const
54+{
55+ return m_inputMethodWindow ? m_inputMethodWindow->surface() : nullptr;
56+}
plugins/WindowManager/InputMethodManager.hnew file+55
@@ -0,0 +1,55 @@
1+/*
2+ * Copyright (C) 2019 UBports Foundation.
3+ * Author(s) Marius Gripsgard <marius@ubports.com>
4+ *
5+ * This program is free software: you can redistribute it and/or modify it under
6+ * the terms of the GNU Lesser General Public License version 3, as published by
7+ * the Free Software Foundation.
8+ *
9+ * This program is distributed in the hope that it will be useful, but WITHOUT
10+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
11+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12+ * Lesser General Public License for more details.
13+ *
14+ * You should have received a copy of the GNU Lesser General Public License
15+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
16+ */
17+
18+#pragma once
19+
20+#include <QLoggingCategory>
21+#include <QObject>
22+
23+#include "WindowManagerGlobal.h"
24+
25+Q_DECLARE_LOGGING_CATEGORY(INPUTMETHODMANAGER)
26+
27+class Window;
28+
29+namespace unity {
30+ namespace shell {
31+ namespace application {
32+ class MirSurfaceInterface;
33+ }
34+ }
35+}
36+
37+class WINDOWMANAGERQML_EXPORT InputMethodManager : public QObject
38+{
39+ Q_OBJECT
40+ Q_PROPERTY(unity::shell::application::MirSurfaceInterface* surface READ surface NOTIFY surfaceChanged)
41+
42+public:
43+ InputMethodManager();
44+ static InputMethodManager* instance();
45+
46+ void setWindow(Window* window);
47+
48+Q_SIGNALS:
49+ void surfaceChanged(unity::shell::application::MirSurfaceInterface* inputMethodSurface);
50+
51+private:
52+ unity::shell::application::MirSurfaceInterface* surface() const;
53+
54+ Window* m_inputMethodWindow{nullptr};
55+};
plugins/WindowManager/TopLevelWindowModel.cpp+3
@@ -30,6 +30,7 @@
3030
3131// local
3232#include "Window.h"
33+#include "InputMethodManager.h"
3334
3435Q_LOGGING_CATEGORY(TOPLEVELWINDOWMODEL, "toplevelwindowmodel", QtInfoMsg)
3536
@@ -472,6 +473,7 @@ void TopLevelWindowModel::setInputMethodWindow(Window *window)
472473 }
473474 m_inputMethodWindow = window;
474475 Q_EMIT inputMethodSurfaceChanged(m_inputMethodWindow->surface());
476+ InputMethodManager::instance()->setWindow(window);
475477}
476478
477479void TopLevelWindowModel::removeInputMethodWindow()
@@ -480,6 +482,7 @@ void TopLevelWindowModel::removeInputMethodWindow()
480482 delete m_inputMethodWindow;
481483 m_inputMethodWindow = nullptr;
482484 Q_EMIT inputMethodSurfaceChanged(nullptr);
485+ InputMethodManager::instance()->setWindow(nullptr);
483486 }
484487}
485488
plugins/WindowManager/WindowManagerPlugin.cpp+9
@@ -20,14 +20,23 @@
2020#include "TopLevelWindowModel.h"
2121#include "Window.h"
2222#include "WindowMargins.h"
23+#include "InputMethodManager.h"
2324
2425#include <QtQml>
2526
27+QObject *inputMethodManager(QQmlEngine *engine, QJSEngine *scriptEngine)
28+{
29+ Q_UNUSED(engine)
30+ Q_UNUSED(scriptEngine)
31+ return InputMethodManager::instance();
32+}
33+
2634void WindowManagerPlugin::registerTypes(const char *uri)
2735{
2836 qmlRegisterType<AvailableDesktopArea>(uri, 1, 0, "AvailableDesktopArea");
2937 qmlRegisterType<TopLevelWindowModel>(uri, 1, 0, "TopLevelWindowModel");
3038 qmlRegisterType<WindowMargins>(uri, 1, 0, "WindowMargins");
39+ qmlRegisterSingletonType<InputMethodManager>(uri, 1, 0, "InputMethodManager", inputMethodManager);
3140
3241 qRegisterMetaType<Window*>("Window*");
3342
qml/Components/InputMethod.qml+2−1
@@ -17,13 +17,14 @@
1717import QtQuick 2.4
1818import Unity.Application 0.1
1919import Ubuntu.Gestures 0.1
20+import WindowManager 1.0
2021
2122Item {
2223 id: root
2324
2425 readonly property rect visibleRect: surfaceItem.surface && visible ? surfaceItem.surface.inputBounds : Qt.rect(0, 0, 0, 0)
2526
26− property var surface
27+ property var surface: root.enabled ? InputMethodManager.surface : null;
2728
2829 MirSurfaceItem {
2930 id: surfaceItem
qml/OrientedShell.qml+7−1
@@ -275,7 +275,13 @@ Item {
275275 hasMouse: pointerInputDevices > 0
276276 hasKeyboard: keyboardsModel.count > 0
277277 hasTouchscreen: touchScreensModel.count > 0
278− oskEnabled: unity8Settings.alwaysShowOsk || !hasKeyboard || forceOSKEnabled
278+
279+ // Since we dont have proper multiscreen support yet
280+ // hardcode screen count to only show osk on this screen
281+ // when it's the only one connected.
282+ // FIXME once multiscreen has landed
283+ oskEnabled: (!hasKeyboard && screens.count === 1) ||
284+ unity8Settings.alwaysShowOsk || forceOSKEnabled
279285
280286 usageScenario: {
281287 if (unity8Settings.usageMode === "Windowed") {
qml/Shell.qml−1
@@ -373,7 +373,6 @@ StyledItem {
373373 InputMethod {
374374 id: inputMethod
375375 objectName: "inputMethod"
376− surface: topLevelSurfaceList.inputMethodSurface
377376 anchors {
378377 fill: parent
379378 topMargin: panel.panelHeight