~profzoom/ubuntu/quantal/wmaker/bug-1079925

« back to all changes in this revision

Viewing changes to src/xdnd.c

  • Committer: Bazaar Package Importer
  • Author(s): Marcelo E. Magallon
  • Date: 2004-11-10 14:05:30 UTC
  • Revision ID: james.westby@ubuntu.com-20041110140530-qpd66b5lm38x7apk
Tags: upstream-0.91.0
ImportĀ upstreamĀ versionĀ 0.91.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Many part of code are ripped of an example from JX's site */
 
2
 
 
3
#include "wconfig.h"
 
4
 
 
5
#ifdef XDND
 
6
 
 
7
#include <X11/Xlib.h>
 
8
#include "WindowMaker.h"
 
9
#include "window.h"
 
10
#include "dock.h"
 
11
#include "xdnd.h"
 
12
#include "motif.h"
 
13
 
 
14
#include "workspace.h"
 
15
 
 
16
#include <stdlib.h>
 
17
#include <string.h>
 
18
 
 
19
#include <X11/Xatom.h>
 
20
 
 
21
 
 
22
#define XDND_VERSION 3L
 
23
 
 
24
Atom _XA_XdndAware;
 
25
Atom _XA_XdndEnter;
 
26
Atom _XA_XdndLeave;
 
27
Atom _XA_XdndDrop;
 
28
Atom _XA_XdndPosition;
 
29
Atom _XA_XdndStatus;
 
30
Atom _XA_XdndActionCopy;
 
31
Atom _XA_XdndSelection;
 
32
Atom _XA_XdndFinished;
 
33
Atom _XA_WINDOWMAKER_XDNDEXCHANGE;
 
34
 
 
35
/*
 
36
 Atom _XA_MOTIF_DRAG_RECEIVER_INFO;
 
37
 Atom _XA_MOTIF_DRAG_AND_DROP_MESSAGE;
 
38
 */
 
39
 
 
40
Atom atom_support;
 
41
 
 
42
void
 
43
wXDNDInitializeAtoms()
 
44
{
 
45
 
 
46
    _XA_XdndAware = XInternAtom(dpy, "XdndAware", False);
 
47
    _XA_XdndEnter = XInternAtom(dpy, "XdndEnter", False);
 
48
    _XA_XdndLeave = XInternAtom(dpy, "XdndLeave", False);
 
49
    _XA_XdndDrop = XInternAtom(dpy, "XdndDrop", False);
 
50
    _XA_XdndPosition = XInternAtom(dpy, "XdndPosition", False);
 
51
    _XA_XdndStatus = XInternAtom(dpy, "XdndStatus", False);
 
52
    _XA_XdndActionCopy = XInternAtom(dpy, "XdndActionCopy", False);
 
53
    _XA_XdndSelection = XInternAtom(dpy, "XdndSelection", False);
 
54
    _XA_XdndFinished = XInternAtom(dpy, "XdndFinished", False);
 
55
 
 
56
    _XA_WINDOWMAKER_XDNDEXCHANGE = XInternAtom(dpy, "_WINDOWMAKER_XDNDEXCHANGE", False);
 
57
 
 
58
    /*
 
59
     _XA_MOTIF_DRAG_RECEIVER_INFO = XInternAtom(dpy, "_MOTIF_DRAG_RECEIVER_INFO",False);
 
60
     _XA_MOTIF_DRAG_AND_DROP_MESSAGE = XInternAtom(dpy, "_MOTIF_DRAG_AND_DROP_MESSAGE", False);
 
61
     */
 
62
}
 
63
 
 
64
void
 
65
wXDNDMakeAwareness(Window window)
 
66
{
 
67
    long int xdnd_version = 3;
 
68
    /*
 
69
     MotifDragReceiverInfo info;
 
70
     */
 
71
    XChangeProperty (dpy, window, _XA_XdndAware, XA_ATOM,
 
72
                     32, PropModeAppend, (char *)&xdnd_version, 1);
 
73
 
 
74
    /*** MOTIF ***
 
75
     info.byte_order = '\0';
 
76
     info.protocol_version = 0;
 
77
     info.protocol_style = XmDRAG_DYNAMIC;
 
78
     info.proxy_window = 0;
 
79
     info.num_drop_sites = 0;
 
80
     info.total_size = sizeof(info);
 
81
 
 
82
     XChangeProperty (dpy, window,
 
83
     _XA_MOTIF_DRAG_RECEIVER_INFO,
 
84
     _XA_MOTIF_DRAG_RECEIVER_INFO,
 
85
     8, PropModeReplace,
 
86
     (unsigned char *)&info,
 
87
     sizeof (info));
 
88
     */
 
89
}
 
90
 
 
91
void
 
92
wXDNDClearAwareness(Window window)
 
93
{
 
94
    XDeleteProperty (dpy, window, _XA_XdndAware);
 
95
}
 
96
 
 
97
Bool
 
98
wXDNDProcessSelection(XEvent *event)
 
