use {glib, gtk, Handler, Options, Window};
use gtk::{ContainerExt, WidgetExt, GtkWindowExt, WindowType};
use std::cell::RefCell;
use std::process;
use std::rc::Rc;
use webkit2gtk::{
ContextMenuExt,
ContextMenuItemExt,
UserContentInjectedFrames,
UserContentManager,
UserContentManagerExt,
UserScript,
UserScriptInjectionTime,
WebContext,
WebView,
WebViewExt,
WebViewExtManual
};
thread_local! {
static WEBVIEW: RefCell<Option<WebView>> = RefCell::new(None);
}
pub fn start<H: Handler>(opts: Options<H>) -> ! {
let handler = Rc::new(RefCell::new(opts.handler));
gtk::init().unwrap();
let window = gtk::Window::new(WindowType::Toplevel);
let min_size = opts.minimum_size.unwrap_or((opts.width, opts.height));
window.set_size_request(min_size.0 as i32, min_size.1 as i32);
window.set_default_size(opts.width as i32, opts.height as i32);
let context = WebContext::get_default().unwrap();
let scripts = UserContentManager::new();
let webview = WebView::new_with_context_and_user_content_manager(
&context,
&scripts,
);
webview.connect_context_menu(|_, menu, _, _| {
use webkit2gtk::ContextMenuAction::*;
let len = menu.get_n_items();
for i in (0..len).rev() {
let item = menu.get_item_at_position(i).unwrap();
match item.get_stock_action() {
NoAction
| CopyLinkToClipboard
| CopyImageToClipboard
| CopyImageUrlToClipboard
| Copy
| Cut
| Paste
| Delete
| SelectAll
| InputMethods
| Unicode
| SpellingGuess
| NoGuessesFound
| IgnoreSpelling
| LearnSpelling
| IgnoreGrammar
| FontMenu
| Bold
| Italic
| Underline
| Outline
| CopyVideoLinkToClipboard
| CopyAudioLinkToClipboard
| ToggleMediaControls
| ToggleMediaLoop
| EnterVideoFullscreen
| MediaPlay
| MediaPause
| MediaMute => (),
_ => menu.remove(&item)
}
}
false
});
window.set_title("");
webview.connect_title_changed({
let window = window.clone();
let webview = webview.clone();
move || {
window.set_title(match webview.get_title() {
Some(ref title) => &title,
None => "",
});
}
});
scripts.connect_script_message_received({
let handler = handler.clone();
move |_, result| {
let ctx = result.get_global_context();
let val = result.get_value();
if let (Some(val), Some(ctx)) = (val, ctx) {
if let Some(msg) = val.to_string(&ctx) {
handler.borrow_mut().message(
unsafe { Window::new() },
&msg,
)
}
}
}
});
scripts.register_script_message_handler("x");
scripts.add_script(&UserScript::new(
"window.tether = function (s) { window.webkit.messageHandlers.x.postMessage(s); };",
UserContentInjectedFrames::TopFrame,
UserScriptInjectionTime::Start,
&[], &[], ));
window.connect_delete_event({
let handler = handler.clone();
move |_, _| {
handler.borrow_mut().suspend(unsafe { Window::new() });
gtk::main_quit();
gtk::Inhibit(false)
}
});
webview.load_html(opts.html, None);
window.add(&webview);
window.show_all();
if opts.fullscreen {
window.fullscreen();
}
WEBVIEW.with(move |global| {
*global.borrow_mut() = Some(webview);
});
gtk::main();
process::exit(0)
}
pub fn load(html: &str) {
WEBVIEW.with(|webview| {
webview
.borrow()
.as_ref()
.unwrap()
.load_html(html, None);
});
}
pub fn eval(js: &str) {
WEBVIEW.with(|webview| {
webview
.borrow()
.as_ref()
.unwrap()
.run_javascript(js);
});
}
pub fn dispatch<F: FnOnce(Window) + Send + 'static>(f: F) {
let mut f = Some(f);
glib::idle_add(move || {
f.take().unwrap()(unsafe { Window::new() });
glib::Continue(false)
});
}