1 /* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 /* implements DOM interface for querying and observing media queries */
8 #include "mozilla/dom/MediaQueryList.h"
9 #include "nsPresContext.h"
10 #include "nsIMediaList.h"
11 #include "nsCSSParser.h"
12 #include "nsIDocument.h"
17 MediaQueryList::MediaQueryList(nsPresContext
*aPresContext
,
18 const nsAString
&aMediaQueryList
)
19 : mPresContext(aPresContext
),
20 mMediaList(new nsMediaList
),
28 parser
.ParseMediaList(aMediaQueryList
, nullptr, 0, mMediaList
, false);
31 MediaQueryList::~MediaQueryList()
38 NS_IMPL_CYCLE_COLLECTION_CLASS(MediaQueryList
)
40 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(MediaQueryList
)
41 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPresContext
)
42 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCallbacks
)
43 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
44 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
46 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(MediaQueryList
)
47 if (tmp
->mPresContext
) {
49 NS_IMPL_CYCLE_COLLECTION_UNLINK(mPresContext
)
51 tmp
->RemoveAllListeners();
52 NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
53 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
55 NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(MediaQueryList
)
57 NS_INTERFACE_MAP_BEGIN(MediaQueryList
)
58 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
59 NS_INTERFACE_MAP_ENTRY(nsISupports
)
60 NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(MediaQueryList
)
63 NS_IMPL_CYCLE_COLLECTING_ADDREF(MediaQueryList
)
64 NS_IMPL_CYCLE_COLLECTING_RELEASE(MediaQueryList
)
67 MediaQueryList::GetMedia(nsAString
&aMedia
)
69 mMediaList
->GetText(aMedia
);
73 MediaQueryList::Matches()
76 NS_ABORT_IF_FALSE(!HasListeners(),
77 "when listeners present, must keep mMatches current");
85 MediaQueryList::AddListener(MediaQueryListListener
& aListener
)
87 if (!HasListeners()) {
88 // When we have listeners, the pres context owns a reference to
89 // this. This is a cyclic reference that can only be broken by
95 NS_ABORT_IF_FALSE(!HasListeners(),
96 "when listeners present, must keep mMatches current");
100 for (uint32_t i
= 0; i
< mCallbacks
.Length(); ++i
) {
101 if (aListener
== *mCallbacks
[i
]) {
102 // Already registered
107 mCallbacks
.AppendElement(&aListener
);
108 if (!HasListeners()) {
109 // Append failed; undo the AddRef above.
115 MediaQueryList::RemoveListener(MediaQueryListListener
& aListener
)
117 for (uint32_t i
= 0; i
< mCallbacks
.Length(); ++i
) {
118 if (aListener
== *mCallbacks
[i
]) {
119 mCallbacks
.RemoveElementAt(i
);
120 if (!HasListeners()) {
121 // See NS_ADDREF_THIS() in AddListener.
130 MediaQueryList::RemoveAllListeners()
132 bool hadListeners
= HasListeners();
135 // See NS_ADDREF_THIS() in AddListener.
141 MediaQueryList::RecomputeMatches()
147 mMatches
= mMediaList
->Matches(mPresContext
, nullptr);
148 mMatchesValid
= true;
152 MediaQueryList::MediumFeaturesChanged(NotifyList
&aListenersToNotify
)
154 mMatchesValid
= false;
156 if (HasListeners()) {
157 bool oldMatches
= mMatches
;
159 if (mMatches
!= oldMatches
) {
160 for (uint32_t i
= 0, i_end
= mCallbacks
.Length(); i
!= i_end
; ++i
) {
161 HandleChangeData
*d
= aListenersToNotify
.AppendElement();
164 d
->callback
= mCallbacks
[i
];
172 MediaQueryList::GetParentObject() const
177 return mPresContext
->Document();
181 MediaQueryList::WrapObject(JSContext
* aCx
)
183 return MediaQueryListBinding::Wrap(aCx
, this);
187 } // namespace mozilla