99
{
 
100
    WScreen *scr = wScreenForWindow(event->xselection.requestor);
 
101
    char *retain;
 
102
    Atom ret_type;
 
103
    int ret_format;
 
104
    unsigned long ret_item;
 
105
    unsigned long remain_byte;
 
106
    char * delme;
 
107
    XEvent xevent;
 
108
    Window selowner = XGetSelectionOwner(dpy,_XA_XdndSelection);
 
109
    WMArray *items;
 
110
 
 
111
 
 
112
    XGetWindowProperty(dpy, event->xselection.requestor,
 
113
                       _XA_WINDOWMAKER_XDNDEXCHANGE,
 
114
                       0, 65536, True, atom_support, &ret_type, &ret_format,
 
115
                       &ret_item, &remain_byte, (unsigned char **)&delme);
 
116
    if (delme){
 
117
        scr->xdestring=delme;
 
118
    }
 
119
 
 
120
    /*send finished*/
 
121
    memset (&xevent, 0, sizeof(xevent));
 
122
    xevent.xany.type = ClientMessage;
 
123
    xevent.xany.display = dpy;
 
124
    xevent.xclient.window = selowner;
 
125
    xevent.xclient.message_type = _XA_XdndFinished;
 
126
    xevent.xclient.format = 32;
 
127
    XDND_FINISHED_TARGET_WIN(&xevent) = event->xselection.requestor;
 
128
    XSendEvent(dpy, selowner, 0, 0, &xevent);
 
129
 
 
130
    /*process dropping*/
 
131
    if (scr->xdestring) {
 
132
        WMArrayIterator iter;
 
133
        int length, str_size;
 
134
        int total_size = 0;
 
135
        char *tmp;
 
136
 
 
137
        items = WMCreateArray(4);
 
138
        retain = wstrdup(scr->xdestring);
 
139
        XFree(scr->xdestring); /* since xdestring was created by Xlib */
 
140
 
 
141
        length = strlen(retain);
 
142
 
 
143
        /* search in string */
 
144
        while (length--) {
 
145
            if (retain[length] == '\r') { /* useless char, nuke it */
 
146
                retain[length] = 0;
 
147
            }
 
148
            if (retain[length] == '\n') {
 
149
                str_size = strlen(&retain[length + 1]);
 
150
                if(str_size) {
 
151
                    WMAddToArray(items, wstrdup(&retain[length + 1]));
 
152
                    total_size += str_size + 3; /* reserve for " \"\"" */
 
153
                    /* this is nonsense -- if (length)
 
154
                     WMAppendArray(items, WMCreateArray(1));*/
 
155
                }
 
156
                retain[length] = 0;
 
157
            }
 
158
        }
 
159
        /* final one */
 
160
        WMAddToArray(items, wstrdup(retain));
 
161
        total_size += strlen(retain) + 3;
 
162
        wfree(retain);
 
163
 
 
164
        /* now pack new string */
 
165
        scr->xdestring = wmalloc(total_size);
 
166
        scr->xdestring[0]=0; /* empty string */
 
167
        WM_ETARETI_ARRAY(items, tmp, iter) {
 
168
            if (!strncmp(tmp,"file:",5)) {
 
169
                /* add more 2 chars while removing 5 is harmless */
 
170
                strcat(scr->xdestring, " \"");
 
171
                strcat(scr->xdestring, &tmp[5]);
 
172
                strcat(scr->xdestring, "\"");
 
173
            } else {
 
174
                /* unsupport object, still need more " ? tell ]d */
 
175
                strcat(scr->xdestring, &tmp[5]);
 
176
            }
 
177
            wfree(tmp);
 
178
        }
 
179
        WMFreeArray(items);
 
180
        wDockReceiveDNDDrop(scr,event);
 
181
        /*
 
182
         printf("free ");
 
183
         puts(scr->xdestring);
 
184
         */
 
185
        wfree(scr->xdestring); /* this xdestring is not from Xlib (no XFree) */
 
186
    }
 
187
 
 
188
    /* why doesn't this function return anything ? -Dan */
 
189
}
 
190
 
 
191
Bool
 
192
isAwareXDND(Window window)
 
193
{
 
194
    Atom actual;
 
195
    int format;
 
196
    unsigned long count, remaining;
 
197
    unsigned char *data=0;
 
198
 
 
199
    if (!window) return False;
 
200
    XGetWindowProperty (dpy, window, _XA_XdndAware,
 
201
                        0, 0x8000000L, False, XA_ATOM,
 
202
                        &actual, &format,
 
203
                        &count, &remaining, &data);
 
204
    if (actual != XA_ATOM || format != 32 || count == 0 || !data) {
 
205
        if (data)
 
206
            XFree (data);
 
207
        return False;
 
208
    }
 
209
    if (data)
 
210
        XFree (data);
 
211
    return True;
 
212
}
 
213
 
 
214
Bool
 
215
acceptXDND(Window window)
 
