diff --git a/widget/src/cocoa/nsAppShell.mm b/widget/src/cocoa/nsAppShell.mm index e64ee6a438af..04fd87c1e0b6 100644 --- a/widget/src/cocoa/nsAppShell.mm +++ b/widget/src/cocoa/nsAppShell.mm @@ -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." diff --git a/widget/src/cocoa/nsChildView.h b/widget/src/cocoa/nsChildView.h index e4f7dedbc57a..fe69c3692020 100644 --- a/widget/src/cocoa/nsChildView.h +++ b/widget/src/cocoa/nsChildView.h @@ -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_ diff --git a/widget/src/cocoa/nsChildView.mm b/widget/src/cocoa/nsChildView.mm index b276696cde87..2cc6e1109a49 100644 --- a/widget/src/cocoa/nsChildView.mm +++ b/widget/src/cocoa/nsChildView.mm @@ -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 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; -}