Handle complex text input for plug-ins
authorandersca@apple.com <andersca@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 14 Dec 2010 19:41:52 +0000 (19:41 +0000)
committerandersca@apple.com <andersca@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 14 Dec 2010 19:41:52 +0000 (19:41 +0000)
https://bugs.webkit.org/show_bug.cgi?id=51047

Reviewed by Sam Weinig.

* PluginProcess/PluginControllerProxy.cpp:
(WebKit::PluginControllerProxy::sendComplexTextInput):
Pass along the text input to the plug-in.

* PluginProcess/PluginControllerProxy.messages.in:
Add SendComplexTextInput message.

* UIProcess/API/mac/WKTextInputWindowController.h: Added.
* UIProcess/API/mac/WKTextInputWindowController.mm: Added.
Add text input window controller, mostly copied from WebKit1.

* UIProcess/API/mac/WKView.mm:
(-[WKView keyDown:]):
If needed, pass along the event to the text input window controller.

(-[WKView inputContext]):
Return the input context of the text input window controller.

(-[WKView _setComplexTextInputEnabled:pluginComplexTextInputIdentifier:]):
Notify the input window controller that the input source changed.

* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::sendComplexTextInputToPlugin):
Send the complex text input to the web process.

* WebKit2.xcodeproj/project.pbxproj:
Add new files.

* WebProcess/Plugins/Netscape/mac/NetscapePluginMac.mm:
(WebKit::convertStringToKeyCodes):
Convert a string to a vector of key codes in the current encoding.

(WebKit::NetscapePlugin::sendComplexTextInput):
In the Cocoa event model, create and dispatch an NPCocoaEventTextInput event.
In the Carbon event model, convert the string to individual key codes and send them
as key down events.

* WebProcess/Plugins/PluginProxy.cpp:
(WebKit::PluginProxy::sendComplexTextInput):
Send the text to the plug-in controller proxy.

* WebProcess/Plugins/PluginView.cpp:
(WebKit::PluginView::sendComplexTextInput):
If the plug-in has a matching text input identifier, call Plugin::sendComplexTextInput.

* WebProcess/WebPage/WebPage.messages.in:
Add SendComplexTextInputToPlugin message.

* WebProcess/WebPage/mac/WebPageMac.mm:
(WebKit::WebPage::sendComplexTextInputToPlugin):
Iterate over all known plug-in views and try to find one to send the text input to.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@74046 268f45cc-cd09-0410-ab3c-d52691b4dbfc

20 files changed:
WebKit2/ChangeLog
WebKit2/PluginProcess/PluginControllerProxy.cpp
WebKit2/PluginProcess/PluginControllerProxy.h
WebKit2/PluginProcess/PluginControllerProxy.messages.in
WebKit2/UIProcess/API/mac/WKTextInputWindowController.h [new file with mode: 0644]
WebKit2/UIProcess/API/mac/WKTextInputWindowController.mm [new file with mode: 0644]
WebKit2/UIProcess/API/mac/WKView.mm
WebKit2/UIProcess/WebPageProxy.cpp
WebKit2/UIProcess/WebPageProxy.h
WebKit2/WebKit2.xcodeproj/project.pbxproj
WebKit2/WebProcess/Plugins/Netscape/NetscapePlugin.h
WebKit2/WebProcess/Plugins/Netscape/mac/NetscapePluginMac.mm
WebKit2/WebProcess/Plugins/Plugin.h
WebKit2/WebProcess/Plugins/PluginProxy.cpp
WebKit2/WebProcess/Plugins/PluginProxy.h
WebKit2/WebProcess/Plugins/PluginView.cpp
WebKit2/WebProcess/Plugins/PluginView.h
WebKit2/WebProcess/WebPage/WebPage.h
WebKit2/WebProcess/WebPage/WebPage.messages.in
WebKit2/WebProcess/WebPage/mac/WebPageMac.mm

