ltk_webkit/wpe/
context_menu.rsuse std::ffi::{ c_char, c_int, CStr };
use std::sync::{ Mutex, Weak };
use glib_sys::{ gboolean, gpointer };
use gobject_sys::{ g_signal_connect_data, GObject };
use wpe_platform_sys::{ WPE_BUTTON_SECONDARY, WPE_EVENT_POINTER_DOWN, WPE_EVENT_POINTER_UP };
use wpe_webkit_sys::*;
use super::{ popups, Inner, WebView };
use crate::types::PageTarget;
type ContextMenuFn = unsafe extern "C" fn( *mut WebKitWebView, *mut WebKitContextMenu, *mut WebKitHitTestResult, gpointer ) -> gboolean;
impl WebView
{
pub fn request_context_menu( &self, x: f64, y: f64 )
{
self.send_button( WPE_EVENT_POINTER_DOWN, WPE_BUTTON_SECONDARY, x, y );
self.send_button( WPE_EVENT_POINTER_UP, WPE_BUTTON_SECONDARY, x, y );
}
pub fn take_page_target( &self ) -> Option<PageTarget>
{
self.inner.lock().ok().and_then( |mut g| g.page_target.take() )
}
}
pub( crate ) unsafe fn connect( webview: *mut WebKitWebView, inner: Weak<Mutex<Inner>> )
{
unsafe
{
let handler = std::mem::transmute::<ContextMenuFn, unsafe extern "C" fn()>( on_context_menu );
let data = Box::into_raw( Box::new( inner ) ) as gpointer;
g_signal_connect_data( webview as *mut GObject, b"context-menu\0".as_ptr() as *const c_char, Some( handler ), data, Some( popups::drop_weak ), 0 );
}
}
unsafe extern "C" fn on_context_menu( _webview: *mut WebKitWebView, menu: *mut WebKitContextMenu, hit: *mut WebKitHitTestResult, user_data: gpointer ) -> gboolean
{
let Some( inner ) = unsafe { &*( user_data as *const Weak<Mutex<Inner>> ) }.upgrade() else { return 1 };
if menu.is_null() || hit.is_null() { return 1; }
let ( mut x, mut y ): ( c_int, c_int ) = ( 0, 0 );
let mut target = unsafe
{
webkit_context_menu_get_position( menu, &mut x, &mut y );
PageTarget
{
x: 0.0,
y: 0.0,
link_uri: text( webkit_hit_test_result_get_link_uri( hit ) ),
link_label: text( webkit_hit_test_result_get_link_label( hit ) ),
image_uri: text( webkit_hit_test_result_get_image_uri( hit ) ),
editable: webkit_hit_test_result_context_is_editable( hit ) != 0,
selection: webkit_hit_test_result_context_is_selection( hit ) != 0,
}
};
if let Ok( mut g ) = inner.lock()
{
let ( hx, hy ) = g.to_host( x as f64, y as f64 );
target.x = hx as f32;
target.y = hy as f32;
g.page_target = Some( target );
}
1
}
pub( super ) unsafe fn text( s: *const c_char ) -> Option<String>
{
if s.is_null() { return None; }
let owned = unsafe { CStr::from_ptr( s ) }.to_string_lossy().into_owned();
( !owned.is_empty() ).then_some( owned )
}