script/dom/media/
mediaquerylist.rs1use std::cell::Cell;
6use std::rc::Rc;
7
8use dom_struct::dom_struct;
9use style::media_queries::MediaList;
10use style::stylesheets::CustomMediaEvaluator;
11use style_traits::ToCss;
12
13use crate::dom::bindings::codegen::Bindings::EventListenerBinding::EventListener;
14use crate::dom::bindings::codegen::Bindings::EventTargetBinding::{
15 AddEventListenerOptions, EventListenerOptions,
16};
17use crate::dom::bindings::codegen::Bindings::MediaQueryListBinding::MediaQueryListMethods;
18use crate::dom::bindings::inheritance::Castable;
19use crate::dom::bindings::reflector::reflect_dom_object;
20use crate::dom::bindings::root::{Dom, DomRoot};
21use crate::dom::bindings::str::DOMString;
22use crate::dom::document::Document;
23use crate::dom::eventtarget::EventTarget;
24use crate::script_runtime::CanGc;
25
26pub(crate) enum MediaQueryListMatchState {
27 Same,
28 Changed,
29}
30
31#[dom_struct]
32pub(crate) struct MediaQueryList {
33 eventtarget: EventTarget,
34 document: Dom<Document>,
35 #[no_trace]
36 media_query_list: MediaList,
37 last_match_state: Cell<Option<bool>>,
38}
39
40impl MediaQueryList {
41 fn new_inherited(document: &Document, media_query_list: MediaList) -> MediaQueryList {
42 MediaQueryList {
43 eventtarget: EventTarget::new_inherited(),
44 document: Dom::from_ref(document),
45 media_query_list,
46 last_match_state: Cell::new(None),
47 }
48 }
49
50 pub(crate) fn new(
51 document: &Document,
52 media_query_list: MediaList,
53 can_gc: CanGc,
54 ) -> DomRoot<MediaQueryList> {
55 reflect_dom_object(
56 Box::new(MediaQueryList::new_inherited(document, media_query_list)),
57 document.window(),
58 can_gc,
59 )
60 }
61}
62
63impl MediaQueryList {
64 pub(crate) fn evaluate_changes(&self) -> MediaQueryListMatchState {
65 let matches = self.evaluate();
66
67 let result = if let Some(old_matches) = self.last_match_state.get() {
68 if old_matches == matches {
69 MediaQueryListMatchState::Same
70 } else {
71 MediaQueryListMatchState::Changed
72 }
73 } else {
74 MediaQueryListMatchState::Changed
75 };
76
77 self.last_match_state.set(Some(matches));
78 result
79 }
80
81 pub(crate) fn evaluate(&self) -> bool {
82 let quirks_mode = self.document.quirks_mode();
83 self.media_query_list.evaluate(
84 self.document.window().layout().device(),
85 quirks_mode,
86 &mut CustomMediaEvaluator::none(),
87 )
88 }
89}
90
91impl MediaQueryListMethods<crate::DomTypeHolder> for MediaQueryList {
92 fn Media(&self) -> DOMString {
94 self.media_query_list.to_css_string().into()
95 }
96
97 fn Matches(&self) -> bool {
99 match self.last_match_state.get() {
100 None => self.evaluate(),
101 Some(state) => state,
102 }
103 }
104
105 fn AddListener(&self, listener: Option<Rc<EventListener>>) {
107 self.upcast::<EventTarget>().add_event_listener(
108 DOMString::from_string("change".to_owned()),
109 listener,
110 AddEventListenerOptions {
111 parent: EventListenerOptions { capture: false },
112 once: false,
113 passive: None,
114 signal: None,
115 },
116 );
117 }
118
119 fn RemoveListener(&self, listener: Option<Rc<EventListener>>) {
121 self.upcast::<EventTarget>().remove_event_listener(
122 DOMString::from_string("change".to_owned()),
123 &listener,
124 &EventListenerOptions { capture: false },
125 );
126 }
127
128 event_handler!(change, GetOnchange, SetOnchange);
130}