--- 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();