beeware / toga

A Python native, OS native GUI toolkit.
https://toga.readthedocs.io/en/latest/
BSD 3-Clause "New" or "Revised" License
4.39k stars 684 forks source link

`PasswordInput` brings up Apple password manager on MacOS but `on_change` doesn't fire #2737

Open corranwebster opened 4 months ago

corranwebster commented 4 months ago

Describe the bug

On MacOS, when using a PasswordInput as the second or later field, when you move focus to the password field it brings up a menu to fill the field from the password manager (this doesn't happen if the field is the default editable field): image If you then go through the password manager and select a password, the obscured password is entered into the field, but the change handler doesn't fire. image

Everything works as expected if you use the right-click -> "AutoFill" -> "Passwords" menu.

This is on macOS Sonoma 14.5, Python 3.12.4 and Toga 0.4.5 installed via pip.

Steps to reproduce

  1. Run the following code:
    
    import toga

def build(app):

def handle_change(widget, /, **kwargs):
    print(widget.value)

username_label = toga.Label("Username:")
username = toga.TextInput(on_change=handle_change)
password_label = toga.Label("Password:")
password = toga.PasswordInput(on_change=handle_change)
box = toga.Box(
    children=[toga.Box(
        children=[username_label, username],
    ),
    toga.Box(
        children=[password_label, password],
    )],
)
box.style.direction = "column"

return box

def main(): return toga.App("Password Example", "com.example.password", startup=build)

if name == "main": main().main_loop()


2. Click on the password field
3. Select a password via the Apple password manager
4. Observe that nothing is printed by the change handler.

### Expected behavior

~1. The password pop-up possibly shouldn't appear (but it can be dismissed easily by pressing escape, and if this is a MacOS behaviour there is nothing to be done).~ Edit: this behaviour seems to be controlled by the control panel settings for password autofill (see discussion), so not something Toga can control.
2. When the password is auto-filled, the `on_change` handler should fire.

### Screenshots

_No response_

### Environment

- Operating System: macOS Sonoma 14.5
- Python version: 3.12.4
- Software versions:
  - Toga: 0.4.5

Machine is a Mac Studio (Apple Silicon M1), Python was installed via MacPorts, toga via `pip` in a dedicated venv:

Package Version Editable project location


fonttools 4.53.1 pip 24.1 rubicon-objc 0.4.9 toga 0.4.5 toga-cocoa 0.4.5 toga-core 0.4.5 travertino 0.3.0


### Logs


### Additional context

When I have some spare cycles I will run against the main branch of the various projects to make sure this hasn't been fixed since the last release, but I couldn't see any issues which matched this.
freakboy3742 commented 4 months ago

Thanks for the report. Unfortunately, I can't reproduce what you're describing. I'm able to autofill a password; I get a notification that the value has changed when the full password is (automatically) entered, and then I get continued notifications if I type after that.

I don't get any automated display of the password autofill dialog though - I have to right-click, select autofill, then select a password. That may be because I don't use Apple's password autofill by default. Are you seeing some sort of automatic behavior on focus?

corranwebster commented 4 months ago

Thanks for the quick response.

Yes, I automatically get the "Password" popup that you see in the first screenshot when I focus on the PasswordInput widget.

Your guess is likely right: I have this setting in my control panel: image When I toggle this off I don't see the automated display of password autofill, and so don't see the issue.

And yes, when using autofill via the right-click menu everything works as expected.

Digging a bit further, this stackoverflow discussion seems relevant or related: https://stackoverflow.com/questions/46391814/how-to-detect-when-user-used-password-autofill-on-a-uitextfield

So this may well be an issue with the underlying Cocoa API.

Since on further investigation on_confirm and on_lose_focus seem to work correctly, I think I can work around this issue for my use-cases (eg. enabling a "login" button when the username and password are not empty: the button will just update when the user confirms or changes focus, rather than immediately upon autofilling the password; slightly worse UX, but still OK).

freakboy3742 commented 4 months ago

Thanks for confirming. It's not clear if this is a bug in macOS, or intentional behavior; but it seems possible that something like this approach from StackOverflow might form the basis for a fix.