Reputation: 30142
I want to make a GTK widget, when dragged and dropped in another program, will act as if a file was dropped (behaving the same way as dragging a file from Nautilus).
I have tried 3 different ways of setting the drag data in the callback, but nothing seems to work:
#include <bits/stdc++.h>
#include <gtkmm.h>
#define FILENAME "/tmp/foo.txt"
int main(int argc, char *argv[]) {
auto app = Gtk::Application::create(argc, argv, "com.tyilo.foo");
Gtk::Window window;
window.set_default_size(200, 200);
window.set_keep_above();
Gtk::Button button("Drag this");
window.add(button);
std::vector<Gtk::TargetEntry> listTargets;
listTargets.push_back(Gtk::TargetEntry("text/uri-list"));
//listTargets.push_back(Gtk::TargetEntry("text/plain"));
//listTargets.push_back(Gtk::TargetEntry("text/plain;charset=utf-8"));
//listTargets.push_back(Gtk::TargetEntry("UTF8_STRING"));
//listTargets.push_back(Gtk::TargetEntry("COMPOUND_STRING"));
//listTargets.push_back(Gtk::TargetEntry("TEXT"));
//listTargets.push_back(Gtk::TargetEntry("STRING"));
button.drag_source_set(listTargets, Gdk::ModifierType(GDK_BUTTON1_MASK | GDK_BUTTON3_MASK),
Gdk::DragAction(GDK_ACTION_COPY | GDK_ACTION_MOVE));
button.drag_source_set_icon("document-save");
button.signal_drag_data_get().connect([&](auto, auto selection_data, auto, auto) {
std::cout << "Data get: " << selection_data.get_target() << std::endl;
auto uri = Glib::filename_to_uri(FILENAME);
std::cout << uri << std::endl;
// All but one of (1), (2) and (3) should be commented out
// (1)
selection_data.set_uris({uri});
// (2)
//uri += "\r\n";
//selection_data.set(selection_data.get_target(), 8, (const guchar*)uri.c_str(), uri.bytes());
// (3)
//selection_data.set("text/uri-list", "file:///tmp/foo.txt\r\n");
});
window.show_all();
return app->run(window);
}
Do I need to specify more targets than just text/uri-list
? Do I need to handle these differently?
Or am I doing something wrong with setting the selection data?
I'm using gtkmm3
version 3.24.1
and gtk3
version 3.24.8
and I'm compiling with:
g++ foo.cpp $(pkg-config gtkmm-3.0 --cflags --libs)
An easy way to test if it works, is try to drag the file to the following <input>
tag in your browser:
<input type=file value="Drop here">
Upvotes: 5
Views: 846
Reputation: 1
#include <gtkmm.h>
#include <glibmm.h>
#include <iostream>
#include <vector>
#define FILENAME "/tmp/foo.txt"
static void on_drag_data_get( const Glib::RefPtr<Gdk::DragContext>& context,
Gtk::SelectionData& selection_data, guint info, guint time){
std::vector<Glib::ustring> vec_uris;
vec_uris.push_back(Glib::filename_to_uri(FILENAME));
std::cout << "File = " << vec_uris[0] << '\n';
selection_data.set_uris(vec_uris);
}
int main(int argc, char *argv[])
{
auto app = Gtk::Application::create(argc, argv, "com.tyilo.foo");
Gtk::Window window;
window.set_default_size(200, 200);
window.set_keep_above();
Gtk::Button button("Drag this");
window.add(button);
std::vector<Gtk::TargetEntry> listTargets;
listTargets.push_back(Gtk::TargetEntry("text/uri-list"));
button.drag_source_set(listTargets, Gdk::ModifierType::BUTTON1_MASK, Gdk::DragAction::ACTION_COPY);
button.drag_source_add_uri_targets();
button.drag_source_set_icon("document-save"); // x-office-spreadsheet, document
button.signal_drag_data_get().connect(sigc::ptr_fun(&on_drag_data_get));
window.show_all();
return app->run(window);
}
Upvotes: 0