Skip to content

Commit

Permalink
feat: add MacOS print options (#1259)
Browse files Browse the repository at this point in the history
* feat: add MacOS print options

Currently, when printing on a MacOS, it defaults to a quite big margin, which does not reflect the side of
it when printing on the web. The current code just creates a new NSPrintInfo from the default, which for some
reason has a large margin.

This changes so that the default margin is 0 and add the option to change it when printing the webview on MacOs.
This is not a field that can be changed by the user on the appkit modal, so it has to be defined before the modal is open.

Other options could be added on top of these ones, but for this initial commit/PR decided to go with adding the margins
since it seems to be the one with bigger discrepancy compared to the web version.

References:
- https://developer.apple.com/documentation/appkit/nsprintinfo
  • Loading branch information
augustoccesar authored May 14, 2024
1 parent f516122 commit 0f14e2a
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .changes/macos_default_print_margins.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"wry": minor
---

Default the margin when printing on MacOS to 0 so it is closer to the behavior of when printing on the web.
5 changes: 5 additions & 0 deletions .changes/macos_print_margin_options.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"wry": minor
---

Add `WebViewExtMacOS::print_with_options` which allows to modify the margins that will be used on the print dialog.
8 changes: 8 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,8 @@ use webkitgtk::*;
pub(crate) mod wkwebview;
#[cfg(any(target_os = "macos", target_os = "ios"))]
use wkwebview::*;
#[cfg(any(target_os = "macos", target_os = "ios"))]
pub use wkwebview::{PrintMargin, PrintOptions};

#[cfg(target_os = "windows")]
pub(crate) mod webview2;
Expand Down Expand Up @@ -1598,6 +1600,8 @@ pub trait WebViewExtMacOS {
fn ns_window(&self) -> cocoa::base::id;
/// Attaches this webview to the given NSWindow and removes it from the current one.
fn reparent(&self, window: cocoa::base::id) -> Result<()>;
// Prints with extra options
fn print_with_options(&self, options: &PrintOptions) -> Result<()>;
}

#[cfg(target_os = "macos")]
Expand All @@ -1620,6 +1624,10 @@ impl WebViewExtMacOS for WebView {
fn reparent(&self, window: cocoa::base::id) -> Result<()> {
self.webview.reparent(window)
}

fn print_with_options(&self, options: &PrintOptions) -> Result<()> {
self.webview.print_with_options(options)
}
}

/// Additional methods on `WebView` that are specific to iOS.
Expand Down
23 changes: 23 additions & 0 deletions src/wkwebview/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ use std::{
sync::{Arc, Mutex},
};

use core_graphics::base::CGFloat;
use core_graphics::geometry::{CGPoint, CGRect, CGSize};

use objc::{
declare::ClassDecl,
runtime::{Class, Object, Sel, BOOL},
Expand Down Expand Up @@ -79,6 +81,19 @@ const NS_JSON_WRITING_FRAGMENTS_ALLOWED: u64 = 4;
static COUNTER: Counter = Counter::new();
static WEBVIEW_IDS: Lazy<Mutex<HashSet<u32>>> = Lazy::new(Default::default);

#[derive(Debug, Default, Copy, Clone)]
pub struct PrintMargin {
pub top: f32,
pub right: f32,
pub bottom: f32,
pub left: f32,
}

#[derive(Debug, Default, Clone)]
pub struct PrintOptions {
pub margins: PrintMargin,
}

pub(crate) struct InnerWebView {
pub webview: id,
pub manager: id,
Expand Down Expand Up @@ -1128,6 +1143,10 @@ r#"Object.defineProperty(window, 'ipc', {
}

pub fn print(&self) -> crate::Result<()> {
self.print_with_options(&PrintOptions::default())
}

pub fn print_with_options(&self, options: &PrintOptions) -> crate::Result<()> {
// Safety: objc runtime calls are unsafe
#[cfg(target_os = "macos")]
unsafe {
Expand All @@ -1139,6 +1158,10 @@ r#"Object.defineProperty(window, 'ipc', {
// Create a shared print info
let print_info: id = msg_send![class!(NSPrintInfo), sharedPrintInfo];
let print_info: id = msg_send![print_info, init];
let () = msg_send![print_info, setTopMargin:CGFloat::from(options.margins.top)];
let () = msg_send![print_info, setRightMargin:CGFloat::from(options.margins.right)];
let () = msg_send![print_info, setBottomMargin:CGFloat::from(options.margins.bottom)];
let () = msg_send![print_info, setLeftMargin:CGFloat::from(options.margins.left)];
// Create new print operation from the webview content
let print_operation: id = msg_send![self.webview, printOperationWithPrintInfo: print_info];
// Allow the modal to detach from the current thread and be non-blocker
Expand Down

0 comments on commit 0f14e2a

Please sign in to comment.