Skip to content

Instantly share code, notes, and snippets.

@kenchris
Created January 6, 2012 15:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kenchris/1571092 to your computer and use it in GitHub Desktop.
Save kenchris/1571092 to your computer and use it in GitHub Desktop.
commit 6a7de7f6428fa6339e8cf48e29bf91b86ed8324e
Author: Kenneth Rohde Christiansen <kenneth@webkit.org>
Date: Fri Jan 6 16:32:31 2012 +0100
WIP
diff --git a/Source/WebCore/loader/EmptyClients.h b/Source/WebCore/loader/EmptyClients.h
index 8d1fe7d..e522eff 100644
--- a/Source/WebCore/loader/EmptyClients.h
+++ b/Source/WebCore/loader/EmptyClients.h
@@ -525,6 +525,7 @@ public:
virtual void willSetInputMethodState() { }
virtual void setInputMethodState(bool) { }
+ virtual bool inputMethodIsPrimaryInputDevice() { return false; }
private:
EmptyTextCheckerClient m_textCheckerClient;
diff --git a/Source/WebCore/page/EditorClient.h b/Source/WebCore/page/EditorClient.h
index 5a4be2c..05fd744 100644
--- a/Source/WebCore/page/EditorClient.h
+++ b/Source/WebCore/page/EditorClient.h
@@ -168,6 +168,7 @@ public:
virtual bool spellingUIIsShowing() = 0;
virtual void willSetInputMethodState() = 0;
virtual void setInputMethodState(bool enabled) = 0;
+ virtual bool inputMethodIsPrimaryInputDevice() = 0;
};
}
diff --git a/Source/WebCore/page/EventHandler.cpp b/Source/WebCore/page/EventHandler.cpp
index c21eb7e..b71ce6e 100644
--- a/Source/WebCore/page/EventHandler.cpp
+++ b/Source/WebCore/page/EventHandler.cpp
@@ -38,6 +38,7 @@
#include "DragController.h"
#include "DragState.h"
#include "Editor.h"
+#include "EditorClient.h"
#include "EventNames.h"
#include "FloatPoint.h"
#include "FloatRect.h"
@@ -2244,8 +2245,22 @@ bool EventHandler::handleGestureEvent(const PlatformGestureEvent& gestureEvent)
PlatformMouseEvent fakeMouseDown(gestureEvent.position(), gestureEvent.globalPosition(), LeftButton, PlatformEvent::MousePressed, /* clickCount */ 1, gestureEvent.shiftKey(), gestureEvent.ctrlKey(), gestureEvent.altKey(), gestureEvent.metaKey(), gestureEvent.timestamp());
PlatformMouseEvent fakeMouseUp(gestureEvent.position(), gestureEvent.globalPosition(), LeftButton, PlatformEvent::MouseReleased, /* clickCount */ 1, gestureEvent.shiftKey(), gestureEvent.ctrlKey(), gestureEvent.altKey(), gestureEvent.metaKey(), gestureEvent.timestamp());
mouseMoved(fakeMouseMove);
+
+ // Elements can loose focus on mousedownEvent but get focused via for instance
+ // the DOM during clickEvent. To not hide and reshow the input method editor, we
+ // disable it until after all event processing.
+ m_frame->page()->editorClient()->willSetInputMethodState();
+ m_frame->page()->focusController()->setPostponeInputMethodStateChanges(true);
+
handleMousePressEvent(fakeMouseDown);
handleMouseReleaseEvent(fakeMouseUp);
+
+ // Reenable the input method, which will reset the state and show the input method iff:
+ // a) an editable element received mousedownEvent and got focused.
+ // b) an editable element received focus via JavaScript focus() as a result of a clickEvent.
+ // c) an editable element received focus as a result of a clickEvent on a <label for=name>.
+ m_frame->page()->focusController()->setPostponeInputMethodStateChanges(false);
+ m_frame->page()->focusController()->inputMethodStateDidChange(m_frame->document()->focusedNode(), FocusController::TapStateChangeReason);
return true;
}
case PlatformEvent::GestureScrollUpdate: {
diff --git a/Source/WebCore/page/FocusController.cpp b/Source/WebCore/page/FocusController.cpp
index 4f58df3..d3c378c 100644
--- a/Source/WebCore/page/FocusController.cpp
+++ b/Source/WebCore/page/FocusController.cpp
@@ -85,6 +85,7 @@ static inline void dispatchEventsOnWindowAndFocusedNode(Document* document, bool
FocusController::FocusController(Page* page)
: m_page(page)
+ , m_postponeInputMethodStateChanges(false)
, m_isActive(false)
, m_isFocused(false)
, m_isChangingFocusedFrame(false)
@@ -511,11 +512,41 @@ static void clearSelectionIfNeeded(Frame* oldFocusedFrame, Frame* newFocusedFram
s->clear();
}
+void FocusController::inputMethodStateDidChange(Node* node, FocusController::StateChangeReason reason)
+{
+ if (m_postponeInputMethodStateChanges)
+ return;
+
+ bool active = false;
+
+ if (m_page->editorClient()->inputMethodIsPrimaryInputDevice()) {
+ if (reason != FocusController::TapStateChangeReason)
+ return;
+
+ // If the input method editor is the primary input device we trust it enough for
+ // all editing needs, such as entering passwords, and thus disregard the result
+ // of shouldUseInputMethod().
+ //
+ // Instead we check the editor state, as We can be in edit mode even when focusing
+ // a non-editable node. This is due to content editable and design mode where it is
+ // possible to click on links etc to change input to bold etc.
+ active = focusedOrMainFrame()->editor() && focusedOrMainFrame()->editor()->canEdit();
+ } else
+ active = node && node->shouldUseInputMethod();
+
+ m_page->editorClient()->setInputMethodState(active);
+}
+
+void FocusController::setPostponeInputMethodStateChanges(bool enable)
+{
+ m_postponeInputMethodStateChanges = enable;
+}
+
bool FocusController::setFocusedNode(Node* node, PassRefPtr<Frame> newFocusedFrame)
{
RefPtr<Frame> oldFocusedFrame = focusedFrame();
RefPtr<Document> oldDocument = oldFocusedFrame ? oldFocusedFrame->document() : 0;
-
+
Node* oldFocusedNode = oldDocument ? oldDocument->focusedNode() : 0;
if (oldFocusedNode == node)
return true;
@@ -531,20 +562,20 @@ bool FocusController::setFocusedNode(Node* node, PassRefPtr<Frame> newFocusedFra
if (!node) {
if (oldDocument)
oldDocument->setFocusedNode(0);
- m_page->editorClient()->setInputMethodState(false);
+ inputMethodStateDidChange(node);
return true;
}
RefPtr<Document> newDocument = node->document();
if (newDocument && newDocument->focusedNode() == node) {
- m_page->editorClient()->setInputMethodState(node->shouldUseInputMethod());
+ inputMethodStateDidChange(node);
return true;
}
-
+
if (oldDocument && oldDocument != newDocument)
oldDocument->setFocusedNode(0);
-
+
setFocusedFrame(newFocusedFrame);
// Setting the focused node can result in losing our last reft to node when JS event handlers fire.
@@ -556,7 +587,7 @@ bool FocusController::setFocusedNode(Node* node, PassRefPtr<Frame> newFocusedFra
}
if (newDocument->focusedNode() == node)
- m_page->editorClient()->setInputMethodState(node->shouldUseInputMethod());
+ inputMethodStateDidChange(node);
return true;
}
diff --git a/Source/WebCore/page/FocusController.h b/Source/WebCore/page/FocusController.h
index 6880a1c..f691397 100644
--- a/Source/WebCore/page/FocusController.h
+++ b/Source/WebCore/page/FocusController.h
@@ -54,7 +54,11 @@ public:
bool setInitialFocus(FocusDirection, KeyboardEvent*);
bool advanceFocus(FocusDirection, KeyboardEvent*, bool initialFocus = false);
-
+
+ void setPostponeInputMethodStateChanges(bool);
+ enum StateChangeReason { TapStateChangeReason, OtherStateChangeReason };
+ void inputMethodStateDidChange(Node*, StateChangeReason reason = OtherStateChangeReason);
+
bool setFocusedNode(Node*, PassRefPtr<Frame>);
void setActive(bool);
@@ -93,6 +97,7 @@ private:
Page* m_page;
RefPtr<Frame> m_focusedFrame;
+ bool m_postponeInputMethodStateChanges;
bool m_isActive;
bool m_isFocused;
bool m_isChangingFocusedFrame;
diff --git a/Source/WebKit/chromium/src/EditorClientImpl.cpp b/Source/WebKit/chromium/src/EditorClientImpl.cpp
index 5fa2378..4b93e12 100644
--- a/Source/WebKit/chromium/src/EditorClientImpl.cpp
+++ b/Source/WebKit/chromium/src/EditorClientImpl.cpp
@@ -807,4 +807,9 @@ void EditorClientImpl::setInputMethodState(bool)
{
}
-} // namesace WebKit
+bool EditorClientImpl::inputMethodIsPrimaryInputDevice()
+{
+ return false;
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit/chromium/src/EditorClientImpl.h b/Source/WebKit/chromium/src/EditorClientImpl.h
index 233695f..9985db6 100644
--- a/Source/WebKit/chromium/src/EditorClientImpl.h
+++ b/Source/WebKit/chromium/src/EditorClientImpl.h
@@ -107,6 +107,7 @@ public:
virtual void getGuessesForWord(const WTF::String& word, const WTF::String& context, WTF::Vector<WTF::String>& guesses);
virtual void willSetInputMethodState();
virtual void setInputMethodState(bool enabled);
+ virtual bool inputMethodIsPrimaryInputDevice();
virtual void requestCheckingOfString(WebCore::SpellChecker*, int, WebCore::TextCheckingTypeMask, const WTF::String&);
virtual WebCore::TextCheckerClient* textChecker() { return this; }
diff --git a/Source/WebKit/efl/WebCoreSupport/EditorClientEfl.cpp b/Source/WebKit/efl/WebCoreSupport/EditorClientEfl.cpp
index 78563ec..27e4836 100644
--- a/Source/WebKit/efl/WebCoreSupport/EditorClientEfl.cpp
+++ b/Source/WebKit/efl/WebCoreSupport/EditorClientEfl.cpp
@@ -50,6 +50,12 @@ void EditorClientEfl::setInputMethodState(bool active)
ewk_view_input_method_state_set(m_view, active);
}
+bool EditorClientEfl::inputMethodIsPrimaryInputDevice()
+{
+ notImplemented();
+ return false;
+}
+
bool EditorClientEfl::shouldDeleteRange(Range*)
{
notImplemented();
diff --git a/Source/WebKit/efl/WebCoreSupport/EditorClientEfl.h b/Source/WebKit/efl/WebCoreSupport/EditorClientEfl.h
index 7ff1813..846a2ed 100644
--- a/Source/WebKit/efl/WebCoreSupport/EditorClientEfl.h
+++ b/Source/WebKit/efl/WebCoreSupport/EditorClientEfl.h
@@ -120,6 +120,7 @@ public:
virtual void getGuessesForWord(const String& word, const String& context, WTF::Vector<String>& guesses);
virtual void willSetInputMethodState();
virtual void setInputMethodState(bool enabled);
+ virtual bool inputMethodIsPrimaryInputDevice();
virtual void requestCheckingOfString(WebCore::SpellChecker*, int, WebCore::TextCheckingTypeMask, const WTF::String&) { }
virtual TextCheckerClient* textChecker() { return this; }
diff --git a/Source/WebKit/gtk/WebCoreSupport/EditorClientGtk.cpp b/Source/WebKit/gtk/WebCoreSupport/EditorClientGtk.cpp
index 913b0df..5c0a4a1 100644
--- a/Source/WebKit/gtk/WebCoreSupport/EditorClientGtk.cpp
+++ b/Source/WebKit/gtk/WebCoreSupport/EditorClientGtk.cpp
@@ -133,6 +133,11 @@ void EditorClient::setInputMethodState(bool active)
#endif
}
+bool EditorClient::inputMethodIsPrimaryInputDevice()
+{
+ return false;
+}
+
bool EditorClient::shouldDeleteRange(Range* range)
{
gboolean accept = TRUE;
diff --git a/Source/WebKit/gtk/WebCoreSupport/EditorClientGtk.h b/Source/WebKit/gtk/WebCoreSupport/EditorClientGtk.h
index 2533c16..e304f36 100644
--- a/Source/WebKit/gtk/WebCoreSupport/EditorClientGtk.h
+++ b/Source/WebKit/gtk/WebCoreSupport/EditorClientGtk.h
@@ -136,6 +136,7 @@ class EditorClient : public WebCore::EditorClient {
virtual bool spellingUIIsShowing();
virtual void willSetInputMethodState();
virtual void setInputMethodState(bool enabled);
+ virtual bool inputMethodIsPrimaryInputDevice();
private:
#if ENABLE(SPELLCHECK)
diff --git a/Source/WebKit/mac/WebCoreSupport/WebEditorClient.h b/Source/WebKit/mac/WebCoreSupport/WebEditorClient.h
index c70d608..b0d5aca 100644
--- a/Source/WebKit/mac/WebCoreSupport/WebEditorClient.h
+++ b/Source/WebKit/mac/WebCoreSupport/WebEditorClient.h
@@ -135,6 +135,7 @@ public:
virtual void getGuessesForWord(const WTF::String& word, const WTF::String& context, WTF::Vector<WTF::String>& guesses) OVERRIDE;
virtual void willSetInputMethodState() OVERRIDE;
virtual void setInputMethodState(bool enabled) OVERRIDE;
+ virtual bool inputMethodIsPrimaryInputDevice() OVERRIDE;
virtual void requestCheckingOfString(WebCore::SpellChecker*, int, WebCore::TextCheckingTypeMask, const WTF::String&) OVERRIDE;
#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
virtual void showCorrectionPanel(WebCore::CorrectionPanelInfo::PanelType, const WebCore::FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings) OVERRIDE;
diff --git a/Source/WebKit/mac/WebCoreSupport/WebEditorClient.mm b/Source/WebKit/mac/WebCoreSupport/WebEditorClient.mm
index 8cb31f8..ed24f88 100644
--- a/Source/WebKit/mac/WebCoreSupport/WebEditorClient.mm
+++ b/Source/WebKit/mac/WebCoreSupport/WebEditorClient.mm
@@ -937,6 +937,11 @@ void WebEditorClient::setInputMethodState(bool)
{
}
+bool WebEditorClient::inputMethodIsPrimaryInputDevice()
+{
+ return NO;
+}
+
#ifndef BUILDING_ON_LEOPARD
@interface WebEditorSpellCheckResponder : NSObject
{
diff --git a/Source/WebKit/qt/WebCoreSupport/EditorClientQt.cpp b/Source/WebKit/qt/WebCoreSupport/EditorClientQt.cpp
index 1d80803..9fdbb93 100644
--- a/Source/WebKit/qt/WebCoreSupport/EditorClientQt.cpp
+++ b/Source/WebKit/qt/WebCoreSupport/EditorClientQt.cpp
@@ -632,6 +632,11 @@ void EditorClientQt::setInputMethodState(bool active)
emit m_page->microFocusChanged();
}
+bool EditorClientQt::inputMethodIsPrimaryInputDevice()
+{
+ return false;
+}
+
}
// vim: ts=4 sw=4 et
diff --git a/Source/WebKit/qt/WebCoreSupport/EditorClientQt.h b/Source/WebKit/qt/WebCoreSupport/EditorClientQt.h
index c20f975..574ecbe 100644
--- a/Source/WebKit/qt/WebCoreSupport/EditorClientQt.h
+++ b/Source/WebKit/qt/WebCoreSupport/EditorClientQt.h
@@ -102,6 +102,7 @@ public:
virtual bool spellingUIIsShowing();
virtual void willSetInputMethodState();
virtual void setInputMethodState(bool enabled);
+ virtual bool inputMethodIsPrimaryInputDevice() OVERRIDE;
virtual TextCheckerClient* textChecker() { return &m_textCheckerClient; }
bool isEditing() const;
diff --git a/Source/WebKit/win/WebCoreSupport/WebEditorClient.cpp b/Source/WebKit/win/WebCoreSupport/WebEditorClient.cpp
index 0b26530..749d479 100644
--- a/Source/WebKit/win/WebCoreSupport/WebEditorClient.cpp
+++ b/Source/WebKit/win/WebCoreSupport/WebEditorClient.cpp
@@ -789,3 +789,9 @@ void WebEditorClient::setInputMethodState(bool enabled)
{
m_webView->setInputMethodState(enabled);
}
+
+bool WebEditorClient::inputMethodIsPrimaryInputDevice()
+{
+ return false;
+}
+
diff --git a/Source/WebKit/win/WebCoreSupport/WebEditorClient.h b/Source/WebKit/win/WebCoreSupport/WebEditorClient.h
index a40586c..d7aab91 100644
--- a/Source/WebKit/win/WebCoreSupport/WebEditorClient.h
+++ b/Source/WebKit/win/WebCoreSupport/WebEditorClient.h
@@ -110,6 +110,7 @@ public:
virtual void willSetInputMethodState();
virtual void setInputMethodState(bool);
+ virtual bool inputMethodIsPrimaryInputDevice();
virtual void requestCheckingOfString(WebCore::SpellChecker*, int, WebCore::TextCheckingTypeMask, const WTF::String&) {}
virtual WebCore::TextCheckerClient* textChecker() { return this; }
diff --git a/Source/WebKit/wince/WebCoreSupport/EditorClientWinCE.cpp b/Source/WebKit/wince/WebCoreSupport/EditorClientWinCE.cpp
index 4cd3aac..01f1c50 100644
--- a/Source/WebKit/wince/WebCoreSupport/EditorClientWinCE.cpp
+++ b/Source/WebKit/wince/WebCoreSupport/EditorClientWinCE.cpp
@@ -501,4 +501,10 @@ void EditorClientWinCE::willSetInputMethodState()
notImplemented();
}
+bool EditorClientWinCE::inputMethodIsPrimaryInputDevice()
+{
+ notImplemented();
+ return false;
+}
+
} // namespace WebKit
diff --git a/Source/WebKit/wince/WebCoreSupport/EditorClientWinCE.h b/Source/WebKit/wince/WebCoreSupport/EditorClientWinCE.h
index c29524e..ed177b8 100644
--- a/Source/WebKit/wince/WebCoreSupport/EditorClientWinCE.h
+++ b/Source/WebKit/wince/WebCoreSupport/EditorClientWinCE.h
@@ -101,6 +101,7 @@ public:
virtual void getGuessesForWord(const WTF::String& word, const WTF::String& context, WTF::Vector<WTF::String>& guesses);
virtual void willSetInputMethodState();
virtual void setInputMethodState(bool);
+ virtual bool inputMethodIsPrimaryInputDevice();
virtual void requestCheckingOfString(WebCore::SpellChecker*, int, WebCore::TextCheckingTypeMask, const WTF::String&) {}
virtual WebCore::TextCheckerClient* textChecker() { return this; }
diff --git a/Source/WebKit/wx/WebKitSupport/EditorClientWx.cpp b/Source/WebKit/wx/WebKitSupport/EditorClientWx.cpp
index e8cf31d..484a070 100644
--- a/Source/WebKit/wx/WebKitSupport/EditorClientWx.cpp
+++ b/Source/WebKit/wx/WebKitSupport/EditorClientWx.cpp
@@ -560,4 +560,10 @@ void EditorClientWx::setInputMethodState(bool enabled)
notImplemented();
}
+bool EditorClientWx::inputMethodIsPrimaryInputDevice()
+{
+ notImplemented();
+ return false;
+}
+
}
diff --git a/Source/WebKit/wx/WebKitSupport/EditorClientWx.h b/Source/WebKit/wx/WebKitSupport/EditorClientWx.h
index 1387fb8..85e3576 100644
--- a/Source/WebKit/wx/WebKitSupport/EditorClientWx.h
+++ b/Source/WebKit/wx/WebKitSupport/EditorClientWx.h
@@ -114,6 +114,8 @@ public:
virtual void willSetInputMethodState();
virtual void setInputMethodState(bool enabled);
+ virtual bool inputMethodIsPrimaryInputDevice();
+
virtual void requestCheckingOfString(WebCore::SpellChecker*, int, WebCore::TextCheckingTypeMask, const WTF::String&) {}
virtual TextCheckerClient* textChecker() { return this; }
diff --git a/Source/WebKit2/WebProcess/WebCoreSupport/WebEditorClient.cpp b/Source/WebKit2/WebProcess/WebCoreSupport/WebEditorClient.cpp
index 1e39864..5e3b89f 100644
--- a/Source/WebKit2/WebProcess/WebCoreSupport/WebEditorClient.cpp
+++ b/Source/WebKit2/WebProcess/WebCoreSupport/WebEditorClient.cpp
@@ -185,11 +185,6 @@ void WebEditorClient::respondToChangedSelection(Frame* frame)
EditorState state = m_page->editorState();
-#if PLATFORM(QT)
- if (Element* scope = frame->selection()->rootEditableElement())
- m_page->send(Messages::WebPageProxy::FocusEditableArea(state.microFocus, scope->getRect()));
-#endif
-
m_page->send(Messages::WebPageProxy::EditorStateChanged(state));
#if PLATFORM(WIN)
@@ -445,11 +440,27 @@ void WebEditorClient::willSetInputMethodState()
notImplemented();
}
-void WebEditorClient::setInputMethodState(bool)
+void WebEditorClient::setInputMethodState(bool active)
{
+#if PLATFORM(QT)
+ Frame* frame = m_page->corePage()->focusController()->focusedOrMainFrame();
+ Element* scope = frame->selection()->rootEditableElement();
+ if (active && scope)
+ m_page->send(Messages::WebPageProxy::FocusEditableArea(m_page->editorState().microFocus, scope->getRect()));
+ return;
+#endif
+
notImplemented();
}
+bool WebEditorClient::inputMethodIsPrimaryInputDevice()
+{
+#if PLATFORM(QT)
+ return true;
+#endif
+ return false;
+}
+
void WebEditorClient::requestCheckingOfString(WebCore::SpellChecker*, int, WebCore::TextCheckingTypeMask, const WTF::String&)
{
notImplemented();
diff --git a/Source/WebKit2/WebProcess/WebCoreSupport/WebEditorClient.h b/Source/WebKit2/WebProcess/WebCoreSupport/WebEditorClient.h
index 6664275..d7c503f 100644
--- a/Source/WebKit2/WebProcess/WebCoreSupport/WebEditorClient.h
+++ b/Source/WebKit2/WebProcess/WebCoreSupport/WebEditorClient.h
@@ -140,6 +140,7 @@ private:
virtual void getGuessesForWord(const String& word, const String& context, Vector<String>& guesses) OVERRIDE;
virtual void willSetInputMethodState() OVERRIDE;
virtual void setInputMethodState(bool enabled) OVERRIDE;
+ virtual bool inputMethodIsPrimaryInputDevice() OVERRIDE;
virtual void requestCheckingOfString(WebCore::SpellChecker*, int, WebCore::TextCheckingTypeMask, const WTF::String&) OVERRIDE;
#if PLATFORM(MAC) && !defined(BUILDING_ON_SNOW_LEOPARD)
virtual void showCorrectionPanel(WebCore::CorrectionPanelInfo::PanelType, const WebCore::FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings) OVERRIDE;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment