chatterino2
chatterino2 copied to clipboard
Double/triple click selection of long words does not select all characters
Checklist
- [X] I'm reporting a problem with Chatterino
- [X] I've verified that I'm running the most recent nightly build or stable release
- [X] I've looked for my problem on the wiki
- [X] I've searched the issues and pull requests for similar looking reports
Describe your issue
When double clicking on a long word in a message, the selection does not span the entire word. This is also exhibited by triple clicking the message.
Example message:
@user-type=;color=#FF0000;emotes=;turbo=0;returning-chatter=0;client-nonce=2513080064f6a1335c3c4b460849e7ac;badges=glhf-pledge/1;user-id=130496419;id=e96f7752-d2d6-45c1-b23f-dd7a6173d535;rm-received-ts=1699732253387;flags=;tmi-sent-ts=1699732253150;first-msg=0;room-id=46673989;subscriber=0;mod=0;display-name=jendrina22;badge-info= :[email protected] PRIVMSG #masayoshi widepepohappycliminghardo4housewithcomodohypeontopholdingapepegadragonpoganonactionfigure
Screenshots
Double click selection:
Expected text selection: widepepohappycliminghardo4housewithcomodohypeontopholdingapepegadragonpoganonactionfigure
Actual text selection: widepepohappycliminghardo4housewithcomodohypeontopholdingapepega
The following videos demonstrate double clicking then triple clicking behaviour.
https://github-production-user-asset-6210df.s3.amazonaws.com/4962764/282263471-071856fe-1130-4830-afb8-d00ac0a31601.mp4
https://github-production-user-asset-6210df.s3.amazonaws.com/4962764/282263462-7317551e-2b3e-4137-b585-6c2454463409.mp4
OS and Chatterino Version
Chatterino 2.4.6 (commit 95620e6e1) built with Qt 6.6.0 Running on Arch Linux, kernel: 6.6.1-zen1-1-zen
double-click selection ends selection on the line's end rather than word end, i tested c2 2.4.4 and it behaves the same so likely it never worked as expected.
But your videos shows more problems:
- your double-click selection doesn't match whole row and skips last 2-3 characters, while also selecting beginning of next row (vid 2), seems like some width calculation is wrong (issue not present on windows)
- triple-click selection also matches username, but shouldn't (#4961)
Biggest problem I see here is that, because of the way line breaks are done, I don't think there is a (good) way to know the difference between these
Any ideas on how to fix this issue without completely remaking the line break logic?
Any ideas on how to fix this issue without completely remaking the line break logic?
When adding a TextLayoutElement
with line breaks, this element can have flags set (on the MessageLayoutElement
) that indicate, which direction the text continues (if any).
The following would be done when calling (a new) MessageLayout::getWordBounds(pos = clickedPos)
:
# this is pseudocode
startIndex, startElement = getElementAt(pos)
endElement = startElement
endIndex = startIndex + endElement.getSelectionIndexCount()
while startElement.hasPrev:
startElement = elementBefore(startElement)
startIndex -= startElement.getSelectionIndexCount()
while endElement.hasNext:
endElement = elementAfter(endElement)
endIndex += endElement.getSelectionIndexCount()
if endElement.hasTrailingSpace():
endIndex -= 1
return startIndex, endIndex
I think this could extend MessageLayoutContainer::getSelectionIndex
.
In ChannelView
, we wouldn't call the anonymous getWordBounds
, but the one from MessageLayoutElement
.
This can get quite fun with off-by-one errors.
Example: Say you have the message "b³ a⁴² b³", which could get broken up like this:
bbb
aaaaaaaaaa
aaaaaaaaaa
aaaaaaaaaa
aaaaaaaaaa
aa bbb
This would result in the following layout elements:
[0]: "bbb" [trailingSpace]
[1]: "aaaaaaaaaa" [hasNext]
[2]: "aaaaaaaaaa" [hasNext, hasPrev]
[3]: "aaaaaaaaaa" [hasNext, hasPrev]
[4]: "aaaaaaaaaa" [hasNext, hasPrev]
[5]: "aa" [hasPrev, trailingSpace]
[6]: "bbb" [trailingSpace]
Suppose the user double-clicks on element 2.
-
getElementAt
would get the element 2 and its starting index, so $\verb|startIndex| = 3 + 1 + 10 = 14$. -
endIndex
would be $14 + 10 = 24$. - The first
while
loop would look at the following elements:-
[1]
: $\verb|startIndex| = 14 - 10 = 4$
-
- The second
while
loop would look at the following elements:-
[3]
: $\verb|endIndex| = 24 + 10 = 34$ -
[4]
: $\verb|endIndex| = 34 + 10 = 44$ -
[5]
: $\verb|endIndex| = 44 + 3 = 47$
-
- The element has a trailing space, so $\verb|endIndex| = 47 - 1 = 46$
Now, $46 - 4 = 42$ characters are selected.
Good idea. I looked into it a bit more yesterday and quickly hacked together a way to get the length of the original word and just return that as the selection length, which surprisingly works a lot of the times but would break in the example you gave (the selection would only go forward from the line).