index 6779ec1..da221e5 100644 (file)
@@ -1,3 +1,62 @@
+2010-12-14  Anders Carlsson  <andersca@apple.com>
+
+        Reviewed by Sam Weinig.
+
+        Handle complex text input for plug-ins
+        https://bugs.webkit.org/show_bug.cgi?id=51047
+
+        * PluginProcess/PluginControllerProxy.cpp:
+        (WebKit::PluginControllerProxy::sendComplexTextInput):
+        Pass along the text input to the plug-in.
+
+        * PluginProcess/PluginControllerProxy.messages.in:
+        Add SendComplexTextInput message.
+
+        * UIProcess/API/mac/WKTextInputWindowController.h: Added.
+        * UIProcess/API/mac/WKTextInputWindowController.mm: Added.
+        Add text input window controller, mostly copied from WebKit1.
+        
+        * UIProcess/API/mac/WKView.mm:
+        (-[WKView keyDown:]):
+        If needed, pass along the event to the text input window controller.
+
+        (-[WKView inputContext]):
+        Return the input context of the text input window controller.
+
+        (-[WKView _setComplexTextInputEnabled:pluginComplexTextInputIdentifier:]):
+        Notify the input window controller that the input source changed.
+
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::sendComplexTextInputToPlugin):
+        Send the complex text input to the web process.
+
+        * WebKit2.xcodeproj/project.pbxproj:
+        Add new files.
+
+        * WebProcess/Plugins/Netscape/mac/NetscapePluginMac.mm:
+        (WebKit::convertStringToKeyCodes):
+        Convert a string to a vector of key codes in the current encoding.
+
+        (WebKit::NetscapePlugin::sendComplexTextInput):
+        In the Cocoa event model, create and dispatch an NPCocoaEventTextInput event.
+        In the Carbon event model, convert the string to individual key codes and send them
+        as key down events.
+
+        * WebProcess/Plugins/PluginProxy.cpp:
+        (WebKit::PluginProxy::sendComplexTextInput):
+        Send the text to the plug-in controller proxy.
+
+        * WebProcess/Plugins/PluginView.cpp:
+        (WebKit::PluginView::sendComplexTextInput):
+        If the plug-in has a matching text input identifier, call Plugin::sendComplexTextInput.
+
+        * WebProcess/WebPage/WebPage.messages.in:
+        Add SendComplexTextInputToPlugin message.
+
+        * WebProcess/WebPage/mac/WebPageMac.mm:
+        (WebKit::WebPage::sendComplexTextInputToPlugin):
+        Iterate over all known plug-in views and try to find one to send the text input to.
+
 2010-12-13  Alexey Proskuryakov  <ap@apple.com>
 
         Reviewed by Adam Barth.
index 352e1ad..af77391 100644 (file)
@@ -416,6 +416,12 @@ void PluginControllerProxy::windowVisibilityChanged(bool isVisible)
 {
     m_plugin->windowVisibilityChanged(isVisible);
 }
+
+void PluginControllerProxy::sendComplexTextInput(const String& textInput)
+{
+    m_plugin->sendComplexTextInput(textInput);
+}
+
 #endif
 
 void PluginControllerProxy::privateBrowsingStateChanged(bool isPrivateBrowsingEnabled)
index 62f59c6..1ab2ca6 100644 (file)
@@ -124,7 +124,9 @@ private:
     void windowFocusChanged(bool);
     void windowAndViewFramesChanged(const WebCore::IntRect& windowFrameInScreenCoordinates, const WebCore::IntRect& viewFrameInWindowCoordinates);
     void windowVisibilityChanged(bool);
+    void sendComplexTextInput(const String& textInput);
 #endif
+
     void privateBrowsingStateChanged(bool);
 
     void platformInitialize();
