aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/textinput.rs
diff options
context:
space:
mode:
authorGae24 <96017547+Gae24@users.noreply.github.com>2025-01-15 20:45:29 +0100
committerGitHub <noreply@github.com>2025-01-15 19:45:29 +0000
commitd470f219b1cb80f50bb9050a7649627397f7a5d9 (patch)
treeab726a47db048f1a14edab25d686f2c2b10e52d5 /components/script/textinput.rs
parentcd9e831e91e7587a71c5fa401b3721b5cfad8f43 (diff)
downloadservo-d470f219b1cb80f50bb9050a7649627397f7a5d9.tar.gz
servo-d470f219b1cb80f50bb9050a7649627397f7a5d9.zip
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>
Diffstat (limited to 'components/script/textinput.rs')
-rw-r--r--components/script/textinput.rs93
1 files changed, 93 insertions, 0 deletions
diff --git a/components/script/textinput.rs b/components/script/textinput.rs
index 338303fc7b8..d59cd5b6a5d 100644
--- a/components/script/textinput.rs
+++ b/components/script/textinput.rs
@@ -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
}