From 0989ef207351294fa5b6810b7cf59c790bbbfd3c Mon Sep 17 00:00:00 2001 From: Yohei Yukawa Date: Sun, 10 Jan 2016 00:16:02 -0800 Subject: [PATCH] Update status icon even for Windows Store Apps. On Windows 10 and later, Windows Store Apps can run in a window mode, and IME status icons on the notification area are expected to be updated. This means that we have to initialize and update status icon via LanguageBar API even for Windows Store Apps. For the simplicity, with this CL, we start initializing and updating status icons on LauguageBar even in immersive mode on Windows 8/8.1. This can introduce some unnecessary overhead for those platforms but basically no user-visible change should happen on Windows 8/8.1. This CL also makes sure to update LanguageBar when ITfThreadMgrEventSink::OnSetFocus is called. This has not been obvious in desktop apps but for Store Apps the lack of force update of LanguageBar in ITfThreadMgrEventSink::OnSetFocus results in a stale icon state on the language bar, which is so confusing. Closes #350. BUG=#350 TEST=manually done REF_BUG=24593171,24793812 REF_CL=104530061,105271317,105271439,105279539,105283782 --- src/mozc_version_template.txt | 2 +- src/win32/tip/tip_lang_bar.cc | 4 + src/win32/tip/tip_lang_bar.h | 3 + src/win32/tip/tip_text_service.cc | 19 +++-- src/win32/tip/tip_text_service.h | 5 ++ src/win32/tip/tip_ui_handler.cc | 88 +++++++++++++++++++- src/win32/tip/tip_ui_handler.h | 2 + src/win32/tip/tip_ui_handler_conventional.cc | 50 +---------- 8 files changed, 111 insertions(+), 62 deletions(-) diff --git a/src/mozc_version_template.txt b/src/mozc_version_template.txt index 0383bc4af..47e39243e 100644 --- a/src/mozc_version_template.txt +++ b/src/mozc_version_template.txt @@ -1,6 +1,6 @@ MAJOR=2 MINOR=17 -BUILD=2308 +BUILD=2309 REVISION=102 # NACL_DICTIONARY_VERSION is the target version of the system dictionary to be # downloaded by NaCl Mozc. diff --git a/src/win32/tip/tip_lang_bar.cc b/src/win32/tip/tip_lang_bar.cc index 647252aac..4faf141d2 100644 --- a/src/win32/tip/tip_lang_bar.cc +++ b/src/win32/tip/tip_lang_bar.cc @@ -462,6 +462,10 @@ HRESULT TipLangBar::UpdateMenu(bool enabled, uint32 composition_mode) { return result; } +bool TipLangBar::IsInitialized() const { + return input_button_menu_ || input_mode_button_for_win8_; +} + } // namespace tsf } // namespace win32 } // namespace mozc diff --git a/src/win32/tip/tip_lang_bar.h b/src/win32/tip/tip_lang_bar.h index 6e2b437da..b87c52cad 100644 --- a/src/win32/tip/tip_lang_bar.h +++ b/src/win32/tip/tip_lang_bar.h @@ -96,6 +96,9 @@ class TipLangBar { // Updates the selected menu in the language bar. HRESULT UpdateMenu(bool enabled, uint32 composition_mode); + // Returns true if this instance is already initialized. + bool IsInitialized() const; + private: // Represents the language bar item manager iff the running OS is Windows 8. // NOTE: We must use the same instance of this class to initialize and diff --git a/src/win32/tip/tip_text_service.cc b/src/win32/tip/tip_text_service.cc index e75070b66..23f5a13ad 100644 --- a/src/win32/tip/tip_text_service.cc +++ b/src/win32/tip/tip_text_service.cc @@ -608,9 +608,7 @@ class TipTextServiceImpl UninitKeyEventSink(); // Remove our button menus from the language bar. - if (!IsImmersiveUI()) { - UninitLanguageBar(); - } + UninitLanguageBar(); // Stop advising the ITfFunctionProvider events. UninitFunctionProvider(); @@ -716,12 +714,10 @@ class TipTextServiceImpl return Deactivate(); } - if (!IsImmersiveUI()) { - result = InitLanguageBar(); - if (FAILED(result)) { - LOG(ERROR) << "InitLanguageBar failed: " << result; - return result; - } + result = InitLanguageBar(); + if (FAILED(result)) { + LOG(ERROR) << "InitLanguageBar failed: " << result; + return result; } // Start advising the keyboard events (ITfKeyEvent) to this object. @@ -1152,6 +1148,10 @@ class TipTextServiceImpl langbar_.UpdateMenu(enabled, mozc_mode); } + virtual bool IsLangbarInitialized() const { + return langbar_.IsInitialized(); + } + // Following functions are private utilities. static void StorePointerForCurrentThread(TipTextServiceImpl *impl) { if (g_module_unloaded) { @@ -1182,6 +1182,7 @@ class TipTextServiceImpl } EnsurePrivateContextExists(context); } + TipUiHandler::OnDocumentMgrChanged(this, document_mgr); TipEditSession::OnSetFocusAsync(this, document_mgr); return S_OK; } diff --git a/src/win32/tip/tip_text_service.h b/src/win32/tip/tip_text_service.h index 5de0d2be0..7e8d28960 100644 --- a/src/win32/tip/tip_text_service.h +++ b/src/win32/tip/tip_text_service.h @@ -73,7 +73,12 @@ class TipTextService : public IUnknown { // the reference count of the returned object. virtual ITfCompositionSink *CreateCompositionSink(ITfContext *context) = 0; + // Updates the language bar as needed. Does nothing if the language bar is + // not available. virtual void UpdateLangbar(bool enabled, uint32 mozc_mode) = 0; + + // Returns true if the language bar is initialized. + virtual bool IsLangbarInitialized() const = 0; }; class TipTextServiceFactory { diff --git a/src/win32/tip/tip_ui_handler.cc b/src/win32/tip/tip_ui_handler.cc index f34908f8e..eff8c42e7 100644 --- a/src/win32/tip/tip_ui_handler.cc +++ b/src/win32/tip/tip_ui_handler.cc @@ -29,15 +29,84 @@ #include "win32/tip/tip_ui_handler.h" +#define _ATL_NO_AUTOMATIC_NAMESPACE +#define _WTL_NO_AUTOMATIC_NAMESPACE +#include +#include +#include + #include "base/logging.h" #include "base/util.h" +#include "protocol/commands.pb.h" +#include "win32/tip/tip_input_mode_manager.h" +#include "win32/tip/tip_status.h" #include "win32/tip/tip_text_service.h" +#include "win32/tip/tip_thread_context.h" #include "win32/tip/tip_ui_handler_conventional.h" #include "win32/tip/tip_ui_handler_immersive.h" +using ATL::CComPtr; +using ::mozc::commands::CompositionMode; + namespace mozc { namespace win32 { namespace tsf { +namespace { + +void UpdateLanguageBarOnFocusChange(TipTextService *text_service, + ITfDocumentMgr *document_manager) { + if (!text_service) { + return; + } + + if (!text_service->IsLangbarInitialized()) { + // If language bar is not initialized, there is nothing to do here. + return; + } + + HRESULT result = S_OK; + ITfThreadMgr *thread_manager = text_service->GetThreadManager(); + + if (thread_manager == nullptr) { + return; + } + + bool disabled = false; + { + if (document_manager == nullptr) { + // When |document_manager| is null, we should show "disabled" icon + // as if |ImmAssociateContext(window_handle, nullptr)| was called. + disabled = true; + } else { + CComPtr context; + result = document_manager->GetTop(&context); + if (SUCCEEDED(result)) { + disabled = TipStatus::IsDisabledContext(context); + } + } + } + + const TipInputModeManager *input_mode_manager = + text_service->GetThreadContext()->GetInputModeManager(); + const bool open = input_mode_manager->GetEffectiveOpenClose(); + const CompositionMode mozc_mode = + open ? static_cast( + input_mode_manager->GetEffectiveConversionMode()) + : commands::DIRECT; + text_service->UpdateLangbar(!disabled, static_cast(mozc_mode)); +} + +bool UpdateInternal(TipTextService *text_service, + ITfContext *context, + TfEditCookie read_cookie) { + if (text_service->IsImmersiveUI()) { + return TipUiHandlerImmersive::Update(text_service, context, read_cookie); + } else { + return TipUiHandlerConventional::Update(text_service, context, read_cookie); + } +} + +} // namespace ITfUIElement *TipUiHandler::CreateUI(UiType type, TipTextService *text_service, @@ -76,6 +145,11 @@ void TipUiHandler::OnDeactivate(TipTextService *text_service) { } } +void TipUiHandler::OnDocumentMgrChanged(TipTextService *text_service, + ITfDocumentMgr *document_manager) { + UpdateLanguageBarOnFocusChange(text_service, document_manager); +} + void TipUiHandler::OnFocusChange(TipTextService *text_service, ITfDocumentMgr *focused_document_manager) { if (text_service->IsImmersiveUI()) { @@ -85,16 +159,24 @@ void TipUiHandler::OnFocusChange(TipTextService *text_service, TipUiHandlerConventional::OnFocusChange( text_service, focused_document_manager); } + UpdateLanguageBarOnFocusChange(text_service, focused_document_manager); } bool TipUiHandler::Update(TipTextService *text_service, ITfContext *context, TfEditCookie read_cookie) { - if (text_service->IsImmersiveUI()) { - return TipUiHandlerImmersive::Update(text_service, context, read_cookie); + const TipInputModeManager *input_mode_manager = + text_service->GetThreadContext()->GetInputModeManager(); + const bool open = input_mode_manager->GetEffectiveOpenClose(); + const CompositionMode mozc_mode = static_cast( + input_mode_manager->GetEffectiveConversionMode()); + const bool result = UpdateInternal(text_service, context, read_cookie); + if (open) { + text_service->UpdateLangbar(true, mozc_mode); } else { - return TipUiHandlerConventional::Update(text_service, context, read_cookie); + text_service->UpdateLangbar(true, commands::DIRECT); } + return result; } bool TipUiHandler::OnDllProcessAttach(HINSTANCE module_handle, diff --git a/src/win32/tip/tip_ui_handler.h b/src/win32/tip/tip_ui_handler.h index 125050b87..7f0cd31bb 100644 --- a/src/win32/tip/tip_ui_handler.h +++ b/src/win32/tip/tip_ui_handler.h @@ -57,6 +57,8 @@ class TipUiHandler { static void OnActivate(TipTextService *text_service); static void OnDeactivate(TipTextService *text_service); + static void OnDocumentMgrChanged(TipTextService *text_service, + ITfDocumentMgr *document_manager); static void OnFocusChange(TipTextService *text_service, ITfDocumentMgr *focused_document_manager); static bool Update(TipTextService *text_service, diff --git a/src/win32/tip/tip_ui_handler_conventional.cc b/src/win32/tip/tip_ui_handler_conventional.cc index 750a6a6d9..f6a502c08 100644 --- a/src/win32/tip/tip_ui_handler_conventional.cc +++ b/src/win32/tip/tip_ui_handler_conventional.cc @@ -38,6 +38,7 @@ #include "base/logging.h" #include "base/util.h" +#include "protocol/commands.pb.h" #include "protocol/renderer_command.pb.h" #include "renderer/win32/win32_renderer_client.h" #include "win32/base/conversion_mode_util.h" @@ -457,42 +458,6 @@ class UpdateUiEditSessionImpl : public ITfEditSession { DISALLOW_COPY_AND_ASSIGN(UpdateUiEditSessionImpl); }; -HRESULT OnUpdateLanguageBar(TipTextService *text_service, - ITfDocumentMgr *document_manager) { - HRESULT result = S_OK; - ITfThreadMgr *thread_manager = text_service->GetThreadManager(); - - if (thread_manager == nullptr) { - return E_FAIL; - } - - bool disabled = false; - { - if (document_manager == nullptr) { - // When |document_manager| is null, we should disable an IME like we - // disable it when ImmAssociateContext(window_handle, nullptr) is - // called. - disabled = true; - } else { - CComPtr context; - result = document_manager->GetTop(&context); - if (SUCCEEDED(result)) { - disabled = TipStatus::IsDisabledContext(context); - } - } - } - - const TipInputModeManager *input_mode_manager = - text_service->GetThreadContext()->GetInputModeManager(); - const bool open = input_mode_manager->GetEffectiveOpenClose(); - const CompositionMode mozc_mode = - open ? static_cast( - input_mode_manager->GetEffectiveConversionMode()) - : commands::DIRECT; - text_service->UpdateLangbar(!disabled, static_cast(mozc_mode)); - return S_OK; -} - } // namespace ITfUIElement *TipUiHandlerConventional::CreateUI(TipUiHandler::UiType type, @@ -546,8 +511,6 @@ void TipUiHandlerConventional::OnFocusChange( command.set_type(RendererCommand::UPDATE); command.set_visible(false); Win32RendererClient::OnUpdated(command); - // Update the langbar. - OnUpdateLanguageBar(text_service, focused_document_manager); return; } @@ -558,7 +521,6 @@ void TipUiHandlerConventional::OnFocusChange( if (!context) { return; } - OnUpdateLanguageBar(text_service, focused_document_manager); UpdateUiEditSessionImpl::BeginRequest(text_service, context); } @@ -566,21 +528,11 @@ bool TipUiHandlerConventional::Update(TipTextService *text_service, ITfContext *context, TfEditCookie read_cookie) { RendererCommand command; - const TipInputModeManager *input_mode_manager = - text_service->GetThreadContext()->GetInputModeManager(); - const bool open = input_mode_manager->GetEffectiveOpenClose(); - const CompositionMode mozc_mode = static_cast( - input_mode_manager->GetEffectiveConversionMode()); bool no_layout = false; UpdateCommand(text_service, context, read_cookie, &command, &no_layout); if (!no_layout || !command.visible()) { Win32RendererClient::OnUpdated(command); } - if (open) { - text_service->UpdateLangbar(true, mozc_mode); - } else { - text_service->UpdateLangbar(true, commands::DIRECT); - } return true; }