Implement Clipboard Event Api (#33576)

* implement ClipboardEvent interface

Signed-off-by: Gae24 <96017547+Gae24@users.noreply.github.com>

* draft implementation of clipboard events

Signed-off-by: Gae24 <96017547+Gae24@users.noreply.github.com>

* handle received clipboard events inside html elemtents

Signed-off-by: Gae24 <96017547+Gae24@users.noreply.github.com>

* use rustdoc style

Signed-off-by: Gae24 <96017547+Gae24@users.noreply.github.com>

* fix compilation errors due to rebase

Signed-off-by: Gae24 <96017547+Gae24@users.noreply.github.com>

* update arboard crate

Signed-off-by: Gae24 <96017547+Gae24@users.noreply.github.com>

* improve paste events

Signed-off-by: Gae24 <96017547+Gae24@users.noreply.github.com>

* code cleanup

revert arboard crate's update, handle text only

Signed-off-by: Gae24 <96017547+Gae24@users.noreply.github.com>

* restrict visibility of some methods to script crate

Signed-off-by: Gae24 <96017547+Gae24@users.noreply.github.com>

* propagate CanGc argument

Signed-off-by: Gae24 <96017547+Gae24@users.noreply.github.com>

* simplify handle_clipboard_msg

Signed-off-by: Gae24 <96017547+Gae24@users.noreply.github.com>

* remove code duplication

Signed-off-by: Gae24 <96017547+Gae24@users.noreply.github.com>

* fix potential borrow hazard

Signed-off-by: Gae24 <96017547+Gae24@users.noreply.github.com>

* add clipboard_event pref, restore unit test code

Signed-off-by: Gae24 <96017547+Gae24@users.noreply.github.com>

* retrict visibility of some document's methods

Signed-off-by: Gae24 <96017547+Gae24@users.noreply.github.com>

* check if clipboardevent is trusted

Signed-off-by: Gae24 <96017547+Gae24@users.noreply.github.com>

* enable clipboardevent

Signed-off-by: Gae24 <96017547+Gae24@users.noreply.github.com>

* fix compilation for egl ports

Signed-off-by: Gae24 <96017547+Gae24@users.noreply.github.com>

---------

Signed-off-by: Gae24 <96017547+Gae24@users.noreply.github.com>
This commit is contained in:
Gae24 2025-01-15 20:45:29 +01:00 committed by GitHub
parent cd9e831e91
commit d470f219b1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
24 changed files with 581 additions and 26 deletions

View file

@ -10,12 +10,21 @@ use std::default::Default;
use std::ops::{Add, AddAssign, Range};
use keyboard_types::{Key, KeyState, Modifiers, ShortcutMatcher};
use script_traits::ScriptToConstellationChan;
use unicode_segmentation::UnicodeSegmentation;
use crate::clipboard_provider::ClipboardProvider;
use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::EventBinding::Event_Binding::EventMethods;
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::str::DOMString;
use crate::dom::compositionevent::CompositionEvent;
use crate::dom::event::Event;
use crate::dom::keyboardevent::KeyboardEvent;
use crate::dom::node::NodeTraits;
use crate::dom::types::ClipboardEvent;
use crate::drag_data_store::{DragDataStore, Kind};
use crate::script_runtime::CanGc;
#[derive(Clone, Copy, PartialEq)]
pub enum Selection {
@ -1128,4 +1137,88 @@ impl<T: ClipboardProvider> TextInput<T> {
.fold(UTF8Bytes::zero(), |acc, x| acc + x.len_utf8());
self.edit_point.index = byte_offset;
}
fn paste_contents(&mut self, drag_data_store: &DragDataStore) {
for item in drag_data_store.iter_item_list() {
if let Kind::Text(string) = item {
self.insert_string(string.data());
}
}
}
}
/// <https://www.w3.org/TR/clipboard-apis/#clipboard-actions> step 3
pub(crate) fn handle_text_clipboard_action(
owning_node: &impl NodeTraits,
textinput: &DomRefCell<TextInput<ScriptToConstellationChan>>,
event: &ClipboardEvent,
can_gc: CanGc,
) -> bool {
let e = event.upcast::<Event>();
if !e.IsTrusted() {
return false;
}
// Step 3
match e.Type().str() {
"copy" => {
let selection = textinput.borrow().get_selection_text();
// Step 3.1 Copy the selected contents, if any, to the clipboard
if let Some(text) = selection {
textinput
.borrow_mut()
.clipboard_provider
.set_clipboard_contents(text);
}
// Step 3.2 Fire a clipboard event named clipboardchange
owning_node
.owner_document()
.fire_clipboardchange_event(can_gc);
},
"cut" => {
let selection = textinput.borrow().get_selection_text();
// Step 3.1 If there is a selection in an editable context where cutting is enabled, then
if let Some(text) = selection {
// Step 3.1.1 Copy the selected contents, if any, to the clipboard
textinput
.borrow_mut()
.clipboard_provider
.set_clipboard_contents(text);
// Step 3.1.2 Remove the contents of the selection from the document and collapse the selection.
textinput.borrow_mut().delete_char(Direction::Backward);
// Step 3.1.3 Fire a clipboard event named clipboardchange
owning_node
.owner_document()
.fire_clipboardchange_event(can_gc);
// Step 3.1.4 Queue tasks to fire any events that should fire due to the modification.
} else {
// Step 3.2 Else, if there is no selection or the context is not editable, then
return false;
}
},
"paste" => {
// Step 3.1 If there is a selection or cursor in an editable context where pasting is enabled, then
if let Some(data) = event.get_clipboard_data() {
// Step 3.1.1 Insert the most suitable content found on the clipboard, if any, into the context.
let drag_data_store = data.data_store().expect("This shouldn't fail");
textinput.borrow_mut().paste_contents(&drag_data_store);
// Step 3.1.2 Queue tasks to fire any events that should fire due to the modification.
} else {
// Step 3.2 Else return false.
return false;
}
},
_ => (),
}
//Step 5
true
}