diff options
author | Yuqian Yang <crupest@crupest.life> | 2025-10-10 16:57:16 +0800 |
---|---|---|
committer | Yuqian Yang <crupest@crupest.life> | 2025-10-10 16:57:16 +0800 |
commit | db26d6e0785f9e1a8420130f9441c72c6a842df5 (patch) | |
tree | b861819c6e68b6e1bf10963de314cf3c6b9f09f3 | |
parent | 79d77619281607f9b189de21493736c61fbcac7c (diff) | |
download | cru-db26d6e0785f9e1a8420130f9441c72c6a842df5.tar.gz cru-db26d6e0785f9e1a8420130f9441c72c6a842df5.tar.bz2 cru-db26d6e0785f9e1a8420130f9441c72c6a842df5.zip |
Fix text box on Linux.
-rw-r--r-- | include/cru/platform/gui/xcb/UiApplication.h | 3 | ||||
-rw-r--r-- | src/platform/gui/xcb/InputMethod.cpp | 25 | ||||
-rw-r--r-- | src/platform/gui/xcb/UiApplication.cpp | 27 |
3 files changed, 36 insertions, 19 deletions
diff --git a/include/cru/platform/gui/xcb/UiApplication.h b/include/cru/platform/gui/xcb/UiApplication.h index 3f27ffe6..ab481c79 100644 --- a/include/cru/platform/gui/xcb/UiApplication.h +++ b/include/cru/platform/gui/xcb/UiApplication.h @@ -86,7 +86,8 @@ class XcbUiApplication : public XcbResource, public virtual IUiApplication { IMenu* GetApplicationMenu() override; private: - void HandleXEvents(); + void DispatchXEventToWindows(xcb_generic_event_t* event); + void PollAllXEvents(); void RegisterWindow(XcbWindow* window); void UnregisterWindow(XcbWindow* window); diff --git a/src/platform/gui/xcb/InputMethod.cpp b/src/platform/gui/xcb/InputMethod.cpp index 90bc8f66..2b495925 100644 --- a/src/platform/gui/xcb/InputMethod.cpp +++ b/src/platform/gui/xcb/InputMethod.cpp @@ -26,13 +26,20 @@ XcbXimInputMethodManager::XcbXimInputMethodManager( void *user_data) { auto manager = static_cast<XcbXimInputMethodManager *>(user_data); if ((event->response_type & ~0x80) == XCB_KEY_PRESS) { - manager->DispatchCommit( - im, ic, + auto text = manager->application_->GetXcbKeyboardManager()->KeycodeToUtf8( - event->detail)); + event->detail); + if (text.empty() || text == "\b") { + if (manager->forward_event_callback_) { + manager->forward_event_callback_(event); + } + } else { + manager->DispatchCommit(im, ic, std::move(text)); + } } else { - if (manager->forward_event_callback_) + if (manager->forward_event_callback_) { manager->forward_event_callback_(event); + } } }, .commit_string = @@ -81,7 +88,7 @@ xcb_xim_t *XcbXimInputMethodManager::GetXcbXim() { return im_; } void XcbXimInputMethodManager::DispatchCommit(xcb_xim_t *im, xcb_xic_t ic, std::string text) { - CRU_LOG_TAG_INFO("IC {} dispatch commit string: {}", ic, text); + CRU_LOG_TAG_DEBUG("IC {} dispatch commit string: {}", ic, text); for (auto window : application_->GetAllWindow()) { auto input_method_context = window->GetInputMethodContext(); auto context = CheckPlatform<XcbXimInputMethodContext>(input_method_context, @@ -185,7 +192,7 @@ static void EmptyXimDestroyIcCallback(xcb_xim_t *im, xcb_xic_t ic, void XcbXimInputMethodContext::SetCandidateWindowPosition(const Point &point) { if (!ic_) return; - CRU_LOG_TAG_INFO("IC {} set candidate window position: {}", *ic_, point); + CRU_LOG_TAG_DEBUG("IC {} set candidate window position: {}", *ic_, point); xcb_point_t spot; spot.x = point.x; @@ -221,7 +228,7 @@ void XcbXimInputMethodContext::CreateIc(xcb_window_t window) { auto XimCreateIcCallback = [](xcb_xim_t *im, xcb_xic_t ic, void *user_data) { auto context = static_cast<XcbXimInputMethodContext *>(user_data); context->ic_ = ic; - CRU_LOG_TAG_INFO("IC {} is created.", ic); + CRU_LOG_TAG_DEBUG("IC {} is created.", ic); if (context->window_->HasFocus()) { xcb_xim_set_ic_focus(context->manager_->GetXcbXim(), ic); } @@ -232,14 +239,14 @@ void XcbXimInputMethodContext::CreateIc(xcb_window_t window) { xcb_xim_create_ic(manager_->GetXcbXim(), XimCreateIcCallback, this, XCB_XIM_XNInputStyle, &input_style, XCB_XIM_XNClientWindow, &window, XCB_XIM_XNFocusWindow, &window, NULL); - CRU_LOG_TAG_INFO("Create XIM IC."); + CRU_LOG_TAG_DEBUG("Create XIM IC."); } void XcbXimInputMethodContext::DestroyIc() { if (!ic_) return; xcb_xim_destroy_ic(manager_->GetXcbXim(), *ic_, EmptyXimDestroyIcCallback, this); - CRU_LOG_TAG_INFO("Destroy XIM IC."); + CRU_LOG_TAG_DEBUG("Destroy XIM IC."); ic_ = std::nullopt; } diff --git a/src/platform/gui/xcb/UiApplication.cpp b/src/platform/gui/xcb/UiApplication.cpp index 07fd5a36..a0a949b7 100644 --- a/src/platform/gui/xcb/UiApplication.cpp +++ b/src/platform/gui/xcb/UiApplication.cpp @@ -32,7 +32,7 @@ XcbUiApplication::XcbUiApplication( this->CheckXcbConnectionError(); event_loop_.SetPoll(xcb_get_file_descriptor(connection), POLLIN, - [this](auto) { HandleXEvents(); }); + [this](auto) { PollAllXEvents(); }); const xcb_setup_t *setup = xcb_get_setup(connection); xcb_screen_iterator_t iter = xcb_setup_roots_iterator(setup); @@ -40,6 +40,11 @@ XcbUiApplication::XcbUiApplication( cursor_manager_ = new XcbCursorManager(this); input_method_manager_ = new XcbXimInputMethodManager(this); + input_method_manager_->SetXimServerUnprocessedXEventCallback( + [this](xcb_key_press_event_t *event) { + DispatchXEventToWindows((xcb_generic_event_t *)event); + }); + keyboard_manager_ = new XcbKeyboardManager(this); clipboard_ = new XcbClipboard(this); } @@ -142,17 +147,21 @@ void XcbUiApplication::CancelTimer(long long id) { return event_loop_.CancelTimer(static_cast<int>(id)); } -void XcbUiApplication::HandleXEvents() { +void XcbUiApplication::DispatchXEventToWindows(xcb_generic_event_t *event) { + auto event_xcb_window = XcbWindow::GetEventWindow(event); + for (auto window : windows_) { + if (window->GetXcbWindow() == event_xcb_window) { + window->HandleEvent(event); + break; + } + } +} + +void XcbUiApplication::PollAllXEvents() { xcb_generic_event_t *event; while ((event = xcb_poll_for_event(xcb_connection_))) { if (!input_method_manager_->HandleXEvent(event)) { - auto event_xcb_window = XcbWindow::GetEventWindow(event); - for (auto window : windows_) { - if (window->GetXcbWindow() == event_xcb_window) { - window->HandleEvent(event); - break; - } - } + DispatchXEventToWindows(event); } ::free(event); } |