index b3727aa..60fd3df 100644 (file)
@@ -86,6 +86,9 @@ messages -> PluginControllerProxy {
     # Get a reference to the plug-in's scriptable NPObject.
     GetPluginScriptableNPObject() -> (uint64_t pluginScriptableNPObjectID)
 
+    # Send the complex text input to the plug-in.
+    SendComplexTextInput(WTF::String textInput)
+
 #if PLATFORM(MAC)
     # Sent when the containing NSWindow's focus changes
     WindowFocusChanged(bool hasFocus)
diff --git a/WebKit2/UIProcess/API/mac/WKTextInputWindowController.h b/WebKit2/UIProcess/API/mac/WKTextInputWindowController.h
new file mode 100644 (file)
index 0000000..b2ad3b0
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2009, 2010 Apple Inc. All Rights Reserved.
+ *
+ * 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. ``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
+ * 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 WKTextInputWindowController_h
+#define WKTextInputWindowController_h
+
+@class WKTextInputPanel;
+
+@interface WKTextInputWindowController : NSObject {
+    WKTextInputPanel *_panel;
+}
+
++ (WKTextInputWindowController *)sharedTextInputWindowController;
+
+- (NSTextInputContext *)inputContext;
+- (BOOL)interpretKeyEvent:(NSEvent *)event string:(NSString **)string;
+
+- (void)keyboardInputSourceChanged;
+
+@end
+
+#endif // WKTextInputWindowController_h
diff --git a/WebKit2/UIProcess/API/mac/WKTextInputWindowController.mm b/WebKit2/UIProcess/API/mac/WKTextInputWindowController.mm
new file mode 100644 (file)
index 0000000..b7dae31
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * 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 "WKTextInputWindowController.h"
+
+#include <WebKitSystemInterface.h>
+
+@interface WKTextInputPanel : NSPanel {
+    NSTextView *_inputTextView;
+}
+
+- (NSTextInputContext *)_inputContext;
+- (BOOL)_interpretKeyEvent:(NSEvent *)event string:(NSString **)string;
+
+@end
+
+#define inputWindowHeight 20
+
+@implementation WKTextInputPanel
+
+- (void)dealloc
+{
+    [[NSNotificationCenter defaultCenter] removeObserver:self];
+    
+    [_inputTextView release];
+    
+    [super dealloc];
+}
+
+- (id)init
+{
+    self = [super initWithContentRect:NSZeroRect styleMask:WKGetInputPanelWindowStyle() backing:NSBackingStoreBuffered defer:YES];
+    if (!self)
+        return nil;
+    
+    // Set the frame size.
+    NSRect visibleFrame = [[NSScreen mainScreen] visibleFrame];
+    NSRect frame = NSMakeRect(visibleFrame.origin.x, visibleFrame.origin.y, visibleFrame.size.width, inputWindowHeight);
+     
+    [self setFrame:frame display:NO];
+        
+    _inputTextView = [[NSTextView alloc] initWithFrame:[self.contentView frame]];        
+    _inputTextView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable | NSViewMaxXMargin | NSViewMinXMargin | NSViewMaxYMargin | NSViewMinYMargin;
+        
+    NSScrollView* scrollView = [[NSScrollView alloc] initWithFrame:[self.contentView frame]];
+    scrollView.documentView = _inputTextView;
+    self.contentView = scrollView;
+    [scrollView release];
+        
+    [self setFloatingPanel:YES];
+
+    return self;
+}
+
+- (void)_keyboardInputSourceChanged
+{
+    [_inputTextView setString:@""];
+    [self orderOut:nil];
+}
+
+- (BOOL)_interpretKeyEvent:(NSEvent *)event string:(NSString **)string
+{
+    BOOL hadMarkedText = [_inputTextView hasMarkedText];
+    *string = nil;
+    
+    if (![[_inputTextView inputContext] handleEvent:event])
+        return NO;
+    
+    if ([_inputTextView hasMarkedText]) {
+        // Don't show the input method window for dead keys
+        if ([[event characters] length] > 0)
+            [self orderFront:nil];
+
+        return YES;
+    }
+    
+    if (hadMarkedText) {
+        [self orderOut:nil];
+
+        NSString *text = [[_inputTextView textStorage] string];
+        if ([text length] > 0)
+            *string = [[text copy] autorelease];
+    }
+            
+    [_inputTextView setString:@""];
+    return hadMarkedText;
+}
+
+- (NSTextInputContext *)_inputContext
+{
+    return [_inputTextView inputContext];
+}
+
+@end
+
+@implementation WKTextInputWindowController
+
++ (WKTextInputWindowController *)sharedTextInputWindowController
+{
+    static WKTextInputWindowController *textInputWindowController;
+    if (!textInputWindowController)
+        textInputWindowController = [[WKTextInputWindowController alloc] init];
+    
+    return textInputWindowController;
+}
+
+- (id)init
+{
+    self = [super init];
+    if (!self)
+        return nil;
+    
+    _panel = [[WKTextInputPanel alloc] init];
+    
+    return self;
+}
+
+- (NSTextInputContext *)inputContext
+{
+    return [_panel _inputContext];
+}
+
+- (BOOL)interpretKeyEvent:(NSEvent *)event string:(NSString **)string
+{
+    return [_panel _interpretKeyEvent:event string:string];
+}
+
+- (void)keyboardInputSourceChanged
+{
+    [_panel _keyboardInputSourceChanged];
+}
+
+@end
index 88be06b..3618152 100644 (file)
@@ -38,6 +38,7 @@
 #import "PDFViewController.h"
 #import "PageClientImpl.h"
 #import "RunLoop.h"
+#import "WKTextInputWindowController.h"
 #import "WebContext.h"
 #import "WebEventFactory.h"
 #import "WebPage.h"
@@ -523,6 +524,16 @@ MOUSE_EVENT_HANDLER(mouseUp)
 
 - (void)keyDown:(NSEvent *)theEvent
 {
+    if (_data->_pluginComplexTextInputIdentifier) {
+        // Try feeding the keyboard event directly to the plug-in.
+        NSString *string = nil;
+        if ([[WKTextInputWindowController sharedTextInputWindowController] interpretKeyEvent:theEvent string:&string]) {
+            if (string)
+                _data->_page->sendComplexTextInputToPlugin(_data->_pluginComplexTextInputIdentifier, string);
+            return;
+        }
+    }
+
     _data->_underlines.clear();
     _data->_selectionStart = 0;
     _data->_selectionEnd = 0;
@@ -539,6 +550,13 @@ MOUSE_EVENT_HANDLER(mouseUp)
     _data->_page->handleKeyboardEvent(NativeWebKeyboardEvent(theEvent, self));
 }
 
+- (NSTextInputContext *)inputContext {
+    if (_data->_pluginComplexTextInputIdentifier)
+        return [[WKTextInputWindowController sharedTextInputWindowController] inputContext];
+
+    return [super inputContext];
+}
+
 - (NSRange)selectedRange
 {
     if (_data->_isSelectionNone || !_data->_isSelectionEditable)
@@ -1173,6 +1191,7 @@ static bool isViewVisible(NSView *view)
 
     if (inputSourceChanged) {
         // Inform the out of line window that the input source changed.
+        [[WKTextInputWindowController sharedTextInputWindowController] keyboardInputSourceChanged];
     }
 }
 
index 23da8a7..a3f2fea 100644 (file)
@@ -1319,12 +1319,22 @@ void WebPageProxy::backForwardForwardListCount(int32_t& count)
     count = m_backForwardList->forwardListCount();
 }
 
