Commit 611bde93 authored by mrobinson@webkit.org's avatar mrobinson@webkit.org
Browse files

[GTK] Rework IME handling to fix bugs and prepare for WebKit2

https://bugs.webkit.org/show_bug.cgi?id=84556

Reviewed by Gustavo Noronha Silva.

Source/WebCore:

No new tests. This change is already covered by a suite of keyboard
handling unit tests in WebKitGTK+. There are some changes in behavior,
but they are difficult to test without mocking out an entire GtkIMContext.

Add a struct, CompositionResults, which is used by PlatformKeyboardEvent
to package composition information with a keyboard event. Also add some logic
to PlatformKeyboardEvent to give the right information when it has composition
results.

* GNUmakefile.list.am: Added new sources to the list.
* platform/PlatformKeyboardEvent.h:  Added a new CompositionResults member,
getter, and argument to the constructor.
* platform/gtk/CompositionResults.h: Added.
* platform/gtk/GtkInputMethodFilter.cpp: Added.
* platform/gtk/GtkInputMethodFilter.h: Added.
* platform/gtk/PlatformKeyboardEventGtk.cpp:
(WebCore::PlatformKeyboardEvent::windowsKeyCodeForGdkKeyCode): When
the key value is void return the VK_PROCESS keycode, which is the keycode
that web content expects with keystrokes that trigger composition events.
(WebCore::eventTypeForGdkKeyEvent): Abstract out this helper.
(WebCore::modifiersForGdkKeyEvent): Abstract out this helper.
(WebCore::PlatformKeyboardEvent::PlatformKeyboardEvent): When a PlatformKeyEvent
has composition results, use VK_PROCESS as the keycode for this event.
(WebCore::PlatformKeyboardEvent::disambiguateKeyDownEvent): When this event is
transformed into a Char event, the PlatformKeyboardEvent used for DOM keypress
events, and it has composition results clear the text members. This forces the
EventHandler code to drop the keypress event. Platform events that change the
composition states do not have corresponding keypress DOM events (only keydown
and keyup events), so this is necessary to ensure web compatibility.

Source/WebKit/gtk:

Rework input method handling logic into a class called GtkInputMethodFilter.
This filter now runs before WebCore event handling, allowing the code to more
easily fake simple compositions that should be seen as keystrokes. We can also
filter keypresses that should not go to web content at all, such as key up events
related to key down events that were filtered.

Also added is a WebViewInputMethodFilter which is a concrete implementation of
GtkInputMethodFilter. This class contains logic for actually sending events to
WebCore. In WebKit2 an implementation of GtkInputMethodFilter will send events
across the IPC channel.

