Drag&Drop implementation for X11

Signed-off-by: Thomas Bernard <miniupnp@free.fr>
This commit is contained in:
Thomas Bernard 2018-07-02 12:47:16 +02:00
parent e8a9d7e700
commit 0d3ab36291
2 changed files with 109 additions and 5 deletions

View File

@ -34,6 +34,7 @@
#ifdef USE_X11
#include <unistd.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/XKBlib.h>
#include <X11/Xutil.h>
@ -51,6 +52,7 @@
#ifdef USE_X11
extern Display * X11_display;
extern Window X11_window;
#endif
#if defined(USE_SDL)
@ -1228,6 +1230,7 @@ int Get_input(int sleep_time)
}
#elif defined(USE_X11)
int user_feedback_required = 0; // Flag qui indique si on doit arrêter de traiter les évènements ou si on peut enchainer
static int xdnd_version = 5;
Color_cycling();
// Commit any pending screen update.
@ -1366,11 +1369,109 @@ int Get_input(int sleep_time)
}
break;
case ClientMessage:
if (event.xclient.message_type == XInternAtom(X11_display,"WM_PROTOCOLS", False))
{
if (event.xclient.data.l[0] == XInternAtom(X11_display, "WM_DELETE_WINDOW", False))
{
Quit_is_required = 1;
user_feedback_required = 1;
}
else
{
// unrecognized WM event.
}
}
else if (event.xclient.message_type == XInternAtom(X11_display, "XdndEnter", False))
{
//int list = event.xclient.data.l[1] & 1;
xdnd_version = event.xclient.data.l[1] >> 24;
}
else if (event.xclient.message_type == XInternAtom(X11_display, "XdndLeave", False))
{
printf("XdndLeave\n");
}
else if (event.xclient.message_type == XInternAtom(X11_display, "XdndPosition", False))
{
XEvent reply;
int x_pos, y_pos;
x_pos = (event.xclient.data.l[2] >> 16) & 0xffff;
y_pos = event.xclient.data.l[2] & 0xffff;
// reply with XdndStatus
// see https://github.com/glfw/glfw/blob/a9a5a0b016215b4e40a19acb69577d91cf21a563/src/x11_window.c
memset(&reply, 0, sizeof(reply));
reply.type = ClientMessage;
reply.xclient.window = event.xclient.data.l[0];
reply.xclient.message_type = XInternAtom(X11_display, "XdndStatus", False);
reply.xclient.format = 32;
reply.xclient.data.l[0] = event.xclient.window;
reply.xclient.data.l[2] = 0; // Specify an empty rectangle
reply.xclient.data.l[3] = 0;
// Reply that we are ready to copy the dragged data
reply.xclient.data.l[1] = 1; // Accept with no rectangle
if (xdnd_version >= 2)
{
reply.xclient.data.l[4] = XInternAtom(X11_display, "XdndActionCopy", False);
}
XSendEvent(X11_display, event.xclient.data.l[0], False, NoEventMask, &reply);
}
else if (event.xclient.message_type == XInternAtom(X11_display, "XdndDrop", False))
{
XConvertSelection(X11_display,
XInternAtom(X11_display, "XdndSelection", False),
XInternAtom(X11_display, "text/uri-list", False),
XInternAtom(X11_display, "XdndSelection", False),
event.xclient.window,
event.xclient.data.l[2]);
}
break;
case SelectionNotify:
if (event.xselection.property == XInternAtom(X11_display, "XdndSelection", False))
{
Atom type = 0;
int format = 0;
int r;
unsigned long count = 0, bytesAfter = 0;
unsigned char * value = NULL;
r = XGetWindowProperty(X11_display, event.xselection.requestor, event.xselection.property, 0, LONG_MAX,
False, event.xselection.target /* type */, &type, &format,
&count, &bytesAfter, &value);
if (r == Success && value != NULL)
{
if (format == 8)
{
int i, j;
Drop_file_name = malloc(count + 1);
i = 0; j = 0;
if (count > 7 && 0 == memcmp(value, "file://", 7))
i = 7;
while (i < (int)count && value[i] != 0 && value[i] != '\n' && value[i] != '\r')
{
Drop_file_name[j++] = (char)value[i++]; // TODO : URI decode
}
Drop_file_name[j++] = '\0';
}
XFree(value);
}
if (xdnd_version >= 2)
{
XEvent reply;
memset(&reply, 0, sizeof(reply));
reply.type = ClientMessage;
reply.xclient.window = event.xselection.requestor;
reply.xclient.message_type = XInternAtom(X11_display, "XdndFinished", False);
reply.xclient.format = 32;
reply.xclient.data.l[0] = X11_window;
reply.xclient.data.l[1] = 1; // success
reply.xclient.data.l[2] = XInternAtom(X11_display, "XdndActionCopy", False);
XSendEvent(X11_display, event.xselection.requestor, False, NoEventMask, &reply);
}
}
break;
default:
printf("event.type = %d\n", event.type);

View File

@ -25,12 +25,13 @@
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include "screen.h"
#include "gfx2surface.h"
#include "loadsave.h"
Display * X11_display = NULL;
static Window X11_window = 0;
Window X11_window = 0;
static XImage * X11_image = NULL;
static char * image_pixels = NULL;
static XTextProperty windowName;
@ -311,7 +312,9 @@ volatile int Allow_colorcycling = 0;
/// Activates or desactivates file drag-dropping in program window.
void Allow_drag_and_drop(int flag)
{
(void)flag;
Atom version = flag ? 5 : 0;
XChangeProperty(X11_display, X11_window, XInternAtom(X11_display, "XdndAware", False), XA_ATOM, 32, PropModeReplace, (unsigned char *)&version, 1);
}
void Define_icon(void)