ltk_webkit/wpe/
file_chooser.rsuse std::ffi::{ c_char, CStr, CString };
use std::os::unix::ffi::OsStrExt;
use std::path::Path;
use std::ptr;
use std::sync::{ Mutex, Weak };
use glib_sys::{ gboolean, gpointer, GFALSE, GTRUE };
use gobject_sys::{ g_object_ref, g_object_unref, g_signal_connect_data, GObject };
use wpe_webkit_sys::*;
use super::popups::drop_weak;
use super::{ Inner, WebView };
type RunFileChooserFn = unsafe extern "C" fn( *mut WebKitWebView, *mut WebKitFileChooserRequest, gpointer ) -> gboolean;
pub struct FileRequest
{
request: *mut WebKitFileChooserRequest,
multiple: bool,
mime_types: Vec<String>,
}
impl FileRequest
{
pub fn multiple( &self ) -> bool { self.multiple }
pub fn mime_types( &self ) -> &[ String ] { &self.mime_types }
pub fn select( mut self, paths: &[ &Path ] )
{
let owned: Vec<CString> = paths.iter().filter_map( |p| CString::new( p.as_os_str().as_bytes() ).ok() ).collect();
let mut list: Vec<*const c_char> = owned.iter().map( |s| s.as_ptr() ).collect();
list.push( ptr::null() );
let request = std::mem::replace( &mut self.request, ptr::null_mut() );
unsafe
{
webkit_file_chooser_request_select_files( request, list.as_ptr() );
g_object_unref( request as *mut GObject );
}
}
pub fn cancel( self ) {}
}
impl Drop for FileRequest
{
fn drop( &mut self )
{
if self.request.is_null() { return; }
unsafe
{
webkit_file_chooser_request_cancel( self.request );
g_object_unref( self.request as *mut GObject );
}
}
}
impl WebView
{
pub fn take_file_request( &self ) -> Option<FileRequest>
{
self.inner.lock().ok()?.file_request.take()
}
}
pub( crate ) unsafe fn connect( webview: *mut WebKitWebView, inner: Weak<Mutex<Inner>> )
{
unsafe
{
let handler = std::mem::transmute::<RunFileChooserFn, unsafe extern "C" fn()>( on_run_file_chooser );
let data = Box::into_raw( Box::new( inner ) ) as gpointer;
g_signal_connect_data( webview as *mut GObject, b"run-file-chooser\0".as_ptr() as *const c_char, Some( handler ), data, Some( drop_weak ), 0 );
}
}
unsafe extern "C" fn on_run_file_chooser( _webview: *mut WebKitWebView, request: *mut WebKitFileChooserRequest, user_data: gpointer ) -> gboolean
{
let Some( inner ) = unsafe { &*( user_data as *const Weak<Mutex<Inner>> ) }.upgrade() else { return GFALSE };
let pending = unsafe
{
g_object_ref( request as *mut GObject );
FileRequest
{
request,
multiple: webkit_file_chooser_request_get_select_multiple( request ) != 0,
mime_types: strings( webkit_file_chooser_request_get_mime_types( request ) ),
}
};
match inner.lock()
{
Ok( mut g ) => g.file_request = Some( pending ),
Err( _ ) => return GFALSE,
}
GTRUE
}
unsafe fn strings( list: *const *const c_char ) -> Vec<String>
{
let mut out = Vec::new();
if list.is_null() { return out; }
let mut i = 0;
unsafe
{
while !( *list.add( i ) ).is_null()
{
out.push( CStr::from_ptr( *list.add( i ) ).to_string_lossy().into_owned() );
i += 1;
}
}
out
}