1
0
mirror of https://github.com/gryf/wmaker.git synced 2025-12-20 04:48:06 +01:00
Files
wmaker/src/xdnd.c
1999-10-16 05:32:14 +00:00

336 lines
9.8 KiB
C

/* Many part of code are ripped of an example from JX's site */
#include "wconfig.h"
#ifdef XDND
#include <X11/Xlib.h>
#include "WindowMaker.h"
#include "window.h"
#include "dock.h"
#include "xdnd.h"
#include "motif.h"
#include "workspace.h"
#include "stdlib.h"
#include <X11/Xatom.h>
#define XDND_VERSION 3L
Atom _XA_XdndAware;
Atom _XA_XdndEnter;
Atom _XA_XdndLeave;
Atom _XA_XdndDrop;
Atom _XA_XdndPosition;
Atom _XA_XdndStatus;
Atom _XA_XdndActionCopy;
Atom _XA_XdndSelection;
Atom _XA_XdndFinished;
Atom _XA_WINDOWMAKER_XDNDEXCHANGE;
/*
Atom _XA_MOTIF_DRAG_RECEIVER_INFO;
Atom _XA_MOTIF_DRAG_AND_DROP_MESSAGE;
*/
Atom atom_support;
void wXDNDInitializeAtoms()
{
_XA_XdndAware = XInternAtom(dpy, "XdndAware", False);
_XA_XdndEnter = XInternAtom(dpy, "XdndEnter", False);
_XA_XdndLeave = XInternAtom(dpy, "XdndLeave", False);
_XA_XdndDrop = XInternAtom(dpy, "XdndDrop", False);
_XA_XdndPosition = XInternAtom(dpy, "XdndPosition", False);
_XA_XdndStatus = XInternAtom(dpy, "XdndStatus", False);
_XA_XdndActionCopy = XInternAtom(dpy, "XdndActionCopy", False);
_XA_XdndSelection = XInternAtom(dpy, "XdndSelection", False);
_XA_XdndFinished = XInternAtom(dpy, "XdndFinished", False);
_XA_WINDOWMAKER_XDNDEXCHANGE = XInternAtom(dpy, "_WINDOWMAKER_XDNDEXCHANGE", False);
/*
_XA_MOTIF_DRAG_RECEIVER_INFO = XInternAtom(dpy, "_MOTIF_DRAG_RECEIVER_INFO",False);
_XA_MOTIF_DRAG_AND_DROP_MESSAGE = XInternAtom(dpy, "_MOTIF_DRAG_AND_DROP_MESSAGE", False);
*/
}
void wXDNDMakeAwareness(Window window) {
long int xdnd_version = 3;
/*
MotifDragReceiverInfo info;
*/
XChangeProperty (dpy, window, _XA_XdndAware, XA_ATOM,
32, PropModeAppend, (char *)&xdnd_version, 1);
/*** MOTIF ***
info.byte_order = '\0';
info.protocol_version = 0;
info.protocol_style = XmDRAG_DYNAMIC;
info.proxy_window = 0;
info.num_drop_sites = 0;
info.total_size = sizeof(info);
XChangeProperty (dpy, window,
_XA_MOTIF_DRAG_RECEIVER_INFO,
_XA_MOTIF_DRAG_RECEIVER_INFO,
8, PropModeReplace,
(unsigned char *)&info,
sizeof (info));
*/
}
void wXDNDClearAwareness(Window window) {
long int xdnd_version = 3;
XDeleteProperty (dpy, window, _XA_XdndAware);
}
Bool
wXDNDProcessSelection(XEvent *event)
{
WScreen *scr = wScreenForWindow(event->xselection.requestor);
char *dropdata;
char *retain;
Atom ret_type;
int ret_format;
unsigned long ret_item;
unsigned long remain_byte;
char * delme;
XEvent xevent;
Window selowner = XGetSelectionOwner(dpy,_XA_XdndSelection);
WMBag *items;
XGetWindowProperty(dpy, event->xselection.requestor,
_XA_WINDOWMAKER_XDNDEXCHANGE,
0, 65536, True, atom_support, &ret_type, &ret_format,
&ret_item, &remain_byte, (unsigned char **)&delme);
if (delme){
scr->xdestring=delme;
}
/*send finished*/
memset (&xevent, 0, sizeof(xevent));
xevent.xany.type = ClientMessage;
xevent.xany.display = dpy;
xevent.xclient.window = selowner;
xevent.xclient.message_type = _XA_XdndFinished;
xevent.xclient.format = 32;
XDND_FINISHED_TARGET_WIN(&xevent) = event->xselection.requestor;
XSendEvent(dpy, selowner, 0, 0, &xevent);
/*process dropping*/
if (scr->xdestring) {
int length, str_size;
int total_size = 0;
char *tmp;
items = WMCreateBag(1);
retain = wstrdup(scr->xdestring);
XFree(scr->xdestring); /* since xdestring was created by Xlib */
length = strlen(retain);
/* search in string */
while (length--) {
if (retain[length] == '\r') { /* useless char, nuke it */
retain[length] = 0;
}
if (retain[length] == '\n') {
str_size = strlen(&retain[length + 1]);
if(str_size) {
WMPutInBag(items, wstrdup(&retain[length + 1]));
total_size += str_size + 3; /* reserve for " \"\"" */
if (length)
WMAppendBag(items, WMCreateBag(1));
}
retain[length] = 0;
}
}
/* final one */
WMPutInBag(items, wstrdup(retain));
total_size += strlen(retain) + 3;
free(retain);
/* now pack new string */
scr->xdestring = wmalloc(total_size);
scr->xdestring[0]=0; /* empty string */
for(length = WMGetBagItemCount(items)-1; length >=0; length--) {
tmp = WMGetFromBag(items, length);
if (!strncmp(tmp,"file:",5)) {
/* add more 2 chars while removing 5 is harmless */
strcat(scr->xdestring, " \"");
strcat(scr->xdestring, &tmp[5]);
strcat(scr->xdestring, "\"");
} else {
/* unsupport object, still need more " ? tell ]d */
strcat(scr->xdestring, &tmp[5]);
}
free(tmp);
}
WMFreeBag(items);
wDockReceiveDNDDrop(scr,event);
/*
printf("free ");
puts(scr->xdestring);
*/
free(scr->xdestring); /* this xdestring is not from Xlib (no XFree) */
}
}
Bool
isAwareXDND(Window window)
{
Atom actual;
int format;
unsigned long count, remaining;
unsigned char *data=0;
Atom *types, *t;
if (!window) return False;
XGetWindowProperty (dpy, window, _XA_XdndAware,
0, 0x8000000L, False, XA_ATOM,
&actual, &format,
&count, &remaining, &data);
if (actual != XA_ATOM || format != 32 || count == 0 || !data) {
if (data)
XFree (data);
return False;
}
if (data)
XFree (data);
return True;
}
Bool
acceptXDND(Window window)
{
WScreen *scr = wScreenForWindow(window);
WWindow *wwin = wWindowFor(window);
WDock *dock;
int icon_pos,i;
icon_pos = -1;
if ((dock = scr->dock)!=NULL) {
for (i=0; i<dock->max_icons; i++) {
if (dock->icon_array[i]
&& dock->icon_array[i]->icon->core->window==window) {
icon_pos = i;
break;
}
}
}
if (icon_pos<0 && (dock = scr->workspaces[scr->current_workspace]->clip)!=NULL) {
for (i=0; i<dock->max_icons; i++) {
if (dock->icon_array[i]
&& dock->icon_array[i]->icon->core->window==window) {
icon_pos = i;
break;
}
}
}
if (icon_pos<0) return False;
if (!dock) return False;
if (isAwareXDND(dock->icon_array[icon_pos]->icon->icon_win)) return False;
if (dock->icon_array[icon_pos]->dnd_command!=NULL) return True;
return False;
}
Bool
wXDNDProcessClientMessage(XClientMessageEvent *event)
{
/* test */
{
char * name = XGetAtomName(dpy, event->message_type);
/*
printf("Get %s\n",name);
*/
XFree(name);
}
/*
if (event->message_type == _XA_MOTIF_DRAG_AND_DROP_MESSAGE) {
printf("motif dnd msg %d\n",event->data.b[0]);
if (event->data.b[0] == XmDROP_START){
unsigned x_root, y_root, flags;
unsigned char reason;
unsigned long timestamp;
Atom atom;
Window source_window;
MotifDragInitiatorInfo *initiator_info;
Atom ret_type;
int ret_format;
unsigned long ret_item;
unsigned long remain_byte;
reason = event->data.b[0];
flags = event->data.s[1];
timestamp = event->data.l[1];
x_root = event->data.s[4];
y_root = event->data.s[5];
atom = event->data.l[3];
source_window = event->data.l[4];
XGetWindowProperty(dpy, source_window, atom,
0, sizeof(*initiator_info), True, atom_support,
&ret_type, &ret_format,
&ret_item, &remain_byte, (unsigned char **)&initiator_info);
}
}
else */
if (event->message_type == _XA_XdndEnter) {
if ((event->data.l[1] & 1) == 0){
atom_support = event->data.l[2];
}
/*
else puts("enter more than 3 types");
*/
return True;
} else if (event->message_type == _XA_XdndLeave) {
return True;
} else if (event->message_type == _XA_XdndDrop) {
if (event->data.l[0] == XGetSelectionOwner(dpy, _XA_XdndSelection)){
XConvertSelection(dpy, _XA_XdndSelection, atom_support,
_XA_WINDOWMAKER_XDNDEXCHANGE, event->window, CurrentTime);
}
else {
puts("wierd selection owner? QT?");
XConvertSelection(dpy, _XA_XdndSelection, atom_support,
_XA_WINDOWMAKER_XDNDEXCHANGE, event->window, CurrentTime);
}
return True;
} else if (event->message_type == _XA_XdndPosition) {
XEvent xevent;
Window srcwin = event->data.l[0];
if (atom_support != XInternAtom(dpy, "text/uri-list", False)) {
return True;
}
{
memset (&xevent, 0, sizeof(xevent));
xevent.xany.type = ClientMessage;
xevent.xany.display = dpy;
xevent.xclient.window = srcwin;
xevent.xclient.message_type = _XA_XdndStatus;
xevent.xclient.format = 32;
XDND_STATUS_TARGET_WIN (&xevent) = event->window;
XDND_STATUS_WILL_ACCEPT_SET (&xevent, acceptXDND(event->window));
XDND_STATUS_WANT_POSITION_SET(&xevent, True);
XDND_STATUS_RECT_SET(&xevent, 0, 0, 1024,768);
XDND_STATUS_ACTION(&xevent) = _XA_XdndActionCopy;
XSendEvent(dpy, srcwin, 0, 0, &xevent);
}
return True;
}
return False;
}
#endif