chore, bldchn, remove dump file upon make uninstall
[sxemacs] / src / offix.c
1 /*
2 This is a modified DND 1.0 library which does not depend on Xt
3 event handling.
4 Modifications Copyright (c) 1997 Oliver Graf <ograf@fga.de>
5
6 Original DND lib
7 Copyright (C) 1996 César Crusius
8
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.
20 */
21
22 /* #define DEBUG */
23
24 #include "ui/X11/offix.h"
25 #include <X11/cursorfont.h>
26 #include <X11/Xatom.h>
27 #include <X11/Xmu/WinUtil.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <limits.h>
31
32 /* Local variables */
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              */
47
48 /*=========================================================================
49  * Data for the standard Dnd cursors
50  *=========================================================================*/
51 #include "ui/X11/offix-cursors.h"
52
53 /*=============================================================== CursorData
54  * CursorData contains all the data for the cursors bitmaps
55  *==========================================================================*/
56 typedef struct {
57         int Width, Height;
58         unsigned char *ImageData, *MaskData;
59         int HotSpotX, HotSpotY;
60         Pixmap ImagePixmap, MaskPixmap;
61         Cursor CursorID;
62 } CursorData;
63
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}
84 };
85
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);
91
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)
99 {
100         XEvent Event;
101         Window root = RootWindowOfScreen(XtScreenOfObject(widget));
102         XtAppContext app = XtWidgetToApplicationContext(widget);
103         Window DispatchWindow;
104         int DropX, DropY;
105
106         if (Dragging)
107                 return 0;
108
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);
115
116         /* Wait for button release */
117         Dragging = 1;
118         RootFlag = 0;
119         while (Dragging) {
120                 XAllowEvents(dpy, SyncPointer, CurrentTime);
121                 XtAppNextEvent(app, &Event);
122                 switch (Event.type) {
123                 case ButtonRelease:
124                         if (Event.xbutton.subwindow)
125                                 RootFlag = 0;
126                         else
127                                 RootFlag = 1;
128                         Dragging = 0;
129                         break;
130                 default:
131                         XtDispatchEvent(&Event);
132                         break;
133                 }
134         }
135         DataOK = 0;
136         /* Now release the pointer */
137         XUngrabPointer(dpy, CurrentTime);
138         /* Try to guess if the drop occurred in the root window */
139         if (!RootFlag) {
140                 Target = XmuClientWindow(dpy, Event.xbutton.subwindow);
141                 if (Target == Event.xbutton.subwindow)
142                         DispatchWindow = Target;
143                 else
144                         DispatchWindow = PointerWindow;
145         } else
146                 Target = DispatchWindow = XtWindow(MainWidget);
147
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;
161
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);
167
168 #ifdef DEBUG
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);
172 #endif
173
174         return 1;
175 }
176
177 /*=============================================================== DndIsIcon
178  * Return non-zero if the application is iconic (widget=toplevel)
179  *========================================================================*/
180 int DndIsIcon(Widget widget)
181 {
182         Atom JunkAtom;
183         int JunkInt;
184         unsigned long WinState, JunkLong;
185         unsigned char *Property;
186
187         XGetWindowProperty(dpy, XtWindow(widget), WM_STATE,
188                            0L, 2L, False, AnyPropertyType,
189                            &JunkAtom, &JunkInt, &WinState, &JunkLong,
190                            &Property);
191         WinState = (unsigned long)(*((long *)Property));
192         return (WinState == 3);
193 }
194
195 /*============================================================ DndInitialize
196  * Must be called anywhere before the top level widget creation and the