Add support for Cocoa NPAPI complex text input. This patch contains a TSM-based implementation for 32-bit builds, and an NSInputContext-based implementation for 64-bit builds. b=512886 r=smichaud sr=jst

This commit is contained in:
Josh Aas 2010-06-09 20:56:17 -04:00
Родитель 8c6be1cd28
Коммит d5610f20b4
10 изменённых файлов: 369 добавлений и 85 удалений

Просмотреть файл

@ -1730,9 +1730,7 @@ nsObjectFrame::PaintPlugin(nsIRenderingContext& aRenderingContext,
pluginEvent.event = mDoublePassEvent;
pluginEvent.wParam = 0;
pluginEvent.lParam = 0;
PRBool eventHandled = PR_FALSE;
inst->HandleEvent(&pluginEvent, &eventHandled);
inst->HandleEvent(&pluginEvent, nsnull);
}
}
#endif
@ -1793,9 +1791,7 @@ nsObjectFrame::PaintPlugin(nsIRenderingContext& aRenderingContext,
pluginEvent.event = WM_WINDOWPOSCHANGED;
pluginEvent.wParam = 0;
pluginEvent.lParam = (uint32)&winpos;
PRBool eventHandled = PR_FALSE;
inst->HandleEvent(&pluginEvent, &eventHandled);
inst->HandleEvent(&pluginEvent, nsnull);
}
inst->SetWindow(window);
@ -3797,8 +3793,7 @@ void nsPluginInstanceOwner::ScrollPositionWillChange(nscoord aX, nscoord aY)
void* window = FixUpPluginWindow(ePluginPaintDisable);
if (window) {
PRBool eventHandled = PR_FALSE;
mInstance->HandleEvent(&scrollEvent, &eventHandled);
mInstance->HandleEvent(&scrollEvent, nsnull);
}
pluginWidget->EndDrawPlugin();
}
@ -3821,8 +3816,7 @@ void nsPluginInstanceOwner::ScrollPositionDidChange(nscoord aX, nscoord aY)
void* window = FixUpPluginWindow(ePluginPaintEnable);
if (window) {
PRBool eventHandled = PR_FALSE;
mInstance->HandleEvent(&scrollEvent, &eventHandled);
mInstance->HandleEvent(&scrollEvent, nsnull);
}
pluginWidget->EndDrawPlugin();
}
@ -4415,9 +4409,9 @@ nsEventStatus nsPluginInstanceOwner::ProcessEventX11Composited(const nsGUIEvent&
#if 0
/* we've sent the event via XSendEvent so don't send it directly to the plugin */
PRBool eventHandled = PR_FALSE;
mInstance->HandleEvent(&pluginEvent, &eventHandled);
if (eventHandled)
PRInt16 response = kNPEventNotHandled;
mInstance->HandleEvent(&pluginEvent, &response);
if (response == kNPEventHandled)
rv = nsEventStatus_eConsumeNoDefault;
#endif
@ -4578,13 +4572,17 @@ nsEventStatus nsPluginInstanceOwner::ProcessEvent(const nsGUIEvent& anEvent)
::DeactivateTSMDocument(::TSMGetActiveDocument());
#endif
PRBool eventHandled = PR_FALSE;
PRInt16 response = kNPEventNotHandled;
void* window = FixUpPluginWindow(ePluginPaintEnable);
if (window || (eventModel == NPEventModelCocoa)) {
mInstance->HandleEvent(event, &eventHandled);
mInstance->HandleEvent(event, &response);
}
if (eventHandled &&
if (eventModel == NPEventModelCocoa && response == kNPEventStartIME) {
pluginWidget->StartComplexTextInputForCurrentEvent();
}
if ((response == kNPEventHandled || response == kNPEventStartIME) &&
!(anEvent.eventStructType == NS_MOUSE_EVENT &&
anEvent.message == NS_MOUSE_BUTTON_DOWN &&
static_cast<const nsMouseEvent&>(anEvent).button == nsMouseEvent::eLeftButton &&
@ -4692,9 +4690,9 @@ nsEventStatus nsPluginInstanceOwner::ProcessEvent(const nsGUIEvent& anEvent)
}
if (pPluginEvent) {
PRBool eventHandled = PR_FALSE;
mInstance->HandleEvent(pPluginEvent, &eventHandled);
if (eventHandled)
PRInt16 response = kNPEventNotHandled;
mInstance->HandleEvent(pPluginEvent, &response);
if (response == kNPEventHandled)
rv = nsEventStatus_eConsumeNoDefault;
}
#endif
@ -4893,10 +4891,10 @@ nsEventStatus nsPluginInstanceOwner::ProcessEvent(const nsGUIEvent& anEvent)
event.serial = 0;
event.send_event = False;
PRBool eventHandled = PR_FALSE;
mInstance->HandleEvent(&pluginEvent, &eventHandled);
if (eventHandled)
rv = nsEventStatus_eConsumeNoDefault;
PRInt16 response = kNPEventNotHandled;
mInstance->HandleEvent(&pluginEvent, &response);
if (response == kNPEventHandled)
rv = nsEventStatus_eConsumeNoDefault;
#endif
return rv;
@ -5019,8 +5017,7 @@ void nsPluginInstanceOwner::Paint(const gfxRect& aDirtyRect, CGContextRef cgCont
updateEvent.what = updateEvt;
updateEvent.message = UInt32(window);
PRBool eventHandled = PR_FALSE;
mInstance->HandleEvent(&updateEvent, &eventHandled);
mInstance->HandleEvent(&updateEvent, nsnull);
} else if (GetEventModel() == NPEventModelCocoa)
#endif
{
@ -5034,8 +5031,7 @@ void nsPluginInstanceOwner::Paint(const gfxRect& aDirtyRect, CGContextRef cgCont
updateEvent.data.draw.width = aDirtyRect.Width();
updateEvent.data.draw.height = aDirtyRect.Height();
PRBool eventHandled = PR_FALSE;
mInstance->HandleEvent(&updateEvent, &eventHandled);
mInstance->HandleEvent(&updateEvent, nsnull);
}
pluginWidget->EndDrawPlugin();
}
@ -5052,8 +5048,7 @@ void nsPluginInstanceOwner::Paint(const RECT& aDirty, HDC aDC)
pluginEvent.event = WM_PAINT;
pluginEvent.wParam = WPARAM(aDC);
pluginEvent.lParam = LPARAM(&aDirty);
PRBool eventHandled = PR_FALSE;
mInstance->HandleEvent(&pluginEvent, &eventHandled);
mInstance->HandleEvent(&pluginEvent, nsnull);
}
#endif
@ -5079,9 +5074,7 @@ void nsPluginInstanceOwner::Paint(const nsRect& aDirtyRect, HPS aHPS)
pluginEvent.event = WM_PAINT;
pluginEvent.wParam = (uint32)aHPS;
pluginEvent.lParam = (uint32)&rectl;
PRBool eventHandled = PR_FALSE;
mInstance->HandleEvent(&pluginEvent, &eventHandled);
mInstance->HandleEvent(&pluginEvent, nsnull);
}
#endif
@ -5420,10 +5413,9 @@ nsPluginInstanceOwner::NativeImageDraw(NPRect* invalidRect)
if (invalidRect)
memset(mSharedXImage->data, 0, mPluginSize.width * mPluginSize.height * 2);
PRBool eventHandled = PR_FALSE;
mInstance->HandleEvent(&pluginEvent, &eventHandled);
if (!eventHandled)
PRInt16 response = kNPEventNotHandled;
mInstance->HandleEvent(&pluginEvent, &response);
if (response == kNPEventNotHandled)
return;
// Setup the clip rectangle
@ -5600,8 +5592,7 @@ nsPluginInstanceOwner::Renderer::NativeDraw(gfxXlibSurface * xsurface,
exposeEvent.major_code = 0;
exposeEvent.minor_code = 0;
PRBool eventHandled = PR_FALSE;
mInstance->HandleEvent(&pluginEvent, &eventHandled);
mInstance->HandleEvent(&pluginEvent, nsnull);
#ifdef MOZ_COMPOSITED_PLUGINS
}
else {
@ -5654,8 +5645,7 @@ void nsPluginInstanceOwner::SendIdleEvent()
if (!mWidgetVisible)
idleEvent.where.h = idleEvent.where.v = 20000;
PRBool eventHandled = PR_FALSE;
mInstance->HandleEvent(&idleEvent, &eventHandled);
mInstance->HandleEvent(&idleEvent, nsnull);
}
pluginWidget->EndDrawPlugin();
@ -5879,13 +5869,12 @@ PRBool nsPluginInstanceOwner::UpdateVisibility(PRBool aVisible)
if (!mInstance)
return PR_TRUE;
PRBool handled;
NPEvent pluginEvent;
XVisibilityEvent& visibilityEvent = pluginEvent.xvisibility;
visibilityEvent.type = VisibilityNotify;
visibilityEvent.display = 0;
visibilityEvent.state = aVisible ? VisibilityUnobscured : VisibilityFullyObscured;
mInstance->HandleEvent(&pluginEvent, &handled);
mInstance->HandleEvent(&pluginEvent, nsnull);
mWidgetVisible = PR_TRUE;
return PR_TRUE;

Просмотреть файл

@ -53,7 +53,7 @@ struct JSObject;
[ptr] native JSContextPtr(JSContext);
[ptr] native JSObjectPtr(JSObject);
[uuid(3B091A81-D15A-4645-83B3-AC0C68A776DB)]
[uuid(84994340-E120-4051-824F-D4EE8AEF1A3E)]
interface nsIPluginInstance : nsISupports
{
/**
@ -144,10 +144,11 @@ interface nsIPluginInstance : nsISupports
* (Corresponds to NPP_HandleEvent.)
*
* @param aEvent - the event to be handled
* @param aHandled - set to PR_TRUE if event was handled
* @param aHandled - if non-NULL, set to the NPAPI NPP_HandleEvent
* return value
* @result - NS_OK if this operation was successful
*/
void handleEvent(in voidPtr aEvent, out boolean aHandled);
void handleEvent(in voidPtr aEvent, out PRInt16 aHandled);
/**
* Corresponds to NPN_InvalidateRect

Просмотреть файл

@ -1360,7 +1360,7 @@ NS_IMETHODIMP nsNPAPIPluginInstance::Print(NPPrint* platformPrint)
return NS_OK;
}
NS_IMETHODIMP nsNPAPIPluginInstance::HandleEvent(void* event, PRBool* handled)
NS_IMETHODIMP nsNPAPIPluginInstance::HandleEvent(void* event, PRInt16* result)
{
if (RUNNING != mRunning)
return NS_OK;
@ -1370,20 +1370,21 @@ NS_IMETHODIMP nsNPAPIPluginInstance::HandleEvent(void* event, PRBool* handled)
PluginDestructionGuard guard(this);
PRInt16 result = 0;
PRInt16 tmpResult = kNPEventNotHandled;
if (mCallbacks->event) {
mCurrentPluginEvent = event;
#if defined(XP_WIN) || defined(XP_OS2)
NS_TRY_SAFE_CALL_RETURN(result, (*mCallbacks->event)(&mNPP, event), mLibrary, this);
NS_TRY_SAFE_CALL_RETURN(tmpResult, (*mCallbacks->event)(&mNPP, event), mLibrary, this);
#else
result = (*mCallbacks->event)(&mNPP, event);
tmpResult = (*mCallbacks->event)(&mNPP, event);
#endif
NPP_PLUGIN_LOG(PLUGIN_LOG_NOISY,
("NPP HandleEvent called: this=%p, npp=%p, event=%p, return=%d\n",
this, &mNPP, event, result));
this, &mNPP, event, tmpResult));
*handled = result;
if (result)
*result = tmpResult;
mCurrentPluginEvent = nsnull;
}

Просмотреть файл

@ -1946,7 +1946,7 @@ necessary. Here is a sample; alter the names:
<h1><a name="apple"></a>Apple License</h1>
<p class="correctme">This license applies to certain files in the directories <span class="path">js/src/assembler/assembler/</span> and <span class="path">js/src/assembler/wtf/</span>.</p>
<p class="correctme">This license applies to certain files in the directories <span class="path">js/src/assembler/assembler/</span>, <span class="path">js/src/assembler/wtf/</span>, and <span class="path">widget/src/cocoa</span>.</p>
<pre>
Copyright (C) 2008, 2009 Apple Inc. All rights reserved.

Просмотреть файл

@ -37,12 +37,9 @@
#include "nsISupports.h"
/* starting interface: nsIPluginWidget */
#define NS_IPLUGINWIDGET_IID_STR "034E8A7E-BE36-4039-B229-39C41E9D4CD2"
#define NS_IPLUGINWIDGET_IID \
{ 0x034E8A7E, 0xBE36, 0x4039, \
{ 0xB2, 0x29, 0x39, 0xC4, 0x1E, 0x9D, 0x4C, 0xD2 } }
{ 0xEB9207E0, 0xD8F1, 0x44B9, \
{ 0xB7, 0x52, 0xAF, 0x8E, 0x9F, 0x8E, 0xBD, 0xF7 } }
struct nsIntPoint;
class nsIPluginInstanceOwner;
@ -64,6 +61,8 @@ class NS_NO_VTABLE nsIPluginWidget : public nsISupports
NS_IMETHOD SetPluginEventModel(int inEventModel) = 0;
NS_IMETHOD GetPluginEventModel(int* outEventModel) = 0;
NS_IMETHOD StartComplexTextInputForCurrentEvent() = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIPluginWidget, NS_IPLUGINWIDGET_IID)

Просмотреть файл

@ -0,0 +1,44 @@
/*
* Copyright (C) 2009 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.
*
* Modified by Josh Aas of Mozilla Corporation.
*/
#ifndef ComplexTextInputPanel_h_
#define ComplexTextInputPanel_h_
#import <Cocoa/Cocoa.h>
@interface ComplexTextInputPanel : NSPanel {
NSTextView *mInputTextView;
}
+ (ComplexTextInputPanel*)sharedComplexTextInputPanel;
- (NSTextInputContext*)inputContext;
- (BOOL)interpretKeyEvent:(NSEvent*)event string:(NSString**)string;
@end
#endif // ComplexTextInputPanel_h_

Просмотреть файл

@ -0,0 +1,122 @@
/*
* Copyright (C) 2009 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.
*
* Modified by Josh Aas of Mozilla Corporation.
*/
#import "ComplexTextInputPanel.h"
#define kInputWindowHeight 20
@implementation ComplexTextInputPanel
+ (ComplexTextInputPanel*)sharedComplexTextInputPanel
{
static ComplexTextInputPanel *sComplexTextInputPanel;
if (!sComplexTextInputPanel)
sComplexTextInputPanel = [[ComplexTextInputPanel alloc] init];
return sComplexTextInputPanel;
}
- (id)init
{
// In the original Apple code the style mask is given by a function which is not open source.
// What could possibly be worth hiding in that function, I do not know.
// Courtesy of gdb: stylemask: 011000011111, 0x61f
self = [super initWithContentRect:NSZeroRect styleMask:0x61f 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, kInputWindowHeight);
[self setFrame:frame display:NO];
mInputTextView = [[NSTextView alloc] initWithFrame:[self.contentView frame]];
mInputTextView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable | NSViewMaxXMargin | NSViewMinXMargin | NSViewMaxYMargin | NSViewMinYMargin;
NSScrollView* scrollView = [[NSScrollView alloc] initWithFrame:[self.contentView frame]];
scrollView.documentView = mInputTextView;
self.contentView = scrollView;
[scrollView release];
[self setFloatingPanel:YES];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardInputSourceChanged:)
name:NSTextInputContextKeyboardSelectionDidChangeNotification
object:nil];
return self;
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
[mInputTextView release];
[super dealloc];
}
- (void)keyboardInputSourceChanged:(NSNotification *)notification
{
[mInputTextView setString:@""];
[self orderOut:nil];
}
- (BOOL)interpretKeyEvent:(NSEvent*)event string:(NSString**)string
{
BOOL hadMarkedText = [mInputTextView hasMarkedText];
*string = nil;
if (![[mInputTextView inputContext] handleEvent:event])
return NO;
if ([mInputTextView hasMarkedText]) {
// Don't show the input method window for dead keys
if ([[event characters] length] > 0)
[self orderFront:nil];
return YES;
} else {
[self orderOut:nil];
NSString *text = [[mInputTextView textStorage] string];
if ([text length] > 0)
*string = [[text copy] autorelease];
}
[mInputTextView setString:@""];
return hadMarkedText;
}
- (NSTextInputContext*)inputContext
{
return [mInputTextView inputContext];
}
@end

