diff --git a/chewing_tip/ChewingTextService.cpp b/chewing_tip/ChewingTextService.cpp index 6081031..88d4712 100644 --- a/chewing_tip/ChewingTextService.cpp +++ b/chewing_tip/ChewingTextService.cpp @@ -96,7 +96,21 @@ TextService::TextService(): // add preserved keys addPreservedKey(VK_SPACE, TF_MOD_SHIFT, g_shiftSpaceGuid); // shift + space +} + +TextService::~TextService(void) { + if(popupMenu_) + ::DestroyMenu(popupMenu_); + + if(messageWindow_) + hideMessage(); + + freeChewingContext(); + OutputDebugStringW(L"[chewing] Unloaded\n"); +} +// virtual +void TextService::onActivate() { // add language bar buttons // siwtch Chinese/English modes TF_LANGBARITEMINFO info = { @@ -171,20 +185,7 @@ TextService::TextService(): ); addButton(imeModeIcon_.get()); } -} -TextService::~TextService(void) { - if(popupMenu_) - ::DestroyMenu(popupMenu_); - - if(messageWindow_) - hideMessage(); - - freeChewingContext(); -} - -// virtual -void TextService::onActivate() { config().reloadIfNeeded(); initChewingContext(); updateLangButtons(); @@ -195,6 +196,18 @@ void TextService::onActivate() { // virtual void TextService::onDeactivate() { + // Remove all buttons to avoid reference cycles + removeButton(switchLangButton_.get()); + switchLangButton_ = nullptr; + removeButton(switchShapeButton_.get()); + switchShapeButton_ = nullptr; + removeButton(settingsMenuButton_.get()); + settingsMenuButton_ = nullptr; + if (imeModeIcon_) { + removeButton(imeModeIcon_.get()); + imeModeIcon_ = nullptr; + } + lastKeyDownCode_ = 0; freeChewingContext(); diff --git a/chewing_tip/TextService.cpp b/chewing_tip/TextService.cpp index d471c43..33838d4 100644 --- a/chewing_tip/TextService.cpp +++ b/chewing_tip/TextService.cpp @@ -99,6 +99,23 @@ void TextService::addButton(ITfLangBarItemButton* button) { } } +void TextService::removeButton(ITfLangBarItemButton* button) { + if(button) { + winrt::com_ptr btn; + btn.copy_from(button); + auto it = find(langBarButtons_.begin(), langBarButtons_.end(), btn); + if(it != langBarButtons_.end()) { + if (threadMgr_) { + winrt::com_ptr langBarItemMgr; + if(threadMgr_->QueryInterface(IID_ITfLangBarItemMgr, langBarItemMgr.put_void()) == S_OK) { + langBarItemMgr->RemoveItem(button); + } + } + langBarButtons_.erase(it); + } + } +} + // preserved key void TextService::addPreservedKey(UINT keyCode, UINT modifiers, const GUID& guid) { PreservedKey preservedKey; diff --git a/chewing_tip/TextService.h b/chewing_tip/TextService.h index 2556690..b6f1a98 100644 --- a/chewing_tip/TextService.h +++ b/chewing_tip/TextService.h @@ -64,6 +64,7 @@ class TextService: // language bar buttons void addButton(ITfLangBarItemButton* button); + void removeButton(ITfLangBarItemButton* button); // preserved keys void addPreservedKey(UINT keyCode, UINT modifiers, const GUID& guid); diff --git a/chewing_tip/src/lang_bar.rs b/chewing_tip/src/lang_bar.rs index ae1ad10..cb2b7e2 100644 --- a/chewing_tip/src/lang_bar.rs +++ b/chewing_tip/src/lang_bar.rs @@ -40,7 +40,6 @@ pub(crate) unsafe trait ILangBarButton: ITfLangBarItemButton { fn set_enabled(&self, enabled: bool) -> Result<()>; } -#[derive(Debug)] #[implement(ITfLangBarItem, ITfLangBarItemButton, ITfSource, ILangBarButton)] struct LangBarButton { info: TF_LANGBARITEMINFO, @@ -69,9 +68,13 @@ unsafe extern "C" fn CreateLangBarButton( icon: HICON, menu: HMENU, command_id: u32, - run_command: IRunCommand, + run_command: *mut IRunCommand, ret: *mut *mut c_void, ) { + let binding = run_command.cast(); + let run_command_ref = + IRunCommand::from_raw_borrowed(&binding).expect("invalid IRunCommand pointer"); + let run_command: IRunCommand = run_command_ref.cast().expect("invalid IRunCommand pointer"); let lang_bar_btn = LangBarButton { info, status: Cell::new(0),