Skip to content

Commit

Permalink
backend: Add basic support
Browse files Browse the repository at this point in the history
  • Loading branch information
A6GibKm authored and bilelmoussaoui committed Aug 10, 2024
1 parent 47aa993 commit 8fe8214
Show file tree
Hide file tree
Showing 30 changed files with 1,646 additions and 13 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
- uses: actions-rs/cargo@v1
with:
command: check
args: --features "gtk4,pipewire,wayland,raw_handle,tracing"
args: --features "gtk4,pipewire,wayland,raw_handle,tracing,backend"

test:
name: Test Suite
Expand All @@ -42,7 +42,7 @@ jobs:
- uses: actions-rs/cargo@v1
with:
command: test
args: --features "gtk4,pipewire,wayland,raw_handle,tracing"
args: --features "gtk4,pipewire,wayland,raw_handle,tracing,backend"

fmt:
name: Rustfmt
Expand Down Expand Up @@ -82,4 +82,4 @@ jobs:
- uses: actions-rs/cargo@v1
with:
command: clippy
args: --features "gtk4,pipewire,wayland,raw_handle,tracing" -- -D warnings
args: --features "gtk4,pipewire,wayland,raw_handle,tracing,backend" -- -D warnings
69 changes: 69 additions & 0 deletions .github/workflows/backend-demo-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
on:
push:
branches: [master]
pull_request:

name: Backend Demo CI

jobs:
check:
name: Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
- uses: actions-rs/cargo@v1
with:
command: check
args: --manifest-path=backend-demo/Cargo.toml

test:
name: Test Suite
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
- uses: actions-rs/cargo@v1
with:
command: test
args: --manifest-path=backend-demo/Cargo.toml

fmt:
name: Rustfmt
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
- run: rustup component add rustfmt
- uses: actions-rs/cargo@v1
with:
command: fmt
args: --manifest-path=backend-demo/Cargo.toml --all -- --check

clippy:
name: Clippy
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
- run: rustup component add clippy
- uses: actions-rs/cargo@v1
with:
command: clippy
args: --manifest-path=backend-demo/Cargo.toml -- -D warnings
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ ashpd-demo/_build/
ashpd-demo/builddir/
ashpd-demo/src/config.rs
ashpd-demo/target/
backend-demo/target

.flatpak
.vscode
_build/
builddir/
session-test
.fenv
5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ rust-version = "1.75"
[features]
async-std = ["zbus/async-io", "dep:async-fs", "dep:async-net"]
default = ["async-std"]

backend = ["async-trait", "nix", "futures-channel/sink", "tokio"]

