1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 /* implements DOM interface for querying and observing media queries */
9 #include "mozilla/dom/MediaQueryList.h"
10 #include "mozilla/dom/MediaQueryListEvent.h"
11 #include "mozilla/dom/MediaList.h"
12 #include "mozilla/dom/EventTarget.h"
13 #include "mozilla/dom/EventTargetBinding.h"
14 #include "nsPresContext.h"
15 #include "mozilla/dom/Document.h"
17 namespace mozilla::dom
{
19 MediaQueryList::MediaQueryList(Document
* aDocument
,
20 const nsACString
& aMediaQueryList
,
21 CallerType aCallerType
)
22 : DOMEventTargetHelper(aDocument
->GetInnerWindow()),
24 mMediaList(MediaList::Create(aMediaQueryList
, aCallerType
)),
25 mViewportDependent(mMediaList
->IsViewportDependent()),
26 mMatches(mMediaList
->Matches(*aDocument
)),
27 mMatchesOnRenderingUpdate(mMatches
) {
28 KeepAliveIfHasListenersFor(nsGkAtoms::onchange
);
31 MediaQueryList::~MediaQueryList() = default;
33 NS_IMPL_CYCLE_COLLECTION_CLASS(MediaQueryList
)
35 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(MediaQueryList
,
37 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument
)
38 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
40 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(MediaQueryList
,
43 static_cast<LinkedListElement
<MediaQueryList
>*>(tmp
)->remove();
44 NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument
)
47 NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
48 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
50 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MediaQueryList
)
51 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper
)
53 NS_IMPL_ADDREF_INHERITED(MediaQueryList
, DOMEventTargetHelper
)
54 NS_IMPL_RELEASE_INHERITED(MediaQueryList
, DOMEventTargetHelper
)
56 void MediaQueryList::GetMedia(nsACString
& aMedia
) const {
57 mMediaList
->GetText(aMedia
);
60 bool MediaQueryList::Matches() {
61 if (mViewportDependent
&&
62 mDocument
->StyleOrLayoutObservablyDependsOnParentDocumentLayout()) {
63 RefPtr
<Document
> doc
= mDocument
;
64 // This is enough to trigger media query updates in the current doc, and
65 // will flush the parent document layout if appropriate.
66 doc
->FlushPendingNotifications(FlushType::Layout
);
71 void MediaQueryList::AddListener(EventListener
* aListener
, ErrorResult
& aRv
) {
76 AddEventListenerOptionsOrBoolean options
;
77 options
.SetAsBoolean() = false;
79 AddEventListener(u
"change"_ns
, aListener
, options
, Nullable
<bool>(), aRv
);
82 void MediaQueryList::RemoveListener(EventListener
* aListener
,
88 EventListenerOptionsOrBoolean options
;
89 options
.SetAsBoolean() = false;
91 RemoveEventListener(u
"change"_ns
, aListener
, options
, aRv
);
94 bool MediaQueryList::HasListeners() const {
95 return HasListenersFor(nsGkAtoms::onchange
);
98 void MediaQueryList::Disconnect() {
99 DisconnectFromOwner();
100 IgnoreKeepAliveIfHasListenersFor(nsGkAtoms::onchange
);
103 nsISupports
* MediaQueryList::GetParentObject() const {
104 return ToSupports(mDocument
);
107 JSObject
* MediaQueryList::WrapObject(JSContext
* aCx
,
108 JS::Handle
<JSObject
*> aGivenProto
) {
109 return MediaQueryList_Binding::Wrap(aCx
, this, aGivenProto
);
112 void MediaQueryList::MediaFeatureValuesChanged() {
113 mMatches
= mDocument
&& mMediaList
->Matches(*mDocument
);
114 // Note that mMatchesOnRenderingUpdate remains with the old value here.
115 // That gets updated in EvaluateOnRenderingUpdate().
118 bool MediaQueryList::EvaluateOnRenderingUpdate() {
119 if (mMatches
== mMatchesOnRenderingUpdate
) {
122 mMatchesOnRenderingUpdate
= mMatches
;
123 return HasListeners();
126 void MediaQueryList::FireChangeEvent() {
127 MediaQueryListEventInit init
;
128 init
.mBubbles
= false;
129 init
.mCancelable
= false;
130 init
.mMatches
= mMatches
;
131 mMediaList
->GetText(init
.mMedia
);
133 RefPtr
<MediaQueryListEvent
> event
=
134 MediaQueryListEvent::Constructor(this, u
"change"_ns
, init
);
135 event
->SetTrusted(true);
136 DispatchEvent(*event
);
139 size_t MediaQueryList::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf
) const {
141 // mMediaList is reference counted, but it's created and primarily owned
142 // by this MediaQueryList object.
143 n
+= mMediaList
->SizeOfIncludingThis(aMallocSizeOf
);
147 } // namespace mozilla::dom