IME: fix crashes with destroyed text-inputs

ref #5189
This commit is contained in:
Vaxry 2024-03-22 18:45:24 +00:00
parent 461757e2fb
commit d2b42e29c6
5 changed files with 53 additions and 11 deletions

View file

@ -244,3 +244,39 @@ void SKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) {
xkb_keymap_unref(NEWKEYMAP); xkb_keymap_unref(NEWKEYMAP);
xkb_context_unref(PCONTEXT); xkb_context_unref(PCONTEXT);
} }
void STextInput::setFocusedSurface(wlr_surface* pSurface) {
focusedSurface = pSurface;
hyprListener_surfaceUnmapped.removeCallback();
hyprListener_surfaceDestroyed.removeCallback();
if (!pSurface)
return;
hyprListener_surfaceUnmapped.initCallback(
&pSurface->events.unmap,
[this](void* owner, void* data) {
if (!focusedSurface)
return;
focusedSurface = nullptr;
hyprListener_surfaceUnmapped.removeCallback();
hyprListener_surfaceDestroyed.removeCallback();
g_pInputManager->m_sIMERelay.removeSurfaceToPTI(this);
},
this, "STextInput");
hyprListener_surfaceDestroyed.initCallback(
&pSurface->events.destroy,
[this](void* owner, void* data) {
if (!focusedSurface)
return;
focusedSurface = nullptr;
hyprListener_surfaceUnmapped.removeCallback();
hyprListener_surfaceDestroyed.removeCallback();
g_pInputManager->m_sIMERelay.removeSurfaceToPTI(this);
},
this, "STextInput");
}

View file

@ -295,10 +295,14 @@ struct STextInput {
STextInputV1* pV1Input = nullptr; STextInputV1* pV1Input = nullptr;
wlr_surface* focusedSurface = nullptr; wlr_surface* focusedSurface = nullptr;
void setFocusedSurface(wlr_surface* pSurface);
DYNLISTENER(textInputEnable); DYNLISTENER(textInputEnable);
DYNLISTENER(textInputDisable); DYNLISTENER(textInputDisable);
DYNLISTENER(textInputCommit); DYNLISTENER(textInputCommit);
DYNLISTENER(textInputDestroy); DYNLISTENER(textInputDestroy);
DYNLISTENER(surfaceUnmapped);
DYNLISTENER(surfaceDestroyed);
}; };
struct SIMEKbGrab { struct SIMEKbGrab {

View file

@ -143,7 +143,7 @@ void CInputMethodRelay::onNewIME(wlr_input_method_v2* pIME) {
} }
wlr_surface* CInputMethodRelay::focusedSurface(STextInput* pTI) { wlr_surface* CInputMethodRelay::focusedSurface(STextInput* pTI) {
return pTI->pWlrInput ? pTI->pWlrInput->focused_surface : pTI->pV1Input->focusedSurface; return pTI->pWlrInput ? pTI->pWlrInput->focused_surface : pTI->focusedSurface;
} }
void CInputMethodRelay::updateInputPopup(SIMEPopup* pPopup) { void CInputMethodRelay::updateInputPopup(SIMEPopup* pPopup) {
@ -346,8 +346,8 @@ void CInputMethodRelay::createNewTextInput(wlr_text_input_v3* pInput, STextInput
// v1 only, map surface to PTI // v1 only, map surface to PTI
if (PINPUT->pV1Input) { if (PINPUT->pV1Input) {
wlr_surface* pSurface = wlr_surface_from_resource((wl_resource*)data); wlr_surface* pSurface = wlr_surface_from_resource((wl_resource*)data);
PINPUT->focusedSurface = pSurface; PINPUT->setFocusedSurface(pSurface);
setSurfaceToPTI(pSurface, PINPUT); setSurfaceToPTI(pSurface, PINPUT);
if (m_pFocusedSurface == pSurface) if (m_pFocusedSurface == pSurface)
onTextInputEnter(pSurface); onTextInputEnter(pSurface);
@ -510,8 +510,8 @@ void CInputMethodRelay::onTextInputLeave(wlr_surface* pSurface) {
wlr_text_input_v3_send_leave(ti->pWlrInput); wlr_text_input_v3_send_leave(ti->pWlrInput);
else { else {
zwp_text_input_v1_send_leave(ti->pV1Input->resourceImpl); zwp_text_input_v1_send_leave(ti->pV1Input->resourceImpl);
ti->pV1Input->focusedSurface = nullptr; ti->setFocusedSurface(nullptr);
ti->pV1Input->active = false; ti->pV1Input->active = false;
} }
} }
@ -527,23 +527,26 @@ void CInputMethodRelay::onTextInputEnter(wlr_surface* pSurface) {
wlr_text_input_v3_send_enter(ti->pWlrInput, pSurface); wlr_text_input_v3_send_enter(ti->pWlrInput, pSurface);
else { else {
zwp_text_input_v1_send_enter(ti->pV1Input->resourceImpl, pSurface->resource); zwp_text_input_v1_send_enter(ti->pV1Input->resourceImpl, pSurface->resource);
ti->pV1Input->focusedSurface = pSurface; ti->setFocusedSurface(pSurface);
ti->pV1Input->active = true; ti->pV1Input->active = true;
} }
} }
void CInputMethodRelay::setSurfaceToPTI(wlr_surface* pSurface, STextInput* pInput) { void CInputMethodRelay::setSurfaceToPTI(wlr_surface* pSurface, STextInput* pInput) {
if (pSurface) { if (pSurface) {
m_mSurfaceToTextInput[pSurface] = pInput; m_mSurfaceToTextInput[pSurface] = pInput;
pInput->focusedSurface = pSurface; pInput->setFocusedSurface(pSurface);
} }
} }
void CInputMethodRelay::removeSurfaceToPTI(STextInput* pInput) { void CInputMethodRelay::removeSurfaceToPTI(STextInput* pInput) {
if (pInput->focusedSurface) { if (pInput->focusedSurface) {
m_mSurfaceToTextInput.erase(pInput->focusedSurface); m_mSurfaceToTextInput.erase(pInput->focusedSurface);
pInput->focusedSurface = nullptr; pInput->setFocusedSurface(nullptr);
return;
} }
std::erase_if(m_mSurfaceToTextInput, [pInput](const auto& el) { return el.second == pInput; });
} }
STextInput* CInputMethodRelay::getTextInput(wlr_surface* pSurface) { STextInput* CInputMethodRelay::getTextInput(wlr_surface* pSurface) {

View file

@ -62,4 +62,5 @@ class CInputMethodRelay {
friend class CHyprRenderer; friend class CHyprRenderer;
friend class CInputManager; friend class CInputManager;
friend class CTextInputV1ProtocolManager; friend class CTextInputV1ProtocolManager;
friend struct STextInput;
}; };

View file

@ -13,8 +13,6 @@ struct STextInputV1 {
wl_resource* resourceImpl = nullptr; wl_resource* resourceImpl = nullptr;
wlr_surface* focusedSurface = nullptr;
STextInput* pTextInput = nullptr; STextInput* pTextInput = nullptr;
wl_signal sEnable; wl_signal sEnable;