2 This is a modified DND 1.0 library which does not depend on Xt
4 Modifications Copyright (c) 1997 Oliver Graf <ograf@fga.de>
7 Copyright (C) 1996 César Crusius
9 This file is part of the DND Library. This library is free
10 software; you can redistribute it and/or modify it under the terms of
11 the GNU Library General Public License as published by the Free
12 Software Foundation; either version 2 of the License, or (at your
13 option) any later version. This library is distributed in the hope
14 that it will be useful, but WITHOUT ANY WARRANTY; without even the
15 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 PURPOSE. See the GNU Library General Public License for more details.
17 You should have received a copy of the GNU Library General Public
18 License along with this library; if not, write to the Free Software
19 Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "ui/X11/offix.h"
25 #include <X11/cursorfont.h>
26 #include <X11/Xatom.h>
27 #include <X11/Xmu/WinUtil.h>
33 static Display *dpy; /* current display */
34 static int DragPrecision; /* minimum dx,dy to start drag */
35 static int Dragging; /* Drag state flag */
36 static int DataOK; /* Non-zero if data registered */
37 static Atom DndProtocol; /* ClientMessage identifier */
38 static Atom DndSelection; /* For the data transfers */
39 static Atom OldDndProtocol; /* Version 0 atom */
40 static Atom OldDndSelection; /* Version 0 atom */
41 static Atom WM_STATE; /* Needed for icon stuff */
42 static Window Target; /* Drop window */
43 static Widget MainWidget; /* Main widget of application */
44 static int DataType; /* Current drag data type */
45 static int RootFlag; /* Non-zero if dropped on root */
46 static XColor Black, White; /* For the cursors */
48 /*=========================================================================
49 * Data for the standard Dnd cursors
50 *=========================================================================*/
51 #include "ui/X11/offix-cursors.h"
53 /*=============================================================== CursorData
54 * CursorData contains all the data for the cursors bitmaps
55 *==========================================================================*/
58 unsigned char *ImageData, *MaskData;
59 int HotSpotX, HotSpotY;
60 Pixmap ImagePixmap, MaskPixmap;
64 static CursorData DndCursor[DndEND] = {
65 {0, 0, NULL, NULL, 0, 0, 0},
66 {grey_width, grey_height, grey_bits, grey_mask_bits,
67 grey_x_hot, grey_y_hot},
68 {file_width, file_height, file_bits, file_mask_bits,
69 file_x_hot, file_y_hot},
70 {files_width, files_height, files_bits, files_mask_bits,
71 files_x_hot, files_y_hot},
72 {text_width, text_height, text_bits, text_mask_bits,
73 text_x_hot, text_y_hot},
74 {dir_width, dir_height, dir_bits, dir_mask_bits,
75 dir_x_hot, dir_y_hot},
76 {link_width, link_height, link_bits, link_mask_bits,
77 link_x_hot, link_y_hot},
78 {app_width, app_height, app_bits, app_mask_bits,
79 app_x_hot, app_y_hot},
80 {url_width, url_height, url_bits, url_mask_bits,
81 url_x_hot, url_y_hot},
82 {mime_width, mime_height, mime_bits, mime_mask_bits,
83 mime_x_hot, mime_y_hot}
86 /* Local prototypes */
87 int DndIsDragging(void);
88 void DndStartAction(Widget widget, XtPointer data, XEvent * event, Boolean * p);
89 void DndPropertyHandler(Widget widget,
90 XtPointer data, XEvent * event, Boolean * p);
92 /*======================================================== DndHandleDragging
93 * Takes care of the drag and drop process. Wait until the pointer had moved
94 * a little. Then takes control over the pointer until the buttons are
95 * released. After that send a Drag And Drop ClientMessage event. Returns
96 * non-zero if a drop did take place.
97 *===========================================================================*/
98 int DndHandleDragging(Widget widget, XEvent * event)
101 Window root = RootWindowOfScreen(XtScreenOfObject(widget));
102 XtAppContext app = XtWidgetToApplicationContext(widget);
103 Window DispatchWindow;
109 XUngrabPointer(dpy, CurrentTime);
110 /* Take control over the pointer */
111 XGrabPointer(dpy, root, False,
112 ButtonMotionMask | ButtonPressMask | ButtonReleaseMask,
113 GrabModeSync, GrabModeAsync, root,
114 DndCursor[DataType].CursorID, CurrentTime);
116 /* Wait for button release */
120 XAllowEvents(dpy, SyncPointer, CurrentTime);
121 XtAppNextEvent(app, &Event);
122 switch (Event.type) {
124 if (Event.xbutton.subwindow)
131 XtDispatchEvent(&Event);
136 /* Now release the pointer */
137 XUngrabPointer(dpy, CurrentTime);
138 /* Try to guess if the drop occurred in the root window */
140 Target = XmuClientWindow(dpy, Event.xbutton.subwindow);
141 if (Target == Event.xbutton.subwindow)
142 DispatchWindow = Target;
144 DispatchWindow = PointerWindow;
146 Target = DispatchWindow = XtWindow(MainWidget);
148 /* Now build the event structure */
149 DropX = Event.xbutton.x_root;
150 DropY = Event.xbutton.y_root;
151 Event.xclient.type = ClientMessage;
152 Event.xclient.display = dpy;
153 Event.xclient.message_type = DndProtocol;
154 Event.xclient.format = 32;
155 Event.xclient.window = Target;
156 Event.xclient.data.l[0] = DataType;
157 Event.xclient.data.l[1] = (long)event->xbutton.state;
158 Event.xclient.data.l[2] = (long)XtWindow(widget);
159 Event.xclient.data.l[3] = DropX + 65536L * (long)DropY;
160 Event.xclient.data.l[4] = 1;
162 /* Send the drop message */
163 XSendEvent(dpy, DispatchWindow, True, NoEventMask, &Event);
164 /* Send an old style version of the message just in case */
165 Event.xclient.message_type = OldDndProtocol;
166 XSendEvent(dpy, DispatchWindow, True, NoEventMask, &Event);
169 fprintf(stderr, "ClientMessage sent to 0x%x(0x%x).\n",
170 DispatchWindow, Target);
171 fprintf(stderr, "The drop coordinates are (%d,%d).\n", DropX, DropY);
177 /*=============================================================== DndIsIcon
178 * Return non-zero if the application is iconic (widget=toplevel)
179 *========================================================================*/
180 int DndIsIcon(Widget widget)
184 unsigned long WinState, JunkLong;
185 unsigned char *Property;
187 XGetWindowProperty(dpy, XtWindow(widget), WM_STATE,
188 0L, 2L, False, AnyPropertyType,
189 &JunkAtom, &JunkInt, &WinState, &JunkLong,
191 WinState = (unsigned long)(*((long *)Property));
192 return (WinState == 3);
195 /*============================================================ DndInitialize
196 * Must be called anywhere before the top level widget creation and the