talonvoice / talon

Issue Tracker for the main Talon app
85 stars 0 forks source link

Mark clipboard entries as transient #478

Open pokey opened 2 years ago

pokey commented 2 years ago

Knausj / Talon use the clipboard for transient operations such as getting selected text. It would be great if there were a way for Talon to mark such clipboard items as transient so that they are ignored by clipboard managers. The clipboard manager that I use respects org.nspasteboard.AutoGeneratedType, so it would be amazing if Talon used that one. See also http://nspasteboard.org/

AndreasArvidsson commented 2 years ago

I would also like to add the reverse user case. My password manager has updated the clipboard and my clipboard manager in talon need to detect this so I can ignore it.

lunixbochs commented 6 months ago

in talon-rust you can likely use MimeData.set_raw() to add a org.nspasteboard.AutoGeneratedType type to the clipboard. Let me know if you get a chance to test it.

pokey commented 6 months ago

Guessing I'm doing something wrong here. Here was my attempt:

mime = clip.MimeData()
mime.text = text
mime.set_raw("org.nspasteboard.AutoGeneratedType", b"true")
clip.set_mime(mime)

But I got

2024-01-03 15:48:37.455 ERROR     5:    talon/scripting/talon_script.py:606| 
    4:    talon/scripting/talon_script.py:308| 
    3:         talon/scripting/actions.py:88 | 
    2: user/pokey_talon/core/edit/edit.py:42 | mime.set_raw("org.nspasteboard.AutoGeneratedType", b"true")
    1:                                         ^^^^^^^^^^^^
AttributeError: 'builtins.PyMimeData' object has no attribute 'set_raw'
pokey commented 2 months ago

Just wanted to follow up on this one; any idea what's going wrong with my code above? It looks like it should work according to the Talon Python stubs but I'm probably doing something wrong here

pokey commented 2 months ago

Did some quick research on Windows. Here are a few links in case helpful:

AndreasArvidsson commented 1 month ago

Tested and is working. Note that the syntax is not the same as the example from Pokey.

mime = clip.MimeData()
mime.text = text
mime["ExcludeClipboardContentFromMonitorProcessing"] = b"true"
clip.set_mime(mime)

https://github.com/AndreasArvidsson/andreas-talon/blob/43d4fa863a8564a4f19276801fdba837b2b0a313/core/edit/edit.py#L154-L159

lunixbochs commented 4 weeks ago

so this is working on both mac and windows now?

AndreasArvidsson commented 4 weeks ago

I can only verify on windows. @pokey do you mind testing on mac?

pokey commented 4 weeks ago

yep working for me on mac! I made this action to test it:


@mod.action_class
class Actions:
    def clip_set_text_transient(text: str):
        """Sets the clipboard text transiently"""
        mime = clip.MimeData()
        mime.text = text
        mime["org.nspasteboard.AutoGeneratedType"] = b"true"
        mime["org.nspasteboard.TransientType"] = b"true"
        mime["ExcludeClipboardContentFromMonitorProcessing"] = b"true"
        clip.set_mime(mime)

Note that clip.revert() doesn't set any of these flags, though, so I still end up with duplicated clipboard entries when I use this with paste:

@mod.action_class
class Actions:
    def paste(text: str):
        """Pastes text and preserves clipboard"""

        with clip.revert():
            actions.user.clip_set_text_transient(text)
            actions.edit.paste()
            # sleep here so that clip.revert doesn't revert the clipboard too soon
            actions.sleep("150ms")
AndreasArvidsson commented 3 weeks ago

clip.revert() not having that mime is unfortunate, but in my clipboard manager I already handle the use case where the clipboard changes to the same thing again. A much larger problem is how we do user.selected_text()

def selected_text() -> str:
        with clip.capture() as s:
            actions.edit.copy()
        try:
            return s.text()
        except clip.NoChange:
            return ""

That copy is never going to set a custom mime type since it's just pressing ctrl-c / cmd-c