Bug 519972 part.10 Move keyup and flagsChanged code to TextInputHandler r=smichaud

This commit is contained in:
Masayuki Nakano 2011-07-21 09:33:16 +09:00
parent 160860a0e2
commit 599da8a7a1
5 changed files with 205 additions and 140 deletions

View File

@ -628,9 +628,6 @@ public:
*/
void HandleKeyUpEventForPlugin(NSEvent* aNativeKeyEvent);
PRBool DoesIgnoreNextKeyUpEvent() { return mIgnoreNextKeyUpEvent; }
void ResetIgnoreNextKeyUpEvent() { mIgnoreNextKeyUpEvent = PR_FALSE; }
/**
* ConvertCocoaKeyEventToNPCocoaEvent() converts aCocoaEvent to NPCocoaEvent.
*
@ -665,26 +662,15 @@ public:
mPluginTSMInComposition = aInComposition;
}
/**
* 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
* provides (those created and managed by the NSTSMInputContext class) -- for
* some reason TSMProcessRawKeyEvent() doesn't work with them.)
*/
void ActivatePluginTSMDocument();
#endif // #ifndef NP_NO_CARBON
/**
* HandleCarbonPluginKeyEvent() handles the aKeyEvent. This is called by
* PluginKeyEventsHandler().
*
* @param aKeyEvent A native Carbon event.
*/
void HandleCarbonPluginKeyEvent(EventRef aKeyEvent);
protected:
PRPackedBool mIgnoreNextKeyUpEvent;
PluginTextInputHandler(nsChildView* aWidget, NSView<mozView> *aNativeView);
~PluginTextInputHandler();
#ifndef NP_NO_CARBON
/**
* ConvertCocoaKeyEventToCarbonEvent() converts aCocoaKeyEvent to
@ -706,12 +692,6 @@ public:
#endif // #ifndef NP_NO_CARBON
protected:
PRPackedBool mIgnoreNextKeyUpEvent;
PluginTextInputHandler(nsChildView* aWidget, NSView<mozView> *aNativeView);
~PluginTextInputHandler();
private:
#ifndef NP_NO_CARBON
@ -743,6 +723,27 @@ private:
#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.
* 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
* provides (those created and managed by the NSTSMInputContext class) -- for
* some reason TSMProcessRawKeyEvent() doesn't work with them.)
*/
void ActivatePluginTSMDocument();
/**
* HandleCarbonPluginKeyEvent() handles the aKeyEvent. This is called by
* PluginKeyEventsHandler().
*
* @param aKeyEvent A native Carbon event.
*/
void HandleCarbonPluginKeyEvent(EventRef aKeyEvent);
/**
* ConvertUnicodeToCharCode() converts aUnichar to native encoded string.
*
@ -1066,6 +1067,8 @@ private:
class TextInputHandler : public IMEInputHandler
{
public:
static PRBool sLastModifierState;
static CFArrayRef CreateAllKeyboardLayoutList();
static void DebugPrintAllKeyboardLayouts(PRLogModuleInfo* aLogModuleInfo);
@ -1075,13 +1078,26 @@ public:
/**
* KeyDown event handler.
*
* @param aNativeEvent A native keydown event which you want to
* handle.
* @param aNativeEvent A native NSKeyDown event.
* @return TRUE if the event is consumed by web contents
* or chrome contents. Otherwise, FALSE.
*/
PRBool HandleKeyDownEvent(NSEvent* aNativeEvent);
/**
* KeyUp event handler.
*
* @param aNativeEvent A native NSKeyUp event.
*/
void HandleKeyUpEvent(NSEvent* aNativeEvent);
/**
* FlagsChanged event handler.
*
* @param aNativeEvent A native NSFlagsChanged event.
*/
void HandleFlagsChanged(NSEvent* aNativeEvent);
/**
* Insert the string to content. I.e., this is a text input event handler.
* If this is called during keydown event handling, this may dispatch a
@ -1104,6 +1120,20 @@ public:
{
return mCurrentKeyEvent.mKeyPressHandled;
}
protected:
/**
* DispatchKeyEventForFlagsChanged() dispatches keydown event or keyup event
* for the aNativeEvent.
*
* @param aNativeEvent A native flagschanged event which you want to
* dispatch our key event for.
* @param aDispatchKeyDown TRUE if you want to dispatch a keydown event.
* Otherwise, i.e., to dispatch keyup event,
* FALSE.
*/
void DispatchKeyEventForFlagsChanged(NSEvent* aNativeEvent,
PRBool aDispatchKeyDown);
};
} // namespace widget

