зеркало из https://github.com/mozilla/gecko-dev.git
Backout of bug 357670 due to bug 434914. a=shaver
This commit is contained in:
Родитель
2505ae95f9
Коммит
deb15a4120
|
@ -56,7 +56,6 @@
|
|||
#include "nsIWebBrowserChrome.h"
|
||||
#include "nsObjCExceptions.h"
|
||||
#include "nsCocoaUtils.h"
|
||||
#include "nsChildView.h"
|
||||
|
||||
// defined in nsChildView.mm
|
||||
extern nsIRollupListener * gRollupListener;
|
||||
|
@ -237,8 +236,6 @@ nsAppShell::Init()
|
|||
|
||||
rv = nsBaseAppShell::Init();
|
||||
|
||||
NS_InstallPluginKeyEventsHandler();
|
||||
|
||||
[localPool release];
|
||||
|
||||
return rv;
|
||||
|
@ -610,8 +607,6 @@ nsAppShell::Exit(void)
|
|||
|
||||
mTerminated = PR_TRUE;
|
||||
|
||||
NS_RemovePluginKeyEventsHandler();
|
||||
|
||||
// Quoting from Apple's doc on the [NSApplication stop:] method (from their
|
||||
// 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."
|
||||
|
|
|
@ -72,36 +72,6 @@ class gfxASurface;
|
|||
class nsChildView;
|
||||
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<
|
||||
#ifdef ACCESSIBILITY
|
||||
mozAccessible,
|
||||
|
@ -162,11 +132,6 @@ extern "C" long TSMProcessRawKeyEvent(EventRef carbonEvent);
|
|||
nsIDragService* mDragService;
|
||||
|
||||
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
|
||||
|
@ -179,8 +144,6 @@ extern "C" long TSMProcessRawKeyEvent(EventRef carbonEvent);
|
|||
- (void)setTransparent:(BOOL)transparent;
|
||||
|
||||
- (void)sendFocusEvent:(PRUint32)eventType;
|
||||
|
||||
- (void) processPluginKeyEvent:(EventRef)aKeyEvent;
|
||||
@end
|
||||
|
||||
|
||||
|
@ -419,7 +382,5 @@ protected:
|
|||
nsIPluginInstanceOwner* mPluginInstanceOwner; // [WEAK]
|
||||
};
|
||||
|
||||
void NS_InstallPluginKeyEventsHandler();
|
||||
void NS_RemovePluginKeyEventsHandler();
|
||||
|
||||
#endif // nsChildView_h_
|
||||
|
|
|
@ -2164,8 +2164,6 @@ NSEvent* gLastDragEvent = nil;
|
|||
|
||||
mLastMouseDownEvent = nil;
|
||||
mDragService = nsnull;
|
||||
|
||||
mPluginTSMDoc = nil;
|
||||
}
|
||||
|
||||
// register for things we'll take from other applications
|
||||
|
@ -2192,8 +2190,6 @@ NSEvent* gLastDragEvent = nil;
|
|||
|
||||
[mPendingDirtyRects release];
|
||||
[mLastMouseDownEvent release];
|
||||
if (mPluginTSMDoc)
|
||||
::DeleteTSMDocument(mPluginTSMDoc);
|
||||
|
||||
if (sLastViewEntered == self)
|
||||
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
|
||||
{
|
||||
#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
|
||||
{
|
||||
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];
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK;
|
||||
}
|
||||
|
||||
|
||||
|
@ -5203,15 +5071,6 @@ static BOOL keyUpAlreadySentKeyDown = NO;
|
|||
ToEscapedString([theEvent characters], str1),
|
||||
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 (!mGeckoChild || [[theEvent characters] length] == 0)
|
||||
return;
|
||||
|
@ -6001,72 +5860,3 @@ nsTSMManager::CancelIME()
|
|||
|
||||
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;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче