Tk Source Code

View Ticket
Login
Ticket UUID: af31a84c9115fc9911f733c44125d3cd4b3a1f35
Title: Replacing selection handler is ineffective.
Type: Bug Version: 8.6.13
Submitter: sbron Created on: 2023-12-13 10:46:49
Subsystem: 53. [selection] Assigned To: sbron
Priority: 5 Medium Severity: Severe
Status: Open Last Modified: 2024-07-09 21:03:41
Resolution: None Closed By: nobody
    Closed on:
Description:

When an existing selection handler for a window is replaced by a different command, the original command is still invoked when an external program obtains the selection. It only works correctly when the original handler is removed before setting the new one.

The attached selection.tcl script shows the problem. Tcl/Tk will internally find the replaced command. But when pasting externally using the middle mouse button, it still reports "Using selproc version 1" instead of "Using selproc version 2".

User Comments: fvogel added on 2024-07-09 21:03:41:

See also [2443069fff].


sbron added on 2023-12-20 14:19:10:

I suppose you could call it a memory leak, although you could reclaim the lost memory by invoking Tk_DeleteSelHandler() enough times.

As mentioned, my proposed fix was based on the assumption that setting, updating, or clearing a STRING handler would do the same for UTF8_STRING. I don't think it's worth the effort to be extremely clever about it. That would probably just confuse users.


fvogel added on 2023-12-19 21:35:07:

...install a new handler every time, without deleting any existing one

Isn't this a memory leak? Maybe I don't understand what you mean.

I have added more tests checking the behavior you have described on the tcl-core list. Test select-14.2.2 currently fails, because the current implementation always replaces a potentially existing handle for the UTF8-STRING target. We have to decide which one between the test and the implementation is correct.


sbron added on 2023-12-18 09:49:40:

If my interpretation of the code is correct, the change you proposed will install a new handler every time, without deleting any existing one. It will also still effectively replace any UTF8_STRING handler the user may have installed when a STRING handler is installed or updated.

If we accept that behavior, and we agree that the size for UTF8_STRING should always be 8 instead of 32, Tk_CreateSelHandler() can be simplified while fixing the problem at the same time. The function is basically doing the same thing twice: Once for the requested target, then again for UTF8_STRING if the requested target was STRING. That second part could simply be done by invoking itself once more.

I created checkin [793effdb8e] with the change described above.


fvogel added on 2023-12-16 14:20:23:

The fix proposal I made in the discussion below at least lets the new test select-14.2 (added in [10121ce3]) pass whereas it failed previously. Moreoved no test from select.test test newly fails.


fvogel added on 2023-12-16 14:13:16:

Discussed on the tcl-core mailing list.


sbron added on 2023-12-13 11:04:32:

The implementation of the selection handle command invokes Tk_CreateSelHandler() to do the actual work. The manual page for Tk_CreateSelHandler() claims: "If Tk_CreateSelHandler is called when there already exists a handler for selection and target on tkwin, then the existing handler is replaced with a new one."

Closer examination of this function shows that in case of the STRING format, it actually installs a handler for both STRING and UTF8_STRING. When the handler is changed, the clientData, pointing to the Tcl command, for STRING is updated. But for the UTF8_STRING case the code just breaks out of the loop, without making any changes!

This means that the STRING handler is updated, explaining why Tcl/Tk finds the new command. But an external command presumably prefers to use the UTF8_STRING version, if available. And that will still invoke the original command.


Attachments: