summaryrefslogtreecommitdiff
path: root/src/managers
diff options
context:
space:
mode:
authorVaxry <vaxry@vaxry.net>2024-03-24 16:08:25 +0000
committerVaxry <vaxry@vaxry.net>2024-03-24 16:08:25 +0000
commit5cc4bf699cfe4d5915b8ea9f2a7c8449cdc7bd2f (patch)
treed524435ee7bafe19d1bfdb2d741bc0e2c7ae30ee /src/managers
parentacf15e5579a5d2bbbe4a13e87306445e31ea5e4f (diff)
IME: Refactor and fixup popups
Diffstat (limited to 'src/managers')
-rw-r--r--src/managers/input/InputManager.cpp6
-rw-r--r--src/managers/input/InputMethodPopup.cpp168
-rw-r--r--src/managers/input/InputMethodPopup.hpp41
-rw-r--r--src/managers/input/InputMethodRelay.cpp154
-rw-r--r--src/managers/input/InputMethodRelay.hpp21
-rw-r--r--src/managers/input/TextInput.cpp4
6 files changed, 247 insertions, 147 deletions
diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp
index 94e6abec..9f38ab22 100644
--- a/src/managers/input/InputManager.cpp
+++ b/src/managers/input/InputManager.cpp
@@ -215,10 +215,10 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
// also IME popups
if (!foundSurface) {
- auto popup = g_pCompositor->vectorToIMEPopup(mouseCoords, m_sIMERelay.m_lIMEPopups);
+ auto popup = g_pInputManager->m_sIMERelay.popupFromCoords(mouseCoords);
if (popup) {
- foundSurface = popup->pSurface->surface;
- surfacePos = Vector2D(popup->realX, popup->realY);
+ foundSurface = popup->getWlrSurface();
+ surfacePos = popup->globalBox().pos();
}
}
diff --git a/src/managers/input/InputMethodPopup.cpp b/src/managers/input/InputMethodPopup.cpp
new file mode 100644
index 00000000..56fb2024
--- /dev/null
+++ b/src/managers/input/InputMethodPopup.cpp
@@ -0,0 +1,168 @@
+#include "InputMethodPopup.hpp"
+
+CInputPopup::CInputPopup(wlr_input_popup_surface_v2* surf) : pWlr(surf) {
+ surface.assign(surf->surface);
+ initCallbacks();
+}
+
+static void onCommit(void* owner, void* data) {
+ const auto PPOPUP = (CInputPopup*)owner;
+ PPOPUP->onCommit();
+}
+
+static void onMap(void* owner, void* data) {
+ const auto PPOPUP = (CInputPopup*)owner;
+ PPOPUP->onMap();
+}
+
+static void onUnmap(void* owner, void* data) {
+ const auto PPOPUP = (CInputPopup*)owner;
+ PPOPUP->onUnmap();
+}
+
+static void onDestroy(void* owner, void* data) {
+ const auto PPOPUP = (CInputPopup*)owner;
+ PPOPUP->onDestroy();
+}
+
+void CInputPopup::initCallbacks() {
+ hyprListener_commitPopup.initCallback(&pWlr->surface->events.commit, &::onCommit, this, "IME Popup");
+ hyprListener_mapPopup.initCallback(&pWlr->surface->events.map, &::onMap, this, "IME Popup");
+ hyprListener_unmapPopup.initCallback(&pWlr->surface->events.unmap, &::onUnmap, this, "IME Popup");
+ hyprListener_destroyPopup.initCallback(&pWlr->events.destroy, &::onDestroy, this, "IME Popup");
+}
+
+CWLSurface* CInputPopup::queryOwner() {
+ const auto FOCUSED = g_pInputManager->m_sIMERelay.getFocusedTextInput();
+
+ if (!FOCUSED)
+ return nullptr;
+
+ return CWLSurface::surfaceFromWlr(FOCUSED->focusedSurface());
+}
+
+void CInputPopup::onDestroy() {
+ hyprListener_commitPopup.removeCallback();
+ hyprListener_destroyPopup.removeCallback();
+ hyprListener_mapPopup.removeCallback();
+ hyprListener_unmapPopup.removeCallback();
+
+ g_pInputManager->m_sIMERelay.removePopup(this);
+}
+
+void CInputPopup::onMap() {
+ Debug::log(LOG, "Mapped an IME Popup");
+
+ updateBox();
+ damageEntire();
+}
+
+void CInputPopup::onUnmap() {
+ Debug::log(LOG, "Unmapped an IME Popup");
+
+ damageEntire();
+}
+
+void CInputPopup::onCommit() {
+ updateBox();
+}
+
+void CInputPopup::damageEntire() {
+ const auto OWNER = queryOwner();
+
+ if (!OWNER) {
+ Debug::log(ERR, "BUG THIS: No owner in imepopup::damageentire");
+ return;
+ }
+
+ Vector2D pos = OWNER->getSurfaceBoxGlobal().value_or(CBox{0, 0, 0, 0}).pos();
+ CBox global = lastBoxLocal.copy().translate(pos);
+
+ g_pHyprRenderer->damageBox(&global);
+}
+
+void CInputPopup::damageSurface() {
+ const auto OWNER = queryOwner();
+
+ if (!OWNER) {
+ Debug::log(ERR, "BUG THIS: No owner in imepopup::damagesurface");
+ return;
+ }
+
+ Vector2D pos = OWNER->getSurfaceBoxGlobal().value_or(CBox{0, 0, 0, 0}).pos() + lastBoxLocal.pos();
+ g_pHyprRenderer->damageSurface(surface.wlr(), pos.x, pos.y);
+}
+
+void CInputPopup::updateBox() {
+ if (!surface.wlr()->mapped)
+ return;
+
+ const auto OWNER = queryOwner();
+ const auto PFOCUSEDTI = g_pInputManager->m_sIMERelay.getFocusedTextInput();
+
+ if (!PFOCUSEDTI)
+ return;
+
+ bool cursorRect = PFOCUSEDTI->hasCursorRectangle();
+ CBox cursorBoxLocal = PFOCUSEDTI->cursorBox();
+
+ CBox parentBox;
+
+ if (!OWNER)
+ parentBox = {0, 0, 500, 500};
+ else
+ parentBox = OWNER->getSurfaceBoxGlobal().value_or(CBox{0, 0, 500, 500});
+
+ 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};
+ }
+
+ if (cursorBoxLocal != lastBoxLocal)
+ damageEntire();
+
+ CMonitor* pMonitor = g_pCompositor->getMonitorFromVector(parentBox.middle());
+
+ if (cursorBoxLocal.y + parentBox.y + surface.wlr()->current.height + cursorBoxLocal.height > pMonitor->vecPosition.y + pMonitor->vecSize.y)
+ cursorBoxLocal.y -= surface.wlr()->current.height + cursorBoxLocal.height;
+
+ if (cursorBoxLocal.x + parentBox.x + surface.wlr()->current.width > pMonitor->vecPosition.x + pMonitor->vecSize.x)
+ cursorBoxLocal.x -= (cursorBoxLocal.x + parentBox.x + surface.wlr()->current.width) - (pMonitor->vecPosition.x + pMonitor->vecSize.x);
+
+ lastBoxLocal = cursorBoxLocal;
+
+ wlr_input_popup_surface_v2_send_text_input_rectangle(pWlr, cursorBoxLocal.pWlr());
+
+ damageSurface();
+
+ if (const auto PM = g_pCompositor->getMonitorFromCursor(); PM && PM->ID != lastMonitor) {
+ const auto PML = g_pCompositor->getMonitorFromID(lastMonitor);
+
+ if (PML)
+ wlr_surface_send_leave(surface.wlr(), PML->output);
+
+ wlr_surface_send_enter(surface.wlr(), PM->output);
+
+ lastMonitor = PM->ID;
+ }
+}
+
+CBox CInputPopup::globalBox() {
+ const auto OWNER = queryOwner();
+
+ if (!OWNER) {
+ Debug::log(ERR, "BUG THIS: No owner in imepopup::globalbox");
+ return {};
+ }
+
+ return lastBoxLocal.copy().translate(OWNER->getSurfaceBoxGlobal().value_or(CBox{0, 0, 0, 0}).pos());
+}
+
+bool CInputPopup::isVecInPopup(const Vector2D& point) {
+ return globalBox().containsPoint(point);
+}
+
+wlr_surface* CInputPopup::getWlrSurface() {
+ return surface.wlr();
+}
diff --git a/src/managers/input/InputMethodPopup.hpp b/src/managers/input/InputMethodPopup.hpp
new file mode 100644
index 00000000..8bcf1101
--- /dev/null
+++ b/src/managers/input/InputMethodPopup.hpp
@@ -0,0 +1,41 @@
+#pragma once
+
+#include "../../helpers/WLListener.hpp"
+#include "../../desktop/WLSurface.hpp"
+#include "../../macros.hpp"
+#include "../../helpers/Box.hpp"
+
+struct wlr_input_popup_surface_v2;
+
+class CInputPopup {
+ public:
+ CInputPopup(wlr_input_popup_surface_v2* surf);
+
+ void onDestroy();
+ void onMap();
+ void onUnmap();
+ void onCommit();
+
+ void damageEntire();
+ void damageSurface();
+
+ bool isVecInPopup(const Vector2D& point);
+
+ CBox globalBox();
+ wlr_surface* getWlrSurface();
+
+ private:
+ void initCallbacks();
+ CWLSurface* queryOwner();
+ void updateBox();
+
+ wlr_input_popup_surface_v2* pWlr = nullptr;
+ CWLSurface surface;
+ CBox lastBoxLocal;
+ 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 13e4c9df..2bd98a79 100644
--- a/src/managers/input/InputMethodRelay.cpp
+++ b/src/managers/input/InputMethodRelay.cpp
@@ -86,14 +86,7 @@ void CInputMethodRelay::onNewIME(wlr_input_method_v2* pIME) {
hyprListener_IMENewPopup.initCallback(
&m_pWLRIME->events.new_popup_surface,
[&](void* owner, void* data) {
- const auto PNEWPOPUP = &m_lIMEPopups.emplace_back();
-
- PNEWPOPUP->pSurface = (wlr_input_popup_surface_v2*)data;
-
- PNEWPOPUP->hyprListener_commitPopup.initCallback(&PNEWPOPUP->pSurface->surface->events.commit, &Events::listener_commitInputPopup, PNEWPOPUP, "IME Popup");
- PNEWPOPUP->hyprListener_mapPopup.initCallback(&PNEWPOPUP->pSurface->surface->events.map, &Events::listener_mapInputPopup, PNEWPOPUP, "IME Popup");
- PNEWPOPUP->hyprListener_unmapPopup.initCallback(&PNEWPOPUP->pSurface->surface->events.unmap, &Events::listener_unmapInputPopup, PNEWPOPUP, "IME Popup");
- PNEWPOPUP->hyprListener_destroyPopup.initCallback(&PNEWPOPUP->pSurface->events.destroy, &Events::listener_destroyInputPopup, PNEWPOPUP, "IME Popup");
+ m_vIMEPopups.emplace_back(std::make_unique<CInputPopup>((wlr_input_popup_surface_v2*)data));
Debug::log(LOG, "New input popup");
},
@@ -103,132 +96,12 @@ void CInputMethodRelay::onNewIME(wlr_input_method_v2* pIME) {
PTI->enter(PTI->focusedSurface());
}
-void CInputMethodRelay::updateInputPopup(SIMEPopup* pPopup) {
- if (!pPopup->pSurface->surface->mapped)
- return;
-
- // damage last known pos & size
- g_pHyprRenderer->damageBox(&pPopup->lastBox);
-
- const auto PFOCUSEDTI = getFocusedTextInput();
-
- if (!PFOCUSEDTI || !PFOCUSEDTI->focusedSurface())
- return;
-
- bool cursorRect = PFOCUSEDTI->hasCursorRectangle();
- const auto PFOCUSEDSURFACE = PFOCUSEDTI->focusedSurface();
- CBox cursorBox = PFOCUSEDTI->cursorBox();
-
- CBox parentBox;
-
- const auto PSURFACE = CWLSurface::surfaceFromWlr(PFOCUSEDSURFACE);
-
- if (!PSURFACE)
- parentBox = {0, 0, 200, 200};
- else
- parentBox = PSURFACE->getSurfaceBoxGlobal().value_or(CBox{0, 0, 200, 200});
-
- if (!cursorRect)
- cursorBox = {0, 0, (int)parentBox.w, (int)parentBox.h};
-
- CMonitor* pMonitor = g_pCompositor->getMonitorFromVector(cursorBox.middle());
-
- if (cursorBox.y + parentBox.y + pPopup->pSurface->surface->current.height + cursorBox.height > pMonitor->vecPosition.y + pMonitor->vecSize.y)
- cursorBox.y -= pPopup->pSurface->surface->current.height + cursorBox.height;
-
- if (cursorBox.x + parentBox.x + pPopup->pSurface->surface->current.width > pMonitor->vecPosition.x + pMonitor->vecSize.x)
- cursorBox.x -= (cursorBox.x + parentBox.x + pPopup->pSurface->surface->current.width) - (pMonitor->vecPosition.x + pMonitor->vecSize.x);
-
- pPopup->x = cursorBox.x;
- pPopup->y = cursorBox.y + cursorBox.height;
-
- pPopup->realX = cursorBox.x + parentBox.x;
- pPopup->realY = cursorBox.y + parentBox.y + cursorBox.height;
-
- pPopup->lastBox = cursorBox;
-
- wlr_input_popup_surface_v2_send_text_input_rectangle(pPopup->pSurface, cursorBox.pWlr());
-
- damagePopup(pPopup);
+void CInputMethodRelay::setIMEPopupFocus(CInputPopup* pPopup, wlr_surface* pSurface) {
+ pPopup->onCommit();
}
-void CInputMethodRelay::setIMEPopupFocus(SIMEPopup* pPopup, wlr_surface* pSurface) {
- updateInputPopup(pPopup);
-}
-
-void Events::listener_mapInputPopup(void* owner, void* data) {
- const auto PPOPUP = (SIMEPopup*)owner;
-
- Debug::log(LOG, "Mapped an IME Popup");
-
- g_pInputManager->m_sIMERelay.updateInputPopup(PPOPUP);
-
- if (const auto PMONITOR = g_pCompositor->getMonitorFromVector(PPOPUP->lastBox.middle()); PMONITOR)
- wlr_surface_send_enter(PPOPUP->pSurface->surface, PMONITOR->output);
-}
-
-void Events::listener_unmapInputPopup(void* owner, void* data) {
- const auto PPOPUP = (SIMEPopup*)owner;
-
- Debug::log(LOG, "Unmapped an IME Popup");
-
- g_pHyprRenderer->damageBox(&PPOPUP->lastBox);
-
- g_pInputManager->m_sIMERelay.updateInputPopup(PPOPUP);
-}
-
-void Events::listener_destroyInputPopup(void* owner, void* data) {
- const auto PPOPUP = (SIMEPopup*)owner;
-
- Debug::log(LOG, "Removed an IME Popup");
-
- PPOPUP->hyprListener_commitPopup.removeCallback();
- PPOPUP->hyprListener_destroyPopup.removeCallback();
- PPOPUP->hyprListener_focusedSurfaceUnmap.removeCallback();
- PPOPUP->hyprListener_mapPopup.removeCallback();
- PPOPUP->hyprListener_unmapPopup.removeCallback();
-
- g_pInputManager->m_sIMERelay.removePopup(PPOPUP);
-}
-
-void Events::listener_commitInputPopup(void* owner, void* data) {
- const auto PPOPUP = (SIMEPopup*)owner;
-
- g_pInputManager->m_sIMERelay.updateInputPopup(PPOPUP);
-}
-
-void CInputMethodRelay::removePopup(SIMEPopup* pPopup) {
- m_lIMEPopups.remove(*pPopup);
-}
-
-void CInputMethodRelay::damagePopup(SIMEPopup* pPopup) {
- if (!pPopup->pSurface->surface->mapped)
- return;
-
- const auto PFOCUSEDTI = getFocusedTextInput();
-
- if (!PFOCUSEDTI || !PFOCUSEDTI->focusedSurface())
- return;
-
- Vector2D parentPos;
-
- const auto PFOCUSEDSURFACE = PFOCUSEDTI->focusedSurface();
-
- if (wlr_layer_surface_v1_try_from_wlr_surface(PFOCUSEDSURFACE)) {
- const auto PLS = g_pCompositor->getLayerSurfaceFromWlr(wlr_layer_surface_v1_try_from_wlr_surface(PFOCUSEDSURFACE));
-
- if (PLS) {
- parentPos = Vector2D(PLS->geometry.x, PLS->geometry.y) + g_pCompositor->getMonitorFromID(PLS->monitorID)->vecPosition;
- }
- } else {
- const auto PWINDOW = g_pCompositor->getWindowFromSurface(PFOCUSEDSURFACE);
-
- if (PWINDOW) {
- parentPos = PWINDOW->m_vRealPosition.goal();
- }
- }
-
- g_pHyprRenderer->damageSurface(pPopup->pSurface->surface, parentPos.x + pPopup->x, parentPos.y + pPopup->y);
+void CInputMethodRelay::removePopup(CInputPopup* pPopup) {
+ std::erase_if(m_vIMEPopups, [pPopup](const auto& other) { return other.get() == pPopup; });
}
SIMEKbGrab* CInputMethodRelay::getIMEKeyboardGrab(SKeyboard* pKeyboard) {
@@ -268,7 +141,13 @@ void CInputMethodRelay::onNewTextInput(STextInputV1* pTIV1) {
}
void CInputMethodRelay::removeTextInput(CTextInput* pInput) {
- m_vTextInputs.remove_if([&](const auto& other) { return other.get() == pInput; });
+ std::erase_if(m_vTextInputs, [pInput](const auto& other) { return other.get() == pInput; });
+}
+
+void CInputMethodRelay::updateAllPopups() {
+ for (auto& p : m_vIMEPopups) {
+ p->onCommit();
+ }
}
void CInputMethodRelay::commitIMEState(CTextInput* pInput) {
@@ -304,3 +183,12 @@ void CInputMethodRelay::onKeyboardFocus(wlr_surface* pSurface) {
ti->enter(pSurface);
}
}
+
+CInputPopup* CInputMethodRelay::popupFromCoords(const Vector2D& point) {
+ for (auto& p : m_vIMEPopups) {
+ if (p->isVecInPopup(point))
+ return p.get();
+ }
+
+ return nullptr;
+}
diff --git a/src/managers/input/InputMethodRelay.hpp b/src/managers/input/InputMethodRelay.hpp
index 7618400f..f19b4bb5 100644
--- a/src/managers/input/InputMethodRelay.hpp
+++ b/src/managers/input/InputMethodRelay.hpp
@@ -4,8 +4,10 @@
#include "../../defines.hpp"
#include "../../helpers/WLClasses.hpp"
#include "TextInput.hpp"
+#include "InputMethodPopup.hpp"
class CInputManager;
+class CHyprRenderer;
struct STextInputV1;
class CInputMethodRelay {
@@ -27,18 +29,20 @@ class CInputMethodRelay {
SIMEKbGrab* getIMEKeyboardGrab(SKeyboard*);
- void setIMEPopupFocus(SIMEPopup*, wlr_surface*);
- void updateInputPopup(SIMEPopup*);
- void damagePopup(SIMEPopup*);
- void removePopup(SIMEPopup*);
+ void setIMEPopupFocus(CInputPopup*, wlr_surface*);
+ void removePopup(CInputPopup*);
+
+ CInputPopup* popupFromCoords(const Vector2D& point);
+
+ void updateAllPopups();
private:
- std::unique_ptr<SIMEKbGrab> m_pKeyboardGrab;
+ std::unique_ptr<SIMEKbGrab> m_pKeyboardGrab;
- std::list<std::unique_ptr<CTextInput>> m_vTextInputs;
- std::list<SIMEPopup> m_lIMEPopups;
+ std::vector<std::unique_ptr<CTextInput>> m_vTextInputs;
+ std::vector<std::unique_ptr<CInputPopup>> m_vIMEPopups;
- wlr_surface* m_pLastKbFocus = nullptr;
+ wlr_surface* m_pLastKbFocus = nullptr;
DYNLISTENER(textInputNew);
DYNLISTENER(IMECommit);
@@ -50,4 +54,5 @@ class CInputMethodRelay {
friend class CInputManager;
friend class CTextInputV1ProtocolManager;
friend struct CTextInput;
+ friend class CHyprRenderer;
};
diff --git a/src/managers/input/TextInput.cpp b/src/managers/input/TextInput.cpp
index c42d4f1f..0e642f82 100644
--- a/src/managers/input/TextInput.cpp
+++ b/src/managers/input/TextInput.cpp
@@ -222,9 +222,7 @@ void CTextInput::commitStateToIME(wlr_input_method_v2* ime) {
wlr_input_method_v2_send_content_type(ime, pV1Input->pendingContentType.hint, pV1Input->pendingContentType.purpose);
}
- for (auto& p : g_pInputManager->m_sIMERelay.m_lIMEPopups) {
- g_pInputManager->m_sIMERelay.updateInputPopup(&p);
- }
+ g_pInputManager->m_sIMERelay.updateAllPopups();
wlr_input_method_v2_send_done(ime);
}