author | Jim Chen <nchen@mozilla.com> |
Thu, 22 Oct 2015 17:45:46 -0400 | |
changeset 269119 | ed18e273554dc11a4bd7ece904a83c61b4b47294 |
parent 269118 | 07bfa35414dcd816198fa935ceed832ce76320fd |
child 269120 | f580afacaa7aded487c709b20293d1b88b2acee4 |
push id | 29572 |
push user | cbook@mozilla.com |
push date | Fri, 23 Oct 2015 09:34:20 +0000 |
treeherder | mozilla-central@0625c68c0abc [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | esawin |
bugs | 1210585 |
milestone | 44.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
widget/android/nsWindow.cpp | file | annotate | diff | comparison | revisions | |
widget/android/nsWindow.h | file | annotate | diff | comparison | revisions |
--- a/widget/android/nsWindow.cpp +++ b/widget/android/nsWindow.cpp @@ -63,16 +63,17 @@ using mozilla::unused; #include "AndroidContentController.h" #include "nsTArray.h" #include "AndroidBridge.h" #include "AndroidBridgeUtilities.h" #include "android_npapi.h" #include "GeneratedJNINatives.h" +#include "KeyEvent.h" #include "imgIEncoder.h" #include "nsString.h" #include "GeckoProfiler.h" // For PROFILER_LABEL #include "nsIXULRuntime.h" using namespace mozilla; @@ -128,19 +129,16 @@ public: return NS_OK; } }; NS_IMPL_ISUPPORTS(ContentCreationNotifier, nsIObserver) -static bool gMenu; -static bool gMenuConsumed; - // All the toplevel windows that have been created; these are in // stacking order, so the window at gAndroidBounds[0] is the topmost // one. static nsTArray<nsWindow*> gTopLevelWindows; // FIXME: because we don't support separate nsWindow for each GeckoView // yet, we have to attach a new GeckoView to an existing nsWindow if it // exists. Eventually, an nsWindow will be opened/closed as each GeckoView @@ -149,60 +147,83 @@ static nsWindow* gGeckoViewWindow; static bool sFailedToCreateGLContext = false; // Multitouch swipe thresholds in inches static const double SWIPE_MAX_PINCH_DELTA_INCHES = 0.4; static const double SWIPE_MIN_DISTANCE_INCHES = 0.6; -class nsWindow::Natives +class nsWindow::Natives final : public GeckoView::Window::Natives<Natives> + , public GeckoEditable::Natives<Natives> , public SupportsWeakPtr<Natives> , public UsesGeckoThreadProxy { - typedef GeckoView::Window::Natives<Natives> Base; - nsWindow& window; public: + typedef GeckoView::Window::Natives<Natives> Base; + typedef GeckoEditable::Natives<Natives> EditableBase; + MOZ_DECLARE_WEAKREFERENCE_TYPENAME(Natives); template<typename Functor> static void OnNativeCall(Functor&& call) { if (call.IsTarget(&Open) && NS_IsMainThread()) { // Gecko state probably just switched to PROFILE_READY, and the // event loop is not running yet. Skip the event loop here so we // can get a head start on opening our window. return call(); } return UsesGeckoThreadProxy::OnNativeCall(mozilla::Move(call)); } Natives(nsWindow* w) : window(*w) {} - + ~Natives(); + + /** + * GeckoView methods + */ // Detach and destroy the window that we created in Open(). void DisposeNative(const GeckoView::Window::LocalRef& instance); // Create and attach a window. static void Open(const jni::ClassObject::LocalRef& cls, GeckoView::Window::Param gvWindow, GeckoView::Param view, int32_t width, int32_t height); // Set the active layer client object static void SetLayerClient(jni::Object::Param client) { MOZ_ASSERT(NS_IsMainThread()); AndroidBridge::Bridge()->SetLayerClient( widget::GeckoLayerClient::Ref::From(client.Get())); } + + /** + * GeckoEditable methods + */ + // Handle an Android KeyEvent. + void OnKeyEvent(int32_t action, int32_t keyCode, int32_t scanCode, + int32_t metaState, int64_t time, int32_t unicodeChar, + int32_t baseUnicodeChar, int32_t domPrintableKeyValue, + int32_t repeatCount, int32_t flags, + bool isSynthesizedImeKey); }; +nsWindow::Natives::~Natives() +{ + // Disassociate our GeckoEditable instance with our native object. + MOZ_ASSERT(mEditable); + EditableBase::DisposeNative(mEditable); +} + void nsWindow::Natives::Open(const jni::ClassObject::LocalRef& cls, GeckoView::Window::Param gvWindow, GeckoView::Param view, int32_t width, int32_t height) { MOZ_ASSERT(NS_IsMainThread()); @@ -211,18 +232,18 @@ nsWindow::Natives::Open(const jni::Class if (gGeckoViewWindow) { // Should have been created the first time. MOZ_ASSERT(gGeckoViewWindow->mNatives); // Associate our previous GeckoEditable with the new GeckoView. gGeckoViewWindow->mEditable->OnViewChange(view); - AttachNative(GeckoView::Window::LocalRef(cls.Env(), gvWindow), - gGeckoViewWindow->mNatives.get()); + Base::AttachNative(GeckoView::Window::LocalRef(cls.Env(), gvWindow), + gGeckoViewWindow->mNatives.get()); return; } nsCOMPtr<nsIWindowWatcher> ww = do_GetService(NS_WINDOWWATCHER_CONTRACTID); MOZ_ASSERT(ww); nsAdoptingCString url = Preferences::GetCString("toolkit.defaultChromeURI"); if (!url) { @@ -252,21 +273,23 @@ nsWindow::Natives::Open(const jni::Class nsCOMPtr<nsIWidget> widget = WidgetUtils::DOMWindowToWidget(window); MOZ_ASSERT(widget); gGeckoViewWindow = static_cast<nsWindow*>(widget.get()); gGeckoViewWindow->mNatives = mozilla::MakeUnique<Natives>(gGeckoViewWindow); // Create GeckoEditable for the new nsWindow/GeckoView pair. - gGeckoViewWindow->mEditable = GeckoEditable::New(); - gGeckoViewWindow->mEditable->OnViewChange(view); - - AttachNative(GeckoView::Window::LocalRef(cls.Env(), gvWindow), - gGeckoViewWindow->mNatives.get()); + GeckoEditable::LocalRef editable = GeckoEditable::New(); + EditableBase::AttachNative(editable, gGeckoViewWindow->mNatives.get()); + editable->OnViewChange(view); + gGeckoViewWindow->mEditable = editable; + + Base::AttachNative(GeckoView::Window::LocalRef(cls.Env(), gvWindow), + gGeckoViewWindow->mNatives.get()); } void nsWindow::Natives::DisposeNative(const GeckoView::Window::LocalRef& instance) { // FIXME: because we don't support separate nsWindow for each GeckoView // yet, we have to keep this window around in case another GeckoView // wants to attach. @@ -281,17 +304,18 @@ nsWindow::Natives::DisposeNative(const G } */ Base::DisposeNative(instance); } void nsWindow::InitNatives() { - nsWindow::Natives::Init(); + nsWindow::Natives::Base::Init(); + nsWindow::Natives::EditableBase::Init(); } nsWindow* nsWindow::TopWindow() { if (!gTopLevelWindows.IsEmpty()) return gTopLevelWindows[0]; return nullptr; @@ -405,16 +429,21 @@ nsWindow::Create(nsIWidget *aParent, return NS_OK; } NS_IMETHODIMP nsWindow::Destroy(void) { nsBaseWidget::mOnDestroyCalled = true; + if (mNatives) { + // Disassociate our native object with GeckoView. + mNatives = nullptr; + } + while (mChildren.Length()) { // why do we still have children? ALOG("### Warning: Destroying window %p and reparenting child %p to null!", (void*)this, (void*)mChildren[0]); mChildren[0]->SetParent(nullptr); } if (IsTopLevel()) gTopLevelWindows.RemoveElement(this); @@ -1011,33 +1040,21 @@ nsWindow::OnGlobalAndroidEvent(AndroidGe break; } case AndroidGeckoEvent::NATIVE_GESTURE_EVENT: { win->OnNativeGestureEvent(ae); break; } - case AndroidGeckoEvent::KEY_EVENT: - win->UserActivity(); - win->OnKeyEvent(ae); - break; - case AndroidGeckoEvent::IME_EVENT: gGeckoViewWindow->UserActivity(); gGeckoViewWindow->OnIMEEvent(ae); break; - case AndroidGeckoEvent::IME_KEY_EVENT: - // Keys synthesized by Java IME code are saved in the mIMEKeyEvents - // array until the next IME_REPLACE_TEXT event, at which point - // these keys are dispatched in sequence. - win->mIMEKeyEvents.AppendElement(*ae); - break; - case AndroidGeckoEvent::COMPOSITOR_PAUSE: // The compositor gets paused when the app is about to go into the // background. While the compositor is paused, we need to ensure that // no layer tree updates (from draw events) occur, since the compositor // cannot make a GL context current in order to process updates. if (sCompositorChild) { sCompositorChild->SendPause(); } @@ -1424,19 +1441,19 @@ static unsigned int ConvertAndroidKeyCod default: ALOG("ConvertAndroidKeyCodeToDOMKeyCode: " "No DOM keycode for Android keycode %d", androidKeyCode); return 0; } } static KeyNameIndex -ConvertAndroidKeyCodeToKeyNameIndex(AndroidGeckoEvent& aAndroidGeckoEvent) +ConvertAndroidKeyCodeToKeyNameIndex(int keyCode, int action, + int domPrintableKeyValue) { - int keyCode = aAndroidGeckoEvent.KeyCode(); // Special-case alphanumeric keycodes because they are most common. if (keyCode >= AKEYCODE_A && keyCode <= AKEYCODE_Z) { return KEY_NAME_INDEX_USE_STRING; } if (keyCode >= AKEYCODE_0 && keyCode <= AKEYCODE_9) { return KEY_NAME_INDEX_USE_STRING; } @@ -1541,251 +1558,206 @@ ConvertAndroidKeyCodeToKeyNameIndex(Andr case AKEYCODE_MANNER_MODE: case AKEYCODE_3D_MODE: case AKEYCODE_CONTACTS: return KEY_NAME_INDEX_Unidentified; case AKEYCODE_UNKNOWN: MOZ_ASSERT( - aAndroidGeckoEvent.Action() != AKEY_EVENT_ACTION_MULTIPLE, + action != AKEY_EVENT_ACTION_MULTIPLE, "Don't call this when action is AKEY_EVENT_ACTION_MULTIPLE!"); // It's actually an unknown key if the action isn't ACTION_MULTIPLE. // However, it might cause text input. So, let's check the value. - return aAndroidGeckoEvent.DOMPrintableKeyValue() ? + return domPrintableKeyValue ? KEY_NAME_INDEX_USE_STRING : KEY_NAME_INDEX_Unidentified; default: ALOG("ConvertAndroidKeyCodeToKeyNameIndex: " "No DOM key name index for Android keycode %d", keyCode); return KEY_NAME_INDEX_Unidentified; } } static CodeNameIndex -ConvertAndroidScanCodeToCodeNameIndex(AndroidGeckoEvent& aAndroidGeckoEvent) +ConvertAndroidScanCodeToCodeNameIndex(int scanCode) { - switch (aAndroidGeckoEvent.ScanCode()) { + switch (scanCode) { #define NS_NATIVE_KEY_TO_DOM_CODE_NAME_INDEX(aNativeKey, aCodeNameIndex) \ case aNativeKey: return aCodeNameIndex; #include "NativeKeyToDOMCodeName.h" #undef NS_NATIVE_KEY_TO_DOM_CODE_NAME_INDEX default: return CODE_NAME_INDEX_UNKNOWN; } } -static void InitPluginEvent(ANPEvent* pluginEvent, ANPKeyActions keyAction, - AndroidGeckoEvent& key) +static bool +IsModifierKey(int32_t keyCode) +{ + using mozilla::widget::sdk::KeyEvent; + return keyCode == KeyEvent::KEYCODE_ALT_LEFT || + keyCode == KeyEvent::KEYCODE_ALT_RIGHT || + keyCode == KeyEvent::KEYCODE_SHIFT_LEFT || + keyCode == KeyEvent::KEYCODE_SHIFT_RIGHT || + keyCode == KeyEvent::KEYCODE_CTRL_LEFT || + keyCode == KeyEvent::KEYCODE_CTRL_RIGHT || + keyCode == KeyEvent::KEYCODE_META_LEFT || + keyCode == KeyEvent::KEYCODE_META_RIGHT; +} + +static Modifiers +GetModifiers(int32_t metaState) { - int androidKeyCode = key.KeyCode(); - uint32_t domKeyCode = ConvertAndroidKeyCodeToDOMKeyCode(androidKeyCode); - - int modifiers = 0; - if (key.IsAltPressed()) - modifiers |= kAlt_ANPKeyModifier; - if (key.IsShiftPressed()) - modifiers |= kShift_ANPKeyModifier; - - pluginEvent->inSize = sizeof(ANPEvent); - pluginEvent->eventType = kKey_ANPEventType; - pluginEvent->data.key.action = keyAction; - pluginEvent->data.key.nativeCode = androidKeyCode; - pluginEvent->data.key.virtualCode = domKeyCode; - pluginEvent->data.key.unichar = key.UnicodeChar(); - pluginEvent->data.key.modifiers = modifiers; - pluginEvent->data.key.repeatCount = key.RepeatCount(); + using mozilla::widget::sdk::KeyEvent; + return (metaState & KeyEvent::META_ALT_MASK ? MODIFIER_ALT : 0) + | (metaState & KeyEvent::META_SHIFT_MASK ? MODIFIER_SHIFT : 0) + | (metaState & KeyEvent::META_CTRL_MASK ? MODIFIER_CONTROL : 0) + | (metaState & KeyEvent::META_META_MASK ? MODIFIER_META : 0) + | (metaState & KeyEvent::META_FUNCTION_ON ? MODIFIER_FN : 0) + | (metaState & KeyEvent::META_CAPS_LOCK_ON ? MODIFIER_CAPSLOCK : 0) + | (metaState & KeyEvent::META_NUM_LOCK_ON ? MODIFIER_NUMLOCK : 0) + | (metaState & KeyEvent::META_SCROLL_LOCK_ON ? MODIFIER_SCROLLLOCK : 0); } -void -nsWindow::InitKeyEvent(WidgetKeyboardEvent& event, AndroidGeckoEvent& key, - ANPEvent* pluginEvent) +static void +InitKeyEvent(WidgetKeyboardEvent& event, + int32_t action, int32_t keyCode, int32_t scanCode, + int32_t metaState, int64_t time, int32_t unicodeChar, + int32_t baseUnicodeChar, int32_t domPrintableKeyValue, + int32_t repeatCount, int32_t flags) { - event.mKeyNameIndex = ConvertAndroidKeyCodeToKeyNameIndex(key); - if (event.mKeyNameIndex == KEY_NAME_INDEX_USE_STRING) { - int keyValue = key.DOMPrintableKeyValue(); - if (keyValue) { - event.mKeyValue = static_cast<char16_t>(keyValue); - } - } - event.mCodeNameIndex = ConvertAndroidScanCodeToCodeNameIndex(key); - uint32_t domKeyCode = ConvertAndroidKeyCodeToDOMKeyCode(key.KeyCode()); + const uint32_t domKeyCode = ConvertAndroidKeyCodeToDOMKeyCode(keyCode); + const int32_t charCode = unicodeChar ? unicodeChar : baseUnicodeChar; + + event.modifiers = GetModifiers(metaState); if (event.mMessage == eKeyPress) { // Android gives us \n, so filter out some control characters. - int charCode = key.UnicodeChar(); - if (!charCode) { - charCode = key.BaseUnicodeChar(); - } event.isChar = (charCode >= ' '); event.charCode = event.isChar ? charCode : 0; - event.keyCode = (event.charCode > 0) ? 0 : domKeyCode; + event.keyCode = event.isChar ? 0 : domKeyCode; event.mPluginEvent.Clear(); - } else { -#ifdef DEBUG - if (event.mMessage != eKeyDown && event.mMessage != eKeyUp) { - ALOG("InitKeyEvent: unexpected event.mMessage %d", event.mMessage); + + // For keypress, if the unicode char already has modifiers applied, we + // don't specify extra modifiers. If UnicodeChar() != BaseUnicodeChar() + // it means UnicodeChar() already has modifiers applied. + // Note that on Android 4.x, Alt modifier isn't set when the key input + // causes text input even while right Alt key is pressed. However, + // this is necessary for Android 2.3 compatibility. + if (unicodeChar && unicodeChar != baseUnicodeChar) { + event.modifiers &= ~(MODIFIER_ALT | MODIFIER_CONTROL + | MODIFIER_META); } -#endif // DEBUG - - // Flash will want a pluginEvent for keydown and keyup events. - ANPKeyActions action = event.mMessage == eKeyDown - ? kDown_ANPKeyAction - : kUp_ANPKeyAction; - InitPluginEvent(pluginEvent, action, key); - + + } else { event.isChar = false; event.charCode = 0; event.keyCode = domKeyCode; - event.mPluginEvent.Copy(*pluginEvent); - } - - event.modifiers = key.DOMModifiers(); - if (gMenu) { - event.modifiers |= MODIFIER_CONTROL; - } - // For keypress, if the unicode char already has modifiers applied, we - // don't specify extra modifiers. If UnicodeChar() != BaseUnicodeChar() - // it means UnicodeChar() already has modifiers applied. - // Note that on Android 4.x, Alt modifier isn't set when the key input - // causes text input even while right Alt key is pressed. However, this - // is necessary for Android 2.3 compatibility. - if (event.mMessage == eKeyPress && - key.UnicodeChar() && key.UnicodeChar() != key.BaseUnicodeChar()) { - event.modifiers &= ~(MODIFIER_ALT | MODIFIER_CONTROL | MODIFIER_META); + + ANPEvent pluginEvent; + pluginEvent.inSize = sizeof(pluginEvent); + pluginEvent.eventType = kKey_ANPEventType; + pluginEvent.data.key.action = event.mMessage == eKeyDown + ? kDown_ANPKeyAction : kUp_ANPKeyAction; + pluginEvent.data.key.nativeCode = keyCode; + pluginEvent.data.key.virtualCode = domKeyCode; + pluginEvent.data.key.unichar = charCode; + pluginEvent.data.key.modifiers = + (metaState & sdk::KeyEvent::META_SHIFT_MASK + ? kShift_ANPKeyModifier : 0) | + (metaState & sdk::KeyEvent::META_ALT_MASK + ? kAlt_ANPKeyModifier : 0); + pluginEvent.data.key.repeatCount = repeatCount; + event.mPluginEvent.Copy(pluginEvent); } event.mIsRepeat = (event.mMessage == eKeyDown || event.mMessage == eKeyPress) && - (!!(key.Flags() & AKEY_EVENT_FLAG_LONG_PRESS) || !!key.RepeatCount()); + ((flags & sdk::KeyEvent::FLAG_LONG_PRESS) || repeatCount); + + event.mKeyNameIndex = ConvertAndroidKeyCodeToKeyNameIndex( + keyCode, action, domPrintableKeyValue); + event.mCodeNameIndex = ConvertAndroidScanCodeToCodeNameIndex(scanCode); + + if (event.mKeyNameIndex == KEY_NAME_INDEX_USE_STRING && + domPrintableKeyValue) { + event.mKeyValue = char16_t(domPrintableKeyValue); + } + event.location = WidgetKeyboardEvent::ComputeLocationFromCodeValue(event.mCodeNameIndex); - event.time = key.Time(); - - if (gMenu) - gMenuConsumed = true; + event.time = time; } void -nsWindow::HandleSpecialKey(AndroidGeckoEvent *ae) +nsWindow::Natives::OnKeyEvent(int32_t action, int32_t keyCode, int32_t scanCode, + int32_t metaState, int64_t time, + int32_t unicodeChar, int32_t baseUnicodeChar, + int32_t domPrintableKeyValue, int32_t repeatCount, + int32_t flags, bool isSynthesizedImeKey) { - RefPtr<nsWindow> kungFuDeathGrip(this); - nsCOMPtr<nsIAtom> command; - bool isDown = ae->Action() == AKEY_EVENT_ACTION_DOWN; - bool isLongPress = !!(ae->Flags() & AKEY_EVENT_FLAG_LONG_PRESS); - bool doCommand = false; - uint32_t keyCode = ae->KeyCode(); - - if (isDown) { - switch (keyCode) { - case AKEYCODE_BACK: - if (isLongPress) { - command = nsGkAtoms::Clear; - doCommand = true; - } - break; - case AKEYCODE_MENU: - gMenu = true; - gMenuConsumed = isLongPress; - break; - } - } else { - switch (keyCode) { - case AKEYCODE_BACK: { - // XXX Where is the keydown event for this?? - WidgetKeyboardEvent pressEvent(true, eKeyPress, this); - ANPEvent pluginEvent; - InitKeyEvent(pressEvent, *ae, &pluginEvent); - DispatchEvent(&pressEvent); - return; - } - case AKEYCODE_MENU: - gMenu = false; - if (!gMenuConsumed) { - command = nsGkAtoms::Menu; - doCommand = true; - } - break; - case AKEYCODE_SEARCH: - command = nsGkAtoms::Search; - doCommand = true; - break; - default: - ALOG("Unknown special key code!"); - return; - } - } - if (doCommand) { - WidgetCommandEvent event(true, nsGkAtoms::onAppCommand, command, this); - InitEvent(event); - DispatchEvent(&event); - } -} - -void -nsWindow::OnKeyEvent(AndroidGeckoEvent *ae) -{ - RefPtr<nsWindow> kungFuDeathGrip(this); - RemoveIMEComposition(); + RefPtr<nsWindow> kungFuDeathGrip(&window); + window.UserActivity(); + window.RemoveIMEComposition(); + EventMessage msg; - switch (ae->Action()) { - case AKEY_EVENT_ACTION_DOWN: + if (action == sdk::KeyEvent::ACTION_DOWN) { msg = eKeyDown; - break; - case AKEY_EVENT_ACTION_UP: + } else if (action == sdk::KeyEvent::ACTION_UP) { msg = eKeyUp; - break; - case AKEY_EVENT_ACTION_MULTIPLE: + } else if (action == sdk::KeyEvent::ACTION_MULTIPLE) { // Keys with multiple action are handled in Java, // and we should never see one here MOZ_CRASH("Cannot handle key with multiple action"); - default: + } else { ALOG("Unknown key action event!"); return; } - bool firePress = ae->Action() == AKEY_EVENT_ACTION_DOWN; - switch (ae->KeyCode()) { - case AKEYCODE_SHIFT_LEFT: - case AKEYCODE_SHIFT_RIGHT: - case AKEYCODE_ALT_LEFT: - case AKEYCODE_ALT_RIGHT: - case AKEYCODE_CTRL_LEFT: - case AKEYCODE_CTRL_RIGHT: - firePress = false; - break; - case AKEYCODE_BACK: - case AKEYCODE_MENU: - case AKEYCODE_SEARCH: - HandleSpecialKey(ae); + nsEventStatus status = nsEventStatus_eIgnore; + WidgetKeyboardEvent event(true, msg, &window); + window.InitEvent(event, nullptr); + InitKeyEvent(event, action, keyCode, scanCode, metaState, time, + unicodeChar, baseUnicodeChar, domPrintableKeyValue, + repeatCount, flags); + + if (isSynthesizedImeKey) { + // Keys synthesized by Java IME code are saved in the mIMEKeyEvents + // array until the next IME_REPLACE_TEXT event, at which point + // these keys are dispatched in sequence. + window.mIMEKeyEvents.AppendElement( + mozilla::UniquePtr<WidgetEvent>(event.Duplicate())); + } else { + window.DispatchEvent(&event, status); + } + + if (window.Destroyed() || + status == nsEventStatus_eConsumeNoDefault || + msg != eKeyDown || IsModifierKey(keyCode)) { + // Skip sending key press event. return; } - nsEventStatus status; - WidgetKeyboardEvent event(true, msg, this); - ANPEvent pluginEvent; - InitKeyEvent(event, *ae, &pluginEvent); - DispatchEvent(&event, status); - - if (Destroyed()) - return; - if (!firePress || status == nsEventStatus_eConsumeNoDefault) { - return; + WidgetKeyboardEvent pressEvent(true, eKeyPress, &window); + window.InitEvent(pressEvent, nullptr); + InitKeyEvent(pressEvent, action, keyCode, scanCode, metaState, time, + unicodeChar, baseUnicodeChar, domPrintableKeyValue, + repeatCount, flags); + + if (isSynthesizedImeKey) { + window.mIMEKeyEvents.AppendElement( + mozilla::UniquePtr<WidgetEvent>(pressEvent.Duplicate())); + } else { + window.DispatchEvent(&pressEvent, status); } - - WidgetKeyboardEvent pressEvent(true, eKeyPress, this); - InitKeyEvent(pressEvent, *ae, &pluginEvent); -#ifdef DEBUG_ANDROID_WIDGET - __android_log_print(ANDROID_LOG_INFO, "Gecko", "Dispatching key pressEvent with keyCode %d charCode %d shift %d alt %d sym/ctrl %d metamask %d", pressEvent.keyCode, pressEvent.charCode, pressEvent.IsShift(), pressEvent.IsAlt(), pressEvent.IsControl(), ae->MetaState()); -#endif - DispatchEvent(&pressEvent); } #ifdef DEBUG_ANDROID_IME #define ALOGIME(args...) ALOG(args) #else #define ALOGIME(args...) ((void)0) #endif @@ -1844,20 +1816,22 @@ nsWindow::RemoveIMEComposition() * Send dummy key events for pages that are unaware of input events, * to provide web compatibility for pages that depend on key events. * Our dummy key events have 0 as the keycode. */ void nsWindow::SendIMEDummyKeyEvents() { WidgetKeyboardEvent downEvent(true, eKeyDown, this); + InitEvent(downEvent, nullptr); MOZ_ASSERT(downEvent.keyCode == 0); DispatchEvent(&downEvent); WidgetKeyboardEvent upEvent(true, eKeyUp, this); + InitEvent(upEvent, nullptr); MOZ_ASSERT(upEvent.keyCode == 0); DispatchEvent(&upEvent); } void nsWindow::OnIMEEvent(AndroidGeckoEvent *ae) { MOZ_ASSERT(!mIMEMaskSelectionUpdate); @@ -1959,18 +1933,23 @@ nsWindow::OnIMEEvent(AndroidGeckoEvent * InitEvent(event, nullptr); event.mOffset = uint32_t(ae->Start()); event.mLength = uint32_t(ae->End() - ae->Start()); event.mExpandToClusterBoundary = false; DispatchEvent(&event); } if (!mIMEKeyEvents.IsEmpty()) { + nsEventStatus status; for (uint32_t i = 0; i < mIMEKeyEvents.Length(); i++) { - OnKeyEvent(&mIMEKeyEvents[i]); + const auto event = static_cast<WidgetGUIEvent*>( + mIMEKeyEvents[i].get()); + // widget for duplicated events is initially nullptr. + event->widget = this; + DispatchEvent(event, status); } mIMEKeyEvents.Clear(); FlushIMEChanges(); mEditable->NotifyIME( GeckoEditableListener::NOTIFY_IME_REPLY_EVENT); // Break out of the switch block break; }
--- a/widget/android/nsWindow.h +++ b/widget/android/nsWindow.h @@ -57,17 +57,16 @@ public: static mozilla::gfx::IntSize GetAndroidScreenBounds(); static nsWindow* TopWindow(); bool OnContextmenuEvent(mozilla::AndroidGeckoEvent *ae); void OnLongTapEvent(mozilla::AndroidGeckoEvent *ae); bool OnMultitouchEvent(mozilla::AndroidGeckoEvent *ae); void OnNativeGestureEvent(mozilla::AndroidGeckoEvent *ae); void OnMouseEvent(mozilla::AndroidGeckoEvent *ae); - void OnKeyEvent(mozilla::AndroidGeckoEvent *ae); void OnIMEEvent(mozilla::AndroidGeckoEvent *ae); void OnSizeChanged(const mozilla::gfx::IntSize& aSize); void InitEvent(mozilla::WidgetGUIEvent& event, nsIntPoint* aPoint = 0); // // nsIWidget @@ -238,37 +237,33 @@ protected: double mLastDist; nsCOMPtr<nsIIdleServiceInternal> mIdleService; bool mIMEMaskSelectionUpdate; int32_t mIMEMaskEventsCount; // Mask events when > 0 RefPtr<mozilla::TextRangeArray> mIMERanges; bool mIMEUpdatingContext; - nsAutoTArray<mozilla::AndroidGeckoEvent, 8> mIMEKeyEvents; + nsAutoTArray<mozilla::UniquePtr<mozilla::WidgetEvent>, 8> mIMEKeyEvents; nsAutoTArray<IMEChange, 4> mIMETextChanges; bool mIMESelectionChanged; bool mAwaitingFullScreen; bool mIsFullScreen; InputContext mInputContext; virtual nsresult NotifyIMEInternal( const IMENotification& aIMENotification) override; static void DumpWindows(); static void DumpWindows(const nsTArray<nsWindow*>& wins, int indent = 0); static void LogWindow(nsWindow *win, int index, int indent); private: - void InitKeyEvent(mozilla::WidgetKeyboardEvent& event, - mozilla::AndroidGeckoEvent& key, - ANPEvent* pluginEvent); - void HandleSpecialKey(mozilla::AndroidGeckoEvent *ae); void CreateLayerManager(int aCompositorWidth, int aCompositorHeight); void RedrawAll(); mozilla::AndroidLayerRendererFrame mLayerRendererFrame; static mozilla::StaticRefPtr<mozilla::layers::APZCTreeManager> sApzcTreeManager; static mozilla::StaticRefPtr<mozilla::layers::LayerManager> sLayerManager; static mozilla::StaticRefPtr<mozilla::layers::CompositorParent> sCompositorParent;