A fast, zbus-based, permissively licensed AT-SPI library written in pure Rust!

Overview

AT-SPI for Rust

crates.io badge docs.rs badge

Higher level, asynchronous Rust bindings to AT-SPI2, using zbus.

Part of the Odilia screen reader project.

Design

  • Fully documented, with #[deny(missing_docs)]
    • Or at least, it will be by 1.0
  • Fully safe, with #[deny(unsafe_code)]
  • Fantastic code style with #[deny(clippy:all, clippy::pedantic, clippy::cargo)]

This crate makes use of the zbus crate for dbus communication. We use the asynchronous zbus API, so to use atspi, you will need to run an async executer like tokio or async-std. The async-io and tokio features are exposed and will be passed through to zbus.

Contributing

We love people who add functionality, find bugs, or improve code quality! You can clone the repository and make modifications just by git clone-ing the repository like so:

$ git clone https://github.com/odilia-app/atspi
$ cd atspi
$ cargo build

If you have permissions to publish to crate to crates.io, then please make sure to tag it like so, pushing it to get, and then publishing to crates.io:

$ git tag -a vMAJ.MIN.PATCH -m "New feature in tag"
$ git push origin --tags

License

The atspi library is licensed as Apache 2.0 or MIT.

Comments
  • [Luuk's] Fully-Typed Events

    [Luuk's] Fully-Typed Events

    • #[must_use] attribute indicates that the user or the method must do something with the return type.
    • Functions that Result<> should document when the functon Err's

    You could also choose to tell Clippy not to complain about it, but either way, I find the squigllies distracting.

    opened by luukvanderduim 13
  • Handle New Event Types

    Handle New Event Types

    As of right now, the Connection::event_stream() function will provide a stream of events for use by client programs (or other libraries). Right now, it can only serialize two types of events: EventBody (sent by all applications except QT), and EventBodyQT (the type sent by QT applications). QT should be updating their implementation to be compliant with all the others if what I read in the at-spi2-core issues is correct.

    Now, there are other kinds of events that may come through that same connection, for example Cache::AddAccessible and Cache::RemoveAccessible return data with types ((so)(so)(so)iiassusau) and (so) respectively.

    Other signals on interfaces whoes signature is currently not supported by atspi: DeviceEventListener::KeystrokeListener(De)registered, Socket::Available, Registry:EventListener(De)registered.

    Ok, so here's the issue: do we use an enum to transport all of these events. Something like this:

    enum A11yEvent {
        RegistryEvent(RegEventBody),
        UserEvent(EventBody),
        DeviceListenerEvent(DeviceListenerBody),
        CacheAddAccessible(AddAccessibleBody),
        CacheRemoveAccessible(RemoveAccessibleBody),
    }
    

    Or is there some other way to handle this that makes more sense?

    Paging @albertotirla , @mcb2003 , @DataTriny for options on this since it will directly effect projects they work on. (Thanks again for all y'alls effort and contributions you've brought so far!)

    @luukvanderduim has been able to produce a working example by slimming down our problem into a smaller binary instead of a huge code-base like a screenreader. With this, we've found that lack of more diverse serialization types has caused these other types of events to be unable to be processed by assistive technologies at the higher level.

    Returning an enum like this would be a breaking change since the event type returned by event_stream() will be different. Any other suggestions or is everyone ok with the breakage?

    I'm personally fine with it, since that part of Odilia's code can be easily modified, but I just want to be sure that others haven't done too much with it, especially DataTriny.

    opened by TTWNO 10
  • atspi-macros: Introduce features to not force tokio

    atspi-macros: Introduce features to not force tokio

    We don't want to force tokio on users of AccessKit. The atspi crate doesn't either.

    Introduces new crate features for the atspi-macros crate and use these inside the main Cargo.toml to propagate the information.

    I haven't looked much into atspi-codegen because it didn't seem to be used directly, but it also uses tokio unconditionally. I just don't know if this is something to worry about.

    opened by DataTriny 5
  • Fully typed events

    Fully typed events

    Following in the tradition of Luuk's fully-typed-events https://github.com/odilia-app/atspi/pull/28

    Now adding Luuk as a contributor so we can work together on improving this branch.

    opened by TTWNO 5
  • [draft] Adds `set_session_accessability`

    [draft] Adds `set_session_accessability`

    Set the IsEnabled property in the session bus.

    Assistive Technology provider applications (ATs) should set the accessibility IsEnabled status on the users session bus on startup as applications may monitor this property to enable their accessibility support dynamically.

    See: The freedesktop - AT-SPI2 wiki

    opened by luukvanderduim 5
  • Add an include directive to minimize the published package size of `atspi`.

    Add an include directive to minimize the published package size of `atspi`.

    Crates that added atspi as a dependency do not need all of the repository. Adding an include or exclude directive allows for minimizing the projects published size.

    This PR reduces the published version of atspi by 27% or 120.3 KB in 26 files (of 447.5 KB and 75 files in entire crate)

    Achieved with the help of cargo-diet

    opened by luukvanderduim 4
  • Fix zbus version requirement

    Fix zbus version requirement

    While fixing #10 on f220104a, the zbus version requirement was not updated accordingly. This creates an issue for everyone depending on an older version of zbus that doesn't yet support the new attributes and outputs confusing compilation errors. With this fix Cargo should try to find an appropriate zbus version to satisfy everyone, or clearly say that a version can't be selected.

    opened by DataTriny 3
  • Change `Event` validation on messages to `MessageType::Signal` test.

    Change `Event` validation on messages to `MessageType::Signal` test.

    Signals are broadcasted Events. So, to test for events, it is sufficient to test if the Message is MessageType::Signal. This test is likely a little bit cheaper than the string compare, but that is not the point. Point is that we allow 5 more streams to come through RegistryProxy:

    $ rg ' signal' src/events/ -trust | wc --lines 56

    $ rg ' signal' src/ -trust | wc --lines 61

    The difference is made up by these events:

    src/registry.rs 31: /// EventListenerDeregistered signal 35: /// EventListenerRegistered signal

    src/cache.rs 59: /// AddAccessible signal 63: /// RemoveAccessible signal

    src/socket.rs 30: /// Available signal

    opened by luukvanderduim 3
  • Git tags for the `atspi` crate

    Git tags for the `atspi` crate

    Please create tags for published versions of the atspi crate. The following commands should do most of the work:

    git tag -a atspi-v0.0.1 f0dc8abfd3d71e4462ee3767055f78df37a0b3f7
    git tag -a atspi-v0.1.0 92f744cb616e9ff6bcd00c2795f87889138067e0
    git tag -a atspi-v0.1.1 bf5260e9b03efe7b1f79d4781988097ce708a357
    git tag -a atspi-v0.1.2 77b926357e0eb4b07bf2a9dc063fc4354ea288f2
    git tag -a atspi-v0.2.0 c1e865d421a9617ca6bbcc95a83be0ac408acd9f
    git tag -a atspi-v0.2.1 c5b360abe29faf99b563c40b9038b1d19e9a4f3f
    git tag -a atspi-v0.2.2 7266f83ee9fa77aecea0c2b954603e14a2c878a3
    git tag -a atspi-v0.3.1 038b59cd6ca36fcab93035773c92add775db08e7
    git tag -a atspi-v0.3.2 5be639425bf4efa92ee58e46ec6bea25d862167a
    

    Unfortunately, the following versions do not point to a commit that still exist in this repository:

    • atspi-v0.2.3 (commit 7ab0c5a204856acc63c39d6677ee3783f4047ccd)
    • atspi-v0.3.0 (commit bfa075e5fd4eb703bc0cdacd12cd213fc9341417)
    • atspi-v0.3.3 (commit 49cdfdebfe330a3a6c5b4ee46d985522d4bd2081)
    • atspi-v0.3.4 (commit 4fdcba0d4334b2782b0ffb62a7a0b990c234a721)

    It would be nice if you could do this for new versions as it helps people figure out what code they are using, and to detect potential supply-chain attacks.

    Thanks.

    opened by DataTriny 3
  • Apparently unneeded dependency on serde_with in atspi-macros

    Apparently unneeded dependency on serde_with in atspi-macros

    It looks like atspi-macros doesn't actually need the dependency on serde_with; it compiles fine without it. I bring this up because serde_with, at least using default features, adds many more dependencies, including such apparently nonsensical ones as android_system_properties (that one came indirectly via chrono). These may all be build-only, and some may be platform-specific dependencies that don't actually come up on any build platform, but some people will find the addition of so many extra dependencies in their Cargo.lock file annoying anyway.

    opened by mwcampbell 2
  • [draft] Add `set_session_accessibility` (again)

    [draft] Add `set_session_accessibility` (again)

    Set the IsEnabled property in the session bus.

    Assistive Technology provider applications (ATs) should set the accessibility IsEnabled status on the users session bus on startup as applications may monitor this property to enable their accessibility support dynamically.

    See: The freedesktop - AT-SPI2 wiki

    • rebased against main
    • removed #[must_use]. It does something different than I intended. Useful, but not here.
    opened by luukvanderduim 2
  • `.enabled()` property on StateChangedEvent should be a boolean

    `.enabled()` property on StateChangedEvent should be a boolean

    Whether the StateChangedEvent contains a boolean or not over the DBus wire, it appears that right now it works with an i32 (DBus: "i") return type.

    Should this be manually changed in the identify.rs file, then add a test for it returning a boolean, or should we leave it up to the library users figure it out? It's not like checking ==1 is super complicated.

    opened by TTWNO 3
  • Fix CI issues

    Fix CI issues

    Some concerns:

    1. I'm getting "module name reiterated as suffix" sort of clippy error on all the Enums in identify.rs; this is because the module name is separate to distinguish between object::PropertyChangeEvent and window::PropertyChangeEvent. Should I ignore these errors, or is there some better way to format that file (note the identify.rs is auto-generated, so please suggest the change here and I will put it in atspi-codegen).
    2. Some methods have "too many parameters", but those parameters have been inserted by the dbus_proxy macro, not the code itself; it would never be visible to end-users. Should this be ignored as well?

    That's just about it, I'm pretty happy with how close we are to passing clippy here.

    opened by TTWNO 3
  • Event de-structuring is cumbersome.

    Event de-structuring is cumbersome.

    Currently the event de-structuring looks as such:

    while let Ok(ev) = event_stream.next().await.expect("None") {
        let Event::Interfaces(EventInterfaces::Object( ObjectEvents::StateChanged(state_ev))) = ev else { continue; };
    
        if state_ev.state() == "focused" {
            let Some(sender) = state_ev.sender()? else { continue; };
            println!("Focused by: {sender}")
         }
    }
    

    If Event would hold a copy of AtspiEvent (instead of EventInterfaces) and the TryFrom implementations are adjusted to convert from Event to respectively: the signified types or the grouped EventInterfaces, we could:

    while let Ok(ev) = event_stream.next().await.expect("None") {
        let ev: StateChangedEvent = ev.try_into()? else { continue; };
    
        if ev.state() == "focused" {
            let Some(sender) = state_ev.sender()? else { continue; };
            println!("Focused by: {sender}")
         }
    }
    

    perhaps have current behaviour as such:

    while let Ok(ev) = event_stream.next().await.expect("None") {
        let evs: EventInterfaces = ev.try_into()? else { continue; };
    
        /// Then do destructuring ...
    }
    
    opened by luukvanderduim 1
  • Make registering for events easy

    Make registering for events easy

    Right now one has to use bpth atspi and zbus separately to allow events to come in on an event stream.

    It should be this easy:

    let conn = connection::new();
    conn.register_event(Event::Document::LoadComplete);
    
    let stream = conn.event_stream();
    while let Some(event) = stream.next().await {
        ...
    }
    

    If the library user would like to add additional things to the dbus connection, then they are welcome to do so by getting the internal connection (already possible) or creating a new connection all on their own.

    It should be easy to use atspi without knowing how dbus works—you should only have to know that this is hpw atspi works, and not be exposed to implementation details.

    opened by TTWNO 0
  • How can at-spi2-core notify you about XML changes?

    How can at-spi2-core notify you about XML changes?

    I'm in the process of doing several things more or less at the same time:

    The result is that the dbus XML files in at-spi2-core are changing to reflect what the C code actually does. Bindings that use the XML as a basis will of course want to be notified of this.

    So, this issue is me asking you for how to best communicate this.

    I can file a bug report here every time I make a change, but this doesn't help other projects (e.g. GTK4, WebKit) that also use DBus directly instead of atk.

    (Concretely, my latest fix is in this commit - not merged yet, hopefully in a merge request soon.)

    opened by federicomenaquintero 4
Owner
Odilia
Building a better screen reader for the Linux desktop, one step at a time.
Odilia
egui: an easy-to-use immediate mode GUI in pure Rust

?? egui: an easy-to-use GUI in pure Rust egui is a simple, fast, and highly portable immediate mode GUI library for Rust. egui runs on the web, native

Emil Ernerfeldt 12.6k Jan 3, 2023
A floating, tag-based window manager written in Rust

worm worm is a floating, tag-based window manager for X11. It is written in the Rust programming language, using the X11RB library. Install cargo buil

null 627 Jan 4, 2023
GUI based tool to sort and categorize images written in Rust

ImageSieve GUI based tool to sort out images based on similarity, categorize them according to their creation date and archive them in a target folder

Florian Fetz 67 Dec 14, 2022
A simple GUI version of the pH calibration tool written in egui, based on the eframe template.

caliphui A simple GUI version of the pH calibration tool written in egui, based on the eframe template. Usage Native binaries are provided under relea

Peter Dunne 0 Dec 29, 2021
Termbox is a library that provides minimalistic API which allows the programmer to write text-based user interfaces.

Termbox is a library that provides minimalistic API which allows the programmer to write text-based user interfaces.

null 1.9k Dec 22, 2022
An idiomatic GUI library inspired by Elm and based on gtk4-rs

An idiomatic GUI library inspired by Elm and based on gtk4-rs. Relm4 is a new version of relm that's built from scratch and is compatible with GTK4 an

Aaron Erhardt 722 Dec 31, 2022
An easy-to-use, 2D GUI library written entirely in Rust.

Conrod An easy-to-use, 2D GUI library written entirely in Rust. Guide What is Conrod? A Brief Summary Screenshots and Videos Feature Overview Availabl

PistonDevelopers 3.3k Jan 1, 2023
SwiftUI Inspired UI Library written in rust

Mule (Definitely a Work in Progress) The night I started this project I was on the couch drinking a Moscow Mule.

null 40 Jun 22, 2022
An Anime Game Launcher variant written on Rust, GTK4 and libadwaita, using Anime Game Core library

An Anime Game Launcher GTK The launcher variant written on Rust, GTK4 and libadwaita, using Anime Game Core library You could also try the main branch

An Anime Team 77 Jan 9, 2023
Honkers Launcher variant written on Rust, GTK4 and libadwaita, using Anime Game Core library

You could also try the main branch Development Folder Description ui Blueprint UI files ui/.dist UI files compiled by the blueprint src Rust source co

An Anime Team 9 Nov 2, 2022
Drew's fast Rust AppKit bindings

Drew's fast Rust AppKit bindings Provides select Rust bindings for Apple AppKit framework. This may be compared to, appkit crate cacao objrs_framework

Drew Crawford 2 Oct 28, 2022
Szyszka is a simple but powerful and fast bulk file renamer.

Szyszka is a simple but powerful and fast bulk file renamer. Features Written in Rust Available for Linux, Mac and Windows Simple GUI created

Rafał Mikrut 649 Dec 28, 2022
⚡ A blazing fast alternative to the default Windows delete.

Turbo Delete A blazing fast alternative to the default Windows delete. Turbodelete is a blazing fast alternative to the default Windows delete functio

Tejas Ravishankar 165 Dec 4, 2022
♾️ Fast & Simple AppImage manager

⚠️ Heavily in development (Not working) Leap Fast & Simple AppImage manager What's working Installation (github only, info about app not stored yet) R

lynx 7 Dec 12, 2022
Unofficial Linux QQ client, based on GTK4 and libadwaita, developed with Rust and Relm4.

GTK QQ (WIP) Unofficial Linux QQ client, based on GTK4 and libadwaita, developed with Rust and Relm4. Screenshots Light Dark Note The two screenshots

Lomírus 198 Dec 24, 2022
Fuse filesystem that returns symlinks to executables based on the PATH of the requesting process.

Envfs Fuse filesystem that returns symlinks to executables based on the PATH of the requesting process. This is useful to execute shebangs on NixOS th

Jörg Thalheim 98 Jan 2, 2023
A lightweight cross-platform system-monitoring fltk gui application based on sysinfo

Sysinfo-gui A lightweight cross-platform system-monitoring fltk gui application based on sysinfo. The UI design is inspired by stacer. The svg icons a

Mohammed Alyousef 22 Dec 31, 2022
Simple, thread-safe, counter based progress logging

?? proglog Documentation Crates.io This is a simple, thread-safe, count-based, progress logger. Synopsis proglog hooks into your existing log implemen

Seth 5 Nov 7, 2022
a day-planner/calendar app based on egui

Malakal Malakal is a day planner application. I crafted it because I was not able to find a comfortable calendar application for Linux. I myself have

null 5 Dec 21, 2022