aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYuqian Yang <crupest@crupest.life>2025-10-10 16:57:16 +0800
committerYuqian Yang <crupest@crupest.life>2025-10-10 16:57:16 +0800
commitdb26d6e0785f9e1a8420130f9441c72c6a842df5 (patch)
treeb861819c6e68b6e1bf10963de314cf3c6b9f09f3
parent79d77619281607f9b189de21493736c61fbcac7c (diff)
downloadcru-db26d6e0785f9e1a8420130f9441c72c6a842df5.tar.gz
cru-db26d6e0785f9e1a8420130f9441c72c6a842df5.tar.bz2
cru-db26d6e0785f9e1a8420130f9441c72c6a842df5.zip
Fix text box on Linux.
-rw-r--r--include/cru/platform/gui/xcb/UiApplication.h3
-rw-r--r--src/platform/gui/xcb/InputMethod.cpp25
-rw-r--r--src/platform/gui/xcb/UiApplication.cpp27
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);
}