Skip to content

Commit

Permalink
Merge pull request #230 from chewing/feat-listen-reg-update
Browse files Browse the repository at this point in the history
feat: listen to registry change event
  • Loading branch information
kanru authored Dec 21, 2024
2 parents 9fcd61b + e646731 commit eb27a8a
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 10 deletions.
64 changes: 63 additions & 1 deletion ChewingTextService/ChewingConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@
#include <Aclapi.h>
#include <Windows.h>
#include <VersionHelpers.h>
#include <debugapi.h>
#include <handleapi.h>
#include <minwindef.h>
#include <synchapi.h>
#include <winbase.h>
#include <winnt.h>
#include <winreg.h>
#include <cassert>
#include <cstddef>

#include "ChewingConfig.h"

Expand Down Expand Up @@ -57,7 +66,9 @@ const wchar_t* Config::convEngines[]={
#define SECURITY_BUILTIN_PACKAGE_ANY_PACKAGE 0x00000001L
#endif

Config::Config() {
Config::Config():
hChangeEvent(NULL),
monitorHkey(NULL) {
// Configuration
keyboardLayout = 0;
candPerRow = 3;
Expand Down Expand Up @@ -86,6 +97,12 @@ Config::Config() {
}

Config::~Config(void) {
if (hChangeEvent) {
CloseHandle(hChangeEvent);
}
if (monitorHkey) {
RegCloseKey(monitorHkey);
}
}

void Config::load() {
Expand Down Expand Up @@ -189,6 +206,51 @@ void Config::reloadIfNeeded(DWORD timestamp) {
}
}

bool Config::reloadIfNeeded() {
if (hChangeEvent) {
DWORD result = WaitForSingleObject(hChangeEvent, 0);
if (WAIT_OBJECT_0 == result) {
load();
watchChanges();
return true;
}
if (WAIT_FAILED == result) {
CloseHandle(hChangeEvent);
hChangeEvent = NULL;
watchChanges();
}
}
return false;
}

void Config::watchChanges() {
if (hChangeEvent == NULL) {
hChangeEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
if (hChangeEvent == NULL) {
OutputDebugStringW(L"Unable to create change event handle\n");
return;
}
} else {
ResetEvent(hChangeEvent);
}

// ensure that we always access 64 bit registry if running under WOW64
if (monitorHkey == NULL){
HANDLE process = ::GetCurrentProcess();
BOOL isWow64 = FALSE;
::IsWow64Process(process, &isWow64);
DWORD regFlags = isWow64 ? KEY_WOW64_64KEY : 0;
if (ERROR_SUCCESS != ::RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\ChewingTextService", 0, regFlags|KEY_NOTIFY, &monitorHkey)) {
OutputDebugStringW(L"Unable to open HKEY handle\n");
return;
}
}
DWORD dwFilter = REG_NOTIFY_CHANGE_LAST_SET | REG_NOTIFY_THREAD_AGNOSTIC;
if (ERROR_SUCCESS != RegNotifyChangeKeyValue(monitorHkey, TRUE, dwFilter, hChangeEvent, TRUE)) {
OutputDebugStringW(L"Unable to register notify for registry change\n");
}
}

// enable access to app containers
// Reference: http://msdn.microsoft.com/en-us/library/windows/desktop/aa379283(v=vs.85).aspx
// http://msdn.microsoft.com/en-us/library/windows/desktop/hh448493(v=vs.85).aspx
Expand Down
6 changes: 6 additions & 0 deletions ChewingTextService/ChewingConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

#include <Windows.h>
#include <AccCtrl.h>
#include <ocidl.h>

namespace Chewing {

Expand All @@ -35,6 +36,9 @@ class Config {

// reload configurations if changes are detected (if timestamp is different from this->stamp)
void reloadIfNeeded(DWORD timestamp);
// Returns true if config was reloaded
bool reloadIfNeeded();
void watchChanges();

static bool grantAppContainerAccess(const wchar_t* object, SE_OBJECT_TYPE type, DWORD access);

Expand Down Expand Up @@ -75,6 +79,8 @@ class Config {

private:
DWORD stamp; // timestamp used to check if the config values are up to date
HANDLE hChangeEvent;
HKEY monitorHkey;
};

}
Expand Down
16 changes: 10 additions & 6 deletions ChewingTextService/ChewingTextService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

#include <Shellapi.h>
#include <assert.h>
#include <debugapi.h>
#include <libIME/LangBarButton.h>
#include <libIME/Utils.h>
#include <minwindef.h>
Expand Down Expand Up @@ -90,6 +91,7 @@ TextService::TextService():
chewingContext_(NULL) {

config_.load();
config_.watchChanges();

// add preserved keys
addPreservedKey(VK_SPACE, TF_MOD_SHIFT, g_shiftSpaceGuid); // shift + space
Expand Down Expand Up @@ -191,6 +193,9 @@ void TextService::onKillFocus() {
// virtual
bool TextService::filterKeyDown(Ime::KeyEvent& keyEvent) {
Config& cfg = config();
if (cfg.reloadIfNeeded()) {
applyConfig();
}
lastKeyDownCode_ = keyEvent.keyCode();
// return false if we don't need this key
assert(chewingContext_);
Expand Down Expand Up @@ -729,11 +734,6 @@ void TextService::initChewingContext() {
symbolsFileTime_ = stbuf.st_mtime;
}

outputSimpChinese_ = config().outputSimpChinese;
// update popup menu to check/uncheck the simplified Chinese item
DWORD checkFlags = outputSimpChinese_ ? MF_CHECKED : MF_UNCHECKED;
::CheckMenuItem(popupMenu_, ID_OUTPUT_SIMP_CHINESE, MF_BYCOMMAND|checkFlags);

applyConfig();
}

Expand Down Expand Up @@ -781,6 +781,11 @@ void TextService::applyConfig() {
chewing_config_set_int(chewingContext_, "chewing.conversion_engine", cfg.convEngine);
}

outputSimpChinese_ = cfg.outputSimpChinese;
// update popup menu to check/uncheck the simplified Chinese item
DWORD checkFlags = outputSimpChinese_ ? MF_CHECKED : MF_UNCHECKED;
::CheckMenuItem(popupMenu_, ID_OUTPUT_SIMP_CHINESE, MF_BYCOMMAND|checkFlags);

if(messageWindow_) {
messageWindow_->setFontSize(cfg.fontSize);
}
Expand Down Expand Up @@ -982,7 +987,6 @@ void TextService::updateLangButtons() {
shapeMode_ = shapeMode;
switchShapeButton_->setIcon(shapeMode == FULLSHAPE_MODE ? IDI_FULL_SHAPE : IDI_HALF_SHAPE);
}

}

std::wstring TextService::userDir() {
Expand Down
7 changes: 4 additions & 3 deletions libIME/TextService.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ class TextService:

// is keyboard disabled for the context (NULL means current context)
bool isKeyboardDisabled(ITfContext* context = NULL);

// is keyboard opened for the whole thread
bool isKeyboardOpened();
void setKeyboardOpen(bool open);
Expand All @@ -130,6 +130,7 @@ class TextService:
void setCompositionCursor(EditSession* session, int pos);

// compartment handling
// XXX if registry monitor works well we can stop using compartments for RPC
winrt::com_ptr<ITfCompartment> globalCompartment(const GUID& key);
winrt::com_ptr<ITfCompartment> threadCompartment(const GUID& key);
winrt::com_ptr<ITfCompartment> contextCompartment(const GUID& key, ITfContext* context = NULL);
Expand Down Expand Up @@ -157,7 +158,7 @@ class TextService:

virtual bool filterKeyDown(KeyEvent& keyEvent);
virtual bool onKeyDown(KeyEvent& keyEvent, EditSession* session);

virtual bool filterKeyUp(KeyEvent& keyEvent);
virtual bool onKeyUp(KeyEvent& keyEvent, EditSession* session);

Expand Down Expand Up @@ -226,7 +227,7 @@ class TextService:
// ITfCompartmentEventSink
STDMETHODIMP OnChange(REFGUID rguid);

// ITfLangBarEventSink
// ITfLangBarEventSink
STDMETHODIMP OnSetFocus(DWORD dwThreadId);
STDMETHODIMP OnThreadTerminate(DWORD dwThreadId);
STDMETHODIMP OnThreadItemChange(DWORD dwThreadId);
Expand Down

0 comments on commit eb27a8a

Please sign in to comment.