From 35ba6a2f719327e2ee3f31d5baa04f0ec5a0a09e Mon Sep 17 00:00:00 2001 From: Yuqian Yang Date: Tue, 30 Sep 2025 00:16:13 +0800 Subject: Impl input method for xim. --- include/cru/platform/gui/Keyboard.h | 10 ++-- include/cru/platform/gui/xcb/InputMethod.h | 77 ++++++++++++++++++++++++++++ include/cru/platform/gui/xcb/UiApplication.h | 4 ++ include/cru/platform/gui/xcb/Window.h | 4 ++ 4 files changed, 90 insertions(+), 5 deletions(-) create mode 100644 include/cru/platform/gui/xcb/InputMethod.h (limited to 'include/cru/platform') diff --git a/include/cru/platform/gui/Keyboard.h b/include/cru/platform/gui/Keyboard.h index eb1cc76e..97665e41 100644 --- a/include/cru/platform/gui/Keyboard.h +++ b/include/cru/platform/gui/Keyboard.h @@ -118,16 +118,16 @@ struct TagKeyModifier {}; using KeyModifier = Bitmask; struct KeyModifiers { - static constexpr KeyModifier none{0}; - static constexpr KeyModifier shift{0b1}; - static constexpr KeyModifier ctrl{0b10}; - static constexpr KeyModifier alt{0b100}; - static constexpr KeyModifier command{0b1000}; static constexpr KeyModifier None = KeyModifier::FromOffset(0); static constexpr KeyModifier Shift = KeyModifier::FromOffset(1); static constexpr KeyModifier Ctrl = KeyModifier::FromOffset(2); static constexpr KeyModifier Alt = KeyModifier::FromOffset(3); static constexpr KeyModifier Command = KeyModifier::FromOffset(4); + static constexpr KeyModifier none = None; + static constexpr KeyModifier shift = Shift; + static constexpr KeyModifier ctrl = Ctrl; + static constexpr KeyModifier alt = Alt; + static constexpr KeyModifier command = Command; }; #ifdef CRU_PLATFORM_OSX diff --git a/include/cru/platform/gui/xcb/InputMethod.h b/include/cru/platform/gui/xcb/InputMethod.h new file mode 100644 index 00000000..286f3158 --- /dev/null +++ b/include/cru/platform/gui/xcb/InputMethod.h @@ -0,0 +1,77 @@ +#pragma once + +#include "../InputMethod.h" +#include "Base.h" + +#include +#include +#include + +namespace cru::platform::gui::xcb { +class XcbUiApplication; +class XcbWindow; + +class XcbXimInputMethodManager : public XcbResource { + friend XcbUiApplication; + + public: + XcbXimInputMethodManager(XcbUiApplication* application); + ~XcbXimInputMethodManager() override; + + xcb_xim_t* GetXcbXim(); + + private: + void DispatchCommit(xcb_xim_t* im, xcb_xic_t ic, std::string text); + void DispatchComposition(xcb_xim_t* im, xcb_xic_t ic, CompositionText text); + + bool HandleXEvent(xcb_generic_event_t* event); + + private: + XcbUiApplication* application_; + xcb_xim_t* im_; +}; + +class XcbXimInputMethodContext : public XcbResource, + public virtual IInputMethodContext { + friend XcbXimInputMethodManager; + + public: + XcbXimInputMethodContext(XcbXimInputMethodManager* manager, + XcbWindow* window); + ~XcbXimInputMethodContext() override; + + bool ShouldManuallyDrawCompositionText() override; + + void EnableIME() override; + void DisableIME() override; + + void CompleteComposition() override; + void CancelComposition() override; + CompositionText GetCompositionText() override; + + // Set the candidate window left-top. Relative to window left-top. Use this + // method to prepare typing. + void SetCandidateWindowPosition(const Point& point) override; + + IEvent* CompositionStartEvent() override; + IEvent* CompositionEndEvent() override; + IEvent* CompositionEvent() override; + IEvent* TextEvent() override; + + private: + void CreateIc(xcb_window_t window); + void DestroyIc(); + + private: + XcbXimInputMethodManager* manager_; + XcbWindow* window_; + bool enabled_; + std::optional ic_; + CompositionText composition_text_; + + Event composition_start_event_; + Event composition_end_event_; + Event composition_event_; + Event text_event_; +}; +} // namespace cru::platform::gui::xcb diff --git a/include/cru/platform/gui/xcb/UiApplication.h b/include/cru/platform/gui/xcb/UiApplication.h index b8de86f2..d6971099 100644 --- a/include/cru/platform/gui/xcb/UiApplication.h +++ b/include/cru/platform/gui/xcb/UiApplication.h @@ -13,6 +13,7 @@ namespace cru::platform::gui::xcb { class XcbWindow; class XcbCursorManager; +class XcbXimInputMethodManager; class XcbUiApplication : public XcbResource, public virtual IUiApplication { friend XcbWindow; @@ -49,6 +50,8 @@ class XcbUiApplication : public XcbResource, public virtual IUiApplication { #undef CRU_XCB_UI_APPLICATION_DEFINE_XCB_ATOM + XcbXimInputMethodManager* GetXcbXimInputMethodManager(); + public: int Run() override; @@ -100,5 +103,6 @@ class XcbUiApplication : public XcbResource, public virtual IUiApplication { std::vector windows_; XcbCursorManager* cursor_manager_; + XcbXimInputMethodManager* input_method_manager_; }; } // namespace cru::platform::gui::xcb diff --git a/include/cru/platform/gui/xcb/Window.h b/include/cru/platform/gui/xcb/Window.h index 61e4b616..e330ba7c 100644 --- a/include/cru/platform/gui/xcb/Window.h +++ b/include/cru/platform/gui/xcb/Window.h @@ -12,6 +12,7 @@ namespace cru::platform::gui::xcb { class XcbUiApplication; class XcbCursor; +class XcbXimInputMethodContext; class XcbWindow : public XcbResource, public virtual INativeWindow { friend XcbUiApplication; @@ -79,6 +80,8 @@ class XcbWindow : public XcbResource, public virtual INativeWindow { public: std::optional GetXcbWindow(); + XcbUiApplication* GetXcbUiApplication(); + bool HasFocus(); private: xcb_window_t DoCreateWindow(); @@ -112,6 +115,7 @@ class XcbWindow : public XcbResource, public virtual INativeWindow { std::shared_ptr cursor_; XcbWindow* parent_; + XcbXimInputMethodContext* input_method_; Event create_event_; Event destroy_event_; -- cgit v1.2.3