-
Notifications
You must be signed in to change notification settings - Fork 17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Be careful with text from the Text
interface.
#161
Comments
A more clear example goes as follows:
|
You can use the Yes, this applies even when they are not strictly a hyperlink; I didn't name the interface. If you put a table inside of a paragraph on a web page, this is the same mechanism that it will use to substitute within the text. Test page (a paragraph starting with "Para", a table with "hi" and "bye" as its only cells, then "graph"; finally, the paragraph tag closes): <p>Para <table style="display:inline;"><td>Hi</td><td>Bye</td></table> graph</p> Results in this text being returned from AT-SPI:
This is not something that is clear through the API, and should at least be indicated by documentation, but ideally by a String-like newtype. |
cc @luukvanderduim any thoughts on this? |
Mainly questions, because I am still a bit confused.
D-Bus is specific on what is considered a 'string-like': I don't think So I assume the unread codepoints are UTF-8 but not vocalizable? Then there is a higher level questions. Is it html found in the address bar or is that just your example? Does the address bar object expose Do Odilia users require conversion from non-vocalizable UTF-8 to something that is vocalizable? |
Yes. The codepoints are multiple instances of the object replacement character.
Not sure what you mean by this question, but both the example with the table and the address bar example (given by @albertotirla) contain "inline children"; the object replacement character is to denote where the children are in the text. This means they (or at least their children) implement the Hyperlink interface (regardless if it's HTML or not).
This ignores the table example, where although the hyperlink interface is available, GetUrl will not return any useful information. It's a poor abstraction but the only one we have of finding out the location of children within the widgets.
Yes. You can not vocalize these codepoints directly. At minimum, we'd have to use a descriptive table of these symbols so they can be pronounced by Speech Dispatcher. There may be a function to do this in speech dispatcher, not sure yet. |
and now we find out why screenreaders use virtual buffers, especially when it comes to web pages and even more so as regards when the apps are normal browser pages and require browse mode. Perhaps we should do the same, updating that buffer as we recieve more information? as to the atspi crate, I don't think we should newtype String just for this, because the text interface still returns normal text most of the time, in edit boxes, in the terminal, etc. A better idea would be to create a type specifically for this purpose, which you construct by giving it ownership of the accessible proxy you're working with, and which then gives you an iterator (or stream) with the Item type something like this, note that the code does not compile: enum InlineObjectKind <'a>{
Text(&'a str),
Hyperlink(AccessibleProxy<'a>,
Other(AtspiRole, AccessibleProxy<'a>,
} and then we, on the odilia side, could build a virtual buffer abstraction which iterates through this, going to the next item every time one presses down arrow, or invokes the next item command when we'll have those abstractions open to input handlers. What do you think? |
Can you expand on what you mean by virtual buffers? |
basically, a virtual buffer is a screenreader specific construct in memory which can present slightly altered views of what the accessibility tree shows. For example, as far as I know orca doesn't have one, so that's why it can only show widgets inline, which makes a huge amount of things be able to fit in one line, but unfortunately that's confusing in almost all cases. Instead, we can use the screenreader's knowledge of how the user wants things shown to build an in-memory representation of it, for example splitting the string by object replacement characters and making an iterator as I said, and then we can make an abstraction that, inside webviews, only moves by one element when you press the down arrow, the d-pad on a controller or whatever. So, if you have a paragraph containing text, then an object replacement character, then a button or link, orca would read this in one big line as it's shown on the page, doing noncomplicated text replacement essentially. We, however, could make it so that we split that into three, first comes the text before the object replacement character, then the control which you can click on, then the text after the character, each being accessible by the user pressing the down arrow |
I understand it a bit better now. Thanks!
The object replacement character is valid UTF-8, so it is a valid Rust string. Otherwise it could not have been constructed.
Is the 'object replacement character' (ORC) the only character we know of that imposes a 'contract'? So if Odilia encounters a Text object, this may be a structured Text, like a tree. First find out the exact rules, then find a structure to fit the rule? The above assumptions are worth nothing if wrong. |
from what I know, only in webview elements, be that in the browser or otherwise, this is relevant. I believe that adding such a type with the logic I mentioned above directly to atspi is beneficial because other assistive technologies may want to treat embedded links and such the way we do, as separate from the text they're in. So, this is how this would work in practice:
So then, one can either do this all at once, doing the replacement and so on for everything and then returning a vector, or lazily consuming the content via an iterator, producing items when it encounters the object replacement character, doing a split and making of that two items, the before and the object itself |
It can be its own crate once we have a nice little module of code, but I don't even know which current atspi module would event apply.
Yes. Confirmed by asking Matthias Clasen. Although it should probably be spec'ed somewhere.
True!
Not sure if its relevant. The point is it exists; it shouldn't matter where it is. |
Text returned from the
org.a11y.atspi.Text
interface is not just a String as per Rust rules.It contains additional contracts like that of how the object replacement character should be interpreted and how to interpret it.
These contracts should be reflected in the API, even if that means using a newtype. Technically, most of the usefulness of this is for screen readers (AT-SPI consumers), and is not directly related to any work done for providers, but it will change the public API for using the interfaces from the
atspi-proxies
crate (both sending and receiving).The text was updated successfully, but these errors were encountered: