GNOME Bugzilla – Bug 780785
Mouse pointer and regex underlining issues
Last modified: 2021-06-10 15:20:02 UTC
Mouse pointer and regex underlining suffer from quite a few issues. Furthermore, their code seems to be overly complex and (at least to me) not clearly documented -- match_hilite_{show,hide,clear,update} and just plain match_hilite, plus set_pointer_visible and a whole lot more, even despite the comments, it's unclear to me which one's supposed to do what. These bugs, as well as me not quite understanding the intent kinda prevents me from robustly implementing hover underlining of hyperlinks. Some bugs, probably not all: - Select with the mouse a part of a regex match. The entire regex stops being underlined. After you release the mouse button and move the pointer within the regex match, it's still not underlined. Leave and re-enter the regex match area, it becomes underlined. - Repeat the same, but after selecting some text, click again to remove the selection. Only the selected part becomes underlined (looks like an unintended display corruption, some regions not being invalidated). - In mouse tracking mode (echo -ne '\e[?1000h'), when the pointer is moved over a regex it remains the standard "mouse tracking mode" pointer, however when the contents change and hence a regex appears underneath the pointer, the pointer changes to a hand. - VteTerminalPrivate::widget_focus_out() calls match_hilite_hide() and sets m_mouse_cursor_visible to false. Why, what's the intent? When the focus is Alt-Tabbed away, the regex match indeed stops being underlined, but gets underlined again when the mouse leaves and then enters the regex's area (without the window getting focus). Not consistent. - Bug 762981. - Code smell: match_hilite() first possibly alters whether the match is underlined (based on previously cached value of regex match and stuff), and then at the end calls match_hilite_update() which re-checks if there's actually a regex underneath the pointer (updates this cache). This doesn't make sense to me in this order. I haven't studied all aspects of the code, but some of this issues (especially the "mouse tracking mode" one) are caused by this: Sometimes when things change, it's the set_pointer_visible() method that's called, which looks at things in a particular order (tracking mode, then regex, etc.) and sets the cursor [possibly calling out to set_cursor_from_regex_match()]. match_check_internal_pcre() however directly calls out to set_cursor_from_regex_match(), skipping the step done by set_pointer_visible() that mouse tracking mode might override the cursor. It should call set_pointer_visible() instead, but perhaps it cannot, since it doesn't know whether the pointer should actually be visible... Instead of this, the right design IMO would be to everyone just setting a variable that belongs to them. E.g. regex matching code sets a variable how the cursor should look like based on the regex. There's another variable whether mouse tracking is in effect. Another one whether auto-hiding the mouse has kicked in. Perhaps a few more. And then there should be a single mouse_pointer_apply() method that doesn't take any parameters, everyone is safe to call it any time (and should call it whenever any of the relevant variables changes), and it knows the precedence of these variables and chooses the actual look. (In the mean time I'm wondering why mouse tracking mode's cursor is supposed to beat regex match and not the other way around. Nevermind.) Probably the same should go for underlining as well, e.g. regex matcher providing one piece of data as input, focus in/out providing another, mouse dragging/selection providing another etc. and then one and only one method being responsible for actually deciding whether to underline or not and acting on it.
Created attachment 349128 [details] [review] Some cleanup This patch does some cleanup that I had in mind, and by the way fixes some of the bugs (the tracking mode cursor shape inconsistency, and the 762981. It also changes the intent at two places: regex match cursor now overrides mouse tracking mode cursor, plus by intent underlining and the cursor shape remains unchanged after a focus out (that was the actual behavior many times, but not always, and was not the documented intent). There's much more to clean up one day. Not now. This is just the bare minimum to unblock the hyperlink feature.
- set_pointer_visible(false); + m_mouse_cursor_autohidden = true; [or false] + apply_mouse_cursor(); This pattern occurs multiple times, so let's keep the ::set_pointer_visible() method and just have it do these 2 lines. WIth that changed, ok to commit. Thanks!
I'd still rename to ::set_pointer_autohidden() to better express what it actually does (i.e. that it does not necessarily immediately show or hide it). The parameter is inverted because I can't think of a good word for the variable name, e.g. "autoshown" sounds stupid to me. Or do you have a better idea? Is this okay?
Created attachment 349913 [details] [review] Some cleanup, v2 Updated as per the previous comments.
Comment on attachment 349913 [details] [review] Some cleanup, v2 Yes, fine :-)
Comment on attachment 349913 [details] [review] Some cleanup, v2 Committed. Leaving the bug open since some of the issues were not yet addressed.
-- GitLab Migration Automatic Message -- This bug has been migrated to GNOME's GitLab instance and has been closed from further activity. You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.gnome.org/GNOME/vte/-/issues/2387.