`Gtk.DropTarget` that has `.reject()`ed drop causes `Gdk-CRITICAL`: `gdk_drop_get_actions: assertion 'GDK_IS_DROP (self)' failed`
I'd appreciate a sanity-check whether/how I might be doing something wrong here - thanks in advance.
There is a test case below (in gtkmm
for now, sorry if that's a hassle).
As per the docs:
If the decision whether the drop will be accepted or rejected depends on the data, this function [the
::accept
handler] should returnTRUE
, theGtkDropTarget:preload
property should be set and the value should be inspected via the::notify:value
signal, callinggtk_drop_target_reject()
if required.
To replicate:
- Create a
DragSource
andDropTarget
- Set the
Target
to:preload
- Connect to
notify::value
and therein callDropTarget.reject()
- Get an error, via
gtk_drop_target_enter()
:
There shouldn't be an error here, presumably? If upon preload
ing the value
, we reject
it, then I would not expect subsequent enter
/motion
handlers to be called, or at least not to emit CRITICAL
s.
Am I doing something wrong in my code, or do we need to be more graceful if self->drop
has become NULL
or something, as in the code I link down below?
Abbreviated backtrace:
#3 0x00007ffff6d0318f in g_return_if_fail_warning (log_domain=0x7ffff5fec9af "Gdk",
pretty_function=0x7ffff5fecee0 <__func__.14> "gdk_drop_get_actions", expression=0x7ffff5fecbb3 "GDK_IS_DROP (self)")
at ../../../../jhbuild/checkout/gnome/glib/glib/gmessages.c:2930
#4 0x00007ffff5e81cf9 in gdk_drop_get_actions (self=0x0) at ../../../../jhbuild/checkout/gnome/gtk/gdk/gdkdrop.c:507
#5 0x00007ffff59b2c7e in gtk_drop_target_enter (self=0x5555556eb010, x=99.8125, y=4.2617192268371582)
at ../../../../jhbuild/checkout/gnome/gtk/gtk/gtkdroptarget.c:375
#6 0x00007ffff59148bf in _gtk_marshal_FLAGS__DOUBLE_DOUBLEv (closure=0x5555556cce70, return_value=0x7fffffffce30,
instance=0x5555556eb010, args=0x7fffffffd058, marshal_data=0x7ffff59b2c50 <gtk_drop_target_enter>, n_params=2,
param_types=0x5555556cd0f0) at gtk/gtkmarshalers.c:2012
#7 0x00007ffff73aa490 in g_type_class_meta_marshalv (closure=0x5555556cce70, return_value=0x7fffffffce30, instance=0x5555556eb010,
args=0x7fffffffd058, marshal_data=0x110, n_params=2, param_types=0x5555556cd0f0)
at ../../../../jhbuild/checkout/gnome/glib/gobject/gclosure.c:1060
#8 0x00007ffff73a9fe3 in _g_closure_invoke_va (closure=0x5555556cce70, return_value=0x7fffffffce30, instance=0x5555556eb010,
args=0x7fffffffd058, n_params=2, param_types=0x5555556cd0f0) at ../../../../jhbuild/checkout/gnome/glib/gobject/gclosure.c:895
#9 0x00007ffff73c8791 in signal_emit_valist_unlocked (instance=0x5555556eb010, signal_id=89, detail=0, var_args=0x7fffffffd058)
at ../../../../jhbuild/checkout/gnome/glib/gobject/gsignal.c:3516
#10 0x00007ffff73c816f in g_signal_emit_valist (instance=0x5555556eb010, signal_id=89, detail=0, var_args=0x7fffffffd058)
at ../../../../jhbuild/checkout/gnome/glib/gobject/gsignal.c:3355
#11 0x00007ffff73c99fa in g_signal_emit (instance=0x5555556eb010, signal_id=89, detail=0)
at ../../../../jhbuild/checkout/gnome/glib/gobject/gsignal.c:3675
#12 0x00007ffff59b317a in gtk_drop_target_handle_crossing (controller=0x5555556eb010, crossing=0x7fffffffd310, x=99.8125,
y=4.2617192268371582) at ../../../../jhbuild/checkout/gnome/gtk/gtk/gtkdroptarget.c:510
#13 0x00007ffff59cadf9 in gtk_event_controller_handle_crossing (controller=0x5555556eb010, crossing=0x7fffffffd310, x=99.8125,
y=4.2617192268371582) at ../../../../jhbuild/checkout/gnome/gtk/gtk/gtkeventcontroller.c:398
#14 0x00007ffff5b9b73a in gtk_widget_handle_crossing (widget=0x5555556e9a30, crossing=0x7fffffffd310, x=99.8125, y=4.2617192268371582)
at ../../../../jhbuild/checkout/gnome/gtk/gtk/gtkwidget.c:4632
#15 0x00007ffff5a6ea1d in gtk_synthesize_crossing_events (toplevel=0x5555556b8130, crossing_type=GTK_CROSSING_DROP,
old_target=0x5555556b8130, new_target=0x555555692190, surface_x=116.8125, surface_y=80.26171875, mode=GDK_CROSSING_NORMAL,
drop=0x555555682ba0) at ../../../../jhbuild/checkout/gnome/gtk/gtk/gtkmain.c:1238
#16 0x00007ffff5a6f22a in handle_pointing_event (event=0x5555556836b0) at ../../../../jhbuild/checkout/gnome/gtk/gtk/gtkmain.c:1454
#17 0x00007ffff5a6f679 in gtk_main_do_event (event=0x5555556836b0) at ../../../../jhbuild/checkout/gnome/gtk/gtk/gtkmain.c:1613
Possible change, here:
static GdkDragAction
gtk_drop_target_enter (GtkDropTarget *self,
double x,
double y)
{
+ if (self->drop == NULL)
+ return 0;
return make_action_unique (self->actions & gdk_drop_get_actions (self->drop));
}
static GdkDragAction
gtk_drop_target_motion (GtkDropTarget *self,
double x,
double y)
{
+ if (self->drop == NULL)
+ return 0;
return make_action_unique (self->actions & gdk_drop_get_actions (self->drop));
}
Test case:
#include <gtkmm.h>
static void
setup_dnd_source(Gtk::Widget& widget, Gdk::DragAction const actions)
{
auto value = Glib::Value<int>();
value.init(G_TYPE_INT);
value.set(42);
auto contentProvider = Gdk::ContentProvider::create(value);
auto source = Gtk::DragSource::create();
source->set_actions(actions);
source->set_content(contentProvider);
widget.add_controller(source);
}
static void
setup_dnd_dest(Gtk::Widget& widget, Gdk::DragAction const actions)
{
auto target = Gtk::DropTarget::create(G_TYPE_INT, actions);
target->set_preload(true);
target->property_value().signal_changed().connect( [=]
{ target->reject(); } );
widget.add_controller(target);
}
static void
setup_dnd(Gtk::Widget& source, Gtk::Widget& target)
{
auto const actions = Gdk::DragAction{Gdk::DragAction::COPY |
Gdk::DragAction::MOVE};
setup_dnd_source(source, actions);
setup_dnd_dest (target, actions);
}
static void
on_activate(Glib::RefPtr<Gtk::Application> const& app)
{
auto& but1 = *Gtk::make_managed<Gtk::Button>("Source");
auto& but2 = *Gtk::make_managed<Gtk::Button>("Target");
setup_dnd(but1, but2);
auto& box = *Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL);
box.append(but1);
box.append(but2);
auto win = new Gtk::Window{};
win->set_child(box);
win->set_visible(true);
app->add_window(*win);
}
auto
main() -> int
{
auto const app = Gtk::Application::create("org.djb.test.DnD");
app->signal_activate().connect( sigc::bind<0>(&on_activate, app) );
return app->run();
}