summaryrefslogtreecommitdiffstats
path: root/widget/gtk/nsNativeMenuDocListener.h
diff options
context:
space:
mode:
Diffstat (limited to 'widget/gtk/nsNativeMenuDocListener.h')
-rw-r--r--widget/gtk/nsNativeMenuDocListener.h146
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__ */