216
{
 
217
    WScreen *scr = wScreenForWindow(window);
 
218
    WDock *dock;
 
219
    int icon_pos,i;
 
220
 
 
221
    icon_pos = -1;
 
222
    if ((dock = scr->dock)!=NULL) {
 
223
        for (i=0; i<dock->max_icons; i++) {
 
224
            if (dock->icon_array[i]
 
225
                && dock->icon_array[i]->icon->core->window==window) {
 
226
                icon_pos = i;
 
227
                break;
 
228
            }
 
229
        }
 
230
    }
 
231
    if (icon_pos<0 && (dock = scr->workspaces[scr->current_workspace]->clip)!=NULL) {
 
232
        for (i=0; i<dock->max_icons; i++) {
 
233
            if (dock->icon_array[i]
 
234
                && dock->icon_array[i]->icon->core->window==window) {
 
235
                icon_pos = i;
 
236
                break;
 
237
            }
 
238
        }
 
239
    }
 
240
    if (icon_pos<0) return False;
 
241
    if (!dock) return False;
 
242
    if (isAwareXDND(dock->icon_array[icon_pos]->icon->icon_win)) return False;
 
243
 
 
244
    if (dock->icon_array[icon_pos]->dnd_command!=NULL) return True;
 
245
 
 
246
    return False;
 
247
}
 
248
 
 
249
Bool
 
250
wXDNDProcessClientMessage(XClientMessageEvent *event)
 
251
{
 
252
    /* test */
 
253
    {
 
254
        char * name = XGetAtomName(dpy, event->message_type);
 
255
        /*
 
256
         printf("Get %s\n",name);
 
257
         */
 
258
        XFree(name);
 
259
    }
 
260
 
 
261
    /*
 
262
     if (event->message_type == _XA_MOTIF_DRAG_AND_DROP_MESSAGE) {
 
263
     printf("motif dnd msg %d\n",event->data.b[0]);
 
264
     if (event->data.b[0] == XmDROP_START){
 
265
     unsigned x_root, y_root, flags;
 
266
     unsigned char reason;
 
267
     unsigned long timestamp;
 
268
     Atom atom;
 
269
     Window source_window;
 
270
     MotifDragInitiatorInfo *initiator_info;
 
271
     Atom ret_type;
 
272
     int ret_format;
 
273
     unsigned long ret_item;
 
274
     unsigned long remain_byte;
 
275
 
 
276
     reason = event->data.b[0];
 
277
     flags = event->data.s[1];
 
278
     timestamp = event->data.l[1];
 
279
     x_root = event->data.s[4];
 
280
     y_root = event->data.s[5];
 
281
     atom = event->data.l[3];
 
282
     source_window = event->data.l[4];
 
283
 
 
284
     XGetWindowProperty(dpy, source_window, atom,
 
285
     0, sizeof(*initiator_info), True, atom_support,
 
286
     &ret_type, &ret_format,
 
287
     &ret_item, &remain_byte, (unsigned char **)&initiator_info);
 
288
     }
 
289
     }
 
290
     else */
 
291
    if (event->message_type == _XA_XdndEnter) {
 
292
        if ((event->data.l[1] & 1) == 0){
 
293
            atom_support = event->data.l[2];
 
294
        }
 
295
        /*
 
296
         else puts("enter more than 3 types");
 
297
         */
 
298
        return True;
 
299
    } else if (event->message_type == _XA_XdndLeave) {
 
300
        return True;
 
301
    } else if (event->message_type == _XA_XdndDrop) {
 
302
        if (event->data.l[0] == XGetSelectionOwner(dpy, _XA_XdndSelection)){
 
303
            XConvertSelection(dpy, _XA_XdndSelection, atom_support,
 
304
                              _XA_WINDOWMAKER_XDNDEXCHANGE, event->window, CurrentTime);
 
305
        }
 
306
        else {
 
307
            puts("wierd selection owner? QT?");
 
308
            XConvertSelection(dpy, _XA_XdndSelection, atom_support,
 
309
                              _XA_WINDOWMAKER_XDNDEXCHANGE, event->window, CurrentTime);
 
310
        }
 
311
        return True;
 
312
    } else if (event->message_type == _XA_XdndPosition) {
 
313
        XEvent xevent;
 
314
        Window srcwin = event->data.l[0];
 
315
        if (atom_support != XInternAtom(dpy, "text/uri-list", False)) {
 
316
            return True;
 
317
        }
 
318
        {
 
319
            memset (&xevent, 0, sizeof(xevent));
 
320
            xevent.xany.type = ClientMessage;
 
321
            xevent.xany.display = dpy;
 
322
            xevent.xclient.window = srcwin;
 
323
            xevent.xclient.message_type = _XA_XdndStatus;
 
324
            xevent.xclient.format = 32;
 
325
 
 
326
            XDND_STATUS_TARGET_WIN (&xevent) = event->window;
 
327
            XDND_STATUS_WILL_ACCEPT_SET (&xevent, acceptXDND(event->window));
 
328
            XDND_STATUS_WANT_POSITION_SET(&xevent, True);
 
329
            XDND_STATUS_RECT_SET(&xevent, 0, 0, 1024,768);
 
330
            XDND_STATUS_ACTION(&xevent) = _XA_XdndActionCopy;
 
331
 
 
332
            XSendEvent(dpy, srcwin, 0, 0, &xevent);
 
333
        }
 
334
        return True;
 
335
    }
 
336
    return False;
 
337
}
 
338
 
 
339
#endif
 
340