xdnd: can handle more than 3 different target types

Now dropping also works with Nemo and PCManFM(gtk)
This commit is contained in:
Andreas Haas 2016-05-29 17:40:08 +02:00
parent ae0a59731e
commit 2c9b28df13
1 changed files with 61 additions and 22 deletions

View File

@ -1180,6 +1180,57 @@ void OS_X11::handle_key_event(XKeyEvent *p_event, bool p_echo) {
input->parse_input_event( event); input->parse_input_event( event);
} }
struct Property
{
unsigned char *data;
int format, nitems;
Atom type;
};
static Property read_property(Display* p_display, Window p_window, Atom p_property) {
Atom actual_type;
int actual_format;
unsigned long nitems;
unsigned long bytes_after;
unsigned char *ret=0;
int read_bytes = 1024;
//Keep trying to read the property until there are no
//bytes unread.
do
{
if(ret != 0)
XFree(ret);
XGetWindowProperty(p_display, p_window, p_property, 0, read_bytes, False, AnyPropertyType,
&actual_type, &actual_format, &nitems, &bytes_after,
&ret);
read_bytes *= 2;
}while(bytes_after != 0);
Property p = {ret, actual_format, nitems, actual_type};
return p;
}
static Atom pick_target_from_list(Display* p_display, Atom *p_list, int p_count) {
static const char* target_type = "text/uri-list";
for (int i = 0; i < p_count; i++) {
Atom atom = p_list[i];
if (atom != None && String(XGetAtomName(p_display, atom)) == target_type)
return atom;
}
return None;
}
static Atom pick_target_from_atoms(Display* p_disp, Atom p_t1, Atom p_t2, Atom p_t3) { static Atom pick_target_from_atoms(Display* p_disp, Atom p_t1, Atom p_t2, Atom p_t3) {
static const char* target_type = "text/uri-list"; static const char* target_type = "text/uri-list";
@ -1489,28 +1540,9 @@ void OS_X11::process_xevents() {
if (event.xselection.target == requested) { if (event.xselection.target == requested) {
Atom actual_type; Property p = read_property(x11_display, x11_window, XInternAtom(x11_display, "PRIMARY", 0));
int actual_format;
unsigned long nitems;
unsigned long bytes_after;
unsigned char *ret=0;
int read_bytes = 1024; Vector<String> files = String((char *)p.data).split("\n", false);
//Keep trying to read the property until there are no
//bytes unread.
do
{
if(ret != 0)
XFree(ret);
XGetWindowProperty(x11_display, x11_window, XInternAtom(x11_display, "PRIMARY", 0), 0, read_bytes, False, AnyPropertyType,
&actual_type, &actual_format, &nitems, &bytes_after,
&ret);
read_bytes *= 2;
}while(bytes_after != 0);
Vector<String> files = String((char *)ret).split("\n", false);
for (int i = 0; i < files.size(); i++) { for (int i = 0; i < files.size(); i++) {
files[i] = files[i].replace("file://", "").replace("%20", " ").strip_escapes(); files[i] = files[i].replace("file://", "").replace("%20", " ").strip_escapes();
} }
@ -1541,7 +1573,14 @@ void OS_X11::process_xevents() {
//File(s) have been dragged over the window, check for supported target (text/uri-list) //File(s) have been dragged over the window, check for supported target (text/uri-list)
xdnd_version = ( event.xclient.data.l[1] >> 24); xdnd_version = ( event.xclient.data.l[1] >> 24);
requested = pick_target_from_atoms(x11_display, event.xclient.data.l[2],event.xclient.data.l[3], event.xclient.data.l[4]); Window source = event.xclient.data.l[0];
bool more_than_3 = event.xclient.data.l[1] & 1;
if (more_than_3) {
Property p = read_property(x11_display, source, XInternAtom(x11_display, "XdndTypeList", False));
requested = pick_target_from_list(x11_display, (Atom*)p.data, p.nitems);
}
else
requested = pick_target_from_atoms(x11_display, event.xclient.data.l[2],event.xclient.data.l[3], event.xclient.data.l[4]);
} }
else if ((unsigned int)event.xclient.message_type == (unsigned int )xdnd_position) { else if ((unsigned int)event.xclient.message_type == (unsigned int )xdnd_position) {