script/dom/clipboard/
clipboardevent.rs1use dom_struct::dom_struct;
6use js::context::JSContext;
7use js::rust::HandleObject;
8use script_bindings::match_domstring_ascii;
9use script_bindings::reflector::reflect_dom_object_with_proto;
10use script_bindings::str::DOMString;
11use style::Atom;
12
13use crate::dom::bindings::codegen::Bindings::ClipboardEventBinding::{
14 ClipboardEventInit, ClipboardEventMethods,
15};
16use crate::dom::bindings::codegen::Bindings::EventBinding::EventMethods;
17use crate::dom::bindings::inheritance::Castable;
18use crate::dom::bindings::root::{DomRoot, MutNullableDom};
19use crate::dom::datatransfer::DataTransfer;
20use crate::dom::event::{Event, EventBubbles, EventCancelable};
21use crate::dom::window::Window;
22use crate::drag::drag_data_store::Kind;
23
24#[derive(Clone, Debug, MallocSizeOf)]
27pub(crate) enum ClipboardEventType {
28 Change,
29 Copy,
30 Cut,
31 Paste,
32 Other(Atom),
33}
34
35impl ClipboardEventType {
36 pub(crate) fn as_atom(&self) -> Atom {
38 match self {
39 ClipboardEventType::Change => "clipboardchange".into(),
40 ClipboardEventType::Copy => "copy".into(),
41 ClipboardEventType::Cut => "cut".into(),
42 ClipboardEventType::Paste => "paste".into(),
43 ClipboardEventType::Other(atom) => atom.clone(),
44 }
45 }
46}
47
48impl From<DOMString> for ClipboardEventType {
49 fn from(value: DOMString) -> Self {
50 match_domstring_ascii!(value,
51 "clipboardchange" => return ClipboardEventType::Change,
52 "copy" => return ClipboardEventType::Copy,
53 "cut" => return ClipboardEventType::Cut,
54 "paste" => return ClipboardEventType::Paste,
55 _ => {},
56 );
57 ClipboardEventType::Other(value.into())
58 }
59}
60
61#[dom_struct]
62pub(crate) struct ClipboardEvent {
63 event: Event,
64 #[no_trace]
65 clipboard_event_type: ClipboardEventType,
66 clipboard_data: MutNullableDom<DataTransfer>,
67}
68
69impl ClipboardEvent {
70 fn new_inherited(
71 clipboard_event_type: ClipboardEventType,
72 clipboard_data: Option<&DataTransfer>,
73 ) -> ClipboardEvent {
74 ClipboardEvent {
75 event: Event::new_inherited(),
76 clipboard_event_type,
77 clipboard_data: MutNullableDom::new(clipboard_data),
78 }
79 }
80
81 pub(crate) fn new(
82 cx: &mut JSContext,
83 window: &Window,
84 proto: Option<HandleObject>,
85 clipboard_event_type: ClipboardEventType,
86 can_bubble: EventBubbles,
87 cancelable: EventCancelable,
88 clipboard_data: Option<&DataTransfer>,
89 ) -> DomRoot<ClipboardEvent> {
90 let event_type = clipboard_event_type.as_atom();
91 let event = reflect_dom_object_with_proto(
92 cx,
93 Box::new(ClipboardEvent::new_inherited(
94 clipboard_event_type,
95 clipboard_data,
96 )),
97 window,
98 proto,
99 );
100 event.upcast::<Event>().init_event(
101 event_type,
102 bool::from(can_bubble),
103 bool::from(cancelable),
104 );
105 event
106 }
107
108 pub(crate) fn clipboard_event_type(&self) -> &ClipboardEventType {
109 &self.clipboard_event_type
110 }
111
112 pub(crate) fn set_clipboard_data(&self, clipboard_data: Option<&DataTransfer>) {
113 self.clipboard_data.set(clipboard_data);
114 }
115
116 pub(crate) fn clipboard_data(&self) -> Option<DomRoot<DataTransfer>> {
117 self.clipboard_data.get()
118 }
119
120 pub(crate) fn text_content(&self) -> Option<String> {
123 self.clipboard_data()?
124 .data_store()?
125 .iter_item_list()
126 .find_map(|item| match item {
127 Kind::Text { data, .. } if !data.is_empty() => Some(data.to_string()),
128 _ => None,
129 })
130 }
131}
132
133impl ClipboardEventMethods<crate::DomTypeHolder> for ClipboardEvent {
134 fn Constructor(
136 cx: &mut JSContext,
137 window: &Window,
138 proto: Option<HandleObject>,
139 event_type: DOMString,
140 init: &ClipboardEventInit,
141 ) -> DomRoot<ClipboardEvent> {
142 let bubbles = EventBubbles::from(init.parent.bubbles);
143 let cancelable = EventCancelable::from(init.parent.cancelable);
144 let event = ClipboardEvent::new(
145 cx,
146 window,
147 proto,
148 event_type.into(),
149 bubbles,
150 cancelable,
151 init.clipboardData.as_deref(),
152 );
153 event.upcast::<Event>().set_composed(init.parent.composed);
154 event
155 }
156
157 fn GetClipboardData(&self) -> Option<DomRoot<DataTransfer>> {
159 self.clipboard_data.get()
160 }
161
162 fn IsTrusted(&self) -> bool {
164 self.event.IsTrusted()
165 }
166}