Skip to content
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

gdk::content_register_deserializer usage is unclear, and possibly broken #1443

Open
awused opened this issue Jul 30, 2023 · 5 comments
Open
Labels
bug Something isn't working gdk

Comments

@awused
Copy link

awused commented Jul 30, 2023

Bug description

I'm not really certain that this is buggy or just completely undocumented and confusing to the point of unusability, but I just cannot get gdk::content_register_deserializer to work.

I've tried all kinds of variations on this code. Calling return_success() or not, setting user_data to Some(mine), even using unsafe to call gdk_content_deserializer_return_success directly (that one made more progress). I've explicitly closed the input stream and not.

    MyType::ensure_type();

    gdk::content_register_deserializer(
        SPECIAL,
        MyType::static_type(),
        |deserializer, user_data: &mut Option<MyType>| {
            let mine = MyType::default();

            deserializer.set_value(mine.into());
            deserializer.return_success();
        },
    );

If I understand it right, this simple code should just unconditionally "deserialize" the default value, but it just throws warnings and the corresponding display.clipboard().read_value_async never calls its callback.

Looking at nautilus code, since i couldn't find any rust usages of register_deserializer, I see it ends with the same two calls and I cannot figure out what I'm doing differently, and throughout the day I've tried code almost identical to Nautilus' code just to try to figure out what is going on. From nautilus-clipboard.c which I was using as a reference.

    g_value_set_boxed (gdk_content_deserializer_get_value (deserializer), clip);
    gdk_content_deserializer_return_success (deserializer);

Backtrace

Really it mostly just throws warnings and does nothing, or it segfaults (even without unsafe in my code) depending on how I try to get it to work. I just don't get how deserializer.return_success() can end up with a confused type.

(aw-fm:2614375): Gdk-CRITICAL **: 23:22:51.795: gdk_content_deserialize_finish: assertion 'GDK_IS_CONTENT_DESERIALIZER (result)' failed

(aw-fm:2614375): GLib-GIO-CRITICAL **: 23:22:51.795: g_task_return_error: assertion 'error != NULL' failed

(aw-fm:2614375): GLib-GIO-CRITICAL **: 23:22:51.795: GTask source_tag (source object: 0x55f96b3bc330, source tag: 0x7f2637292cc0) finalized without ever returning (using g_task_return_*()). This potentially indicates a bug in the program.

(aw-fm:2614375): GLib-GObject-CRITICAL **: 23:22:51.795: g_object_unref: assertion 'G_IS_OBJECT (object)' failed

@awused awused added the bug Something isn't working label Jul 30, 2023
@bilelmoussaoui
Copy link
Member

Please provide an easy to run example.

@awused
Copy link
Author

awused commented Aug 2, 2023

Honestly I think that's part of the problem, there aren't any examples or documentation at all in gtk4-rs and I think I'm probably the first person, period, to ever try using this function. I wasn't able to get any code at all to successfully run to completion. I'll try and make a more minimal example of something that should probably work later, but the example given is already pretty minimal: calling set_value and return_success with some dummy value should be enough.

@awused
Copy link
Author

awused commented Aug 2, 2023

Here's some code that, to the best of my understanding from reading the GTK docs and Nautilus/Caja code, should work. Assumes you have some text in your clipboard, I've only tested this on X myself. This example segfaults.

It is wrong in that it doesn't close deserializer's input stream, but that shouldn't break anything, not immediately. Reading that requires some additional async mess and doesn't change the eventual crash or failure.

use gtk4::gio::Cancellable;
use gtk4::glib::BoxedAnyObject;
use gtk4::prelude::{ApplicationExt, ApplicationExtManual, DisplayExt, StaticType};
use gtk4::traits::WidgetExt;
use gtk4::{gdk, glib, Application, ApplicationWindow};

fn main() -> glib::ExitCode {
    let app = Application::builder().application_id("org.example.HelloWorld").build();

    app.connect_activate(|app| {
        // We create the main window.
        let window = ApplicationWindow::builder()
            .application(app)
            .default_width(320)
            .default_height(200)
            .title("Hello, World!")
            .build();

        window.set_visible(true);


        gdk::content_register_deserializer(
            "text/plain;charset=utf-8",
            BoxedAnyObject::static_type(),
            |deserializer, user_data: &mut Option<BoxedAnyObject>| {
                println!("Deserializing");
                let boxed = BoxedAnyObject::new("Dummy value");

                deserializer.set_value(boxed.into());
                deserializer.return_success();
            },
        );


        window.display().clipboard().read_value_async(
            BoxedAnyObject::static_type(),
            glib::Priority::DEFAULT,
            Cancellable::NONE,
            move |text| {
                let text = text.unwrap();
                let text = text.get::<BoxedAnyObject>().unwrap();
                let text = text.borrow::<String>();

                println!("Got clipboard contents {text}");
            },
        );
        println!("timeout-done");
    });

    app.run()
}

Edit: Also, setting user_data to Some(value) doesn't help either.

@bilelmoussaoui
Copy link
Member

I do believe the content_register_deserializer is probably wrong. Needs someone to look into it at some point but what is exactly you are trying to achieve? because the code itself doesn't seem to be correct, you are registering a deserializer and then reading the value from clipboard except nothing is set on the clipboard?

bilelmoussaoui added a commit that referenced this issue Aug 2, 2023
bilelmoussaoui added a commit that referenced this issue Aug 2, 2023
@awused
Copy link
Author

awused commented Aug 2, 2023

Well my ultimate goal is to actually read the contents of the clipboard and deserialize it into my custom type, so that I get cross-platform (at least X and Wayland) clipboard support. The example is very, very obviously just a dummy example that neither reads the contents of the clipboard nor actually deserializes them, it's just a minimal example of API usage that should work in that the deserializer is completed and should produce some value.

See https://gitlab.gnome.org/GNOME/nautilus/-/blob/ffc39891d4692e74b26df26f8ac697bd30882c4c/src/nautilus-clipboard.c#L215 and the referenced functions for something similar to what I was trying to do. I've wasted enough hours trying to get this to work in gtk-rs.

Edit: On the other hand, the clipboard setting code (GdkContentProvider) does seem to work just fine, and I'm using that.

bilelmoussaoui added a commit that referenced this issue Aug 12, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working gdk
Projects
None yet
Development

No branches or pull requests

2 participants