Changeset View
Changeset View
Standalone View
Standalone View
virtualkeyboard.cpp
Show All 23 Lines | |||||
24 | #include "utils.h" | 24 | #include "utils.h" | ||
25 | #include "screens.h" | 25 | #include "screens.h" | ||
26 | #include "wayland_server.h" | 26 | #include "wayland_server.h" | ||
27 | #include "workspace.h" | 27 | #include "workspace.h" | ||
28 | #include "xkb.h" | 28 | #include "xkb.h" | ||
29 | #include "xdgshellclient.h" | 29 | #include "xdgshellclient.h" | ||
30 | #include "screenlockerwatcher.h" | 30 | #include "screenlockerwatcher.h" | ||
31 | 31 | | |||
32 | #include <KWayland/Server/compositor_interface.h> | ||||
32 | #include <KWayland/Server/display.h> | 33 | #include <KWayland/Server/display.h> | ||
34 | #include <KWayland/Server/inputmethod_interface.h> | ||||
33 | #include <KWayland/Server/seat_interface.h> | 35 | #include <KWayland/Server/seat_interface.h> | ||
34 | #include <KWayland/Server/textinput_interface.h> | 36 | #include <KWayland/Server/textinput_interface.h> | ||
35 | #include <KWayland/Server/surface_interface.h> | 37 | #include <KWayland/Server/surface_interface.h> | ||
36 | 38 | | |||
37 | #include <KStatusNotifierItem> | 39 | #include <KStatusNotifierItem> | ||
38 | #include <KLocalizedString> | 40 | #include <KLocalizedString> | ||
39 | 41 | | |||
40 | #include <QDBusConnection> | 42 | #include <QDBusConnection> | ||
▲ Show 20 Lines • Show All 81 Lines • ▼ Show 20 Line(s) | 78 | { | |||
122 | connect(this, &VirtualKeyboard::enabledChanged, dbus, &VirtualKeyboardDBus::setEnabled); | 124 | connect(this, &VirtualKeyboard::enabledChanged, dbus, &VirtualKeyboardDBus::setEnabled); | ||
123 | 125 | | |||
124 | if (waylandServer()) { | 126 | if (waylandServer()) { | ||
125 | // we can announce support for the text input interface | 127 | // we can announce support for the text input interface | ||
126 | auto t = waylandServer()->display()->createTextInputManager(TextInputInterfaceVersion::UnstableV0, waylandServer()->display()); | 128 | auto t = waylandServer()->display()->createTextInputManager(TextInputInterfaceVersion::UnstableV0, waylandServer()->display()); | ||
127 | t->create(); | 129 | t->create(); | ||
128 | auto t2 = waylandServer()->display()->createTextInputManager(TextInputInterfaceVersion::UnstableV2, waylandServer()->display()); | 130 | auto t2 = waylandServer()->display()->createTextInputManager(TextInputInterfaceVersion::UnstableV2, waylandServer()->display()); | ||
129 | t2->create(); | 131 | t2->create(); | ||
132 | | ||||
133 | connect(waylandServer()->inputPanel(), &InputPanelInterface::inputPanelSurfaceAdded, this, [this](quint32, InputPanelSurfaceInterface *surface) { | ||||
134 | m_inputSurface = waylandServer()->createInputPanelSurface(surface); | ||||
135 | connect(m_inputSurface, &KWin::AbstractClient::geometryShapeChanged, this, [this] { | ||||
zzag: Use `frameGeometryChanged` instead of `geometryShapeChanged`. | |||||
136 | if (!m_trackedClient) | ||||
137 | return; | ||||
138 | m_trackedClient->setVirtualKeyboardGeometry(m_inputSurface->rect()); | ||||
139 | }); | ||||
140 | }); | ||||
141 | | ||||
130 | connect(waylandServer()->seat(), &SeatInterface::focusedTextInputChanged, this, | 142 | connect(waylandServer()->seat(), &SeatInterface::focusedTextInputChanged, this, | ||
131 | [this] { | 143 | [this] { | ||
132 | disconnect(m_waylandShowConnection); | 144 | disconnect(m_waylandShowConnection); | ||
133 | disconnect(m_waylandHideConnection); | 145 | disconnect(m_waylandHideConnection); | ||
134 | disconnect(m_waylandHintsConnection); | 146 | disconnect(m_waylandHintsConnection); | ||
135 | disconnect(m_waylandSurroundingTextConnection); | 147 | disconnect(m_waylandSurroundingTextConnection); | ||
136 | disconnect(m_waylandResetConnection); | 148 | disconnect(m_waylandResetConnection); | ||
137 | disconnect(m_waylandEnabledConnection); | 149 | disconnect(m_waylandEnabledConnection); | ||
138 | qApp->inputMethod()->reset(); | 150 | qApp->inputMethod()->reset(); | ||
139 | if (auto t = waylandServer()->seat()->focusedTextInput()) { | 151 | if (auto t = waylandServer()->seat()->focusedTextInput()) { | ||
140 | m_waylandShowConnection = connect(t, &TextInputInterface::requestShowInputPanel, this, &VirtualKeyboard::show); | 152 | m_waylandShowConnection = connect(t, &TextInputInterface::requestShowInputPanel, this, &VirtualKeyboard::show); | ||
141 | m_waylandHideConnection = connect(t, &TextInputInterface::requestHideInputPanel, this, &VirtualKeyboard::hide); | 153 | m_waylandHideConnection = connect(t, &TextInputInterface::requestHideInputPanel, this, &VirtualKeyboard::hide); | ||
142 | m_waylandSurroundingTextConnection = connect(t, &TextInputInterface::surroundingTextChanged, this, | 154 | m_waylandSurroundingTextConnection = connect(t, &TextInputInterface::surroundingTextChanged, this, | ||
143 | [] { | 155 | [] { | ||
144 | qApp->inputMethod()->update(Qt::ImSurroundingText | Qt::ImCursorPosition | Qt::ImAnchorPosition); | 156 | qApp->inputMethod()->update(Qt::ImSurroundingText | Qt::ImCursorPosition | Qt::ImAnchorPosition); | ||
145 | } | 157 | } | ||
146 | ); | 158 | ); | ||
147 | m_waylandHintsConnection = connect(t, &TextInputInterface::contentTypeChanged, this, | 159 | m_waylandHintsConnection = connect(t, &TextInputInterface::contentTypeChanged, this, | ||
148 | [] { | 160 | [] { | ||
149 | qApp->inputMethod()->update(Qt::ImHints); | 161 | qApp->inputMethod()->update(Qt::ImHints); | ||
150 | } | 162 | } | ||
151 | ); | 163 | ); | ||
152 | m_waylandResetConnection = connect(t, &TextInputInterface::requestReset, qApp->inputMethod(), &QInputMethod::reset); | 164 | m_waylandResetConnection = connect(t, &TextInputInterface::requestReset, qApp->inputMethod(), &QInputMethod::reset); | ||
153 | m_waylandEnabledConnection = connect(t, &TextInputInterface::enabledChanged, this, | 165 | m_waylandEnabledConnection = connect(t, &TextInputInterface::enabledChanged, this, [t, this] { | ||
154 | [] { | 166 | if (t->isEnabled()) { | ||
167 | waylandServer()->inputMethod()->sendDeactivate(); | ||||
168 | waylandServer()->inputMethod()->sendActivate(); | ||||
169 | adoptInputMethodContext(); | ||||
170 | } else | ||||
171 | waylandServer()->inputMethod()->sendDeactivate(); | ||||
155 | qApp->inputMethod()->update(Qt::ImQueryAll); | 172 | qApp->inputMethod()->update(Qt::ImQueryAll); | ||
156 | } | 173 | }); | ||
157 | ); | | |||
158 | 174 | | |||
159 | auto newClient = waylandServer()->findAbstractClient(waylandServer()->seat()->focusedTextInputSurface()); | 175 | auto newClient = waylandServer()->findAbstractClient(waylandServer()->seat()->focusedTextInputSurface()); | ||
160 | // Reset the old client virtual keybaord geom if necessary | 176 | // Reset the old client virtual keybaord geom if necessary | ||
161 | // Old and new clients could be the same if focus moves between subsurfaces | 177 | // Old and new clients could be the same if focus moves between subsurfaces | ||
162 | if (newClient != m_trackedClient) { | 178 | if (newClient != m_trackedClient) { | ||
163 | if (m_trackedClient) { | 179 | if (m_trackedClient) { | ||
164 | m_trackedClient->setVirtualKeyboardGeometry(QRect()); | 180 | m_trackedClient->setVirtualKeyboardGeometry(QRect()); | ||
165 | } | 181 | } | ||
▲ Show 20 Lines • Show All 52 Lines • ▼ Show 20 Line(s) | 232 | QDBusMessage msg = QDBusMessage::createMethodCall( | |||
218 | QStringLiteral("/org/kde/osdService"), | 234 | QStringLiteral("/org/kde/osdService"), | ||
219 | QStringLiteral("org.kde.osdService"), | 235 | QStringLiteral("org.kde.osdService"), | ||
220 | QStringLiteral("virtualKeyboardEnabledChanged") | 236 | QStringLiteral("virtualKeyboardEnabledChanged") | ||
221 | ); | 237 | ); | ||
222 | msg.setArguments({enabled}); | 238 | msg.setArguments({enabled}); | ||
223 | QDBusConnection::sessionBus().asyncCall(msg); | 239 | QDBusConnection::sessionBus().asyncCall(msg); | ||
224 | } | 240 | } | ||
225 | 241 | | |||
242 | void VirtualKeyboard::adoptInputMethodContext() | ||||
243 | { | ||||
244 | auto inputContext = waylandServer()->inputMethod()->context(); | ||||
245 | TextInputInterface *ti = waylandServer()->seat()->focusedTextInput(); | ||||
246 | | ||||
247 | inputContext->sendSurroundingText(QString::fromUtf8(ti->surroundingText()), ti->surroundingTextCursorPosition(), ti->surroundingTextSelectionAnchor()); | ||||
248 | inputContext->sendPreferredLanguage(QString::fromUtf8(ti->preferredLanguage())); | ||||
249 | | ||||
250 | connect(inputContext, &KWayland::Server::InputMethodContextInterface::keysym, waylandServer(), [](quint32 serial, quint32 time, quint32 sym, bool pressed, Qt::KeyboardModifiers modifiers) { | ||||
251 | auto t = waylandServer()->seat()->focusedTextInput(); | ||||
252 | if (t && t->isEnabled()) { | ||||
253 | if (pressed) { | ||||
254 | t->keysymPressed(sym, modifiers); | ||||
255 | } else { | ||||
256 | t->keysymReleased(sym, modifiers); | ||||
257 | } | ||||
258 | } | ||||
259 | }); | ||||
260 | | ||||
261 | connect(inputContext, &KWayland::Server::InputMethodContextInterface::commitString, waylandServer(), [](qint32 serial, const QString &text) { | ||||
262 | auto t = waylandServer()->seat()->focusedTextInput(); | ||||
263 | if (t && t->isEnabled()) { | ||||
264 | t->commit(text.toUtf8()); | ||||
265 | } | ||||
266 | }); | ||||
267 | connect(inputContext, &KWayland::Server::InputMethodContextInterface::preeditCursor, waylandServer(), [](qint32 index) { | ||||
268 | auto t = waylandServer()->seat()->focusedTextInput(); | ||||
269 | if (t && t->isEnabled()) { | ||||
270 | t->setPreEditCursor(index); | ||||
271 | } | ||||
272 | }); | ||||
273 | connect(inputContext, &KWayland::Server::InputMethodContextInterface::preeditString, waylandServer(), [](uint32_t serial, const QString &text, const QString &commit) { | ||||
274 | auto t = waylandServer()->seat()->focusedTextInput(); | ||||
275 | if (t && t->isEnabled()) { | ||||
276 | t->preEdit(text.toUtf8(), commit.toUtf8()); | ||||
277 | } | ||||
278 | }); | ||||
279 | connect(inputContext, &KWayland::Server::InputMethodContextInterface::deleteSurroundingText, waylandServer(), [](int32_t index, uint32_t length) { | ||||
280 | auto t = waylandServer()->seat()->focusedTextInput(); | ||||
281 | if (t && t->isEnabled()) { | ||||
282 | t->deleteSurroundingText(index, length); | ||||
283 | } | ||||
284 | }); | ||||
285 | connect(inputContext, &KWayland::Server::InputMethodContextInterface::cursorPosition, waylandServer(), [](qint32 index, qint32 anchor) { | ||||
286 | auto t = waylandServer()->seat()->focusedTextInput(); | ||||
287 | if (t && t->isEnabled()) { | ||||
288 | t->setCursorPosition(index, anchor); | ||||
289 | } | ||||
290 | }); | ||||
291 | connect(inputContext, &KWayland::Server::InputMethodContextInterface::language, waylandServer(), [](uint32_t serial, const QString &language) { | ||||
292 | auto t = waylandServer()->seat()->focusedTextInput(); | ||||
293 | if (t && t->isEnabled()) { | ||||
294 | t->setLanguage(language.toUtf8()); | ||||
295 | } | ||||
296 | }); | ||||
297 | connect(inputContext, &KWayland::Server::InputMethodContextInterface::textDirection, waylandServer(), [](uint32_t serial, Qt::LayoutDirection direction) { | ||||
298 | auto t = waylandServer()->seat()->focusedTextInput(); | ||||
299 | if (t && t->isEnabled()) { | ||||
300 | t->setTextDirection(direction); | ||||
301 | } | ||||
302 | }); | ||||
303 | } | ||||
304 | | ||||
226 | void VirtualKeyboard::updateSni() | 305 | void VirtualKeyboard::updateSni() | ||
227 | { | 306 | { | ||
228 | if (!m_sni) { | 307 | if (!m_sni) { | ||
229 | return; | 308 | return; | ||
230 | } | 309 | } | ||
231 | if (m_enabled) { | 310 | if (m_enabled) { | ||
232 | m_sni->setIconByName(QStringLiteral("input-keyboard-virtual-on")); | 311 | m_sni->setIconByName(QStringLiteral("input-keyboard-virtual-on")); | ||
233 | m_sni->setTitle(i18n("Virtual Keyboard: enabled")); | 312 | m_sni->setTitle(i18n("Virtual Keyboard: enabled")); | ||
234 | } else { | 313 | } else { | ||
235 | m_sni->setIconByName(QStringLiteral("input-keyboard-virtual-off")); | 314 | m_sni->setIconByName(QStringLiteral("input-keyboard-virtual-off")); | ||
236 | m_sni->setTitle(i18n("Virtual Keyboard: disabled")); | 315 | m_sni->setTitle(i18n("Virtual Keyboard: disabled")); | ||
237 | } | 316 | } | ||
238 | m_sni->setToolTipTitle(i18n("Whether to show the virtual keyboard on demand.")); | 317 | m_sni->setToolTipTitle(i18n("Whether to show the virtual keyboard on demand.")); | ||
239 | } | 318 | } | ||
240 | 319 | | |||
241 | void VirtualKeyboard::updateInputPanelState() | 320 | void VirtualKeyboard::updateInputPanelState() | ||
242 | { | 321 | { | ||
243 | if (!waylandServer()) { | 322 | if (!waylandServer()) { | ||
244 | return; | 323 | return; | ||
245 | } | 324 | } | ||
246 | 325 | | |||
247 | auto t = waylandServer()->seat()->focusedTextInput(); | 326 | auto t = waylandServer()->seat()->focusedTextInput(); | ||
248 | 327 | | |||
249 | if (!t || !m_inputWindow) { | 328 | if (!t) { | ||
250 | return; | 329 | return; | ||
251 | } | 330 | } | ||
252 | 331 | | |||
332 | if (m_inputWindow) { | ||||
253 | const bool inputPanelHasBeenClosed = m_inputWindow->isVisible() && !qApp->inputMethod()->isVisible(); | 333 | const bool inputPanelHasBeenClosed = m_inputWindow->isVisible() && !qApp->inputMethod()->isVisible(); | ||
254 | if (inputPanelHasBeenClosed && m_floodTimer->isActive()) { | 334 | if (inputPanelHasBeenClosed && m_floodTimer->isActive()) { | ||
255 | return; | 335 | return; | ||
256 | } | 336 | } | ||
257 | m_floodTimer->start(); | 337 | m_floodTimer->start(); | ||
258 | 338 | | |||
259 | m_inputWindow->setVisible(qApp->inputMethod()->isVisible()); | 339 | m_inputWindow->setVisible(qApp->inputMethod()->isVisible()); | ||
260 | 340 | | |||
Show All 11 Lines | |||||
272 | } else { | 352 | } else { | ||
273 | if (inputPanelHasBeenClosed && m_trackedClient) { | 353 | if (inputPanelHasBeenClosed && m_trackedClient) { | ||
274 | m_trackedClient->setVirtualKeyboardGeometry(QRect()); | 354 | m_trackedClient->setVirtualKeyboardGeometry(QRect()); | ||
275 | } | 355 | } | ||
276 | 356 | | |||
277 | t->setInputPanelState(false, QRect(0, 0, 0, 0)); | 357 | t->setInputPanelState(false, QRect(0, 0, 0, 0)); | ||
278 | } | 358 | } | ||
279 | } | 359 | } | ||
360 | if (m_inputSurface) { | ||||
361 | m_trackedClient->setVirtualKeyboardGeometry(m_inputSurface->frameGeometry()); | ||||
362 | t->setInputPanelState(true, QRect(0, 0, 0, 0)); | ||||
363 | } | ||||
364 | } | ||||
280 | 365 | | |||
281 | void VirtualKeyboard::show() | 366 | void VirtualKeyboard::show() | ||
282 | { | 367 | { | ||
283 | if (m_inputWindow.isNull() || !m_enabled) { | 368 | if (m_inputWindow.isNull() || !m_enabled) { | ||
284 | return; | 369 | return; | ||
285 | } | 370 | } | ||
286 | m_inputWindow->setGeometry(screens()->geometry(screens()->current())); | 371 | m_inputWindow->setGeometry(screens()->geometry(screens()->current())); | ||
287 | qApp->inputMethod()->show(); | 372 | qApp->inputMethod()->show(); | ||
▲ Show 20 Lines • Show All 215 Lines • Show Last 20 Lines |
Use frameGeometryChanged instead of geometryShapeChanged.