-// Selection change support
 #if PLATFORM(MAC)
+// Selection change support
 void WebPageProxy::didSelectionChange(bool isNone, bool isContentEditable, bool isPasswordField, bool hasComposition, uint64_t location, uint64_t length)
 {
     m_pageClient->selectionChanged(isNone, isContentEditable, isPasswordField, hasComposition, location, length);
 }
+
+// Complex text input support for plug-ins.
+void WebPageProxy::sendComplexTextInputToPlugin(uint64_t pluginComplexTextInputIdentifier, const String& textInput)
+{
+    if (!isValid())
+        return;
+    
+    process()->send(Messages::WebPage::SendComplexTextInputToPlugin(pluginComplexTextInputIdentifier, textInput), m_pageID);
+}
+    
 #else    
 void WebPageProxy::didSelectionChange(bool isNone, bool isContentEditable, bool isPasswordField, bool hasComposition)
 {
index 223e54b..d8f0cb2 100644 (file)
@@ -178,6 +178,9 @@ public:
     uint64_t characterIndexForPoint(const WebCore::IntPoint);
     WebCore::IntRect firstRectForCharacterRange(uint64_t, uint64_t);
     void didSelectionChange(bool, bool, bool, bool, uint64_t, uint64_t);
+
+    void sendComplexTextInputToPlugin(uint64_t pluginComplexTextInputIdentifier, const String& textInput);
+
 #else
     void didSelectionChange(bool, bool, bool, bool);
 #endif
index 99990b1..16feb0f 100644 (file)
                1A3E736111CC2659007BD539 /* WebPlatformStrategies.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A3E735F11CC2659007BD539 /* WebPlatformStrategies.h */; };
                1A3E736211CC2659007BD539 /* WebPlatformStrategies.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A3E736011CC2659007BD539 /* WebPlatformStrategies.cpp */; };
                1A433F0D113C53DD00FACDE9 /* WebErrors.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A433F0C113C53DD00FACDE9 /* WebErrors.h */; };
