Forcing Single-Sided Printing with AppKit

I've been hand-writing GOTV postcards for two organizations1, and I decided to write a quick app to print address labels for one of them. (The other requires hand-written addresses.) It's been a long time since I did any coding, and this seemed like a nice low-stakes project to start the Cocoa wheels turning in my head again2. Worst case, I could always throw the code away and use mail-merge in Word or Pages like a normal person.

I soon had a fully functional app — not in a state to share publicly, but good enough for personal use.

There was one thing that bugged me though.

If your printer supports double-sided printing, the macOS print panel always defaults to double-sided, no matter what option you chose the last time you printed. This is apparently on purpose and has been the case for a while now.

I found that as a user you can change this with a few simple steps:

  1. Using sudo privileges, enable the web interface to CUPS.
  2. And I stopped reading there, because WTF.

Okay, well, I figured I'm writing the printing code in my app, so as the All-Powerful Programmer all I have to do is set the NSPrintInfo's duplex mode to kPMDuplexNone, which indicates single-sided printing. But no, AppKit blows away the value I set and forces the duplex mode to kPMDuplexNoTumble, which indicates double-sided printing.

The only workaround I could figure out was to subclass NSPrintPanel and override the method that opens the print panel in a sheet. My override sets the duplex mode immediately after the sheet is presented, replacing the double-sided setting AppKit stuck in, and doing so before the user interacts with the print panel. You can see my code on GitHub.

I haven't looked at how (or whether) commercial label-printing programs deal with this issue. All I know is how I dealt with it. [EDIT: It occurred to me that one way would be to not use the system print panel at all, but rather to implement one's own print panel, like Google Chrome does. Doable, but not worth it for me, and IMO it's not great to have to resort to re-implementing standard system UI just to work around a quirk.]

Unfortunately this is not a generally useful workaround, because the "Two-Sided" checkbox in the print panel is still checked, which means it does not accurately reflect the state of the NSPrintInfo. My app hides the checkbox, but this means it also hides the number-of-copies text field. This is okay for my purposes. I never want multiple copies, and because I'm printing labels I never want double-sided.

Right now I'm too lazy, but I should probably file a Feedback ticket:

  • I want the ability for my app to force single-sided every time instead of AppKit insisting on double-sided3. Another way of putting it is that I'd like the controls in the print panel to accurately reflect the values they correspond to in the NSPrintInfo instance I provide.
  • I want to be able to hide just the "Two-Sided" checkbox without having to hide the number-of-copies text field.
  • It might make sense for AppKit to default to single-sided printing, if not outright force it, when "Labels" is chosen as the media type.

Printer Brother HL L2395DW series

  1. Postcards to Voters and the Georgia Postcard Project. There's a third GOTV group I've joined called Vote Forward that writes letters rather than postcards. I haven't written for them yet. 

  2. This is the "quick Mac app" I referred to in my previous post

  3. In the latest Big Sur beta (20A5374i as of 2020-09-30) I think there is a change I did not see in the release notes. If I'm not mistaken, the "Two-Sided" checkbox remembers its setting between invocations of the print panel. But this doesn't help me. I need to always force single-sided. 

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.