gtk4 = ["gtk4_x11", "gtk4_wayland"]
gtk4_wayland = ["gdk4wayland", "glib", "dep:gtk4"]
gtk4_x11 = ["gdk4x11", "glib", "dep:gtk4"]
Expand All @@ -25,13 +28,15 @@ wayland = ["wayland-client", "wayland-protocols", "wayland-backend"]
[dependencies]
async-fs = { version = "2.1.0", optional = true }
async-net = { version = "2.0.0", optional = true }
async-trait = {version = "0.1.60", optional = true}
enumflags2 = "0.7"
futures-channel = "0.3"
futures-util = "0.3"
gdk4wayland = { package = "gdk4-wayland", version = "0.9", optional = true }
gdk4x11 = { package = "gdk4-x11", version = "0.9", optional = true }
glib = { version = "0.20", optional = true }
gtk4 = { version = "0.9", optional = true }
nix = { version = "0.29", optional = true, features = ["user"], default-features = false}
pipewire = { version = "0.8", optional = true }
rand = { version = "0.8", default-features = false }
raw-window-handle = { version = "0.6", optional = true }
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ pub async fn run() -> ashpd::Result<()> {
| tracing | Record various debug information using the `tracing` library | No |
| tokio | Enable tokio runtime on zbus dependency | No |
| async-std | Enable the use of the async-std runtime | Yes |
| backend | *unstable* Enables APIs useful for writing portals implementations | No |
| glib | Make all the enums derive `glib::Enum`. Flags are not supported yet | No |
| gtk4 | Implement `From<Color>` for [`gdk4::RGBA`](https://gtk-rs.org/gtk4-rs/stable/latest/docs/gdk4/struct.RGBA.html) Provides `WindowIdentifier::from_native` that takes a [`IsA<gtk4::Native>`](https://gtk-rs.org/gtk4-rs/stable/latest/docs/gtk4/struct.Native.html) | No |
| gtk4_wayland |Provides `WindowIdentifier::from_native` that takes a [`IsA<gtk4::Native>`](https://gtk-rs.org/gtk4-rs/stable/latest/docs/gtk4/struct.Native.html) with Wayland backend support only | No |
Expand Down
21 changes: 21 additions & 0 deletions backend-demo/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[package]
name = "ashpd-backend-demo"
version = "0.1.0"
edition = "2021"

[dependencies]
anyhow = "1.0"
async-trait = "0.1.60"
tokio = { version = "1.0", features = ["io-util", "net", "time", "macros", "rt-multi-thread"] }
byteorder = "1.4.3"
futures-channel = "0.3.25"
futures-util = "0.3.25"
tracing = "0.1"
tracing-subscriber = "0.3.16"
url = "2.3.1"
zbus = "4.2"

[dependencies.ashpd]
path = "../"
features = ["backend", "tracing"]
default-features = false
3 changes: 3 additions & 0 deletions backend-demo/data/ashpd-backend-demo.portal
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[portal]
DBusName=org.freedesktop.impl.portal.desktop.ashpd-backend-demo
Interfaces=org.freedesktop.impl.portal.Account;org.freedesktop.impl.portal.Screenshot;org.freedesktop.impl.portal.Wallpaper;
41 changes: 41 additions & 0 deletions backend-demo/src/account.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use std::num::NonZeroU32;

use ashpd::{
backend::{
account::{AccountImpl, UserInformationOptions},
request::RequestImpl,
},
desktop::{account::UserInformation, Response},
AppID, WindowIdentifierType,
};
use async_trait::async_trait;

#[derive(Default)]
pub struct Account;

#[async_trait]
impl RequestImpl for Account {
async fn close(&self) {
tracing::debug!("IN Close()");
}
}

#[async_trait]
impl AccountImpl for Account {
const VERSION: NonZeroU32 = NonZeroU32::MIN;

async fn get_information(
&self,
_app_id: AppID,
_window_identifier: Option<WindowIdentifierType>,
_options: UserInformationOptions,
) -> Response<UserInformation> {
match UserInformation::current_user().await {
Ok(info) => Response::ok(info),
Err(err) => {
tracing::error!("Failed to get user info: {err}");
Response::other()
}
}
}
}
54 changes: 54 additions & 0 deletions backend-demo/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
use futures_util::future::pending;
mod account;
mod screenshot;
mod secret;
mod wallpaper;

use account::Account;
use screenshot::Screenshot;
use secret::Secret;
use wallpaper::Wallpaper;

// NOTE Uncomment if you have ashpd-backend-demo.portal installed.
// const NAME: &str = "org.freedesktop.impl.portal.desktop.ashpd-backend-demo";
const NAME: &str = "org.freedesktop.impl.portal.desktop.gnome";
// Run with
// RUST_LOG=ashpd_backend_demo=debug,ashpd=debug cargo run --manifest-path
// ./backend-demo/Cargo.toml

#[tokio::main]
async fn main() -> ashpd::Result<()> {
// Enable debug with `RUST_LOG=ashpd_backend_demo=debug COMMAND`.
tracing_subscriber::fmt::init();

tracing::debug!("Serving interfaces at {NAME}");
let backend = ashpd::backend::Backend::new(NAME).await?;
let account = ashpd::backend::account::Account::new(Account, &backend).await?;
tokio::task::spawn(async move {
loop {
account.try_next().await.unwrap();
}
});
let wallpaper = ashpd::backend::wallpaper::Wallpaper::new(Wallpaper, &backend).await?;
tokio::task::spawn(async move {
loop {
wallpaper.try_next().await.unwrap();
}
});
let screenshot = ashpd::backend::screenshot::Screenshot::new(Screenshot, &backend).await?;
tokio::task::spawn(async move {
loop {
screenshot.try_next().await.unwrap();
}
});
let secret = ashpd::backend::secret::Secret::new(Secret, &backend).await?;
tokio::task::spawn(async move {
loop {
secret.try_next().await.unwrap();
}
});

loop {
pending::<()>().await;
}
}
46 changes: 46 additions & 0 deletions backend-demo/src/screenshot.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use std::num::NonZeroU32;

use ashpd::{
backend::{
request::RequestImpl,
screenshot::{ColorOptions, ScreenshotImpl, ScreenshotOptions},
},
desktop::{screenshot::Screenshot as ScreenshotResponse, Color, Response},
AppID, WindowIdentifierType,
};
use async_trait::async_trait;

#[derive(Default)]
pub struct Screenshot;

#[async_trait]
impl RequestImpl for Screenshot {
async fn close(&self) {
tracing::debug!("IN Close()");
}
}

#[async_trait]
impl ScreenshotImpl for Screenshot {
const VERSION: NonZeroU32 = NonZeroU32::MIN;

async fn screenshot(
&self,
_app_id: AppID,
_window_identifier: Option<WindowIdentifierType>,
_options: ScreenshotOptions,
) -> Response<ScreenshotResponse> {
Response::ok(ScreenshotResponse::new(
url::Url::parse("file:///some/sreenshot").unwrap(),
))
}

async fn pick_color(
&self,
_app_id: AppID,
_window_identifier: Option<WindowIdentifierType>,
_options: ColorOptions,
) -> Response<Color> {
Response::ok(Color::new(1.0, 1.0, 1.0))
}
}
32 changes: 32 additions & 0 deletions backend-demo/src/secret.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
use std::{collections::HashMap, num::NonZeroU32};

use ashpd::{
backend::{request::RequestImpl, secret::SecretImpl},
desktop::Response,
zbus::zvariant::{self, OwnedValue},
AppID,
};
use async_trait::async_trait;

#[derive(Default)]
pub struct Secret;

#[async_trait]
impl RequestImpl for Secret {
async fn close(&self) {
tracing::debug!("IN Close()");
}
}

#[async_trait]
impl SecretImpl for Secret {
const VERSION: NonZeroU32 = NonZeroU32::MIN;

async fn retrieve(
&self,
_app_id: AppID,
_fd: zvariant::OwnedFd,
) -> Response<HashMap<String, OwnedValue>> {
Response::Ok(Default::default())
}
}
36 changes: 36 additions & 0 deletions backend-demo/src/wallpaper.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
use std::num::NonZeroU32;

use ashpd::{
backend::{
request::RequestImpl,
wallpaper::{WallpaperImpl, WallpaperOptions},
},
desktop::Response,
AppID, WindowIdentifierType,
};
use async_trait::async_trait;

#[derive(Default)]
pub struct Wallpaper;

#[async_trait]
impl RequestImpl for Wallpaper {
async fn close(&self) {
tracing::debug!("IN Close()");
}
}

#[async_trait]
impl WallpaperImpl for Wallpaper {
const VERSION: NonZeroU32 = NonZeroU32::MIN;

async fn with_uri(
&self,
_app_id: AppID,
_window_identifier: Option<WindowIdentifierType>,
_uri: url::Url,
_options: WallpaperOptions,
) -> Response<()> {
Response::ok(())
}
}
12 changes: 12 additions & 0 deletions src/app_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,18 @@ use zbus::zvariant::Type;
#[derive(Debug, Serialize, Type, PartialEq, Eq, Hash, Clone)]
pub struct AppID(String);

impl AppID {
#[cfg(all(
feature = "backend",
any(feature = "gtk4_x11", feature = "gtk4_wayland")
))]
/// Retrieves the associated `gio::DesktopAppInfo` if found
pub fn app_info(&self) -> Option<gtk4::gio::DesktopAppInfo> {
let desktop_file = format!("{}.desktop", self.0);
gtk4::gio::DesktopAppInfo::new(&desktop_file)
}
}

impl FromStr for AppID {
type Err = crate::Error;
fn from_str(value: &str) -> Result<Self, Self::Err> {
Expand Down
Loading

0 comments on commit 8fe8214

Please sign in to comment.