+               1A4A9AA812B7E796008FE984 /* WKTextInputWindowController.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A4A9AA612B7E796008FE984 /* WKTextInputWindowController.h */; };
+               1A4A9AA912B7E796008FE984 /* WKTextInputWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1A4A9AA712B7E796008FE984 /* WKTextInputWindowController.mm */; };
                1A50DB66110A3D57000D3FE5 /* WebProcess.app in CopyFiles */ = {isa = PBXBuildFile; fileRef = 1A50DB1E110A3BDC000D3FE5 /* WebProcess.app */; };
                1A594ABA112A1FB6009DE7C7 /* WebUIClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A594AB8112A1FB6009DE7C7 /* WebUIClient.cpp */; };
                1A594ABB112A1FB6009DE7C7 /* WebUIClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A594AB9112A1FB6009DE7C7 /* WebUIClient.h */; };
                1A3E735F11CC2659007BD539 /* WebPlatformStrategies.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebPlatformStrategies.h; sourceTree = "<group>"; };
                1A3E736011CC2659007BD539 /* WebPlatformStrategies.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebPlatformStrategies.cpp; sourceTree = "<group>"; };
                1A433F0C113C53DD00FACDE9 /* WebErrors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebErrors.h; sourceTree = "<group>"; };
+               1A4A9AA612B7E796008FE984 /* WKTextInputWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKTextInputWindowController.h; sourceTree = "<group>"; };
+               1A4A9AA712B7E796008FE984 /* WKTextInputWindowController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKTextInputWindowController.mm; sourceTree = "<group>"; };
                1A4F976A100E7B6600637A18 /* Base.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Base.xcconfig; sourceTree = "<group>"; };
                1A4F976B100E7B6600637A18 /* DebugRelease.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = DebugRelease.xcconfig; sourceTree = "<group>"; };
                1A4F976C100E7B6600637A18 /* FeatureDefines.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = FeatureDefines.xcconfig; sourceTree = "<group>"; };
                                1AAF061312B01131008E49E2 /* PDFViewController.mm */,
                                BC111B4B112F619200337BAB /* PageClientImpl.h */,
                                BC111B4C112F619200337BAB /* PageClientImpl.mm */,
+                               1A4A9AA612B7E796008FE984 /* WKTextInputWindowController.h */,
+                               1A4A9AA712B7E796008FE984 /* WKTextInputWindowController.mm */,
                                BC8699B2116AADAA002A925B /* WKView.h */,
                                BC8699B3116AADAA002A925B /* WKView.mm */,
                                BC8699B4116AADAA002A925B /* WKViewInternal.h */,
                                F62A766212B1ABED0005F1B6 /* WKDatabaseManager.h in Headers */,
                                F62A76B712B1B25F0005F1B6 /* WebDatabaseManagerMessages.h in Headers */,
                                F62A76B912B1B25F0005F1B6 /* WebDatabaseManagerProxyMessages.h in Headers */,
+                               1A4A9AA812B7E796008FE984 /* WKTextInputWindowController.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                F62A76B612B1B25F0005F1B6 /* WebDatabaseManagerMessageReceiver.cpp in Sources */,
                                F62A76B812B1B25F0005F1B6 /* WebDatabaseManagerProxyMessageReceiver.cpp in Sources */,
                                BC857E8712B71EBB00EDEB2E /* WebPageProxyMac.mm in Sources */,