* GNUmakefile.am: Add new files to the source list.
* WebCoreSupport/ContextMenuClientGtk.cpp:
(WebKit::inputMethodsMenuItem): Access the input method context via the filter.
* WebCoreSupport/EditorClientGtk.cpp: Remove the tricky logic of input method
events from this class, because it's now in the GtkInputMethodFilter.
(WebKit::EditorClient::setInputMethodState): Call into the filter.
(WebKit::EditorClient::shouldBeginEditing): We no longer need to update the composition here.
This is handled by the focus in and focus out logic in the filter.
(WebKit::EditorClient::shouldEndEditing): Ditto.
(WebKit::EditorClient::respondToChangedSelection): Call into the filter now.
(WebKit::EditorClient::handleInputMethodKeyboardEvent): Added this helper which executes
any pending composition confirmation or preedit update actions as the default action of
the keydown event.
(WebKit::EditorClient::handleKeyboardEvent): Call handleInputMethodKeyboardEvent to do
any pending composition action.
(WebKit::EditorClient::handleInputMethodKeydown): Remove all the logic from this method.
Keys are filtered before they are sent to WebCore now and the actual action of input method
events happens in the keydown default action to increase compatibility with other browsers.
(WebKit::EditorClient::EditorClient): Remove context signal management.
(WebKit::EditorClient::~EditorClient): Ditto.
* WebCoreSupport/EditorClientGtk.h:
(EditorClient): No longer has some members that tracked IME status.
* WebCoreSupport/WebViewInputMethodFilter.cpp: Added.
* WebCoreSupport/WebViewInputMethodFilter.h: Added.
* webkit/webkitwebview.cpp:
(webkit_web_view_get_property): Get the context from the filter now.
(webkit_web_view_key_press_event): Just send events straight to the filter.
The filter will decide whether or not to send them to WebCore.
(webkit_web_view_key_release_event): Ditto.
(webkit_web_view_button_press_event): Use the filter to handle button press
events related to IME.
(webkit_web_view_focus_in_event): Notify the filter now.
(webkit_web_view_focus_out_event): Ditto.
(webkit_web_view_realize): The filter takes care of listening for realize now.
(webkit_web_view_init): Set the WebView widget on the filter.
* webkit/webkitwebviewprivate.h: Change the GtkIMContext member to be a GtkInputMethodFilter member.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@116114 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 7495f961
2012-05-03 Martin Robinson <mrobinson@igalia.com>
[GTK] Rework IME handling to fix bugs and prepare for WebKit2
https://bugs.webkit.org/show_bug.cgi?id=84556
Reviewed by Gustavo Noronha Silva.
No new tests. This change is already covered by a suite of keyboard
handling unit tests in WebKitGTK+. There are some changes in behavior,
but they are difficult to test without mocking out an entire GtkIMContext.
Add a struct, CompositionResults, which is used by PlatformKeyboardEvent
to package composition information with a keyboard event. Also add some logic
to PlatformKeyboardEvent to give the right information when it has composition
results.
* GNUmakefile.list.am: Added new sources to the list.
* platform/PlatformKeyboardEvent.h: Added a new CompositionResults member,
getter, and argument to the constructor.
* platform/gtk/CompositionResults.h: Added.
* platform/gtk/GtkInputMethodFilter.cpp: Added.
* platform/gtk/GtkInputMethodFilter.h: Added.
* platform/gtk/PlatformKeyboardEventGtk.cpp:
(WebCore::PlatformKeyboardEvent::windowsKeyCodeForGdkKeyCode): When
the key value is void return the VK_PROCESS keycode, which is the keycode
that web content expects with keystrokes that trigger composition events.
(WebCore::eventTypeForGdkKeyEvent): Abstract out this helper.
(WebCore::modifiersForGdkKeyEvent): Abstract out this helper.
(WebCore::PlatformKeyboardEvent::PlatformKeyboardEvent): When a PlatformKeyEvent
has composition results, use VK_PROCESS as the keycode for this event.
(WebCore::PlatformKeyboardEvent::disambiguateKeyDownEvent): When this event is
transformed into a Char event, the PlatformKeyboardEvent used for DOM keypress
events, and it has composition results clear the text members. This forces the
EventHandler code to drop the keypress event. Platform events that change the
composition states do not have corresponding keypress DOM events (only keydown
and keyup events), so this is necessary to ensure web compatibility.
2012-05-04 Jochen Eisinger <jochen@chromium.org>
 