Просмотреть файл

@ -94,6 +94,10 @@ CMMSRCS = \
nsStandaloneNativeMenu.mm \
$(NULL)
ifeq (x86_64,$(TARGET_CPU))
CMMSRCS += ComplexTextInputPanel.mm
endif
XPIDLSRCS += \
nsPIWidgetCocoa.idl \
$(NULL)

Просмотреть файл

@ -162,6 +162,7 @@ extern "C" long TSMProcessRawKeyEvent(EventRef carbonEvent);
// class) -- for some reason TSMProcessRawKeyEvent() doesn't work with them.
TSMDocumentID mPluginTSMDoc;
#endif
BOOL mPluginComplexTextInputRequested;
NSOpenGLContext *mContext;
@ -212,6 +213,7 @@ extern "C" long TSMProcessRawKeyEvent(EventRef carbonEvent);
#ifndef NP_NO_CARBON
- (void) processPluginKeyEvent:(EventRef)aKeyEvent;
#endif
- (void)pluginRequestsComplexTextInputForCurrentEvent;
- (void)update;
- (void)lockFocus;
@ -349,6 +351,8 @@ public:
NS_IMETHOD SetPluginEventModel(int inEventModel);
NS_IMETHOD GetPluginEventModel(int* outEventModel);
NS_IMETHOD StartComplexTextInputForCurrentEvent();
virtual nsTransparencyMode GetTransparencyMode();
virtual void SetTransparencyMode(nsTransparencyMode aMode);

