issue #21251: magstripe reader support

If you are in the sales order screen and swipe a credit card, it will automatically associate the credit card with the order's customer, slide the panel over to the credit card box, add the credit card to the credit card box, and put the focus on ccv or amount (depending on if ccv is visible).

One gotcha: if the cursor is inside a textbox, the magstripe stream will not be captured by the app, but will enter into the textbox. I can't think of any non-terrible ways of preventing this.

The magstripe will only get captured in the sales order workspace. It wouldn't be tough to get it working in other places, too, if we want.

Note also that the credit card type (Visa, etc) does not get reliably captured by the magstripe reader. However, this data is not required by Authorize.net, so we don't capture or send it. It's worth noting that we don't let users change this data after the card has been entered, so in the case of magstripe-captured cards there is no way to ever set this field.

Note also that I refactored the dirty-workspace-exit popup to use the general notify popup, so it's verbiage is a bit different now.

I also got working keyboard input in the notify popup. You can press enter, left, right, tab, or shift-tab, and the popup will respond as expected.

I also implemented hotkeys, but because we're planning on changing the UI soon, we're not going to advertise it as available.