chatterino2 icon indicating copy to clipboard operation
chatterino2 copied to clipboard

Double/triple click selection of long words does not select all characters

Open jupjohn opened this issue 1 year ago • 1 comments

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:

image

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

jupjohn avatar Nov 11 '23 20:11 jupjohn

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)

kornes avatar Nov 12 '23 12:11 kornes

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

image

Any ideas on how to fix this issue without completely remaking the line break logic?

KleberPF avatar Mar 06 '24 00:03 KleberPF

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.

Nerixyz avatar Mar 06 '24 19:03 Nerixyz

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).

KleberPF avatar Mar 07 '24 01:03 KleberPF