Skip to content

Commit

Permalink
* Make compartment monitoring more flexible.
Browse files Browse the repository at this point in the history
* Fix a bug in ComQIPtr::operator=().
  • Loading branch information
PCMan committed Sep 18, 2013
1 parent 500d3ff commit 9d3c417
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 106 deletions.
2 changes: 0 additions & 2 deletions libIME/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ add_library(libIME_static STATIC
${PROJECT_SOURCE_DIR}/DisplayAttributeInfoEnum.h
${PROJECT_SOURCE_DIR}/DisplayAttributeProvider.cpp
${PROJECT_SOURCE_DIR}/DisplayAttributeProvider.h
${PROJECT_SOURCE_DIR}/CompartmentEventSink.cpp
${PROJECT_SOURCE_DIR}/CompartmentEventSink.h
${PROJECT_SOURCE_DIR}/LangBarButton.cpp
${PROJECT_SOURCE_DIR}/LangBarButton.h
${PROJECT_SOURCE_DIR}/Utils.cpp
Expand Down
2 changes: 1 addition & 1 deletion libIME/ComPtr.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ class ComQIPtr: public ComPtr<T> {
}

ComQIPtr& operator = (IUnknown* p) {
*this = NULL;
ComPtr<T>::operator = (NULL);
if(p) {
p->QueryInterface(__uuidof(T), (void**)&p_);
}
Expand Down
48 changes: 0 additions & 48 deletions libIME/CompartmentEventSink.cpp

This file was deleted.

31 changes: 0 additions & 31 deletions libIME/CompartmentEventSink.h

This file was deleted.

97 changes: 74 additions & 23 deletions libIME/TextService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,27 @@ TextService::TextService(ImeModule* module):
composition_(NULL),
candidateWindow_(NULL),
refCount_(1) {

addCompartmentMonitor(GUID_COMPARTMENT_KEYBOARD_OPENCLOSE, false);
}

TextService::~TextService(void) {
if(candidateWindow_)
delete candidateWindow_;

// This should only happen in rare cases
if(!compartmentMonitors_.empty()) {
vector<CompartmentMonitor>::iterator it;
for(it = compartmentMonitors_.begin(); it != compartmentMonitors_.end(); ++it) {
ComQIPtr<ITfSource> source;
if(it->isGlobal)
source = globalCompartment(it->guid);
else
source = threadCompartment(it->guid);
source->UnadviseSink(it->cookie);
}
}

if(!langBarButtons_.empty()) {
for(vector<LangBarButton*>::iterator it = langBarButtons_.begin(); it != langBarButtons_.end(); ++it) {
LangBarButton* button = *it;
Expand Down Expand Up @@ -156,7 +171,7 @@ bool TextService::isKeyboardDisabled(ITfContext* context) {
}

// is keyboard opened for the whole thread
bool TextService::isKeyboardOpened() const {
bool TextService::isKeyboardOpened() {
return isKeyboardOpened_;
}

Expand Down Expand Up @@ -331,8 +346,11 @@ DWORD TextService::threadCompartmentValue(const GUID& key) {
ComPtr<ITfCompartment> compartment = threadCompartment(key);
if(compartment) {
VARIANT var;
if(compartment->GetValue(&var) == S_OK && var.vt == VT_I4) {
return (DWORD)var.lVal;
::VariantInit(&var);
HRESULT r = compartment->GetValue(&var);
if(r == S_OK) {
if(var.vt == VT_I4)
return (DWORD)var.lVal;
}
}
return 0;
Expand Down Expand Up @@ -383,6 +401,42 @@ void TextService::setContextCompartmentValue(const GUID& key, DWORD value, ITfCo
}


void TextService::addCompartmentMonitor(const GUID key, bool isGlobal) {
CompartmentMonitor monitor;
monitor.guid = key;
monitor.cookie = 0;
monitor.isGlobal = isGlobal;
// if the text service is activated
if(threadMgr_) {
ComQIPtr<ITfSource> source;
if(isGlobal)
source = globalCompartment(key);
else
source = threadCompartment(key);
if(source) {
source->AdviseSink(IID_ITfCompartmentEventSink, (ITfCompartmentEventSink*)this, &monitor.cookie);
}
}
compartmentMonitors_.push_back(monitor);
}

void TextService::removeCompartmentMonitor(const GUID key) {
vector<CompartmentMonitor>::iterator it;
it = find(compartmentMonitors_.begin(), compartmentMonitors_.end(), key);
if(it != compartmentMonitors_.end()) {
if(threadMgr_) {
ComQIPtr<ITfSource> source;
if(it->isGlobal)
source = globalCompartment(key);
else
source = threadCompartment(key);
source->UnadviseSink(it->cookie);
}
compartmentMonitors_.erase(it);
}
}


// virtual
void TextService::onActivate() {
}
Expand Down Expand Up @@ -523,28 +577,25 @@ STDMETHODIMP TextService::Activate(ITfThreadMgr *pThreadMgr, TfClientId tfClient
// ITfCompositionSink

// ITfCompartmentEventSink
// thread specific compartment
ComPtr<ITfCompartment> compartment = threadCompartment(GUID_COMPARTMENT_KEYBOARD_OPENCLOSE);
if(compartment) {
VARIANT var;
::VariantInit(&var);
compartment->GetValue(&var);
isKeyboardOpened_ = (var.vt == VT_I4 && var.lVal) ? true : false;

ComQIPtr<ITfSource> compartmentSource = compartment;
if(compartmentSource)
compartmentSource->AdviseSink(IID_ITfCompartmentEventSink, (ITfCompartmentEventSink*)this, &keyboardOpenEventSinkCookie_);
// get current keyboard state
if(!compartmentMonitors_.empty()) {
vector<CompartmentMonitor>::iterator it;
for(it = compartmentMonitors_.begin(); it != compartmentMonitors_.end(); ++it) {
ComQIPtr<ITfSource> compartmentSource;
if(it->isGlobal) // global compartment
compartmentSource = globalCompartment(it->guid);
else // thread specific compartment
compartmentSource = threadCompartment(it->guid);
compartmentSource->AdviseSink(IID_ITfCompartmentEventSink, (ITfCompartmentEventSink*)this, &it->cookie);
}
}
isKeyboardOpened_ = threadCompartmentValue(GUID_COMPARTMENT_KEYBOARD_OPENCLOSE);

/*
// global compartment
compartment = globalCompartment(XXX_GUID);
if(compartment) {
ComQIPtr<ITfSource> compartmentSource = compartment;
if(compartmentSource)
compartmentSource->AdviseSink(IID_ITfCompartmentEventSink, (ITfCompartmentEventSink*)this, &globalCompartmentEventSinkCookie_);
}
*/
// FIXME: under Windows 7, it seems that the keyboard is closed every time
// our text service is activated. The value in the compartment is always empty. :-(
// So, we open the keyboard manually here, but I'm not sure if this is the correct behavior.
if(!isKeyboardOpened_)
setKeyboardOpen(true);

// initialize language bar
// Note: language bar has no effects in Win 8 immersive mode
Expand Down
17 changes: 16 additions & 1 deletion libIME/TextService.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ class TextService:
bool isKeyboardDisabled(ITfContext* context = NULL);

// is keyboard opened for the whole thread
bool isKeyboardOpened() const;
bool isKeyboardOpened();
void setKeyboardOpen(bool open);

bool isInsertionAllowed(EditSession* session);
Expand All @@ -120,6 +120,10 @@ class TextService:
void setThreadCompartmentValue(const GUID& key, DWORD value);
void setContextCompartmentValue(const GUID& key, DWORD value, ITfContext* context = NULL);

// manage sinks to global or thread compartment (context specific compartment is not used)
void addCompartmentMonitor(const GUID key, bool isGlobal = false);
void removeCompartmentMonitor(const GUID key);

// virtual functions that IME implementors may need to override
virtual void onActivate();
virtual void onDeactivate();
Expand Down Expand Up @@ -226,6 +230,16 @@ class TextService:
GUID guid;
};

struct CompartmentMonitor {
GUID guid;
DWORD cookie;
bool isGlobal;

bool operator == (const GUID& other) {
return ::IsEqualGUID(guid, other);
}
};

private:
ComPtr<ImeModule> module_;
ComPtr<ITfThreadMgr> threadMgr_;
Expand All @@ -244,6 +258,7 @@ class TextService:
CandidateWindow* candidateWindow_;
std::vector<LangBarButton*> langBarButtons_;
std::vector<PreservedKey> preservedKeys_;
std::vector<CompartmentMonitor> compartmentMonitors_;

long refCount_; // reference counting
};
Expand Down

0 comments on commit 9d3c417

Please sign in to comment.