+                               1A4A9AA912B7E796008FE984 /* WKTextInputWindowController.mm in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index 29e71d1..c83dc15 100644 (file)
@@ -163,6 +163,7 @@ private:
     virtual void windowVisibilityChanged(bool);
 
     virtual uint64_t pluginComplexTextInputIdentifier() const;
+    virtual void sendComplexTextInput(const String& textInput);
 #endif
 
     virtual void privateBrowsingStateChanged(bool);
index 0cd4e5b..add76c3 100644 (file)
@@ -28,6 +28,8 @@
 #include "PluginController.h"
 #include "WebEvent.h"
 #include <WebCore/GraphicsContext.h>
+#include <Carbon/Carbon.h>
+#include <WebKitSystemInterface.h>
 
 using namespace WebCore;
 
@@ -717,6 +719,79 @@ uint64_t NetscapePlugin::pluginComplexTextInputIdentifier() const
     return 0;
 }
 
+
+#ifndef NP_NO_CARBON
+static bool convertStringToKeyCodes(const String& string, ScriptCode scriptCode, Vector<UInt8>& keyCodes)
+{
+    // Create the mapping.
+    UnicodeMapping mapping;
+
+    if (GetTextEncodingFromScriptInfo(scriptCode, kTextLanguageDontCare, kTextRegionDontCare, &mapping.otherEncoding) != noErr)
+        return false;
+
+    mapping.unicodeEncoding = CreateTextEncoding(kTextEncodingUnicodeDefault, kTextEncodingDefaultVariant, kTextEncodingDefaultFormat);
+    mapping.mappingVersion = kUnicodeUseLatestMapping;
+    
+    // Create the converter
+    UnicodeToTextInfo textInfo;
+    
+    if (CreateUnicodeToTextInfo(&mapping, &textInfo) != noErr)
+        return false;
+    
+    ByteCount inputLength = string.length() * sizeof(UniChar);
+    ByteCount inputRead;
+    ByteCount outputLength;
+    ByteCount maxOutputLength = string.length() * sizeof(UniChar);
+
+    Vector<UInt8> outputData(maxOutputLength);
+    OSStatus status = ConvertFromUnicodeToText(textInfo, inputLength, string.characters(), kNilOptions, 0, 0, 0, 0, maxOutputLength, &inputRead, &outputLength, outputData.data());
+    
+    DisposeUnicodeToTextInfo(&textInfo);
+    
+    if (status != noErr)
+        return false;
+
+    outputData.swap(keyCodes);
+    return true;
+}
+#endif
+
+void NetscapePlugin::sendComplexTextInput(const String& textInput)
+{
+    switch (m_eventModel) {
+    case NPEventModelCocoa: {
+        NPCocoaEvent event = initializeEvent(NPCocoaEventTextInput);
+        event.data.text.text = reinterpret_cast<NPNSString*>(static_cast<NSString*>(textInput));
+        NPP_HandleEvent(&event);
+        break;
+    }
+#ifndef NP_NO_CARBON
+    case NPEventModelCarbon: {
+        ScriptCode scriptCode = WKGetScriptCodeFromCurrentKeyboardInputSource();
+        Vector<UInt8> keyCodes;
+
+        if (!convertStringToKeyCodes(textInput, scriptCode, keyCodes))
+            return;
+
+        // Set the script code as the keyboard script. Normally Carbon does this whenever the input source changes.
+        // However, this is only done for the process that has the keyboard focus. We cheat and do it here instead.
+        SetScriptManagerVariable(smKeyScript, scriptCode);
+        
+        EventRecord event = initializeEventRecord(keyDown);
+        event.modifiers = 0;
+
+        for (size_t i = 0; i < keyCodes.size(); i++) {
+            event.message = keyCodes[i];
+            NPP_HandleEvent(&event);
+        }
+        break;
+    }
+#endif
+    default:
+        ASSERT_NOT_REACHED();
+    }
+}
+
 PlatformLayer* NetscapePlugin::pluginLayer()
 {
     return static_cast<PlatformLayer*>(m_pluginLayer.get());
index 57b0d91..6f20159 100644 (file)
@@ -153,6 +153,9 @@ public:
 
     // Get the per complex text input identifier.
     virtual uint64_t pluginComplexTextInputIdentifier() const = 0;
+
+    // Send the complex text input to the plug-in.
+    virtual void sendComplexTextInput(const String& textInput) = 0;
 #endif
 
     // Called when the private browsing state for this plug-in changes.
index 31db464..3caedf8 100644 (file)
@@ -323,6 +323,11 @@ uint64_t PluginProxy::pluginComplexTextInputIdentifier() const
     return m_pluginInstanceID;
 }
 
+void PluginProxy::sendComplexTextInput(const String& textInput)
+{
+    m_connection->connection()->send(Messages::PluginControllerProxy::SendComplexTextInput(textInput), m_pluginInstanceID);
+}
+
 #endif
 
 void PluginProxy::privateBrowsingStateChanged(bool isPrivateBrowsingEnabled)
index a2b65d0..0432331 100644 (file)
@@ -96,6 +96,7 @@ private:
     virtual void windowAndViewFramesChanged(const WebCore::IntRect& windowFrameInScreenCoordinates, const WebCore::IntRect& viewFrameInWindowCoordinates);
     virtual void windowVisibilityChanged(bool);
     virtual uint64_t pluginComplexTextInputIdentifier() const;
+    virtual void sendComplexTextInput(const String& textInput);
 #endif
 
     virtual void privateBrowsingStateChanged(bool);
index c12b414..9d39fa3 100644 (file)
@@ -362,6 +362,18 @@ void PluginView::windowAndViewFramesChanged(const IntRect& windowFrameInScreenCo
     m_plugin->windowAndViewFramesChanged(windowFrameInScreenCoordinates, viewFrameInWindowCoordinates);
 }
 
+bool PluginView::sendComplexTextInput(uint64_t pluginComplexTextInputIdentifier, const String& textInput)
+{
+    if (!m_plugin)
+        return false;
+
+    if (m_plugin->pluginComplexTextInputIdentifier() != pluginComplexTextInputIdentifier)
+        return false;
+
+    m_plugin->sendComplexTextInput(textInput);
+    return true;
+}
+
 #endif
 
 void PluginView::initializePlugin()
index 8929dbc..9281385 100644 (file)
@@ -62,6 +62,7 @@ public:
     void setWindowIsVisible(bool);
     void setWindowIsFocused(bool);
     void windowAndViewFramesChanged(const WebCore::IntRect& windowFrameInScreenCoordinates, const WebCore::IntRect& viewFrameInWindowCoordinates);
+    bool sendComplexTextInput(uint64_t pluginComplexTextInputIdentifier, const String& textInput);
 #endif
 
 private:
index b8f364d..eef827f 100644 (file)
@@ -239,7 +239,10 @@ public:
     };
 
     SandboxExtensionTracker& sandboxExtensionTracker() { return m_sandboxExtensionTracker; }
+    
 #if PLATFORM(MAC)
+    void sendComplexTextInputToPlugin(uint64_t pluginComplexTextInputIdentifier, const String& textInput);
+
     void getMarkedRange(uint64_t& location, uint64_t& length);
     void characterIndexForPoint(const WebCore::IntPoint point, uint64_t& result);
     void firstRectForCharacterRange(uint64_t location, uint64_t length, WebCore::IntRect& resultRect);
index 6d63f71..01c279a 100644 (file)
@@ -94,6 +94,9 @@ messages -> WebPage {
     SetWindowResizerSize(WebCore::IntSize intersectsView)
 
 #if PLATFORM(MAC)
+    # Complex text input support for plug-ins.
+    SendComplexTextInputToPlugin(uint64_t pluginComplexTextInputIdentifier, String textInput)
+
     SetWindowIsVisible(bool windowIsVisible)
     WindowAndViewFramesChanged(WebCore::IntRect windowFrameInScreenCoordinates, WebCore::IntRect viewFrameInWindowCoordinates)
     GetMarkedRange() -> (uint64_t location, uint64_t length)
index 1e80522..7bb3115 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "WebPage.h"
 
+#include "PluginView.h"
 #include "WebCoreArgumentCoders.h"
 #include "WebEvent.h"
 #include "WebPageProxyMessages.h"
@@ -151,7 +152,15 @@ void WebPage::convertRangeToPlatformRange(WebCore::Frame* frame, WebCore::Range
     ASSERT(testRange->startContainer() == scope);
     length = TextIterator::rangeLength(testRange.get()) - location;
 }
-    
+
+void WebPage::sendComplexTextInputToPlugin(uint64_t pluginComplexTextInputIdentifier, const String& textInput)
+{
+    for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it) {
+        if ((*it)->sendComplexTextInput(pluginComplexTextInputIdentifier, textInput))
+            break;
+    }
+}
+
 void WebPage::getMarkedRange(uint64_t& location, uint64_t& length)
 {
     location = NSNotFound;