From 9f956655a89e4160dd1ebb2ab91436ba9d3bdcd8 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Mon, 13 Mar 2023 17:27:32 +0000 Subject: [PATCH 1/9] initial v1 impl --- CMakeLists.txt | 1 + Makefile | 12 +- src/helpers/WLClasses.hpp | 3 + src/managers/ProtocolManager.cpp | 1 + src/managers/ProtocolManager.hpp | 2 + src/managers/input/InputMethodRelay.cpp | 65 +++++--- src/managers/input/InputMethodRelay.hpp | 8 +- src/protocols/TextInputV1.cpp | 203 ++++++++++++++++++++++++ src/protocols/TextInputV1.hpp | 68 ++++++++ 9 files changed, 340 insertions(+), 23 deletions(-) create mode 100644 src/protocols/TextInputV1.cpp create mode 100644 src/protocols/TextInputV1.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index a5ea06a68d3..d7e8930b3ed 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -140,5 +140,6 @@ target_link_libraries(Hyprland ${CMAKE_SOURCE_DIR}/wlr-foreign-toplevel-management-unstable-v1-protocol.o ${CMAKE_SOURCE_DIR}/hyprland-toplevel-export-v1-protocol.o ${CMAKE_SOURCE_DIR}/fractional-scale-v1-protocol.o + ${CMAKE_SOURCE_DIR}/text-input-v1-protocol.o ${CMAKE_SOURCE_DIR}/subprojects/udis86/build/libudis86/liblibudis86.a ) diff --git a/Makefile b/Makefile index 12613b273d0..efa083146e0 100644 --- a/Makefile +++ b/Makefile @@ -131,6 +131,16 @@ fractional-scale-v1-protocol.c: fractional-scale-v1-protocol.o: fractional-scale-v1-protocol.h +text-input-v1-protocol.h: + $(WAYLAND_SCANNER) server-header \ + $(WAYLAND_PROTOCOLS)/unstable/text-input/text-input-unstable-v1.xml $@ + +text-input-v1-protocol.c: + $(WAYLAND_SCANNER) private-code \ + $(WAYLAND_PROTOCOLS)/unstable/text-input/text-input-unstable-v1.xml $@ + +text-input-v1-protocol.o: text-input-v1-protocol.h + legacyrenderer: mkdir -p build && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DLEGACY_RENDERER:STRING=true -H./ -B./build -G Ninja cmake --build ./build --config Release --target all -j$(shell nproc) @@ -196,7 +206,7 @@ uninstall: rm -f ${PREFIX}/share/man/man1/Hyprland.1 rm -f ${PREFIX}/share/man/man1/hyprctl.1 -protocols: xdg-shell-protocol.o wlr-layer-shell-unstable-v1-protocol.o wlr-screencopy-unstable-v1-protocol.o idle-protocol.o ext-workspace-unstable-v1-protocol.o pointer-constraints-unstable-v1-protocol.o tablet-unstable-v2-protocol.o wlr-output-power-management-unstable-v1-protocol.o linux-dmabuf-unstable-v1-protocol.o hyprland-toplevel-export-v1-protocol.o wlr-foreign-toplevel-management-unstable-v1-protocol.o fractional-scale-v1-protocol.o +protocols: xdg-shell-protocol.o wlr-layer-shell-unstable-v1-protocol.o wlr-screencopy-unstable-v1-protocol.o idle-protocol.o ext-workspace-unstable-v1-protocol.o pointer-constraints-unstable-v1-protocol.o tablet-unstable-v2-protocol.o wlr-output-power-management-unstable-v1-protocol.o linux-dmabuf-unstable-v1-protocol.o hyprland-toplevel-export-v1-protocol.o wlr-foreign-toplevel-management-unstable-v1-protocol.o fractional-scale-v1-protocol.o text-input-v1-protocol.o fixwlr: sed -i -E 's/(soversion = 12)([^032]|$$)/soversion = 12032/g' subprojects/wlroots/meson.build diff --git a/src/helpers/WLClasses.hpp b/src/helpers/WLClasses.hpp index 15646c30ef4..8a96c6ff865 100644 --- a/src/helpers/WLClasses.hpp +++ b/src/helpers/WLClasses.hpp @@ -297,8 +297,11 @@ struct SSwipeGesture { CMonitor* pMonitor = nullptr; }; +struct STextInputV1; + struct STextInput { wlr_text_input_v3* pWlrInput = nullptr; + STextInputV1* pV1Input = nullptr; wlr_surface* pPendingSurface = nullptr; diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index 4dd9ed79a5c..6271b0ca363 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -3,4 +3,5 @@ CProtocolManager::CProtocolManager() { m_pToplevelExportProtocolManager = std::make_unique(); m_pFractionalScaleProtocolManager = std::make_unique(); + m_pTextInputV1ProtocolManager = std::make_unique(); } \ No newline at end of file diff --git a/src/managers/ProtocolManager.hpp b/src/managers/ProtocolManager.hpp index 66d8ef2045b..6160176d881 100644 --- a/src/managers/ProtocolManager.hpp +++ b/src/managers/ProtocolManager.hpp @@ -3,6 +3,7 @@ #include "../defines.hpp" #include "../protocols/ToplevelExport.hpp" #include "../protocols/FractionalScale.hpp" +#include "../protocols/TextInputV1.hpp" class CProtocolManager { public: @@ -10,6 +11,7 @@ class CProtocolManager { std::unique_ptr m_pToplevelExportProtocolManager; std::unique_ptr m_pFractionalScaleProtocolManager; + std::unique_ptr m_pTextInputV1ProtocolManager; }; inline std::unique_ptr g_pProtocolManager; diff --git a/src/managers/input/InputMethodRelay.cpp b/src/managers/input/InputMethodRelay.cpp index 95f0b6fbcac..3583ca12e9e 100644 --- a/src/managers/input/InputMethodRelay.cpp +++ b/src/managers/input/InputMethodRelay.cpp @@ -302,10 +302,14 @@ void CInputMethodRelay::onNewTextInput(wlr_text_input_v3* pInput) { createNewTextInput(pInput); } -void CInputMethodRelay::createNewTextInput(wlr_text_input_v3* pInput) { +void CInputMethodRelay::createNewTextInput(wlr_text_input_v3* pInput, STextInputV1* pTIV1) { const auto PTEXTINPUT = &m_lTextInputs.emplace_back(); PTEXTINPUT->pWlrInput = pInput; + PTEXTINPUT->pV1Input = pTIV1; + + if (pTIV1) + pTIV1->pTextInput = PTEXTINPUT; PTEXTINPUT->hyprListener_textInputEnable.initCallback( &pInput->events.enable, @@ -320,7 +324,7 @@ void CInputMethodRelay::createNewTextInput(wlr_text_input_v3* pInput) { Debug::log(LOG, "Enable TextInput"); wlr_input_method_v2_send_activate(g_pInputManager->m_sIMERelay.m_pWLRIME); - g_pInputManager->m_sIMERelay.commitIMEState(PINPUT->pWlrInput); + g_pInputManager->m_sIMERelay.commitIMEState(PINPUT); }, PTEXTINPUT, "textInput"); @@ -339,7 +343,7 @@ void CInputMethodRelay::createNewTextInput(wlr_text_input_v3* pInput) { return; } - g_pInputManager->m_sIMERelay.commitIMEState(PINPUT->pWlrInput); + g_pInputManager->m_sIMERelay.commitIMEState(PINPUT); }, PTEXTINPUT, "textInput"); @@ -357,7 +361,7 @@ void CInputMethodRelay::createNewTextInput(wlr_text_input_v3* pInput) { wlr_input_method_v2_send_deactivate(g_pInputManager->m_sIMERelay.m_pWLRIME); - g_pInputManager->m_sIMERelay.commitIMEState(PINPUT->pWlrInput); + g_pInputManager->m_sIMERelay.commitIMEState(PINPUT); }, PTEXTINPUT, "textInput"); @@ -374,7 +378,7 @@ void CInputMethodRelay::createNewTextInput(wlr_text_input_v3* pInput) { if (PINPUT->pWlrInput->current_enabled) { wlr_input_method_v2_send_deactivate(g_pInputManager->m_sIMERelay.m_pWLRIME); - g_pInputManager->m_sIMERelay.commitIMEState(PINPUT->pWlrInput); + g_pInputManager->m_sIMERelay.commitIMEState(PINPUT); } g_pInputManager->m_sIMERelay.setPendingSurface(PINPUT, nullptr); @@ -384,26 +388,40 @@ void CInputMethodRelay::createNewTextInput(wlr_text_input_v3* pInput) { PINPUT->hyprListener_textInputDisable.removeCallback(); PINPUT->hyprListener_textInputEnable.removeCallback(); - g_pInputManager->m_sIMERelay.removeTextInput(PINPUT->pWlrInput); + g_pInputManager->m_sIMERelay.removeTextInput(PINPUT); }, PTEXTINPUT, "textInput"); } -void CInputMethodRelay::removeTextInput(wlr_text_input_v3* pInput) { - m_lTextInputs.remove_if([&](const auto& other) { return other.pWlrInput == pInput; }); +void CInputMethodRelay::removeTextInput(STextInput* pInput) { + m_lTextInputs.remove_if([&](const auto& other) { return other.pWlrInput == pInput->pWlrInput && other.pV1Input == pInput->pV1Input; }); } -void CInputMethodRelay::commitIMEState(wlr_text_input_v3* pInput) { +void CInputMethodRelay::commitIMEState(STextInput* pInput) { if (!m_pWLRIME) return; - if (pInput->active_features & WLR_TEXT_INPUT_V3_FEATURE_SURROUNDING_TEXT) - wlr_input_method_v2_send_surrounding_text(m_pWLRIME, pInput->current.surrounding.text, pInput->current.surrounding.cursor, pInput->current.surrounding.anchor); + if (pInput->pWlrInput) { + // V3 + if (pInput->pWlrInput->active_features & WLR_TEXT_INPUT_V3_FEATURE_SURROUNDING_TEXT) + wlr_input_method_v2_send_surrounding_text(m_pWLRIME, pInput->pWlrInput->current.surrounding.text, pInput->pWlrInput->current.surrounding.cursor, + pInput->pWlrInput->current.surrounding.anchor); + + wlr_input_method_v2_send_text_change_cause(m_pWLRIME, pInput->pWlrInput->current.text_change_cause); + + if (pInput->pWlrInput->active_features & WLR_TEXT_INPUT_V3_FEATURE_CONTENT_TYPE) + wlr_input_method_v2_send_content_type(m_pWLRIME, pInput->pWlrInput->current.content_type.hint, pInput->pWlrInput->current.content_type.purpose); + } else { + // V1 + if (pInput->pV1Input->pendingSurrounding.isPending) + wlr_input_method_v2_send_surrounding_text(m_pWLRIME, pInput->pV1Input->pendingSurrounding.text.c_str(), pInput->pV1Input->pendingSurrounding.cursor, + pInput->pV1Input->pendingSurrounding.anchor); - wlr_input_method_v2_send_text_change_cause(m_pWLRIME, pInput->current.text_change_cause); + wlr_input_method_v2_send_text_change_cause(m_pWLRIME, 0); - if (pInput->active_features & WLR_TEXT_INPUT_V3_FEATURE_CONTENT_TYPE) - wlr_input_method_v2_send_content_type(m_pWLRIME, pInput->current.content_type.hint, pInput->current.content_type.purpose); + if (pInput->pV1Input->pendingContentType.isPending) + wlr_input_method_v2_send_content_type(m_pWLRIME, pInput->pV1Input->pendingContentType.hint, pInput->pV1Input->pendingContentType.purpose); + } for (auto& p : m_lIMEPopups) { updateInputPopup(&p); @@ -416,6 +434,9 @@ void CInputMethodRelay::onKeyboardFocus(wlr_surface* pSurface) { if (!m_pWLRIME) return; + auto focusedSurface = [](STextInput* pTI) -> wlr_surface* { return pTI->pWlrInput ? pTI->pWlrInput->focused_surface : pTI->pV1Input->focusedSurface; }; + auto client = [](STextInput* pTI) -> wl_client* { return pTI->pWlrInput ? wl_resource_get_client(pTI->pWlrInput->resource) : pTI->pV1Input->client; }; + for (auto& ti : m_lTextInputs) { if (ti.pPendingSurface) { @@ -424,20 +445,26 @@ void CInputMethodRelay::onKeyboardFocus(wlr_surface* pSurface) { } else if (ti.pWlrInput->focused_surface) { - if (pSurface != ti.pWlrInput->focused_surface) { + if (pSurface != focusedSurface(&ti)) { wlr_input_method_v2_send_deactivate(m_pWLRIME); - commitIMEState(ti.pWlrInput); + commitIMEState(&ti); - wlr_text_input_v3_send_leave(ti.pWlrInput); + if (ti.pWlrInput) + wlr_text_input_v3_send_leave(ti.pWlrInput); + else + zwp_text_input_v1_send_leave(ti.pV1Input->resourceImpl); } else { continue; } } - if (pSurface && wl_resource_get_client(ti.pWlrInput->resource) == wl_resource_get_client(pSurface->resource)) { + if (pSurface && client(&ti) == wl_resource_get_client(pSurface->resource)) { if (m_pWLRIME) { - wlr_text_input_v3_send_enter(ti.pWlrInput, pSurface); + if (ti.pWlrInput) + wlr_text_input_v3_send_enter(ti.pWlrInput, pSurface); + else + zwp_text_input_v1_send_enter(ti.pV1Input->resourceImpl, pSurface->resource); } else { setPendingSurface(&ti, pSurface); } diff --git a/src/managers/input/InputMethodRelay.hpp b/src/managers/input/InputMethodRelay.hpp index 767464875d5..e781298c4c8 100644 --- a/src/managers/input/InputMethodRelay.hpp +++ b/src/managers/input/InputMethodRelay.hpp @@ -4,6 +4,7 @@ #include "../../helpers/WLClasses.hpp" class CInputManager; +struct STextInputV1; class CInputMethodRelay { public: @@ -14,8 +15,8 @@ class CInputMethodRelay { wlr_input_method_v2* m_pWLRIME = nullptr; - void commitIMEState(wlr_text_input_v3*); - void removeTextInput(wlr_text_input_v3*); + void commitIMEState(STextInput* pInput); + void removeTextInput(STextInput* pInput); void onKeyboardFocus(wlr_surface*); @@ -43,8 +44,9 @@ class CInputMethodRelay { DYNLISTENER(IMEGrab); DYNLISTENER(IMENewPopup); - void createNewTextInput(wlr_text_input_v3*); + void createNewTextInput(wlr_text_input_v3*, STextInputV1* tiv1 = nullptr); friend class CHyprRenderer; friend class CInputManager; + friend class CTextInputV1ProtocolManager; }; \ No newline at end of file diff --git a/src/protocols/TextInputV1.cpp b/src/protocols/TextInputV1.cpp new file mode 100644 index 00000000000..a1b84662814 --- /dev/null +++ b/src/protocols/TextInputV1.cpp @@ -0,0 +1,203 @@ +#include "TextInputV1.hpp" + +#include "../Compositor.hpp" + +#define TEXT_INPUT_VERSION 1 + +static void bindManagerInt(wl_client* client, void* data, uint32_t version, uint32_t id) { + g_pProtocolManager->m_pFractionalScaleProtocolManager->bindManager(client, data, version, id); +} + +static void handleDisplayDestroy(struct wl_listener* listener, void* data) { + g_pProtocolManager->m_pFractionalScaleProtocolManager->displayDestroy(); +} + +void CTextInputV1ProtocolManager::displayDestroy() { + wl_global_destroy(m_pGlobal); +} + +CTextInputV1ProtocolManager::CTextInputV1ProtocolManager() { + m_pGlobal = wl_global_create(g_pCompositor->m_sWLDisplay, &zwp_text_input_manager_v1_interface, TEXT_INPUT_VERSION, this, bindManagerInt); + + if (!m_pGlobal) { + Debug::log(ERR, "TextInputV1Manager could not start!"); + return; + } + + m_liDisplayDestroy.notify = handleDisplayDestroy; + wl_display_add_destroy_listener(g_pCompositor->m_sWLDisplay, &m_liDisplayDestroy); + + Debug::log(LOG, "TextInputV1Manager started successfully!"); +} + +static void createTI(wl_client* client, wl_resource* resource, uint32_t id) { + g_pProtocolManager->m_pTextInputV1ProtocolManager->createTI(client, resource, id); +} + +static const struct zwp_text_input_manager_v1_interface textInputManagerImpl = { + .create_text_input = &createTI, +}; + +void CTextInputV1ProtocolManager::bindManager(wl_client* client, void* data, uint32_t version, uint32_t id) { + const auto RESOURCE = wl_resource_create(client, &zwp_text_input_manager_v1_interface, version, id); + wl_resource_set_implementation(RESOURCE, &textInputManagerImpl, this, nullptr); + + Debug::log(LOG, "TextInputV1Manager bound successfully!"); +} + +// + +void handleActivate(wl_client* client, wl_resource* resource, wl_resource* seat, wl_resource* surface) { + g_pProtocolManager->m_pTextInputV1ProtocolManager->handleActivate(client, resource, seat, surface); +} + +void handleDeactivate(wl_client* client, wl_resource* resource, wl_resource* seat) { + g_pProtocolManager->m_pTextInputV1ProtocolManager->handleDeactivate(client, resource, seat); +} + +void handleShowInputPanel(wl_client* client, wl_resource* resource) { + g_pProtocolManager->m_pTextInputV1ProtocolManager->handleShowInputPanel(client, resource); +} + +void handleHideInputPanel(wl_client* client, wl_resource* resource) { + g_pProtocolManager->m_pTextInputV1ProtocolManager->handleHideInputPanel(client, resource); +} + +void handleReset(wl_client* client, wl_resource* resource) { + g_pProtocolManager->m_pTextInputV1ProtocolManager->handleReset(client, resource); +} + +void handleSetSurroundingText(wl_client* client, wl_resource* resource, const char* text, uint32_t cursor, uint32_t anchor) { + g_pProtocolManager->m_pTextInputV1ProtocolManager->handleSetSurroundingText(client, resource, text, cursor, anchor); +} + +void handleSetContentType(wl_client* client, wl_resource* resource, uint32_t hint, uint32_t purpose) { + g_pProtocolManager->m_pTextInputV1ProtocolManager->handleSetContentType(client, resource, hint, purpose); +} + +void handleSetCursorRectangle(wl_client* client, wl_resource* resource, int32_t x, int32_t y, int32_t width, int32_t height) { + g_pProtocolManager->m_pTextInputV1ProtocolManager->handleSetCursorRectangle(client, resource, x, y, width, height); +} + +void handleSetPreferredLanguage(wl_client* client, wl_resource* resource, const char* language) { + g_pProtocolManager->m_pTextInputV1ProtocolManager->handleSetPreferredLanguage(client, resource, language); +} + +void handleCommitState(wl_client* client, wl_resource* resource, uint32_t serial) { + g_pProtocolManager->m_pTextInputV1ProtocolManager->handleCommitState(client, resource, serial); +} + +void handleInvokeAction(wl_client* client, wl_resource* resource, uint32_t button, uint32_t index) { + g_pProtocolManager->m_pTextInputV1ProtocolManager->handleInvokeAction(client, resource, button, index); +} + +static const struct zwp_text_input_v1_interface textInputImpl = { + .activate = &handleActivate, + .deactivate = &handleDeactivate, + .show_input_panel = &handleShowInputPanel, + .hide_input_panel = &handleHideInputPanel, + .reset = &handleReset, + .set_surrounding_text = &handleSetSurroundingText, + .set_content_type = &handleSetContentType, + .set_cursor_rectangle = &handleSetCursorRectangle, + .set_preferred_language = &handleSetPreferredLanguage, + .commit_state = &handleCommitState, + .invoke_action = &handleInvokeAction, +}; + +void CTextInputV1ProtocolManager::removeTI(STextInputV1* pTI) { + const auto TI = std::find_if(m_pClients.begin(), m_pClients.end(), [&](const auto& other) { return other->resourceCaller == pTI->resourceCaller; }); + if (TI == m_pClients.end()) + return; + + if ((*TI)->resourceImpl) + wl_resource_destroy((*TI)->resourceImpl); + + std::erase_if(m_pClients, [&](const auto& other) { return other.get() == pTI; }); +} + +STextInputV1* tiFromResource(wl_resource* resource) { + ASSERT(wl_resource_instance_of(resource, &zwp_text_input_v1_interface, &textInputImpl)); + return (STextInputV1*)wl_resource_get_user_data(resource); +} + +static void destroyTI(wl_resource* resource) { + const auto TI = tiFromResource(resource); + + if (TI->resourceImpl) { + wl_resource_set_user_data(resource, nullptr); + } + + TI->pTextInput->hyprListener_textInputDestroy.emit(nullptr); + + g_pProtocolManager->m_pTextInputV1ProtocolManager->removeTI(TI); +} + +void CTextInputV1ProtocolManager::createTI(wl_client* client, wl_resource* resource, uint32_t id) { + const auto PTI = m_pClients.emplace_back(std::make_unique()).get(); + Debug::log(LOG, "New TI V1 at %x", PTI); + + PTI->client = client; + PTI->resourceCaller = resource; + PTI->resourceImpl = wl_resource_create(client, &zwp_text_input_v1_interface, TEXT_INPUT_VERSION, id); + + if (!PTI->resourceImpl) { + Debug::log(ERR, "Could not alloc wl_resource for TIV1"); + removeTI(PTI); + return; + } + + wl_resource_set_implementation(PTI->resourceImpl, &textInputImpl, PTI, &destroyTI); +} + +void CTextInputV1ProtocolManager::handleActivate(wl_client* client, wl_resource* resource, wl_resource* seat, wl_resource* surface) { + const auto PTI = tiFromResource(resource); + PTI->pTextInput->hyprListener_textInputEnable.emit(nullptr); +} + +void CTextInputV1ProtocolManager::handleDeactivate(wl_client* client, wl_resource* resource, wl_resource* seat) { + const auto PTI = tiFromResource(resource); + PTI->pTextInput->hyprListener_textInputDisable.emit(nullptr); +} + +void CTextInputV1ProtocolManager::handleShowInputPanel(wl_client* client, wl_resource* resource) { + ; +} + +void CTextInputV1ProtocolManager::handleHideInputPanel(wl_client* client, wl_resource* resource) { + ; +} + +void CTextInputV1ProtocolManager::handleReset(wl_client* client, wl_resource* resource) { + const auto PTI = tiFromResource(resource); + PTI->pendingSurrounding.isPending = false; +} + +void CTextInputV1ProtocolManager::handleSetSurroundingText(wl_client* client, wl_resource* resource, const char* text, uint32_t cursor, uint32_t anchor) { + const auto PTI = tiFromResource(resource); + PTI->pendingSurrounding = {true, std::string(text), cursor, anchor}; +} + +void CTextInputV1ProtocolManager::handleSetContentType(wl_client* client, wl_resource* resource, uint32_t hint, uint32_t purpose) { + const auto PTI = tiFromResource(resource); + PTI->pendingContentType = {true, hint == ZWP_TEXT_INPUT_V1_CONTENT_HINT_DEFAULT ? ZWP_TEXT_INPUT_V1_CONTENT_HINT_NONE : hint, + purpose > ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_PASSWORD ? hint + 1 : hint}; +} + +void CTextInputV1ProtocolManager::handleSetCursorRectangle(wl_client* client, wl_resource* resource, int32_t x, int32_t y, int32_t width, int32_t height) { + const auto PTI = tiFromResource(resource); + PTI->cursorRectangle = wlr_box{x, y, width, height}; +} + +void CTextInputV1ProtocolManager::handleSetPreferredLanguage(wl_client* client, wl_resource* resource, const char* language) { + ; +} + +void CTextInputV1ProtocolManager::handleCommitState(wl_client* client, wl_resource* resource, uint32_t serial) { + const auto PTI = tiFromResource(resource); + PTI->pTextInput->hyprListener_textInputCommit.emit(nullptr); +} + +void CTextInputV1ProtocolManager::handleInvokeAction(wl_client* client, wl_resource* resource, uint32_t button, uint32_t index) { + ; +} \ No newline at end of file diff --git a/src/protocols/TextInputV1.hpp b/src/protocols/TextInputV1.hpp new file mode 100644 index 00000000000..3b54fd5feb0 --- /dev/null +++ b/src/protocols/TextInputV1.hpp @@ -0,0 +1,68 @@ +#pragma once + +#include "../defines.hpp" +#include "text-input-v1-protocol.h" + +#include + +struct STextInput; + +struct STextInputV1 { + wl_client* client = nullptr; + wl_resource* resourceCaller = nullptr; + + wl_resource* resourceImpl = nullptr; + + wlr_surface* focusedSurface = nullptr; + + STextInput* pTextInput = nullptr; + + struct SPendingSurr { + bool isPending = false; + std::string text = ""; + uint32_t cursor = 0; + uint32_t anchor = 0; + } pendingSurrounding; + + struct SPendingCT { + bool isPending = false; + uint32_t hint = 0; + uint32_t purpose = 0; + } pendingContentType; + + wlr_box cursorRectangle = {0, 0, 0, 0}; + + bool operator==(const STextInputV1& other) { + return other.client == client && other.resourceCaller == resourceCaller && other.resourceImpl == resourceImpl; + } +}; + +class CTextInputV1ProtocolManager { + public: + CTextInputV1ProtocolManager(); + + void bindManager(wl_client* client, void* data, uint32_t version, uint32_t id); + void createTI(wl_client* client, wl_resource* resource, uint32_t id); + void removeTI(STextInputV1* pTI); + + void displayDestroy(); + + // handlers for tiv1 + void handleActivate(wl_client* client, wl_resource* resource, wl_resource* seat, wl_resource* surface); + void handleDeactivate(wl_client* client, wl_resource* resource, wl_resource* seat); + void handleShowInputPanel(wl_client* client, wl_resource* resource); + void handleHideInputPanel(wl_client* client, wl_resource* resource); + void handleReset(wl_client* client, wl_resource* resource); + void handleSetSurroundingText(wl_client* client, wl_resource* resource, const char* text, uint32_t cursor, uint32_t anchor); + void handleSetContentType(wl_client* client, wl_resource* resource, uint32_t hint, uint32_t purpose); + void handleSetCursorRectangle(wl_client* client, wl_resource* resource, int32_t x, int32_t y, int32_t width, int32_t height); + void handleSetPreferredLanguage(wl_client* client, wl_resource* resource, const char* language); + void handleCommitState(wl_client* client, wl_resource* resource, uint32_t serial); + void handleInvokeAction(wl_client* client, wl_resource* resource, uint32_t button, uint32_t index); + + private: + wl_global* m_pGlobal = nullptr; + wl_listener m_liDisplayDestroy; + + std::vector> m_pClients; +}; \ No newline at end of file From be9bfedc26f6155a0e7c4806b666546cceb94edd Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Mon, 13 Mar 2023 18:00:59 +0000 Subject: [PATCH 2/9] fix typo --- src/protocols/TextInputV1.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/protocols/TextInputV1.cpp b/src/protocols/TextInputV1.cpp index a1b84662814..3518ebc7135 100644 --- a/src/protocols/TextInputV1.cpp +++ b/src/protocols/TextInputV1.cpp @@ -5,11 +5,11 @@ #define TEXT_INPUT_VERSION 1 static void bindManagerInt(wl_client* client, void* data, uint32_t version, uint32_t id) { - g_pProtocolManager->m_pFractionalScaleProtocolManager->bindManager(client, data, version, id); + g_pProtocolManager->m_pTextInputV1ProtocolManager->bindManager(client, data, version, id); } static void handleDisplayDestroy(struct wl_listener* listener, void* data) { - g_pProtocolManager->m_pFractionalScaleProtocolManager->displayDestroy(); + g_pProtocolManager->m_pTextInputV1ProtocolManager->displayDestroy(); } void CTextInputV1ProtocolManager::displayDestroy() { From 05fab111f589a2cb5f2ba27b3b8fc001e510cf29 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Mon, 13 Mar 2023 18:20:29 +0000 Subject: [PATCH 3/9] fix typos --- src/protocols/TextInputV1.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/protocols/TextInputV1.cpp b/src/protocols/TextInputV1.cpp index 3518ebc7135..6ada544ef27 100644 --- a/src/protocols/TextInputV1.cpp +++ b/src/protocols/TextInputV1.cpp @@ -35,7 +35,7 @@ static void createTI(wl_client* client, wl_resource* resource, uint32_t id) { } static const struct zwp_text_input_manager_v1_interface textInputManagerImpl = { - .create_text_input = &createTI, + .create_text_input = createTI, }; void CTextInputV1ProtocolManager::bindManager(wl_client* client, void* data, uint32_t version, uint32_t id) { @@ -92,17 +92,17 @@ void handleInvokeAction(wl_client* client, wl_resource* resource, uint32_t butto } static const struct zwp_text_input_v1_interface textInputImpl = { - .activate = &handleActivate, - .deactivate = &handleDeactivate, - .show_input_panel = &handleShowInputPanel, - .hide_input_panel = &handleHideInputPanel, - .reset = &handleReset, - .set_surrounding_text = &handleSetSurroundingText, - .set_content_type = &handleSetContentType, - .set_cursor_rectangle = &handleSetCursorRectangle, - .set_preferred_language = &handleSetPreferredLanguage, - .commit_state = &handleCommitState, - .invoke_action = &handleInvokeAction, + .activate = handleActivate, + .deactivate = handleDeactivate, + .show_input_panel = handleShowInputPanel, + .hide_input_panel = handleHideInputPanel, + .reset = handleReset, + .set_surrounding_text = handleSetSurroundingText, + .set_content_type = handleSetContentType, + .set_cursor_rectangle = handleSetCursorRectangle, + .set_preferred_language = handleSetPreferredLanguage, + .commit_state = handleCommitState, + .invoke_action = handleInvokeAction, }; void CTextInputV1ProtocolManager::removeTI(STextInputV1* pTI) { From d3157ceb5066e699ae0074eac68c60be3b8ab39b Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Mon, 13 Mar 2023 18:35:11 +0000 Subject: [PATCH 4/9] staticify internal funcs --- src/managers/input/InputMethodRelay.cpp | 2 +- src/protocols/TextInputV1.cpp | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/managers/input/InputMethodRelay.cpp b/src/managers/input/InputMethodRelay.cpp index 3583ca12e9e..c64aad8e063 100644 --- a/src/managers/input/InputMethodRelay.cpp +++ b/src/managers/input/InputMethodRelay.cpp @@ -375,7 +375,7 @@ void CInputMethodRelay::createNewTextInput(wlr_text_input_v3* pInput, STextInput return; } - if (PINPUT->pWlrInput->current_enabled) { + if (PINPUT->pWlrInput && PINPUT->pWlrInput->current_enabled) { wlr_input_method_v2_send_deactivate(g_pInputManager->m_sIMERelay.m_pWLRIME); g_pInputManager->m_sIMERelay.commitIMEState(PINPUT); diff --git a/src/protocols/TextInputV1.cpp b/src/protocols/TextInputV1.cpp index 6ada544ef27..0cc3108cb02 100644 --- a/src/protocols/TextInputV1.cpp +++ b/src/protocols/TextInputV1.cpp @@ -47,47 +47,47 @@ void CTextInputV1ProtocolManager::bindManager(wl_client* client, void* data, uin // -void handleActivate(wl_client* client, wl_resource* resource, wl_resource* seat, wl_resource* surface) { +static void handleActivate(wl_client* client, wl_resource* resource, wl_resource* seat, wl_resource* surface) { g_pProtocolManager->m_pTextInputV1ProtocolManager->handleActivate(client, resource, seat, surface); } -void handleDeactivate(wl_client* client, wl_resource* resource, wl_resource* seat) { +static void handleDeactivate(wl_client* client, wl_resource* resource, wl_resource* seat) { g_pProtocolManager->m_pTextInputV1ProtocolManager->handleDeactivate(client, resource, seat); } -void handleShowInputPanel(wl_client* client, wl_resource* resource) { +static void handleShowInputPanel(wl_client* client, wl_resource* resource) { g_pProtocolManager->m_pTextInputV1ProtocolManager->handleShowInputPanel(client, resource); } -void handleHideInputPanel(wl_client* client, wl_resource* resource) { +static void handleHideInputPanel(wl_client* client, wl_resource* resource) { g_pProtocolManager->m_pTextInputV1ProtocolManager->handleHideInputPanel(client, resource); } -void handleReset(wl_client* client, wl_resource* resource) { +static void handleReset(wl_client* client, wl_resource* resource) { g_pProtocolManager->m_pTextInputV1ProtocolManager->handleReset(client, resource); } -void handleSetSurroundingText(wl_client* client, wl_resource* resource, const char* text, uint32_t cursor, uint32_t anchor) { +static void handleSetSurroundingText(wl_client* client, wl_resource* resource, const char* text, uint32_t cursor, uint32_t anchor) { g_pProtocolManager->m_pTextInputV1ProtocolManager->handleSetSurroundingText(client, resource, text, cursor, anchor); } -void handleSetContentType(wl_client* client, wl_resource* resource, uint32_t hint, uint32_t purpose) { +static void handleSetContentType(wl_client* client, wl_resource* resource, uint32_t hint, uint32_t purpose) { g_pProtocolManager->m_pTextInputV1ProtocolManager->handleSetContentType(client, resource, hint, purpose); } -void handleSetCursorRectangle(wl_client* client, wl_resource* resource, int32_t x, int32_t y, int32_t width, int32_t height) { +static void handleSetCursorRectangle(wl_client* client, wl_resource* resource, int32_t x, int32_t y, int32_t width, int32_t height) { g_pProtocolManager->m_pTextInputV1ProtocolManager->handleSetCursorRectangle(client, resource, x, y, width, height); } -void handleSetPreferredLanguage(wl_client* client, wl_resource* resource, const char* language) { +static void handleSetPreferredLanguage(wl_client* client, wl_resource* resource, const char* language) { g_pProtocolManager->m_pTextInputV1ProtocolManager->handleSetPreferredLanguage(client, resource, language); } -void handleCommitState(wl_client* client, wl_resource* resource, uint32_t serial) { +static void handleCommitState(wl_client* client, wl_resource* resource, uint32_t serial) { g_pProtocolManager->m_pTextInputV1ProtocolManager->handleCommitState(client, resource, serial); } -void handleInvokeAction(wl_client* client, wl_resource* resource, uint32_t button, uint32_t index) { +static void handleInvokeAction(wl_client* client, wl_resource* resource, uint32_t button, uint32_t index) { g_pProtocolManager->m_pTextInputV1ProtocolManager->handleInvokeAction(client, resource, button, index); } From 94ba1713c457e11acb877df6c10b01fe4cd49252 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Mon, 13 Mar 2023 20:28:07 +0000 Subject: [PATCH 5/9] fixes --- src/managers/input/InputMethodRelay.cpp | 91 +++++++++++++++++-------- src/managers/input/InputMethodRelay.hpp | 3 +- src/protocols/TextInputV1.cpp | 16 ++++- src/protocols/TextInputV1.hpp | 7 ++ 4 files changed, 84 insertions(+), 33 deletions(-) diff --git a/src/managers/input/InputMethodRelay.cpp b/src/managers/input/InputMethodRelay.cpp index c64aad8e063..bb3e3efa4bc 100644 --- a/src/managers/input/InputMethodRelay.cpp +++ b/src/managers/input/InputMethodRelay.cpp @@ -28,20 +28,36 @@ void CInputMethodRelay::onNewIME(wlr_input_method_v2* pIME) { return; } - if (PIMR->m_pWLRIME->current.preedit.text) { - wlr_text_input_v3_send_preedit_string(PTI->pWlrInput, PIMR->m_pWLRIME->current.preedit.text, PIMR->m_pWLRIME->current.preedit.cursor_begin, - PIMR->m_pWLRIME->current.preedit.cursor_end); - } + if (PTI->pWlrInput) { + if (PIMR->m_pWLRIME->current.preedit.text) { + wlr_text_input_v3_send_preedit_string(PTI->pWlrInput, PIMR->m_pWLRIME->current.preedit.text, PIMR->m_pWLRIME->current.preedit.cursor_begin, + PIMR->m_pWLRIME->current.preedit.cursor_end); + } - if (PIMR->m_pWLRIME->current.commit_text) { - wlr_text_input_v3_send_commit_string(PTI->pWlrInput, PIMR->m_pWLRIME->current.commit_text); - } + if (PIMR->m_pWLRIME->current.commit_text) { + wlr_text_input_v3_send_commit_string(PTI->pWlrInput, PIMR->m_pWLRIME->current.commit_text); + } - if (PIMR->m_pWLRIME->current.delete_.before_length || PIMR->m_pWLRIME->current.delete_.after_length) { - wlr_text_input_v3_send_delete_surrounding_text(PTI->pWlrInput, PIMR->m_pWLRIME->current.delete_.before_length, PIMR->m_pWLRIME->current.delete_.after_length); - } + if (PIMR->m_pWLRIME->current.delete_.before_length || PIMR->m_pWLRIME->current.delete_.after_length) { + wlr_text_input_v3_send_delete_surrounding_text(PTI->pWlrInput, PIMR->m_pWLRIME->current.delete_.before_length, PIMR->m_pWLRIME->current.delete_.after_length); + } - wlr_text_input_v3_send_done(PTI->pWlrInput); + wlr_text_input_v3_send_done(PTI->pWlrInput); + } else { + if (PIMR->m_pWLRIME->current.preedit.text) { + zwp_text_input_v1_send_preedit_string(PTI->pV1Input->resourceImpl, PTI->pV1Input->serial, PIMR->m_pWLRIME->current.preedit.text, + PIMR->m_pWLRIME->current.preedit.text); + } + + if (PIMR->m_pWLRIME->current.commit_text) { + zwp_text_input_v1_send_commit_string(PTI->pV1Input->resourceImpl, PTI->pV1Input->serial, PIMR->m_pWLRIME->current.commit_text); + } + + if (PIMR->m_pWLRIME->current.delete_.before_length || PIMR->m_pWLRIME->current.delete_.after_length) { + zwp_text_input_v1_send_delete_surrounding_text(PTI->pV1Input->resourceImpl, PIMR->m_pWLRIME->current.delete_.before_length, + PIMR->m_pWLRIME->current.delete_.after_length); + } + } }, this, "IMERelay"); @@ -62,9 +78,12 @@ void CInputMethodRelay::onNewIME(wlr_input_method_v2* pIME) { Debug::log(LOG, "IME Destroy"); if (PTI) { - setPendingSurface(PTI, PTI->pWlrInput->focused_surface); + setPendingSurface(PTI, focusedSurface(PTI)); - wlr_text_input_v3_send_leave(PTI->pWlrInput); + if (PTI->pWlrInput) + wlr_text_input_v3_send_leave(PTI->pWlrInput); + else + zwp_text_input_v1_send_leave(PTI->pV1Input->resourceImpl); } }, this, "IMERelay"); @@ -122,11 +141,19 @@ void CInputMethodRelay::onNewIME(wlr_input_method_v2* pIME) { const auto PTI = getFocusableTextInput(); if (PTI) { - wlr_text_input_v3_send_enter(PTI->pWlrInput, PTI->pPendingSurface); + if (PTI->pWlrInput) + wlr_text_input_v3_send_enter(PTI->pWlrInput, PTI->pPendingSurface); + else + zwp_text_input_v1_send_enter(PTI->pV1Input->resourceImpl, PTI->pPendingSurface->resource); + setPendingSurface(PTI, nullptr); } } +wlr_surface* CInputMethodRelay::focusedSurface(STextInput* pTI) { + return pTI->pWlrInput ? pTI->pWlrInput->focused_surface : pTI->pV1Input->focusedSurface; +} + void CInputMethodRelay::updateInputPopup(SIMEPopup* pPopup) { if (!pPopup->pSurface->mapped) return; @@ -136,12 +163,12 @@ void CInputMethodRelay::updateInputPopup(SIMEPopup* pPopup) { const auto PFOCUSEDTI = getFocusedTextInput(); - if (!PFOCUSEDTI || !PFOCUSEDTI->pWlrInput->focused_surface) + if (!PFOCUSEDTI || !focusedSurface(PFOCUSEDTI)) return; - bool cursorRect = PFOCUSEDTI->pWlrInput->current.features & WLR_TEXT_INPUT_V3_FEATURE_CURSOR_RECTANGLE; - const auto PFOCUSEDSURFACE = PFOCUSEDTI->pWlrInput->focused_surface; - auto cursorBox = PFOCUSEDTI->pWlrInput->current.cursor_rectangle; + bool cursorRect = PFOCUSEDTI->pWlrInput ? PFOCUSEDTI->pWlrInput->current.features & WLR_TEXT_INPUT_V3_FEATURE_CURSOR_RECTANGLE : true; + const auto PFOCUSEDSURFACE = focusedSurface(PFOCUSEDTI); + auto cursorBox = PFOCUSEDTI->pWlrInput ? PFOCUSEDTI->pWlrInput->current.cursor_rectangle : PFOCUSEDTI->pV1Input->cursorRectangle; Vector2D parentPos; Vector2D parentSize; @@ -238,12 +265,12 @@ void CInputMethodRelay::damagePopup(SIMEPopup* pPopup) { const auto PFOCUSEDTI = getFocusedTextInput(); - if (!PFOCUSEDTI || !PFOCUSEDTI->pWlrInput->focused_surface) + if (!PFOCUSEDTI || !focusedSurface(PFOCUSEDTI)) return; Vector2D parentPos; - const auto PFOCUSEDSURFACE = PFOCUSEDTI->pWlrInput->focused_surface; + const auto PFOCUSEDSURFACE = focusedSurface(PFOCUSEDTI); 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)); @@ -279,8 +306,9 @@ SIMEKbGrab* CInputMethodRelay::getIMEKeyboardGrab(SKeyboard* pKeyboard) { } STextInput* CInputMethodRelay::getFocusedTextInput() { + for (auto& ti : m_lTextInputs) { - if (ti.pWlrInput->focused_surface) { + if (focusedSurface(&ti)) { return &ti; } } @@ -312,7 +340,7 @@ void CInputMethodRelay::createNewTextInput(wlr_text_input_v3* pInput, STextInput pTIV1->pTextInput = PTEXTINPUT; PTEXTINPUT->hyprListener_textInputEnable.initCallback( - &pInput->events.enable, + pInput ? &pInput->events.enable : &pTIV1->sEnable, [](void* owner, void* data) { const auto PINPUT = (STextInput*)owner; @@ -329,7 +357,7 @@ void CInputMethodRelay::createNewTextInput(wlr_text_input_v3* pInput, STextInput PTEXTINPUT, "textInput"); PTEXTINPUT->hyprListener_textInputCommit.initCallback( - &pInput->events.commit, + pInput ? &pInput->events.commit : &pTIV1->sCommit, [](void* owner, void* data) { const auto PINPUT = (STextInput*)owner; @@ -348,7 +376,7 @@ void CInputMethodRelay::createNewTextInput(wlr_text_input_v3* pInput, STextInput PTEXTINPUT, "textInput"); PTEXTINPUT->hyprListener_textInputDisable.initCallback( - &pInput->events.disable, + pInput ? &pInput->events.disable : &pTIV1->sDisable, [](void* owner, void* data) { const auto PINPUT = (STextInput*)owner; @@ -366,7 +394,7 @@ void CInputMethodRelay::createNewTextInput(wlr_text_input_v3* pInput, STextInput PTEXTINPUT, "textInput"); PTEXTINPUT->hyprListener_textInputDestroy.initCallback( - &pInput->events.destroy, + pInput ? &pInput->events.destroy : &pTIV1->sDestroy, [](void* owner, void* data) { const auto PINPUT = (STextInput*)owner; @@ -434,8 +462,7 @@ void CInputMethodRelay::onKeyboardFocus(wlr_surface* pSurface) { if (!m_pWLRIME) return; - auto focusedSurface = [](STextInput* pTI) -> wlr_surface* { return pTI->pWlrInput ? pTI->pWlrInput->focused_surface : pTI->pV1Input->focusedSurface; }; - auto client = [](STextInput* pTI) -> wl_client* { return pTI->pWlrInput ? wl_resource_get_client(pTI->pWlrInput->resource) : pTI->pV1Input->client; }; + auto client = [](STextInput* pTI) -> wl_client* { return pTI->pWlrInput ? wl_resource_get_client(pTI->pWlrInput->resource) : pTI->pV1Input->client; }; for (auto& ti : m_lTextInputs) { if (ti.pPendingSurface) { @@ -443,7 +470,7 @@ void CInputMethodRelay::onKeyboardFocus(wlr_surface* pSurface) { if (pSurface != ti.pPendingSurface) setPendingSurface(&ti, nullptr); - } else if (ti.pWlrInput->focused_surface) { + } else if (focusedSurface(&ti)) { if (pSurface != focusedSurface(&ti)) { wlr_input_method_v2_send_deactivate(m_pWLRIME); @@ -451,8 +478,10 @@ void CInputMethodRelay::onKeyboardFocus(wlr_surface* pSurface) { if (ti.pWlrInput) wlr_text_input_v3_send_leave(ti.pWlrInput); - else + else { zwp_text_input_v1_send_leave(ti.pV1Input->resourceImpl); + ti.pV1Input->focusedSurface = nullptr; + } } else { continue; } @@ -463,8 +492,10 @@ void CInputMethodRelay::onKeyboardFocus(wlr_surface* pSurface) { if (m_pWLRIME) { if (ti.pWlrInput) wlr_text_input_v3_send_enter(ti.pWlrInput, pSurface); - else + else { zwp_text_input_v1_send_enter(ti.pV1Input->resourceImpl, pSurface->resource); + ti.pV1Input->focusedSurface = pSurface; + } } else { setPendingSurface(&ti, pSurface); } diff --git a/src/managers/input/InputMethodRelay.hpp b/src/managers/input/InputMethodRelay.hpp index e781298c4c8..83332285291 100644 --- a/src/managers/input/InputMethodRelay.hpp +++ b/src/managers/input/InputMethodRelay.hpp @@ -44,7 +44,8 @@ class CInputMethodRelay { DYNLISTENER(IMEGrab); DYNLISTENER(IMENewPopup); - void createNewTextInput(wlr_text_input_v3*, STextInputV1* tiv1 = nullptr); + void createNewTextInput(wlr_text_input_v3*, STextInputV1* tiv1 = nullptr); + wlr_surface* focusedSurface(STextInput* pInput); friend class CHyprRenderer; friend class CInputManager; diff --git a/src/protocols/TextInputV1.cpp b/src/protocols/TextInputV1.cpp index 0cc3108cb02..4da7cd4f81c 100644 --- a/src/protocols/TextInputV1.cpp +++ b/src/protocols/TextInputV1.cpp @@ -110,8 +110,8 @@ void CTextInputV1ProtocolManager::removeTI(STextInputV1* pTI) { if (TI == m_pClients.end()) return; - if ((*TI)->resourceImpl) - wl_resource_destroy((*TI)->resourceImpl); + // if ((*TI)->resourceImpl) + // wl_resource_destroy((*TI)->resourceImpl); std::erase_if(m_pClients, [&](const auto& other) { return other.get() == pTI; }); } @@ -124,6 +124,9 @@ STextInputV1* tiFromResource(wl_resource* resource) { static void destroyTI(wl_resource* resource) { const auto TI = tiFromResource(resource); + if (!TI) + return; + if (TI->resourceImpl) { wl_resource_set_user_data(resource, nullptr); } @@ -148,6 +151,14 @@ void CTextInputV1ProtocolManager::createTI(wl_client* client, wl_resource* resou } wl_resource_set_implementation(PTI->resourceImpl, &textInputImpl, PTI, &destroyTI); + wl_resource_set_user_data(PTI->resourceImpl, PTI); + + wl_signal_init(&PTI->sEnable); + wl_signal_init(&PTI->sDisable); + wl_signal_init(&PTI->sDestroy); + wl_signal_init(&PTI->sCommit); + + g_pInputManager->m_sIMERelay.createNewTextInput(nullptr, PTI); } void CTextInputV1ProtocolManager::handleActivate(wl_client* client, wl_resource* resource, wl_resource* seat, wl_resource* surface) { @@ -195,6 +206,7 @@ void CTextInputV1ProtocolManager::handleSetPreferredLanguage(wl_client* client, void CTextInputV1ProtocolManager::handleCommitState(wl_client* client, wl_resource* resource, uint32_t serial) { const auto PTI = tiFromResource(resource); + PTI->serial = serial; PTI->pTextInput->hyprListener_textInputCommit.emit(nullptr); } diff --git a/src/protocols/TextInputV1.hpp b/src/protocols/TextInputV1.hpp index 3b54fd5feb0..ef0986a2ec5 100644 --- a/src/protocols/TextInputV1.hpp +++ b/src/protocols/TextInputV1.hpp @@ -17,6 +17,13 @@ struct STextInputV1 { STextInput* pTextInput = nullptr; + wl_signal sEnable; + wl_signal sDisable; + wl_signal sCommit; + wl_signal sDestroy; + + uint32_t serial = 0; + struct SPendingSurr { bool isPending = false; std::string text = ""; From 9d89b46ec3887273404f83e58e76c57035b30bd6 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Mon, 13 Mar 2023 20:41:41 +0000 Subject: [PATCH 6/9] fix some crashes --- src/managers/input/InputMethodRelay.cpp | 6 ++++-- src/protocols/TextInputV1.cpp | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/managers/input/InputMethodRelay.cpp b/src/managers/input/InputMethodRelay.cpp index bb3e3efa4bc..788020302c7 100644 --- a/src/managers/input/InputMethodRelay.cpp +++ b/src/managers/input/InputMethodRelay.cpp @@ -45,8 +45,10 @@ void CInputMethodRelay::onNewIME(wlr_input_method_v2* pIME) { wlr_text_input_v3_send_done(PTI->pWlrInput); } else { if (PIMR->m_pWLRIME->current.preedit.text) { - zwp_text_input_v1_send_preedit_string(PTI->pV1Input->resourceImpl, PTI->pV1Input->serial, PIMR->m_pWLRIME->current.preedit.text, - PIMR->m_pWLRIME->current.preedit.text); + zwp_text_input_v1_send_preedit_string(PTI->pV1Input->resourceImpl, PTI->pV1Input->serial, PIMR->m_pWLRIME->current.preedit.text, ""); + zwp_text_input_v1_send_preedit_cursor(PTI->pV1Input->resourceImpl, 0); + zwp_text_input_v1_send_preedit_styling(PTI->pV1Input->resourceImpl, 0, std::string(PIMR->m_pWLRIME->current.preedit.text).length() - 1, + ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_ACTIVE); } if (PIMR->m_pWLRIME->current.commit_text) { diff --git a/src/protocols/TextInputV1.cpp b/src/protocols/TextInputV1.cpp index 4da7cd4f81c..fa2dda5950a 100644 --- a/src/protocols/TextInputV1.cpp +++ b/src/protocols/TextInputV1.cpp @@ -182,6 +182,7 @@ void CTextInputV1ProtocolManager::handleHideInputPanel(wl_client* client, wl_res void CTextInputV1ProtocolManager::handleReset(wl_client* client, wl_resource* resource) { const auto PTI = tiFromResource(resource); PTI->pendingSurrounding.isPending = false; + PTI->pendingContentType.isPending = false; } void CTextInputV1ProtocolManager::handleSetSurroundingText(wl_client* client, wl_resource* resource, const char* text, uint32_t cursor, uint32_t anchor) { From 295bece15db5871e920af51ba6a6b2925e867d05 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Mon, 13 Mar 2023 23:10:38 +0200 Subject: [PATCH 7/9] text-input: fix protocol name & add to meson --- CMakeLists.txt | 2 +- Makefile | 8 ++++---- protocols/meson.build | 1 + src/protocols/TextInputV1.hpp | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d7e8930b3ed..9b3259505d1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -140,6 +140,6 @@ target_link_libraries(Hyprland ${CMAKE_SOURCE_DIR}/wlr-foreign-toplevel-management-unstable-v1-protocol.o ${CMAKE_SOURCE_DIR}/hyprland-toplevel-export-v1-protocol.o ${CMAKE_SOURCE_DIR}/fractional-scale-v1-protocol.o - ${CMAKE_SOURCE_DIR}/text-input-v1-protocol.o + ${CMAKE_SOURCE_DIR}/text-input-unstable-v1-protocol.o ${CMAKE_SOURCE_DIR}/subprojects/udis86/build/libudis86/liblibudis86.a ) diff --git a/Makefile b/Makefile index efa083146e0..4aaed5e9daa 100644 --- a/Makefile +++ b/Makefile @@ -131,15 +131,15 @@ fractional-scale-v1-protocol.c: fractional-scale-v1-protocol.o: fractional-scale-v1-protocol.h -text-input-v1-protocol.h: +text-input-unstable-v1-protocol.h: $(WAYLAND_SCANNER) server-header \ $(WAYLAND_PROTOCOLS)/unstable/text-input/text-input-unstable-v1.xml $@ -text-input-v1-protocol.c: +text-input-unstable-v1-protocol.c: $(WAYLAND_SCANNER) private-code \ $(WAYLAND_PROTOCOLS)/unstable/text-input/text-input-unstable-v1.xml $@ -text-input-v1-protocol.o: text-input-v1-protocol.h +text-input-unstable-v1-protocol.o: text-input-unstable-v1-protocol.h legacyrenderer: mkdir -p build && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DLEGACY_RENDERER:STRING=true -H./ -B./build -G Ninja @@ -206,7 +206,7 @@ uninstall: rm -f ${PREFIX}/share/man/man1/Hyprland.1 rm -f ${PREFIX}/share/man/man1/hyprctl.1 -protocols: xdg-shell-protocol.o wlr-layer-shell-unstable-v1-protocol.o wlr-screencopy-unstable-v1-protocol.o idle-protocol.o ext-workspace-unstable-v1-protocol.o pointer-constraints-unstable-v1-protocol.o tablet-unstable-v2-protocol.o wlr-output-power-management-unstable-v1-protocol.o linux-dmabuf-unstable-v1-protocol.o hyprland-toplevel-export-v1-protocol.o wlr-foreign-toplevel-management-unstable-v1-protocol.o fractional-scale-v1-protocol.o text-input-v1-protocol.o +protocols: xdg-shell-protocol.o wlr-layer-shell-unstable-v1-protocol.o wlr-screencopy-unstable-v1-protocol.o idle-protocol.o ext-workspace-unstable-v1-protocol.o pointer-constraints-unstable-v1-protocol.o tablet-unstable-v2-protocol.o wlr-output-power-management-unstable-v1-protocol.o linux-dmabuf-unstable-v1-protocol.o hyprland-toplevel-export-v1-protocol.o wlr-foreign-toplevel-management-unstable-v1-protocol.o fractional-scale-v1-protocol.o text-input-unstable-v1-protocol.o fixwlr: sed -i -E 's/(soversion = 12)([^032]|$$)/soversion = 12032/g' subprojects/wlroots/meson.build diff --git a/protocols/meson.build b/protocols/meson.build index 9d47e0a6041..47b2dcaeb8e 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -21,6 +21,7 @@ wayland_scanner = find_program( protocols = [ [wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'], [wl_protocol_dir, 'unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml'], + [wl_protocol_dir, 'unstable/text-input/text-input-unstable-v1.xml'], [wl_protocol_dir, 'staging/fractional-scale/fractional-scale-v1.xml'], ['wlr-foreign-toplevel-management-unstable-v1.xml'], ['wlr-layer-shell-unstable-v1.xml'], diff --git a/src/protocols/TextInputV1.hpp b/src/protocols/TextInputV1.hpp index ef0986a2ec5..9057e13267a 100644 --- a/src/protocols/TextInputV1.hpp +++ b/src/protocols/TextInputV1.hpp @@ -1,7 +1,7 @@ #pragma once #include "../defines.hpp" -#include "text-input-v1-protocol.h" +#include "text-input-unstable-v1-protocol.h" #include From a131212ec14cd525828076f054896ea874811801 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Mon, 13 Mar 2023 21:14:49 +0000 Subject: [PATCH 8/9] fix crashes --- src/managers/input/InputMethodRelay.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/managers/input/InputMethodRelay.cpp b/src/managers/input/InputMethodRelay.cpp index 788020302c7..f8fa6b0943e 100644 --- a/src/managers/input/InputMethodRelay.cpp +++ b/src/managers/input/InputMethodRelay.cpp @@ -45,10 +45,10 @@ void CInputMethodRelay::onNewIME(wlr_input_method_v2* pIME) { wlr_text_input_v3_send_done(PTI->pWlrInput); } else { if (PIMR->m_pWLRIME->current.preedit.text) { - zwp_text_input_v1_send_preedit_string(PTI->pV1Input->resourceImpl, PTI->pV1Input->serial, PIMR->m_pWLRIME->current.preedit.text, ""); zwp_text_input_v1_send_preedit_cursor(PTI->pV1Input->resourceImpl, 0); zwp_text_input_v1_send_preedit_styling(PTI->pV1Input->resourceImpl, 0, std::string(PIMR->m_pWLRIME->current.preedit.text).length() - 1, ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_ACTIVE); + zwp_text_input_v1_send_preedit_string(PTI->pV1Input->resourceImpl, PTI->pV1Input->serial, PIMR->m_pWLRIME->current.preedit.text, ""); } if (PIMR->m_pWLRIME->current.commit_text) { @@ -58,6 +58,9 @@ void CInputMethodRelay::onNewIME(wlr_input_method_v2* pIME) { if (PIMR->m_pWLRIME->current.delete_.before_length || PIMR->m_pWLRIME->current.delete_.after_length) { zwp_text_input_v1_send_delete_surrounding_text(PTI->pV1Input->resourceImpl, PIMR->m_pWLRIME->current.delete_.before_length, PIMR->m_pWLRIME->current.delete_.after_length); + + if (PIMR->m_pWLRIME->current.preedit.text) + zwp_text_input_v1_send_commit_string(PTI->pV1Input->resourceImpl, PTI->pV1Input->serial, PIMR->m_pWLRIME->current.preedit.text); } } }, From fafc743677005092c2a1ed18b9f968b90325d926 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Mon, 13 Mar 2023 21:18:36 +0000 Subject: [PATCH 9/9] fix warm --- src/protocols/TextInputV1.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/protocols/TextInputV1.cpp b/src/protocols/TextInputV1.cpp index fa2dda5950a..f50f3298042 100644 --- a/src/protocols/TextInputV1.cpp +++ b/src/protocols/TextInputV1.cpp @@ -192,8 +192,8 @@ void CTextInputV1ProtocolManager::handleSetSurroundingText(wl_client* client, wl void CTextInputV1ProtocolManager::handleSetContentType(wl_client* client, wl_resource* resource, uint32_t hint, uint32_t purpose) { const auto PTI = tiFromResource(resource); - PTI->pendingContentType = {true, hint == ZWP_TEXT_INPUT_V1_CONTENT_HINT_DEFAULT ? ZWP_TEXT_INPUT_V1_CONTENT_HINT_NONE : hint, - purpose > ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_PASSWORD ? hint + 1 : hint}; + PTI->pendingContentType = {true, hint == (uint32_t)ZWP_TEXT_INPUT_V1_CONTENT_HINT_DEFAULT ? (uint32_t)ZWP_TEXT_INPUT_V1_CONTENT_HINT_NONE : hint, + purpose > (uint32_t)ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_PASSWORD ? hint + 1 : hint}; } void CTextInputV1ProtocolManager::handleSetCursorRectangle(wl_client* client, wl_resource* resource, int32_t x, int32_t y, int32_t width, int32_t height) {