ltk_webkit/wpe/
clipboard.rsuse std::ffi::{ c_char, CString };
use glib_sys::g_free;
use wpe_platform_sys::*;
use super::WebView;
use crate::page_scripts::{ paste_script, selection_of, SELECTION_SCRIPT };
const TEXT_FORMATS: [ &[ u8 ]; 2 ] = [ b"text/plain;charset=utf-8\0", b"text/plain\0" ];
impl WebView
{
pub fn take_copied_text( &self ) -> Option<String>
{
let clipboard =
{
let mut g = self.inner.lock().ok()?;
let clipboard = clipboard_of( g.display )?;
let count = unsafe { wpe_clipboard_get_change_count( clipboard ) };
if count == g.clipboard_seen { return None; }
g.clipboard_seen = count;
clipboard
};
read_text( clipboard )
}
pub fn set_clipboard_text( &self, text: &str )
{
let Ok( text ) = CString::new( text ) else { return };
let Ok( mut g ) = self.inner.lock() else { return };
let Some( clipboard ) = clipboard_of( g.display ) else { return };
unsafe
{
let content = wpe_clipboard_content_new();
wpe_clipboard_content_set_text( content, text.as_ptr() );
wpe_clipboard_set_content( clipboard, content );
wpe_clipboard_content_unref( content );
g.clipboard_seen = wpe_clipboard_get_change_count( clipboard );
}
}
pub fn selected_text( &self, done: impl FnOnce( String ) + 'static )
{
self.evaluate_javascript( SELECTION_SCRIPT, move |result|
{
done( result.map( |json| selection_of( &json ) ).unwrap_or_default() );
} );
}
pub fn paste_at( &self, x: f64, y: f64, text: &str )
{
let zoom = self.zoom().max( 0.01 );
let Some( ( vx, vy ) ) = self.inner.lock().ok().map( |g| g.to_view( x, y ) ) else { return };
self.evaluate_javascript( &paste_script( vx / zoom, vy / zoom, text ), |_| {} );
}
}
fn clipboard_of( display: *mut WPEDisplay ) -> Option<*mut WPEClipboard>
{
if display.is_null() { return None; }
let clipboard = unsafe { wpe_display_get_clipboard( display ) };
( !clipboard.is_null() ).then_some( clipboard )
}
fn read_text( clipboard: *mut WPEClipboard ) -> Option<String>
{
for format in TEXT_FORMATS
{
let mut size = 0;
let data = unsafe { wpe_clipboard_read_text( clipboard, format.as_ptr() as *const c_char, &mut size ) };
if data.is_null() { continue; }
let text = String::from_utf8_lossy( unsafe { std::slice::from_raw_parts( data as *const u8, size ) } ).into_owned();
unsafe { g_free( data as *mut _ ) };
if !text.is_empty() { return Some( text ); }
}
None
}