diff --git a/assets/po/zh_CN.po b/assets/po/zh_CN.po index 0367b8b..23fb357 100644 --- a/assets/po/zh_CN.po +++ b/assets/po/zh_CN.po @@ -16,18 +16,26 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: macosfrontend/macosfrontend.h:42 +#: macosfrontend/macosfrontend.h:43 msgid "App default IM" msgstr "应用默认输入法" -#: macosfrontend/macosfrontend.h:44 +#: macosfrontend/macosfrontend.h:45 msgid "Simulate key release" msgstr "模拟按键释放" -#: macosfrontend/macosfrontend.h:47 +#: macosfrontend/macosfrontend.h:48 msgid "Delay of simulated key release in milliseconds" msgstr "模拟按键释放延迟毫秒数" +#: macosfrontend/macosfrontend.h:51 +msgid "Monitor Pasteboard" +msgstr "监视剪贴板" + +#: macosfrontend/macosfrontend.h:53 +msgid "Poll Pasteboard interval (s)" +msgstr "轮询剪贴板的间隔(秒)" + #: macosnotifications/macosnotifications.h:20 msgid "Hidden Notifications" msgstr "隐藏通知" diff --git a/fcitx5-webview b/fcitx5-webview index da4b9ae..35c4323 160000 --- a/fcitx5-webview +++ b/fcitx5-webview @@ -1 +1 @@ -Subproject commit da4b9ae421f31b24be84a5484d1120fe91744117 +Subproject commit 35c43238a2d3925c35ecab3e2052978d5faaf045 diff --git a/macosfrontend/macosfrontend.cpp b/macosfrontend/macosfrontend.cpp index c76970b..ba68354 100644 --- a/macosfrontend/macosfrontend.cpp +++ b/macosfrontend/macosfrontend.cpp @@ -16,6 +16,8 @@ #include #include +#include "../fcitx5/src/modules/clipboard/clipboard_public.h" + namespace fcitx { MacosFrontend::MacosFrontend(Instance *instance) @@ -24,10 +26,38 @@ MacosFrontend::MacosFrontend(Instance *instance) reloadConfig(); } +// Runs on the fcitx thread. +void MacosFrontend::pollPasteboard() { + monitorPasteboardEvent_ = instance_->eventLoop().addTimeEvent( + CLOCK_MONOTONIC, + now(CLOCK_MONOTONIC) + *config_.pollPasteboardInterval * 1000000, + 100000, [this](EventSourceTime *time, uint64_t) { + if (!*config_.monitorPasteboard) { + return true; + } + if (auto clipboard = + instance_->addonManager().addon("clipboard", true)) { + bool isPassword = false; + const char *p = SwiftFrontend::getPasteboardString(&isPassword); + if (p) { + std::string str = p; + clipboard->call("", str, + isPassword); + FCITX_DEBUG() << "Add to clipboard: " << str; + } + } + time->setNextInterval(*config_.pollPasteboardInterval * 1000000); + time->setOneShot(); + return true; + }); + monitorPasteboardEvent_->setOneShot(); +} + void MacosFrontend::updateConfig() { simulateKeyRelease_ = config_.simulateKeyRelease.value(); simulateKeyReleaseDelay_ = static_cast(config_.simulateKeyReleaseDelay.value()) * 1000L; + pollPasteboard(); } void MacosFrontend::reloadConfig() { diff --git a/macosfrontend/macosfrontend.h b/macosfrontend/macosfrontend.h index cd3bc6b..2b7c243 100644 --- a/macosfrontend/macosfrontend.h +++ b/macosfrontend/macosfrontend.h @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -45,7 +46,12 @@ FCITX_CONFIGURATION( Option simulateKeyReleaseDelay{ this, "SimulateKeyReleaseDelay", _("Delay of simulated key release in milliseconds"), 100, - IntConstrain(10, 1500)};); + IntConstrain(10, 1500)}; + Option monitorPasteboard{this, "MonitorPasteboard", + _("Monitor Pasteboard"), false}; + Option pollPasteboardInterval{ + this, "PollPasteboardInterval", _("Poll Pasteboard interval (s)"), 2, + IntConstrain(1, 60)};); class MacosFrontend : public AddonInstance { public: @@ -75,6 +81,8 @@ class MacosFrontend : public AddonInstance { MacosFrontendConfig config_; bool simulateKeyRelease_; long simulateKeyReleaseDelay_; + std::unique_ptr monitorPasteboardEvent_; + void pollPasteboard(); static const inline std::string ConfPath = "conf/macosfrontend.conf"; diff --git a/macosfrontend/macosfrontend.swift b/macosfrontend/macosfrontend.swift index 8544ff3..dc9ad25 100644 --- a/macosfrontend/macosfrontend.swift +++ b/macosfrontend/macosfrontend.swift @@ -1,3 +1,4 @@ +import AppKit import InputMethodKit private var u16pos = 0 @@ -81,3 +82,22 @@ public func getCursorCoordinates( } return false } + +private var lastChangeCount = 0 +private var data: Data? +private let passwordType = NSPasteboard.PasteboardType("org.nspasteboard.ConcealedType") + +// Retrieve the current string data from the default pasteboard. +public func getPasteboardString(_ isPassword: UnsafeMutablePointer) -> UnsafePointer? { + let pasteboard = NSPasteboard.general + if pasteboard.changeCount == lastChangeCount { + return nil + } + lastChangeCount = pasteboard.changeCount + data = pasteboard.data(forType: .string) + if let data = data { + isPassword.pointee = pasteboard.string(forType: passwordType) != nil + return data.withUnsafeBytes { $0.baseAddress?.assumingMemoryBound(to: CChar.self) } + } + return nil +} diff --git a/webpanel/webpanel.cpp b/webpanel/webpanel.cpp index 91ef9a4..942e6ce 100644 --- a/webpanel/webpanel.cpp +++ b/webpanel/webpanel.cpp @@ -323,10 +323,12 @@ void WebPanel::update(UserInterfaceComponent component, scrollState_ = candidate_window::scroll_state_t::none; } window_->set_paging_buttons(pageable, hasPrev, hasNext); + window_->set_layout(layout); window_->set_writing_mode(writingMode); + // Must be called after set_layout and set_writing_mode so that proper + // states are read after set. window_->set_candidates(candidates, highlighted, scrollState_, false, false); - window_->set_layout(layout); updatePanelShowFlags(!candidates.empty(), PanelShowFlag::HasCandidates); updateClient(inputContext); showAsync(panelShow_); @@ -358,8 +360,7 @@ void WebPanel::updateInputPanel(const Text &preedit, const Text &auxUp, void WebPanel::updateClient(InputContext *ic) { if (auto macosIC = dynamic_cast(ic)) { - macosIC->setDummyPreedit((panelShow_ & PanelShowFlag::HasPreedit) | - (panelShow_ & PanelShowFlag::HasCandidates)); + macosIC->setDummyPreedit(bool(panelShow_)); if (!macosIC->isSyncEvent) { macosIC->commitAndSetPreeditAsync(); }