View File

@ -766,6 +766,8 @@ TISInputSourceWrapper::InitKeyPressEvent(NSEvent *aNativeKeyEvent,
*
******************************************************************************/
PRBool TextInputHandler::sLastModifierState = PR_FALSE;
// static
CFArrayRef
TextInputHandler::CreateAllKeyboardLayoutList()
@ -951,6 +953,132 @@ TextInputHandler::HandleKeyDownEvent(NSEvent* aNativeEvent)
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(PR_FALSE);
}
void
TextInputHandler::HandleKeyUpEvent(NSEvent* aNativeEvent)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
if (mIgnoreNextKeyUpEvent) {
mIgnoreNextKeyUpEvent = PR_FALSE;
return;
}
if (Destroyed()) {
return;
}
// if we don't have any characters we can't generate a keyUp event
if ([[aNativeEvent characters] length] == 0 || IsIMEComposing()) {
return;
}
nsKeyEvent keyupEvent(PR_TRUE, NS_KEY_UP, mWidget);
InitKeyEvent(aNativeEvent, keyupEvent);
DispatchEvent(keyupEvent);
NS_OBJC_END_TRY_ABORT_BLOCK;
}
void
TextInputHandler::HandleFlagsChanged(NSEvent* aNativeEvent)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
if (Destroyed()) {
return;
}
nsRefPtr<nsChildView> kungFuDeathGrip(mWidget);
// CapsLock state and other modifier states are different:
// CapsLock state does not revert when the CapsLock key goes up, as the
// modifier state does for other modifier keys on key up.
if ([aNativeEvent keyCode] == kCapsLockKeyCode) {
// Fire key down event for caps lock.
DispatchKeyEventForFlagsChanged(aNativeEvent, PR_TRUE);
if (Destroyed()) {
return;
}
// XXX should we fire keyup event too? The keyup event for CapsLock key
// is never dispatched on Gecko.
} else if ([aNativeEvent type] == NSFlagsChanged) {
// Fire key up/down events for the modifier keys (shift, alt, ctrl, command)
NSUInteger modifiers =
[aNativeEvent modifierFlags] & NSDeviceIndependentModifierFlagsMask;
const NSUInteger kModifierMaskTable[] =
{ NSShiftKeyMask, NSControlKeyMask,
NSAlternateKeyMask, NSCommandKeyMask };
const PRUint32 kModifierCount = NS_ARRAY_LENGTH(kModifierMaskTable);
for (PRUint32 i = 0; i < kModifierCount; i++) {
NSUInteger modifierBit = kModifierMaskTable[i];
if ((modifiers & modifierBit) != (sLastModifierState & modifierBit)) {
PRBool isKeyDown = ((modifiers & modifierBit) != 0);
DispatchKeyEventForFlagsChanged(aNativeEvent, isKeyDown);
if (Destroyed()) {
return;
}
// Stop if focus has changed.
// Check to see if mView is still the first responder.
if (![mView isFirstResponder]) {
break;
}
}
}
sLastModifierState = modifiers;
}
NS_OBJC_END_TRY_ABORT_BLOCK;
}
void
TextInputHandler::DispatchKeyEventForFlagsChanged(NSEvent* aNativeEvent,
PRBool aDispatchKeyDown)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
if (Destroyed()) {
return;
}
if ([aNativeEvent type] != NSFlagsChanged || IsIMEComposing()) {
return;
}
PRUint32 message = aDispatchKeyDown ? NS_KEY_DOWN : NS_KEY_UP;
#ifndef NP_NO_CARBON
EventRecord carbonEvent;
#endif // ifndef NP_NO_CARBON
NPCocoaEvent cocoaEvent;
// Fire a key event.
nsKeyEvent keyEvent(PR_TRUE, message, mWidget);
InitKeyEvent(aNativeEvent, keyEvent);
// create event for use by plugins
if ([mView isPluginView]) {
#ifndef NP_NO_CARBON
if ([mView pluginEventModel] == NPEventModelCarbon) {
ConvertCocoaKeyEventToCarbonEvent(aNativeEvent, carbonEvent,
aDispatchKeyDown);
keyEvent.pluginEvent = &carbonEvent;
}
#endif // ifndef NP_NO_CARBON
if ([mView pluginEventModel] == NPEventModelCocoa) {
ConvertCocoaKeyEventToNPCocoaEvent(aNativeEvent, cocoaEvent);
keyEvent.pluginEvent = &cocoaEvent;
}
}
DispatchEvent(keyEvent);
NS_OBJC_END_TRY_ABORT_BLOCK;
}
void
TextInputHandler::InsertText(NSAttributedString *aAttrString)
{
@ -2739,6 +2867,11 @@ PluginTextInputHandler::HandleKeyDownEventForPlugin(NSEvent* aNativeKeyEvent)
void
PluginTextInputHandler::HandleKeyUpEventForPlugin(NSEvent* aNativeKeyEvent)
{
if (mIgnoreNextKeyUpEvent) {
mIgnoreNextKeyUpEvent = PR_FALSE;
return;
}
if (Destroyed()) {
return;
}

View File

@ -87,6 +87,9 @@ class TextInputHandler;
// Call when you dispatch an event which may cause to open context menu.
- (void)maybeInitContextMenuTracking;
// Checks whether the view is for plugin or not
- (BOOL)isPluginView;
@end
// An informal protocol implemented by the NSWindow of the host application.

View File

@ -70,7 +70,6 @@ using namespace mozilla::widget;
// defined in nsChildView.mm
extern nsIRollupListener * gRollupListener;
extern nsIWidget * gRollupWidget;
extern PRUint32 gLastModifierState;
// defined in nsCocoaWindow.mm
extern PRInt32 gXULModalLevel;
@ -950,8 +949,9 @@ nsAppShell::AfterProcessNextEvent(nsIThreadInternal *aThread,
// applicationDidBecomeActive
//
// Make sure gLastModifierState is updated when we become active (since we
// won't have received [ChildView flagsChanged:] messages while inactive).
// Make sure TextInputHandler::sLastModifierState is updated when we become
// active (since we won't have received [ChildView flagsChanged:] messages
// while inactive).
- (void)applicationDidBecomeActive:(NSNotification*)aNotification
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
@ -960,7 +960,8 @@ nsAppShell::AfterProcessNextEvent(nsIThreadInternal *aThread,
// to worry about getting an NSInternalInconsistencyException here.
NSEvent* currentEvent = [NSApp currentEvent];
if (currentEvent) {
gLastModifierState = [currentEvent modifierFlags] & NSDeviceIndependentModifierFlagsMask;
TextInputHandler::sLastModifierState =
[currentEvent modifierFlags] & NSDeviceIndependentModifierFlagsMask;
}
NS_OBJC_END_TRY_ABORT_BLOCK;

View File

@ -145,8 +145,6 @@ nsIRollupListener * gRollupListener = nsnull;
nsIMenuRollup * gMenuRollup = nsnull;
nsIWidget * gRollupWidget = nsnull;
PRUint32 gLastModifierState = 0;
PRBool gUserCancelledDrag = PR_FALSE;
PRUint32 nsChildView::sLastInputEventCount = 0;
@ -166,7 +164,6 @@ PRUint32 nsChildView::sLastInputEventCount = 0;
- (NSMenu*)contextMenu;
- (void)setIsPluginView:(BOOL)aIsPlugin;
- (BOOL)isPluginView;
- (void)setPluginEventModel:(NPEventModel)eventModel;
- (void)setPluginDrawingModel:(NPDrawingModel)drawingModel;
- (NPDrawingModel)pluginDrawingModel;
@ -191,8 +188,6 @@ PRUint32 nsChildView::sLastInputEventCount = 0;
- (id<mozAccessible>)accessible;
#endif
- (void)fireKeyEventForFlagsChanged:(NSEvent*)theEvent keyDown:(BOOL)isKeyDown;
- (BOOL)inactiveWindowAcceptsMouseEvent:(NSEvent*)aEvent;
@end
@ -4094,13 +4089,7 @@ static const char* ToEscapedString(NSString* aString, nsCAutoString& aBuf)
ToEscapedString([theEvent characters], str1),
ToEscapedString([theEvent charactersIgnoringModifiers], str2)));
if (!mGeckoChild || !mTextInputHandler)
return;
if (mTextInputHandler->DoesIgnoreNextKeyUpEvent()) {
mTextInputHandler->ResetIgnoreNextKeyUpEvent();
return;
}
NS_ENSURE_TRUE(mGeckoChild, );
nsAutoRetainCocoaObject kungFuDeathGrip(self);
@ -4109,16 +4098,7 @@ static const char* ToEscapedString(NSString* aString, nsCAutoString& aBuf)
return;
}
// if we don't have any characters we can't generate a keyUp event
if ([[theEvent characters] length] == 0 ||
mTextInputHandler->IsIMEComposing()) {
return;
}
nsKeyEvent geckoEvent(PR_TRUE, NS_KEY_UP, mGeckoChild);
mTextInputHandler->InitKeyEvent(theEvent, geckoEvent);
mGeckoChild->DispatchWindowEvent(geckoEvent);
mTextInputHandler->HandleKeyUpEvent(theEvent);
NS_OBJC_END_TRY_ABORT_BLOCK;
}
@ -4127,48 +4107,10 @@ static const char* ToEscapedString(NSString* aString, nsCAutoString& aBuf)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
if (!mGeckoChild)
return;
NS_ENSURE_TRUE(mGeckoChild, );
nsAutoRetainCocoaObject kungFuDeathGrip(self);
// CapsLock state and other modifier states are different:
// CapsLock state does not revert when the CapsLock key goes up, as the
// modifier state does for other modifier keys on key up.
if ([theEvent keyCode] == kCapsLockKeyCode) {
// Fire key down event for caps lock.
[self fireKeyEventForFlagsChanged:theEvent keyDown:YES];
if (!mGeckoChild)
return;
// XXX should we fire keyup event too? The keyup event for CapsLock key
// is never sent to gecko.
} else if ([theEvent type] == NSFlagsChanged) {
// Fire key up/down events for the modifier keys (shift, alt, ctrl, command).
unsigned int modifiers = [theEvent modifierFlags] & NSDeviceIndependentModifierFlagsMask;
const PRUint32 kModifierMaskTable[] =
{ NSShiftKeyMask, NSControlKeyMask, NSAlternateKeyMask, NSCommandKeyMask };
const PRUint32 kModifierCount = sizeof(kModifierMaskTable) /
sizeof(kModifierMaskTable[0]);
for (PRUint32 i = 0; i < kModifierCount; i++) {
PRUint32 modifierBit = kModifierMaskTable[i];
if ((modifiers & modifierBit) != (gLastModifierState & modifierBit)) {
BOOL isKeyDown = (modifiers & modifierBit) != 0 ? YES : NO;
[self fireKeyEventForFlagsChanged:theEvent keyDown:isKeyDown];
if (!mGeckoChild)
return;
// Stop if focus has changed.
// Check to see if we are still the first responder.
if (![self isFirstResponder])
break;
}
}
gLastModifierState = modifiers;
}
mTextInputHandler->HandleFlagsChanged(theEvent);
NS_OBJC_END_TRY_ABORT_BLOCK;
}
@ -4193,50 +4135,6 @@ static const char* ToEscapedString(NSString* aString, nsCAutoString& aBuf)
return dragSession != nsnull;
}
- (void)fireKeyEventForFlagsChanged:(NSEvent*)theEvent keyDown:(BOOL)isKeyDown
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
if (!mGeckoChild || !mTextInputHandler || [theEvent type] != NSFlagsChanged ||
mTextInputHandler->IsIMEComposing()) {
return;
}
nsAutoRetainCocoaObject kungFuDeathGrip(self);
PRUint32 message = isKeyDown ? NS_KEY_DOWN : NS_KEY_UP;
#ifndef NP_NO_CARBON
EventRecord carbonEvent;
#endif // ifndef NP_NO_CARBON
NPCocoaEvent cocoaEvent;
// Fire a key event.
nsKeyEvent geckoEvent(PR_TRUE, message, mGeckoChild);
mTextInputHandler->InitKeyEvent(theEvent, geckoEvent);
// create event for use by plugins
if (mIsPluginView) {
#ifndef NP_NO_CARBON
if (mPluginEventModel == NPEventModelCarbon) {
TextInputHandler::ConvertCocoaKeyEventToCarbonEvent(theEvent,
carbonEvent,
isKeyDown);
geckoEvent.pluginEvent = &carbonEvent;
}
#endif
if (mPluginEventModel == NPEventModelCocoa) {
TextInputHandler::ConvertCocoaKeyEventToNPCocoaEvent(theEvent,
cocoaEvent);
geckoEvent.pluginEvent = &cocoaEvent;
}
}
mGeckoChild->DispatchWindowEvent(geckoEvent);
NS_OBJC_END_TRY_ABORT_BLOCK;
}
- (BOOL)inactiveWindowAcceptsMouseEvent:(NSEvent*)aEvent
{
// If we're being destroyed assume the default -- return YES.