Correctly update the outgoing referrer when navigating back from an history item created by pushState/replaceState
......@@ -4709,6 +4709,8 @@ webcoregtk_sources += \
Source/WebCore/platform/gtk/GtkClickCounter.h \
Source/WebCore/platform/gtk/GtkDragAndDropHelper.cpp \
Source/WebCore/platform/gtk/GtkDragAndDropHelper.h \
Source/WebCore/platform/gtk/GtkInputMethodFilter.cpp \
Source/WebCore/platform/gtk/GtkInputMethodFilter.h \
Source/WebCore/platform/gtk/GtkUtilities.cpp \
Source/WebCore/platform/gtk/GtkUtilities.h \
Source/WebCore/platform/gtk/GOwnPtrGtk.cpp \
......
......@@ -43,6 +43,7 @@ typedef long LPARAM;
#if PLATFORM(GTK)
typedef struct _GdkEventKey GdkEventKey;
#include "CompositionResults.h"
#endif
#if PLATFORM(QT)
......@@ -151,8 +152,9 @@ namespace WebCore {
#endif
#if PLATFORM(GTK)
PlatformKeyboardEvent(GdkEventKey*);
GdkEventKey* gdkEventKey() const;
PlatformKeyboardEvent(GdkEventKey*, const CompositionResults&);
GdkEventKey* gdkEventKey() const { return m_gdkEventKey; }
const CompositionResults& compositionResults() const { return m_compositionResults; }
// Used by WebKit2
static String keyIdentifierForGdkKeyCode(unsigned);
......@@ -200,6 +202,7 @@ namespace WebCore {
#endif
#if PLATFORM(GTK)
GdkEventKey* m_gdkEventKey;
CompositionResults m_compositionResults;
#endif
#if PLATFORM(QT)
QKeyEvent* m_qtEvent;
......
/*
* 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 COMPUTER, INC. ``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 COMPUTER, INC. OR
* 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.
*/
#ifndef CompositionResults_h
#define CompositionResults_h
#include <wtf/text/WTFString.h>
namespace WebCore {
struct CompositionResults {
CompositionResults()
: preeditCursorOffset(0)
{
}
CompositionResults(String simpleString)
: simpleString(simpleString)
, preeditCursorOffset(0)
{
}
CompositionResults(String confirmedComposition, String preedit, int preeditCursorOffset)
: confirmedComposition(confirmedComposition)
, preedit(preedit)
, preeditCursorOffset(preeditCursorOffset)
{
}
bool compositionUpdated() const
{
return !confirmedComposition.isNull() || !preedit.isNull();
}
// Some simple input methods return a string for all keyboard events. This
// value should be treated as the string representation of the keycode.
String simpleString;
// If the input method had a "real" composition it will be stored here.
String confirmedComposition;
// The event may have caused the preedit to update.
String preedit;
int preeditCursorOffset;
};
}
#endif // CompositionResults_h
/*
* 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 "config.h"
#include "GtkInputMethodFilter.h"
#include "GOwnPtrGtk.h"
#include "GtkVersioning.h"
#include <gdk/gdkkeysyms.h>
#include <gtk/gtk.h>
#include <wtf/MathExtras.h>
// 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->handleCommit(compositionString);
}
static void handlePreeditStartCallback(GtkIMContext*, GtkInputMethodFilter* filter)
{
filter->handlePreeditStart();
}
static void handlePreeditChangedCallback(GtkIMContext*, GtkInputMethodFilter* filter)
{
filter->handlePreeditChanged();
}
static void handlePreeditEndCallback(GtkIMContext*, GtkInputMethodFilter* filter)
{
filter->handlePreeditEnd();
}
static void handleWidgetRealize(GtkWidget* widget, GtkInputMethodFilter* filter)
{
GdkWindow* window = gtk_widget_get_window(widget);
ASSERT(window);
gtk_im_context_set_client_window(filter->context(), window);
}
void GtkInputMethodFilter::setWidget(GtkWidget* widget)
{
ASSERT(!m_widget);
m_widget = widget;
if (GdkWindow* window = gtk_widget_get_window(m_widget))
handleWidgetRealize(m_widget, this);
else
g_signal_connect_after(widget, "realize", G_CALLBACK(handleWidgetRealize), this);
}
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(), "commit", G_CALLBACK(handleCommitCallback), this);
g_signal_connect(m_context.get(), "preedit-start", G_CALLBACK(handlePreeditStartCallback), this);
g_signal_connect(m_context.get(), "preedit-changed", G_CALLBACK(handlePreeditChangedCallback), this);
g_signal_connect(m_context.get(), "preedit-end", G_CALLBACK(handlePreeditEndCallback), this);
}
GtkInputMethodFilter::~GtkInputMethodFilter()
{
g_signal_handlers_disconnect_by_func(m_context.get(), reinterpret_cast<void*>(handleCommitCallback), this);
g_signal_handlers_disconnect_by_func(m_context.get(), reinterpret_cast<void*>(handlePreeditStartCallback), this);
g_signal_handlers_disconnect_by_func(m_context.get(), reinterpret_cast<void*>(handlePreeditChangedCallback), this);
g_signal_handlers_disconnect_by_func(m_context.get(), reinterpret_cast<void*>(handlePreeditEndCallback), this);
g_signal_handlers_disconnect_by_func(m_widget, reinterpret_cast<void*>(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 && event->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 && !m_composingTextCurrently && !m_preeditChanged && m_confirmedComposition.length() == 1) {
bool result = sendSimpleKeyEvent(event, m_confirmedComposition);
m_confirmedComposition = String();
return result;
}
if (filtered && event->type == GDK_KEY_PRESS) {
if (!m_preeditChanged && m_confirmedComposition.isNull()) {
m_composingTextCurrently = true;
m_lastFilteredKeyPressCodeWithNoResults = event->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->type == GDK_KEY_RELEASE && lastFilteredKeyPressCodeWithNoResults == event->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 "a"
// 3. keyup 'a' (unfiltered)
// 4. keydown Backspace (unfiltered)
// 5. commit "a"
// 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.
m_composingTextCurrently = false;
confirmCurrentComposition();
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;
m_composingTextCurrently = false;
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)
{
GOwnPtr<GdkEvent> event(gdk_event_new(GDK_KEY_PRESS));
event->key.time = GDK_CURRENT_TIME;
event->key.keyval = gCompositionEventKeyCode;
sendKeyEventWithCompositionResults(&event->key, resultsToSend);
m_confirmedComposition = String();
m_composingTextCurrently = false;
event->type = GDK_KEY_RELEASE;
sendSimpleKeyEvent(&event->key);
m_justSentFakeKeyUp = true;
}
void GtkInputMethodFilter::handleCommit(const char* compositionString)
{
if (m_preventNextCommit) {
m_preventNextCommit = false;
return;
}
if (!m_enabled)
return;
m_confirmedComposition += 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 = "";
}
void GtkInputMethodFilter::handlePreeditChanged()
{
if (!m_enabled)
return;
GOwnPtr<gchar> newPreedit;
gtk_im_context_get_preedit_string(m_context.get(), &newPreedit.outPtr(), 0, &m_cursorOffset);
if (m_preventNextCommit) {
if (strlen(newPreedit.get()) > 0)
m_preventNextCommit = false;
else
return;
}
m_preedit = String::fromUTF8(newPreedit.get());
m_cursorOffset = std::min(std::max(m_cursorOffset, 0), static_cast<int>(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();
}
}
/*
* 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 "GRefPtrGtk.h"
#include <gdk/gdk.h>
#include <wtf/text/WTFString.h>
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();
GtkIMContext* context() { return m_context.get(); }
protected:
enum ResultsToSend {
Preedit = 1 << 1,
Composition = 1 << 2,
PreeditAndComposition = Preedit + Composition
};
void setWidget(GtkWidget*);
virtual bool canEdit() = 0;
virtual bool sendSimpleKeyEvent(GdkEventKey*, WTF::String eventString = String()) = 0;
virtual bool sendKeyEventWithCompositionResults(GdkEventKey*, ResultsToSend = PreeditAndComposition) = 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<GtkIMContext> 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;
};
} // namespace WebCore
......@@ -510,7 +510,8 @@ int PlatformKeyboardEvent::windowsKeyCodeForGdkKeyCode(unsigned keycode)
case GDK_F23:
case GDK_F24:
return VK_F1 + (keycode - GDK_F1);
case GDK_KEY_VoidSymbol:
return VK_PROCESSKEY;
default:
return 0;
}
......@@ -545,12 +546,30 @@ String PlatformKeyboardEvent::singleCharacterString(unsigned val)
}
}
static PlatformEvent::Type eventTypeForGdkKeyEvent(GdkEventKey* event)
{
return event->type == GDK_KEY_RELEASE ? PlatformEvent::KeyUp : PlatformEvent::KeyDown;
}
static PlatformEvent::Modifiers modifiersForGdkKeyEvent(GdkEventKey* event)
{
unsigned int modifiers = 0;
if (event->state & GDK_SHIFT_MASK || event->keyval == GDK_3270_BackTab)
modifiers |= PlatformEvent::ShiftKey;
if (event->state & GDK_CONTROL_MASK)
modifiers |= PlatformEvent::CtrlKey;
if (event->state & GDK_MOD1_MASK)
modifiers |= PlatformEvent::AltKey;
if (event->state & GDK_META_MASK)
modifiers |= PlatformEvent::MetaKey;
return static_cast<PlatformEvent::Modifiers>(modifiers);
}