<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[175046] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/175046">175046</a></dd>
<dt>Author</dt> <dd>carlosgc@webkit.org</dd>
<dt>Date</dt> <dd>2014-10-22 06:00:12 -0700 (Wed, 22 Oct 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>[GTK] Move GtkInputMethodFilter from Platform to WebKit2
https://bugs.webkit.org/show_bug.cgi?id=137884

Reviewed by Gustavo Noronha Silva.

Source/WebCore:

Remove GtkInputMethodFilter.

* PlatformGTK.cmake:
* platform/gtk/GtkInputMethodFilter.cpp: Removed.
* platform/gtk/GtkInputMethodFilter.h: Removed.

Source/WebKit2:

Merge WebViewBaseInputMethodFilter and GtkInputMethodFilter into a
single class InputMethodFilter. The code is mostly the same, but
instead of having a setWebView method only to get the WebPageProxy,
it has a setPage method that passes the WebPageProxy. The GtkIMContext
client window is set by the WebView when it's realized/unrealized.

* PlatformGTK.cmake:
* Shared/NativeWebKeyboardEvent.h:
* Shared/gtk/NativeWebKeyboardEventGtk.cpp:
(WebKit::NativeWebKeyboardEvent::NativeWebKeyboardEvent):
* UIProcess/API/gtk/WebKitWebViewBase.cpp:
(webkitWebViewBaseRealize):
(webkitWebViewBaseUnrealize):
(webkit_web_view_base_class_init):
(webkitWebViewBaseCreateWebPage):
(webkitWebViewBaseEnterFullScreen): Deleted.
* UIProcess/API/gtk/WebViewBaseInputMethodFilter.cpp: Removed.
* UIProcess/API/gtk/WebViewBaseInputMethodFilter.h: Removed.
* UIProcess/gtk/InputMethodFilter.cpp: Added.
(WebKit::InputMethodFilter::handleCommitCallback):
(WebKit::InputMethodFilter::handlePreeditStartCallback):
(WebKit::InputMethodFilter::handlePreeditChangedCallback):
(WebKit::InputMethodFilter::handlePreeditEndCallback):
(WebKit::InputMethodFilter::InputMethodFilter):
(WebKit::InputMethodFilter::~InputMethodFilter):
(WebKit::InputMethodFilter::setEnabled):
(WebKit::InputMethodFilter::setCursorRect):
(WebKit::InputMethodFilter::handleKeyboardEvent):
(WebKit::InputMethodFilter::handleKeyboardEventWithCompositionResults):
(WebKit::InputMethodFilter::filterKeyEvent):
(WebKit::InputMethodFilter::confirmComposition):
(WebKit::InputMethodFilter::updatePreedit):
(WebKit::InputMethodFilter::notifyFocusedIn):
(WebKit::InputMethodFilter::notifyFocusedOut):
(WebKit::InputMethodFilter::notifyMouseButtonPress):
(WebKit::InputMethodFilter::confirmCurrentComposition):
(WebKit::InputMethodFilter::cancelContextComposition):
(WebKit::InputMethodFilter::sendCompositionAndPreeditWithFakeKeyEvents):
(WebKit::InputMethodFilter::handleCommit):
(WebKit::InputMethodFilter::handlePreeditStart):
(WebKit::InputMethodFilter::handlePreeditChanged):
(WebKit::InputMethodFilter::handlePreeditEnd):
(WebKit::InputMethodFilter::logHandleKeyboardEventForTesting):
(WebKit::InputMethodFilter::logHandleKeyboardEventWithCompositionResultsForTesting):
(WebKit::InputMethodFilter::logConfirmCompositionForTesting):
(WebKit::InputMethodFilter::logSetPreeditForTesting):
* UIProcess/gtk/InputMethodFilter.h: Added.
(WebKit::InputMethodFilter::context):
(WebKit::InputMethodFilter::setPage):
(WebKit::InputMethodFilter::setTestingMode):
(WebKit::InputMethodFilter::events):

Tools:

Move InputMethodFilter test from WebCore tests to WebKit2 tests
and adapt it to use the new InputMethodFilter WebKit class. Instead
of having virtual methods just for testing, it has a testing mode
that logs the events.

* TestWebKitAPI/PlatformGTK.cmake:
* TestWebKitAPI/Tests/WebKit2/gtk/InputMethodFilter.cpp: Renamed from Tools/TestWebKitAPI/Tests/WebCore/gtk/InputMethodFilter.cpp.
(TestWebKitAPI::TestInputMethodFilter::TestInputMethodFilter):
(TestWebKitAPI::TestInputMethodFilter::~TestInputMethodFilter):
(TestWebKitAPI::TestInputMethodFilter::sendKeyEventToFilter):
(TestWebKitAPI::TestInputMethodFilter::sendPressAndReleaseKeyEventPairToFilter):
(TestWebKitAPI::TEST):
(TestWebKitAPI::temporaryGetPreeditStringOverride):
(TestWebKitAPI::temporaryResetOverride):
(TestWebKitAPI::verifyCanceledComposition):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorePlatformGTKcmake">trunk/Source/WebCore/PlatformGTK.cmake</a></li>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2PlatformGTKcmake">trunk/Source/WebKit2/PlatformGTK.cmake</a></li>
<li><a href="#trunkSourceWebKit2SharedNativeWebKeyboardEventh">trunk/Source/WebKit2/Shared/NativeWebKeyboardEvent.h</a></li>
<li><a href="#trunkSourceWebKit2SharedgtkNativeWebKeyboardEventGtkcpp">trunk/Source/WebKit2/Shared/gtk/NativeWebKeyboardEventGtk.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPIgtkWebKitWebViewBasecpp">trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp</a></li>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsTestWebKitAPIPlatformGTKcmake">trunk/Tools/TestWebKitAPI/PlatformGTK.cmake</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWebKit2UIProcessgtkInputMethodFiltercpp">trunk/Source/WebKit2/UIProcess/gtk/InputMethodFilter.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcessgtkInputMethodFilterh">trunk/Source/WebKit2/UIProcess/gtk/InputMethodFilter.h</a></li>
<li>trunk/Tools/TestWebKitAPI/Tests/WebKit2/gtk/</li>
<li><a href="#trunkToolsTestWebKitAPITestsWebKit2gtkInputMethodFiltercpp">trunk/Tools/TestWebKitAPI/Tests/WebKit2/gtk/InputMethodFilter.cpp</a></li>
</ul>

<h3>Removed Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreplatformgtkGtkInputMethodFiltercpp">trunk/Source/WebCore/platform/gtk/GtkInputMethodFilter.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgtkGtkInputMethodFilterh">trunk/Source/WebCore/platform/gtk/GtkInputMethodFilter.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPIgtkWebViewBaseInputMethodFiltercpp">trunk/Source/WebKit2/UIProcess/API/gtk/WebViewBaseInputMethodFilter.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPIgtkWebViewBaseInputMethodFilterh">trunk/Source/WebKit2/UIProcess/API/gtk/WebViewBaseInputMethodFilter.h</a></li>
<li><a href="#trunkToolsTestWebKitAPITestsWebCoregtkInputMethodFiltercpp">trunk/Tools/TestWebKitAPI/Tests/WebCore/gtk/InputMethodFilter.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (175045 => 175046)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-10-22 12:27:44 UTC (rev 175045)
+++ trunk/Source/WebCore/ChangeLog        2014-10-22 13:00:12 UTC (rev 175046)
</span><span class="lines">@@ -1,3 +1,16 @@
</span><ins>+2014-10-22  Carlos Garcia Campos  &lt;cgarcia@igalia.com&gt;
+
+        [GTK] Move GtkInputMethodFilter from Platform to WebKit2
+        https://bugs.webkit.org/show_bug.cgi?id=137884
+
+        Reviewed by Gustavo Noronha Silva.
+
+        Remove GtkInputMethodFilter.
+
+        * PlatformGTK.cmake:
+        * platform/gtk/GtkInputMethodFilter.cpp: Removed.
+        * platform/gtk/GtkInputMethodFilter.h: Removed.
+
</ins><span class="cx"> 2014-10-22  Tibor Meszaros  &lt;tmeszaros.u-szeged@partner.samsung.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Match spec for font-weight: bolder|lighter
</span></span></pre></div>
<a id="trunkSourceWebCorePlatformGTKcmake"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/PlatformGTK.cmake (175045 => 175046)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/PlatformGTK.cmake        2014-10-22 12:27:44 UTC (rev 175045)
+++ trunk/Source/WebCore/PlatformGTK.cmake        2014-10-22 13:00:12 UTC (rev 175046)
</span><span class="lines">@@ -222,7 +222,6 @@
</span><span class="cx">     platform/gtk/DragImageGtk.cpp
</span><span class="cx">     platform/gtk/GRefPtrGtk.cpp
</span><span class="cx">     platform/gtk/GtkClickCounter.cpp
</span><del>-    platform/gtk/GtkInputMethodFilter.cpp
</del><span class="cx">     platform/gtk/GtkUtilities.cpp
</span><span class="cx">     platform/gtk/GtkVersioning.c
</span><span class="cx">     platform/gtk/KeyBindingTranslator.cpp
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgtkGtkInputMethodFiltercpp"></a>
<div class="delfile"><h4>Deleted: trunk/Source/WebCore/platform/gtk/GtkInputMethodFilter.cpp (175045 => 175046)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/gtk/GtkInputMethodFilter.cpp        2014-10-22 12:27:44 UTC (rev 175045)
+++ trunk/Source/WebCore/platform/gtk/GtkInputMethodFilter.cpp        2014-10-22 13:00:12 UTC (rev 175046)
</span><span class="lines">@@ -1,353 +0,0 @@
</span><del>-/*
- *  Copyright (C) 2012 Igalia S.L.
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#include &quot;config.h&quot;
-#include &quot;GtkInputMethodFilter.h&quot;
-
-#include &quot;GUniquePtrGtk.h&quot;
-#include &quot;GtkVersioning.h&quot;
-#include &lt;gdk/gdkkeysyms.h&gt;
-#include &lt;gtk/gtk.h&gt;
-#include &lt;wtf/MathExtras.h&gt;
-#include &lt;wtf/gobject/GUniquePtr.h&gt;
-
-// The Windows composition key event code is 299 or VK_PROCESSKEY. We need to
-// emit this code for web compatibility reasons when key events trigger
-// composition results. GDK doesn't have an equivalent, so we send VoidSymbol
-// here to WebCore. PlatformKeyEvent knows to convert this code into
-// VK_PROCESSKEY.
-const int gCompositionEventKeyCode = GDK_KEY_VoidSymbol;
-
-namespace WebCore {
-
-static void handleCommitCallback(GtkIMContext*, const char* compositionString, GtkInputMethodFilter* filter)
-{
-    filter-&gt;handleCommit(compositionString);
-}
-
-static void handlePreeditStartCallback(GtkIMContext*, GtkInputMethodFilter* filter)
-{
-    filter-&gt;handlePreeditStart();
-}
-
-static void handlePreeditChangedCallback(GtkIMContext*, GtkInputMethodFilter* filter)
-{
-    filter-&gt;handlePreeditChanged();
-}
-
-static void handlePreeditEndCallback(GtkIMContext*, GtkInputMethodFilter* filter)
-{
-    filter-&gt;handlePreeditEnd();
-}
-
-static void handleWidgetRealize(GtkWidget* widget, GtkInputMethodFilter* filter)
-{
-    GdkWindow* window = gtk_widget_get_window(widget);
-    ASSERT(window);
-    gtk_im_context_set_client_window(filter-&gt;context(), window);
-}
-
-void GtkInputMethodFilter::setWidget(GtkWidget* widget)
-{
-    ASSERT(!m_widget);
-
-    m_widget = widget;
-    if (gtk_widget_get_window(m_widget))
-        handleWidgetRealize(m_widget, this);
-    else
-        g_signal_connect_after(widget, &quot;realize&quot;, G_CALLBACK(handleWidgetRealize), this);
-}
-
-void GtkInputMethodFilter::setCursorRect(const IntRect&amp; cursorRect)
-{
-    // Don't move the window unless the cursor actually moves more than 10
-    // pixels. This prevents us from making the window flash during minor
-    // cursor adjustments.
-    static const int windowMovementThreshold = 10 * 10;
-    if (cursorRect.location().distanceSquaredToPoint(m_lastCareLocation) &lt; windowMovementThreshold)
-        return;
-
-    m_lastCareLocation = cursorRect.location();
-    IntRect translatedRect = cursorRect;
-
-    ASSERT(m_widget);
-    GtkAllocation allocation;
-    gtk_widget_get_allocation(m_widget, &amp;allocation);
-    translatedRect.move(allocation.x, allocation.y);
-
-    GdkRectangle gdkCursorRect = { cursorRect.x(), cursorRect.y(), cursorRect.width(), cursorRect.height() };
-    gtk_im_context_set_cursor_location(m_context.get(), &amp;gdkCursorRect);
-}
-
-GtkInputMethodFilter::GtkInputMethodFilter()
-    : m_cursorOffset(0)
-    , m_context(adoptGRef(gtk_im_multicontext_new()))
-    , m_widget(0)
-    , m_enabled(false)
-    , m_composingTextCurrently(false)
-    , m_filteringKeyEvent(false)
-    , m_preeditChanged(false)
-    , m_preventNextCommit(false)
-    , m_justSentFakeKeyUp(false)
-    , m_lastFilteredKeyPressCodeWithNoResults(GDK_KEY_VoidSymbol)
-{
-    g_signal_connect(m_context.get(), &quot;commit&quot;, G_CALLBACK(handleCommitCallback), this);
-    g_signal_connect(m_context.get(), &quot;preedit-start&quot;, G_CALLBACK(handlePreeditStartCallback), this);
-    g_signal_connect(m_context.get(), &quot;preedit-changed&quot;, G_CALLBACK(handlePreeditChangedCallback), this);
-    g_signal_connect(m_context.get(), &quot;preedit-end&quot;, G_CALLBACK(handlePreeditEndCallback), this);
-}
-
-GtkInputMethodFilter::~GtkInputMethodFilter()
-{
-    g_signal_handlers_disconnect_by_func(m_context.get(), reinterpret_cast&lt;void*&gt;(handleCommitCallback), this);
-    g_signal_handlers_disconnect_by_func(m_context.get(), reinterpret_cast&lt;void*&gt;(handlePreeditStartCallback), this);
-    g_signal_handlers_disconnect_by_func(m_context.get(), reinterpret_cast&lt;void*&gt;(handlePreeditChangedCallback), this);
-    g_signal_handlers_disconnect_by_func(m_context.get(), reinterpret_cast&lt;void*&gt;(handlePreeditEndCallback), this);
-    g_signal_handlers_disconnect_by_func(m_widget, reinterpret_cast&lt;void*&gt;(handleWidgetRealize), this);
-}
-
-void GtkInputMethodFilter::setEnabled(bool enabled)
-{
-    m_enabled = enabled;
-    if (enabled)
-        gtk_im_context_focus_in(m_context.get());
-    else
-        gtk_im_context_focus_out(m_context.get());
-}
-
-bool GtkInputMethodFilter::filterKeyEvent(GdkEventKey* event)
-{
-    if (!canEdit() || !m_enabled)
-        return sendSimpleKeyEvent(event);
-
-    m_preeditChanged = false;
-    m_filteringKeyEvent = true;
-
-    unsigned int lastFilteredKeyPressCodeWithNoResults = m_lastFilteredKeyPressCodeWithNoResults;
-    m_lastFilteredKeyPressCodeWithNoResults = GDK_KEY_VoidSymbol;
-
-    bool filtered = gtk_im_context_filter_keypress(m_context.get(), event);
-    m_filteringKeyEvent = false;
-
-    bool justSentFakeKeyUp = m_justSentFakeKeyUp;
-    m_justSentFakeKeyUp = false;
-    if (justSentFakeKeyUp &amp;&amp; event-&gt;type == GDK_KEY_RELEASE)
-        return true;
-
-    // Simple input methods work such that even normal keystrokes fire the
-    // commit signal. We detect those situations and treat them as normal
-    // key events, supplying the commit string as the key character.
-    if (filtered &amp;&amp; !m_composingTextCurrently &amp;&amp; !m_preeditChanged &amp;&amp; m_confirmedComposition.length() == 1) {
-        bool result = sendSimpleKeyEvent(event, m_confirmedComposition);
-        m_confirmedComposition = String();
-        return result;
-    }
-
-    if (filtered &amp;&amp; event-&gt;type == GDK_KEY_PRESS) {
-        if (!m_preeditChanged &amp;&amp; m_confirmedComposition.isNull()) {
-            m_composingTextCurrently = true;
-            m_lastFilteredKeyPressCodeWithNoResults = event-&gt;keyval;
-            return true;
-        }
-
-        bool result = sendKeyEventWithCompositionResults(event);
-        if (!m_confirmedComposition.isEmpty()) {
-            m_composingTextCurrently = false;
-            m_confirmedComposition = String();
-        }
-        return result;
-    }
-
-    // If we previously filtered a key press event and it yielded no results. Suppress
-    // the corresponding key release event to avoid confusing the web content.
-    if (event-&gt;type == GDK_KEY_RELEASE &amp;&amp; lastFilteredKeyPressCodeWithNoResults == event-&gt;keyval)
-        return true;
-
-    // At this point a keystroke was either:
-    // 1. Unfiltered
-    // 2. A filtered keyup event. As the IME code in EditorClient.h doesn't
-    //    ever look at keyup events, we send any composition results before
-    //    the key event.
-    // Both might have composition results or not.
-    //
-    // It's important to send the composition results before the event
-    // because some IM modules operate that way. For example (taken from
-    // the Chromium source), the latin-post input method gives this sequence
-    // when you press 'a' and then backspace:
-    //  1. keydown 'a' (filtered)
-    //  2. preedit changed to &quot;a&quot;
-    //  3. keyup 'a' (unfiltered)
-    //  4. keydown Backspace (unfiltered)
-    //  5. commit &quot;a&quot;
-    //  6. preedit end
-    if (!m_confirmedComposition.isEmpty())
-        confirmComposition();
-    if (m_preeditChanged)
-        updatePreedit();
-    return sendSimpleKeyEvent(event);
-}
-
-void GtkInputMethodFilter::notifyMouseButtonPress()
-{
-    // Confirming the composition may trigger a selection change, which
-    // might trigger further unwanted actions on the context, so we prevent
-    // that by setting m_composingTextCurrently to false.
-    if (m_composingTextCurrently)
-        confirmCurrentComposition();
-    m_composingTextCurrently = false;
-    cancelContextComposition();
-}
-
-void GtkInputMethodFilter::resetContext()
-{
-
-    // We always cancel the current WebCore composition here, in case the
-    // composition was set outside the GTK+ IME path (via a script, for
-    // instance) and we aren't tracking it.
-    cancelCurrentComposition();
-
-    if (!m_composingTextCurrently)
-        return;
-    m_composingTextCurrently = false;
-    cancelContextComposition();
-}
-
-void GtkInputMethodFilter::cancelContextComposition()
-{
-    m_preventNextCommit = !m_preedit.isEmpty();
-
-    gtk_im_context_reset(m_context.get());
-
-    m_composingTextCurrently = false;
-    m_justSentFakeKeyUp = false;
-    m_preedit = String();
-    m_confirmedComposition = String();
-}
-
-void GtkInputMethodFilter::notifyFocusedIn()
-{
-    m_enabled = true;
-    gtk_im_context_focus_in(m_context.get());
-}
-
-void GtkInputMethodFilter::notifyFocusedOut()
-{
-    if (!m_enabled)
-        return;
-
-    if (m_composingTextCurrently)
-        confirmCurrentComposition();
-    cancelContextComposition();
-    gtk_im_context_focus_out(m_context.get());
-    m_enabled = false;
-}
-
-void GtkInputMethodFilter::confirmComposition()
-{
-    confirmCompositionText(m_confirmedComposition);
-    m_confirmedComposition = String();
-}
-
-void GtkInputMethodFilter::updatePreedit()
-{
-    setPreedit(m_preedit, m_cursorOffset);
-    m_preeditChanged = false;
-}
-
-void GtkInputMethodFilter::sendCompositionAndPreeditWithFakeKeyEvents(ResultsToSend resultsToSend)
-{
-    GUniquePtr&lt;GdkEvent&gt; event(gdk_event_new(GDK_KEY_PRESS));
-    event-&gt;key.time = GDK_CURRENT_TIME;
-    event-&gt;key.keyval = gCompositionEventKeyCode;
-    sendKeyEventWithCompositionResults(&amp;event-&gt;key, resultsToSend, EventFaked);
-
-    m_confirmedComposition = String();
-    if (resultsToSend &amp; Composition)
-        m_composingTextCurrently = false;
-
-    event-&gt;type = GDK_KEY_RELEASE;
-    sendSimpleKeyEvent(&amp;event-&gt;key, String(), EventFaked);
-    m_justSentFakeKeyUp = true;
-}
-
-void GtkInputMethodFilter::handleCommit(const char* compositionString)
-{
-    if (m_preventNextCommit) {
-        m_preventNextCommit = false;
-        return;
-    }
-
-    if (!m_enabled)
-        return;
-
-    m_confirmedComposition.append(String::fromUTF8(compositionString));
-
-    // If the commit was triggered outside of a key event, just send
-    // the IME event now. If we are handling a key event, we'll decide
-    // later how to handle this.
-    if (!m_filteringKeyEvent)
-        sendCompositionAndPreeditWithFakeKeyEvents(Composition);
-}
-
-void GtkInputMethodFilter::handlePreeditStart()
-{
-    if (m_preventNextCommit || !m_enabled)
-        return;
-    m_preeditChanged = true;
-    m_preedit = &quot;&quot;;
-}
-
-void GtkInputMethodFilter::handlePreeditChanged()
-{
-    if (!m_enabled)
-        return;
-
-    GUniqueOutPtr&lt;gchar&gt; newPreedit;
-    gtk_im_context_get_preedit_string(m_context.get(), &amp;newPreedit.outPtr(), 0, &amp;m_cursorOffset);
-
-    if (m_preventNextCommit) {
-        if (strlen(newPreedit.get()) &gt; 0)
-            m_preventNextCommit = false;
-        else
-            return;
-    }
-
-    m_preedit = String::fromUTF8(newPreedit.get());
-    m_cursorOffset = std::min(std::max(m_cursorOffset, 0), static_cast&lt;int&gt;(m_preedit.length()));
-
-    m_composingTextCurrently = !m_preedit.isEmpty();
-    m_preeditChanged = true;
-
-    if (!m_filteringKeyEvent)
-        sendCompositionAndPreeditWithFakeKeyEvents(Preedit);
-}
-
-void GtkInputMethodFilter::handlePreeditEnd()
-{
-    if (m_preventNextCommit || !m_enabled)
-        return;
-
-    m_preedit = String();
-    m_cursorOffset = 0;
-    m_preeditChanged = true;
-
-    if (!m_filteringKeyEvent)
-        updatePreedit();
-}
-
-}
</del></span></pre></div>
<a id="trunkSourceWebCoreplatformgtkGtkInputMethodFilterh"></a>
<div class="delfile"><h4>Deleted: trunk/Source/WebCore/platform/gtk/GtkInputMethodFilter.h (175045 => 175046)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/gtk/GtkInputMethodFilter.h        2014-10-22 12:27:44 UTC (rev 175045)
+++ trunk/Source/WebCore/platform/gtk/GtkInputMethodFilter.h        2014-10-22 13:00:12 UTC (rev 175046)
</span><span class="lines">@@ -1,99 +0,0 @@
</span><del>-/*
- * Copyright (C) 2012 Igalia S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef GtkInputMethodFilter_h
-#define GtkInputMethodFilter_h
-
-#include &quot;GRefPtrGtk.h&quot;
-#include &quot;IntRect.h&quot;
-#include &lt;gdk/gdk.h&gt;
-#include &lt;wtf/text/WTFString.h&gt;
-
-typedef struct _GtkIMContext GtkIMContext;
-typedef struct _GtkWidget GtkWidget;
-
-namespace WebCore {
-
-class GtkInputMethodFilter {
-public:
-    GtkInputMethodFilter();
-    ~GtkInputMethodFilter();
-
-    bool filterKeyEvent(GdkEventKey*);
-    void notifyMouseButtonPress();
-    void notifyFocusedIn();
-    void notifyFocusedOut();
-    void resetContext();
-    void setEnabled(bool);
-
-    void handleCommit(const char* compositionString);
-    void handlePreeditChanged();
-    void handlePreeditStart();
-    void handlePreeditEnd();
-
-    void confirmComposition();
-    void cancelContextComposition();
-    void updatePreedit();
-    void setCursorRect(const IntRect&amp; location);
-
-    GtkIMContext* context() { return m_context.get(); }
-
-    enum EventFakedForComposition {
-        EventFaked,
-        EventNotFaked
-    };
-
-protected:
-    enum ResultsToSend {
-        Preedit = 1 &lt;&lt; 1,
-        Composition = 1 &lt;&lt; 2,
-        PreeditAndComposition = Preedit + Composition
-    };
-
-    void setWidget(GtkWidget*);
-    virtual bool canEdit() = 0;
-    virtual bool sendSimpleKeyEvent(GdkEventKey*, WTF::String eventString = String(), EventFakedForComposition = EventNotFaked) = 0;
-    virtual bool sendKeyEventWithCompositionResults(GdkEventKey*, ResultsToSend = PreeditAndComposition, EventFakedForComposition = EventNotFaked) = 0;
-    virtual void confirmCompositionText(String composition) = 0;
-    virtual void confirmCurrentComposition() = 0;
-    virtual void cancelCurrentComposition() = 0;
-    virtual void setPreedit(String, int cursorOffset) = 0;
-
-    WTF::String m_confirmedComposition;
-    WTF::String m_preedit;
-    int m_cursorOffset;
-
-private:
-    void sendCompositionAndPreeditWithFakeKeyEvents(ResultsToSend);
-
-    GRefPtr&lt;GtkIMContext&gt; m_context;
-    GtkWidget* m_widget;
-    bool m_enabled;
-    bool m_composingTextCurrently;
-    bool m_filteringKeyEvent;
-    bool m_preeditChanged;
-    bool m_preventNextCommit;
-    bool m_justSentFakeKeyUp;
-    unsigned int m_lastFilteredKeyPressCodeWithNoResults;
-    IntPoint m_lastCareLocation;
-};
-
-} // namespace WebCore
-
-#endif // GtkInputMethodFilter_h
</del></span></pre></div>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (175045 => 175046)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2014-10-22 12:27:44 UTC (rev 175045)
+++ trunk/Source/WebKit2/ChangeLog        2014-10-22 13:00:12 UTC (rev 175046)
</span><span class="lines">@@ -1,3 +1,62 @@
</span><ins>+2014-10-22  Carlos Garcia Campos  &lt;cgarcia@igalia.com&gt;
+
+        [GTK] Move GtkInputMethodFilter from Platform to WebKit2
+        https://bugs.webkit.org/show_bug.cgi?id=137884
+
+        Reviewed by Gustavo Noronha Silva.
+
+        Merge WebViewBaseInputMethodFilter and GtkInputMethodFilter into a
+        single class InputMethodFilter. The code is mostly the same, but
+        instead of having a setWebView method only to get the WebPageProxy,
+        it has a setPage method that passes the WebPageProxy. The GtkIMContext
+        client window is set by the WebView when it's realized/unrealized.
+
+        * PlatformGTK.cmake:
+        * Shared/NativeWebKeyboardEvent.h:
+        * Shared/gtk/NativeWebKeyboardEventGtk.cpp:
+        (WebKit::NativeWebKeyboardEvent::NativeWebKeyboardEvent):
+        * UIProcess/API/gtk/WebKitWebViewBase.cpp:
+        (webkitWebViewBaseRealize):
+        (webkitWebViewBaseUnrealize):
+        (webkit_web_view_base_class_init):
+        (webkitWebViewBaseCreateWebPage):
+        (webkitWebViewBaseEnterFullScreen): Deleted.
+        * UIProcess/API/gtk/WebViewBaseInputMethodFilter.cpp: Removed.
+        * UIProcess/API/gtk/WebViewBaseInputMethodFilter.h: Removed.
+        * UIProcess/gtk/InputMethodFilter.cpp: Added.
+        (WebKit::InputMethodFilter::handleCommitCallback):
+        (WebKit::InputMethodFilter::handlePreeditStartCallback):
+        (WebKit::InputMethodFilter::handlePreeditChangedCallback):
+        (WebKit::InputMethodFilter::handlePreeditEndCallback):
+        (WebKit::InputMethodFilter::InputMethodFilter):
+        (WebKit::InputMethodFilter::~InputMethodFilter):
+        (WebKit::InputMethodFilter::setEnabled):
+        (WebKit::InputMethodFilter::setCursorRect):
+        (WebKit::InputMethodFilter::handleKeyboardEvent):
+        (WebKit::InputMethodFilter::handleKeyboardEventWithCompositionResults):
+        (WebKit::InputMethodFilter::filterKeyEvent):
+        (WebKit::InputMethodFilter::confirmComposition):
+        (WebKit::InputMethodFilter::updatePreedit):
+        (WebKit::InputMethodFilter::notifyFocusedIn):
+        (WebKit::InputMethodFilter::notifyFocusedOut):
+        (WebKit::InputMethodFilter::notifyMouseButtonPress):
+        (WebKit::InputMethodFilter::confirmCurrentComposition):
+        (WebKit::InputMethodFilter::cancelContextComposition):
+        (WebKit::InputMethodFilter::sendCompositionAndPreeditWithFakeKeyEvents):
+        (WebKit::InputMethodFilter::handleCommit):
+        (WebKit::InputMethodFilter::handlePreeditStart):
+        (WebKit::InputMethodFilter::handlePreeditChanged):
+        (WebKit::InputMethodFilter::handlePreeditEnd):
+        (WebKit::InputMethodFilter::logHandleKeyboardEventForTesting):
+        (WebKit::InputMethodFilter::logHandleKeyboardEventWithCompositionResultsForTesting):
+        (WebKit::InputMethodFilter::logConfirmCompositionForTesting):
+        (WebKit::InputMethodFilter::logSetPreeditForTesting):
+        * UIProcess/gtk/InputMethodFilter.h: Added.
+        (WebKit::InputMethodFilter::context):
+        (WebKit::InputMethodFilter::setPage):
+        (WebKit::InputMethodFilter::setTestingMode):
+        (WebKit::InputMethodFilter::events):
+
</ins><span class="cx"> 2014-10-21  Tim Horton  &lt;timothy_horton@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Quick Look preview bubble has unnecessary controls
</span></span></pre></div>
<a id="trunkSourceWebKit2PlatformGTKcmake"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/PlatformGTK.cmake (175045 => 175046)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/PlatformGTK.cmake        2014-10-22 12:27:44 UTC (rev 175045)
+++ trunk/Source/WebKit2/PlatformGTK.cmake        2014-10-22 13:00:12 UTC (rev 175046)
</span><span class="lines">@@ -228,8 +228,6 @@
</span><span class="cx">     UIProcess/API/gtk/WebKitWindowProperties.cpp
</span><span class="cx">     UIProcess/API/gtk/WebKitWindowProperties.h
</span><span class="cx">     UIProcess/API/gtk/WebKitWindowPropertiesPrivate.h
</span><del>-    UIProcess/API/gtk/WebViewBaseInputMethodFilter.cpp
-    UIProcess/API/gtk/WebViewBaseInputMethodFilter.h
</del><span class="cx">     UIProcess/API/gtk/webkit2.h
</span><span class="cx"> 
</span><span class="cx">     UIProcess/InspectorServer/gtk/WebInspectorServerGtk.cpp
</span><span class="lines">@@ -254,6 +252,7 @@
</span><span class="cx">     UIProcess/gtk/DragAndDropHandler.cpp
</span><span class="cx">     UIProcess/gtk/ExperimentalFeatures.cpp
</span><span class="cx">     UIProcess/gtk/GestureController.cpp
</span><ins>+    UIProcess/gtk/InputMethodFilter.cpp
</ins><span class="cx">     UIProcess/gtk/TextCheckerGtk.cpp
</span><span class="cx">     UIProcess/gtk/WebContextGtk.cpp
</span><span class="cx">     UIProcess/gtk/WebContextMenuProxyGtk.cpp
</span></span></pre></div>
<a id="trunkSourceWebKit2SharedNativeWebKeyboardEventh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/Shared/NativeWebKeyboardEvent.h (175045 => 175046)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/Shared/NativeWebKeyboardEvent.h        2014-10-22 12:27:44 UTC (rev 175045)
+++ trunk/Source/WebKit2/Shared/NativeWebKeyboardEvent.h        2014-10-22 13:00:12 UTC (rev 175046)
</span><span class="lines">@@ -44,9 +44,9 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> #if PLATFORM(GTK)
</span><ins>+#include &quot;InputMethodFilter.h&quot;
</ins><span class="cx"> #include &lt;WebCore/CompositionResults.h&gt;
</span><span class="cx"> #include &lt;WebCore/GUniquePtrGtk.h&gt;
</span><del>-#include &lt;WebCore/GtkInputMethodFilter.h&gt;
</del><span class="cx"> typedef union _GdkEvent GdkEvent;
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="lines">@@ -63,7 +63,7 @@
</span><span class="cx">     NativeWebKeyboardEvent(NSEvent *, bool handledByInputMethod, const Vector&lt;WebCore::KeypressCommand&gt;&amp;);
</span><span class="cx"> #elif PLATFORM(GTK)
</span><span class="cx">     NativeWebKeyboardEvent(const NativeWebKeyboardEvent&amp;);
</span><del>-    NativeWebKeyboardEvent(GdkEvent*, const WebCore::CompositionResults&amp;, WebCore::GtkInputMethodFilter::EventFakedForComposition);
</del><ins>+    NativeWebKeyboardEvent(GdkEvent*, const WebCore::CompositionResults&amp;, InputMethodFilter::EventFakedForComposition);
</ins><span class="cx"> #elif PLATFORM(EFL)
</span><span class="cx">     NativeWebKeyboardEvent(const Evas_Event_Key_Down*, bool);
</span><span class="cx">     NativeWebKeyboardEvent(const Evas_Event_Key_Up*);
</span></span></pre></div>
<a id="trunkSourceWebKit2SharedgtkNativeWebKeyboardEventGtkcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/Shared/gtk/NativeWebKeyboardEventGtk.cpp (175045 => 175046)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/Shared/gtk/NativeWebKeyboardEventGtk.cpp        2014-10-22 12:27:44 UTC (rev 175045)
+++ trunk/Source/WebKit2/Shared/gtk/NativeWebKeyboardEventGtk.cpp        2014-10-22 13:00:12 UTC (rev 175046)
</span><span class="lines">@@ -35,11 +35,11 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebKit {
</span><span class="cx"> 
</span><del>-NativeWebKeyboardEvent::NativeWebKeyboardEvent(GdkEvent* event, const WebCore::CompositionResults&amp; compositionResults, GtkInputMethodFilter::EventFakedForComposition faked)
</del><ins>+NativeWebKeyboardEvent::NativeWebKeyboardEvent(GdkEvent* event, const WebCore::CompositionResults&amp; compositionResults, InputMethodFilter::EventFakedForComposition faked)
</ins><span class="cx">     : WebKeyboardEvent(WebEventFactory::createWebKeyboardEvent(event, compositionResults))
</span><span class="cx">     , m_nativeEvent(gdk_event_copy(event))
</span><span class="cx">     , m_compositionResults(compositionResults)
</span><del>-    , m_fakeEventForComposition(faked == GtkInputMethodFilter::EventFaked)
</del><ins>+    , m_fakeEventForComposition(faked == InputMethodFilter::EventFaked)
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIgtkWebKitWebViewBasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp (175045 => 175046)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp        2014-10-22 12:27:44 UTC (rev 175045)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp        2014-10-22 13:00:12 UTC (rev 175046)
</span><span class="lines">@@ -30,6 +30,7 @@
</span><span class="cx"> #include &quot;WebKitWebViewBase.h&quot;
</span><span class="cx"> 
</span><span class="cx"> #include &quot;DrawingAreaProxyImpl.h&quot;
</span><ins>+#include &quot;InputMethodFilter.h&quot;
</ins><span class="cx"> #include &quot;NativeWebMouseEvent.h&quot;
</span><span class="cx"> #include &quot;NativeWebWheelEvent.h&quot;
</span><span class="cx"> #include &quot;PageClientImpl.h&quot;
</span><span class="lines">@@ -46,7 +47,6 @@
</span><span class="cx"> #include &quot;WebPageProxy.h&quot;
</span><span class="cx"> #include &quot;WebPreferences.h&quot;
</span><span class="cx"> #include &quot;WebUserContentControllerProxy.h&quot;
</span><del>-#include &quot;WebViewBaseInputMethodFilter.h&quot;
</del><span class="cx"> #include &lt;WebCore/CairoUtilities.h&gt;
</span><span class="cx"> #include &lt;WebCore/GUniquePtrGtk.h&gt;
</span><span class="cx"> #include &lt;WebCore/GtkClickCounter.h&gt;
</span><span class="lines">@@ -107,7 +107,7 @@
</span><span class="cx">     unsigned inspectorViewSize;
</span><span class="cx">     GUniquePtr&lt;GdkEvent&gt; contextMenuEvent;
</span><span class="cx">     WebContextMenuProxyGtk* activeContextMenuProxy;
</span><del>-    WebViewBaseInputMethodFilter inputMethodFilter;
</del><ins>+    InputMethodFilter inputMethodFilter;
</ins><span class="cx">     TouchEventsMap touchEvents;
</span><span class="cx"> 
</span><span class="cx">     GtkWindow* toplevelOnScreenWindow;
</span><span class="lines">@@ -299,11 +299,21 @@
</span><span class="cx">     gtk_style_context_set_background(gtk_widget_get_style_context(widget), window);
</span><span class="cx"> 
</span><span class="cx">     WebKitWebViewBase* webView = WEBKIT_WEB_VIEW_BASE(widget);
</span><ins>+    gtk_im_context_set_client_window(webView-&gt;priv-&gt;inputMethodFilter.context(), window);
+
</ins><span class="cx">     GtkWidget* toplevel = gtk_widget_get_toplevel(widget);
</span><span class="cx">     if (widgetIsOnscreenToplevelWindow(toplevel))
</span><span class="cx">         webkitWebViewBaseSetToplevelOnScreenWindow(webView, GTK_WINDOW(toplevel));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static void webkitWebViewBaseUnrealize(GtkWidget* widget)
+{
+    WebKitWebViewBase* webView = WEBKIT_WEB_VIEW_BASE(widget);
+    gtk_im_context_set_client_window(webView-&gt;priv-&gt;inputMethodFilter.context(), nullptr);
+
+    GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)-&gt;unrealize(widget);
+}
+
</ins><span class="cx"> static bool webkitWebViewChildIsInternalWidget(WebKitWebViewBase* webViewBase, GtkWidget* widget)
</span><span class="cx"> {
</span><span class="cx">     WebKitWebViewBasePrivate* priv = webViewBase-&gt;priv;
</span><span class="lines">@@ -965,6 +975,7 @@
</span><span class="cx"> {
</span><span class="cx">     GtkWidgetClass* widgetClass = GTK_WIDGET_CLASS(webkitWebViewBaseClass);
</span><span class="cx">     widgetClass-&gt;realize = webkitWebViewBaseRealize;
</span><ins>+    widgetClass-&gt;unrealize = webkitWebViewBaseUnrealize;
</ins><span class="cx">     widgetClass-&gt;draw = webkitWebViewBaseDraw;
</span><span class="cx">     widgetClass-&gt;size_allocate = webkitWebViewBaseSizeAllocate;
</span><span class="cx">     widgetClass-&gt;map = webkitWebViewBaseMap;
</span><span class="lines">@@ -1050,6 +1061,8 @@
</span><span class="cx">     priv-&gt;pageProxy = context-&gt;createWebPage(*priv-&gt;pageClient, WTF::move(webPageConfiguration));
</span><span class="cx">     priv-&gt;pageProxy-&gt;initializeWebPage();
</span><span class="cx"> 
</span><ins>+    priv-&gt;inputMethodFilter.setPage(priv-&gt;pageProxy.get());
+
</ins><span class="cx"> #if USE(TEXTURE_MAPPER_GL) &amp;&amp; PLATFORM(X11)
</span><span class="cx">     if (priv-&gt;redirectedWindow)
</span><span class="cx">         priv-&gt;pageProxy-&gt;setAcceleratedCompositingWindowId(priv-&gt;redirectedWindow-&gt;windowId());
</span><span class="lines">@@ -1062,10 +1075,6 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     webkitWebViewBaseUpdatePreferences(webkitWebViewBase);
</span><del>-
-    // This must happen here instead of the instance initializer, because the input method
-    // filter must have access to the page.
-    priv-&gt;inputMethodFilter.setWebView(webkitWebViewBase);
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void webkitWebViewBaseSetTooltipText(WebKitWebViewBase* webViewBase, const char* tooltip)
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIgtkWebViewBaseInputMethodFiltercpp"></a>
<div class="delfile"><h4>Deleted: trunk/Source/WebKit2/UIProcess/API/gtk/WebViewBaseInputMethodFilter.cpp (175045 => 175046)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/gtk/WebViewBaseInputMethodFilter.cpp        2014-10-22 12:27:44 UTC (rev 175045)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/WebViewBaseInputMethodFilter.cpp        2014-10-22 13:00:12 UTC (rev 175046)
</span><span class="lines">@@ -1,95 +0,0 @@
</span><del>-/*
- * Copyright (C) 2012 Igalia S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include &quot;config.h&quot;
-#include &quot;WebViewBaseInputMethodFilter.h&quot;
-
-#include &quot;NativeWebKeyboardEvent.h&quot;
-#include &quot;WebKitWebViewBasePrivate.h&quot;
-#include &quot;WebPageProxy.h&quot;
-#include &lt;WebCore/Color.h&gt;
-#include &lt;WebCore/CompositionResults.h&gt;
-#include &lt;WebCore/Editor.h&gt;
-
-using namespace WebCore;
-
-namespace WebKit {
-
-void WebViewBaseInputMethodFilter::setWebView(WebKitWebViewBase* webView)
-{
-    GtkInputMethodFilter::setWidget(GTK_WIDGET(webView));
-
-    m_webPageProxy = webkitWebViewBaseGetPage(webView);
-    ASSERT(m_webPageProxy);
-}
-
-bool WebViewBaseInputMethodFilter::canEdit()
-{
-    return true;
-}
-
-bool WebViewBaseInputMethodFilter::sendSimpleKeyEvent(GdkEventKey* event, WTF::String simpleString, EventFakedForComposition faked)
-{
-    ASSERT(m_webPageProxy);
-    m_webPageProxy-&gt;handleKeyboardEvent(NativeWebKeyboardEvent(reinterpret_cast&lt;GdkEvent*&gt;(event),
-                                       CompositionResults(simpleString), faked));
-    return true;
-}
-
-bool WebViewBaseInputMethodFilter::sendKeyEventWithCompositionResults(GdkEventKey* event, ResultsToSend resultsToSend, EventFakedForComposition faked)
-{
-    ASSERT(m_webPageProxy);
-    m_webPageProxy-&gt;handleKeyboardEvent(NativeWebKeyboardEvent(reinterpret_cast&lt;GdkEvent*&gt;(event),
-                                        CompositionResults(CompositionResults::WillSendCompositionResultsSoon),
-                                        faked));
-
-    if (resultsToSend &amp; Composition &amp;&amp; !m_confirmedComposition.isNull())
-        confirmCompositionText(m_confirmedComposition);
-    if (resultsToSend &amp; Preedit &amp;&amp; !m_preedit.isNull())
-        setPreedit(m_preedit, m_cursorOffset);
-    return true;
-}
-
-void WebViewBaseInputMethodFilter::confirmCompositionText(String text)
-{
-    ASSERT(m_webPageProxy);
-    m_webPageProxy-&gt;confirmComposition(text, -1, 0);
-}
-
-void WebViewBaseInputMethodFilter::confirmCurrentComposition()
-{
-    ASSERT(m_webPageProxy);
-    m_webPageProxy-&gt;confirmComposition(String(), -1, 0);
-}
-
-void WebViewBaseInputMethodFilter::cancelCurrentComposition()
-{
-    ASSERT(m_webPageProxy);
-    m_webPageProxy-&gt;cancelComposition();
-}
-
-void WebViewBaseInputMethodFilter::setPreedit(String newPreedit, int /* cursorOffset */)
-{
-    // TODO: We should parse the PangoAttrList that we get from the IM context here.
-    ASSERT(m_webPageProxy);
-    m_webPageProxy-&gt;setComposition(newPreedit, Vector&lt;CompositionUnderline&gt;{ CompositionUnderline(0, newPreedit.length(), Color(1, 1, 1), false) },
-        m_cursorOffset, m_cursorOffset, 0 /* replacement start */, 0 /* replacement end */);
-}
-
-} // namespace WebKit
</del></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIgtkWebViewBaseInputMethodFilterh"></a>
<div class="delfile"><h4>Deleted: trunk/Source/WebKit2/UIProcess/API/gtk/WebViewBaseInputMethodFilter.h (175045 => 175046)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/gtk/WebViewBaseInputMethodFilter.h        2014-10-22 12:27:44 UTC (rev 175045)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/WebViewBaseInputMethodFilter.h        2014-10-22 13:00:12 UTC (rev 175046)
</span><span class="lines">@@ -1,49 +0,0 @@
</span><del>-/*
- * Copyright (C) 2012 Igalia S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef WebViewBaseInputMethodFilter_h
-#define WebViewBaseInputMethodFilter_h
-
-#include &quot;GtkInputMethodFilter.h&quot;
-#include &quot;WebPageProxy.h&quot;
-
-typedef struct _WebKitWebViewBase WebKitWebViewBase;
-
-namespace WebKit {
-
-class WebViewBaseInputMethodFilter : public WebCore::GtkInputMethodFilter {
-public:
-    void setWebView(WebKitWebViewBase*);
-
-protected:
-    virtual bool sendSimpleKeyEvent(GdkEventKey*, WTF::String eventString, EventFakedForComposition);
-    virtual bool sendKeyEventWithCompositionResults(GdkEventKey*, ResultsToSend, EventFakedForComposition);
-    virtual bool canEdit();
-    virtual void confirmCompositionText(String);
-    virtual void confirmCurrentComposition();
-    virtual void cancelCurrentComposition();
-    virtual void setPreedit(String, int cursorOffset);
-
-private:
-    WebPageProxy* m_webPageProxy;
-};
-
-} // namespace WebKit
-
-#endif // WebViewBaseInputMethodFilter_h
</del></span></pre></div>
<a id="trunkSourceWebKit2UIProcessgtkInputMethodFiltercpp"></a>
<div class="addfile"><h4>Added: trunk/Source/WebKit2/UIProcess/gtk/InputMethodFilter.cpp (0 => 175046)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/gtk/InputMethodFilter.cpp                                (rev 0)
+++ trunk/Source/WebKit2/UIProcess/gtk/InputMethodFilter.cpp        2014-10-22 13:00:12 UTC (rev 175046)
</span><span class="lines">@@ -0,0 +1,441 @@
</span><ins>+/*
+ * Copyright (C) 2012, 2014 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include &quot;config.h&quot;
+#include &quot;InputMethodFilter.h&quot;
+
+#include &quot;NativeWebKeyboardEvent.h&quot;
+#include &quot;WebPageProxy.h&quot;
+#include &lt;WebCore/Color.h&gt;
+#include &lt;WebCore/CompositionResults.h&gt;
+#include &lt;WebCore/Editor.h&gt;
+#include &lt;WebCore/GUniquePtrGtk.h&gt;
+#include &lt;WebCore/IntRect.h&gt;
+#include &lt;gdk/gdkkeysyms.h&gt;
+#include &lt;gtk/gtk.h&gt;
+#include &lt;wtf/Vector.h&gt;
+#include &lt;wtf/gobject/GUniquePtr.h&gt;
+
+using namespace WebCore;
+
+namespace WebKit {
+
+void InputMethodFilter::handleCommitCallback(InputMethodFilter* filter, const char* compositionString)
+{
+    filter-&gt;handleCommit(compositionString);
+}
+
+void InputMethodFilter::handlePreeditStartCallback(InputMethodFilter* filter)
+{
+    filter-&gt;handlePreeditStart();
+}
+
+void InputMethodFilter::handlePreeditChangedCallback(InputMethodFilter* filter)
+{
+    filter-&gt;handlePreeditChanged();
+}
+
+void InputMethodFilter::handlePreeditEndCallback(InputMethodFilter* filter)
+{
+    filter-&gt;handlePreeditEnd();
+}
+
+InputMethodFilter::InputMethodFilter()
+    : m_context(adoptGRef(gtk_im_multicontext_new()))
+    , m_page(nullptr)
+    , m_enabled(false)
+    , m_composingTextCurrently(false)
+    , m_filteringKeyEvent(false)
+    , m_preeditChanged(false)
+    , m_preventNextCommit(false)
+    , m_justSentFakeKeyUp(false)
+    , m_cursorOffset(0)
+    , m_lastFilteredKeyPressCodeWithNoResults(GDK_KEY_VoidSymbol)
+#if ENABLE(API_TESTS)
+    , m_testingMode(false)
+#endif
+{
+    g_signal_connect_swapped(m_context.get(), &quot;commit&quot;, G_CALLBACK(handleCommitCallback), this);
+    g_signal_connect_swapped(m_context.get(), &quot;preedit-start&quot;, G_CALLBACK(handlePreeditStartCallback), this);
+    g_signal_connect_swapped(m_context.get(), &quot;preedit-changed&quot;, G_CALLBACK(handlePreeditChangedCallback), this);
+    g_signal_connect_swapped(m_context.get(), &quot;preedit-end&quot;, G_CALLBACK(handlePreeditEndCallback), this);
+}
+
+InputMethodFilter::~InputMethodFilter()
+{
+    g_signal_handlers_disconnect_matched(m_context.get(), G_SIGNAL_MATCH_DATA, 0, 0, nullptr, nullptr, this);
+}
+
+void InputMethodFilter::setEnabled(bool enabled)
+{
+    ASSERT(m_page);
+
+    m_enabled = enabled;
+    if (enabled)
+        gtk_im_context_focus_in(m_context.get());
+    else
+        gtk_im_context_focus_out(m_context.get());
+}
+
+void InputMethodFilter::setCursorRect(const IntRect&amp; cursorRect)
+{
+    ASSERT(m_page);
+    // Don't move the window unless the cursor actually moves more than 10
+    // pixels. This prevents us from making the window flash during minor
+    // cursor adjustments.
+    static const int windowMovementThreshold = 10 * 10;
+    if (cursorRect.location().distanceSquaredToPoint(m_lastCareLocation) &lt; windowMovementThreshold)
+        return;
+
+    m_lastCareLocation = cursorRect.location();
+    IntRect translatedRect = cursorRect;
+
+    ASSERT(m_widget);
+    GtkAllocation allocation;
+    gtk_widget_get_allocation(m_page-&gt;viewWidget(), &amp;allocation);
+    translatedRect.move(allocation.x, allocation.y);
+
+    GdkRectangle gdkCursorRect = translatedRect;
+    gtk_im_context_set_cursor_location(m_context.get(), &amp;gdkCursorRect);
+}
+
+void InputMethodFilter::handleKeyboardEvent(GdkEventKey* event, const String&amp; simpleString, EventFakedForComposition faked)
+{
+#if ENABLE(API_TESTS)
+    if (m_testingMode) {
+        logHandleKeyboardEventForTesting(event, simpleString, faked);
+        return;
+    }
+#endif
+    m_page-&gt;handleKeyboardEvent(NativeWebKeyboardEvent(reinterpret_cast&lt;GdkEvent*&gt;(event), CompositionResults(simpleString), faked));
+}
+
+void InputMethodFilter::handleKeyboardEventWithCompositionResults(GdkEventKey* event, ResultsToSend resultsToSend, EventFakedForComposition faked)
+{
+#if ENABLE(API_TESTS)
+    if (m_testingMode) {
+        logHandleKeyboardEventWithCompositionResultsForTesting(event, resultsToSend, faked);
+        return;
+    }
+#endif
+    m_page-&gt;handleKeyboardEvent(NativeWebKeyboardEvent(reinterpret_cast&lt;GdkEvent*&gt;(event), CompositionResults(CompositionResults::WillSendCompositionResultsSoon), faked));
+
+    if (resultsToSend &amp; Composition &amp;&amp; !m_confirmedComposition.isNull())
+        m_page-&gt;confirmComposition(m_confirmedComposition, -1, 0);
+
+    if (resultsToSend &amp; Preedit &amp;&amp; !m_preedit.isNull()) {
+        m_page-&gt;setComposition(m_preedit, Vector&lt;CompositionUnderline&gt;{ CompositionUnderline(0, m_preedit.length(), Color(1, 1, 1), false) },
+            m_cursorOffset, m_cursorOffset, 0 /* replacement start */, 0 /* replacement end */);
+    }
+}
+
+void InputMethodFilter::filterKeyEvent(GdkEventKey* event)
+{
+#if ENABLE(API_TESTS)
+    ASSERT(m_page || m_testingMode);
+#else
+    ASSERT(m_page);
+#endif
+    if (!m_enabled) {
+        handleKeyboardEvent(event);
+        return;
+    }
+
+    m_preeditChanged = false;
+    m_filteringKeyEvent = true;
+
+    unsigned lastFilteredKeyPressCodeWithNoResults = m_lastFilteredKeyPressCodeWithNoResults;
+    m_lastFilteredKeyPressCodeWithNoResults = GDK_KEY_VoidSymbol;
+
+    bool filtered = gtk_im_context_filter_keypress(m_context.get(), event);
+    m_filteringKeyEvent = false;
+
+    bool justSentFakeKeyUp = m_justSentFakeKeyUp;
+    m_justSentFakeKeyUp = false;
+    if (justSentFakeKeyUp &amp;&amp; event-&gt;type == GDK_KEY_RELEASE)
+        return;
+
+    // Simple input methods work such that even normal keystrokes fire the
+    // commit signal. We detect those situations and treat them as normal
+    // key events, supplying the commit string as the key character.
+    if (filtered &amp;&amp; !m_composingTextCurrently &amp;&amp; !m_preeditChanged &amp;&amp; m_confirmedComposition.length() == 1) {
+        handleKeyboardEvent(event, m_confirmedComposition);
+        m_confirmedComposition = String();
+        return;
+    }
+
+    if (filtered &amp;&amp; event-&gt;type == GDK_KEY_PRESS) {
+        if (!m_preeditChanged &amp;&amp; m_confirmedComposition.isNull()) {
+            m_composingTextCurrently = true;
+            m_lastFilteredKeyPressCodeWithNoResults = event-&gt;keyval;
+            return;
+        }
+
+        handleKeyboardEventWithCompositionResults(event);
+        if (!m_confirmedComposition.isEmpty()) {
+            m_composingTextCurrently = false;
+            m_confirmedComposition = String();
+        }
+        return;
+    }
+
+    // If we previously filtered a key press event and it yielded no results. Suppress
+    // the corresponding key release event to avoid confusing the web content.
+    if (event-&gt;type == GDK_KEY_RELEASE &amp;&amp; lastFilteredKeyPressCodeWithNoResults == event-&gt;keyval)
+        return;
+
+    // At this point a keystroke was either:
+    // 1. Unfiltered
+    // 2. A filtered keyup event. As the IME code in EditorClient.h doesn't
+    //    ever look at keyup events, we send any composition results before
+    //    the key event.
+    // Both might have composition results or not.
+    //
+    // It's important to send the composition results before the event
+    // because some IM modules operate that way. For example (taken from
+    // the Chromium source), the latin-post input method gives this sequence
+    // when you press 'a' and then backspace:
+    //  1. keydown 'a' (filtered)
+    //  2. preedit changed to &quot;a&quot;
+    //  3. keyup 'a' (unfiltered)
+    //  4. keydown Backspace (unfiltered)
+    //  5. commit &quot;a&quot;
+    //  6. preedit end
+    if (!m_confirmedComposition.isEmpty())
+        confirmComposition();
+    if (m_preeditChanged)
+        updatePreedit();
+    handleKeyboardEvent(event);
+}
+
+void InputMethodFilter::confirmComposition()
+{
+#if ENABLE(API_TESTS)
+    if (m_testingMode) {
+        logConfirmCompositionForTesting();
+        m_confirmedComposition = String();
+        return;
+    }
+#endif
+    m_page-&gt;confirmComposition(m_confirmedComposition, -1, 0);
+    m_confirmedComposition = String();
+}
+
+void InputMethodFilter::updatePreedit()
+{
+#if ENABLE(API_TESTS)
+    if (m_testingMode) {
+        logSetPreeditForTesting();
+        return;
+    }
+#endif
+    // FIXME: We should parse the PangoAttrList that we get from the IM context here.
+    m_page-&gt;setComposition(m_preedit, Vector&lt;CompositionUnderline&gt;{ CompositionUnderline(0, m_preedit.length(), Color(1, 1, 1), false) },
+        m_cursorOffset, m_cursorOffset, 0 /* replacement start */, 0 /* replacement end */);
+    m_preeditChanged = false;
+}
+
+void InputMethodFilter::notifyFocusedIn()
+{
+#if ENABLE(API_TESTS)
+    ASSERT(m_page || m_testingMode);
+#else
+    ASSERT(m_page);
+#endif
+    m_enabled = true;
+    gtk_im_context_focus_in(m_context.get());
+}
+
+void InputMethodFilter::notifyFocusedOut()
+{
+#if ENABLE(API_TESTS)
+    ASSERT(m_page || m_testingMode);
+#else
+    ASSERT(m_page);
+#endif
+    if (!m_enabled)
+        return;
+
+    confirmCurrentComposition();
+    cancelContextComposition();
+    gtk_im_context_focus_out(m_context.get());
+    m_enabled = false;
+}
+
+void InputMethodFilter::notifyMouseButtonPress()
+{
+#if ENABLE(API_TESTS)
+    ASSERT(m_page || m_testingMode);
+#else
+    ASSERT(m_page);
+#endif
+
+    // Confirming the composition may trigger a selection change, which
+    // might trigger further unwanted actions on the context, so we prevent
+    // that by setting m_composingTextCurrently to false.
+    confirmCurrentComposition();
+    cancelContextComposition();
+}
+
+void InputMethodFilter::confirmCurrentComposition()
+{
+    if (!m_composingTextCurrently)
+        return;
+    m_page-&gt;confirmComposition(String(), -1, 0);
+    m_composingTextCurrently = false;
+}
+
+void InputMethodFilter::cancelContextComposition()
+{
+    m_preventNextCommit = !m_preedit.isEmpty();
+
+    gtk_im_context_reset(m_context.get());
+
+    m_composingTextCurrently = false;
+    m_justSentFakeKeyUp = false;
+    m_preedit = String();
+    m_confirmedComposition = String();
+}
+
+void InputMethodFilter::sendCompositionAndPreeditWithFakeKeyEvents(ResultsToSend resultsToSend)
+{
+    // The Windows composition key event code is 299 or VK_PROCESSKEY. We need to
+    // emit this code for web compatibility reasons when key events trigger
+    // composition results. GDK doesn't have an equivalent, so we send VoidSymbol
+    // here to WebCore. PlatformKeyEvent knows to convert this code into
+    // VK_PROCESSKEY.
+    static const int compositionEventKeyCode = GDK_KEY_VoidSymbol;
+
+    GUniquePtr&lt;GdkEvent&gt; event(gdk_event_new(GDK_KEY_PRESS));
+    event-&gt;key.time = GDK_CURRENT_TIME;
+    event-&gt;key.keyval = compositionEventKeyCode;
+    handleKeyboardEventWithCompositionResults(&amp;event-&gt;key, resultsToSend, EventFaked);
+
+    m_confirmedComposition = String();
+    if (resultsToSend &amp; Composition)
+        m_composingTextCurrently = false;
+
+    event-&gt;type = GDK_KEY_RELEASE;
+    handleKeyboardEvent(&amp;event-&gt;key, String(), EventFaked);
+    m_justSentFakeKeyUp = true;
+}
+
+void InputMethodFilter::handleCommit(const char* compositionString)
+{
+    if (m_preventNextCommit) {
+        m_preventNextCommit = false;
+        return;
+    }
+
+    if (!m_enabled)
+        return;
+
+    m_confirmedComposition.append(String::fromUTF8(compositionString));
+
+    // If the commit was triggered outside of a key event, just send
+    // the IME event now. If we are handling a key event, we'll decide
+    // later how to handle this.
+    if (!m_filteringKeyEvent)
+        sendCompositionAndPreeditWithFakeKeyEvents(Composition);
+}
+
+void InputMethodFilter::handlePreeditStart()
+{
+    if (m_preventNextCommit || !m_enabled)
+        return;
+    m_preeditChanged = true;
+    m_preedit = emptyString();
+}
+
+void InputMethodFilter::handlePreeditChanged()
+{
+    if (!m_enabled)
+        return;
+
+    GUniqueOutPtr&lt;gchar&gt; newPreedit;
+    gtk_im_context_get_preedit_string(m_context.get(), &amp;newPreedit.outPtr(), nullptr, &amp;m_cursorOffset);
+
+    if (m_preventNextCommit) {
+        if (strlen(newPreedit.get()) &gt; 0)
+            m_preventNextCommit = false;
+        else
+            return;
+    }
+
+    m_preedit = String::fromUTF8(newPreedit.get());
+    m_cursorOffset = std::min(std::max(m_cursorOffset, 0), static_cast&lt;int&gt;(m_preedit.length()));
+
+    m_composingTextCurrently = !m_preedit.isEmpty();
+    m_preeditChanged = true;
+
+    if (!m_filteringKeyEvent)
+        sendCompositionAndPreeditWithFakeKeyEvents(Preedit);
+}
+
+void InputMethodFilter::handlePreeditEnd()
+{
+    if (m_preventNextCommit || !m_enabled)
+        return;
+
+    m_preedit = String();
+    m_cursorOffset = 0;
+    m_preeditChanged = true;
+
+    if (!m_filteringKeyEvent)
+        updatePreedit();
+}
+
+#if ENABLE(API_TESTS)
+void InputMethodFilter::logHandleKeyboardEventForTesting(GdkEventKey* event, const String&amp; eventString, EventFakedForComposition faked)
+{
+    const char* eventType = event-&gt;type == GDK_KEY_RELEASE ? &quot;release&quot; : &quot;press&quot;;
+    const char* fakedString = faked == EventFaked ? &quot; (faked)&quot; : &quot;&quot;;
+    if (!eventString.isNull())
+        m_events.append(String::format(&quot;sendSimpleKeyEvent type=%s keycode=%x text='%s'%s&quot;, eventType, event-&gt;keyval, eventString.utf8().data(), fakedString));
+    else
+        m_events.append(String::format(&quot;sendSimpleKeyEvent type=%s keycode=%x%s&quot;, eventType, event-&gt;keyval, fakedString));
+}
+
+void InputMethodFilter::logHandleKeyboardEventWithCompositionResultsForTesting(GdkEventKey* event, ResultsToSend resultsToSend, EventFakedForComposition faked)
+{
+    const char* eventType = event-&gt;type == GDK_KEY_RELEASE ? &quot;release&quot; : &quot;press&quot;;
+    const char* fakedString = faked == EventFaked ? &quot; (faked)&quot; : &quot;&quot;;
+    m_events.append(String::format(&quot;sendKeyEventWithCompositionResults type=%s keycode=%u%s&quot;, eventType, event-&gt;keyval, fakedString));
+
+    if (resultsToSend &amp; Composition &amp;&amp; !m_confirmedComposition.isNull())
+        logConfirmCompositionForTesting();
+    if (resultsToSend &amp; Preedit &amp;&amp; !m_preedit.isNull())
+        logSetPreeditForTesting();
+}
+
+void InputMethodFilter::logConfirmCompositionForTesting()
+{
+    if (m_confirmedComposition.isEmpty())
+        m_events.append(String(&quot;confirmCurrentcomposition&quot;));
+    else
+        m_events.append(String::format(&quot;confirmComposition '%s'&quot;, m_confirmedComposition.utf8().data()));
+}
+
+void InputMethodFilter::logSetPreeditForTesting()
+{
+    m_events.append(String::format(&quot;setPreedit text='%s' cursorOffset=%i&quot;, m_preedit.utf8().data(), m_cursorOffset));
+}
+#endif // ENABLE(API_TESTS)
+
+} // namespace WebKit
</ins></span></pre></div>
<a id="trunkSourceWebKit2UIProcessgtkInputMethodFilterh"></a>
<div class="addfile"><h4>Added: trunk/Source/WebKit2/UIProcess/gtk/InputMethodFilter.h (0 => 175046)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/gtk/InputMethodFilter.h                                (rev 0)
+++ trunk/Source/WebKit2/UIProcess/gtk/InputMethodFilter.h        2014-10-22 13:00:12 UTC (rev 175046)
</span><span class="lines">@@ -0,0 +1,122 @@
</span><ins>+/*
+ * Copyright (C) 2012, 2014 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef InputMethodFilter_h
+#define InputMethodFilter_h
+
+#include &lt;WebCore/IntPoint.h&gt;
+#include &lt;wtf/Noncopyable.h&gt;
+#include &lt;wtf/gobject/GRefPtr.h&gt;
+#include &lt;wtf/text/WTFString.h&gt;
+
+typedef struct _GdkEventKey GdkEventKey;
+typedef struct _GtkIMContext GtkIMContext;
+
+namespace WebCore {
+class IntRect;
+}
+
+namespace WebKit {
+
+class WebPageProxy;
+
+class InputMethodFilter {
+    WTF_MAKE_NONCOPYABLE(InputMethodFilter);
+public:
+    enum EventFakedForComposition {
+        EventFaked,
+        EventNotFaked
+    };
+
+    InputMethodFilter();
+    ~InputMethodFilter();
+
+    GtkIMContext* context() const { return m_context.get(); }
+
+    void setPage(WebPageProxy* page) { m_page = page; }
+
+    void setEnabled(bool);
+    void setCursorRect(const WebCore::IntRect&amp;);
+
+    void filterKeyEvent(GdkEventKey*);
+    void notifyFocusedIn();
+    void notifyFocusedOut();
+    void notifyMouseButtonPress();
+
+#if ENABLE(API_TESTS)
+    void setTestingMode(bool enable) { m_testingMode = enable; }
+    const Vector&lt;String&gt;&amp; events() const { return m_events; }
+#endif
+
+private:
+    enum ResultsToSend {
+        Preedit = 1 &lt;&lt; 1,
+        Composition = 1 &lt;&lt; 2,
+        PreeditAndComposition = Preedit | Composition
+    };
+
+    static void handleCommitCallback(InputMethodFilter*, const char* compositionString);
+    static void handlePreeditStartCallback(InputMethodFilter*);
+    static void handlePreeditChangedCallback(InputMethodFilter*);
+    static void handlePreeditEndCallback(InputMethodFilter*);
+
+    void handleCommit(const char* compositionString);
+    void handlePreeditChanged();
+    void handlePreeditStart();
+    void handlePreeditEnd();
+
+    void handleKeyboardEvent(GdkEventKey*, const String&amp; eventString = String(), EventFakedForComposition = EventNotFaked);
+    void handleKeyboardEventWithCompositionResults(GdkEventKey*, ResultsToSend = PreeditAndComposition, EventFakedForComposition = EventNotFaked);
+
+    void sendCompositionAndPreeditWithFakeKeyEvents(ResultsToSend);
+    void confirmComposition();
+    void updatePreedit();
+    void confirmCurrentComposition();
+    void cancelContextComposition();
+
+#if ENABLE(API_TESTS)
+    void logHandleKeyboardEventForTesting(GdkEventKey*, const String&amp;, EventFakedForComposition);
+    void logHandleKeyboardEventWithCompositionResultsForTesting(GdkEventKey*, ResultsToSend, EventFakedForComposition);
+    void logConfirmCompositionForTesting();
+    void logSetPreeditForTesting();
+#endif
+
+    GRefPtr&lt;GtkIMContext&gt; m_context;
+    WebPageProxy* m_page;
+    unsigned m_enabled : 1;
+    unsigned m_composingTextCurrently : 1;
+    unsigned m_filteringKeyEvent : 1;
+    unsigned m_preeditChanged : 1;
+    unsigned m_preventNextCommit : 1;
+    unsigned m_justSentFakeKeyUp : 1;
+    int m_cursorOffset;
+    unsigned m_lastFilteredKeyPressCodeWithNoResults;
+    WebCore::IntPoint m_lastCareLocation;
+    String m_confirmedComposition;
+    String m_preedit;
+
+#if ENABLE(API_TESTS)
+    bool m_testingMode;
+    Vector&lt;String&gt; m_events;
+#endif
+};
+
+} // namespace WebKit
+
+#endif // InputMethodFilter_h
</ins></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (175045 => 175046)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog        2014-10-22 12:27:44 UTC (rev 175045)
+++ trunk/Tools/ChangeLog        2014-10-22 13:00:12 UTC (rev 175046)
</span><span class="lines">@@ -1,3 +1,26 @@
</span><ins>+2014-10-22  Carlos Garcia Campos  &lt;cgarcia@igalia.com&gt;
+
+        [GTK] Move GtkInputMethodFilter from Platform to WebKit2
+        https://bugs.webkit.org/show_bug.cgi?id=137884
+
+        Reviewed by Gustavo Noronha Silva.
+
+        Move InputMethodFilter test from WebCore tests to WebKit2 tests
+        and adapt it to use the new InputMethodFilter WebKit class. Instead
+        of having virtual methods just for testing, it has a testing mode
+        that logs the events.
+
+        * TestWebKitAPI/PlatformGTK.cmake:
+        * TestWebKitAPI/Tests/WebKit2/gtk/InputMethodFilter.cpp: Renamed from Tools/TestWebKitAPI/Tests/WebCore/gtk/InputMethodFilter.cpp.
+        (TestWebKitAPI::TestInputMethodFilter::TestInputMethodFilter):
+        (TestWebKitAPI::TestInputMethodFilter::~TestInputMethodFilter):
+        (TestWebKitAPI::TestInputMethodFilter::sendKeyEventToFilter):
+        (TestWebKitAPI::TestInputMethodFilter::sendPressAndReleaseKeyEventPairToFilter):
+        (TestWebKitAPI::TEST):
+        (TestWebKitAPI::temporaryGetPreeditStringOverride):
+        (TestWebKitAPI::temporaryResetOverride):
+        (TestWebKitAPI::verifyCanceledComposition):
+
</ins><span class="cx"> 2014-10-21  Alexey Proskuryakov  &lt;ap@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         build.webkit.org/dashboard: Cannot click on green tester bubbles
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPIPlatformGTKcmake"></a>
<div class="modfile"><h4>Modified: trunk/Tools/TestWebKitAPI/PlatformGTK.cmake (175045 => 175046)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/PlatformGTK.cmake        2014-10-22 12:27:44 UTC (rev 175045)
+++ trunk/Tools/TestWebKitAPI/PlatformGTK.cmake        2014-10-22 13:00:12 UTC (rev 175046)
</span><span class="lines">@@ -98,6 +98,7 @@
</span><span class="cx">     ${TESTWEBKITAPI_DIR}/Tests/WebKit2/WKString.cpp
</span><span class="cx">     ${TESTWEBKITAPI_DIR}/Tests/WebKit2/WKStringJSString.cpp
</span><span class="cx">     ${TESTWEBKITAPI_DIR}/Tests/WebKit2/WKURL.cpp
</span><ins>+    ${TESTWEBKITAPI_DIR}/Tests/WebKit2/gtk/InputMethodFilter.cpp
</ins><span class="cx"> )
</span><span class="cx"> 
</span><span class="cx"> target_link_libraries(TestWebKit2 ${test_webkit2_api_LIBRARIES})
</span><span class="lines">@@ -106,12 +107,6 @@
</span><span class="cx"> set_target_properties(TestWebKit2 PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${TESTWEBKITAPI_RUNTIME_OUTPUT_DIRECTORY}/WebKit2)
</span><span class="cx"> 
</span><span class="cx"> set(TestWebCoreGtk_SOURCES
</span><del>-    ${WEBCORE_DIR}/platform/graphics/IntPoint.cpp
-    ${WEBCORE_DIR}/platform/graphics/IntRect.cpp
-    ${WEBCORE_DIR}/platform/graphics/IntSize.cpp
-    ${WEBCORE_DIR}/platform/graphics/cairo/IntRectCairo.cpp
-    ${WEBCORE_DIR}/platform/gtk/GtkInputMethodFilter.cpp
-    ${TESTWEBKITAPI_DIR}/Tests/WebCore/gtk/InputMethodFilter.cpp
</del><span class="cx">     ${TESTWEBKITAPI_DIR}/Tests/WebCore/gtk/UserAgentQuirks.cpp
</span><span class="cx"> )
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPITestsWebCoregtkInputMethodFiltercpp"></a>
<div class="delfile"><h4>Deleted: trunk/Tools/TestWebKitAPI/Tests/WebCore/gtk/InputMethodFilter.cpp (175045 => 175046)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/Tests/WebCore/gtk/InputMethodFilter.cpp        2014-10-22 12:27:44 UTC (rev 175045)
+++ trunk/Tools/TestWebKitAPI/Tests/WebCore/gtk/InputMethodFilter.cpp        2014-10-22 13:00:12 UTC (rev 175046)
</span><span class="lines">@@ -1,310 +0,0 @@
</span><del>-/*
- * Copyright (C) 2012 Igalia S.L.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include &quot;config.h&quot;
-
-#include &quot;WTFStringUtilities.h&quot;
-#include &lt;WebCore/GtkInputMethodFilter.h&gt;
-#include &lt;gdk/gdkkeysyms.h&gt;
-#include &lt;gtk/gtk.h&gt;
-#include &lt;wtf/gobject/GUniquePtr.h&gt;
-#include &lt;wtf/gobject/GRefPtr.h&gt;
-#include &lt;wtf/text/CString.h&gt;
-
-using namespace WebCore;
-
-namespace TestWebKitAPI {
-
-class TestInputMethodFilter : public GtkInputMethodFilter {
-public:
-    TestInputMethodFilter()
-        : m_testWindow(gtk_window_new(GTK_WINDOW_POPUP))
-    {
-        gtk_widget_show(m_testWindow.get());
-        setWidget(m_testWindow.get());
-
-        // Focus in is necessary to activate the default input method in the multicontext.
-        notifyFocusedIn();
-    }
-
-    Vector&lt;String&gt;&amp; events() { return m_events; }
-
-    void sendKeyEventToFilter(unsigned gdkKeyValue, GdkEventType type, unsigned modifiers = 0)
-    {
-        GdkEvent* event = gdk_event_new(type);
-        event-&gt;key.keyval = gdkKeyValue;
-        event-&gt;key.state = modifiers;
-        event-&gt;key.window = gtk_widget_get_window(m_testWindow.get());
-        event-&gt;key.time = GDK_CURRENT_TIME;
-        g_object_ref(event-&gt;key.window);
-
-#ifndef GTK_API_VERSION_2
-        gdk_event_set_device(event, gdk_device_manager_get_client_pointer(gdk_display_get_device_manager(gdk_display_get_default())));
-#endif
-
-        GUniqueOutPtr&lt;GdkKeymapKey&gt; keys;
-        gint nKeys;
-        if (gdk_keymap_get_entries_for_keyval(gdk_keymap_get_default(), gdkKeyValue, &amp;keys.outPtr(), &amp;nKeys))
-            event-&gt;key.hardware_keycode = keys.get()[0].keycode;
-
-        filterKeyEvent(&amp;event-&gt;key);
-        gdk_event_free(event);
-    }
-
-    void sendPressAndReleaseKeyEventPairToFilter(unsigned gdkKeyValue, unsigned modifiers = 0)
-    {
-        sendKeyEventToFilter(gdkKeyValue, GDK_KEY_PRESS, modifiers);
-        sendKeyEventToFilter(gdkKeyValue, GDK_KEY_RELEASE, modifiers);
-    }
-
-protected:
-    virtual bool sendSimpleKeyEvent(GdkEventKey* event, WTF::String eventString, EventFakedForComposition faked)
-    {
-        const char* eventType = event-&gt;type == GDK_KEY_RELEASE ? &quot;release&quot; : &quot;press&quot;;
-        const char* fakedString = faked == EventFaked ? &quot; (faked)&quot; : &quot;&quot;;
-        if (!eventString.isNull())
-            m_events.append(String::format(&quot;sendSimpleKeyEvent type=%s keycode=%x text='%s'%s&quot;, eventType, event-&gt;keyval, eventString.utf8().data(), fakedString));
-        else
-            m_events.append(String::format(&quot;sendSimpleKeyEvent type=%s keycode=%x%s&quot;, eventType, event-&gt;keyval, fakedString));
-
-        return true;
-    }
-
-    virtual bool sendKeyEventWithCompositionResults(GdkEventKey* event, ResultsToSend resultsToSend, EventFakedForComposition faked)
-    {
-        const char* eventType = event-&gt;type == GDK_KEY_RELEASE ? &quot;release&quot; : &quot;press&quot;;
-        const char* fakedString = faked == EventFaked ? &quot; (faked)&quot; : &quot;&quot;;
-        m_events.append(String::format(&quot;sendKeyEventWithCompositionResults type=%s keycode=%u%s&quot;, eventType, event-&gt;keyval, fakedString));
-
-        if (resultsToSend &amp; Composition &amp;&amp; !m_confirmedComposition.isNull())
-            confirmCompositionText(m_confirmedComposition);
-        if (resultsToSend &amp; Preedit &amp;&amp; !m_preedit.isNull())
-            setPreedit(m_preedit, m_cursorOffset);
-
-        return true;
-    }
-
-    virtual bool canEdit()
-    {
-        return true;
-    }
-
-    virtual void confirmCompositionText(String text)
-    {
-        m_events.append(String::format(&quot;confirmComposition '%s'&quot;, text.utf8().data()));
-    }
-
-    virtual void confirmCurrentComposition()
-    {
-        m_events.append(String(&quot;confirmCurrentcomposition&quot;));
-    }
-
-    virtual void cancelCurrentComposition()
-    {
-        m_events.append(String(&quot;cancelCurrentComposition&quot;));
-    }
-
-    virtual void setPreedit(String preedit, int cursorOffset)
-    {
-        m_events.append(String::format(&quot;setPreedit text='%s' cursorOffset=%i&quot;, preedit.utf8().data(), cursorOffset));
-    }
-
-private:
-    GRefPtr&lt;GtkWidget&gt; m_testWindow;
-    Vector&lt;String&gt; m_events;
-};
-
-TEST(GTK, GtkInputMethodFilterSimple)
-{
-    TestInputMethodFilter inputMethodFilter;
-    inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_g);
-    inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_t);
-    inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_k);
-
-    const Vector&lt;String&gt;&amp; events = inputMethodFilter.events();
-
-    ASSERT_EQ(6, events.size());
-    ASSERT_EQ(String(&quot;sendSimpleKeyEvent type=press keycode=67 text='g'&quot;), events[0]);
-    ASSERT_EQ(String(&quot;sendSimpleKeyEvent type=release keycode=67&quot;), events[1]);
-    ASSERT_EQ(String(&quot;sendSimpleKeyEvent type=press keycode=74 text='t'&quot;), events[2]);
-    ASSERT_EQ(String(&quot;sendSimpleKeyEvent type=release keycode=74&quot;), events[3]);
-    ASSERT_EQ(String(&quot;sendSimpleKeyEvent type=press keycode=6b text='k'&quot;), events[4]);
-    ASSERT_EQ(String(&quot;sendSimpleKeyEvent type=release keycode=6b&quot;), events[5]);
-}
-
-TEST(GTK, GtkInputMethodFilterUnicodeSequence)
-{
-    TestInputMethodFilter inputMethodFilter;
-
-    // This is simple unicode hex entry of the characters, u, 0, 0, f, 4 pressed with
-    // the shift and controls keys held down. In reality, these values are not typical
-    // of an actual hex entry, because they'd be transformed by the shift modifier according
-    // to the keyboard layout. For instance, on a US keyboard a 0 with the shift key pressed
-    // is a right parenthesis. Using these values prevents having to work out what the
-    // transformed characters are based on the current keyboard layout.
-    inputMethodFilter.sendKeyEventToFilter(GDK_KEY_Control_L, GDK_KEY_PRESS);
-    inputMethodFilter.sendKeyEventToFilter(GDK_KEY_Shift_L, GDK_KEY_PRESS, GDK_CONTROL_MASK);
-
-    inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_U, GDK_SHIFT_MASK | GDK_CONTROL_MASK);
-    inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_0, GDK_SHIFT_MASK | GDK_CONTROL_MASK);
-    inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_0, GDK_SHIFT_MASK | GDK_CONTROL_MASK);
-    inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_F, GDK_SHIFT_MASK | GDK_CONTROL_MASK);
-    inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_4, GDK_SHIFT_MASK | GDK_CONTROL_MASK);
-
-    inputMethodFilter.sendKeyEventToFilter(GDK_KEY_Shift_L, GDK_KEY_RELEASE, GDK_CONTROL_MASK | GDK_SHIFT_MASK);
-    inputMethodFilter.sendKeyEventToFilter(GDK_KEY_Control_L, GDK_KEY_RELEASE, GDK_CONTROL_MASK);
-
-    const Vector&lt;String&gt;&amp; events = inputMethodFilter.events();
-    ASSERT_EQ(21, events.size());
-    ASSERT_EQ(String(&quot;sendSimpleKeyEvent type=press keycode=ffe3&quot;), events[0]);
-    ASSERT_EQ(String(&quot;sendSimpleKeyEvent type=press keycode=ffe1&quot;), events[1]);
-    ASSERT_EQ(String(&quot;sendKeyEventWithCompositionResults type=press keycode=85&quot;), events[2]);
-    ASSERT_EQ(String(&quot;setPreedit text='u' cursorOffset=1&quot;), events[3]);
-    ASSERT_EQ(String(&quot;sendSimpleKeyEvent type=release keycode=55&quot;), events[4]);
-    ASSERT_EQ(String(&quot;sendKeyEventWithCompositionResults type=press keycode=48&quot;), events[5]);
-    ASSERT_EQ(String(&quot;setPreedit text='u0' cursorOffset=2&quot;), events[6]);
-    ASSERT_EQ(String(&quot;sendSimpleKeyEvent type=release keycode=30&quot;), events[7]);
-    ASSERT_EQ(String(&quot;sendKeyEventWithCompositionResults type=press keycode=48&quot;), events[8]);
-    ASSERT_EQ(String(&quot;setPreedit text='u00' cursorOffset=3&quot;), events[9]);
-    ASSERT_EQ(String(&quot;sendSimpleKeyEvent type=release keycode=30&quot;), events[10]);
-    ASSERT_EQ(String(&quot;sendKeyEventWithCompositionResults type=press keycode=70&quot;), events[11]);
-    ASSERT_EQ(String(&quot;setPreedit text='u00F' cursorOffset=4&quot;), events[12]);
-    ASSERT_EQ(String(&quot;sendSimpleKeyEvent type=release keycode=46&quot;), events[13]);
-    ASSERT_EQ(String(&quot;sendKeyEventWithCompositionResults type=press keycode=52&quot;), events[14]);
-    ASSERT_EQ(String(&quot;setPreedit text='u00F4' cursorOffset=5&quot;), events[15]);
-    ASSERT_EQ(String(&quot;sendSimpleKeyEvent type=release keycode=34&quot;), events[16]);
-    ASSERT_EQ(String(&quot;confirmComposition 'ô'&quot;), events[17]);
-    ASSERT_EQ(String(&quot;setPreedit text='' cursorOffset=0&quot;), events[18]);
-    ASSERT_EQ(String(&quot;sendSimpleKeyEvent type=release keycode=ffe1&quot;), events[19]);
-    ASSERT_EQ(String(&quot;sendSimpleKeyEvent type=release keycode=ffe3&quot;), events[20]);
-}
-
-TEST(GTK, GtkInputMethodFilterComposeKey)
-{
-    TestInputMethodFilter inputMethodFilter;
-
-    inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_Multi_key);
-    inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_apostrophe);
-    inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_o);
-
-    const Vector&lt;String&gt;&amp; events = inputMethodFilter.events();
-    ASSERT_EQ(5, events.size());
-    ASSERT_EQ(String(&quot;sendKeyEventWithCompositionResults type=press keycode=39&quot;), events[0]);
-    ASSERT_EQ(String(&quot;setPreedit text='' cursorOffset=0&quot;), events[1]);
-    ASSERT_EQ(String(&quot;sendSimpleKeyEvent type=release keycode=27&quot;), events[2]);
-    ASSERT_EQ(String(&quot;sendSimpleKeyEvent type=press keycode=6f text='ó'&quot;), events[3]);
-    ASSERT_EQ(String(&quot;sendSimpleKeyEvent type=release keycode=6f&quot;), events[4]);
-}
-
-typedef void (*GetPreeditStringCallback) (GtkIMContext*, gchar**, PangoAttrList**, int*);
-static void temporaryGetPreeditStringOverride(GtkIMContext*, char** string, PangoAttrList** attrs, int* cursorPosition)
-{
-    *string = g_strdup(&quot;preedit of doom, bringer of cheese&quot;);
-    *cursorPosition = 3;
-}
-
-TEST(GTK, GtkInputMethodFilterContextEventsWithoutKeyEvents)
-{
-    TestInputMethodFilter inputMethodFilter;
-
-    // This is a bit of a hack to avoid mocking out the entire InputMethodContext, by
-    // simply replacing the get_preedit_string virtual method for the length of this test.
-    GtkIMContext* context = inputMethodFilter.context();
-    GtkIMContextClass* contextClass = GTK_IM_CONTEXT_GET_CLASS(context);
-    GetPreeditStringCallback previousCallback = contextClass-&gt;get_preedit_string;
-    contextClass-&gt;get_preedit_string = temporaryGetPreeditStringOverride;
-
-    g_signal_emit_by_name(context, &quot;preedit-changed&quot;);
-    g_signal_emit_by_name(context, &quot;commit&quot;, &quot;commit text&quot;);
-
-    contextClass-&gt;get_preedit_string = previousCallback;
-
-    const Vector&lt;String&gt;&amp; events = inputMethodFilter.events();
-    ASSERT_EQ(6, events.size());
-    ASSERT_EQ(String(&quot;sendKeyEventWithCompositionResults type=press keycode=16777215 (faked)&quot;), events[0]);
-    ASSERT_EQ(String(&quot;setPreedit text='preedit of doom, bringer of cheese' cursorOffset=3&quot;), events[1]);
-    ASSERT_EQ(String(&quot;sendSimpleKeyEvent type=release keycode=ffffff (faked)&quot;), events[2]);
-    ASSERT_EQ(String(&quot;sendKeyEventWithCompositionResults type=press keycode=16777215 (faked)&quot;), events[3]);
-    ASSERT_EQ(String(&quot;confirmComposition 'commit text'&quot;), events[4]);
-    ASSERT_EQ(String(&quot;sendSimpleKeyEvent type=release keycode=ffffff (faked)&quot;), events[5]);
-}
-
-static bool gSawContextReset = false;
-typedef void (*ResetCallback) (GtkIMContext*);
-static void temporaryResetOverride(GtkIMContext*)
-{
-    gSawContextReset = true;
-}
-
-static void verifyCanceledComposition(const Vector&lt;String&gt;&amp; events)
-{
-    ASSERT_EQ(3, events.size());
-    ASSERT_EQ(String(&quot;sendKeyEventWithCompositionResults type=press keycode=39&quot;), events[0]);
-    ASSERT_EQ(String(&quot;setPreedit text='' cursorOffset=0&quot;), events[1]);
-    ASSERT_EQ(String(&quot;sendSimpleKeyEvent type=release keycode=27&quot;), events[2]);
-    ASSERT(gSawContextReset);
-}
-
-TEST(GTK, GtkInputMethodFilterContextFocusOutDuringOngoingComposition)
-{
-    TestInputMethodFilter inputMethodFilter;
-
-    // See comment above about this technique.
-    GtkIMContext* context = inputMethodFilter.context();
-    GtkIMContextClass* contextClass = GTK_IM_CONTEXT_GET_CLASS(context);
-    ResetCallback previousCallback = contextClass-&gt;reset;
-    contextClass-&gt;reset = temporaryResetOverride;
-
-    gSawContextReset = false;
-    inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_Multi_key);
-    inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_apostrophe);
-    inputMethodFilter.notifyFocusedOut();
-
-    verifyCanceledComposition(inputMethodFilter.events());
-
-    contextClass-&gt;reset = previousCallback;
-}
-
-TEST(GTK, GtkInputMethodFilterContextMouseClickDuringOngoingComposition)
-{
-    TestInputMethodFilter inputMethodFilter;
-
-    // See comment above about this technique.
-    GtkIMContext* context = inputMethodFilter.context();
-    GtkIMContextClass* contextClass = GTK_IM_CONTEXT_GET_CLASS(context);
-    ResetCallback previousCallback = contextClass-&gt;reset;
-    contextClass-&gt;reset = temporaryResetOverride;
-
-    gSawContextReset = false;
-    inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_Multi_key);
-    inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_apostrophe);
-    inputMethodFilter.notifyMouseButtonPress();
-
-    verifyCanceledComposition(inputMethodFilter.events());
-
-    contextClass-&gt;reset = previousCallback;
-}
-
-} // namespace TestWebKitAPI
</del></span></pre></div>
<a id="trunkToolsTestWebKitAPITestsWebKit2gtkInputMethodFiltercppfromrev175043trunkToolsTestWebKitAPITestsWebCoregtkInputMethodFiltercpp"></a>
<div class="copfile"><h4>Copied: trunk/Tools/TestWebKitAPI/Tests/WebKit2/gtk/InputMethodFilter.cpp (from rev 175043, trunk/Tools/TestWebKitAPI/Tests/WebCore/gtk/InputMethodFilter.cpp) (0 => 175046)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/Tests/WebKit2/gtk/InputMethodFilter.cpp                                (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit2/gtk/InputMethodFilter.cpp        2014-10-22 13:00:12 UTC (rev 175046)
</span><span class="lines">@@ -0,0 +1,259 @@
</span><ins>+/*
+ * Copyright (C) 2012 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include &quot;config.h&quot;
+
+#include &quot;WTFStringUtilities.h&quot;
+#include &lt;WebKit/InputMethodFilter.h&gt;
+#include &lt;gdk/gdkkeysyms.h&gt;
+#include &lt;gtk/gtk.h&gt;
+#include &lt;wtf/gobject/GUniquePtr.h&gt;
+#include &lt;wtf/gobject/GRefPtr.h&gt;
+#include &lt;wtf/text/CString.h&gt;
+
+using namespace WebKit;
+
+namespace TestWebKitAPI {
+
+class TestInputMethodFilter : public InputMethodFilter {
+public:
+    TestInputMethodFilter()
+        : m_testWindow(gtk_window_new(GTK_WINDOW_POPUP))
+    {
+        setTestingMode(true);
+
+        gtk_widget_show(m_testWindow);
+        gtk_im_context_set_client_window(context(), gtk_widget_get_window(m_testWindow));
+
+        // Focus in is necessary to activate the default input method in the multicontext.
+        notifyFocusedIn();
+    }
+
+    ~TestInputMethodFilter()
+    {
+        gtk_widget_destroy(m_testWindow);
+    }
+
+    void sendKeyEventToFilter(unsigned gdkKeyValue, GdkEventType type, unsigned modifiers = 0)
+    {
+        GdkEvent* event = gdk_event_new(type);
+        event-&gt;key.keyval = gdkKeyValue;
+        event-&gt;key.state = modifiers;
+        event-&gt;key.window = gtk_widget_get_window(m_testWindow);
+        event-&gt;key.time = GDK_CURRENT_TIME;
+        g_object_ref(event-&gt;key.window);
+        gdk_event_set_device(event, gdk_device_manager_get_client_pointer(gdk_display_get_device_manager(gdk_display_get_default())));
+
+        GUniqueOutPtr&lt;GdkKeymapKey&gt; keys;
+        gint nKeys;
+        if (gdk_keymap_get_entries_for_keyval(gdk_keymap_get_default(), gdkKeyValue, &amp;keys.outPtr(), &amp;nKeys))
+            event-&gt;key.hardware_keycode = keys.get()[0].keycode;
+
+        filterKeyEvent(&amp;event-&gt;key);
+        gdk_event_free(event);
+    }
+
+    void sendPressAndReleaseKeyEventPairToFilter(unsigned gdkKeyValue, unsigned modifiers = 0)
+    {
+        sendKeyEventToFilter(gdkKeyValue, GDK_KEY_PRESS, modifiers);
+        sendKeyEventToFilter(gdkKeyValue, GDK_KEY_RELEASE, modifiers);
+    }
+
+private:
+    GtkWidget* m_testWindow;
+};
+
+TEST(WebKit2, InputMethodFilterSimple)
+{
+    TestInputMethodFilter inputMethodFilter;
+    inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_g);
+    inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_t);
+    inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_k);
+
+    const Vector&lt;String&gt;&amp; events = inputMethodFilter.events();
+
+    ASSERT_EQ(6, events.size());
+    ASSERT_EQ(String(&quot;sendSimpleKeyEvent type=press keycode=67 text='g'&quot;), events[0]);
+    ASSERT_EQ(String(&quot;sendSimpleKeyEvent type=release keycode=67&quot;), events[1]);
+    ASSERT_EQ(String(&quot;sendSimpleKeyEvent type=press keycode=74 text='t'&quot;), events[2]);
+    ASSERT_EQ(String(&quot;sendSimpleKeyEvent type=release keycode=74&quot;), events[3]);
+    ASSERT_EQ(String(&quot;sendSimpleKeyEvent type=press keycode=6b text='k'&quot;), events[4]);
+    ASSERT_EQ(String(&quot;sendSimpleKeyEvent type=release keycode=6b&quot;), events[5]);
+}
+
+TEST(WebKit2, InputMethodFilterUnicodeSequence)
+{
+    TestInputMethodFilter inputMethodFilter;
+
+    // This is simple unicode hex entry of the characters, u, 0, 0, f, 4 pressed with
+    // the shift and controls keys held down. In reality, these values are not typical
+    // of an actual hex entry, because they'd be transformed by the shift modifier according
+    // to the keyboard layout. For instance, on a US keyboard a 0 with the shift key pressed
+    // is a right parenthesis. Using these values prevents having to work out what the
+    // transformed characters are based on the current keyboard layout.
+    inputMethodFilter.sendKeyEventToFilter(GDK_KEY_Control_L, GDK_KEY_PRESS);
+    inputMethodFilter.sendKeyEventToFilter(GDK_KEY_Shift_L, GDK_KEY_PRESS, GDK_CONTROL_MASK);
+
+    inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_U, GDK_SHIFT_MASK | GDK_CONTROL_MASK);
+    inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_0, GDK_SHIFT_MASK | GDK_CONTROL_MASK);
+    inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_0, GDK_SHIFT_MASK | GDK_CONTROL_MASK);
+    inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_F, GDK_SHIFT_MASK | GDK_CONTROL_MASK);
+    inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_4, GDK_SHIFT_MASK | GDK_CONTROL_MASK);
+
+    inputMethodFilter.sendKeyEventToFilter(GDK_KEY_Shift_L, GDK_KEY_RELEASE, GDK_CONTROL_MASK | GDK_SHIFT_MASK);
+    inputMethodFilter.sendKeyEventToFilter(GDK_KEY_Control_L, GDK_KEY_RELEASE, GDK_CONTROL_MASK);
+
+    const Vector&lt;String&gt;&amp; events = inputMethodFilter.events();
+    ASSERT_EQ(21, events.size());
+    ASSERT_EQ(String(&quot;sendSimpleKeyEvent type=press keycode=ffe3&quot;), events[0]);
+    ASSERT_EQ(String(&quot;sendSimpleKeyEvent type=press keycode=ffe1&quot;), events[1]);
+    ASSERT_EQ(String(&quot;sendKeyEventWithCompositionResults type=press keycode=85&quot;), events[2]);
+    ASSERT_EQ(String(&quot;setPreedit text='u' cursorOffset=1&quot;), events[3]);
+    ASSERT_EQ(String(&quot;sendSimpleKeyEvent type=release keycode=55&quot;), events[4]);
+    ASSERT_EQ(String(&quot;sendKeyEventWithCompositionResults type=press keycode=48&quot;), events[5]);
+    ASSERT_EQ(String(&quot;setPreedit text='u0' cursorOffset=2&quot;), events[6]);
+    ASSERT_EQ(String(&quot;sendSimpleKeyEvent type=release keycode=30&quot;), events[7]);
+    ASSERT_EQ(String(&quot;sendKeyEventWithCompositionResults type=press keycode=48&quot;), events[8]);
+    ASSERT_EQ(String(&quot;setPreedit text='u00' cursorOffset=3&quot;), events[9]);
+    ASSERT_EQ(String(&quot;sendSimpleKeyEvent type=release keycode=30&quot;), events[10]);
+    ASSERT_EQ(String(&quot;sendKeyEventWithCompositionResults type=press keycode=70&quot;), events[11]);
+    ASSERT_EQ(String(&quot;setPreedit text='u00F' cursorOffset=4&quot;), events[12]);
+    ASSERT_EQ(String(&quot;sendSimpleKeyEvent type=release keycode=46&quot;), events[13]);
+    ASSERT_EQ(String(&quot;sendKeyEventWithCompositionResults type=press keycode=52&quot;), events[14]);
+    ASSERT_EQ(String(&quot;setPreedit text='u00F4' cursorOffset=5&quot;), events[15]);
+    ASSERT_EQ(String(&quot;sendSimpleKeyEvent type=release keycode=34&quot;), events[16]);
+    ASSERT_EQ(String(&quot;confirmComposition 'ô'&quot;), events[17]);
+    ASSERT_EQ(String(&quot;setPreedit text='' cursorOffset=0&quot;), events[18]);
+    ASSERT_EQ(String(&quot;sendSimpleKeyEvent type=release keycode=ffe1&quot;), events[19]);
+    ASSERT_EQ(String(&quot;sendSimpleKeyEvent type=release keycode=ffe3&quot;), events[20]);
+}
+
+TEST(WebKit2, InputMethodFilterComposeKey)
+{
+    TestInputMethodFilter inputMethodFilter;
+
+    inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_Multi_key);
+    inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_apostrophe);
+    inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_o);
+
+    const Vector&lt;String&gt;&amp; events = inputMethodFilter.events();
+    ASSERT_EQ(5, events.size());
+    ASSERT_EQ(String(&quot;sendKeyEventWithCompositionResults type=press keycode=39&quot;), events[0]);
+    ASSERT_EQ(String(&quot;setPreedit text='' cursorOffset=0&quot;), events[1]);
+    ASSERT_EQ(String(&quot;sendSimpleKeyEvent type=release keycode=27&quot;), events[2]);
+    ASSERT_EQ(String(&quot;sendSimpleKeyEvent type=press keycode=6f text='ó'&quot;), events[3]);
+    ASSERT_EQ(String(&quot;sendSimpleKeyEvent type=release keycode=6f&quot;), events[4]);
+}
+
+typedef void (*GetPreeditStringCallback) (GtkIMContext*, gchar**, PangoAttrList**, int*);
+static void temporaryGetPreeditStringOverride(GtkIMContext*, char** string, PangoAttrList** attrs, int* cursorPosition)
+{
+    *string = g_strdup(&quot;preedit of doom, bringer of cheese&quot;);
+    *cursorPosition = 3;
+}
+
+TEST(WebKit2, InputMethodFilterContextEventsWithoutKeyEvents)
+{
+    TestInputMethodFilter inputMethodFilter;
+
+    // This is a bit of a hack to avoid mocking out the entire InputMethodContext, by
+    // simply replacing the get_preedit_string virtual method for the length of this test.
+    GtkIMContext* context = inputMethodFilter.context();
+    GtkIMContextClass* contextClass = GTK_IM_CONTEXT_GET_CLASS(context);
+    GetPreeditStringCallback previousCallback = contextClass-&gt;get_preedit_string;
+    contextClass-&gt;get_preedit_string = temporaryGetPreeditStringOverride;
+
+    g_signal_emit_by_name(context, &quot;preedit-changed&quot;);
+    g_signal_emit_by_name(context, &quot;commit&quot;, &quot;commit text&quot;);
+
+    contextClass-&gt;get_preedit_string = previousCallback;
+
+    const Vector&lt;String&gt;&amp; events = inputMethodFilter.events();
+    ASSERT_EQ(6, events.size());
+    ASSERT_EQ(String(&quot;sendKeyEventWithCompositionResults type=press keycode=16777215 (faked)&quot;), events[0]);
+    ASSERT_EQ(String(&quot;setPreedit text='preedit of doom, bringer of cheese' cursorOffset=3&quot;), events[1]);
+    ASSERT_EQ(String(&quot;sendSimpleKeyEvent type=release keycode=ffffff (faked)&quot;), events[2]);
+    ASSERT_EQ(String(&quot;sendKeyEventWithCompositionResults type=press keycode=16777215 (faked)&quot;), events[3]);
+    ASSERT_EQ(String(&quot;confirmComposition 'commit text'&quot;), events[4]);
+    ASSERT_EQ(String(&quot;sendSimpleKeyEvent type=release keycode=ffffff (faked)&quot;), events[5]);
+}
+
+static bool gSawContextReset = false;
+typedef void (*ResetCallback) (GtkIMContext*);
+static void temporaryResetOverride(GtkIMContext*)
+{
+    gSawContextReset = true;
+}
+
+static void verifyCanceledComposition(const Vector&lt;String&gt;&amp; events)
+{
+    ASSERT_EQ(3, events.size());
+    ASSERT_EQ(String(&quot;sendKeyEventWithCompositionResults type=press keycode=39&quot;), events[0]);
+    ASSERT_EQ(String(&quot;setPreedit text='' cursorOffset=0&quot;), events[1]);
+    ASSERT_EQ(String(&quot;sendSimpleKeyEvent type=release keycode=27&quot;), events[2]);
+    ASSERT(gSawContextReset);
+}
+
+TEST(WebKit2, InputMethodFilterContextFocusOutDuringOngoingComposition)
+{
+    TestInputMethodFilter inputMethodFilter;
+
+    // See comment above about this technique.
+    GtkIMContext* context = inputMethodFilter.context();
+    GtkIMContextClass* contextClass = GTK_IM_CONTEXT_GET_CLASS(context);
+    ResetCallback previousCallback = contextClass-&gt;reset;
+    contextClass-&gt;reset = temporaryResetOverride;
+
+    gSawContextReset = false;
+    inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_Multi_key);
+    inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_apostrophe);
+    inputMethodFilter.notifyFocusedOut();
+
+    verifyCanceledComposition(inputMethodFilter.events());
+
+    contextClass-&gt;reset = previousCallback;
+}
+
+TEST(WebKit2, InputMethodFilterContextMouseClickDuringOngoingComposition)
+{
+    TestInputMethodFilter inputMethodFilter;
+
+    // See comment above about this technique.
+    GtkIMContext* context = inputMethodFilter.context();
+    GtkIMContextClass* contextClass = GTK_IM_CONTEXT_GET_CLASS(context);
+    ResetCallback previousCallback = contextClass-&gt;reset;
+    contextClass-&gt;reset = temporaryResetOverride;
+
+    gSawContextReset = false;
+    inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_Multi_key);
+    inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_apostrophe);
+    inputMethodFilter.notifyMouseButtonPress();
+
+    verifyCanceledComposition(inputMethodFilter.events());
+
+    contextClass-&gt;reset = previousCallback;
+}
+
+} // namespace TestWebKitAPI
</ins></span></pre>
</div>
</div>

</body>
</html>