Skip to content

Commit

Permalink
Make OnKeyEvent asynchronous to match the design.
Browse files Browse the repository at this point in the history
BUG=None
TEST=None

Review URL: http://codereview.chromium.org/7721006

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@100107 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
zork@chromium.org committed Sep 8, 2011
1 parent b103b59 commit cd0b04c
Show file tree
Hide file tree
Showing 9 changed files with 205 additions and 19 deletions.
67 changes: 56 additions & 11 deletions chrome/browser/chromeos/input_method/ibus_engine_controller.cc
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ namespace input_method {
(G_TYPE_CHECK_CLASS_TYPE((klass), IBUS_TYPE_CHROMEOS_ENGINE))
#define IBUS_CHROMEOS_ENGINE_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS((obj), IBUS_TYPE_CHROMEOS_ENGINE, \
IBusChromeOSEngine))
IBusChromeOSEngineClass))

class IBusEngineControllerImpl;
struct IBusChromeOSEngine {
Expand Down Expand Up @@ -332,6 +332,15 @@ class IBusEngineControllerImpl : public IBusEngineController {
}
}

virtual void KeyEventDone(KeyEventHandle* key_data, bool handled) {
GDBusMethodInvocation* invocation =
reinterpret_cast<GDBusMethodInvocation*>(key_data);

g_dbus_method_invocation_return_value(invocation,
g_variant_new("(b)", handled));
}


