Drag&Drop implementation for X11
Signed-off-by: Thomas Bernard <miniupnp@free.fr>
This commit is contained in:
parent
e8a9d7e700
commit
0d3ab36291
101
src/input.c
101
src/input.c
@ -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);
|
||||
|
||||
@ -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)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user