Desktop: Text clipboard support (#3461)

* gray background for viewport texture

* cust copy paste support

* connect clipboard read on web

* fix eyedropper bounds

* cleanup

* add missing char events for some named keys like enter
This commit is contained in:
Timon
2025-12-12 00:16:35 +00:00
committed by GitHub
parent d6c06da878
commit 6d852f11af
30 changed files with 602 additions and 115 deletions
+12
View File
@@ -259,6 +259,18 @@ impl App {
window.update_menu(entries);
}
}
DesktopFrontendMessage::ClipboardRead => {
if let Some(window) = &self.window {
let content = window.clipboard_read();
let message = DesktopWrapperMessage::ClipboardReadResult { content };
self.app_event_scheduler.schedule(AppEvent::DesktopWrapperMessage(message));
}
}
DesktopFrontendMessage::ClipboardWrite { content } => {
if let Some(window) = &mut self.window {
window.clipboard_write(content);
}
}
DesktopFrontendMessage::WindowClose => {
self.app_event_scheduler.schedule(AppEvent::CloseWindow);
}
+4
View File
@@ -91,6 +91,10 @@ pub(crate) fn handle_window_event(browser: &Browser, input_state: &mut InputStat
key_event.character = event.logical_key.to_char_representation() as u16;
if event.state == ElementState::Pressed && key_event.character != 0 {
key_event.type_ = cef_key_event_type_t::KEYEVENT_CHAR.into();
}
// Mitigation for CEF on Mac bug to prevent NSMenu being triggered by this key event.
//
// CEF converts the key event into an `NSEvent` internally and passes that to Chromium.
+5 -1
View File
@@ -61,7 +61,11 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
}
let overlay_srgb = textureSample(t_overlays, s_diffuse, viewport_coordinate);
let viewport_srgb = textureSample(t_viewport, s_diffuse, viewport_coordinate);
var viewport_srgb = textureSample(t_viewport, s_diffuse, viewport_coordinate);
if (viewport_srgb.a < 0.001) {
viewport_srgb = constants.background_color;
}
if (overlay_srgb.a < 0.001) {
if (ui_srgb.a < 0.001) {
+19
View File
@@ -38,6 +38,7 @@ pub(crate) struct Window {
#[allow(dead_code)]
native_handle: native::NativeWindowImpl,
custom_cursors: HashMap<CustomCursorSource, CustomCursor>,
clipboard: window_clipboard::Clipboard,
}
impl Window {
@@ -57,10 +58,12 @@ impl Window {
let winit_window = event_loop.create_window(attributes).unwrap();
let native_handle = native::NativeWindowImpl::new(winit_window.as_ref(), app_event_scheduler);
let clipboard = unsafe { window_clipboard::Clipboard::connect(&winit_window) }.expect("failed to create clipboard");
Self {
winit_window: winit_window.into(),
native_handle,
custom_cursors: HashMap::new(),
clipboard,
}
}
@@ -136,6 +139,22 @@ impl Window {
pub(crate) fn update_menu(&self, entries: Vec<MenuItem>) {
self.native_handle.update_menu(entries);
}
pub(crate) fn clipboard_read(&self) -> Option<String> {
match self.clipboard.read() {
Ok(data) => Some(data),
Err(e) => {
tracing::error!("Failed to read from clipboard: {e}");
None
}
}
}
pub(crate) fn clipboard_write(&mut self, data: String) {
if let Err(e) = self.clipboard.write(data) {
tracing::error!("Failed to write to clipboard: {e}")
}
}
}
pub(crate) enum Cursor {