static void InitEngineClass(IBusChromeOSEngineClass *klass) {
GObjectClass *object_class = G_OBJECT_CLASS(klass);
IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS(klass);
Expand All @@ -340,7 +349,9 @@ class IBusEngineControllerImpl : public IBusEngineController {
object_class->constructor = EngineConstructor;
ibus_object_class->destroy = (IBusObjectDestroyFunc) OnDestroy;

engine_class->process_key_event = OnProcessKeyEvent;
IBUS_SERVICE_CLASS(klass)->service_method_call = OnServiceMethodCall;

engine_class->process_key_event = NULL;
engine_class->reset = OnReset;
engine_class->enable = OnEnable;
engine_class->disable = OnDisable;
Expand Down Expand Up @@ -439,17 +450,51 @@ class IBusEngineControllerImpl : public IBusEngineController {
return true;
}

static gboolean OnProcessKeyEvent(IBusEngine* ibus_engine, guint keyval,
guint keycode, guint modifiers) {
static void OnServiceMethodCall(IBusService* service,
GDBusConnection* connection,
const gchar* sender,
const gchar* object_path,
const gchar* interface_name,
const gchar* method_name,
GVariant* parameters,
GDBusMethodInvocation* invocation) {
if (g_strcmp0(method_name, "ProcessKeyEvent") == 0) {
// Override the default ProcessKeyEvent handler so that we can send the
// response asynchronously.
IBusEngine *engine = IBUS_ENGINE(service);

guint keyval;
guint keycode;
guint state;
g_variant_get(parameters, "(uuu)", &keyval, &keycode, &state);

OnProcessKeyEvent(engine, keyval, keycode, state, invocation);
} else {
IBUS_SERVICE_CLASS(
ibus_chromeos_engine_parent_class)->service_method_call(
service,
connection,
sender,
object_path,
interface_name,
method_name,
parameters,
invocation);
}
}

static void OnProcessKeyEvent(IBusEngine* ibus_engine, guint keyval,
guint keycode, guint modifiers,
GDBusMethodInvocation* key_data) {
VLOG(1) << "OnProcessKeyEvent";
// TODO: Use async version.
IBusChromeOSEngine* engine = IBUS_CHROMEOS_ENGINE(ibus_engine);
engine->connection->observer_->OnKeyEvent(!(modifiers & IBUS_RELEASE_MASK),
keyval, keycode,
modifiers & IBUS_MOD1_MASK,
modifiers & IBUS_CONTROL_MASK,
modifiers & IBUS_SHIFT_MASK);
return true;
engine->connection->observer_->OnKeyEvent(
!(modifiers & IBUS_RELEASE_MASK),
keyval, keycode,
modifiers & IBUS_MOD1_MASK,
modifiers & IBUS_CONTROL_MASK,
modifiers & IBUS_SHIFT_MASK,
reinterpret_cast<KeyEventHandle*>(key_data));
}

static void OnReset(IBusEngine* ibus_engine) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
namespace chromeos {
namespace input_method {

struct KeyEventHandle;

// IBusEngineController is used to encapsulate an ibus engine.
class IBusEngineController {
public:
Expand All @@ -22,7 +24,8 @@ class IBusEngineController {
// Called when a key is pressed or released.
virtual void OnKeyEvent(bool key_press, unsigned int keyval,
unsigned int keycode, bool alt_key,
bool ctrl_key, bool shift_key) = 0;
bool ctrl_key, bool shift_key,
KeyEventHandle* key_data) = 0;

// Called when the engine should reset its internal state.
virtual void OnReset() = 0;
Expand Down Expand Up @@ -114,6 +117,9 @@ class IBusEngineController {

// Set the posistion of the cursor in the candidate window.
virtual void SetCursorPosition(unsigned int position) = 0;

// Inform the engine that a key event has been processed.
virtual void KeyEventDone(KeyEventHandle* key_data, bool handled) = 0;
};

} // namespace input_method
Expand Down
17 changes: 13 additions & 4 deletions chrome/browser/chromeos/input_method/input_method_engine.cc
Original file line number Diff line number Diff line change
Expand Up @@ -90,15 +90,18 @@ class InputMethodEngineImpl
virtual bool IsActive() const {
return active_;
}
virtual void KeyEventDone(input_method::KeyEventHandle* key_data,
bool handled);

virtual void OnReset();
virtual void OnEnable();
virtual void OnDisable();
virtual void OnFocusIn();
virtual void OnFocusOut();
virtual void OnKeyEvent(bool key_press, unsigned int keyval,
unsigned int keycode, bool alt_key,
bool ctrl_key, bool shift_key);
unsigned int keycode, bool alt_key, bool ctrl_key,
bool shift_key,
input_method::KeyEventHandle* key_data);
virtual void OnPropertyActivate(const char* name, unsigned int state);
virtual void OnCandidateClicked(unsigned int index, unsigned int button,
unsigned int state);
Expand Down Expand Up @@ -359,6 +362,11 @@ void InputMethodEngineImpl::UpdateMenuItems(
// TODO(zork): Implement this function
}

void InputMethodEngineImpl::KeyEventDone(input_method::KeyEventHandle* key_data,
bool handled) {
connection_->KeyEventDone(key_data, handled);
}

void InputMethodEngineImpl::OnReset() {
// Ignored
}
Expand Down Expand Up @@ -393,15 +401,16 @@ void InputMethodEngineImpl::OnFocusOut() {

void InputMethodEngineImpl::OnKeyEvent(bool key_press, unsigned int keyval,
unsigned int keycode, bool alt_key,
bool ctrl_key, bool shift_key) {
bool ctrl_key, bool shift_key,
input_method::KeyEventHandle* key_data) {
KeyboardEvent event;
event.type = key_press ? "keydown" : "keyup";
event.key = input_method::GetIBusKey(keyval);
event.key_code = input_method::GetIBusKeyCode(keycode);
event.alt_key = alt_key;
event.ctrl_key = ctrl_key;
event.shift_key = shift_key;
observer_->OnKeyEvent(engine_id_, event);
observer_->OnKeyEvent(engine_id_, event, key_data);
}

void InputMethodEngineImpl::OnPropertyActivate(const char* name,
Expand Down
11 changes: 10 additions & 1 deletion chrome/browser/chromeos/input_method/input_method_engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@

namespace chromeos {

namespace input_method {
struct KeyEventHandle;
} // namespace input_method

extern const char* kExtensionImePrefix;

// InputMethodEngine is used to translate from the Chrome IME API to the native
Expand Down Expand Up @@ -87,7 +91,8 @@ class InputMethodEngine {

// Called when the user pressed a key with a text field focused.
virtual void OnKeyEvent(const std::string& engine_id,
const KeyboardEvent& event) = 0;
const KeyboardEvent& event,
input_method::KeyEventHandle* key_data) = 0;

// Called when the user clicks on an item in the candidate list.
virtual void OnCandidateClicked(const std::string& engine_id,
Expand Down Expand Up @@ -172,6 +177,10 @@ class InputMethodEngine {
// Returns true if this IME is active, false if not.
virtual bool IsActive() const = 0;

// Inform the engine that a key event has been processed.
virtual void KeyEventDone(input_method::KeyEventHandle* key_data,
bool handled) = 0;

// Create an IME engine.
static InputMethodEngine* CreateEngine(
InputMethodEngine::Observer* observer,
Expand Down
2 changes: 2 additions & 0 deletions chrome/browser/extensions/extension_function_dispatcher.cc
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,8 @@ void FactoryRegistry::ResetFunctions() {
RegisterFunction<SetCursorPositionFunction>();
RegisterFunction<SetMenuItemsFunction>();
RegisterFunction<UpdateMenuItemsFunction>();

RegisterFunction<InputEventHandled>();
#if defined(TOUCH_UI)
RegisterFunction<CandidateClickedInputUiFunction>();
RegisterFunction<CursorUpInputUiFunction>();
Expand Down
59 changes: 57 additions & 2 deletions chrome/browser/extensions/extension_input_ime_api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "chrome/browser/extensions/extension_input_ime_api.h"

#include "base/json/json_writer.h"
#include "base/string_number_conversions.h"
#include "base/values.h"
#include "chrome/browser/chromeos/input_method/input_method_engine.h"
#include "chrome/browser/extensions/extension_event_router.h"
Expand Down Expand Up @@ -115,12 +116,18 @@ class ImeObserver : public chromeos::InputMethodEngine::Observer {
}

virtual void OnKeyEvent(const std::string& engine_id,
const InputMethodEngine::KeyboardEvent& event) {
const InputMethodEngine::KeyboardEvent& event,
chromeos::input_method::KeyEventHandle* key_data) {
if (profile_ == NULL || extension_id_.empty())
return;

std::string request_id =
ExtensionInputImeEventRouter::GetInstance()->AddRequest(engine_id,
key_data);

DictionaryValue* dict = new DictionaryValue();
dict->SetString("type", event.type);
dict->SetString("requestId", request_id);
dict->SetString("key", event.key);
dict->SetString("keyCode", event.key_code);
dict->SetBoolean("altKey", event.alt_key);
Expand Down Expand Up @@ -200,7 +207,8 @@ ExtensionInputImeEventRouter::GetInstance() {
return Singleton<ExtensionInputImeEventRouter>::get();
}

ExtensionInputImeEventRouter::ExtensionInputImeEventRouter() {
ExtensionInputImeEventRouter::ExtensionInputImeEventRouter()
: next_request_id_(1) {
}

ExtensionInputImeEventRouter::~ExtensionInputImeEventRouter() {
Expand Down Expand Up @@ -296,6 +304,40 @@ chromeos::InputMethodEngine* ExtensionInputImeEventRouter::GetActiveEngine(
return NULL;
}

void ExtensionInputImeEventRouter::OnEventHandled(
const std::string& extension_id,
const std::string& request_id,
bool handled) {
RequestMap::iterator request = request_map_.find(request_id);
if (request == request_map_.end()) {
LOG(ERROR) << "Request ID not found: " << request_id;
return;
}

std::string engine_id = request->second.first;
chromeos::input_method::KeyEventHandle* key_data = request->second.second;
request_map_.erase(request);

chromeos::InputMethodEngine* engine = GetEngine(extension_id, engine_id);
if (!engine) {
LOG(ERROR) << "Engine does not exist: " << engine_id;
return;
}

engine->KeyEventDone(key_data, handled);
}

std::string ExtensionInputImeEventRouter::AddRequest(
const std::string& engine_id,
chromeos::input_method::KeyEventHandle* key_data) {
std::string request_id = base::IntToString(next_request_id_);
++next_request_id_;

request_map_[request_id] = std::make_pair(engine_id, key_data);

return request_id;
}

bool SetCompositionFunction::RunImpl() {
chromeos::InputMethodEngine* engine =
ExtensionInputImeEventRouter::GetInstance()->
Expand Down Expand Up @@ -631,4 +673,17 @@ bool UpdateMenuItemsFunction::RunImpl() {
// TODO
return true;
}

bool InputEventHandled::RunImpl() {
std::string request_id_str;
EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &request_id_str));

bool handled = false;
EXTENSION_FUNCTION_VALIDATE(args_->GetBoolean(1, &handled));

ExtensionInputImeEventRouter::GetInstance()->OnEventHandled(
extension_id(), request_id_str, handled);

return true;
}
#endif
19 changes: 19 additions & 0 deletions chrome/browser/extensions/extension_input_ime_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,18 @@ class ExtensionInputImeEventRouter {
chromeos::InputMethodEngine* GetActiveEngine(const std::string& extension_id);


// Called when a key event was handled.
void OnEventHandled(const std::string& extension_id,
const std::string& request_id,
bool handled);

std::string AddRequest(const std::string& engine_id,
chromeos::input_method::KeyEventHandle* key_data);

private:
friend struct DefaultSingletonTraits<ExtensionInputImeEventRouter>;
typedef std::map<std::string, std::pair<std::string,
chromeos::input_method::KeyEventHandle*> > RequestMap;

ExtensionInputImeEventRouter();
~ExtensionInputImeEventRouter();
Expand All @@ -48,6 +58,9 @@ class ExtensionInputImeEventRouter {
std::map<std::string, std::map<std::string, chromeos::ImeObserver*> >
observers_;

unsigned int next_request_id_;
RequestMap request_map_;

DISALLOW_COPY_AND_ASSIGN(ExtensionInputImeEventRouter);
};

Expand Down Expand Up @@ -111,4 +124,10 @@ class UpdateMenuItemsFunction : public AsyncExtensionFunction {
"experimental.input.updateMenuItems");
};

class InputEventHandled : public AsyncExtensionFunction {
public:
virtual bool RunImpl();
DECLARE_EXTENSION_FUNCTION_NAME("experimental.input.eventHandled");
};

#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_INPUT_IME_API_H_
11 changes: 11 additions & 0 deletions chrome/common/extensions/api/extension_api.json
Original file line number Diff line number Diff line change
Expand Up @@ -2823,6 +2823,7 @@
"description": "See http://www.w3.org/TR/DOM-Level-3-Events/#events-KeyboardEvent",
"properties": {
"type": {"type": "string", "description": "One of keyup or keydown.", "enum": ["keyup", "keydown"]},
"requestId": {"type": "string", "description": "The ID of the request."},
"key": {"type": "string", "description": "Value of the key being pressed"},
"keyCode": {"type": "string", "description": "Value of the key being press, unmodified by control keys."},
"altKey": {"type": "boolean", "optional": true, "description": "Whether or not the ALT key is pressed."},
Expand Down Expand Up @@ -3325,6 +3326,16 @@
"minimum": 0
}
]
},
{
"name": "eventHandled",
"nodoc": true,
"type": "function",
"description": "Used internally to send a response for onKeyEvent.",
"parameters": [
{"type": "string", "name": "requestId"},
{"type": "boolean", "name": "response"}
]
}
],
"events": [
Expand Down
Loading

0 comments on commit cd0b04c

Please sign in to comment.