diff --git a/misc/fcitx5-vmk-server@.service b/misc/fcitx5-vmk-server@.service index 39c338e..89835d7 100644 --- a/misc/fcitx5-vmk-server@.service +++ b/misc/fcitx5-vmk-server@.service @@ -16,7 +16,7 @@ Type=simple ExecStart=/usr/bin/fcitx5-vmk-server -u %i Restart=on-failure -RestartSec=5 +RestartSec=0 [Install] WantedBy=multi-user.target \ No newline at end of file diff --git a/server/vmk-server.cpp b/server/vmk-server.cpp index b5dceee..fba91d3 100644 --- a/server/vmk-server.cpp +++ b/server/vmk-server.cpp @@ -123,10 +123,15 @@ int main(int argc, char* argv[]) { if (uinput_fd_ >= 0) { ioctl(uinput_fd_, UI_SET_EVBIT, EV_KEY); ioctl(uinput_fd_, UI_SET_KEYBIT, KEY_BACKSPACE); - struct uinput_user_dev uidev{}; - snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "Fcitx5_Uinput_Server"); - (void)write(uinput_fd_, &uidev, sizeof(uidev)); + struct uinput_setup usetup; + memset(&usetup, 0, sizeof(usetup)); + usetup.id.bustype = BUS_USB; + usetup.id.vendor = 0x1234; + usetup.id.product = 0x5678; + strncpy(usetup.name, "VMK-Uinput-Server", UINPUT_MAX_NAME_SIZE - 1); + ioctl(uinput_fd_, UI_DEV_SETUP, &usetup); ioctl(uinput_fd_, UI_DEV_CREATE); + sleep(1); } int server_fd = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0); // Non-blocking socket @@ -200,6 +205,10 @@ int main(int argc, char* argv[]) { if (pending_backspaces > 0) { send_single_backspace(); --pending_backspaces; + if (pending_backspaces == 0) { + char ack = '7'; + send(fds[3].fd, &ack, sizeof(ack), MSG_NOSIGNAL | MSG_DONTWAIT); + } } } diff --git a/src/ack-apps.h b/src/ack-apps.h new file mode 100644 index 0000000..ad1d602 --- /dev/null +++ b/src/ack-apps.h @@ -0,0 +1,4 @@ +#include +#include + +static std::vector ack_apps = {"chrome", "chromium", "brave", "edge", "vivaldi", "opera", "coccoc", "cromite", "helium", "thorium", "slimjet", "yandex"}; \ No newline at end of file diff --git a/src/vmk-config.h b/src/vmk-config.h index fc3b5bf..6cd0ae4 100644 --- a/src/vmk-config.h +++ b/src/vmk-config.h @@ -135,6 +135,7 @@ namespace fcitx { Option autoNonVnRestore{this, "AutoNonVnRestore", _("Auto restore keys with invalid words"), true}; Option modernStyle{this, "ModernStyle", _("Use oà, _uý (instead of òa, úy)"), true}; Option freeMarking{this, "FreeMarking", _("Allow type with more freedom"), true}; + Option fixVmk1WithAck{this, "FixVmk1WithAck", _("Fix uinput mode with ack"), false}; SubConfigOption customKeymap{this, "CustomKeymap", _("Custom Keymap"), "fcitx://config/addon/vmk/custom_keymap"};); } // namespace fcitx diff --git a/src/vmk.cpp b/src/vmk.cpp index e5fc45a..43818cf 100644 --- a/src/vmk.cpp +++ b/src/vmk.cpp @@ -7,7 +7,7 @@ * */ #include "vmk.h" -#include "vmk-config.h" +#include "ack-apps.h" #include #include @@ -68,9 +68,8 @@ std::atomic needEngineReset{false}; std::string BASE_SOCKET_PATH; // Global flag to signal mouse click for closing app mode menu static std::atomic g_mouse_clicked{false}; - std::atomic is_deleting_{false}; -static const int MAX_BACKSPACE_COUNT = 15; +static const int MAX_BACKSPACE_COUNT = 8; std::string SubstrChar(const std::string& s, size_t start, size_t len); int compareAndSplitStrings(const std::string& A, const std::string& B, std::string& commonPrefix, std::string& deletedPart, std::string& addedPart); std::once_flag monitor_init_flag; @@ -78,6 +77,7 @@ std::atomic stop_flag_monitor{false}; std::atomic monitor_running{false}; int uinput_client_fd_ = -1; int realtextLen = 0; +bool waitAck = false; std::atomic mouse_socket_fd{-1}; std::atomic replacement_start_ms_{0}; @@ -305,6 +305,11 @@ namespace fcitx { send(uinput_client_fd_, &count, sizeof(count), MSG_NOSIGNAL); } } + + if (waitAck) { + char ack; + recv(uinput_client_fd_, &ack, sizeof(ack), MSG_NOSIGNAL); + } } void replayBufferToEngine(const std::string& buffer) { @@ -1170,6 +1175,9 @@ namespace fcitx { } void clearAllBuffers() { + if (is_deleting_.load(std::memory_order_acquire)) { + return; + } oldPreBuffer_.clear(); history_.clear(); if (!is_deleting_.load(std::memory_order_acquire)) { @@ -1463,6 +1471,18 @@ namespace fcitx { })); uiManager.registerAction("vmk-freemarking", freeMarkingAction_.get()); + fixVmk1WithAckAction_ = std::make_unique(); + fixVmk1WithAckAction_->setLongText(_("Fix uinput mode with ack")); + fixVmk1WithAckAction_->setIcon("network-transmit-receive"); + fixVmk1WithAckAction_->setCheckable(true); + connections_.emplace_back(fixVmk1WithAckAction_->connect([this](InputContext* ic) { + config_.fixVmk1WithAck.setValue(!*config_.fixVmk1WithAck); + saveConfig(); + refreshOption(); + updateFixVmk1WithAckAction(ic); + })); + uiManager.registerAction("vmk-fixvmk1withack", fixVmk1WithAckAction_.get()); + reloadConfig(); globalMode_ = modeStringToEnum(config_.mode.value()); updateModeAction(nullptr); @@ -1530,6 +1550,7 @@ namespace fcitx { updateAutoNonVnRestoreAction(nullptr); updateModernStyleAction(nullptr); updateFreeMarkingAction(nullptr); + updateFixVmk1WithAckAction(nullptr); } void vmkEngine::setSubConfig(const std::string& path, const RawConfig& config) { @@ -1577,6 +1598,19 @@ namespace fcitx { updateInputMethodAction(event.inputContext()); updateCharsetAction(event.inputContext()); + if (*config_.fixVmk1WithAck) { + if (targetMode == VMKMode::VMK1 || targetMode == VMKMode::VMK1HC || targetMode == VMKMode::VMKSmooth) { + bool needWaitAck = false; + for (const auto& ackApp : ack_apps) { + if (appName.find(ackApp) != std::string::npos) { + needWaitAck = true; + break; + } + } + waitAck = needWaitAck; + } + } + setMode(targetMode, event.inputContext()); auto state = ic->propertyFor(&factory_); @@ -1597,6 +1631,7 @@ namespace fcitx { statusArea.addAction(StatusGroup::InputMethod, autoNonVnRestoreAction_.get()); statusArea.addAction(StatusGroup::InputMethod, modernStyleAction_.get()); statusArea.addAction(StatusGroup::InputMethod, freeMarkingAction_.get()); + statusArea.addAction(StatusGroup::InputMethod, fixVmk1WithAckAction_.get()); } void vmkEngine::keyEvent(const InputMethodEntry& entry, KeyEvent& keyEvent) { @@ -1786,7 +1821,9 @@ namespace fcitx { return; } - state->reset(); + if (event.type() == EventType::InputContextFocusOut) { + state->reset(); + } } void vmkEngine::deactivate(const InputMethodEntry& entry, InputContextEvent& event) { @@ -1918,6 +1955,15 @@ namespace fcitx { freeMarkingAction_->update(ic); } } + + void vmkEngine::updateFixVmk1WithAckAction(InputContext* ic) { + fixVmk1WithAckAction_->setChecked(*config_.fixVmk1WithAck); + fixVmk1WithAckAction_->setShortText(*config_.fixVmk1WithAck ? _("Fix Vmk1 With Ack: On") : _("Fix Vmk1 With Ack: Off")); + if (ic) { + fixVmk1WithAckAction_->update(ic); + } + } + void vmkEngine::loadAppRules() { appRules_.clear(); std::ifstream file(appRulesPath_); diff --git a/src/vmk.h b/src/vmk.h index c667c4f..0fb4290 100644 --- a/src/vmk.h +++ b/src/vmk.h @@ -148,6 +148,7 @@ namespace fcitx { void updateAutoNonVnRestoreAction(InputContext* ic); void updateModernStyleAction(InputContext* ic); void updateFreeMarkingAction(InputContext* ic); + void updateFixVmk1WithAckAction(InputContext* ic); void updateInputMethodAction(InputContext* ic); void updateCharsetAction(InputContext* ic); void populateConfig(); @@ -188,6 +189,7 @@ namespace fcitx { std::unique_ptr autoNonVnRestoreAction_; std::unique_ptr modernStyleAction_; std::unique_ptr freeMarkingAction_; + std::unique_ptr fixVmk1WithAckAction_; std::vector connections_; CGoObject dictionary_; // ibus-bamboo mode save/load