From d657b59f701a65c7a85986e8d99754716468ee5b Mon Sep 17 00:00:00 2001 From: Junxuan Liao <70618504+MikeWalrus@users.noreply.github.com> Date: Sun, 7 Apr 2024 22:15:50 +0800 Subject: [PATCH] IME: fix IME popup mouse inputs (again) (#5417) `lastBoxLocal`'s size should be the actual popup's size instead of the cursor rectangle's size. Also, the rectangle position is now relative to the popup. (Actually fixes #5255 imho.) One thing #3922 missed was handling focus held by buttons. Let's hope I get it right this time. --- src/managers/input/InputManager.cpp | 36 ++++++++++---------- src/managers/input/InputManager.hpp | 2 ++ src/managers/input/InputMethodPopup.cpp | 45 +++++++++++++------------ src/managers/input/InputMethodPopup.hpp | 3 +- src/managers/input/InputMethodRelay.cpp | 9 +++++ src/managers/input/InputMethodRelay.hpp | 1 + 6 files changed, 54 insertions(+), 42 deletions(-) diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 05317281..84ac00b5 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -171,26 +171,26 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { updateDragIcon(); if (!m_sDrag.drag && !m_lCurrentlyHeldButtons.empty() && g_pCompositor->m_pLastFocus && m_pLastMouseSurface) { - if (m_bLastFocusOnLS) { - foundSurface = m_pLastMouseSurface; - pFoundLayerSurface = g_pCompositor->getLayerSurfaceFromSurface(foundSurface); - if (pFoundLayerSurface) { - surfacePos = g_pCompositor->getLayerSurfaceFromSurface(foundSurface)->position; - m_bFocusHeldByButtons = true; - m_bRefocusHeldByButtons = refocus; - } else { - // ? - foundSurface = nullptr; - pFoundLayerSurface = nullptr; - } - } else if (g_pCompositor->m_pLastWindow) { - foundSurface = m_pLastMouseSurface; - pFoundWindow = g_pCompositor->m_pLastWindow; - - surfaceCoords = g_pCompositor->vectorToSurfaceLocal(mouseCoords, pFoundWindow, foundSurface); - + foundSurface = m_pLastMouseSurface; + pFoundLayerSurface = g_pCompositor->getLayerSurfaceFromSurface(foundSurface); + if (pFoundLayerSurface) { + surfacePos = pFoundLayerSurface->position; m_bFocusHeldByButtons = true; m_bRefocusHeldByButtons = refocus; + } else { + CInputPopup* foundPopup = m_sIMERelay.popupFromSurface(foundSurface); + if (foundPopup) { + surfacePos = foundPopup->globalBox().pos(); + m_bFocusHeldByButtons = true; + m_bRefocusHeldByButtons = refocus; + } else if (g_pCompositor->m_pLastWindow) { + foundSurface = m_pLastMouseSurface; + pFoundWindow = g_pCompositor->m_pLastWindow; + + surfaceCoords = g_pCompositor->vectorToSurfaceLocal(mouseCoords, pFoundWindow, foundSurface); + m_bFocusHeldByButtons = true; + m_bRefocusHeldByButtons = refocus; + } } } diff --git a/src/managers/input/InputManager.hpp b/src/managers/input/InputManager.hpp index a89981f3..f1c322ca 100644 --- a/src/managers/input/InputManager.hpp +++ b/src/managers/input/InputManager.hpp @@ -184,6 +184,8 @@ class CInputManager { // for some bugs in follow mouse 0 bool m_bLastFocusOnLS = false; + bool m_bLastFocusOnIMEPopup = false; + // for hiding cursor on touch bool m_bLastInputTouch = false; diff --git a/src/managers/input/InputMethodPopup.cpp b/src/managers/input/InputMethodPopup.cpp index bc2876ad..7d101e10 100644 --- a/src/managers/input/InputMethodPopup.cpp +++ b/src/managers/input/InputMethodPopup.cpp @@ -83,11 +83,8 @@ void CInputPopup::damageEntire() { Debug::log(ERR, "BUG THIS: No owner in imepopup::damageentire"); return; } - - Vector2D pos = OWNER->getSurfaceBoxGlobal().value_or(CBox{0, 0, 0, 0}).pos() + lastBoxLocal.pos(); - CBox global = {pos, lastPopupSize}; - - g_pHyprRenderer->damageBox(&global); + CBox box = globalBox(); + g_pHyprRenderer->damageBox(&box); } void CInputPopup::damageSurface() { @@ -98,7 +95,7 @@ void CInputPopup::damageSurface() { return; } - Vector2D pos = OWNER->getSurfaceBoxGlobal().value_or(CBox{0, 0, 0, 0}).pos() + lastBoxLocal.pos(); + Vector2D pos = globalBox().pos(); g_pHyprRenderer->damageSurface(surface.wlr(), pos.x, pos.y); } @@ -112,8 +109,8 @@ void CInputPopup::updateBox() { if (!PFOCUSEDTI) return; - bool cursorRect = PFOCUSEDTI->hasCursorRectangle(); - CBox cursorBoxLocal = PFOCUSEDTI->cursorBox(); + bool cursorRect = PFOCUSEDTI->hasCursorRectangle(); + CBox cursorBoxParent = PFOCUSEDTI->cursorBox(); CBox parentBox; @@ -125,29 +122,32 @@ void CInputPopup::updateBox() { if (!cursorRect) { Vector2D coords = OWNER ? OWNER->getSurfaceBoxGlobal().value_or(CBox{0, 0, 500, 500}).pos() : Vector2D{0, 0}; parentBox = {coords, {500, 500}}; - cursorBoxLocal = {0, 0, (int)parentBox.w, (int)parentBox.h}; + cursorBoxParent = {0, 0, (int)parentBox.w, (int)parentBox.h}; } - Vector2D currentPopupSize = surface.getViewporterCorrectedSize(); - - if (cursorBoxLocal != lastBoxLocal || currentPopupSize != lastPopupSize) - damageEntire(); + Vector2D currentPopupSize = surface.getViewporterCorrectedSize(); CMonitor* pMonitor = g_pCompositor->getMonitorFromVector(parentBox.middle()); - if (cursorBoxLocal.y + parentBox.y + currentPopupSize.y + cursorBoxLocal.height > pMonitor->vecPosition.y + pMonitor->vecSize.y) - cursorBoxLocal.y -= currentPopupSize.y; + Vector2D popupOffset(0, 0); + + if (parentBox.y + cursorBoxParent.y + cursorBoxParent.height + currentPopupSize.y > pMonitor->vecPosition.y + pMonitor->vecSize.y) + popupOffset.y = -currentPopupSize.y; else - cursorBoxLocal.y += cursorBoxLocal.height; + popupOffset.y = cursorBoxParent.height; - if (cursorBoxLocal.x + parentBox.x + currentPopupSize.x > pMonitor->vecPosition.x + pMonitor->vecSize.x) - cursorBoxLocal.x -= (cursorBoxLocal.x + parentBox.x + currentPopupSize.x) - (pMonitor->vecPosition.x + pMonitor->vecSize.x); - - lastBoxLocal = cursorBoxLocal; - lastPopupSize = currentPopupSize; + double popupOverflow = parentBox.x + cursorBoxParent.x + currentPopupSize.x - (pMonitor->vecPosition.x + pMonitor->vecSize.x); + if (popupOverflow > 0) + popupOffset.x -= popupOverflow; + CBox cursorBoxLocal({-popupOffset.x, -popupOffset.y}, cursorBoxParent.size()); wlr_input_popup_surface_v2_send_text_input_rectangle(pWlr, cursorBoxLocal.pWlr()); + CBox popupBoxParent(cursorBoxParent.pos() + popupOffset, currentPopupSize); + if (popupBoxParent != lastBoxLocal) { + damageEntire(); + lastBoxLocal = popupBoxParent; + } damageSurface(); if (const auto PM = g_pCompositor->getMonitorFromCursor(); PM && PM->ID != lastMonitor) { @@ -169,8 +169,9 @@ CBox CInputPopup::globalBox() { Debug::log(ERR, "BUG THIS: No owner in imepopup::globalbox"); return {}; } + CBox parentBox = OWNER->getSurfaceBoxGlobal().value_or(CBox{0, 0, 500, 500}); - return lastBoxLocal.copy().translate(OWNER->getSurfaceBoxGlobal().value_or(CBox{0, 0, 0, 0}).pos()); + return lastBoxLocal.copy().translate(parentBox.pos()); } bool CInputPopup::isVecInPopup(const Vector2D& point) { diff --git a/src/managers/input/InputMethodPopup.hpp b/src/managers/input/InputMethodPopup.hpp index 71b2fe64..aed4dbc2 100644 --- a/src/managers/input/InputMethodPopup.hpp +++ b/src/managers/input/InputMethodPopup.hpp @@ -32,11 +32,10 @@ class CInputPopup { wlr_input_popup_surface_v2* pWlr = nullptr; CWLSurface surface; CBox lastBoxLocal; - Vector2D lastPopupSize; uint64_t lastMonitor = -1; DYNLISTENER(mapPopup); DYNLISTENER(unmapPopup); DYNLISTENER(destroyPopup); DYNLISTENER(commitPopup); -}; \ No newline at end of file +}; diff --git a/src/managers/input/InputMethodRelay.cpp b/src/managers/input/InputMethodRelay.cpp index 8c21247a..a2d75f20 100644 --- a/src/managers/input/InputMethodRelay.cpp +++ b/src/managers/input/InputMethodRelay.cpp @@ -221,3 +221,12 @@ CInputPopup* CInputMethodRelay::popupFromCoords(const Vector2D& point) { return nullptr; } + +CInputPopup* CInputMethodRelay::popupFromSurface(const wlr_surface* surface) { + for (auto& p : m_vIMEPopups) { + if (p->getWlrSurface() == surface) + return p.get(); + } + + return nullptr; +} diff --git a/src/managers/input/InputMethodRelay.hpp b/src/managers/input/InputMethodRelay.hpp index eb7c9f64..01d36675 100644 --- a/src/managers/input/InputMethodRelay.hpp +++ b/src/managers/input/InputMethodRelay.hpp @@ -35,6 +35,7 @@ class CInputMethodRelay { void removePopup(CInputPopup*); CInputPopup* popupFromCoords(const Vector2D& point); + CInputPopup* popupFromSurface(const wlr_surface* surface); void updateAllPopups();