Pull clipboard support from 0.1-dev

This commit is contained in:
Joonas Javanainen 2019-07-08 17:47:36 +03:00
parent 35f7ed9737
commit 3f6bc12e0b
No known key found for this signature in database
GPG Key ID: D39CCA5CB19B9179
8 changed files with 216 additions and 1 deletions

View File

@ -12,6 +12,7 @@
- Support for navigation input system
- Support for backend/renderer name strings
- Support for saving/loading INI settings manually
- Pluggable clipboard support
### Changed

View File

@ -98,6 +98,26 @@ dependencies = [
"libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "clipboard"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"clipboard-win 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"objc 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"objc-foundation 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"objc_id 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"x11-clipboard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "clipboard-win"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "cloudabi"
version = "0.0.3"
@ -388,6 +408,7 @@ dependencies = [
name = "imgui-examples"
version = "0.0.0"
dependencies = [
"clipboard 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"glium 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)",
"image 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)",
"imgui 0.1.0-pre",
@ -599,6 +620,24 @@ dependencies = [
"malloc_buf 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "objc-foundation"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"block 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"objc 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"objc_id 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "objc_id"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"objc 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ordered-float"
version = "1.0.2"
@ -1090,6 +1129,14 @@ dependencies = [
"x11-dl 2.18.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "x11-clipboard"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"xcb 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "x11-dl"
version = "2.18.3"
@ -1100,6 +1147,15 @@ dependencies = [
"pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "xcb"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "xdg"
version = "2.2.0"
@ -1125,6 +1181,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "39f75544d7bbaf57560d2168f28fd649ff9c76153874db88bdbdfd839b1a7e7d"
"checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33"
"checksum cgl 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "55e7ec0b74fe5897894cbc207092c577e87c52f8a59e8ca8d97ef37551f60a49"
"checksum clipboard 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "25a904646c0340239dcf7c51677b33928bf24fdf424b79a57909c0109075b2e7"
"checksum clipboard-win 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3a093d6fed558e5fe24c3dfc85a68bb68f1c824f440d3ba5aca189e2998786b"
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
"checksum cocoa 0.18.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cf79daa4e11e5def06e55306aa3601b87de6b5149671529318da048f67cdd77b"
"checksum color_quant 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0dbbb57365263e881e805dc77d94697c9118fd94d8da011240555aa7b23445bd"
@ -1178,6 +1236,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32"
"checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273"
"checksum objc 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "31d20fd2b37e07cf5125be68357b588672e8cefe9a96f8c17a9d46053b3e590d"
"checksum objc-foundation 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9"
"checksum objc_id 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b"
"checksum ordered-float 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "18869315e81473c951eb56ad5558bbc56978562d3ecfb87abb7a1e944cea4518"
"checksum osmesa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "88cfece6e95d2e717e0872a7f53a8684712ad13822a7979bc760b9c77ec0013b"
"checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13"
@ -1234,6 +1294,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
"checksum winit 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d233301129ddd33260b47f76900b50e154b7254546e2edba0e5468a1a5fe4de3"
"checksum x11-clipboard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "89bd49c06c9eb5d98e6ba6536cf64ac9f7ee3a009b2f53996d405b3944f6bcea"
"checksum x11-dl 2.18.3 (registry+https://github.com/rust-lang/crates.io-index)" = "940586acb859ea05c53971ac231685799a7ec1dee66ac0bccc0e6ad96e06b4e3"
"checksum xcb 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5e917a3f24142e9ff8be2414e36c649d47d6cc2ba81f16201cdef96e533e02de"
"checksum xdg 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d089681aa106a86fade1b0128fb5daf07d5867a509ab036d99988dec80429a57"
"checksum xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "541b12c998c5b56aa2b4e6f18f03664eef9a4fd0a246a55594efae6cc2d964b5"

View File

@ -10,8 +10,9 @@ license = "MIT/Apache-2.0"
publish = false
[dev-dependencies]
clipboard = "0.5"
glium = { version = "0.25", default-features = true }
image = "0.21"
imgui = { version = "0.1.0-pre", path = "../" }
imgui-glium-renderer = { version = "0.1.0-pre", path = "../imgui-glium-renderer" }
imgui-winit-support = { version = "0.1.0-pre", path = "../imgui-winit-support" }
image = "0.21"

View File

@ -0,0 +1,19 @@
use clipboard::{ClipboardContext, ClipboardProvider};
use imgui::{ClipboardBackend, ImStr, ImString};
pub struct ClipboardSupport(ClipboardContext);
pub fn init() -> Option<ClipboardSupport> {
ClipboardContext::new()
.ok()
.map(|ctx| ClipboardSupport(ctx))
}
impl ClipboardBackend for ClipboardSupport {
fn get(&mut self) -> Option<ImString> {
self.0.get_contents().ok().map(|text| text.into())
}
fn set(&mut self, text: &ImStr) {
let _ = self.0.set_contents(text.to_str().to_owned());
}
}

View File

@ -5,6 +5,8 @@ use imgui_glium_renderer::GliumRenderer;
use imgui_winit_support::{HiDpiMode, WinitPlatform};
use std::time::Instant;
mod clipboard;
pub struct System {
pub events_loop: glutin::EventsLoop,
pub display: glium::Display,
@ -30,6 +32,12 @@ pub fn init(title: &str) -> System {
let mut imgui = Context::create();
imgui.set_ini_filename(None);
if let Some(backend) = clipboard::init() {
imgui.set_clipboard_backend(Box::new(backend));
} else {
eprintln!("Failed to initialize clipboard");
}
let mut platform = WinitPlatform::init(&mut imgui);
{
let gl_window = display.gl_window();

109
src/clipboard.rs Normal file
View File

@ -0,0 +1,109 @@
use std::fmt;
use std::os::raw::{c_char, c_void};
use std::panic::catch_unwind;
use std::process;
use std::ptr;
use crate::string::{ImStr, ImString};
use crate::Ui;
pub trait ClipboardBackend {
fn get(&mut self) -> Option<ImString>;
fn set(&mut self, value: &ImStr);
}
pub(crate) struct ClipboardContext {
backend: Box<dyn ClipboardBackend>,
// this is needed to keep ownership of the value when the raw C callback is called
last_value: ImString,
}
impl ClipboardContext {
pub fn new(backend: Box<dyn ClipboardBackend>) -> ClipboardContext {
ClipboardContext {
backend,
last_value: ImString::default(),
}
}
}
impl fmt::Debug for ClipboardContext {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"ClipboardContext({:?}, {:?})",
&(*self.backend) as *const _,
self.last_value
)
}
}
pub(crate) unsafe extern "C" fn get_clipboard_text(user_data: *mut c_void) -> *const c_char {
let result = catch_unwind(|| {
let ctx = &mut *(user_data as *mut ClipboardContext);
match ctx.backend.get() {
Some(text) => {
ctx.last_value = text;
ctx.last_value.as_ptr()
}
None => ptr::null(),
}
});
result.unwrap_or_else(|_| {
eprintln!("Clipboard getter panicked");
process::abort();
})
}
pub(crate) unsafe extern "C" fn set_clipboard_text(user_data: *mut c_void, text: *const c_char) {
let result = catch_unwind(|| {
let ctx = &mut *(user_data as *mut ClipboardContext);
let text = ImStr::from_ptr_unchecked(text);
ctx.backend.set(text);
});
result.unwrap_or_else(|_| {
eprintln!("Clipboard setter panicked");
process::abort();
});
}
impl<'ui> Ui<'ui> {
/// Returns the current clipboard contents as text or None if clipboard cannot be accessed or
/// it is empty
pub fn clipboard_text(&self) -> Option<ImString> {
let io = self.io();
io.get_clipboard_text_fn.and_then(|get_clipboard_text_fn| {
// Bypass FFI if we end up calling our own function anyway
if get_clipboard_text_fn == get_clipboard_text {
let ctx = unsafe { &mut *(io.clipboard_user_data as *mut ClipboardContext) };
ctx.backend.get()
} else {
unsafe {
let text_ptr = get_clipboard_text_fn(io.clipboard_user_data);
if text_ptr.is_null() || *text_ptr == b'\0' as c_char {
None
} else {
Some(ImStr::from_ptr_unchecked(text_ptr).to_owned())
}
}
}
})
}
/// Sets the clipboard contents.
///
/// Does nothing if the clipboard cannot be accessed.
pub fn set_clipboard_text(&self, text: &ImStr) {
let io = self.io();
if let Some(set_clipboard_text_fn) = io.set_clipboard_text_fn {
// Bypass FFI if we end up calling our own function anyway
if set_clipboard_text_fn == set_clipboard_text {
let ctx = unsafe { &mut *(io.clipboard_user_data as *mut ClipboardContext) };
ctx.backend.set(text);
} else {
unsafe {
set_clipboard_text_fn(io.clipboard_user_data, text.as_ptr());
}
}
}
}
}

View File

@ -5,6 +5,7 @@ use std::ops::Drop;
use std::ptr;
use std::rc::Rc;
use crate::clipboard::{ClipboardBackend, ClipboardContext};
use crate::fonts::atlas::{FontAtlas, FontAtlasRefMut, FontId, SharedFontAtlas};
use crate::io::Io;
use crate::string::{ImStr, ImString};
@ -54,6 +55,7 @@ pub struct Context {
log_filename: Option<ImString>,
platform_name: Option<ImString>,
renderer_name: Option<ImString>,
clipboard_ctx: Option<Box<ClipboardContext>>,
}
lazy_static! {
@ -170,6 +172,15 @@ impl Context {
let data = unsafe { CStr::from_ptr(sys::igSaveIniSettingsToMemory(ptr::null_mut())) };
buf.push_str(&data.to_string_lossy());
}
pub fn set_clipboard_backend(&mut self, backend: Box<dyn ClipboardBackend>) {
use std::borrow::BorrowMut;
let mut clipboard_ctx = Box::new(ClipboardContext::new(backend));
let io = self.io_mut();
io.set_clipboard_text_fn = Some(crate::clipboard::set_clipboard_text);
io.get_clipboard_text_fn = Some(crate::clipboard::get_clipboard_text);
io.clipboard_user_data = clipboard_ctx.borrow_mut() as *mut ClipboardContext as *mut _;
self.clipboard_ctx.replace(clipboard_ctx);
}
fn create_internal(shared_font_atlas: Option<Rc<RefCell<SharedFontAtlas>>>) -> Self {
let _guard = CTX_MUTEX.lock();
assert!(
@ -186,6 +197,7 @@ impl Context {
log_filename: None,
platform_name: None,
renderer_name: None,
clipboard_ctx: None,
}
}
fn is_current_context(&self) -> bool {
@ -263,6 +275,7 @@ impl SuspendedContext {
log_filename: None,
platform_name: None,
renderer_name: None,
clipboard_ctx: None,
};
if ctx.is_current_context() {
// Oops, the context was activated -> deactivate

View File

@ -10,6 +10,7 @@ use std::str;
use std::thread;
pub use self::child_frame::ChildFrame;
pub use self::clipboard::*;
pub use self::color_editors::{
ColorButton, ColorEdit, ColorEditMode, ColorFormat, ColorPicker, ColorPickerMode, ColorPreview,
EditableColor,
@ -52,6 +53,7 @@ pub use self::window_draw_list::{ChannelsSplit, ImColor, WindowDrawList};
use internal::RawCast;
mod child_frame;
mod clipboard;
mod color_editors;
mod context;
mod drag;