DeserializeDict fails to find a key that exists?
I have a DBusProxy that calls PickColor
method in the following interface org.freedesktop.portal.Screenshot
. The response is an ObjectPath
of a Request
Object that has a Response
signal as there's a user interaction (to pick the colour).
Here's a little example of the interface implementation
#[derive(SerializeDict, DeserializeDict, TypeDict, Debug, Default)]
/// Specified options on a pick color request.
pub struct PickColorOptions {
/// A string that will be used as the last element of the handle. Must be a valid object path element.
pub handle_token: Option<String>,
}
#[dbus_proxy(
interface = "org.freedesktop.portal.Screenshot",
default_service = "org.freedesktop.portal.Desktop",
default_path = "/org/freedesktop/portal/desktop"
)]
/// The interface lets sandboxed applications request a screenshot.
trait Screenshot {
/// Obtains the color of a single pixel.
///
/// Returns a [`Request`] handle
///
/// # Arguments
///
/// * `parent_window` - Identifier for the application window
/// * `options` - A [`PickColorOptions`]
///
/// [`PickColorOptions`]: ./struct.PickColorOptions.html
/// [`Request`]: ../request/struct.RequestProxy.html
fn pick_color(
&self,
parent_window: &str,
options: PickColorOptions,
) -> Result<OwnedObjectPath>;
}
In order to get the color, I have implemented a RquestProxy manually so I can provide a on_response
handler myself.
pub struct RequestProxy<'a> {
proxy: DBusProxy<'a>,
connection: &'a Connection,
}
impl<'a> RequestProxy<'a> {
pub fn new(connection: &'a Connection, handle: &'a str) -> Result<Self> {
let proxy = DBusProxy::new_for(connection, handle, "/org/freedesktop/portal/desktop")?;
Ok(Self { proxy, connection })
}
pub fn on_response<F, T>(&self, callback: F) -> Result<()>
where
F: FnOnce(T),
T: serde::de::DeserializeOwned + zvariant::Type,
{
loop {
let msg = self.connection.receive_message()?;
let msg_header = msg.header()?;
if msg_header.message_type()? == zbus::MessageType::Signal
&& msg_header.member()? == Some("Response")
{
let response = msg.body::<T>()?;
callback(response);
break;
}
}
Ok(())
}
}
The RequestProxy
is something common with all the portals that requests a user interaction, hence the type T so that the user can specify which response they are expecting.
My idea is then to provide the various types of the expected responses, here's what I get for a PickColor
response using Bustle (uint32 0, {'color': <(1.0, 1.0, 1.0)>})
and here's my PickColorResponse
type.
#[derive(Serialize_repr, Deserialize_repr, PartialEq, Debug, Type)]
#[repr(u32)]
pub enum ResponseType {
// Success, the request is carried out
Success = 0,
// The user cancelled the interaction
Cancelled = 1,
// The user interaction was ended in some other way
Other = 2,
}
#[derive(Debug, Type, Deserialize)]
pub struct ColorResponse(pub ResponseType, pub std::collections::HashMap<String, OwnedValue>);
The HashMap contains the following data
{
"color": OwnedValue(
Structure(
Structure(
[
F64(
1.0,
),
F64(
1.0,
),
F64(
1.0,
),
],
),
),
),
}
My idea is to replace the HashMap with a structure so that I can provide a Color
struct & make it easier to convert it to a gdk::RGBA
for example.
But replacing ColorResponse with something like
#[derive(Debug, Type, Deserialize)]
pub struct ColorResponse(pub ResponseType, pub ColorResult);
#[derive(Debug, TypeDict, DeserializeDict, SerializeDict)]
pub struct ColorResult {
pub color: Vec<f64>,
}
Results in the following error
Error: InconsistentMessage("missing field `color`")
I have put together a demo of the current situation here https://gitlab.gnome.org/bilelmoussaoui/color-bus
Let me know if I should provide more information or try something, I'm more or less lost on how I should handle this :) thanks!