Backout of bug 357670 due to bug 434914. a=shaver
git-svn-id: svn://10.0.0.236/trunk@251976 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
parent
2081ec9a5f
commit
900d9df010
@ -56,7 +56,6 @@
|
|||||||
#include "nsIWebBrowserChrome.h"
|
#include "nsIWebBrowserChrome.h"
|
||||||
#include "nsObjCExceptions.h"
|
#include "nsObjCExceptions.h"
|
||||||
#include "nsCocoaUtils.h"
|
#include "nsCocoaUtils.h"
|
||||||
#include "nsChildView.h"
|
|
||||||
|
|
||||||
// defined in nsChildView.mm
|
// defined in nsChildView.mm
|
||||||
extern nsIRollupListener * gRollupListener;
|
extern nsIRollupListener * gRollupListener;
|
||||||
@ -237,8 +236,6 @@ nsAppShell::Init()
|
|||||||
|
|
||||||
rv = nsBaseAppShell::Init();
|
rv = nsBaseAppShell::Init();
|
||||||
|
|
||||||
NS_InstallPluginKeyEventsHandler();
|
|
||||||
|
|
||||||
[localPool release];
|
[localPool release];
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
@ -610,8 +607,6 @@ nsAppShell::Exit(void)
|
|||||||
|
|
||||||
mTerminated = PR_TRUE;
|
mTerminated = PR_TRUE;
|
||||||
|
|
||||||
NS_RemovePluginKeyEventsHandler();
|
|
||||||
|
|
||||||
// Quoting from Apple's doc on the [NSApplication stop:] method (from their
|
// Quoting from Apple's doc on the [NSApplication stop:] method (from their
|
||||||
// doc on the NSApplication class): "If this method is invoked during a
|
// doc on the NSApplication class): "If this method is invoked during a
|
||||||
// modal event loop, it will break that loop but not the main event loop."
|
// modal event loop, it will break that loop but not the main event loop."
|
||||||
|
|||||||
@ -72,36 +72,6 @@ class gfxASurface;
|
|||||||
class nsChildView;
|
class nsChildView;
|
||||||
union nsPluginPort;
|
union nsPluginPort;
|
||||||
|
|
||||||
enum {
|
|
||||||
// Currently focused ChildView (while this TSM document is active).
|
|
||||||
// Transient (only set while TSMProcessRawKeyEvent() is processing a key
|
|
||||||
// event), and the ChildView will be retained and released around the call
|
|
||||||
// to TSMProcessRawKeyEvent() -- so it can be weak.
|
|
||||||
kFocusedChildViewTSMDocPropertyTag = 'GKFV', // type ChildView* [WEAK]
|
|
||||||
};
|
|
||||||
|
|
||||||
// Undocumented HIToolbox function used by WebKit to allow Carbon-based IME
|
|
||||||
// to work in a Cocoa-based browser (like Safari or Cocoa-widgets Firefox).
|
|
||||||
// (Recent WebKit versions actually use a thin wrapper around this function
|
|
||||||
// called WKSendKeyEventToTSM().)
|
|
||||||
//
|
|
||||||
// Calling TSMProcessRawKeyEvent() from ChildView's keyDown: and keyUp:
|
|
||||||
// methods (when the ChildView is a plugin view) bypasses Cocoa's IME
|
|
||||||
// infrastructure and (instead) causes Carbon TSM events to be sent on each
|
|
||||||
// NSKeyDown event. We install a Carbon event handler
|
|
||||||
// (PluginKeyEventsHandler()) to catch these events and pass them to Gecko
|
|
||||||
// (which in turn passes them to the plugin).
|
|
||||||
extern "C" long TSMProcessRawKeyEvent(EventRef carbonEvent);
|
|
||||||
|
|
||||||
@interface NSEvent (Undocumented)
|
|
||||||
|
|
||||||
// Return Cocoa event's corresponding Carbon event. Not initialized (on
|
|
||||||
// synthetic events) until the OS actually "sends" the event. This method
|
|
||||||
// has been present in the same form since at least OS X 10.2.8.
|
|
||||||
- (EventRef)_eventRef;
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
@interface ChildView : NSView<
|
@interface ChildView : NSView<
|
||||||
#ifdef ACCESSIBILITY
|
#ifdef ACCESSIBILITY
|
||||||
mozAccessible,
|
mozAccessible,
|
||||||
@ -162,11 +132,6 @@ extern "C" long TSMProcessRawKeyEvent(EventRef carbonEvent);
|
|||||||
nsIDragService* mDragService;
|
nsIDragService* mDragService;
|
||||||
|
|
||||||
PRUint32 mLastModifierState;
|
PRUint32 mLastModifierState;
|
||||||
|
|
||||||
// For use with plugins, so that we can support IME in them. We can't use
|
|
||||||
// Cocoa TSM documents (those created and managed by the NSTSMInputContext
|
|
||||||
// class) -- for some reason TSMProcessRawKeyEvent() doesn't work with them.
|
|
||||||
TSMDocumentID mPluginTSMDoc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// these are sent to the first responder when the window key status changes
|
// these are sent to the first responder when the window key status changes
|
||||||
@ -179,8 +144,6 @@ extern "C" long TSMProcessRawKeyEvent(EventRef carbonEvent);
|
|||||||
- (void)setTransparent:(BOOL)transparent;
|
- (void)setTransparent:(BOOL)transparent;
|
||||||
|
|
||||||
- (void)sendFocusEvent:(PRUint32)eventType;
|
- (void)sendFocusEvent:(PRUint32)eventType;
|
||||||
|
|
||||||
- (void) processPluginKeyEvent:(EventRef)aKeyEvent;
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
@ -419,7 +382,5 @@ protected:
|
|||||||
nsIPluginInstanceOwner* mPluginInstanceOwner; // [WEAK]
|
nsIPluginInstanceOwner* mPluginInstanceOwner; // [WEAK]
|
||||||
};
|
};
|
||||||
|
|
||||||
void NS_InstallPluginKeyEventsHandler();
|
|
||||||
void NS_RemovePluginKeyEventsHandler();
|
|
||||||
|
|
||||||
#endif // nsChildView_h_
|
#endif // nsChildView_h_
|
||||||
|
|||||||
@ -2164,8 +2164,6 @@ NSEvent* gLastDragEvent = nil;
|
|||||||
|
|
||||||
mLastMouseDownEvent = nil;
|
mLastMouseDownEvent = nil;
|
||||||
mDragService = nsnull;
|
mDragService = nsnull;
|
||||||
|
|
||||||
mPluginTSMDoc = nil;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// register for things we'll take from other applications
|
// register for things we'll take from other applications
|
||||||
@ -2192,8 +2190,6 @@ NSEvent* gLastDragEvent = nil;
|
|||||||
|
|
||||||
[mPendingDirtyRects release];
|
[mPendingDirtyRects release];
|
||||||
[mLastMouseDownEvent release];
|
[mLastMouseDownEvent release];
|
||||||
if (mPluginTSMDoc)
|
|
||||||
::DeleteTSMDocument(mPluginTSMDoc);
|
|
||||||
|
|
||||||
if (sLastViewEntered == self)
|
if (sLastViewEntered == self)
|
||||||
sLastViewEntered = nil;
|
sLastViewEntered = nil;
|
||||||
@ -4438,80 +4434,6 @@ GetUSLayoutCharFromKeyTranslate(UInt32 aKeyCode, UInt32 aModifiers)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Called from PluginKeyEventsHandler() (a handler for Carbon TSM events) to
|
|
||||||
// process a Carbon key event for the currently focused plugin. Both Unicode
|
|
||||||
// characters and "Mac encoding characters" (in the MBCS or "multibyte
|
|
||||||
// character system") are (or should be) available from aKeyEvent, but here we
|
|
||||||
// use the MCBS characters. This is how the WebKit does things, and seems to
|
|
||||||
// be what plugins expect.
|
|
||||||
- (void) processPluginKeyEvent:(EventRef)aKeyEvent
|
|
||||||
{
|
|
||||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
||||||
|
|
||||||
if (!mGeckoChild)
|
|
||||||
return;
|
|
||||||
|
|
||||||
nsAutoRetainCocoaObject kungFuDeathGrip(self);
|
|
||||||
|
|
||||||
UInt32 numCharCodes;
|
|
||||||
OSStatus status = ::GetEventParameter(aKeyEvent, kEventParamKeyMacCharCodes,
|
|
||||||
typeChar, NULL, 0, &numCharCodes, NULL);
|
|
||||||
if (status != noErr)
|
|
||||||
return;
|
|
||||||
|
|
||||||
nsAutoTArray<unsigned char, 3> charCodes;
|
|
||||||
charCodes.SetLength(numCharCodes);
|
|
||||||
status = ::GetEventParameter(aKeyEvent, kEventParamKeyMacCharCodes,
|
|
||||||
typeChar, NULL, numCharCodes, NULL, charCodes.Elements());
|
|
||||||
if (status != noErr)
|
|
||||||
return;
|
|
||||||
|
|
||||||
EventRef cloneEvent = ::CopyEvent(aKeyEvent);
|
|
||||||
for (unsigned int i = 0; i < numCharCodes; ++i) {
|
|
||||||
status = ::SetEventParameter(cloneEvent, kEventParamKeyMacCharCodes,
|
|
||||||
typeChar, 1, charCodes.Elements() + i);
|
|
||||||
if (status != noErr)
|
|
||||||
break;
|
|
||||||
|
|
||||||
EventRecord eventRec;
|
|
||||||
if (::ConvertEventRefToEventRecord(cloneEvent, &eventRec)) {
|
|
||||||
PRUint32 keyCode(GetGeckoKeyCodeFromChar((PRUnichar)charCodes.ElementAt(i)));
|
|
||||||
PRUint32 charCode(charCodes.ElementAt(i));
|
|
||||||
|
|
||||||
// For some reason we must send just an NS_KEY_PRESS to Gecko here: If
|
|
||||||
// we send an NS_KEY_DOWN plus an NS_KEY_PRESS, or just an NS_KEY_DOWN,
|
|
||||||
// the plugin receives two events.
|
|
||||||
nsKeyEvent keyPressEvent(PR_TRUE, NS_KEY_PRESS, mGeckoChild);
|
|
||||||
keyPressEvent.time = PR_IntervalNow();
|
|
||||||
keyPressEvent.nativeMsg = &eventRec;
|
|
||||||
if (IsSpecialGeckoKey(keyCode)) {
|
|
||||||
keyPressEvent.keyCode = keyCode;
|
|
||||||
} else {
|
|
||||||
keyPressEvent.charCode = charCode;
|
|
||||||
keyPressEvent.isChar = PR_TRUE;
|
|
||||||
}
|
|
||||||
mGeckoChild->DispatchWindowEvent(keyPressEvent);
|
|
||||||
if (!mGeckoChild)
|
|
||||||
break;
|
|
||||||
|
|
||||||
// PluginKeyEventsHandler() never sends us keyUp events, so we need to
|
|
||||||
// synthesize them for Gecko.
|
|
||||||
nsKeyEvent keyUpEvent(PR_TRUE, NS_KEY_UP, mGeckoChild);
|
|
||||||
keyUpEvent.time = PR_IntervalNow();
|
|
||||||
keyUpEvent.keyCode = keyCode;
|
|
||||||
keyUpEvent.nativeMsg = &eventRec;
|
|
||||||
mGeckoChild->DispatchWindowEvent(keyUpEvent);
|
|
||||||
if (!mGeckoChild)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
::ReleaseEvent(cloneEvent);
|
|
||||||
|
|
||||||
NS_OBJC_END_TRY_ABORT_BLOCK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
- (nsRect)sendCompositionEvent:(PRInt32) aEventType
|
- (nsRect)sendCompositionEvent:(PRInt32) aEventType
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_IME
|
#ifdef DEBUG_IME
|
||||||
@ -5127,63 +5049,9 @@ static const char* ToEscapedString(NSString* aString, nsCAutoString& aBuf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 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.
|
|
||||||
// the Flash plugin running in Camino) don't create their own TSM document --
|
|
||||||
// without which IME can't work. Others (e.g. the Flash plugin running in
|
|
||||||
// Firefox) create a TSM document that (somehow) makes the input window behave
|
|
||||||
// badly when it contains more than one kind of input (say Hiragana and
|
|
||||||
// Romaji). (We can't just use the per-NSView TSM documents that Cocoa
|
|
||||||
// provices (those created and managed by the NSTSMInputContext class) -- for
|
|
||||||
// some reason TSMProcessRawKeyEvent() doesn't work with them.)
|
|
||||||
- (void)activatePluginTSMDoc
|
|
||||||
{
|
|
||||||
if (!mPluginTSMDoc) {
|
|
||||||
// Create a TSM document that supports both non-Unicode and Unicode input.
|
|
||||||
// Though [ChildView processPluginKeyEvent:] only sends Mac char codes to
|
|
||||||
// the plugin, this makes the input window behave better when it contains
|
|
||||||
// more than one kind of input (say Hiragana and Romaji). This is what
|
|
||||||
// the OS does when it creates a TSM document for use by an
|
|
||||||
// NSTSMInputContext class.
|
|
||||||
InterfaceTypeList supportedServices;
|
|
||||||
supportedServices[0] = kTextServiceDocumentInterfaceType;
|
|
||||||
supportedServices[1] = kUnicodeDocumentInterfaceType;
|
|
||||||
::NewTSMDocument(2, supportedServices, &mPluginTSMDoc, 0);
|
|
||||||
// We'll need to use the "input window".
|
|
||||||
::UseInputWindow(mPluginTSMDoc, YES);
|
|
||||||
::ActivateTSMDocument(mPluginTSMDoc);
|
|
||||||
} else if (::TSMGetActiveDocument() != mPluginTSMDoc) {
|
|
||||||
::ActivateTSMDocument(mPluginTSMDoc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
- (void)keyDown:(NSEvent*)theEvent
|
- (void)keyDown:(NSEvent*)theEvent
|
||||||
{
|
{
|
||||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
||||||
|
|
||||||
// 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) {
|
|
||||||
[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);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
[self processKeyDownEvent:theEvent keyEquiv:NO];
|
[self processKeyDownEvent:theEvent keyEquiv:NO];
|
||||||
|
|
||||||
NS_OBJC_END_TRY_ABORT_BLOCK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -5203,15 +5071,6 @@ static BOOL keyUpAlreadySentKeyDown = NO;
|
|||||||
ToEscapedString([theEvent characters], str1),
|
ToEscapedString([theEvent characters], str1),
|
||||||
ToEscapedString([theEvent charactersIgnoringModifiers], str2)));
|
ToEscapedString([theEvent charactersIgnoringModifiers], str2)));
|
||||||
|
|
||||||
if (mGeckoChild && mIsPluginView) {
|
|
||||||
// I'm not sure the call to TSMProcessRawKeyEvent() is needed here (though
|
|
||||||
// WebKit makes one). But we definitely need to short-circuit NSKeyUp
|
|
||||||
// handling when a plugin has the focus -- since we synthesize keyUp events
|
|
||||||
// in [ChildView processPluginKeyEvent:].
|
|
||||||
::TSMProcessRawKeyEvent([theEvent _eventRef]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we don't have any characters we can't generate a keyUp event
|
// if we don't have any characters we can't generate a keyUp event
|
||||||
if (!mGeckoChild || [[theEvent characters] length] == 0)
|
if (!mGeckoChild || [[theEvent characters] length] == 0)
|
||||||
return;
|
return;
|
||||||
@ -6001,72 +5860,3 @@ nsTSMManager::CancelIME()
|
|||||||
|
|
||||||
NS_OBJC_END_TRY_ABORT_BLOCK;
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Target for text services events sent as the result of calls made to
|
|
||||||
// TSMProcessRawKeyEvent() in [ChildView keyDown:] (above) when a plugin has
|
|
||||||
// the focus. The calls to TSMProcessRawKeyEvent() short-circuit Cocoa-based
|
|
||||||
// IME (which would otherwise interfere with our efforts) and allow Carbon-
|
|
||||||
// based IME to work in plugins (via the NPAPI). This strategy doesn't cause
|
|
||||||
// trouble for plugins that (like the Java Embedding Plugin) bypass the NPAPI
|
|
||||||
// to get their keyboard events and do their own Cocoa-based IME.
|
|
||||||
OSStatus PluginKeyEventsHandler(EventHandlerCallRef inHandlerRef,
|
|
||||||
EventRef inEvent, void *userData)
|
|
||||||
{
|
|
||||||
id arp = [[NSAutoreleasePool alloc] init];
|
|
||||||
|
|
||||||
TSMDocumentID activeDoc = ::TSMGetActiveDocument();
|
|
||||||
if (!activeDoc) {
|
|
||||||
[arp release];
|
|
||||||
return eventNotHandledErr;
|
|
||||||
}
|
|
||||||
|
|
||||||
ChildView *target = nil;
|
|
||||||
OSStatus status = ::TSMGetDocumentProperty(activeDoc, kFocusedChildViewTSMDocPropertyTag,
|
|
||||||
sizeof(ChildView *), nil, &target);
|
|
||||||
if (status != noErr)
|
|
||||||
target = nil;
|
|
||||||
if (!target) {
|
|
||||||
[arp release];
|
|
||||||
return eventNotHandledErr;
|
|
||||||
}
|
|
||||||
|
|
||||||
EventRef keyEvent = NULL;
|
|
||||||
status = ::GetEventParameter(inEvent, kEventParamTextInputSendKeyboardEvent,
|
|
||||||
typeEventRef, NULL, sizeof(EventRef), NULL, &keyEvent);
|
|
||||||
if ((status != noErr) || !keyEvent) {
|
|
||||||
[arp release];
|
|
||||||
return eventNotHandledErr;
|
|
||||||
}
|
|
||||||
|
|
||||||
[target processPluginKeyEvent:keyEvent];
|
|
||||||
|
|
||||||
[arp release];
|
|
||||||
return noErr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static EventHandlerRef gPluginKeyEventsHandler = NULL;
|
|
||||||
|
|
||||||
// Called from nsAppShell::Init()
|
|
||||||
void NS_InstallPluginKeyEventsHandler()
|
|
||||||
{
|
|
||||||
if (gPluginKeyEventsHandler)
|
|
||||||
return;
|
|
||||||
static const EventTypeSpec sTSMEvents[] =
|
|
||||||
{ { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent } };
|
|
||||||
::InstallEventHandler(::GetEventDispatcherTarget(),
|
|
||||||
::NewEventHandlerUPP(PluginKeyEventsHandler),
|
|
||||||
GetEventTypeCount(sTSMEvents),
|
|
||||||
sTSMEvents,
|
|
||||||
NULL,
|
|
||||||
&gPluginKeyEventsHandler);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called from nsAppShell::Exit()
|
|
||||||
void NS_RemovePluginKeyEventsHandler()
|
|
||||||
{
|
|
||||||
if (!gPluginKeyEventsHandler)
|
|
||||||
return;
|
|
||||||
::RemoveEventHandler(gPluginKeyEventsHandler);
|
|
||||||
gPluginKeyEventsHandler = NULL;
|
|
||||||
}
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user