Make text selection more visible (bug 1879559)#20981
Make text selection more visible (bug 1879559)#20981wooorm wants to merge 16 commits intomozilla:masterfrom
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #20981 +/- ##
==========================================
+ Coverage 63.32% 63.86% +0.54%
==========================================
Files 177 177
Lines 124719 125704 +985
==========================================
+ Hits 78980 80284 +1304
+ Misses 45739 45420 -319
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
My idea was to create a specific filter for mapping the foreground color (usually black) on a color A and the background one (usually white) on a color B. pdf.js/src/display/filter_factory.js Line 188 in 777251d and then we can map the two colors on their system counterparts (Highlight and HighlightText): This way we've by default the same colors as the system has. |
|
@calixteman I think you mean something like this patch. This ignores the FF light:
FF with custom colors in
chrome:
Sadly, this does not work in Safari. It reports that the color filter is supported, but doesn’t, and no selection is thus visible |
|
Alright, another small patch, now using Importantly, though, is that Chrome and Safari do not use the user’s preferred theme colors for that. Probably for security, to prevent fingerprinting. Safari also has a bug where it does not support SVG filters in For that reason, I now gated this as a Firefox only thing. Other browsers get the normal CSS, which now uses a blue background, with some transparency. It may be possible to gate this entire approach for FF only. Or for non-Safari. I opted not to. I think it keeps the code simpler. |
|
@calixteman a) how can I reproduce your example (it seems different than what I am testing wtih) and b) what would the expected output be? |
On Windows, switch to HCM (High Contrast Mode: it's one of the a11y settings) and switch to Night Sky theme. |
|
@calixteman fascinatingly, it seems to be That made me think, what about the alpha? |
|
IRL, do you have some alpha ? or do you wonder ? |
|
Yes, I get alpha back from macOS. |
|
The problem with these colors in dark mode + graphite ( In light mode, the PDF.js pages match with what the system expects. |
|
@calixteman re starting a selection and dragging outside of the page, that did already work on Chrome but not Firefox and Safari. I pushed a fix to make it work there too. And, tests. |
|
The draw layer creation depends on having a annotationEditorUIManager: Line 1196 in 419c265 For protected documents, the UIManager isn't created. |
| let hasViewerRange = false; | ||
| for (let i = 0, ii = selection.rangeCount; i < ii; i++) { | ||
| if ( | ||
| this.viewer.contains(selection.getRangeAt(i).commonAncestorContainer) |
There was a problem hiding this comment.
contains can potentially walk all the DOM. If the selection is in the text layer then selection.getRangeAt(i).commonAncestorContainer then is the text layer div so maybe we could have a fast path here. Generally, using closest should be faster.
There was a problem hiding this comment.
simplified the code!
| if (this._pagesRotation === rotation) { | ||
| return; // The rotation didn't change. | ||
| } | ||
| this.clearSelection(); |
There was a problem hiding this comment.
Can't we keep the selection ?
If not, it would be a "regression" (quoted because it's likely not a big deal).
There was a problem hiding this comment.
I tried some things but it’s not easy. Though I don’t have the entire project in my head.
I think it means capturing all the selected text nodes (node index, textContent index * start, end), and then selecting all text nodes after draw and restoring.
Which sounds possible, renaming clearSelection to captureSelection / applySelection.
But I think it’s acceptable that a selection is lost when a user does something that like, changes the PDF (rotate) or goes somewhere different (another page).
| return; | ||
| } | ||
| this.drawLayer ||= new DrawLayerBuilder(); | ||
| this.drawLayer ||= new DrawLayerBuilder({ |
There was a problem hiding this comment.
As said, previously it should be created whatever we've annotationEditorUIManager.
There was a problem hiding this comment.
Sorry i don’t quite understand, i think you mean b020c5e right?
I forced that branch and the new selection then still worked
| return [...rgb, 1]; | ||
| } | ||
|
|
||
| const alpha = MathClamp( |
There was a problem hiding this comment.
You can create a new function getRGBA similar to getRGB.
I mean add it in display_utils and avoid to call getRGB if we have "rgba(".
| // Track mouse selection state to preserve selections during | ||
| // cross-boundary drags. | ||
| document.addEventListener( | ||
| "mousedown", |
There was a problem hiding this comment.
Can't we use pointer instead of mouse ?
There was a problem hiding this comment.
yeah, done; I think that should work
| } | ||
| for (const textLayer of this.#textLayerSet) { | ||
| if (!selectedTextLayers.has(textLayer)) { | ||
| this.#cleanupTextLayerSelection(textLayer); |
There was a problem hiding this comment.
On every selection change within the same text layer, we clean the selection div when we could just update the path in the svg element and it'd avoid needless DOM churn, right ? or am I missing something ?
There was a problem hiding this comment.
Hmm you mean, you are seeing this in the devtools right?
2 lines before your comment there’s a let i = 1. I don’t know why that was there.
I think the current layer (0) should be a selectedTextLayers, and not cleaned up. That also works. So I pushed that.
(If you mean even less cleaning up, say by setting d on path to something empty or so: possible too, but then you end up with more DOM nodes I guess)













References https://bugzilla.mozilla.org/show_bug.cgi?id=1879559 (“In HCM, the text selection is barely visible”).
Continues work from @calixteman who had a partial patch.
This PR improves viewer text-selection highlighting by rendering selection shapes in the draw layer.
My main question is: how should it appear?
I don’t have access to the Figma file linked on bugzilla.
In the CSS (
draw_layer-builder.css) there are 3 blocks:@supportsfor browsers supportingbackdrop-filter:forced-colorsmode:So it’s possible to design for those (or more).
Personally, the
backdrop-filter: invert(1)is the most contrast, so perhaps it’s better to use something else as the default, and to useinvert(1)if high contrast mode is used (maybe with aprefers-contrastmedia query instead)?