Issue: CBBROWSER-94, CBBROWSER-95, CBBROWSER-93, CBBROWSER-96, CBBROWSER-228, CBBROWSER-229, CBBROWSER-227,
[Problem]: Tests form issuses above are failing.
[Cause]: Some of IME events are not dispatched and others are in unproper order.
[Solution]: Change handling IME events as it is in Webkit.
Change-Id: I876a3c6da9f19dfb6dea08e2d53b59ccd3bd3c8b
Conflicts:
impl/browser/renderer_host/im_context_efl.cc
impl/browser/renderer_host/render_widget_host_view_efl.cc
impl/browser/renderer_host/render_widget_host_view_efl.h
src/content/renderer/render_widget.cc
#include <Ecore_Evas.h>
#include <Ecore_IMF_Evas.h>
+#include "wtf/unicode/icu/UnicodeIcu.h"
+#include "third_party/icu/source/common/unicode/uchar.h"
#ifdef IM_CTX_DEBUG
#define IM_CTX_LOG_CHANNEL LOG(ERROR)
focused_(false),
enabled_(false),
panel_was_ever_shown_(false),
- is_in_form_tag_(false) {
+ is_in_form_tag_(false),
+ is_handling_keydown_(false) {
IM_CTX_LOG;
InitializeIMFContext(context_);
}
void IMContextEfl::Reset() {
ecore_imf_context_reset(context_);
+ ClearQueues();
+ view_->ClearQueues();
}
void IMContextEfl::HandleKeyDownEvent(const Evas_Event_Key_Down* event, bool* wasFiltered) {
#if USE_IM_COMPOSITING
Ecore_IMF_Event im_event;
+ is_handling_keydown_ = true;
ecore_imf_evas_event_key_down_wrap(const_cast<Evas_Event_Key_Down*>(event), &im_event.key_down);
*wasFiltered = ecore_imf_context_filter_event(context_, ECORE_IMF_EVENT_KEY_DOWN, &im_event);
+ is_handling_keydown_ = false;
#endif
}
enabled_ = enabled;
ecore_imf_context_reset(context_);
+ ClearQueues();
+ view_->ClearQueues();
+
// This can only be called when having focus since we disable IME messages in OnFocusOut.
DCHECK(focused_);
}
void IMContextEfl::OnFocusIn() {
+
+ ClearQueues();
+ view_->ClearQueues();
+
if (focused_)
return;
// Disable RenderWidget's IME related events to save bandwidth.
if (view_->GetRenderWidgetHost())
RenderWidgetHostImpl::From(view_->GetRenderWidgetHost())->SetInputMethodActive(false);
+
+ ClearQueues();
+ view_->ClearQueues();
}
void IMContextEfl::CancelComposition() {
#if USE_IM_COMPOSITING
IM_CTX_LOG;
composition_.Clear();
- if (view_->GetRenderWidgetHost()) {
- char* text = static_cast<char*>(event_info);
- base::string16 text16;
- base::UTF8ToUTF16(text, strlen(text), &text16);
- // XXX Consider doing the SendFakeCompositionKeyEvent workaround what Gtk does.
- RenderWidgetHostImpl::From(view_->GetRenderWidgetHost())->ImeConfirmComposition(text16, gfx::Range::InvalidRange(), false);
- }
+ char* text = static_cast<char*>(event_info);
+ base::string16 text16;
+ base::UTF8ToUTF16(text, strlen(text), &text16);
+
+ // Only add commit to queue, till we dont know if key event
+ // should be handled. It can be default prevented for exactly.
+ commit_queue_.push(text16);
+
+ // sending fake key event if hardware key is not handled as it is
+ // in Webkit.
+ SendFakeCompositionKeyEvent(text);
#endif
}
+void IMContextEfl::SendFakeCompositionKeyEvent(char * buf) {
+ if (is_handling_keydown_)
+ return;
+
+ if (!buf)
+ return;
+
+ UChar32 ch = 0;
+ if (strlen(buf)) {
+ ch = buf[strlen(buf) - 1];
+ }
+
+ std::string str;
+
+ if (u_isspace(ch))
+ str = "space";
+ else
+ str.append(1, ch);
+
+ Evas_Event_Key_Down downEvent;
+ memset(&downEvent, 0, sizeof(Evas_Event_Key_Down));
+ downEvent.key = str.c_str();
+ downEvent.string = str.c_str();
+
+ NativeWebKeyboardEvent n_event = WebEventFactoryEfl::toWebKeyboardEvent(view_->evas(), &downEvent);
+ n_event.type = blink::WebInputEvent::KeyDown;
+
+ n_event.isSystemKey = true;
+
+ if (!view_->GetRenderWidgetHost())
+ return;
+
+ view_->KeyUpEventQueuePush(n_event.windowsKeyCode);
+ view_->GetRenderWidgetHost()->ForwardKeyboardEvent(n_event);
+}
+
void IMContextEfl::OnPreeditChanged(void* data, Ecore_IMF_Context* context, void* event_info) {
#if USE_IM_COMPOSITING
composition_.Clear();
if (!buffer)
return;
+ SendFakeCompositionKeyEvent(buffer);
composition_.Clear();
composition_.text = base::UTF8ToUTF16(buffer);
- free(buffer);
-
- if (!view_->GetRenderWidgetHost())
- return;
composition_.underlines.push_back(ui::CompositionUnderline(0, composition_.text.length(), SK_ColorBLACK, false));
composition_.selection = gfx::Range(composition_.text.length());
- const std::vector<blink::WebCompositionUnderline>& underlines =
- reinterpret_cast<const std::vector<blink::WebCompositionUnderline>&>(
- composition_.underlines);
- RenderWidgetHostImpl::From(
- view_->GetRenderWidgetHost())->ImeSetComposition(
- composition_.text, underlines, composition_.selection.start(),
- composition_.selection.end());
+ // Only add preedit to queue, till we dont know if key event
+ // should be handled. It can be default prevented for exactly.
+ preedit_queue_.push(composition_);
+
+ free(buffer);
+
#endif
}
return (context_ && focused_ && ecore_imf_context_input_panel_state_get(context_) != ECORE_IMF_INPUT_PANEL_STATE_HIDE);
}
+void IMContextEfl::ClearQueues() {
+ while (!commit_queue_.empty()) {
+ commit_queue_.pop();
+ }
+
+ while (!preedit_queue_.empty()) {
+ preedit_queue_.pop();
+ }
+}
+
} // namespace content
#include "ui/base/ime/text_input_type.h"
#include "ui/base/ime/composition_text.h"
#include "ui/gfx/rect.h"
+#include "content/public/browser/native_web_keyboard_event.h"
+#include "browser/renderer_host/web_event_factory_efl.h"
#include <Evas.h>
class Rect;
}
+typedef std::queue<base::string16> CommitQueue;
+typedef std::queue<ui::CompositionText> PreeditQueue;
+
typedef struct _Ecore_IMF_Context Ecore_IMF_Context;
namespace content {
void SetIsInFormTag(bool is_in_form_tag);
bool IsShow();
gfx::Rect GetIMERect() const { return ime_rect_; }
+ CommitQueue GetCommitQueue() { return commit_queue_; }
+ PreeditQueue GetPreeditQueue() { return preedit_queue_; }
+ void CommitQueuePop() { commit_queue_.pop(); }
+ void PreeditQueuePop() { preedit_queue_.pop(); }
+ void ClearQueues();
+
+ void SendFakeCompositionKeyEvent(char * buf);
private:
IMContextEfl(RenderWidgetHostViewEfl*, Ecore_IMF_Context*);
ui::CompositionText composition_;
gfx::Rect ime_rect_;
+
+ CommitQueue commit_queue_;
+ PreeditQueue preedit_queue_;
+
+ bool is_handling_keydown_;
};
} // namespace content
#include "ui/views/widget/desktop_aura/desktop_screen.h"
#include "ui/events/event_utils.h"
#include "browser/motion/wkext_motion.h"
+#include "content/common/input_messages.h"
#include <assert.h>
#include <Ecore.h>
IPC_MESSAGE_HANDLER(EwkHostMsg_DidChangePageScaleFactor, OnDidChangePageScaleFactor)
IPC_MESSAGE_HANDLER(EwkHostMsg_DidChangePageScaleRange, OnDidChangePageScaleRange)
IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputInFormStateChanged, OnTextInputInFormStateChanged)
+#if defined(OS_TIZEN)
+ IPC_MESSAGE_HANDLER(InputHostMsg_DidInputEventHandled, OnDidInputEventHandled)
+#endif
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
void RenderWidgetHostViewEfl::HandleEvasEvent(const Evas_Event_Key_Down* event) {
LOG(INFO) << __PRETTY_FUNCTION__ << " : " << event->key;
bool wasFiltered = false;
- if (im_context_)
- im_context_->HandleKeyDownEvent(event, &wasFiltered);
if (!strcmp(event->key, "BackSpace")) {
SelectionControllerEfl* controller = web_view_->GetSelectionController();
controller->HideHandleAndContextMenu();
}
- if(!wasFiltered)
+ if (im_context_) {
+ im_context_->HandleKeyDownEvent(event, &wasFiltered);
+ NativeWebKeyboardEvent n_event = WebEventFactoryEfl::toWebKeyboardEvent(evas_, event);
+
+ if (wasFiltered)
+ n_event.isSystemKey = true;
+
+ // Do not forward keyevent now if there is fake key event
+ // handling at the moment to preserve orders of events as in Webkit
+ if (im_context_->GetPreeditQueue().empty() ||
+ keyupev_queue_.empty()) {
+ host_->ForwardKeyboardEvent(n_event);
+ } else {
+ NativeWebKeyboardEvent *n_event_ptr = new NativeWebKeyboardEvent();
+
+ n_event_ptr->timeStampSeconds = n_event.timeStampSeconds;
+ n_event_ptr->modifiers = n_event.modifiers;
+ n_event_ptr->type = n_event.type;
+ n_event_ptr->nativeKeyCode = n_event.nativeKeyCode;
+ n_event_ptr->windowsKeyCode = n_event.windowsKeyCode;
+ n_event_ptr->isSystemKey = n_event.isSystemKey;
+ n_event_ptr->unmodifiedText[0] = n_event.unmodifiedText[0];
+ n_event_ptr->text[0] = n_event.text[0];
+
+ keydownev_queue_.push(n_event_ptr);
+ }
+
+ keyupev_queue_.push(n_event.windowsKeyCode);
+ } else
host_->ForwardKeyboardEvent(WebEventFactoryEfl::toWebKeyboardEvent(evas_, event));
}
if (im_context_)
im_context_->HandleKeyUpEvent(event, &wasFiltered);
- if(!wasFiltered)
- host_->ForwardKeyboardEvent(WebEventFactoryEfl::toWebKeyboardEvent(evas_, event));
+ if (!im_context_)
+ host_->ForwardKeyboardEvent(WebEventFactoryEfl::toWebKeyboardEvent(evas_, event));
}
#ifdef OS_TIZEN
ui::GestureEventDetails(ui::ET_GESTURE_PINCH_UPDATE, motionEvent->scale, 0), 1);
HandleGesture(&event);
}
+
+void RenderWidgetHostViewEfl::OnDidInputEventHandled(const blink::WebInputEvent* input_event, bool processed) {
+ if (!im_context_)
+ return;
+
+ if (blink::WebInputEvent::isKeyboardEventType(input_event->type)) {
+ if (input_event->type == blink::WebInputEvent::KeyDown) {
+
+ HandleCommitQueue(processed);
+ HandlePreeditQueue(processed);
+
+ HandleKeyUpQueue();
+ HandleKeyDownQueue();
+ }
+ }
+}
#endif
void RenderWidgetHostViewEfl::HandleGesture(ui::GestureEvent* event) {
// Update the touch event first.
blink::WebTouchPoint* point =
content::UpdateWebTouchEventFromUIEvent(*event, &touch_event_);
-
// Forward the touch event only if a touch point was updated, and there's a
// touch-event handler in the page, and no other touch-event is in the queue.
// It is important to always consume the event if there is a touch-event
// handler in the page, or some touch-event is already in the queue, even if
// no point has been updated, to make sure that this event does not get
// processed by the gesture recognizer before the events in the queue.
- if (host_->ShouldForwardTouchEvent())
+ if (host_->ShouldForwardTouchEvent()) {
event->StopPropagation();
+ }
if (point) {
if (host_->ShouldForwardTouchEvent()) {
return web_view_->GetSelectionController();
}
+void RenderWidgetHostViewEfl::ClearQueues() {
+ while (!keyupev_queue_.empty()) {
+ keyupev_queue_.pop();
+ }
+
+ while (!keydownev_queue_.empty()) {
+ delete keydownev_queue_.front();
+ keydownev_queue_.pop();
+ }
+}
+
+void RenderWidgetHostViewEfl::HandleCommitQueue(bool processed) {
+ if (!im_context_)
+ return;
+
+ if (!processed) {
+ if (!im_context_->GetCommitQueue().empty()) {
+ base::string16 text16 = im_context_->GetCommitQueue().front();
+ host_->ImeConfirmComposition(text16, gfx::Range::InvalidRange(), false);
+ im_context_->CommitQueuePop();
+ }
+ } else {
+ if (!im_context_->GetCommitQueue().empty())
+ im_context_->CommitQueuePop();
+ }
+}
+
+void RenderWidgetHostViewEfl::HandlePreeditQueue(bool processed) {
+ if (!im_context_)
+ return;
+
+ if (!processed) {
+ if (!im_context_->GetPreeditQueue().empty()) {
+ ui::CompositionText composition_ = im_context_->GetPreeditQueue().front();
+
+ const std::vector<blink::WebCompositionUnderline>& underlines =
+ reinterpret_cast<const std::vector<blink::WebCompositionUnderline>&>(
+ composition_.underlines);
+
+ host_->ImeSetComposition(
+ composition_.text, underlines, composition_.selection.start(),
+ composition_.selection.end());
+ im_context_->PreeditQueuePop();
+ }
+ } else {
+ if (!im_context_->GetPreeditQueue().empty())
+ im_context_->PreeditQueuePop();
+ }
+}
+
+void RenderWidgetHostViewEfl::HandleKeyUpQueue() {
+ if (!im_context_)
+ return;
+
+ if (keyupev_queue_.empty())
+ return;
+
+ int keyCode = keyupev_queue_.front();
+ SendCompositionKeyUpEvent(keyCode);
+ keyupev_queue_.pop();
+}
+
+void RenderWidgetHostViewEfl::HandleKeyDownQueue() {
+ if (!im_context_)
+ return;
+
+ if (keydownev_queue_.empty())
+ return;
+
+ NativeWebKeyboardEvent *n_event = keydownev_queue_.front();
+ host_->ForwardKeyboardEvent(*n_event);
+ keydownev_queue_.pop();
+ delete n_event;
+}
+
+void RenderWidgetHostViewEfl::SendCompositionKeyUpEvent(char c) {
+ NativeWebKeyboardEvent event;
+ event.windowsKeyCode = c;
+ event.skip_in_browser = false;
+ event.type = blink::WebInputEvent::KeyUp;
+ host_->ForwardKeyboardEvent(event);
+}
+
} // namespace content
#include "ui/base/ime/text_input_client.h"
#include "eweb_view.h"
#include "browser/renderer_host/im_context_efl.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
+
+#include <deque>
#include <Evas.h>
#include <Ecore_Evas.h>
#include <Evas_GL.h>
+#include <Ecore_IMF_Evas.h>
#ifndef OS_TIZEN
// On desktops using mesa as GLES2 implementation GLchar is not defined
#ifdef OS_TIZEN
void FilterInputMotion(const blink::WebGestureEvent& gesture_event);
void makePinchZoom(void* eventInfo);
+ void OnDidInputEventHandled(const blink::WebInputEvent* input_event, bool processed);
#endif
Evas* evas() const {
gfx::Point ConvertPointInViewPix(gfx::Point point);
void OnTextInputInFormStateChanged(bool is_in_form_tag);
+ void KeyUpEventQueuePush(int key) { keyupev_queue_.push(key); }
+ void ClearQueues();
protected:
friend class RenderWidgetHostView;
Ecore_X_Window GetEcoreXWindow() const;
+ void HandleCommitQueue(bool processed);
+ void HandlePreeditQueue(bool processed);
+ void HandleKeyUpQueue();
+ void HandleKeyDownQueue();
+ void SendCompositionKeyUpEvent(char c);
+
RenderWidgetHostImpl* host_;
EWebView* web_view_;
IMContextEfl* im_context_;
unsigned long next_pixmap_id_;
GLuint texture_id_;
+ typedef std::queue<int> KeyUpEventQueue;
+ KeyUpEventQueue keyupev_queue_;
+
+ typedef std::queue<NativeWebKeyboardEvent*> KeyDownEventQueue;
+ KeyDownEventQueue keydownev_queue_;
+
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewEfl);
};