Ticket UUID: | e94c8bc845b4d5a658cd5421ef23ef2484560fa8 | |||
Title: | X11 clipboard clear command has no effect when xclipboard is running | |||
Type: | Bug | Version: | 9.0.1 | |
Submitter: | anonymous | Created on: | 2025-05-23 23:18:51 | |
Subsystem: | 52. [clipboard] | Assigned To: | nobody | |
Priority: | 5 Medium | Severity: | Minor | |
Status: | Open | Last Modified: | 2025-06-10 17:10:05 | |
Resolution: | None | Closed By: | nobody | |
Closed on: | ||||
Description: |
The Tk clipboard commands seem to update the clipboard in some way that is invisible to clipboard managers on Mac OS. To be more precise, the first time Tk sets the clipboard, clipboard managers notice it, but all subsequent times, they don't. (See below for reproduction) I do not think this is a bug in the clipboard managers, since I can see this behavior with not just my clipboard manager (Maccy), but also a more low-level program designed for debugging clipboard issues (Pasteboard Viewer, see the "simpler reproduction" below). I originally experienced this bug with I tested this with tk 9.0.1 and tk 8.6.16, both installed via Homebrew, as well as tk 8.6.15 installed from nixpkgs. I'm using MacOS Sonoma 14.7.6 on ARM. I am not a macOS expert, I just use it :). The author of Maccy is; perhaps he will reply if you comment on https://github.com/p0deje/Maccy/issues/1100. ReproductionI'm assuming that you have Homebrew installed (though you can also reproduce this with Nix, or likely see the same thing if you adapt the steps to some other setup). After reproducing, it might help to see how Maccy and/or Pasteboard viewer interact with a normal Mac app by e.g. right-clicking on various links in Firefox and selecting "Copy link to clipboard", and observing Maccy or Pasteboard viewer. Original reproduction with Maccy and
| |||
User Comments: |
marc_culler (claiming to be Marc Culler) added on 2025-06-10 17:10:05:
I have removed the fancy clipboard transient command and merged just the fix for this bug into the main branch. The fix makes it so that Pasteboard Viewer sees all changes to the Tk clipboard. However, in the course of this project a different bug, similar in nature but affecting linux, was observed. Specifically, when the xclipboard app is running, the Tk clipboard clear command has no effect. The xclipboard app is the X11 equivalent of Pasteboard Viewer.app. So I have changed the name of this ticket, assigned it to nobody, and will leave it open. marc_culler (claiming to be Marc Culler) added on 2025-06-07 04:00:46: I have now completely redesigned this change. The clipboard flush command is gone. The clipboard append and clipboard get commands always (with one exceeption explaned below) cause an increment of the changeCount, which means that the change is noticed by Pasteboard Viewer. There is a new command: clipboard transient ?-displayof window? data The effect of the this command is to change the state of the pasteboard in a way which makes the next call to clipboard append behave differently. Namely: * The changeCount is not incremented, so Pasteboard Viewer is not aware of the append. * The text provided as data is available in the Apple pasteboard, so it will be pasted on the next Cmd v operation. * The text can only be pasted once. After the paste, the clipboard is cleared. This should allow pasting a password into another app without having the password beome visible to any clipboard manager which is polling the changeCount property to detect clipboard activity. Code that only uses get, clear and append should behave as before, except that the appends will be visible to clipboard managers. The clipboard transient command is a no-op on other platforms. Finally, the branch has been renamed as clipboard_transient. @ilyagr: Can you please test the clipboard_transient branch? Thanks. marc_culler (claiming to be Marc Culler) added on 2025-06-05 19:46:02: @ilyagr: Thank you for testing! I am coming around to your point of view on this. I now agree that the default behavior should be to make the clipboard copies viewable by a clipboard manager. One major advantage of this is that making that change, without changing the API, turns this project into a bugfix - not a change requiring a TIP. I am still concerned about how to make it possible to keep things like passwords away from clipboard managers. (OK. I admit that I am working on a Tk-based password manager.) But accommodating that situation should not be part of the default behavior. One fact which supports that last statement is that when the NSApp becomes the owner of a NSPasteboard type, the name of the type is public.utf8-plain-text. Public data should be public. I have some ideas for how to deal with private data, but I intend to make the default behavior become the one which makes all clipboard copies available to a a clipboard manager which is watching the changeCount. Stay tuned ... ilyagr added on 2025-06-05 00:40:09: The other question that's unclear to me is whether there's any downsides to doing As a quick test,
works as expected. (As I said previously, This is a bit of a fraught decision, since I don't know how to prove that no Tk program relies on the old behavior. It's hard for me to imagine why they would intend it, and I imagine most would benefit from this change. Still, programs could rely on the old behavior in some way or for some reason I haven't imagined. ilyagr added on 2025-06-04 21:35:02: Thank you! I did manage to compile your branch (following the instructions for building I found one minor bug: if you run Re your long postThe post is mostly great, but there is one point that seems slightly off. (Unfortunately, I guess there is no way to edit comments?)
In my experience, only the first append after the first clear command is visible to Pasteboard Viewer/Maccy. If this quote were correct, and the first Again, what actually happens is that only the first Aside on how other tools seem to workI also played with Firefox a bit more. I opened
The clipboard manager picked up both changes immediately. I have no idea whether Firefox is doing the same thing you are suggesting, or something else. marc_culler (claiming to be Marc Culler) added on 2025-05-31 22:25:30: I have implemented my proposed extension of the clipboard command which adds a new action "flush". It works as I proposed, and I think it would allow gitk to work as you would like. Testing with the Pasteboard Viewer I see that the first append to a cleared clipboard is shown on the Pasteboard Viewer. A second append is not shown in the Viewer although the appended text does appear when I do a paste. If I call `clipboard flush` then the Pasteboard Viewer updates to show the appended text. Since this would be a change to the Tk API, a TIP would be required. But the first question would be whether it works. @ilyagr: The changes are in the clipboard_flush branch of the Tk fossil repository. Would you be able to clone, build and install that branch and check whether the `clipboard flush` command works for you with gitk? marc_culler (claiming to be Marc Culler) added on 2025-05-31 15:41:21: The purpose of this post is to record how the Tk clipboard currently works on macOS, and suggest a possible extension. Here are the main points about the current implementation: * Apple declares a protocol named NSPasteboardTypeOwner. In order to support this protocol an object must implement the method - pasteboard: provideDataForTyype: The protocal also includes a callback method - pasteboardChangedOwner: which will be called on the current owner of a pasteboard type when a new Object becomes the owner. * The TKApplication subclass of NSApplication supports the NSPAsteboardTypeOwner protocol but does not implement the callback method. The only type that it supports is the String type. * The TKApplication instance behaves as follows: + It maintains a string which is cleared by `clipboard clear`, appended to by `clipboard append` and returned by `clipboard get`. + If Tk's string is empty, and `clipboard append` is called, the TKApplication registers itself as the owner of the String Type for the general NSPasteboard. + The TKApplication's implementation of -pasteboard: provideDataForType just provides a copy of its saved string. A consequence of this design is that only an append to an empty string will change the owner of the String type for the general Pasteboard. Therfore, only an append to an empty saved string will change the value of the changeCount attribute of the general NSPasteBoard. To avoid unnecessary copies of the clipboard content, a typical clipboard manager evidently uses the changeCount value to determine whether the value of the general NSPAsteboard string Type has changed, even though that is not what the changeCount means - it means that the owner has changed, not that the value has changed. So appends to the Tk clipboard, except for the first append after a clear command, will not be visible to a clipboard manager which uses this strategy. It is possible (actually, likely) that Apple is not telling the whole truth about the meaning of changeCount. Possibly when the owner is nil and the value of the String Type is changed, but the owner remains nil, the changeCount gets incremented. An experiment would be needed to see if that is the case since it is not covered in the documentation (as usual). If so, it muddles the meaning of changeCount, but makes it closer to having the meaning assumed by the clipboard managers, but only in the case where the owner of the String type is always nil. I now think that the motivation for the Tk design was simply to match the Apple clipboard protocol to the Tk protocol in a clean way. I doubt that privacy was a consideration then. I do think it is a consideration now, although I don't really think that any accidental privacy benefits of the current design are very effective. Here is an idea for how to address this issue in Tk. Perhaps the Tk clipboard command could be extended by adding a new action: `clipboard flush`. On macOS the implementation of `clipboard flush` would be that the TKApplication would resign ownership of the general NSPasteboard String Type by assigning a nil owner and (as is required) immediately sending the entire saved string to the general NSPasteboard. The saved string would not change, but the ownership status would be recorded in a state variable. Essentially, non-ownership status would replace the prior meaning of having an empty saved string. So a subsequent append to the Tk clipboard would result in Tk taking ownership of the String Type until the next clear or flush. This would also involve implementing the callback method, which would be used to maintain the ownership state variable. Quite possibly other platforms would not have any meaningful way of implementing the flush action. So I guess it could just be a no-op on other platforms. ilyagr added on 2025-05-30 21:50:40:
Specifically, The latter mode is inconvenient without a clipboard manager (or while Also, when talking about several commits, it's convenient to use the command to copy a commit's description several times in a row (on several commits), without switching to any other window. Then, you can (say) switch to the window where you are writing an email and paste all of these descriptions as you are writing about them, one after another. There is probably some room for marc_culler (claiming to be Marc Culler) added on 2025-05-30 21:25:36: Can you please explain why gitk needs to interact with a clipboard manager? I.e. why it is not sufficient for gitk to write to the clipboard so a user can then paste the clipboard into a different application? ilyagr added on 2025-05-30 20:49:23: Aside regarding password managers: You may know this already, but there are features to prevent clipboard managers from capturing passwords, but they are imperfect. For example, Bitwarden'd macOS desktop client supports this feature, but the browser extension currently does not. I'm not sure whether something similar exists on Windows/Linux; I think something does exist, but it's a different API. I, personally, don't find it a huge hassle to manually remove the passwords from the clipboard manager's history, but it's certainly something to be aware of. ilyagr added on 2025-05-30 20:41:21: Thank you again for looking into it! Again, I'm not an expert, but you diagnosis seems reasonable to me. I can't judge why Tk behaves the way it does, and I'm not sure about the best course of action. Two naive thoughts:
I'm not sure whether there are other reasons for lazy copying or what other changes in behavior that would occur if copying became strict. My first guess would be that strict vs lazy copying would mainly make a difference when copying large amount of data into the clipboard. I did not test how marc_culler added on 2025-05-29 22:44:13: I notice that, anticipating the conclusion of my post, I accidentally referred to "password manager" when I meant to say "clipboard manager": I meant: "it makes sense that a clipboard manager which is watching the changeCount of the NSPasteboard will not be aware that anything has changed." marc_culler (claiming to be Marc Culler) added on 2025-05-29 22:36:16: I may have found some clues about this. The internet says that there is no way to get notification when an item is added to the general NSPasteBoard. The only way to handle this seems to be to poll the pasteboard at some time interval to see whether the value of its changeCount has changed. I will assume that this is what your clipboard managers do. Moreover, the internet suggests that not providing a notification was an intentional decision on Apple's part. The Apple documentation says "The change count subsequently increments each time the pasteboard ownership changes." That does not mean that the changeCount will be incremented if the string value of the first item on the pasteBoard changes. Especially given that it is allowed for the string value of an item on the pasteBoard to be provided lazily. And it appears that is what Tk is doing. The function TkSelUpdateClipboard does this:
The TKApplication subclass of NSApplication has a method tkProvidePasteboard which appears to be the function that the NSPasteBoard calls when it needs to know the value of a string item which Tk has placed on the pasteboard. In your example, I am guessing, the first call to "clipboard append" makes Tk's NSApplication object become the owner of the clipboard. The second append changes the value of the first item on the clipboard, which is only known to Tk since it is being provided lazily, and does not change the owner of the clipboard, which remains set to Tk's TKApplicaton. if the ownership does not change and the actual string value is not known to the NSPasteBoard then it makes sense that a password manager which is watching the changeCount of the NSPasteboard will not be aware that anything has changed. The owner is allowed to be nil. According to Apple, when the owner is nil the the value of the first item on the NSPasteBoard must be provided immediately. Here is an example from the Chrome browser, which uses the general NSPasteBoard that way:
The call to the addTypes method, with nil owner, is immediately followed by a call to the setString method. It seems likely that changing from providing the string value lazily to providing it immediately would "fix" the behavior being reported in this ticket. However, that is not a trivial change, and it may be unwise to "fix" it. Experience suggests that Tk design decisions, like whether to provide clipboard string values lazily, were usually made for a reason. Changing a basic part of the design almost always breaks things. Experience also suggests that it will be difficult to predict in advance which things will break. After that is finally known, the question remains whether the broken things were more important than making sure that a random clipboard manager is notified whenever Tk puts anything on its clipboard. I know of one particular context where not notifying other apps that the clipboard has changed is a very important positive feature. That is for a Tk based password manager. Many password managers allow copying the password to the clipboard so that the user can then paste it into a web browser. That operation is a lot safer if it is not possible for some other app that happens to be running on the same computer to record everything which gets placed on the clipboard. I think it is quite likely that this sort of privacy issue was what was behind the choice to provide values for clipboard strings lazily. Perhaps changing terminology from "clipboard manager" to "clipboard snooper" would help to view this issue from a better perspective. ilyagr added on 2025-05-29 22:28:31: Thank you! As I mentioned before, the minimal C example from https://nathancraddock.com/blog/writing-to-the-clipboard-the-hard-way/ and https://github.com/natecraddock/sandbox/tree/main/objc seem to work fine too. However, they set the clipboard, they don't do marc_culler (claiming to be Marc Culler) added on 2025-05-29 11:42:01: Well, maybe there is something Tk should be doing to notify other apps about a write to the clipboard. I didn't think so, since there would seem to be no way for Tk to know who the listeners are. I will look at the code for these clipboard managers and see if I can figure out how they are getting notified. ilyagr (claiming to be original poster, made an account) added on 2025-05-29 06:05:09: The pasting is not the problem, the correct info is getting pasted either way. The difference is in when or whether a clipboard manager (or Pasteboard viewer) detect that the clipboard changed. When I copy from Firefox or when I use So, I can't be 100% sure that Pasteboard Viewer or Maccy (the clipboard manager) are bug-free, but I'm 100% sure that Unfortunately, this does also mean that I don't know a good way to detect the problem without these tools, since I don't understand what the difference is. marc_culler (claiming to be Marc Culler) added on 2025-05-28 13:20:00: I repeated my experiment, but pasting into TextEdit to see what was in the clipboard. Again, it seemed to behave as expected. marc_culler (claiming to be Marc Culler) added on 2025-05-28 13:06:16: It seems like the first question would be whether this is a bug in Tk or a bug in Pasteboard Viewer (or a bug in Apple's clipboard management). Your statement: > (You *can* get the Pasteboard Viewer to update by interacting with it > and e.g. switching between the hex view and the text view. strongly suggests that it is not Tk that is misbehaving, although the claim that you see the failures with non-Tk mac apps suggests otherwise. I tried running your clipboard command commands in wish and pasting into a different Terminal window, Terminal being a non-Tk app. After appending aa I pasted in the other Terminal window and got aa. After appending bb I got aabb in the other window. After the get, clean and append cc I got aabbcc. So it is not clear to me how to reliably reproduce the problem, which would be needed in order to degug it. It would be great if you could provide a self-contained script so that we could focus on debugging Tk, rather than wondering whether we are actually seeing bugs in various clipboard managers that are being used for testing. anonymous added on 2025-05-24 23:43:15: A workaround is to use anonymous added on 2025-05-24 02:46:17: For reference, I found a seemingly very nice and minimal implementation of copying to clipboard on a Mac in C or objective C here: https://nathancraddock.com/blog/writing-to-the-clipboard-the-hard-way/#fnref3 https://github.com/natecraddock/sandbox/tree/main/objc This implementation seems to work fine with Maccy or Pasteboard Viewer. To test it, I just followed the first set of instructions in the README (which use lua). Its one downside is that this example implements a "clipboard set" function, while Tk seems to need an "clipboard append" function. |
