diff options
-rw-r--r-- | CMakeLists.txt | 5 | ||||
-rw-r--r-- | protocols/meson.build | 2 | ||||
-rw-r--r-- | src/managers/ProtocolManager.cpp | 4 | ||||
-rw-r--r-- | src/managers/ProtocolManager.hpp | 2 | ||||
-rw-r--r-- | src/managers/input/InputMethodRelay.cpp | 10 | ||||
-rw-r--r-- | src/managers/input/InputMethodRelay.hpp | 7 | ||||
-rw-r--r-- | src/managers/input/TextInput.cpp | 86 | ||||
-rw-r--r-- | src/managers/input/TextInput.hpp | 14 | ||||
-rw-r--r-- | src/protocols/TextInputV1.cpp | 257 | ||||
-rw-r--r-- | src/protocols/TextInputV1.hpp | 88 | ||||
-rw-r--r-- | src/protocols/VirtualPointer.hpp | 1 |
11 files changed, 179 insertions, 297 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index d9411075..550f1dc5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -292,10 +292,7 @@ protocol( "subprojects/hyprland-protocols/protocols/hyprland-global-shortcuts-v1.xml" "hyprland-global-shortcuts-v1" true) -protocol( - "unstable/text-input/text-input-unstable-v1.xml" - "text-input-unstable-v1" false) - +protocolnew("unstable/text-input" "text-input-unstable-v1" false) protocolnew("subprojects/hyprland-protocols/protocols" "hyprland-toplevel-export-v1" true) protocolnew("protocols" "wlr-screencopy-unstable-v1" true) protocolnew("protocols" "wlr-gamma-control-unstable-v1" true) diff --git a/protocols/meson.build b/protocols/meson.build index 35b2b29b..4fd40859 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -24,7 +24,6 @@ hyprwayland_scanner = find_program( ) protocols = [ - [wl_protocol_dir, 'unstable/text-input/text-input-unstable-v1.xml'], [hl_protocol_dir, 'protocols/hyprland-global-shortcuts-v1.xml'] ] @@ -55,6 +54,7 @@ new_protocols = [ [wl_protocol_dir, 'unstable/pointer-gestures/pointer-gestures-unstable-v1.xml'], [wl_protocol_dir, 'unstable/keyboard-shortcuts-inhibit/keyboard-shortcuts-inhibit-unstable-v1.xml'], [wl_protocol_dir, 'unstable/text-input/text-input-unstable-v3.xml'], + [wl_protocol_dir, 'unstable/text-input/text-input-unstable-v1.xml'], [wl_protocol_dir, 'unstable/pointer-constraints/pointer-constraints-unstable-v1.xml'], [wl_protocol_dir, 'staging/xdg-activation/xdg-activation-v1.xml'], [wl_protocol_dir, 'staging/ext-idle-notify/ext-idle-notify-v1.xml'], diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index 3704befb..d052e045 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -41,6 +41,7 @@ #include "../protocols/DRMSyncobj.hpp" #include "../protocols/Screencopy.hpp" #include "../protocols/ToplevelExport.hpp" +#include "../protocols/TextInputV1.hpp" #include "../protocols/core/Seat.hpp" #include "../protocols/core/DataDevice.hpp" @@ -125,6 +126,7 @@ CProtocolManager::CProtocolManager() { PROTO::pointerGestures = std::make_unique<CPointerGesturesProtocol>(&zwp_pointer_gestures_v1_interface, 3, "PointerGestures"); PROTO::foreignToplevelWlr = std::make_unique<CForeignToplevelWlrProtocol>(&zwlr_foreign_toplevel_manager_v1_interface, 3, "ForeignToplevelWlr"); PROTO::shortcutsInhibit = std::make_unique<CKeyboardShortcutsInhibitProtocol>(&zwp_keyboard_shortcuts_inhibit_manager_v1_interface, 1, "ShortcutsInhibit"); + PROTO::textInputV1 = std::make_unique<CTextInputV1Protocol>(&zwp_text_input_manager_v1_interface, 1, "TextInputV1"); PROTO::textInputV3 = std::make_unique<CTextInputV3Protocol>(&zwp_text_input_manager_v3_interface, 1, "TextInputV3"); PROTO::constraints = std::make_unique<CPointerConstraintsProtocol>(&zwp_pointer_constraints_v1_interface, 1, "PointerConstraints"); PROTO::outputPower = std::make_unique<COutputPowerProtocol>(&zwlr_output_power_manager_v1_interface, 1, "OutputPower"); @@ -165,7 +167,6 @@ CProtocolManager::CProtocolManager() { // Old protocol implementations. // TODO: rewrite them to use hyprwayland-scanner. - m_pTextInputV1ProtocolManager = std::make_unique<CTextInputV1ProtocolManager>(); m_pGlobalShortcutsProtocolManager = std::make_unique<CGlobalShortcutsProtocolManager>(); } @@ -197,6 +198,7 @@ CProtocolManager::~CProtocolManager() { PROTO::pointerGestures.reset(); PROTO::foreignToplevelWlr.reset(); PROTO::shortcutsInhibit.reset(); + PROTO::textInputV1.reset(); PROTO::textInputV3.reset(); PROTO::constraints.reset(); PROTO::outputPower.reset(); diff --git a/src/managers/ProtocolManager.hpp b/src/managers/ProtocolManager.hpp index 62653e89..044a4d9b 100644 --- a/src/managers/ProtocolManager.hpp +++ b/src/managers/ProtocolManager.hpp @@ -1,7 +1,6 @@ #pragma once #include "../defines.hpp" -#include "../protocols/TextInputV1.hpp" #include "../protocols/GlobalShortcuts.hpp" #include "../helpers/Monitor.hpp" #include "../helpers/memory/Memory.hpp" @@ -14,7 +13,6 @@ class CProtocolManager { ~CProtocolManager(); // TODO: rewrite to use the new protocol framework - std::unique_ptr<CTextInputV1ProtocolManager> m_pTextInputV1ProtocolManager; std::unique_ptr<CGlobalShortcutsProtocolManager> m_pGlobalShortcutsProtocolManager; private: diff --git a/src/managers/input/InputMethodRelay.cpp b/src/managers/input/InputMethodRelay.cpp index f1fe6421..7cfd54b4 100644 --- a/src/managers/input/InputMethodRelay.cpp +++ b/src/managers/input/InputMethodRelay.cpp @@ -2,6 +2,7 @@ #include "InputManager.hpp" #include "../../Compositor.hpp" #include "../../protocols/TextInputV3.hpp" +#include "../../protocols/TextInputV1.hpp" #include "../../protocols/InputMethodV2.hpp" #include "../../protocols/core/Compositor.hpp" @@ -9,7 +10,8 @@ CInputMethodRelay::CInputMethodRelay() { static auto P = g_pHookSystem->hookDynamic("keyboardFocus", [&](void* self, SCallbackInfo& info, std::any param) { onKeyboardFocus(std::any_cast<SP<CWLSurfaceResource>>(param)); }); - listeners.newTIV3 = PROTO::textInputV3->events.newTextInput.registerListener([this](std::any ti) { onNewTextInput(ti); }); + 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)); }); listeners.newIME = PROTO::ime->events.newIME.registerListener([this](std::any ime) { onNewIME(std::any_cast<SP<CInputMethodV2>>(ime)); }); } @@ -86,11 +88,11 @@ CTextInput* CInputMethodRelay::getFocusedTextInput() { return nullptr; } -void CInputMethodRelay::onNewTextInput(std::any tiv3) { - m_vTextInputs.emplace_back(std::make_unique<CTextInput>(std::any_cast<WP<CTextInputV3>>(tiv3))); +void CInputMethodRelay::onNewTextInput(WP<CTextInputV3> tiv3) { + m_vTextInputs.emplace_back(std::make_unique<CTextInput>(tiv3)); } -void CInputMethodRelay::onNewTextInput(STextInputV1* pTIV1) { +void CInputMethodRelay::onNewTextInput(WP<CTextInputV1> pTIV1) { m_vTextInputs.emplace_back(std::make_unique<CTextInput>(pTIV1)); } diff --git a/src/managers/input/InputMethodRelay.hpp b/src/managers/input/InputMethodRelay.hpp index e13a1f1c..5ecc11a2 100644 --- a/src/managers/input/InputMethodRelay.hpp +++ b/src/managers/input/InputMethodRelay.hpp @@ -10,7 +10,7 @@ class CInputManager; class CHyprRenderer; -struct STextInputV1; +class CTextInputV1; class CInputMethodV2; class CInputMethodRelay { @@ -18,8 +18,8 @@ class CInputMethodRelay { CInputMethodRelay(); void onNewIME(SP<CInputMethodV2>); - void onNewTextInput(std::any tiv3); - void onNewTextInput(STextInputV1* pTIV1); + void onNewTextInput(WP<CTextInputV3> tiv3); + void onNewTextInput(WP<CTextInputV1> pTIV1); void activateIME(CTextInput* pInput); void deactivateIME(CTextInput* pInput); @@ -48,6 +48,7 @@ class CInputMethodRelay { struct { CHyprSignalListener newTIV3; + CHyprSignalListener newTIV1; CHyprSignalListener newIME; CHyprSignalListener commitIME; CHyprSignalListener destroyIME; diff --git a/src/managers/input/TextInput.cpp b/src/managers/input/TextInput.cpp index 635a8b01..5bff9fed 100644 --- a/src/managers/input/TextInput.cpp +++ b/src/managers/input/TextInput.cpp @@ -7,8 +7,7 @@ #include "../../protocols/InputMethodV2.hpp" #include "../../protocols/core/Compositor.hpp" -CTextInput::CTextInput(STextInputV1* ti) : pV1Input(ti) { - ti->pTextInput = this; +CTextInput::CTextInput(WP<CTextInputV1> ti) : pV1Input(ti) { initCallbacks(); } @@ -16,17 +15,6 @@ CTextInput::CTextInput(WP<CTextInputV3> ti) : pV3Input(ti) { initCallbacks(); } -CTextInput::~CTextInput() { - if (pV1Input) - pV1Input->pTextInput = nullptr; -} - -void CTextInput::tiV1Destroyed() { - pV1Input = nullptr; - - g_pInputManager->m_sIMERelay.removeTextInput(this); -} - void CTextInput::initCallbacks() { if (isV3()) { const auto INPUT = pV3Input.lock(); @@ -41,25 +29,19 @@ void CTextInput::initCallbacks() { g_pInputManager->m_sIMERelay.removeTextInput(this); }); } else { - hyprListener_textInputEnable.initCallback(&pV1Input->sEnable, [this](void* owner, void* data) { onEnabled(); }, this, "textInput"); + const auto INPUT = pV1Input.lock(); - hyprListener_textInputCommit.initCallback(&pV1Input->sCommit, [this](void* owner, void* data) { onCommit(); }, this, "textInput"); - - hyprListener_textInputDisable.initCallback(&pV1Input->sDisable, [this](void* owner, void* data) { onDisabled(); }, this, "textInput"); - - hyprListener_textInputDestroy.initCallback( - &pV1Input->sDestroy, - [this](void* owner, void* data) { - hyprListener_textInputCommit.removeCallback(); - hyprListener_textInputDestroy.removeCallback(); - hyprListener_textInputDisable.removeCallback(); - hyprListener_textInputEnable.removeCallback(); - listeners.surfaceUnmap.reset(); - listeners.surfaceDestroy.reset(); - - g_pInputManager->m_sIMERelay.removeTextInput(this); - }, - this, "textInput"); + listeners.enable = INPUT->events.enable.registerListener([this](std::any p) { + const auto SURFACE = std::any_cast<SP<CWLSurfaceResource>>(p); + onEnabled(SURFACE); + }); + listeners.disable = INPUT->events.disable.registerListener([this](std::any p) { onDisabled(); }); + listeners.commit = INPUT->events.onCommit.registerListener([this](std::any p) { onCommit(); }); + listeners.destroy = INPUT->events.destroy.registerListener([this](std::any p) { + listeners.surfaceUnmap.reset(); + listeners.surfaceDestroy.reset(); + g_pInputManager->m_sIMERelay.removeTextInput(this); + }); } } @@ -149,7 +131,7 @@ void CTextInput::setFocusedSurface(SP<CWLSurfaceResource> pSurface) { } bool CTextInput::isV3() { - return !pV1Input; + return pV3Input && !pV1Input; } void CTextInput::enter(SP<CWLSurfaceResource> pSurface) { @@ -174,8 +156,7 @@ void CTextInput::enter(SP<CWLSurfaceResource> pSurface) { if (isV3()) pV3Input->enter(pSurface); else { - zwp_text_input_v1_send_enter(pV1Input->resourceImpl, pSurface->getResource()->resource()); - pV1Input->active = true; + pV1Input->enter(pSurface); } setFocusedSurface(pSurface); @@ -194,8 +175,7 @@ void CTextInput::leave() { if (isV3() && focusedSurface()) pV3Input->leave(focusedSurface()); else if (focusedSurface() && pV1Input) { - zwp_text_input_v1_send_leave(pV1Input->resourceImpl); - pV1Input->active = false; + pV1Input->leave(); } setFocusedSurface(nullptr); @@ -208,7 +188,7 @@ SP<CWLSurfaceResource> CTextInput::focusedSurface() { } wl_client* CTextInput::client() { - return isV3() ? pV3Input->client() : pV1Input->client; + return isV3() ? pV3Input->client() : pV1Input->client(); } void CTextInput::commitStateToIME(SP<CInputMethodV2> ime) { @@ -223,13 +203,15 @@ void CTextInput::commitStateToIME(SP<CInputMethodV2> ime) { if (INPUT->current.contentType.updated) ime->textContentType(INPUT->current.contentType.hint, INPUT->current.contentType.purpose); } else { - if (pV1Input->pendingSurrounding.isPending) - ime->surroundingText(pV1Input->pendingSurrounding.text, pV1Input->pendingSurrounding.cursor, pV1Input->pendingSurrounding.anchor); + const auto INPUT = pV1Input.lock(); + + if (INPUT->pendingSurrounding.isPending) + ime->surroundingText(INPUT->pendingSurrounding.text, INPUT->pendingSurrounding.cursor, INPUT->pendingSurrounding.anchor); ime->textChangeCause(ZWP_TEXT_INPUT_V3_CHANGE_CAUSE_INPUT_METHOD); if (pV1Input->pendingContentType.isPending) - ime->textContentType((zwpTextInputV3ContentHint)pV1Input->pendingContentType.hint, (zwpTextInputV3ContentPurpose)pV1Input->pendingContentType.purpose); + ime->textContentType((zwpTextInputV3ContentHint)INPUT->pendingContentType.hint, (zwpTextInputV3ContentPurpose)INPUT->pendingContentType.purpose); } g_pInputManager->m_sIMERelay.updateAllPopups(); @@ -252,25 +234,27 @@ void CTextInput::updateIMEState(SP<CInputMethodV2> ime) { INPUT->sendDone(); } else { + const auto INPUT = pV1Input.lock(); + if (ime->current.preeditString.committed) { - zwp_text_input_v1_send_preedit_cursor(pV1Input->resourceImpl, ime->current.preeditString.begin); - zwp_text_input_v1_send_preedit_styling(pV1Input->resourceImpl, 0, std::string(ime->current.preeditString.string).length(), ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_HIGHLIGHT); - zwp_text_input_v1_send_preedit_string(pV1Input->resourceImpl, pV1Input->serial, ime->current.preeditString.string.c_str(), ""); + INPUT->preeditCursor(ime->current.preeditString.begin); + INPUT->preeditStyling(0, std::string(ime->current.preeditString.string).length(), ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_HIGHLIGHT); + INPUT->preeditString(pV1Input->serial, ime->current.preeditString.string.c_str(), ""); } else { - zwp_text_input_v1_send_preedit_cursor(pV1Input->resourceImpl, ime->current.preeditString.begin); - zwp_text_input_v1_send_preedit_styling(pV1Input->resourceImpl, 0, 0, ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_HIGHLIGHT); - zwp_text_input_v1_send_preedit_string(pV1Input->resourceImpl, pV1Input->serial, "", ""); + INPUT->preeditCursor(ime->current.preeditString.begin); + INPUT->preeditStyling(0, 0, ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_HIGHLIGHT); + INPUT->preeditString(pV1Input->serial, "", ""); } if (ime->current.committedString.committed) - zwp_text_input_v1_send_commit_string(pV1Input->resourceImpl, pV1Input->serial, ime->current.committedString.string.c_str()); + INPUT->commitString(pV1Input->serial, ime->current.committedString.string.c_str()); if (ime->current.deleteSurrounding.committed) { - zwp_text_input_v1_send_delete_surrounding_text(pV1Input->resourceImpl, std::string(ime->current.preeditString.string).length() - ime->current.deleteSurrounding.before, - ime->current.deleteSurrounding.after + ime->current.deleteSurrounding.before); + INPUT->deleteSurroundingText(std::string(ime->current.preeditString.string).length() - ime->current.deleteSurrounding.before, + ime->current.deleteSurrounding.after + ime->current.deleteSurrounding.before); if (ime->current.preeditString.committed) - zwp_text_input_v1_send_commit_string(pV1Input->resourceImpl, pV1Input->serial, ime->current.preeditString.string.c_str()); + INPUT->commitString(pV1Input->serial, ime->current.preeditString.string.c_str()); } } } @@ -281,4 +265,4 @@ bool CTextInput::hasCursorRectangle() { CBox CTextInput::cursorBox() { return CBox{isV3() ? pV3Input->current.box.cursorBox : pV1Input->cursorRectangle}; -}
\ No newline at end of file +} diff --git a/src/managers/input/TextInput.hpp b/src/managers/input/TextInput.hpp index 79e08af9..0f69866e 100644 --- a/src/managers/input/TextInput.hpp +++ b/src/managers/input/TextInput.hpp @@ -8,7 +8,7 @@ struct wl_client; -struct STextInputV1; +class CTextInputV1; class CTextInputV3; class CInputMethodV2; class CWLSurfaceResource; @@ -16,8 +16,7 @@ class CWLSurfaceResource; class CTextInput { public: CTextInput(WP<CTextInputV3> ti); - CTextInput(STextInputV1* ti); - ~CTextInput(); + CTextInput(WP<CTextInputV1> ti); bool isV3(); void enter(SP<CWLSurfaceResource> pSurface); @@ -43,12 +42,7 @@ class CTextInput { WP<CWLSurfaceResource> pFocusedSurface; int enterLocks = 0; WP<CTextInputV3> pV3Input; - STextInputV1* pV1Input = nullptr; - - DYNLISTENER(textInputEnable); - DYNLISTENER(textInputDisable); - DYNLISTENER(textInputCommit); - DYNLISTENER(textInputDestroy); + WP<CTextInputV1> pV1Input; struct { CHyprSignalListener enable; @@ -58,4 +52,4 @@ class CTextInput { CHyprSignalListener surfaceUnmap; CHyprSignalListener surfaceDestroy; } listeners; -};
\ No newline at end of file +}; diff --git a/src/protocols/TextInputV1.cpp b/src/protocols/TextInputV1.cpp index 12068671..78e910cb 100644 --- a/src/protocols/TextInputV1.cpp +++ b/src/protocols/TextInputV1.cpp @@ -3,228 +3,125 @@ #include "../Compositor.hpp" #include "core/Compositor.hpp" -#define TEXT_INPUT_VERSION 1 +#define LOGM PROTO::textInputV1->protoLog -static void bindManagerInt(wl_client* client, void* data, uint32_t version, uint32_t id) { - g_pProtocolManager->m_pTextInputV1ProtocolManager->bindManager(client, data, version, id); +CTextInputV1::~CTextInputV1() { + events.destroy.emit(); } -static void handleDisplayDestroy(struct wl_listener* listener, void* data) { - CTextInputV1ProtocolManager* proto = wl_container_of(listener, proto, m_liDisplayDestroy); - proto->displayDestroy(); -} - -void CTextInputV1ProtocolManager::displayDestroy() { - wl_list_remove(&m_liDisplayDestroy.link); - wl_list_init(&m_liDisplayDestroy.link); - wl_global_destroy(m_pGlobal); -} - -CTextInputV1ProtocolManager::~CTextInputV1ProtocolManager() { - displayDestroy(); -} - -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!"); +CTextInputV1::CTextInputV1(SP<CZwpTextInputV1> resource_) : resource(resource_) { + if (!good()) 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); -} + resource->setOnDestroy([this](CZwpTextInputV1* pMgr) { PROTO::textInputV1->destroyResource(this); }); -static const struct zwp_text_input_manager_v1_interface textInputManagerImpl = { - .create_text_input = createTI, -}; + resource->setActivate([this](CZwpTextInputV1* pMgr, wl_resource* seat, wl_resource* surface) { + if (!surface) { + LOGM(WARN, "Text-input-v1 PTI{:x}: No surface to activate text input on!", (uintptr_t)this); + return; + } -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); + active = true; + events.enable.emit(CWLSurfaceResource::fromResource(surface)); + }); - Debug::log(LOG, "TextInputV1Manager bound successfully!"); -} + resource->setDeactivate([this](CZwpTextInputV1* pMgr, wl_resource* seat) { + active = false; + events.disable.emit(); + }); -// + resource->setReset([this](CZwpTextInputV1* pMgr) { + pendingSurrounding.isPending = false; + pendingContentType.isPending = false; + }); -static void handleActivate(wl_client* client, wl_resource* resource, wl_resource* seat, wl_resource* surface) { - g_pProtocolManager->m_pTextInputV1ProtocolManager->handleActivate(client, resource, seat, surface); -} + resource->setSetSurroundingText( + [this](CZwpTextInputV1* pMgr, const char* text, uint32_t cursor, uint32_t anchor) { pendingSurrounding = {true, std::string(text), cursor, anchor}; }); -static void handleDeactivate(wl_client* client, wl_resource* resource, wl_resource* seat) { - g_pProtocolManager->m_pTextInputV1ProtocolManager->handleDeactivate(client, resource, seat); -} + resource->setSetContentType([this](CZwpTextInputV1* pMgr, uint32_t hint, uint32_t purpose) { + 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}; + }); -static void handleShowInputPanel(wl_client* client, wl_resource* resource) { - g_pProtocolManager->m_pTextInputV1ProtocolManager->handleShowInputPanel(client, resource); -} + resource->setSetCursorRectangle([this](CZwpTextInputV1* pMgr, int32_t x, int32_t y, int32_t width, int32_t height) { cursorRectangle = CBox{x, y, width, height}; }); -static void handleHideInputPanel(wl_client* client, wl_resource* resource) { - g_pProtocolManager->m_pTextInputV1ProtocolManager->handleHideInputPanel(client, resource); -} + resource->setCommitState([this](CZwpTextInputV1* pMgr, uint32_t serial_) { + serial = serial_; + events.onCommit.emit(); + }); -static void handleReset(wl_client* client, wl_resource* resource) { - g_pProtocolManager->m_pTextInputV1ProtocolManager->handleReset(client, resource); + // nothing + resource->setShowInputPanel([this](CZwpTextInputV1* pMgr) {}); + resource->setHideInputPanel([this](CZwpTextInputV1* pMgr) {}); + resource->setSetPreferredLanguage([this](CZwpTextInputV1* pMgr, const char* language) {}); + resource->setInvokeAction([this](CZwpTextInputV1* pMgr, uint32_t button, uint32_t index) {}); } -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); +bool CTextInputV1::good() { + return resource->resource(); } -static void handleSetContentType(wl_client* client, wl_resource* resource, uint32_t hint, uint32_t purpose) { - g_pProtocolManager->m_pTextInputV1ProtocolManager->handleSetContentType(client, resource, hint, purpose); +wl_client* CTextInputV1::client() { + return resource->client(); } -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 CTextInputV1::enter(SP<CWLSurfaceResource> surface) { + resource->sendEnter(surface->getResource()->resource()); + active = true; } -static void handleSetPreferredLanguage(wl_client* client, wl_resource* resource, const char* language) { - g_pProtocolManager->m_pTextInputV1ProtocolManager->handleSetPreferredLanguage(client, resource, language); +void CTextInputV1::leave() { + resource->sendLeave(); + active = false; } -static void handleCommitState(wl_client* client, wl_resource* resource, uint32_t serial) { - g_pProtocolManager->m_pTextInputV1ProtocolManager->handleCommitState(client, resource, serial); +void CTextInputV1::preeditCursor(int32_t index) { + resource->sendPreeditCursor(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); +void CTextInputV1::preeditStyling(uint32_t index, uint32_t length, zwpTextInputV1PreeditStyle style) { + resource->sendPreeditStyling(index, length, style); } -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; }); +void CTextInputV1::preeditString(uint32_t serial, const char* text, const char* commit) { + resource->sendPreeditString(serial, text, commit); } -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); +void CTextInputV1::commitString(uint32_t serial, const char* text) { + resource->sendCommitString(serial, text); } -static void destroyTI(wl_resource* resource) { - const auto TI = tiFromResource(resource); - - if (!TI) - return; - - if (TI->resourceImpl) { - wl_resource_set_user_data(resource, nullptr); - } - - TI->pTextInput->tiV1Destroyed(); - - g_pProtocolManager->m_pTextInputV1ProtocolManager->removeTI(TI); +void CTextInputV1::deleteSurroundingText(int32_t index, uint32_t length) { + resource->sendDeleteSurroundingText(index, length); } -void CTextInputV1ProtocolManager::createTI(wl_client* client, wl_resource* resource, uint32_t id) { - const auto PTI = m_pClients.emplace_back(std::make_unique<STextInputV1>()).get(); - Debug::log(LOG, "New TI V1 at {:x}", (uintptr_t)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); - 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.onNewTextInput(PTI); -} - -void CTextInputV1ProtocolManager::handleActivate(wl_client* client, wl_resource* resource, wl_resource* seat, wl_resource* surface) { - const auto PTI = tiFromResource(resource); - if (!surface) { - Debug::log(WARN, "Text-input-v1 PTI{:x}: No surface to activate text input on!", (uintptr_t)PTI); - return; - } - PTI->active = true; - PTI->pTextInput->onEnabled(CWLSurfaceResource::fromResource(surface)); -} - -void CTextInputV1ProtocolManager::handleDeactivate(wl_client* client, wl_resource* resource, wl_resource* seat) { - const auto PTI = tiFromResource(resource); - PTI->active = false; - PTI->pTextInput->onDisabled(); -} - -void CTextInputV1ProtocolManager::handleShowInputPanel(wl_client* client, wl_resource* resource) { +CTextInputV1Protocol::CTextInputV1Protocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { ; } -void CTextInputV1ProtocolManager::handleHideInputPanel(wl_client* client, wl_resource* resource) { - ; -} +void CTextInputV1Protocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { + const auto RESOURCE = m_vManagers.emplace_back(makeShared<CZwpTextInputManagerV1>(client, ver, id)); -void CTextInputV1ProtocolManager::handleReset(wl_client* client, wl_resource* resource) { - const auto PTI = tiFromResource(resource); - PTI->pendingSurrounding.isPending = false; - PTI->pendingContentType.isPending = false; -} + RESOURCE->setOnDestroy([this](CZwpTextInputManagerV1* pMgr) { PROTO::textInputV1->destroyResource(pMgr); }); + RESOURCE->setCreateTextInput([this](CZwpTextInputManagerV1* pMgr, uint32_t id) { + const auto PTI = m_vClients.emplace_back(makeShared<CTextInputV1>(makeShared<CZwpTextInputV1>(pMgr->client(), pMgr->version(), id))); + LOGM(LOG, "New TI V1 at {:x}", (uintptr_t)PTI.get()); -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}; -} + if (!PTI->good()) { + LOGM(ERR, "Could not alloc wl_resource for TIV1"); + pMgr->noMemory(); + PROTO::textInputV1->destroyResource(PTI.get()); + return; + } -void CTextInputV1ProtocolManager::handleSetContentType(wl_client* client, wl_resource* resource, uint32_t hint, uint32_t purpose) { - const auto PTI = tiFromResource(resource); - 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}; + events.newTextInput.emit(WP<CTextInputV1>(PTI)); + }); } -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 = CBox{x, y, width, height}; +void CTextInputV1Protocol::destroyResource(CTextInputV1* client) { + std::erase_if(m_vClients, [&](const auto& other) { return other.get() == client; }); } -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->serial = serial; - PTI->pTextInput->onCommit(); -} - -void CTextInputV1ProtocolManager::handleInvokeAction(wl_client* client, wl_resource* resource, uint32_t button, uint32_t index) { - ; +void CTextInputV1Protocol::destroyResource(CZwpTextInputManagerV1* client) { + std::erase_if(m_vManagers, [&](const auto& other) { return other.get() == client; }); } diff --git a/src/protocols/TextInputV1.hpp b/src/protocols/TextInputV1.hpp index e56a8990..c85a1f31 100644 --- a/src/protocols/TextInputV1.hpp +++ b/src/protocols/TextInputV1.hpp @@ -1,28 +1,44 @@ #pragma once #include "../defines.hpp" -#include "text-input-unstable-v1-protocol.h" +#include "../protocols/core/Compositor.hpp" +#include "text-input-unstable-v1.hpp" +#include "WaylandProtocol.hpp" #include <vector> class CTextInput; -struct STextInputV1 { - wl_client* client = nullptr; - wl_resource* resourceCaller = nullptr; +class CTextInputV1 { + public: + CTextInputV1(SP<CZwpTextInputV1> resource); + ~CTextInputV1(); + + void enter(SP<CWLSurfaceResource> surface); + void leave(); - wl_resource* resourceImpl = nullptr; + void preeditCursor(int32_t index); + void preeditStyling(uint32_t index, uint32_t length, zwpTextInputV1PreeditStyle style); + void preeditString(uint32_t serial, const char* text, const char* commit); + void commitString(uint32_t serial, const char* text); + void deleteSurroundingText(int32_t index, uint32_t length); - CTextInput* pTextInput = nullptr; + bool good(); + wl_client* client(); - wl_signal sEnable; - wl_signal sDisable; - wl_signal sCommit; - wl_signal sDestroy; + private: + SP<CZwpTextInputV1> resource; + WP<CTextInputV1> self; - uint32_t serial = 0; + uint32_t serial = 0; + bool active = false; - bool active = false; + struct { + CSignal onCommit; + CSignal enable; + CSignal disable; + CSignal destroy; + } events; struct SPendingSurr { bool isPending = false; @@ -39,39 +55,29 @@ struct STextInputV1 { CBox cursorRectangle = {0, 0, 0, 0}; - bool operator==(const STextInputV1& other) { - return other.client == client && other.resourceCaller == resourceCaller && other.resourceImpl == resourceImpl; - } + friend class CTextInput; + friend class CTextInputV1Protocol; }; -class CTextInputV1ProtocolManager { +class CTextInputV1Protocol : IWaylandProtocol { public: - CTextInputV1ProtocolManager(); - ~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); - - wl_listener m_liDisplayDestroy; + CTextInputV1Protocol(const wl_interface* iface, const int& ver, const std::string& name); + + virtual void bindManager(wl_client* client, void* data, uint32_t version, uint32_t id); + void destroyResource(CTextInputV1* resource); + void destroyResource(CZwpTextInputManagerV1* client); + + struct { + CSignal newTextInput; // WP<CTextInputV3> + } events; private: - wl_global* m_pGlobal = nullptr; + std::vector<SP<CZwpTextInputManagerV1>> m_vManagers; + std::vector<SP<CTextInputV1>> m_vClients; + + friend class CTextInputV1; +}; - std::vector<std::unique_ptr<STextInputV1>> m_pClients; +namespace PROTO { + inline UP<CTextInputV1Protocol> textInputV1; }; diff --git a/src/protocols/VirtualPointer.hpp b/src/protocols/VirtualPointer.hpp index 1a51d977..7ee450dc 100644 --- a/src/protocols/VirtualPointer.hpp +++ b/src/protocols/VirtualPointer.hpp @@ -8,6 +8,7 @@ #include "wlr-virtual-pointer-unstable-v1.hpp" #include "../helpers/signal/Signal.hpp" #include "../devices/IPointer.hpp" +#include "../helpers/Monitor.hpp" class CVirtualPointerV1Resource { public: |