2022-08-05 13:03:37 +02:00
|
|
|
#include "InputMethodRelay.hpp"
|
|
|
|
|
#include "InputManager.hpp"
|
2022-08-05 16:21:08 +02:00
|
|
|
#include "../../Compositor.hpp"
|
2024-04-25 23:27:25 +01:00
|
|
|
#include "../../protocols/TextInputV3.hpp"
|
2024-07-29 11:14:19 -05:00
|
|
|
#include "../../protocols/TextInputV1.hpp"
|
2024-05-01 16:41:17 +01:00
|
|
|
#include "../../protocols/InputMethodV2.hpp"
|
2024-06-08 10:07:59 +02:00
|
|
|
#include "../../protocols/core/Compositor.hpp"
|
2022-08-05 13:03:37 +02:00
|
|
|
|
2023-02-19 20:54:53 +00:00
|
|
|
CInputMethodRelay::CInputMethodRelay() {
|
2024-06-08 10:07:59 +02:00
|
|
|
static auto P =
|
|
|
|
|
g_pHookSystem->hookDynamic("keyboardFocus", [&](void* self, SCallbackInfo& info, std::any param) { onKeyboardFocus(std::any_cast<SP<CWLSurfaceResource>>(param)); });
|
2024-04-25 23:27:25 +01:00
|
|
|
|
2024-07-29 11:14:19 -05:00
|
|
|
listeners.newTIV3 = PROTO::textInputV3->events.newTextInput.registerListener([this](std::any ti) { onNewTextInput(std::any_cast<WP<CTextInputV3>>(ti)); });
|
|
|
|
|
listeners.newTIV1 = PROTO::textInputV1->events.newTextInput.registerListener([this](std::any ti) { onNewTextInput(std::any_cast<WP<CTextInputV1>>(ti)); });
|
2024-05-01 16:41:17 +01:00
|
|
|
listeners.newIME = PROTO::ime->events.newIME.registerListener([this](std::any ime) { onNewIME(std::any_cast<SP<CInputMethodV2>>(ime)); });
|
2023-02-19 20:54:53 +00:00
|
|
|
}
|
2022-08-05 13:03:37 +02:00
|
|
|
|
2024-05-01 16:41:17 +01:00
|
|
|
void CInputMethodRelay::onNewIME(SP<CInputMethodV2> pIME) {
|
|
|
|
|
if (!m_pIME.expired()) {
|
2022-08-05 13:03:37 +02:00
|
|
|
Debug::log(ERR, "Cannot register 2 IMEs at once!");
|
|
|
|
|
|
2024-05-01 16:41:17 +01:00
|
|
|
pIME->unavailable();
|
2022-08-05 13:03:37 +02:00
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-01 16:41:17 +01:00
|
|
|
m_pIME = pIME;
|
2022-08-05 13:03:37 +02:00
|
|
|
|
2024-05-01 16:41:17 +01:00
|
|
|
listeners.commitIME = pIME->events.onCommit.registerListener([this](std::any d) {
|
|
|
|
|
const auto PTI = getFocusedTextInput();
|
2022-08-05 13:03:37 +02:00
|
|
|
|
2024-05-01 16:41:17 +01:00
|
|
|
if (!PTI) {
|
|
|
|
|
Debug::log(LOG, "No focused TextInput on IME Commit");
|
|
|
|
|
return;
|
|
|
|
|
}
|
2022-08-05 13:03:37 +02:00
|
|
|
|
2024-05-01 16:41:17 +01:00
|
|
|
PTI->updateIMEState(m_pIME.lock());
|
|
|
|
|
});
|
2022-08-05 13:03:37 +02:00
|
|
|
|
2024-05-01 16:41:17 +01:00
|
|
|
listeners.destroyIME = pIME->events.destroy.registerListener([this](std::any d) {
|
|
|
|
|
const auto PTI = getFocusedTextInput();
|
2022-08-05 13:03:37 +02:00
|
|
|
|
2024-05-01 16:41:17 +01:00
|
|
|
Debug::log(LOG, "IME Destroy");
|
2022-08-05 16:21:08 +02:00
|
|
|
|
2024-05-01 16:41:17 +01:00
|
|
|
if (PTI)
|
|
|
|
|
PTI->leave();
|
2022-08-05 16:21:08 +02:00
|
|
|
|
2024-05-01 16:41:17 +01:00
|
|
|
m_pIME.reset();
|
|
|
|
|
});
|
2022-08-05 16:21:08 +02:00
|
|
|
|
2024-05-01 16:41:17 +01:00
|
|
|
listeners.newPopup = pIME->events.newPopup.registerListener([this](std::any d) {
|
|
|
|
|
m_vIMEPopups.emplace_back(std::make_unique<CInputPopup>(std::any_cast<SP<CInputMethodPopupV2>>(d)));
|
2022-08-05 16:21:08 +02:00
|
|
|
|
2024-05-01 16:41:17 +01:00
|
|
|
Debug::log(LOG, "New input popup");
|
|
|
|
|
});
|
2022-08-05 17:07:01 +02:00
|
|
|
|
2024-04-05 01:34:04 +09:00
|
|
|
if (!g_pCompositor->m_pLastFocus)
|
|
|
|
|
return;
|
|
|
|
|
|
2024-08-26 20:24:30 +02:00
|
|
|
for (auto const& ti : m_vTextInputs) {
|
2024-06-08 10:07:59 +02:00
|
|
|
if (ti->client() != g_pCompositor->m_pLastFocus->client())
|
2024-04-05 01:34:04 +09:00
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (ti->isV3())
|
2024-06-08 10:07:59 +02:00
|
|
|
ti->enter(g_pCompositor->m_pLastFocus.lock());
|
2024-04-05 01:34:04 +09:00
|
|
|
else
|
2024-06-08 10:07:59 +02:00
|
|
|
ti->onEnabled(g_pCompositor->m_pLastFocus.lock());
|
2024-04-05 01:34:04 +09:00
|
|
|
}
|
2023-03-14 12:57:50 +00:00
|
|
|
}
|
|
|
|
|
|
2024-06-08 10:07:59 +02:00
|
|
|
void CInputMethodRelay::setIMEPopupFocus(CInputPopup* pPopup, SP<CWLSurfaceResource> pSurface) {
|
2024-03-24 16:08:25 +00:00
|
|
|
pPopup->onCommit();
|
2022-08-05 17:07:01 +02:00
|
|
|
}
|
|
|
|
|
|
2024-03-24 16:08:25 +00:00
|
|
|
void CInputMethodRelay::removePopup(CInputPopup* pPopup) {
|
|
|
|
|
std::erase_if(m_vIMEPopups, [pPopup](const auto& other) { return other.get() == pPopup; });
|
2022-08-05 17:07:01 +02:00
|
|
|
}
|
|
|
|
|
|
2024-03-22 23:08:52 +00:00
|
|
|
CTextInput* CInputMethodRelay::getFocusedTextInput() {
|
|
|
|
|
if (!g_pCompositor->m_pLastFocus)
|
|
|
|
|
return nullptr;
|
|
|
|
|
|
2024-08-26 20:24:30 +02:00
|
|
|
for (auto const& ti : m_vTextInputs) {
|
2024-03-22 23:08:52 +00:00
|
|
|
if (ti->focusedSurface() == g_pCompositor->m_pLastFocus)
|
|
|
|
|
return ti.get();
|
|
|
|
|
}
|
2022-08-05 13:03:37 +02:00
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-29 11:14:19 -05:00
|
|
|
void CInputMethodRelay::onNewTextInput(WP<CTextInputV3> tiv3) {
|
|
|
|
|
m_vTextInputs.emplace_back(std::make_unique<CTextInput>(tiv3));
|
2022-08-05 13:03:37 +02:00
|
|
|
}
|
|
|
|
|
|
2024-07-29 11:14:19 -05:00
|
|
|
void CInputMethodRelay::onNewTextInput(WP<CTextInputV1> pTIV1) {
|
2024-03-22 23:08:52 +00:00
|
|
|
m_vTextInputs.emplace_back(std::make_unique<CTextInput>(pTIV1));
|
2022-08-05 13:03:37 +02:00
|
|
|
}
|
|
|
|
|
|
2024-03-22 23:08:52 +00:00
|
|
|
void CInputMethodRelay::removeTextInput(CTextInput* pInput) {
|
2024-03-24 16:08:25 +00:00
|
|
|
std::erase_if(m_vTextInputs, [pInput](const auto& other) { return other.get() == pInput; });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CInputMethodRelay::updateAllPopups() {
|
2024-08-26 20:24:30 +02:00
|
|
|
for (auto const& p : m_vIMEPopups) {
|
2024-03-24 16:08:25 +00:00
|
|
|
p->onCommit();
|
|
|
|
|
}
|
2022-08-05 13:03:37 +02:00
|
|
|
}
|
|
|
|
|
|
2024-04-06 23:54:02 +09:00
|
|
|
void CInputMethodRelay::activateIME(CTextInput* pInput) {
|
2024-05-01 16:41:17 +01:00
|
|
|
if (m_pIME.expired())
|
2024-04-06 23:54:02 +09:00
|
|
|
return;
|
|
|
|
|
|
2024-05-05 17:16:00 +01:00
|
|
|
m_pIME->activate();
|
2024-04-06 23:54:02 +09:00
|
|
|
commitIMEState(pInput);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CInputMethodRelay::deactivateIME(CTextInput* pInput) {
|
2024-05-01 16:41:17 +01:00
|
|
|
if (m_pIME.expired())
|
2024-04-06 23:54:02 +09:00
|
|
|
return;
|
|
|
|
|
|
2024-05-05 17:16:00 +01:00
|
|
|
m_pIME->deactivate();
|
2024-04-06 23:54:02 +09:00
|
|
|
commitIMEState(pInput);
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-22 23:08:52 +00:00
|
|
|
void CInputMethodRelay::commitIMEState(CTextInput* pInput) {
|
2024-05-01 16:41:17 +01:00
|
|
|
if (m_pIME.expired())
|
2022-08-05 17:19:49 +02:00
|
|
|
return;
|
|
|
|
|
|
2024-05-01 16:41:17 +01:00
|
|
|
pInput->commitStateToIME(m_pIME.lock());
|
2022-08-05 13:03:37 +02:00
|
|
|
}
|
|
|
|
|
|
2024-06-08 10:07:59 +02:00
|
|
|
void CInputMethodRelay::onKeyboardFocus(SP<CWLSurfaceResource> pSurface) {
|
2024-05-01 16:41:17 +01:00
|
|
|
if (m_pIME.expired())
|
2022-08-05 13:03:37 +02:00
|
|
|
return;
|
|
|
|
|
|
2024-03-22 23:08:52 +00:00
|
|
|
if (pSurface == m_pLastKbFocus)
|
2024-03-19 23:54:33 +08:00
|
|
|
return;
|
2022-08-05 13:03:37 +02:00
|
|
|
|
2024-03-22 23:08:52 +00:00
|
|
|
m_pLastKbFocus = pSurface;
|
2023-03-14 12:57:50 +00:00
|
|
|
|
2024-08-26 20:24:30 +02:00
|
|
|
for (auto const& ti : m_vTextInputs) {
|
2024-03-22 23:08:52 +00:00
|
|
|
if (!ti->focusedSurface())
|
|
|
|
|
continue;
|
2022-08-05 13:03:37 +02:00
|
|
|
|
2024-03-22 23:08:52 +00:00
|
|
|
ti->leave();
|
2024-03-19 23:54:33 +08:00
|
|
|
}
|
2022-08-05 13:19:16 +02:00
|
|
|
|
2024-06-25 22:46:36 +02:00
|
|
|
if (!pSurface)
|
|
|
|
|
return;
|
|
|
|
|
|
2024-08-26 20:24:30 +02:00
|
|
|
for (auto const& ti : m_vTextInputs) {
|
2024-03-22 23:08:52 +00:00
|
|
|
if (!ti->isV3())
|
|
|
|
|
continue;
|
2024-03-22 18:45:24 +00:00
|
|
|
|
2024-06-08 10:07:59 +02:00
|
|
|
if (ti->client() != pSurface->client())
|
2024-03-22 23:08:52 +00:00
|
|
|
continue;
|
2022-08-05 13:19:16 +02:00
|
|
|
|
2024-03-22 23:08:52 +00:00
|
|
|
ti->enter(pSurface);
|
2022-08-05 13:19:16 +02:00
|
|
|
}
|
2022-09-25 20:07:48 +02:00
|
|
|
}
|
2024-03-24 16:08:25 +00:00
|
|
|
|
|
|
|
|
CInputPopup* CInputMethodRelay::popupFromCoords(const Vector2D& point) {
|
2024-08-26 20:24:30 +02:00
|
|
|
for (auto const& p : m_vIMEPopups) {
|
2024-03-24 16:08:25 +00:00
|
|
|
if (p->isVecInPopup(point))
|
|
|
|
|
return p.get();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
2024-04-07 22:15:50 +08:00
|
|
|
|
2024-06-08 10:07:59 +02:00
|
|
|
CInputPopup* CInputMethodRelay::popupFromSurface(const SP<CWLSurfaceResource> surface) {
|
2024-08-26 20:24:30 +02:00
|
|
|
for (auto const& p : m_vIMEPopups) {
|
2024-06-08 10:07:59 +02:00
|
|
|
if (p->getSurface() == surface)
|
2024-04-07 22:15:50 +08:00
|
|
|
return p.get();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|