This source file includes following definitions.
- input_type_
- CompositionUpdated
- CompositionCompleted
- SendEvents
- GetStatus
- GetProcAddress
- Lock
- Unlock
- GetInstance
- ImmAssociateContextEx
- ImmGetCompositionStringW
- ImmGetContext
- ImmReleaseContext
- ImmSetCandidateWindow
- ImmSetOpenStatus
#include "content/child/npapi/webplugin_ime_win.h"
#include <cstring>
#include <string>
#include <vector>
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/lock.h"
#include "content/child/npapi/plugin_instance.h"
#include "content/common/plugin_constants_win.h"
#pragma comment(lib, "imm32.lib")
namespace content {
base::LazyInstance<base::Lock>::Leaky
g_webplugin_ime_lock = LAZY_INSTANCE_INITIALIZER;
WebPluginIMEWin* WebPluginIMEWin::instance_ = NULL;
WebPluginIMEWin::WebPluginIMEWin()
: cursor_position_(0),
delta_start_(0),
composing_text_(false),
support_ime_messages_(false),
status_updated_(false),
input_type_(1) {
memset(result_clauses_, 0, sizeof(result_clauses_));
}
WebPluginIMEWin::~WebPluginIMEWin() {
}
void WebPluginIMEWin::CompositionUpdated(const base::string16& text,
std::vector<int> clauses,
std::vector<int> target,
int cursor_position) {
NPEvent np_event;
if (!composing_text_) {
composing_text_ = true;
result_text_.clear();
np_event.event = WM_IME_STARTCOMPOSITION;
np_event.wParam = 0;
np_event.lParam = 0;
events_.push_back(np_event);
}
np_event.event = WM_IME_COMPOSITION;
np_event.wParam = 0;
np_event.lParam = GCS_COMPSTR | GCS_COMPATTR | GCS_COMPCLAUSE |
GCS_CURSORPOS | GCS_DELTASTART;
events_.push_back(np_event);
composition_text_ = text;
composition_clauses_.clear();
for (size_t i = 0; i < clauses.size(); ++i)
composition_clauses_.push_back(clauses[i]);
if (target.size() == 2) {
composition_attributes_.assign(text.length(), ATTR_CONVERTED);
for (int i = target[0]; i < target[1]; ++i)
composition_attributes_[i] = ATTR_TARGET_CONVERTED;
} else {
composition_attributes_.assign(text.length(), ATTR_INPUT);
}
cursor_position_ = cursor_position;
delta_start_ = cursor_position;
}
void WebPluginIMEWin::CompositionCompleted(const base::string16& text) {
composing_text_ = false;
NPEvent np_event;
np_event.event = WM_IME_COMPOSITION;
np_event.wParam = 0;
np_event.lParam = GCS_CURSORPOS | GCS_DELTASTART | GCS_RESULTSTR |
GCS_RESULTCLAUSE;
events_.push_back(np_event);
np_event.event = WM_IME_ENDCOMPOSITION;
np_event.wParam = 0;
np_event.lParam = 0;
events_.push_back(np_event);
if (!support_ime_messages_) {
np_event.event = WM_CHAR;
np_event.wParam = 0;
np_event.lParam = 0;
for (size_t i = 0; i < result_text_.length(); ++i) {
np_event.wParam = result_text_[i];
events_.push_back(np_event);
}
}
result_text_ = text;
result_clauses_[0] = 0;
result_clauses_[1] = result_text_.length();
cursor_position_ = result_clauses_[1];
delta_start_ = result_clauses_[1];
}
bool WebPluginIMEWin::SendEvents(PluginInstance* instance) {
ScopedLock lock(this);
bool ret = true;
for (std::vector<NPEvent>::iterator it = events_.begin();
it != events_.end(); ++it) {
if (!instance->NPP_HandleEvent(&(*it)))
ret = false;
}
events_.clear();
return ret;
}
bool WebPluginIMEWin::GetStatus(int* input_type, gfx::Rect* caret_rect) {
*input_type = input_type_;
*caret_rect = caret_rect_;
return true;
}
FARPROC WebPluginIMEWin::GetProcAddress(LPCSTR name) {
static const struct {
const char* name;
FARPROC function;
} kImm32Functions[] = {
{ "ImmAssociateContextEx",
reinterpret_cast<FARPROC>(ImmAssociateContextEx) },
{ "ImmGetCompositionStringW",
reinterpret_cast<FARPROC>(ImmGetCompositionStringW) },
{ "ImmGetContext", reinterpret_cast<FARPROC>(ImmGetContext) },
{ "ImmReleaseContext", reinterpret_cast<FARPROC>(ImmReleaseContext) },
{ "ImmSetCandidateWindow",
reinterpret_cast<FARPROC>(ImmSetCandidateWindow) },
{ "ImmSetOpenStatus", reinterpret_cast<FARPROC>(ImmSetOpenStatus) },
};
for (int i = 0; i < arraysize(kImm32Functions); ++i) {
if (!lstrcmpiA(name, kImm32Functions[i].name))
return kImm32Functions[i].function;
}
return NULL;
}
void WebPluginIMEWin::Lock() {
g_webplugin_ime_lock.Pointer()->Acquire();
instance_ = this;
}
void WebPluginIMEWin::Unlock() {
instance_ = NULL;
g_webplugin_ime_lock.Pointer()->Release();
}
WebPluginIMEWin* WebPluginIMEWin::GetInstance(HIMC context) {
return instance_ && context == reinterpret_cast<HIMC>(instance_) ?
instance_ : NULL;
}
BOOL WINAPI WebPluginIMEWin::ImmAssociateContextEx(HWND window,
HIMC context,
DWORD flags) {
WebPluginIMEWin* instance = GetInstance(context);
if (!instance)
return ::ImmAssociateContextEx(window, context, flags);
int input_type = !context && !flags;
instance->input_type_ = input_type;
instance->status_updated_ = true;
return TRUE;
}
LONG WINAPI WebPluginIMEWin::ImmGetCompositionStringW(HIMC context,
DWORD index,
LPVOID dst_data,
DWORD dst_size) {
WebPluginIMEWin* instance = GetInstance(context);
if (!instance)
return ::ImmGetCompositionStringW(context, index, dst_data, dst_size);
const void* src_data = NULL;
DWORD src_size = 0;
switch (index) {
case GCS_COMPSTR:
src_data = instance->composition_text_.c_str();
src_size = instance->composition_text_.length() * sizeof(wchar_t);
break;
case GCS_COMPATTR:
src_data = instance->composition_attributes_.c_str();
src_size = instance->composition_attributes_.length();
break;
case GCS_COMPCLAUSE:
src_data = &instance->composition_clauses_[0];
src_size = instance->composition_clauses_.size() * sizeof(uint32);
break;
case GCS_CURSORPOS:
return instance->cursor_position_;
case GCS_DELTASTART:
return instance->delta_start_;
case GCS_RESULTSTR:
src_data = instance->result_text_.c_str();
src_size = instance->result_text_.length() * sizeof(wchar_t);
break;
case GCS_RESULTCLAUSE:
src_data = &instance->result_clauses_[0];
src_size = sizeof(instance->result_clauses_);
break;
default:
break;
}
if (!src_data || !src_size)
return IMM_ERROR_NODATA;
if (dst_size >= src_size)
memcpy(dst_data, src_data, src_size);
return src_size;
}
HIMC WINAPI WebPluginIMEWin::ImmGetContext(HWND window) {
if (IsWindow(window)) {
wchar_t name[128];
GetClassName(window, &name[0], arraysize(name));
if (!wcscmp(&name[0], kNativeWindowClassName))
return ::ImmGetContext(window);
}
WebPluginIMEWin* instance = instance_;
if (instance)
instance->support_ime_messages_ = true;
return reinterpret_cast<HIMC>(instance);
}
BOOL WINAPI WebPluginIMEWin::ImmReleaseContext(HWND window, HIMC context) {
if (!GetInstance(context))
return ::ImmReleaseContext(window, context);
return TRUE;
}
BOOL WINAPI WebPluginIMEWin::ImmSetCandidateWindow(HIMC context,
CANDIDATEFORM* candidate) {
WebPluginIMEWin* instance = GetInstance(context);
if (!instance)
return ::ImmSetCandidateWindow(context, candidate);
gfx::Rect caret_rect(candidate->rcArea);
if ((candidate->dwStyle & CFS_EXCLUDE) &&
instance->caret_rect_ != caret_rect) {
instance->caret_rect_ = caret_rect;
instance->status_updated_ = true;
}
return TRUE;
}
BOOL WINAPI WebPluginIMEWin::ImmSetOpenStatus(HIMC context, BOOL open) {
WebPluginIMEWin* instance = GetInstance(context);
if (!instance)
return ::ImmSetOpenStatus(context, open);
int input_type = open ? 1 : 0;
if (instance->input_type_ != input_type) {
instance->input_type_ = input_type;
instance->status_updated_ = true;
}
return TRUE;
}
}