Added some IME (broken for now... i think)

This commit is contained in:
vaxerski 2022-05-14 14:32:05 +02:00
parent 0273d21a77
commit 727c56df2f
9 changed files with 294 additions and 2 deletions

View File

@ -102,6 +102,10 @@ CCompositor::CCompositor() {
m_sWLRVKeyboardMgr = wlr_virtual_keyboard_manager_v1_create(m_sWLDisplay);
m_sWLRVirtPtrMgr = wlr_virtual_pointer_manager_v1_create(m_sWLDisplay);
m_sWLRIMEMgr = wlr_input_method_manager_v2_create(m_sWLDisplay);
m_sWLRTextInputMgr = wlr_text_input_manager_v3_create(m_sWLDisplay);
}
CCompositor::~CCompositor() {
@ -135,6 +139,8 @@ void CCompositor::initAllSignals() {
addWLSignal(&m_sWLRPointerConstraints->events.new_constraint, &Events::listen_newConstraint, m_sWLRPointerConstraints, "PointerConstraints");
addWLSignal(&m_sWLRXDGDecoMgr->events.new_toplevel_decoration, &Events::listen_NewXDGDeco, m_sWLRXDGDecoMgr, "XDGDecoMgr");
addWLSignal(&m_sWLRVirtPtrMgr->events.new_virtual_pointer, &Events::listen_newVirtPtr, m_sWLRVirtPtrMgr, "VirtPtrMgr");
addWLSignal(&m_sWLRTextInputMgr->events.text_input, &Events::listen_newInput, m_sWLRTextInputMgr, "TextInputMgr");
addWLSignal(&m_sWLRIMEMgr->events.input_method, &Events::listen_NewIME, m_sWLRIMEMgr, "IMEMgr");
signal(SIGINT, handleCritSignal);
signal(SIGTERM, handleCritSignal);
@ -464,6 +470,7 @@ void CCompositor::focusSurface(wlr_surface* pSurface, CWindow* pWindowOwner) {
return;
wlr_seat_keyboard_notify_enter(m_sSeat.seat, pSurface, KEYBOARD->keycodes, KEYBOARD->num_keycodes, &KEYBOARD->modifiers);
g_pInputManager->textInputSetFocusAll(pSurface);
wlr_seat_keyboard_focus_change_event event = {
.seat = m_sSeat.seat,

View File

@ -56,6 +56,8 @@ public:
wlr_server_decoration_manager* m_sWLRServerDecoMgr;
wlr_xdg_decoration_manager_v1* m_sWLRXDGDecoMgr;
wlr_virtual_pointer_manager_v1* m_sWLRVirtPtrMgr;
wlr_input_method_manager_v2* m_sWLRIMEMgr;
wlr_text_input_manager_v3* m_sWLRTextInputMgr;
// ------------------------------------------------- //

View File

@ -109,4 +109,20 @@ namespace Events {
// Deco XDG
LISTENER(NewXDGDeco);
// Text input and IME
LISTENER(TextInput);
LISTENER(NewIME);
DYNLISTENFUNC(TextInputEnable);
DYNLISTENFUNC(TextInputDisable);
DYNLISTENFUNC(TextInputCommit);
DYNLISTENFUNC(TextInputDestroy);
DYNLISTENFUNC(TextInputFocusedSurfaceDestroy);
DYNLISTENFUNC(IMENew);
DYNLISTENFUNC(IMECommit);
DYNLISTENFUNC(IMEGrab);
DYNLISTENFUNC(IMEDestroy);
DYNLISTENFUNC(IMEDestroyGrab);
};

87
src/events/Text.cpp Normal file
View File

@ -0,0 +1,87 @@
#include "Events.hpp"
#include "../Compositor.hpp"
#include "../helpers/WLClasses.hpp"
#include "../managers/InputManager.hpp"
#include "../render/Renderer.hpp"
#include "../helpers/TextInput.hpp"
void Events::listener_TextInput(wl_listener* listener, void* data) {
const auto WLRTEXTINPUT = (wlr_text_input_v3*)data;
g_pInputManager->createTextInput(WLRTEXTINPUT);
}
void Events::listener_NewIME(wl_listener* listener, void* data) {
const auto WLRIME = (wlr_input_method_v2*)data;
Debug::log(LOG, "Creating new IME at %x", WLRIME);
if (g_pCompositor->m_sSeat.pCurrentIME) {
Debug::log(ERR, "Cannot create a new IME, one is already active!");
return;
}
g_pCompositor->m_sSeat.IME.hyprListener_IMECommit.initCallback(&WLRIME->events.commit, &Events::listener_IMECommit, &g_pCompositor->m_sSeat.IME, "IME");
g_pCompositor->m_sSeat.IME.hyprListener_IMEGrab.initCallback(&WLRIME->events.grab_keyboard, &Events::listener_IMEGrab, &g_pCompositor->m_sSeat.IME, "IME");
g_pCompositor->m_sSeat.IME.hyprListener_IMEDestroy.initCallback(&WLRIME->events.destroy, &Events::listener_IMEDestroy, &g_pCompositor->m_sSeat.IME, "IME");
g_pCompositor->m_sSeat.pCurrentIME = WLRIME;
}
void Events::listener_IMECommit(void* owner, void* data) {
const auto IME = g_pCompositor->m_sSeat.pCurrentIME;
const auto TEXTINPUT = g_pInputManager->getFocusedTextInput();
ASSERT(IME);
if (IME->current.preedit.text)
wlr_text_input_v3_send_preedit_string(TEXTINPUT->wlrInput, IME->current.preedit.text, IME->current.preedit.cursor_begin, IME->current.preedit.cursor_end);
if (IME->current.commit_text)
wlr_text_input_v3_send_commit_string(TEXTINPUT->wlrInput, IME->current.commit_text);
if (IME->current.delete_.before_length || IME->current.delete_.after_length)
wlr_text_input_v3_send_delete_surrounding_text(TEXTINPUT->wlrInput, IME->current.delete_.before_length, IME->current.delete_.after_length);
wlr_text_input_v3_send_done(TEXTINPUT->wlrInput);
}
void Events::listener_IMEGrab(void* owner, void* data) {
const auto WLRKBGRAB = (wlr_input_method_keyboard_grab_v2*)data;
const auto PKEYBOARD = g_pInputManager->getActiveKeyboard();
if (!PKEYBOARD) {
Debug::log(ERR, "IME Cannot grab, no active keyboard!");
return;
}
wlr_input_method_keyboard_grab_v2_set_keyboard(WLRKBGRAB, PKEYBOARD->keyboard->keyboard);
Debug::log(LOG, "IME grabbed keyboard %x", PKEYBOARD);
g_pCompositor->m_sSeat.IME.hyprListener_IMEDestroyGrab.initCallback(&WLRKBGRAB->events.destroy, Events::listener_IMEDestroyGrab, &g_pCompositor->m_sSeat.IME, "IME");
}
void Events::listener_IMEDestroyGrab(void* owner, void* data) {
//const auto WLRKBGRAB = (wlr_input_method_keyboard_grab_v2*)data;
Debug::log(LOG, "IME destroyed grab");
g_pCompositor->m_sSeat.IME.hyprListener_IMEDestroyGrab.removeCallback();
}
void Events::listener_IMEDestroy(void* owner, void* data) {
//const auto IME = (wlr_input_method_v2*)data;
g_pCompositor->m_sSeat.pCurrentIME = nullptr;
const auto TEXTINPUT = g_pInputManager->getFocusedTextInput();
if (TEXTINPUT) {
wlr_text_input_v3_send_leave(TEXTINPUT->wlrInput);
}
}

18
src/helpers/TextInput.hpp Normal file
View File

@ -0,0 +1,18 @@
#pragma once
#include "../defines.hpp"
struct STextInput {
wlr_text_input_v3* wlrInput = nullptr;
wlr_surface* pSurface = nullptr;
DYNLISTENER(InputEnable);
DYNLISTENER(InputCommit);
DYNLISTENER(InputDisable);
DYNLISTENER(InputDestroy);
bool operator==(const STextInput& b) const {
return wlrInput == b.wlrInput;
}
};

View File

@ -5,6 +5,7 @@
#include "../../wlr-layer-shell-unstable-v1-protocol.h"
#include "../Window.hpp"
#include "SubsurfaceTree.hpp"
#include "TextInput.hpp"
struct SLayerSurface {
wlr_layer_surface_v1* layerSurface;
@ -114,11 +115,26 @@ struct SXDGPopup {
}
};
struct SIME {
wlr_input_method_v2* pIME = nullptr;
DYNLISTENER(newTextInput);
DYNLISTENER(IMENew);
DYNLISTENER(IMECommit);
DYNLISTENER(IMEGrab);
DYNLISTENER(IMEDestroy);
DYNLISTENER(IMEDestroyGrab);
};
struct SSeat {
wlr_seat* seat = nullptr;
wl_client* exclusiveClient = nullptr;
SMouse* mouse = nullptr;
wlr_input_method_v2* pCurrentIME = nullptr;
SIME IME;
};
struct SDrag {

View File

@ -73,6 +73,10 @@ extern "C" {
#include <wlr/types/wlr_input_inhibitor.h>
#include <wlr/types/wlr_keyboard_shortcuts_inhibit_v1.h>
#include <wlr/types/wlr_virtual_pointer_v1.h>
#define delete delete_
#include <wlr/types/wlr_input_method_v2.h>
#include <wlr/types/wlr_text_input_v3.h>
#undef delete
#include <wlr/util/log.h>
#include <wlr/xwayland.h>
#include <wlr/util/region.h>

View File

@ -210,6 +210,10 @@ Vector2D CInputManager::getMouseCoordsInternal() {
return Vector2D(g_pCompositor->m_sWLRCursor->x, g_pCompositor->m_sWLRCursor->y);
}
SKeyboard* CInputManager::getActiveKeyboard() {
return m_pActiveKeyboard;
}
void CInputManager::newKeyboard(wlr_input_device* keyboard) {
m_lKeyboards.push_back(SKeyboard());
@ -236,6 +240,8 @@ void CInputManager::newKeyboard(wlr_input_device* keyboard) {
wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, keyboard->keyboard);
m_pActiveKeyboard = PNEWKEYBOARD;
Debug::log(LOG, "New keyboard created, pointers Hypr: %x and WLR: %x", PNEWKEYBOARD, keyboard);
setKeyboardLayout();
@ -312,6 +318,8 @@ void CInputManager::destroyKeyboard(SKeyboard* pKeyboard) {
pKeyboard->hyprListener_keyboardKey.removeCallback();
m_lKeyboards.remove(*pKeyboard);
m_pActiveKeyboard = m_lKeyboards.size() > 0 ? &m_lKeyboards.back() : nullptr;
}
void CInputManager::destroyMouse(wlr_input_device* mouse) {
@ -450,3 +458,123 @@ void CInputManager::constrainMouse(SMouse* pMouse, wlr_pointer_constraint_v1* co
void Events::listener_commitConstraint(void* owner, void* data) {
//g_pInputManager->recheckConstraint((SMouse*)owner);
}
void CInputManager::createTextInput(wlr_text_input_v3* pInput) {
Debug::log(LOG, "Request to create TextInput at %x", pInput);
m_lTextInputs.emplace_back();
const auto PINPUT = &m_lTextInputs.back();
PINPUT->hyprListener_InputCommit.initCallback(&pInput->events.commit, Events::listener_TextInputCommit, PINPUT, "TextInput");
PINPUT->hyprListener_InputDestroy.initCallback(&pInput->events.destroy, Events::listener_TextInputDestroy, PINPUT, "TextInput");
PINPUT->hyprListener_InputDisable.initCallback(&pInput->events.disable, Events::listener_TextInputDisable, PINPUT, "TextInput");
PINPUT->hyprListener_InputEnable.initCallback(&pInput->events.enable, Events::listener_TextInputEnable, PINPUT, "TextInput");
Debug::log(LOG, "Created TextInput at %x", PINPUT);
}
void CInputManager::sendIMState(wlr_text_input_v3* pTextInput) {
const auto PIME = g_pCompositor->m_sSeat.pCurrentIME;
if (!PIME) {
Debug::log(LOG, "SendIMState in dead IME");
return;
}
if (pTextInput->active_features & WLR_TEXT_INPUT_V3_FEATURE_SURROUNDING_TEXT) {
wlr_input_method_v2_send_surrounding_text(PIME, pTextInput->current.surrounding.text, pTextInput->current.surrounding.cursor, pTextInput->current.surrounding.anchor);
}
wlr_input_method_v2_send_text_change_cause(PIME, pTextInput->current.text_change_cause);
if (pTextInput->active_features & WLR_TEXT_INPUT_V3_FEATURE_CONTENT_TYPE) {
wlr_input_method_v2_send_content_type(PIME, pTextInput->current.content_type.hint, pTextInput->current.content_type.purpose);
}
wlr_input_method_v2_send_done(PIME);
}
void CInputManager::destroyTextInput(STextInput* pInput) {
m_lTextInputs.remove(*pInput); // will cleanup listeners
}
void Events::listener_TextInputEnable(void* owner, void* data) {
const auto PTI = (STextInput*)owner;
if (!g_pCompositor->m_sSeat.pCurrentIME) {
Debug::log(LOG, "Enabling TextInput in dead IME!");
return;
}
Debug::log(LOG, "Enabling IME state (TextInput)");
wlr_input_method_v2_send_activate(g_pCompositor->m_sSeat.pCurrentIME);
g_pInputManager->sendIMState(PTI->wlrInput);
}
void Events::listener_TextInputCommit(void* owner, void* data) {
const auto PTI = (STextInput*)owner;
if (!PTI->wlrInput->current_enabled) {
Debug::log(LOG, "Ignoring commit from IME that's disabled");
return;
}
if (!g_pCompositor->m_sSeat.pCurrentIME) {
Debug::log(LOG, "Committing TextInput in dead IME!");
return;
}
Debug::log(LOG, "Committing IME state (TextInput)");
g_pInputManager->sendIMState(PTI->wlrInput);
}
void Events::listener_TextInputDisable(void* owner, void* data) {
const auto PTI = (STextInput*)owner;
if (!g_pCompositor->m_sSeat.pCurrentIME) {
Debug::log(LOG, "Disabling TextInput in dead IME!");
return;
}
Debug::log(LOG, "Disabling IME state (TextInput)");
wlr_input_method_v2_send_deactivate(g_pCompositor->m_sSeat.pCurrentIME);
g_pInputManager->sendIMState(PTI->wlrInput);
}
void Events::listener_TextInputDestroy(void* owner, void* data) {
const auto PTI = (STextInput*)owner;
Debug::log(LOG, "Destroying IME state (TextInput)");
g_pInputManager->destroyTextInput(PTI);
}
STextInput* CInputManager::getFocusedTextInput() {
for (auto& ti : m_lTextInputs) {
if (ti.pSurface)
return &ti;
}
return nullptr;
}
void CInputManager::textInputSetFocus(STextInput* pInput, wlr_surface* pSurface) {
if (pInput->pSurface == pSurface)
return;
if (pInput->pSurface)
wlr_text_input_v3_send_leave(pInput->wlrInput);
pInput->pSurface = pSurface;
wlr_text_input_v3_send_enter(pInput->wlrInput, pSurface);
}
void CInputManager::textInputSetFocusAll(wlr_surface* pSurface) {
for (auto& ti : m_lTextInputs) {
textInputSetFocus(&ti, pSurface);
}
}

View File

@ -3,6 +3,7 @@
#include "../defines.hpp"
#include <list>
#include "../helpers/WLClasses.hpp"
#include "../helpers/TextInput.hpp"
#include "../Window.hpp"
class CInputManager {
@ -18,6 +19,7 @@ public:
void newMouse(wlr_input_device*);
void destroyKeyboard(SKeyboard*);
void destroyMouse(wlr_input_device*);
SKeyboard* getActiveKeyboard();
void constrainMouse(SMouse*, wlr_pointer_constraint_v1*);
void recheckConstraint(SMouse*);
@ -29,6 +31,14 @@ public:
void updateDragIcon();
// IME and text input
void createTextInput(wlr_text_input_v3*);
void destroyTextInput(STextInput*);
STextInput* getFocusedTextInput();
void textInputSetFocus(STextInput*, wlr_surface*);
void textInputSetFocusAll(wlr_surface*);
void sendIMState(wlr_text_input_v3*);
// for dragging floating windows
CWindow* currentlyDraggedWindow = nullptr;
@ -40,10 +50,14 @@ public:
private:
std::list<SKeyboard> m_lKeyboards;
std::list<SMouse> m_lMice;
std::list<SKeyboard> m_lKeyboards;
std::list<SMouse> m_lMice;
std::list<STextInput> m_lTextInputs;
SKeyboard* m_pActiveKeyboard = nullptr;
void mouseMoveUnified(uint32_t, bool refocus = false);
};
inline std::unique_ptr<CInputManager> g_pInputManager;