diff options
author | Moonchild <moonchild@palemoon.org> | 2020-07-10 18:46:10 +0000 |
---|---|---|
committer | Moonchild <moonchild@palemoon.org> | 2020-07-10 18:46:10 +0000 |
commit | f1b51be787c11090c8d9b2ec73255df7a67c7eb7 (patch) | |
tree | 9c6d35ce6f19e0fef3c47c7e2c152394854cf217 /widget/gtk/nsNativeMenuDocListener.h | |
parent | 2deaddfca28508ac1a634eb6088a1da8e571ec6e (diff) | |
parent | 82faff19e1761797b7a75f9221f0709c5a38bfe6 (diff) | |
download | UXP-RELBASE_20200711.tar UXP-RELBASE_20200711.tar.gz UXP-RELBASE_20200711.tar.lz UXP-RELBASE_20200711.tar.xz UXP-RELBASE_20200711.zip |
Merge branch 'redwood' into releaseRELBASE_20200711
Diffstat (limited to 'widget/gtk/nsNativeMenuDocListener.h')
-rw-r--r-- | widget/gtk/nsNativeMenuDocListener.h | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/widget/gtk/nsNativeMenuDocListener.h b/widget/gtk/nsNativeMenuDocListener.h new file mode 100644 index 000000000..c0a503da1 --- /dev/null +++ b/widget/gtk/nsNativeMenuDocListener.h @@ -0,0 +1,146 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef __nsNativeMenuDocListener_h__ +#define __nsNativeMenuDocListener_h__ + +#include "mozilla/Attributes.h" +#include "mozilla/GuardObjects.h" +#include "mozilla/RefPtr.h" +#include "nsAutoPtr.h" +#include "nsDataHashtable.h" +#include "nsStubMutationObserver.h" +#include "nsTArray.h" + +class nsIAtom; +class nsIContent; +class nsIDocument; +class nsNativeMenuChangeObserver; + +/* + * This class keeps a mapping of content nodes to observers and forwards DOM + * mutations to these. There is exactly one of these for every menubar. + */ +class nsNativeMenuDocListener final : nsStubMutationObserver { +public: + NS_DECL_ISUPPORTS + + nsNativeMenuDocListener(nsIContent* aRootNode); + + // Register an observer to receive mutation events for the specified + // content node. The caller must keep the observer alive until + // UnregisterForContentChanges is called. + void RegisterForContentChanges(nsIContent* aContent, + nsNativeMenuChangeObserver* aObserver); + + // Unregister the registered observer for the specified content node + void UnregisterForContentChanges(nsIContent* aContent); + + // Start listening to the document and forwarding DOM mutations to + // registered observers. + void Start(); + + // Stop listening to the document. No DOM mutations will be forwarded + // to registered observers. + void Stop(); + + /* + * This class is intended to be used inside GObject signal handlers. + * It allows us to queue updates until we have finished delivering + * events to Goanna, and then we can batch updates to our view of the + * menu. This allows us to do menu updates without altering the structure + * seen by the OS. + */ + class MOZ_STACK_CLASS BlockUpdatesScope { + public: + BlockUpdatesScope(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM) { + MOZ_GUARD_OBJECT_NOTIFIER_INIT; + nsNativeMenuDocListener::AddUpdateBlocker(); + } + + ~BlockUpdatesScope() { + nsNativeMenuDocListener::RemoveUpdateBlocker(); + } + + private: + MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER + }; + +private: + friend class DispatchHelper; + + struct MutationRecord { + enum RecordType { + eAttributeChanged, + eContentInserted, + eContentRemoved + } mType; + + nsCOMPtr<nsIContent> mTarget; + nsCOMPtr<nsIContent> mChild; + nsCOMPtr<nsIContent> mPrevSibling; + nsCOMPtr<nsIAtom> mAttribute; + }; + + ~nsNativeMenuDocListener(); + + NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED + NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED + NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED + NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED + NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED + + void DoAttributeChanged(nsIContent* aContent, nsIAtom* aAttribute); + void DoContentInserted(nsIContent* aContainer, + nsIContent* aChild, + nsIContent* aPrevSibling); + void DoContentRemoved(nsIContent* aContainer, nsIContent* aChild); + void DoBeginUpdates(nsIContent* aTarget); + void DoEndUpdates(nsIContent* aTarget); + + void FlushPendingMutations(); + static void ScheduleFlush(nsNativeMenuDocListener* aListener); + static void CancelFlush(nsNativeMenuDocListener* aListener); + + static void AddUpdateBlocker() { + ++sUpdateBlockersCount; + } + static void RemoveUpdateBlocker(); + + nsCOMPtr<nsIContent> mRootNode; + nsIDocument* mDocument; + nsIContent* mLastSource; + nsNativeMenuChangeObserver* mLastTarget; + nsTArray<nsAutoPtr<MutationRecord> > mPendingMutations; + nsDataHashtable<nsPtrHashKey<nsIContent>, nsNativeMenuChangeObserver* > mContentToObserverTable; + + static uint32_t sUpdateBlockersCount; +}; + +typedef nsTArray<RefPtr<nsNativeMenuDocListener> > nsNativeMenuDocListenerTArray; + +/* + * Implemented by classes that want to listen to mutation events from content + * nodes. + */ +class nsNativeMenuChangeObserver { +public: + virtual void OnAttributeChanged(nsIContent* aContent, nsIAtom* aAttribute) {} + + virtual void OnContentInserted(nsIContent* aContainer, + nsIContent* aChild, + nsIContent* aPrevSibling) {} + + virtual void OnContentRemoved(nsIContent* aContainer, nsIContent* aChild) {} + + // Signals the start of a sequence of more than 1 event for the specified + // node. This only happens when events are flushed as all BlockUpdatesScope + // instances go out of scope + virtual void OnBeginUpdates(nsIContent* aContent) {}; + + // Signals the end of a sequence of events + virtual void OnEndUpdates() {}; +}; + +#endif /* __nsNativeMenuDocListener_h__ */ |