147 lines
4.8 KiB
C++
147 lines
4.8 KiB
C++
/* 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__ */
|