-
-
Notifications
You must be signed in to change notification settings - Fork 278
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
enhance: Add API to allow print options #1317
base: dev
Are you sure you want to change the base?
Conversation
Currently there is an issue with printing PDF on webkit. It shows |
It seems there is easy way to print to PDF in WebkitGtk: https://bugs.webkit.org/show_bug.cgi?id=212814 |
Perhaps there is a way to make the PDF generation work by using the PDF printer by name, but there is a problem with i18n in that case as the printer name can change... I'm not sure how to continue there. Still, it's possible to have the printing options without the PDF generation if that can be of use to other people (it seems it would be looking at tauri-apps/tauri#4917) |
On windows, you could use the WebView2 function |
Here's a workable POC for the Windows to print to PDF. I'm unfamiliar with win32 API, it would be nice if this one can give you some ideas. pub fn print(&self) -> Result<()> {
// self.eval(
// "window.print()",
// None::<Box<dyn FnOnce(String) + Send + 'static>>,
// )
unsafe {
if let Ok(webview7) = self.webview.cast::<ICoreWebView2_7>() {
if let Ok(env) = self.env.cast::<ICoreWebView2Environment6>() {
let printsettings = env.CreatePrintSettings().unwrap();
let _ = webview7.PrintToPdf(
PCWSTR::from_raw(HSTRING::from("C:\\Users\\Jason\\Downloads\\webview2.pdf").as_ptr()),
&printsettings,
&PrintToPdfCompletedHandler::create(Box::new(move |_hresult, _is_success| {
dbg!(_hresult, _is_success);
Ok(())
})),
);
}
}
Ok(())
}
} |
It seems possible to print to PDF using the print to file printer, and it's possible to discover this printer as webkitgtk does it already, but in a private part of its code... Just below you have the code that uses the "print to file printer" and generates a file Ideally, in wry, we should be able to run identical code and fetch the printer name to feed it to the printer settings. Here is the code that selects the printer from the printer settings in WebkitGtk (and if not found selects the default printer) Up until now, I was not able to select correctly the file printer, I could trace the function calls with What's tricky is that the gtk_enumerate_printers is not available to the gtk crate. And the gtk crate is unmaintained. However, the gtk4 crate has the function, but that's not the gtk version wry is built against... :( Also, trying to use extern C bindings for those gtk functions could work but the use gtk;
pub struct Printer { }
pub struct PrinterBackend { }
struct UserData {
printer_name: &str
}
extern "C" {
// pub fn wry_gtk_find_file_printer(settings: >k::PrintSettings) -> &str;
pub fn gtk_enumerate_printers(cb: Fn(&Printer, &UserData) -> bool, userdata: &UserData, destroy: &UserData, wait: bool);
pub fn gtk_printer_get_backend(printer: &Printer) -> &PrinterBackend;
pub fn gtk_printer_get_name(printer: &Printer) -> &str;
fn g_type_name(backend: &PrinterBackend) -> &str;
}
pub fn find_file_printer() -> String {
let userdata: UserData;
unsafe {
gtk_enumerate_printers(|printer, userdata| {
let backend = gtk_printer_get_backend(printer);
let type_name = g_type_name(backend);
if (type_name == "GtkPrintBackendFile") {
userdata.printer_name = gtk_printer_get_name(printer);
}
}, &userdata, null, true);
}
return userdata.printer_name;
} I'll probably continue investigation later... |
As for Win32, I have no means of testing |
Another problem... with this I found that the printers have all an empty name :( use gtk;
use std::ptr;
pub struct Printer { }
pub struct PrinterBackend { }
struct UserData {
printer_name: String
}
extern "C" {
// pub fn wry_gtk_find_file_printer(settings: >k::PrintSettings) -> &str;
pub fn gtk_enumerate_printers(cb: extern "C" fn(&Printer, &UserData) -> bool, userdata: &UserData, destroy: *const i32, wait: bool);
pub fn gtk_printer_get_backend(printer: &Printer) -> &PrinterBackend;
pub fn gtk_printer_get_name(printer: &Printer) -> &str;
fn g_type_name(backend: &PrinterBackend) -> &str;
}
extern "C" fn printer_enumerate(printer: &Printer, _userdata: &UserData) -> bool {
unsafe {
// let backend = gtk_printer_get_backend(printer);
//let type_name = g_type_name(backend);
//if type_name == "GtkPrintBackendFile" {
// userdata.printer_name = gtk_printer_get_name(printer).to_string();
// return true; // stop iteration
//}
let printer_name = gtk_printer_get_name(printer);
println!("Printer: {printer_name}");
return false; // continue iteration
}
}
pub fn find_file_printer() -> String {
let userdata: UserData = UserData { printer_name: "".to_string() };
unsafe {
let cb = printer_enumerate as extern "C" fn(&Printer, &UserData) -> bool;
gtk_enumerate_printers(cb, &userdata, ptr::null(), true);
}
return userdata.printer_name;
} |
What I'll probably be doing is to set up a HTTP server and open the browser to localhost on that server and let the user use the print dialog himself... But this PR is still interesting to get a print API rolling... |
Implement global print options with WebKitGtk2 support and reuse MacOS support from #1259
Previous failed attempt for Windows was #1167
This could allow a print API in Tauri: tauri-apps/tauri#4917
The specific goal I have is to generate PDF files from WebViews in Tauri.
I took the approach of specifying options in an array as it allows to only pass some options of interest and not the full list, and it also allows some platform to support some options and not others. this would be easier to have the feature developped and some options might not be relevant everywhere.