mirror of https://github.com/hyprwm/Hyprland
Added some IME (broken for now... i think)
This commit is contained in:
parent
0273d21a77
commit
727c56df2f
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
// ------------------------------------------------- //
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
};
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
};
|
|
@ -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 {
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
Loading…
Reference in New Issue