Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix clipboard on Wayland #1613

Merged
merged 1 commit into from
May 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion egui-winit/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ bytemuck = ["egui/bytemuck"]

# enable cut/copy/paste to OS clipboard.
# if disabled a clipboard will be simulated so you can still copy/paste within the egui app.
clipboard = ["arboard"]
clipboard = ["arboard", "smithay-clipboard"]

# enable opening links in a browser when an egui hyperlink is clicked.
links = ["webbrowser"]
Expand Down Expand Up @@ -55,3 +55,6 @@ webbrowser = { version = "0.7", optional = true }

# feature screen_reader
tts = { version = "0.20", optional = true } # stuck on old version due to compilation problems on linux

[target.'cfg(any(target_os="linux", target_os="dragonfly", target_os="freebsd", target_os="netbsd", target_os="openbsd"))'.dependencies]
smithay-clipboard = { version = "0.6.3", optional = true }
92 changes: 86 additions & 6 deletions egui-winit/src/clipboard.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::os::raw::c_void;

/// Handles interfacing with the OS clipboard.
///
/// If the "clipboard" feature is off, or we cannot connect to the OS clipboard,
Expand All @@ -6,23 +8,64 @@ pub struct Clipboard {
#[cfg(feature = "arboard")]
arboard: Option<arboard::Clipboard>,

#[cfg(all(
any(
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd"
),
feature = "smithay-clipboard"
))]
smithay: Option<smithay_clipboard::Clipboard>,

/// Fallback manual clipboard.
clipboard: String,
}

impl Default for Clipboard {
fn default() -> Self {
impl Clipboard {
#[allow(unused_variables)]
pub fn new(#[allow(unused_variables)] wayland_display: Option<*mut c_void>) -> Self {
Self {
#[cfg(feature = "arboard")]
arboard: init_arboard(),

clipboard: String::default(),
#[cfg(all(
any(
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd"
),
feature = "smithay-clipboard"
))]
smithay: init_smithay_clipboard(wayland_display),
clipboard: Default::default(),
}
}
}

impl Clipboard {
pub fn get(&mut self) -> Option<String> {
#[cfg(all(
any(
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd"
),
feature = "smithay-clipboard"
))]
if let Some(clipboard) = &mut self.smithay {
return match clipboard.load() {
Ok(text) => Some(text),
Err(err) => {
tracing::error!("Paste error: {}", err);
None
}
};
}

#[cfg(feature = "arboard")]
if let Some(clipboard) = &mut self.arboard {
return match clipboard.get_text() {
Expand All @@ -38,6 +81,21 @@ impl Clipboard {
}

pub fn set(&mut self, text: String) {
#[cfg(all(
any(
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd"
),
feature = "smithay-clipboard"
))]
if let Some(clipboard) = &mut self.smithay {
clipboard.store(text);
return;
}

#[cfg(feature = "arboard")]
if let Some(clipboard) = &mut self.arboard {
if let Err(err) = clipboard.set_text(text) {
Expand All @@ -60,3 +118,25 @@ fn init_arboard() -> Option<arboard::Clipboard> {
}
}
}

#[cfg(all(
any(
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd"
),
feature = "smithay-clipboard"
))]
fn init_smithay_clipboard(
wayland_display: Option<*mut c_void>,
) -> Option<smithay_clipboard::Clipboard> {
if let Some(display) = wayland_display {
#[allow(unsafe_code)]
Some(unsafe { smithay_clipboard::Clipboard::new(display) })
} else {
tracing::error!("Cannot initialize smithay clipboard without a display handle!");
None
}
}
42 changes: 39 additions & 3 deletions egui-winit/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

#![allow(clippy::manual_range_contains)]

use std::os::raw::c_void;

pub use egui;
pub use winit;

Expand All @@ -14,6 +16,15 @@ mod window_settings;

pub use window_settings::WindowSettings;

#[cfg(any(
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd"
))]
use winit::platform::unix::WindowExtUnix;

pub fn native_pixels_per_point(window: &winit::window::Window) -> f32 {
window.scale_factor() as f32
}
Expand Down Expand Up @@ -53,13 +64,21 @@ impl State {
/// * `max_texture_side`: e.g. `GL_MAX_TEXTURE_SIZE`
/// * the native `pixels_per_point` (dpi scaling).
pub fn new(max_texture_side: usize, window: &winit::window::Window) -> Self {
Self::from_pixels_per_point(max_texture_side, native_pixels_per_point(window))
Self::from_pixels_per_point(
max_texture_side,
native_pixels_per_point(window),
get_wayland_display(window),
)
}

/// Initialize with:
/// * `max_texture_side`: e.g. `GL_MAX_TEXTURE_SIZE`
/// * the given `pixels_per_point` (dpi scaling).
pub fn from_pixels_per_point(max_texture_side: usize, pixels_per_point: f32) -> Self {
pub fn from_pixels_per_point(
max_texture_side: usize,
pixels_per_point: f32,
wayland_display: Option<*mut c_void>,
) -> Self {
Self {
start_time: instant::Instant::now(),
egui_input: egui::RawInput {
Expand All @@ -72,7 +91,7 @@ impl State {
current_cursor_icon: egui::CursorIcon::Default,
current_pixels_per_point: pixels_per_point,

clipboard: Default::default(),
clipboard: clipboard::Clipboard::new(wayland_display),
screen_reader: screen_reader::ScreenReader::default(),

simulate_touch_screen: false,
Expand Down Expand Up @@ -659,6 +678,23 @@ fn translate_cursor(cursor_icon: egui::CursorIcon) -> Option<winit::window::Curs
}
}

/// Returns a Wayland display handle if the target is running Wayland
fn get_wayland_display(window: &winit::window::Window) -> Option<*mut c_void> {
#[cfg(any(
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd"
))]
{
return window.wayland_display();
}

#[allow(unreachable_code)]
None
}

// ---------------------------------------------------------------------------

/// Profiling macro for feature "puffin"
Expand Down