summaryrefslogtreecommitdiffstats
path: root/layout/generic/nsQueryFrame.h
diff options
context:
space:
mode:
Diffstat (limited to 'layout/generic/nsQueryFrame.h')
-rw-r--r--layout/generic/nsQueryFrame.h102
1 files changed, 102 insertions, 0 deletions
diff --git a/layout/generic/nsQueryFrame.h b/layout/generic/nsQueryFrame.h
new file mode 100644
index 000000000..7f7ea2fc1
--- /dev/null
+++ b/layout/generic/nsQueryFrame.h
@@ -0,0 +1,102 @@
+/* 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 nsQueryFrame_h
+#define nsQueryFrame_h
+
+#include "nscore.h"
+#include "mozilla/Assertions.h"
+#include "mozilla/TypeTraits.h"
+
+// NOTE: the long lines in this file are intentional to make compiler error
+// messages more readable.
+
+#define NS_DECL_QUERYFRAME_TARGET(classname) \
+ static const nsQueryFrame::FrameIID kFrameIID = nsQueryFrame::classname##_id; \
+ typedef classname Has_NS_DECL_QUERYFRAME_TARGET;
+
+#define NS_DECL_QUERYFRAME \
+ virtual void* QueryFrame(FrameIID id) override;
+
+#define NS_QUERYFRAME_HEAD(class) \
+ void* class::QueryFrame(FrameIID id) { switch (id) {
+
+#define NS_QUERYFRAME_ENTRY(class) \
+ case class::kFrameIID: { \
+ static_assert(mozilla::IsSame<class, class::Has_NS_DECL_QUERYFRAME_TARGET>::value, \
+ #class " must declare itself as a queryframe target"); \
+ return static_cast<class*>(this); \
+ }
+
+#define NS_QUERYFRAME_ENTRY_CONDITIONAL(class, condition) \
+ case class::kFrameIID: \
+ if (condition) { \
+ static_assert(mozilla::IsSame<class, class::Has_NS_DECL_QUERYFRAME_TARGET>::value, \
+ #class " must declare itself as a queryframe target"); \
+ return static_cast<class*>(this); \
+ } \
+ break;
+
+#define NS_QUERYFRAME_TAIL_INHERITING(class) \
+ default: break; \
+ } \
+ return class::QueryFrame(id); \
+}
+
+#define NS_QUERYFRAME_TAIL_INHERITANCE_ROOT \
+ default: break; \
+ } \
+ MOZ_ASSERT(id != GetFrameId(), \
+ "A frame failed to QueryFrame to its *own type*. " \
+ "It may be missing NS_DECL_QUERYFRAME, or a " \
+ "NS_QUERYFRAME_ENTRY() line with its own type name"); \
+ return nullptr; \
+}
+
+class nsQueryFrame
+{
+public:
+ enum FrameIID {
+#define FRAME_ID(classname) classname##_id,
+#include "nsFrameIdList.h"
+#undef FRAME_ID
+
+ // The PresArena implementation uses this bit to distinguish objects
+ // allocated by size from objects allocated by type ID (that is, frames
+ // using AllocateByFrameID, and other objects using AllocateByObjectID).
+ // It should not collide with any frame ID (above) or Object ID (in
+ // nsPresArena.h). It is not 0x80000000 to avoid the question of
+ // whether enumeration constants are signed.
+ NON_FRAME_MARKER = 0x20000000
+ };
+
+ virtual void* QueryFrame(FrameIID id) = 0;
+};
+
+class do_QueryFrame
+{
+public:
+ explicit do_QueryFrame(nsQueryFrame *s) : mRawPtr(s) { }
+
+ // The return and argument types here are arbitrarily selected so no
+ // corresponding member function exists.
+ typedef void (do_QueryFrame::* MatchNullptr)(double, float);
+ // Implicit constructor for nullptr, trick borrowed from already_AddRefed.
+ MOZ_IMPLICIT do_QueryFrame(MatchNullptr aRawPtr) : mRawPtr(nullptr) {}
+
+ template<class Dest>
+ operator Dest*() {
+ static_assert(mozilla::IsSame<Dest, typename Dest::Has_NS_DECL_QUERYFRAME_TARGET>::value,
+ "Dest must declare itself as a queryframe target");
+ if (!mRawPtr)
+ return nullptr;
+
+ return reinterpret_cast<Dest*>(mRawPtr->QueryFrame(Dest::kFrameIID));
+ }
+
+private:
+ nsQueryFrame *mRawPtr;
+};
+
+#endif // nsQueryFrame_h