author | Masayuki Nakano <masayuki@d-toybox.com> |
Fri, 19 May 2017 17:49:41 +0900 | |
changeset 359282 | b75c111837a802ceb953dba50a3c5a193d53ca22 |
parent 359281 | a950fbfa6d8cb1c3287a5ed14b4b09d497057224 |
child 359283 | 8d32e150bf7fe9b0db1c37174c70b352ce34812e |
push id | 31851 |
push user | kwierso@gmail.com |
push date | Fri, 19 May 2017 21:18:45 +0000 |
treeherder | mozilla-central@5a8f2dcbeac0 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | smaug |
bugs | 1339543 |
milestone | 55.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
|
--- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -1873,31 +1873,47 @@ TabChild::RecvPluginEvent(const WidgetPl if (status != nsEventStatus_eConsumeNoDefault) { // If not consumed, we should call default action SendDefaultProcOfPluginEvent(aEvent); } return IPC_OK(); } void -TabChild::RequestNativeKeyBindings(AutoCacheNativeKeyCommands* aAutoCache, - const WidgetKeyboardEvent* aEvent) +TabChild::RequestNativeKeyBindings(nsIWidget::NativeKeyBindingsType aType, + const WidgetKeyboardEvent& aEvent, + nsTArray<CommandInt>& aCommands) { - MaybeNativeKeyBinding maybeBindings; - if (!SendRequestNativeKeyBindings(*aEvent, &maybeBindings)) { + MOZ_ASSERT(aCommands.IsEmpty()); + + if (NS_WARN_IF(aEvent.IsEditCommandsInitialized(aType))) { + aCommands = aEvent.EditCommandsConstRef(aType); return; } - if (maybeBindings.type() == MaybeNativeKeyBinding::TNativeKeyBinding) { - const NativeKeyBinding& bindings = maybeBindings; - aAutoCache->Cache(bindings.singleLineCommands(), - bindings.multiLineCommands(), - bindings.richTextCommands()); - } else { - aAutoCache->CacheNoCommands(); + // TODO: Should retrieve edit commands only for specific type. + MaybeNativeKeyBinding maybeBindings; + if (!SendRequestNativeKeyBindings(aEvent, &maybeBindings) || + maybeBindings.type() != MaybeNativeKeyBinding::TNativeKeyBinding) { + return; + } + + const NativeKeyBinding& bindings = maybeBindings; + switch (aType) { + case nsIWidget::NativeKeyBindingsForSingleLineEditor: + aCommands = bindings.singleLineCommands(); + break; + case nsIWidget::NativeKeyBindingsForMultiLineEditor: + aCommands = bindings.multiLineCommands(); + break; + case nsIWidget::NativeKeyBindingsForRichTextEditor: + aCommands = bindings.richTextCommands(); + break; + default: + MOZ_ASSERT_UNREACHABLE("Invalid native key bindings type"); } } mozilla::ipc::IPCResult TabChild::RecvNativeSynthesisResponse(const uint64_t& aObserverId, const nsCString& aResponse) { mozilla::widget::AutoObserverNotifier::NotifySavedObserver(aObserverId,
--- a/dom/ipc/TabChild.h +++ b/dom/ipc/TabChild.h @@ -506,18 +506,19 @@ public: void GetMaxTouchPoints(uint32_t* aTouchPoints); ScreenOrientationInternal GetOrientation() const { return mOrientation; } void SetBackgroundColor(const nscolor& aColor); void NotifyPainted(); - void RequestNativeKeyBindings(mozilla::widget::AutoCacheNativeKeyCommands* aAutoCache, - const WidgetKeyboardEvent* aEvent); + void RequestNativeKeyBindings(nsIWidget::NativeKeyBindingsType aType, + const WidgetKeyboardEvent& aEvent, + nsTArray<CommandInt>& aCommands); /** * Signal to this TabChild that it should be made visible: * activated widget, retained layer tree, etc. (Respectively, * made not visible.) */ void MakeVisible(); void MakeHidden();
--- a/dom/ipc/TabParent.cpp +++ b/dom/ipc/TabParent.cpp @@ -1209,54 +1209,45 @@ TabParent::RecvDispatchKeyboardEvent(con WidgetKeyboardEvent localEvent(aEvent); localEvent.mWidget = widget; localEvent.mRefPoint -= GetChildProcessOffset(); widget->DispatchInputEvent(&localEvent); return IPC_OK(); } -static void -DoCommandCallback(mozilla::Command aCommand, void* aData) -{ - static_cast<InfallibleTArray<mozilla::CommandInt>*>(aData)-> - AppendElement(aCommand); -} - mozilla::ipc::IPCResult TabParent::RecvRequestNativeKeyBindings(const WidgetKeyboardEvent& aEvent, MaybeNativeKeyBinding* aBindings) { - AutoTArray<mozilla::CommandInt, 4> singleLine; - AutoTArray<mozilla::CommandInt, 4> multiLine; - AutoTArray<mozilla::CommandInt, 4> richText; - *aBindings = mozilla::void_t(); nsCOMPtr<nsIWidget> widget = GetWidget(); if (!widget) { return IPC_OK(); } WidgetKeyboardEvent localEvent(aEvent); + localEvent.mWidget = widget; if (NS_FAILED(widget->AttachNativeKeyEvent(localEvent))) { return IPC_OK(); } - widget->ExecuteNativeKeyBinding( - nsIWidget::NativeKeyBindingsForSingleLineEditor, - localEvent, DoCommandCallback, &singleLine); - widget->ExecuteNativeKeyBinding( - nsIWidget::NativeKeyBindingsForMultiLineEditor, - localEvent, DoCommandCallback, &multiLine); - widget->ExecuteNativeKeyBinding( - nsIWidget::NativeKeyBindingsForRichTextEditor, - localEvent, DoCommandCallback, &richText); - + localEvent.InitAllEditCommands(); + + const nsTArray<CommandInt>& multiLine = + localEvent.EditCommandsConstRef( + nsIWidget::NativeKeyBindingsForSingleLineEditor); + const nsTArray<CommandInt>& singleLine = + localEvent.EditCommandsConstRef( + nsIWidget::NativeKeyBindingsForMultiLineEditor); + const nsTArray<CommandInt>& richText = + localEvent.EditCommandsConstRef( + nsIWidget::NativeKeyBindingsForRichTextEditor); if (!singleLine.IsEmpty() || !multiLine.IsEmpty() || !richText.IsEmpty()) { *aBindings = NativeKeyBinding(singleLine, multiLine, richText); } return IPC_OK(); } class SynthesizedEventObserver : public nsIObserver
--- a/widget/PuppetWidget.cpp +++ b/widget/PuppetWidget.cpp @@ -544,60 +544,25 @@ PuppetWidget::UpdateZoomConstraints(cons } bool PuppetWidget::AsyncPanZoomEnabled() const { return mTabChild && mTabChild->AsyncPanZoomEnabled(); } -bool -PuppetWidget::ExecuteNativeKeyBinding( - NativeKeyBindingsType aType, - const mozilla::WidgetKeyboardEvent& aEvent, - DoCommandCallback aCallback, - void* aCallbackData) +void +PuppetWidget::GetEditCommands(NativeKeyBindingsType aType, + const WidgetKeyboardEvent& aEvent, + nsTArray<CommandInt>& aCommands) { - MOZ_ASSERT(!aEvent.IsEditCommandsInitialized(aType)); - - AutoCacheNativeKeyCommands autoCache(this); - if (!mNativeKeyCommandsValid) { - // Abort if untrusted to avoid leaking system settings - if (NS_WARN_IF(!aEvent.IsTrusted())) { - return false; - } - mTabChild->RequestNativeKeyBindings(&autoCache, &aEvent); - } - - MOZ_ASSERT(mNativeKeyCommandsValid); + // Validate the arguments. + nsIWidget::GetEditCommands(aType, aEvent, aCommands); - const nsTArray<mozilla::CommandInt>* commands = nullptr; - switch (aType) { - case nsIWidget::NativeKeyBindingsForSingleLineEditor: - commands = &mSingleLineCommands; - break; - case nsIWidget::NativeKeyBindingsForMultiLineEditor: - commands = &mMultiLineCommands; - break; - case nsIWidget::NativeKeyBindingsForRichTextEditor: - commands = &mRichTextCommands; - break; - default: - MOZ_CRASH("Invalid type"); - break; - } - - if (commands->IsEmpty()) { - return false; - } - - for (uint32_t i = 0; i < commands->Length(); i++) { - aCallback(static_cast<mozilla::Command>((*commands)[i]), aCallbackData); - } - return true; + mTabChild->RequestNativeKeyBindings(aType, aEvent, aCommands); } LayerManager* PuppetWidget::GetLayerManager(PLayerTransactionChild* aShadowManager, LayersBackend aBackendHint, LayerManagerPersistence aPersistence) { if (!mLayerManager) {
--- a/widget/PuppetWidget.h +++ b/widget/PuppetWidget.h @@ -152,21 +152,20 @@ public: nsEventStatus DispatchInputEvent(WidgetInputEvent* aEvent) override; void SetConfirmedTargetAPZC(uint64_t aInputBlockId, const nsTArray<ScrollableLayerGuid>& aTargets) const override; void UpdateZoomConstraints(const uint32_t& aPresShellId, const FrameMetrics::ViewID& aViewId, const mozilla::Maybe<ZoomConstraints>& aConstraints) override; bool AsyncPanZoomEnabled() const override; - virtual bool - ExecuteNativeKeyBinding(NativeKeyBindingsType aType, - const mozilla::WidgetKeyboardEvent& aEvent, - DoCommandCallback aCallback, - void* aCallbackData) override; + virtual void GetEditCommands( + NativeKeyBindingsType aType, + const mozilla::WidgetKeyboardEvent& aEvent, + nsTArray<mozilla::CommandInt>& aCommands) override; friend struct AutoCacheNativeKeyCommands; // // nsBaseWidget methods we override // // Documents loaded in child processes are always subdocuments of
--- a/widget/TextEvents.h +++ b/widget/TextEvents.h @@ -304,28 +304,37 @@ public: mEditCommandsForSingleLineEditor.Clear(); mEditCommandsForMultiLineEditor.Clear(); mEditCommandsForRichTextEditor.Clear(); mEditCommandsForSingleLineEditorInitialized = true; mEditCommandsForMultiLineEditorInitialized = true; mEditCommandsForRichTextEditorInitialized = true; } -#ifdef DEBUG + /** + * EditCommandsConstRef() returns reference to edit commands for aType. + */ + const nsTArray<CommandInt>& + EditCommandsConstRef(nsIWidget::NativeKeyBindingsType aType) const + { + return const_cast<WidgetKeyboardEvent*>(this)->EditCommandsRef(aType); + } + /** * IsEditCommandsInitialized() returns true if edit commands for aType * was already initialized. Otherwise, false. */ bool IsEditCommandsInitialized( nsIWidget::NativeKeyBindingsType aType) const { return const_cast<WidgetKeyboardEvent*>(this)-> IsEditCommandsInitializedRef(aType); } +#ifdef DEBUG /** * AreAllEditCommandsInitialized() returns true if edit commands for all * types were already initialized. Otherwise, false. */ bool AreAllEditCommandsInitialized() const { return mEditCommandsForSingleLineEditorInitialized && mEditCommandsForMultiLineEditorInitialized && @@ -334,18 +343,19 @@ public: #endif // #ifdef DEBUG /** * Execute edit commands for aType. * * @return true if the caller should do nothing anymore. * false, otherwise. */ + typedef void (*DoCommandCallback)(Command, void*); bool ExecuteEditCommands(nsIWidget::NativeKeyBindingsType aType, - nsIWidget::DoCommandCallback aCallback, + DoCommandCallback aCallback, void* aCallbackData); // If the key should cause keypress events, this returns true. // Otherwise, false. bool ShouldCauseKeypressEvents() const; // mCharCode value of non-eKeyPress events is always 0. However, if // non-eKeyPress event has one or more alternative char code values,
--- a/widget/WidgetEventImpl.cpp +++ b/widget/WidgetEventImpl.cpp @@ -623,40 +623,34 @@ WidgetKeyboardEvent::InitAllEditCommands MOZ_ASSERT(!AreAllEditCommandsInitialized(), "Shouldn't be called two or more times"); InitEditCommandsFor(nsIWidget::NativeKeyBindingsForSingleLineEditor); InitEditCommandsFor(nsIWidget::NativeKeyBindingsForMultiLineEditor); InitEditCommandsFor(nsIWidget::NativeKeyBindingsForRichTextEditor); } -static void -DoCommandCallback(Command aCommand, void* aData) -{ - static_cast<nsTArray<CommandInt>*>(aData)->AppendElement(aCommand); -} - void WidgetKeyboardEvent::InitEditCommandsFor(nsIWidget::NativeKeyBindingsType aType) { MOZ_ASSERT(mWidget); MOZ_RELEASE_ASSERT(IsTrusted()); bool& initialized = IsEditCommandsInitializedRef(aType); if (initialized) { return; } nsTArray<CommandInt>& commands = EditCommandsRef(aType); - mWidget->ExecuteNativeKeyBinding(aType, *this, DoCommandCallback, &commands); + mWidget->GetEditCommands(aType, *this, commands); initialized = true; } bool WidgetKeyboardEvent::ExecuteEditCommands(nsIWidget::NativeKeyBindingsType aType, - nsIWidget::DoCommandCallback aCallback, + DoCommandCallback aCallback, void* aCallbackData) { // If the event was created without widget, e.g., created event in chrome // script, this shouldn't execute native key bindings. if (NS_WARN_IF(!mWidget)) { return false; }
--- a/widget/cocoa/NativeKeyBindings.h +++ b/widget/cocoa/NativeKeyBindings.h @@ -16,27 +16,25 @@ namespace mozilla { namespace widget { typedef nsDataHashtable<nsPtrHashKey<struct objc_selector>, CommandInt> SelectorCommandHashtable; class NativeKeyBindings final { typedef nsIWidget::NativeKeyBindingsType NativeKeyBindingsType; - typedef nsIWidget::DoCommandCallback DoCommandCallback; public: static NativeKeyBindings* GetInstance(NativeKeyBindingsType aType); static void Shutdown(); void Init(NativeKeyBindingsType aType); - bool Execute(const WidgetKeyboardEvent& aEvent, - DoCommandCallback aCallback, - void* aCallbackData); + void GetEditCommands(const WidgetKeyboardEvent& aEvent, + nsTArray<CommandInt>& aCommands); private: NativeKeyBindings(); SelectorCommandHashtable mSelectorToCommand; static NativeKeyBindings* sInstanceForSingleLineEditor; static NativeKeyBindings* sInstanceForMultiLineEditor;
--- a/widget/cocoa/NativeKeyBindings.mm +++ b/widget/cocoa/NativeKeyBindings.mm @@ -190,100 +190,93 @@ NativeKeyBindings::Init(NativeKeyBinding // SEL_TO_COMMAND(transpose:, ); // SEL_TO_COMMAND(transposeWords:, ); // SEL_TO_COMMAND(uppercaseWord:, ); // SEL_TO_COMMAND(yank:, ); } #undef SEL_TO_COMMAND -bool -NativeKeyBindings::Execute(const WidgetKeyboardEvent& aEvent, - DoCommandCallback aCallback, - void* aCallbackData) +void +NativeKeyBindings::GetEditCommands(const WidgetKeyboardEvent& aEvent, + nsTArray<CommandInt>& aCommands) { + MOZ_ASSERT(aCommands.IsEmpty()); + MOZ_LOG(gNativeKeyBindingsLog, LogLevel::Info, - ("%p NativeKeyBindings::KeyPress", this)); + ("%p NativeKeyBindings::GetEditCommands", this)); // Recover the current event, which should always be the key down we are // responding to. NSEvent* cocoaEvent = reinterpret_cast<NSEvent*>(aEvent.mNativeKeyEvent); if (!cocoaEvent || [cocoaEvent type] != NSKeyDown) { MOZ_LOG(gNativeKeyBindingsLog, LogLevel::Info, - ("%p NativeKeyBindings::KeyPress, no Cocoa key down event", this)); + ("%p NativeKeyBindings::GetEditCommands, no Cocoa key down event", this)); - return false; + return; } MOZ_LOG(gNativeKeyBindingsLog, LogLevel::Info, - ("%p NativeKeyBindings::KeyPress, interpreting", this)); + ("%p NativeKeyBindings::GetEditCommands, interpreting", this)); AutoTArray<KeyBindingsCommand, 2> bindingCommands; nsCocoaUtils::GetCommandsFromKeyEvent(cocoaEvent, bindingCommands); MOZ_LOG(gNativeKeyBindingsLog, LogLevel::Info, - ("%p NativeKeyBindings::KeyPress, bindingCommands=%" PRIuSIZE, + ("%p NativeKeyBindings::GetEditCommands, bindingCommands=%" PRIuSIZE, this, bindingCommands.Length())); - AutoTArray<Command, 4> geckoCommands; - for (uint32_t i = 0; i < bindingCommands.Length(); i++) { SEL selector = bindingCommands[i].selector; if (MOZ_LOG_TEST(gNativeKeyBindingsLog, LogLevel::Info)) { NSString* selectorString = NSStringFromSelector(selector); nsAutoString nsSelectorString; nsCocoaUtils::GetStringForNSString(selectorString, nsSelectorString); MOZ_LOG(gNativeKeyBindingsLog, LogLevel::Info, - ("%p NativeKeyBindings::KeyPress, selector=%s", + ("%p NativeKeyBindings::GetEditCommands, selector=%s", this, NS_LossyConvertUTF16toASCII(nsSelectorString).get())); } // Try to find a simple mapping in the hashtable - Command geckoCommand = static_cast<Command>(mSelectorToCommand.Get( - reinterpret_cast<struct objc_selector*>(selector))); + CommandInt geckoCommand = + mSelectorToCommand.Get(reinterpret_cast<struct objc_selector*>(selector)); if (geckoCommand) { - geckoCommands.AppendElement(geckoCommand); + aCommands.AppendElement(geckoCommand); } else if (selector == @selector(selectLine:)) { // This is functional, but Cocoa's version is direction-less in that // selection direction is not determined until some future directed action // is taken. See bug 282097, comment 79 for more details. - geckoCommands.AppendElement(CommandBeginLine); - geckoCommands.AppendElement(CommandSelectEndLine); + aCommands.AppendElement(CommandBeginLine); + aCommands.AppendElement(CommandSelectEndLine); } else if (selector == @selector(selectWord:)) { // This is functional, but Cocoa's version is direction-less in that // selection direction is not determined until some future directed action // is taken. See bug 282097, comment 79 for more details. - geckoCommands.AppendElement(CommandWordPrevious); - geckoCommands.AppendElement(CommandSelectWordNext); + aCommands.AppendElement(CommandWordPrevious); + aCommands.AppendElement(CommandSelectWordNext); } } - if (geckoCommands.IsEmpty()) { - MOZ_LOG(gNativeKeyBindingsLog, LogLevel::Info, - ("%p NativeKeyBindings::KeyPress, handled=false", this)); - - return false; + if (!MOZ_LOG_TEST(gNativeKeyBindingsLog, LogLevel::Info)) { + return; } - for (uint32_t i = 0; i < geckoCommands.Length(); i++) { - Command geckoCommand = geckoCommands[i]; - + if (aCommands.IsEmpty()) { MOZ_LOG(gNativeKeyBindingsLog, LogLevel::Info, - ("%p NativeKeyBindings::KeyPress, command=%s", - this, WidgetKeyboardEvent::GetCommandStr(geckoCommand))); - - // Execute the Gecko command - aCallback(geckoCommand, aCallbackData); + ("%p NativeKeyBindings::GetEditCommands, handled=false", this)); + return; } - MOZ_LOG(gNativeKeyBindingsLog, LogLevel::Info, - ("%p NativeKeyBindings::KeyPress, handled=true", this)); - - return true; + for (CommandInt commandInt : aCommands) { + Command geckoCommand = static_cast<Command>(commandInt); + MOZ_LOG(gNativeKeyBindingsLog, LogLevel::Info, + ("%p NativeKeyBindings::GetEditCommands, command=%s", + this, WidgetKeyboardEvent::GetCommandStr(geckoCommand))); + } } } // namespace widget } // namespace mozilla
--- a/widget/cocoa/nsChildView.h +++ b/widget/cocoa/nsChildView.h @@ -387,28 +387,25 @@ public: GetSelectionAsPlaintext(nsAString& aResult) override; virtual void SetInputContext(const InputContext& aContext, const InputContextAction& aAction) override; virtual InputContext GetInputContext() override; virtual TextEventDispatcherListener* GetNativeTextEventDispatcherListener() override; virtual MOZ_MUST_USE nsresult AttachNativeKeyEvent(mozilla::WidgetKeyboardEvent& aEvent) override; - virtual bool ExecuteNativeKeyBinding( - NativeKeyBindingsType aType, - const mozilla::WidgetKeyboardEvent& aEvent, - DoCommandCallback aCallback, - void* aCallbackData) override; - bool ExecuteNativeKeyBindingRemapped( - NativeKeyBindingsType aType, - const mozilla::WidgetKeyboardEvent& aEvent, - DoCommandCallback aCallback, - void* aCallbackData, - uint32_t aGeckoKeyCode, - uint32_t aCocoaKeyCode); + virtual void GetEditCommands( + NativeKeyBindingsType aType, + const mozilla::WidgetKeyboardEvent& aEvent, + nsTArray<mozilla::CommandInt>& aCommands) override; + void GetEditCommandsRemapped(NativeKeyBindingsType aType, + const mozilla::WidgetKeyboardEvent& aEvent, + nsTArray<mozilla::CommandInt>& aCommands, + uint32_t aGeckoKeyCode, + uint32_t aCocoaKeyCode); virtual nsTransparencyMode GetTransparencyMode() override; virtual void SetTransparencyMode(nsTransparencyMode aMode) override; virtual nsresult SynthesizeNativeKeyEvent(int32_t aNativeKeyboardLayout, int32_t aNativeKeyCode, uint32_t aModifierFlags, const nsAString& aCharacters,
--- a/widget/cocoa/nsChildView.mm +++ b/widget/cocoa/nsChildView.mm @@ -1845,23 +1845,22 @@ nsChildView::GetNativeTextEventDispatche nsresult nsChildView::AttachNativeKeyEvent(mozilla::WidgetKeyboardEvent& aEvent) { NS_ENSURE_TRUE(mTextInputHandler, NS_ERROR_NOT_AVAILABLE); return mTextInputHandler->AttachNativeKeyEvent(aEvent); } -bool -nsChildView::ExecuteNativeKeyBindingRemapped(NativeKeyBindingsType aType, - const WidgetKeyboardEvent& aEvent, - DoCommandCallback aCallback, - void* aCallbackData, - uint32_t aGeckoKeyCode, - uint32_t aCocoaKeyCode) +void +nsChildView::GetEditCommandsRemapped(NativeKeyBindingsType aType, + const WidgetKeyboardEvent& aEvent, + nsTArray<CommandInt>& aCommands, + uint32_t aGeckoKeyCode, + uint32_t aCocoaKeyCode) { NSEvent *originalEvent = reinterpret_cast<NSEvent*>(aEvent.mNativeKeyEvent); WidgetKeyboardEvent modifiedEvent(aEvent); modifiedEvent.mKeyCode = aGeckoKeyCode; unichar ch = nsCocoaUtils::ConvertGeckoKeyCodeToMacCharCode(aGeckoKeyCode); NSString *chars = @@ -1875,30 +1874,33 @@ nsChildView::ExecuteNativeKeyBindingRema windowNumber:[originalEvent windowNumber] context:[originalEvent context] characters:chars charactersIgnoringModifiers:chars isARepeat:[originalEvent isARepeat] keyCode:aCocoaKeyCode]; NativeKeyBindings* keyBindings = NativeKeyBindings::GetInstance(aType); - return keyBindings->Execute(modifiedEvent, aCallback, aCallbackData); -} - -bool -nsChildView::ExecuteNativeKeyBinding(NativeKeyBindingsType aType, - const WidgetKeyboardEvent& aEvent, - DoCommandCallback aCallback, - void* aCallbackData) -{ + keyBindings->GetEditCommands(modifiedEvent, aCommands); +} + +void +nsChildView::GetEditCommands(NativeKeyBindingsType aType, + const WidgetKeyboardEvent& aEvent, + nsTArray<CommandInt>& aCommands) +{ + // Validate the arguments. + nsIWidget::GetEditCommands(aType, aEvent, aCommands); + // If the key is a cursor-movement arrow, and the current selection has // vertical writing-mode, we'll remap so that the movement command // generated (in terms of characters/lines) will be appropriate for // the physical direction of the arrow. if (aEvent.mKeyCode >= NS_VK_LEFT && aEvent.mKeyCode <= NS_VK_DOWN) { + // XXX This may be expensive. Should use the cache in TextInputHandler. WidgetQueryContentEvent query(true, eQuerySelectedText, this); DispatchWindowEvent(query); if (query.mSucceeded && query.mReply.mWritingMode.IsVertical()) { uint32_t geckoKey = 0; uint32_t cocoaKey = 0; switch (aEvent.mKeyCode) { @@ -1928,24 +1930,23 @@ nsChildView::ExecuteNativeKeyBinding(Nat break; case NS_VK_DOWN: geckoKey = NS_VK_RIGHT; cocoaKey = kVK_RightArrow; break; } - return ExecuteNativeKeyBindingRemapped(aType, aEvent, aCallback, - aCallbackData, - geckoKey, cocoaKey); + GetEditCommandsRemapped(aType, aEvent, aCommands, geckoKey, cocoaKey); + return; } } NativeKeyBindings* keyBindings = NativeKeyBindings::GetInstance(aType); - return keyBindings->Execute(aEvent, aCallback, aCallbackData); + keyBindings->GetEditCommands(aEvent, aCommands); } NSView<mozView>* nsChildView::GetEditorView() { NSView<mozView>* editorView = mView; // We need to get editor's view. E.g., when the focus is in the bookmark // dialog, the view is <panel> element of the dialog. At this time, the key // events are processed the parent window's view that has native focus.
--- a/widget/cocoa/nsCocoaWindow.h +++ b/widget/cocoa/nsCocoaWindow.h @@ -341,21 +341,20 @@ public: nsMenuBarX *GetMenuBar(); virtual void SetInputContext(const InputContext& aContext, const InputContextAction& aAction) override; virtual InputContext GetInputContext() override { return mInputContext; } - virtual bool ExecuteNativeKeyBinding( - NativeKeyBindingsType aType, - const mozilla::WidgetKeyboardEvent& aEvent, - DoCommandCallback aCallback, - void* aCallbackData) override; + virtual void GetEditCommands( + NativeKeyBindingsType aType, + const mozilla::WidgetKeyboardEvent& aEvent, + nsTArray<mozilla::CommandInt>& aCommands) override; void SetPopupWindowLevel(); protected: virtual ~nsCocoaWindow(); nsresult CreateNativeWindow(const NSRect &aRect, nsBorderStyle aBorderStyle,
--- a/widget/cocoa/nsCocoaWindow.mm +++ b/widget/cocoa/nsCocoaWindow.mm @@ -2340,24 +2340,26 @@ nsCocoaWindow::SetInputContext(const Inp { NS_OBJC_BEGIN_TRY_ABORT_BLOCK; mInputContext = aContext; NS_OBJC_END_TRY_ABORT_BLOCK; } -bool -nsCocoaWindow::ExecuteNativeKeyBinding(NativeKeyBindingsType aType, - const WidgetKeyboardEvent& aEvent, - DoCommandCallback aCallback, - void* aCallbackData) +void +nsCocoaWindow::GetEditCommands(NativeKeyBindingsType aType, + const WidgetKeyboardEvent& aEvent, + nsTArray<CommandInt>& aCommands) { + // Validate the arguments. + nsIWidget::GetEditCommands(aType, aEvent, aCommands); + NativeKeyBindings* keyBindings = NativeKeyBindings::GetInstance(aType); - return keyBindings->Execute(aEvent, aCallback, aCallbackData); + keyBindings->GetEditCommands(aEvent, aCommands); } @implementation WindowDelegate // We try to find a gecko menu bar to paint. If one does not exist, just paint // the application menu by itself so that a window doesn't have some other // window's menu bar. + (void)paintMenubarForWindow:(NSWindow*)aWindow
--- a/widget/gtk/NativeKeyBindings.cpp +++ b/widget/gtk/NativeKeyBindings.cpp @@ -14,33 +14,32 @@ #include <gtk/gtk.h> #include <gdk/gdkkeysyms.h> #include <gdk/gdk.h> namespace mozilla { namespace widget { -static nsIWidget::DoCommandCallback gCurrentCallback; -static void *gCurrentCallbackData; -static bool gHandled; +static nsTArray<CommandInt>* gCurrentCommands = nullptr; +static bool gHandled = false; // Common GtkEntry and GtkTextView signals static void copy_clipboard_cb(GtkWidget *w, gpointer user_data) { - gCurrentCallback(CommandCopy, gCurrentCallbackData); + gCurrentCommands->AppendElement(CommandCopy); g_signal_stop_emission_by_name(w, "copy_clipboard"); gHandled = true; } static void cut_clipboard_cb(GtkWidget *w, gpointer user_data) { - gCurrentCallback(CommandCut, gCurrentCallbackData); + gCurrentCommands->AppendElement(CommandCut); g_signal_stop_emission_by_name(w, "cut_clipboard"); gHandled = true; } // GTK distinguishes between display lines (wrapped, as they appear on the // screen) and paragraphs, which are runs of text terminated by a newline. // We don't have this distinction, so we always use editor's notion of // lines, which are newline-terminated. @@ -88,42 +87,42 @@ delete_from_cursor_cb(GtkWidget *w, GtkD // unsupported deletion type return; } if (del_type == GTK_DELETE_WORDS) { // This works like word_ends, except we first move the caret to the // beginning/end of the current word. if (forward) { - gCurrentCallback(CommandWordNext, gCurrentCallbackData); - gCurrentCallback(CommandWordPrevious, gCurrentCallbackData); + gCurrentCommands->AppendElement(CommandWordNext); + gCurrentCommands->AppendElement(CommandWordPrevious); } else { - gCurrentCallback(CommandWordPrevious, gCurrentCallbackData); - gCurrentCallback(CommandWordNext, gCurrentCallbackData); + gCurrentCommands->AppendElement(CommandWordPrevious); + gCurrentCommands->AppendElement(CommandWordNext); } } else if (del_type == GTK_DELETE_DISPLAY_LINES || del_type == GTK_DELETE_PARAGRAPHS) { // This works like display_line_ends, except we first move the caret to the // beginning/end of the current line. if (forward) { - gCurrentCallback(CommandBeginLine, gCurrentCallbackData); + gCurrentCommands->AppendElement(CommandBeginLine); } else { - gCurrentCallback(CommandEndLine, gCurrentCallbackData); + gCurrentCommands->AppendElement(CommandEndLine); } } Command command = sDeleteCommands[del_type][forward]; if (!command) { return; // unsupported command } unsigned int absCount = Abs(count); for (unsigned int i = 0; i < absCount; ++i) { - gCurrentCallback(command, gCurrentCallbackData); + gCurrentCommands->AppendElement(command); } } static const Command sMoveCommands[][2][2] = { // non-extend { backward, forward }, extend { backward, forward } // GTK differentiates between logical position, which is prev/next, // and visual position, which is always left/right. // We should fix this to work the same way for RTL text input. @@ -183,33 +182,33 @@ move_cursor_cb(GtkWidget *w, GtkMovement Command command = sMoveCommands[step][extend_selection][forward]; if (!command) { return; // unsupported command } unsigned int absCount = Abs(count); for (unsigned int i = 0; i < absCount; ++i) { - gCurrentCallback(command, gCurrentCallbackData); + gCurrentCommands->AppendElement(command); } } static void paste_clipboard_cb(GtkWidget *w, gpointer user_data) { - gCurrentCallback(CommandPaste, gCurrentCallbackData); + gCurrentCommands->AppendElement(CommandPaste); g_signal_stop_emission_by_name(w, "paste_clipboard"); gHandled = true; } // GtkTextView-only signals static void select_all_cb(GtkWidget *w, gboolean select, gpointer user_data) { - gCurrentCallback(CommandSelectAll, gCurrentCallbackData); + gCurrentCommands->AppendElement(CommandSelectAll); g_signal_stop_emission_by_name(w, "select_all"); gHandled = true; } NativeKeyBindings* NativeKeyBindings::sInstanceForSingleLineEditor = nullptr; NativeKeyBindings* NativeKeyBindings::sInstanceForMultiLineEditor = nullptr; // static @@ -283,50 +282,49 @@ NativeKeyBindings::Init(NativeKeyBinding } NativeKeyBindings::~NativeKeyBindings() { gtk_widget_destroy(mNativeTarget); g_object_unref(mNativeTarget); } -bool -NativeKeyBindings::Execute(const WidgetKeyboardEvent& aEvent, - DoCommandCallback aCallback, - void* aCallbackData) +void +NativeKeyBindings::GetEditCommands(const WidgetKeyboardEvent& aEvent, + nsTArray<CommandInt>& aCommands) { // If the native key event is set, it must be synthesized for tests. // We just ignore such events because this behavior depends on system // settings. if (!aEvent.mNativeKeyEvent) { // It must be synthesized event or dispatched DOM event from chrome. - return false; + return; } guint keyval; if (aEvent.mCharCode) { keyval = gdk_unicode_to_keyval(aEvent.mCharCode); } else { keyval = static_cast<GdkEventKey*>(aEvent.mNativeKeyEvent)->keyval; } - if (ExecuteInternal(aEvent, aCallback, aCallbackData, keyval)) { - return true; + if (GetEditCommandsInternal(aEvent, aCommands, keyval)) { + return; } for (uint32_t i = 0; i < aEvent.mAlternativeCharCodes.Length(); ++i) { uint32_t ch = aEvent.IsShift() ? aEvent.mAlternativeCharCodes[i].mShiftedCharCode : aEvent.mAlternativeCharCodes[i].mUnshiftedCharCode; if (ch && ch != aEvent.mCharCode) { keyval = gdk_unicode_to_keyval(ch); - if (ExecuteInternal(aEvent, aCallback, aCallbackData, keyval)) { - return true; + if (GetEditCommandsInternal(aEvent, aCommands, keyval)) { + return; } } } /* gtk_bindings_activate_event is preferable, but it has unresolved bug: http://bugzilla.gnome.org/show_bug.cgi?id=162726 The bug was already marked as FIXED. However, somebody reports that the @@ -334,41 +332,38 @@ bug still exists. Also gtk_bindings_activate may work with some non-shortcuts operations (todo: check it). See bug 411005 and bug 406407. Code, which should be used after fixing GNOME bug 162726: gtk_bindings_activate_event(GTK_OBJECT(mNativeTarget), static_cast<GdkEventKey*>(aEvent.mNativeKeyEvent)); */ - - return false; } bool -NativeKeyBindings::ExecuteInternal(const WidgetKeyboardEvent& aEvent, - DoCommandCallback aCallback, - void* aCallbackData, - guint aKeyval) +NativeKeyBindings::GetEditCommandsInternal(const WidgetKeyboardEvent& aEvent, + nsTArray<CommandInt>& aCommands, + guint aKeyval) { guint modifiers = static_cast<GdkEventKey*>(aEvent.mNativeKeyEvent)->state; - gCurrentCallback = aCallback; - gCurrentCallbackData = aCallbackData; + gCurrentCommands = &aCommands; gHandled = false; #if (MOZ_WIDGET_GTK == 2) gtk_bindings_activate(GTK_OBJECT(mNativeTarget), aKeyval, GdkModifierType(modifiers)); #else gtk_bindings_activate(G_OBJECT(mNativeTarget), aKeyval, GdkModifierType(modifiers)); #endif - gCurrentCallback = nullptr; - gCurrentCallbackData = nullptr; + gCurrentCommands = nullptr; + + MOZ_ASSERT(!gHandled || !aCommands.IsEmpty()); return gHandled; } } // namespace widget } // namespace mozilla
--- a/widget/gtk/NativeKeyBindings.h +++ b/widget/gtk/NativeKeyBindings.h @@ -12,35 +12,32 @@ #include "nsIWidget.h" namespace mozilla { namespace widget { class NativeKeyBindings final { typedef nsIWidget::NativeKeyBindingsType NativeKeyBindingsType; - typedef nsIWidget::DoCommandCallback DoCommandCallback; public: static NativeKeyBindings* GetInstance(NativeKeyBindingsType aType); static void Shutdown(); void Init(NativeKeyBindingsType aType); - bool Execute(const WidgetKeyboardEvent& aEvent, - DoCommandCallback aCallback, - void* aCallbackData); + void GetEditCommands(const WidgetKeyboardEvent& aEvent, + nsTArray<CommandInt>& aCommands); private: ~NativeKeyBindings(); - bool ExecuteInternal(const WidgetKeyboardEvent& aEvent, - DoCommandCallback aCallback, - void* aCallbackData, - guint aKeyval); + bool GetEditCommandsInternal(const WidgetKeyboardEvent& aEvent, + nsTArray<CommandInt>& aCommands, + guint aKeyval); GtkWidget* mNativeTarget; static NativeKeyBindings* sInstanceForSingleLineEditor; static NativeKeyBindings* sInstanceForMultiLineEditor; }; } // namespace widget
--- a/widget/gtk/nsWindow.cpp +++ b/widget/gtk/nsWindow.cpp @@ -6160,43 +6160,44 @@ TextEventDispatcherListener* nsWindow::GetNativeTextEventDispatcherListener() { if (NS_WARN_IF(!mIMContext)) { return nullptr; } return mIMContext; } -bool -nsWindow::ExecuteNativeKeyBindingRemapped(NativeKeyBindingsType aType, - const WidgetKeyboardEvent& aEvent, - DoCommandCallback aCallback, - void* aCallbackData, - uint32_t aGeckoKeyCode, - uint32_t aNativeKeyCode) +void +nsWindow::GetEditCommandsRemapped(NativeKeyBindingsType aType, + const WidgetKeyboardEvent& aEvent, + nsTArray<CommandInt>& aCommands, + uint32_t aGeckoKeyCode, + uint32_t aNativeKeyCode) { WidgetKeyboardEvent modifiedEvent(aEvent); modifiedEvent.mKeyCode = aGeckoKeyCode; static_cast<GdkEventKey*>(modifiedEvent.mNativeKeyEvent)->keyval = aNativeKeyCode; NativeKeyBindings* keyBindings = NativeKeyBindings::GetInstance(aType); - return keyBindings->Execute(modifiedEvent, aCallback, aCallbackData); -} - -bool -nsWindow::ExecuteNativeKeyBinding(NativeKeyBindingsType aType, - const WidgetKeyboardEvent& aEvent, - DoCommandCallback aCallback, - void* aCallbackData) -{ + return keyBindings->GetEditCommands(modifiedEvent, aCommands); +} + +void +nsWindow::GetEditCommands(NativeKeyBindingsType aType, + const WidgetKeyboardEvent& aEvent, + nsTArray<CommandInt>& aCommands) +{ + // Validate the arguments. + nsIWidget::GetEditCommands(aType, aEvent, aCommands); + if (aEvent.mKeyCode >= NS_VK_LEFT && aEvent.mKeyCode <= NS_VK_DOWN) { - // Check if we're targeting content with vertical writing mode, // and if so remap the arrow keys. + // XXX This may be expensive. WidgetQueryContentEvent query(true, eQuerySelectedText, this); nsEventStatus status; DispatchEvent(&query, status); if (query.mSucceeded && query.mReply.mWritingMode.IsVertical()) { uint32_t geckoCode = 0; uint32_t gdkCode = 0; switch (aEvent.mKeyCode) { @@ -6226,24 +6227,24 @@ nsWindow::ExecuteNativeKeyBinding(Native break; case NS_VK_DOWN: geckoCode = NS_VK_RIGHT; gdkCode = GDK_Right; break; } - return ExecuteNativeKeyBindingRemapped(aType, aEvent, aCallback, - aCallbackData, - geckoCode, gdkCode); + GetEditCommandsRemapped(aType, aEvent, aCommands, + geckoCode, gdkCode); + return; } } NativeKeyBindings* keyBindings = NativeKeyBindings::GetInstance(aType); - return keyBindings->Execute(aEvent, aCallback, aCallbackData); + keyBindings->GetEditCommands(aEvent, aCommands); } #if defined(MOZ_X11) && (MOZ_WIDGET_GTK == 2) /* static */ already_AddRefed<DrawTarget> nsWindow::GetDrawTargetForGdkDrawable(GdkDrawable* aDrawable, const IntSize& aSize) { GdkVisual* visual = gdk_drawable_get_visual(aDrawable);
--- a/widget/gtk/nsWindow.h +++ b/widget/gtk/nsWindow.h @@ -285,28 +285,25 @@ public: mozilla::TimeStamp GetEventTimeStamp(guint32 aEventTime); mozilla::CurrentX11TimeGetter* GetCurrentTimeGetter(); virtual void SetInputContext(const InputContext& aContext, const InputContextAction& aAction) override; virtual InputContext GetInputContext() override; virtual TextEventDispatcherListener* GetNativeTextEventDispatcherListener() override; - bool ExecuteNativeKeyBindingRemapped( - NativeKeyBindingsType aType, - const mozilla::WidgetKeyboardEvent& aEvent, - DoCommandCallback aCallback, - void* aCallbackData, - uint32_t aGeckoKeyCode, - uint32_t aNativeKeyCode); - virtual bool ExecuteNativeKeyBinding( - NativeKeyBindingsType aType, - const mozilla::WidgetKeyboardEvent& aEvent, - DoCommandCallback aCallback, - void* aCallbackData) override; + void GetEditCommandsRemapped(NativeKeyBindingsType aType, + const mozilla::WidgetKeyboardEvent& aEvent, + nsTArray<mozilla::CommandInt>& aCommands, + uint32_t aGeckoKeyCode, + uint32_t aNativeKeyCode); + virtual void GetEditCommands( + NativeKeyBindingsType aType, + const mozilla::WidgetKeyboardEvent& aEvent, + nsTArray<mozilla::CommandInt>& aCommands) override; // These methods are for toplevel windows only. void ResizeTransparencyBitmap(); void ApplyTransparencyBitmap(); void ClearTransparencyBitmap(); virtual void SetTransparencyMode(nsTransparencyMode aMode) override; virtual nsTransparencyMode GetTransparencyMode() override;
--- a/widget/nsBaseWidget.cpp +++ b/widget/nsBaseWidget.cpp @@ -2282,16 +2282,25 @@ nsIWidget::OnWindowedPluginKeyEvent(cons return NS_ERROR_NOT_IMPLEMENTED; } void nsIWidget::PostHandleKeyEvent(mozilla::WidgetKeyboardEvent* aEvent) { } +void +nsIWidget::GetEditCommands(nsIWidget::NativeKeyBindingsType aType, + const WidgetKeyboardEvent& aEvent, + nsTArray<CommandInt>& aCommands) +{ + MOZ_ASSERT(aEvent.IsTrusted()); + MOZ_ASSERT(aCommands.IsEmpty()); +} + namespace mozilla { namespace widget { const char* ToChar(IMEMessage aIMEMessage) { switch (aIMEMessage) { case NOTIFY_IME_OF_NOTHING:
--- a/widget/nsBaseWidget.h +++ b/widget/nsBaseWidget.h @@ -274,21 +274,16 @@ public: virtual void SetCandidateWindowForPlugin( const mozilla::widget::CandidateWindowPosition& aPosition) override { } virtual void DefaultProcOfPluginEvent( const mozilla::WidgetPluginEvent& aEvent) override { } virtual MOZ_MUST_USE nsresult AttachNativeKeyEvent(mozilla::WidgetKeyboardEvent& aEvent) override { return NS_ERROR_NOT_IMPLEMENTED; } - virtual bool ExecuteNativeKeyBinding( - NativeKeyBindingsType aType, - const mozilla::WidgetKeyboardEvent& aEvent, - DoCommandCallback aCallback, - void* aCallbackData) override { return false; } bool ComputeShouldAccelerate(); virtual bool WidgetTypeSupportsAcceleration() { return true; } virtual MOZ_MUST_USE nsresult OnDefaultButtonLoaded(const LayoutDeviceIntRect& aButtonRect) override { return NS_ERROR_NOT_IMPLEMENTED; } virtual already_AddRefed<nsIWidget> CreateChild(const LayoutDeviceIntRect& aRect, nsWidgetInitData* aInitData = nullptr, bool aForceUseIWidgetParent = false) override; virtual void AttachViewToTopLevel(bool aUseAttachedEvents) override;
--- a/widget/nsIWidget.h +++ b/widget/nsIWidget.h @@ -1812,31 +1812,29 @@ public: * Given a WidgetKeyboardEvent, this method synthesizes a corresponding * native (OS-level) event for it. This method allows tests to simulate * keystrokes that trigger native key bindings (which require a native * event). */ virtual MOZ_MUST_USE nsresult AttachNativeKeyEvent(mozilla::WidgetKeyboardEvent& aEvent) = 0; - /* - * Execute native key bindings for aType. + /** + * Retrieve edit commands when the key combination of aEvent is used + * in platform native applications. */ - typedef void (*DoCommandCallback)(mozilla::Command, void*); enum NativeKeyBindingsType { NativeKeyBindingsForSingleLineEditor, NativeKeyBindingsForMultiLineEditor, NativeKeyBindingsForRichTextEditor }; - virtual bool ExecuteNativeKeyBinding( - NativeKeyBindingsType aType, - const mozilla::WidgetKeyboardEvent& aEvent, - DoCommandCallback aCallback, - void* aCallbackData) = 0; + virtual void GetEditCommands(NativeKeyBindingsType aType, + const mozilla::WidgetKeyboardEvent& aEvent, + nsTArray<mozilla::CommandInt>& aCommands); /* * Retrieves a reference to notification requests of IME. Note that the * reference is valid while the nsIWidget instance is alive. So, if you * need to store the reference for a long time, you need to grab the widget * instance too. */ const IMENotificationRequests& IMENotificationRequestsRef();