Просмотреть файл

@ -74,6 +74,9 @@
#include "nsCocoaUtils.h"
#include "nsMenuUtilsX.h"
#include "nsMenuBarX.h"
#ifdef __LP64__
#include "ComplexTextInputPanel.h"
#endif
#include "gfxContext.h"
#include "gfxQuartzSurface.h"
@ -1331,6 +1334,12 @@ NS_IMETHODIMP nsChildView::GetPluginEventModel(int* outEventModel)
return NS_OK;
}
NS_IMETHODIMP nsChildView::StartComplexTextInputForCurrentEvent()
{
[(ChildView*)mView pluginRequestsComplexTextInputForCurrentEvent];
return NS_OK;
}
static NSString* ToNSString(const nsAString& aString)
{
return [NSString stringWithCharacters:aString.BeginReading()
@ -2203,6 +2212,7 @@ NSEvent* gLastDragMouseDownEvent = nil;
#ifndef NP_NO_CARBON
mPluginTSMDoc = nil;
#endif
mPluginComplexTextInputRequested = NO;
mGestureState = eGestureState_None;
mCumulativeMagnification = 0.0;
@ -4464,6 +4474,44 @@ GetUSLayoutCharFromKeyTranslate(UInt32 aKeyCode, UInt32 aModifiers)
if (!mGeckoChild)
return;
if (mPluginEventModel == NPEventModelCocoa) {
UInt32 size;
OSStatus status = ::GetEventParameter(aKeyEvent, kEventParamKeyUnicodes, typeUnicodeText, NULL, 0, &size, NULL);
if (status != noErr)
return;
UniChar* chars = (UniChar*)malloc(size);
if (!chars)
return;
status = ::GetEventParameter(aKeyEvent, kEventParamKeyUnicodes, typeUnicodeText, NULL, size, NULL, chars);
if (status != noErr) {
free(chars);
return;
}
CFStringRef text = ::CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, chars, (size / sizeof(UniChar)), kCFAllocatorNull);
if (!text) {
free(chars);
return;
}
NPCocoaEvent cocoaTextEvent;
InitNPCocoaEvent(&cocoaTextEvent);
cocoaTextEvent.type = NPCocoaEventTextInput;
cocoaTextEvent.data.text.text = (NPNSString*)text;
nsGUIEvent pluginTextEvent(PR_TRUE, NS_NON_RETARGETED_PLUGIN_EVENT, mGeckoChild);
pluginTextEvent.time = PR_IntervalNow();
pluginTextEvent.pluginEvent = (void*)&cocoaTextEvent;
mGeckoChild->DispatchWindowEvent(pluginTextEvent);
::CFRelease(text);
free(chars);
return;
}
nsAutoRetainCocoaObject kungFuDeathGrip(self);
UInt32 numCharCodes;
@ -4529,6 +4577,11 @@ GetUSLayoutCharFromKeyTranslate(UInt32 aKeyCode, UInt32 aModifiers)
}
#endif // NP_NO_CARBON
- (void)pluginRequestsComplexTextInputForCurrentEvent
{
mPluginComplexTextInputRequested = YES;
}
- (void)sendCompositionEvent:(PRInt32) aEventType
{
#ifdef DEBUG_IME
@ -4624,7 +4677,6 @@ GetUSLayoutCharFromKeyTranslate(UInt32 aKeyCode, UInt32 aModifiers)
#ifndef NP_NO_CARBON
EventRecord carbonEvent;
#endif
NPCocoaEvent cocoaEvent;
if (mCurKeyEvent) {
// XXX The ASCII characters inputting mode of egbridge (Japanese IME)
// might send the keyDown event with wrong keyboard layout if other
@ -4636,10 +4688,6 @@ GetUSLayoutCharFromKeyTranslate(UInt32 aKeyCode, UInt32 aModifiers)
geckoEvent.pluginEvent = &carbonEvent;
}
#endif
if (mPluginEventModel == NPEventModelCocoa) {
ConvertCocoaKeyEventToNPCocoaEvent(mCurKeyEvent, cocoaEvent);
geckoEvent.pluginEvent = &cocoaEvent;
}
geckoEvent.isShift = ([mCurKeyEvent modifierFlags] & NSShiftKeyMask) != 0;
if (!IsPrintableChar(geckoEvent.charCode)) {
@ -5109,13 +5157,6 @@ static const char* ToEscapedString(NSString* aString, nsCAutoString& aBuf)
!mGeckoChild->IME_IsComposing()) {
if (mKeyDownHandled)
geckoEvent.flags |= NS_EVENT_FLAG_NO_DEFAULT;
NPCocoaEvent cocoaEvent;
if (mPluginEventModel == NPEventModelCocoa) {
ConvertCocoaKeyEventToNPCocoaEvent(theEvent, cocoaEvent);
geckoEvent.pluginEvent = &cocoaEvent;
}
mKeyPressHandled = mGeckoChild->DispatchWindowEvent(geckoEvent);
mKeyPressSent = YES;
if (!mGeckoChild)
@ -5148,13 +5189,6 @@ static const char* ToEscapedString(NSString* aString, nsCAutoString& aBuf)
if (!(interpretKeyEventsCalled && IsNormalCharInputtingEvent(geckoEvent))) {
if (mKeyDownHandled)
geckoEvent.flags |= NS_EVENT_FLAG_NO_DEFAULT;
NPCocoaEvent cocoaEvent;
if (mPluginEventModel == NPEventModelCocoa) {
ConvertCocoaKeyEventToNPCocoaEvent(theEvent, cocoaEvent);
geckoEvent.pluginEvent = &cocoaEvent;
}
mKeyPressHandled = mGeckoChild->DispatchWindowEvent(geckoEvent);
}
}
@ -5174,6 +5208,16 @@ static const char* ToEscapedString(NSString* aString, nsCAutoString& aBuf)
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NO);
}
#ifdef NP_NO_CARBON
- (NSTextInputContext *)inputContext
{
if (mIsPluginView && mPluginEventModel == NPEventModelCocoa)
return [[ComplexTextInputPanel sharedComplexTextInputPanel] inputContext];
else
return [super inputContext];
}
#endif
#ifndef NP_NO_CARBON
// Create a TSM document for use with plugins, so that we can support IME in
// them. Once it's created, if need be (re)activate it. Some plugins (e.g.
@ -5210,14 +5254,52 @@ static const char* ToEscapedString(NSString* aString, nsCAutoString& aBuf)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
if (mGeckoChild && mIsPluginView) {
// If a plugin has the focus, we need to use an alternate method for
// handling NSKeyDown and NSKeyUp events (otherwise Carbon-based IME won't
// work in plugins like the Flash plugin). The same strategy is used by the
// WebKit. See PluginKeyEventsHandler() and [ChildView processPluginKeyEvent:]
// for more info.
if (mPluginEventModel == NPEventModelCocoa) {
// Reset complex text input request.
mPluginComplexTextInputRequested = NO;
// Send key down event.
nsGUIEvent pluginEvent(PR_TRUE, NS_NON_RETARGETED_PLUGIN_EVENT, mGeckoChild);
NPCocoaEvent cocoaEvent;
ConvertCocoaKeyEventToNPCocoaEvent(theEvent, cocoaEvent);
pluginEvent.pluginEvent = &cocoaEvent;
mGeckoChild->DispatchWindowEvent(pluginEvent);
if (!mGeckoChild)
return;
if (!mPluginComplexTextInputRequested) {
// Ideally we'd cancel any TSM composition here.
return;
}
#ifdef NP_NO_CARBON
ComplexTextInputPanel* ctInputPanel = [ComplexTextInputPanel sharedComplexTextInputPanel];
NSString* textString = nil;
[ctInputPanel interpretKeyEvent:theEvent string:&textString];
if (textString) {
NPCocoaEvent cocoaTextEvent;
InitNPCocoaEvent(&cocoaTextEvent);
cocoaTextEvent.type = NPCocoaEventTextInput;
cocoaTextEvent.data.text.text = (NPNSString*)textString;
nsGUIEvent pluginTextEvent(PR_TRUE, NS_NON_RETARGETED_PLUGIN_EVENT, mGeckoChild);
pluginTextEvent.time = PR_IntervalNow();
pluginTextEvent.pluginEvent = (void*)&cocoaTextEvent;
mGeckoChild->DispatchWindowEvent(pluginTextEvent);
}
return;
#endif
}
#ifndef NP_NO_CARBON
// If a plugin has the focus, we need to use an alternate method for
// handling NSKeyDown and NSKeyUp events (otherwise Carbon-based IME won't
// work in plugins like the Flash plugin). The same strategy is used by the
// WebKit. See PluginKeyEventsHandler() and [ChildView processPluginKeyEvent:]
// for more info.
if (mGeckoChild && mIsPluginView &&
(mPluginEventModel == NPEventModelCarbon)) {
// This will take care of all Carbon plugin events and also send Cocoa plugin
// text events when NSInputContext is not available (ifndef NP_NO_CARBON).
[self activatePluginTSMDoc];
// We use the active TSM document to pass a pointer to ourselves (the
// currently focused ChildView) to PluginKeyEventsHandler(). Because this
@ -5229,8 +5311,8 @@ static const char* ToEscapedString(NSString* aString, nsCAutoString& aBuf)
::TSMProcessRawKeyEvent([theEvent _eventRef]);
::TSMRemoveDocumentProperty(mPluginTSMDoc, kFocusedChildViewTSMDocPropertyTag);
return;
}
#endif
}
[self processKeyDownEvent:theEvent keyEquiv:NO];
@ -5409,6 +5491,44 @@ static const char* ToEscapedString(NSString* aString, nsCAutoString& aBuf)
(modifierFlags & (NSControlKeyMask | NSAlternateKeyMask)))
return handledByEmbedding;
// At this point we're about to hand the event off to "processKeyDownEvent:keyEquiv:".
// Don't bother if this is a Cocoa plugin event, just handle it directly.
if (mGeckoChild && mIsPluginView && mPluginEventModel == NPEventModelCocoa) {
// Reset complex text input request.
mPluginComplexTextInputRequested = NO;
// Send key down event.
nsGUIEvent pluginEvent(PR_TRUE, NS_NON_RETARGETED_PLUGIN_EVENT, mGeckoChild);
NPCocoaEvent cocoaEvent;
ConvertCocoaKeyEventToNPCocoaEvent(theEvent, cocoaEvent);
pluginEvent.pluginEvent = &cocoaEvent;
mGeckoChild->DispatchWindowEvent(pluginEvent);
if (!mGeckoChild)
return YES;
if (!mPluginComplexTextInputRequested) {
// Ideally we'd cancel any TSM composition here.
return YES;
}
// We send these events to Carbon TSM but not to the ComplexTextInputPanel.
// We assume that events coming in through pKE: are only relevant to TSM.
#ifndef NP_NO_CARBON
[self activatePluginTSMDoc];
// We use the active TSM document to pass a pointer to ourselves (the
// currently focused ChildView) to PluginKeyEventsHandler(). Because this
// pointer is weak, we should retain and release ourselves around the call
// to TSMProcessRawKeyEvent().
nsAutoRetainCocoaObject kungFuDeathGrip(self);
::TSMSetDocumentProperty(mPluginTSMDoc, kFocusedChildViewTSMDocPropertyTag,
sizeof(ChildView *), &self);
::TSMProcessRawKeyEvent([theEvent _eventRef]);
::TSMRemoveDocumentProperty(mPluginTSMDoc, kFocusedChildViewTSMDocPropertyTag);
#endif
return YES;
}
if ([theEvent type] == NSKeyDown) {
// We trust the Gecko handled status for cmd key events. See bug 417466 for more info.
if (modifierFlags & NSCommandKeyMask)