2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $TOG: demo.c /main/5 1999/07/20 14:48:53 mgreess $ */
24 /*****************************************************************************
25 *****************************************************************************
29 ** Description: The Drag & Drop Demo program demonstrates the
30 ** CDE DnD functions in the Desktop Services library:
33 ** DtDndDropRegister.3x
34 ** DtDndCreateSourceIcon.3x
36 ** The demo consists of a row of three different sources
37 ** for text, filename and appointment buffer drags.
38 ** It also has a text field that can accept either
39 ** text or filename drops. Finally there is a data
40 ** area that accepts filename or buffer drops.
42 ** (c) Copyright 1993, 1994 Hewlett-Packard Company
43 ** (c) Copyright 1993, 1994 International Business Machines Corp.
44 ** (c) Copyright 1993, 1994 Sun Microsystems, Inc.
45 ** (c) Copyright 1993, 1994 Unix System Labs, Inc., a subsidiary of
48 ****************************************************************************
49 ************************************<+>*************************************/
56 #include <X11/Intrinsic.h>
59 #include <Xm/DrawingA.h>
63 #include <Xm/MwmUtil.h>
64 #include <Xm/RowColumn.h>
65 #include <Xm/Separator.h>
66 #include <Xm/DragDrop.h>
67 #include <Xm/Screen.h>
77 /*************************************************************************
79 * Data Structures & Declarations For Drag & Drop Demo
81 *************************************************************************/
84 * The Drag Threshold is the distance, measured in pixels, over which the
85 * pointer must travel while the BSelect button (first mouse button) is held
86 * down in order to start a drag. CDE defines this to be 10 pixels.
89 #define DRAG_THRESHOLD 10
92 * Absolute value macro
96 #define ABS(x) (((x) > 0) ? (x) : (-(x)))
104 XtAppContext demoAppContext;
105 Boolean demoDoingDrag = False;
108 * Private Drag & Drop Demo Function Declarations
111 void demoTransferCallback(Widget, XtPointer, XtPointer);
113 /*************************************************************************
115 * General-Purpose Drag & Drop Functions
117 *************************************************************************/
120 * demoDragFinishCallback
122 * Resets drag state to indicate the drag is over.
125 demoDragFinishCallback(
127 XtPointer clientData,
130 demoDoingDrag = False;
134 * demoDragMotionHandler
136 * Determine if the pointer has moved beyond the drag threshold while button 1
137 * was being held down.
140 demoDragMotionHandler(
141 Widget dragInitiator,
142 XtPointer clientData,
145 static int initialX = -1;
146 static int initialY = -1;
148 long dragProtocol = (long)clientData;
150 if (!demoDoingDrag) {
153 * If the drag is just starting, set initial button down coords
156 if (initialX == -1 && initialY == -1) {
157 initialX = event->xmotion.x;
158 initialY = event->xmotion.y;
162 * Find out how far pointer has moved since button press
165 diffX = initialX - event->xmotion.x;
166 diffY = initialY - event->xmotion.y;
168 if ((ABS(diffX) >= DRAG_THRESHOLD) ||
169 (ABS(diffY) >= DRAG_THRESHOLD)) {
170 demoDoingDrag = True;
171 switch (dragProtocol) {
172 case DtDND_TEXT_TRANSFER:
173 textDragStart(dragInitiator, event);
175 case DtDND_FILENAME_TRANSFER:
176 fileCheckForDrag(dragInitiator, event,
179 case DtDND_BUFFER_TRANSFER:
180 apptDragStart(dragInitiator, event);
194 static Bool demoLookForButton(Display *d, XEvent *event, XPointer arg)
197 #define ABS_DELTA(x1, x2) (x1 < x2 ? x2 - x1 : x1 - x2)
199 if( event->type == MotionNotify)
201 XEvent * press = (XEvent *) arg;
203 if (ABS_DELTA(press->xbutton.x_root, event->xmotion.x_root) > DAMPING ||
204 ABS_DELTA(press->xbutton.y_root, event->xmotion.y_root) > DAMPING)
207 else if (event->type == ButtonRelease) return(True);
216 void demoProcessPress(Widget w, XEvent *event, String *parms, Cardinal *nparms)
218 #define SELECTION_ACTION 0
219 #define TRANSFER_ACTION 1
221 int i, action, cur_item;
222 int *selected_positions, nselected_positions;
225 * This action happens when Button1 is pressed and the Selection
226 * and Transfer are integrated on Button1. It is passed two
227 * parameters: the action to call when the event is a selection,
228 * and the action to call when the event is a transfer.
231 if (*nparms != 2 || !XmIsList(w)) return;
233 action = SELECTION_ACTION;
234 cur_item = XmListYToPos(w, event->xbutton.y);
238 XmNselectedPositions, &selected_positions,
239 XmNselectedPositionCount, &nselected_positions,
242 for (i=0; i<nselected_positions; i++)
244 if (cur_item == selected_positions[i])
247 * The determination of whether this is a transfer drag
248 * cannot be made until a Motion event comes in. It is
249 * not a drag as soon as a ButtonUp event happens.
258 switch (new_event.type)
261 action = TRANSFER_ACTION;
264 action = SELECTION_ACTION;
272 XtCallActionProc(w, parms[action], event, parms, *nparms);
276 * demoDrawAnimateCallback
278 * Expands the icon melted into the draw area by Motif.
281 demoDrawAnimateCallback(
282 Widget dragContext, /* WARNING: This is being destroyed. */
283 XtPointer clientData,
286 DtDndDropAnimateCallbackStruct *animateInfo =
287 (DtDndDropAnimateCallbackStruct *) callData;
288 Widget dropDraw = (Widget)clientData;
289 Display *display = XtDisplayOfObject(dropDraw);
290 Screen *screen = XtScreen(dropDraw);
291 Window window = XtWindow(dropDraw);
292 int expandWidth, expandHeight,
294 static GC graphicsContext = NULL;
299 * Create graphics context if it doesn't yet exist
302 if (graphicsContext == NULL) {
303 gcValues.foreground = BlackPixelOfScreen(screen);
304 gcValues.background = WhitePixelOfScreen(screen);
305 graphicsContext = XCreateGC(display, window,
306 GCForeground | GCBackground, &gcValues);
310 * Get the dragged icon from the dropDraw area
313 XtVaGetValues(dropDraw, XmNuserData, &iconPtr, NULL);
315 if (iconPtr == NULL) {
320 * Set clip mask and coordinates for this icon in the graphics context
323 gcValues.clip_mask = iconPtr->mask;
324 gcValues.clip_x_origin = iconPtr->icon.x;
325 gcValues.clip_y_origin = iconPtr->icon.y;
326 XChangeGC(display, graphicsContext,
327 GCClipMask | GCClipXOrigin | GCClipYOrigin,
331 * Reconstitute the icon after Motif melts it
334 for (expandWidth = expandHeight = 0;
335 expandWidth < (int)iconPtr->icon.width &&
336 expandHeight < (int)iconPtr->icon.height;
337 expandWidth += 2, expandHeight += 2) {
339 sourceX = ((int)iconPtr->icon.width - expandWidth)/2;
340 sourceY = ((int)iconPtr->icon.height - expandHeight)/2;
342 XCopyPlane(display, iconPtr->bitmap, window, graphicsContext,
343 sourceX, sourceY, expandWidth, expandHeight,
344 iconPtr->icon.x + sourceX, iconPtr->icon.y + sourceY,
347 XmeMicroSleep(25000L);
353 * demoDrawExposeCallback
355 * Draws all the icons associated with the drawing area.
358 demoDrawExposeCallback(
360 XtPointer clientData,
365 XtVaGetValues(widget, XmNuserData, &iconPtr, NULL);
367 while (iconPtr != NULL) {
368 IconDraw(widget, iconPtr);
369 iconPtr = iconPtr->next;
376 * Registers draw area to accept drops of files or buffers such as appointments.
382 static XtCallbackRec transferCBRec[] = { {demoTransferCallback, NULL},
384 static XtCallbackRec animateCBRec[] = { {demoDrawAnimateCallback, NULL},
387 animateCBRec[0].closure = (XtPointer)dropDraw;
389 DtDndVaDropRegister(dropDraw,
390 DtDND_FILENAME_TRANSFER | DtDND_BUFFER_TRANSFER,
391 XmDROP_COPY | XmDROP_MOVE, transferCBRec,
392 DtNdropAnimateCallback, animateCBRec,
393 DtNtextIsBuffer, True,
394 DtNpreserveRegistration, False,
399 * demoTransferCallback
401 * Called when something is dropped on the drawing area drop site. If the
402 * transfer protocol is DtDND_FILENAME_TRANSFER or DtDND_BUFFER_TRANSFER
403 * the fileTransferCallback and apptTransferCallback are called respectively.
406 demoTransferCallback(
408 XtPointer clientData,
411 DtDndTransferCallbackStruct *transferInfo =
412 (DtDndTransferCallbackStruct *) callData;
414 if (transferInfo == NULL) {
418 switch (transferInfo->dropData->protocol) {
420 case DtDND_FILENAME_TRANSFER:
421 fileTransferCallback(widget, clientData, callData);
423 case DtDND_BUFFER_TRANSFER:
424 apptTransferCallback(widget, clientData, callData);
429 /*************************************************************************
431 * Demo Client Creation
433 *************************************************************************/
436 * Fallback resources are used if app-defaults file is not found
439 String fallbackResources[] = {
440 "title: CDE Drag & Drop Demo",
442 "*outerRowColumn.orientation: VERTICAL",
443 "*outerRowColumn.spacing: 15",
444 "*outerRowColumn.marginHeight: 15",
445 "*outerRowColumn.marginWidth: 15",
447 "*upperRowColumn.orientation: HORIZONTAL",
448 "*upperRowColumn.packing: PACK_COLUMN",
449 "*upperRowColumn.spacing: 15",
450 "*upperRowColumn.marginHeight: 0",
451 "*upperRowColumn.marginWidth: 0",
453 "*fileDraw.height: 175",
454 "*fileDraw.resizePolicy: RESIZE_NONE",
456 "*fruitList.listSizePolicy: CONSTANT",
457 "*fruitList.scrollBarDisplayPolicy: STATIC",
458 "*fruitList.selectionPolicy: MULTIPLE_SELECT",
460 "*apptList.listSizePolicy: CONSTANT",
461 "*apptList.scrollBarDisplayPolicy: STATIC",
462 "*apptList.selectionPolicy: MULTIPLE_SELECT",
464 "*textRowColumn.orientation: HORIZONTAL",
465 "*textRowColumn.packing: PACK_TIGHT",
466 "*textRowColumn*textLabel.labelString: Name:",
467 "*textRowColumn*textField.width: 550",
468 "*textRowColumn.marginWidth: 0",
470 "*dropDraw.height: 100",
471 "*dropDraw.resizePolicy: RESIZE_NONE",
478 * Creates the drawing area at the bottom of the demo which is used as a drop
479 * site for files and appointments.
488 dropFrame = XtVaCreateManagedWidget("dropFrame",
489 xmFrameWidgetClass, parent,
492 dropDraw = XtVaCreateManagedWidget("dropDraw",
493 xmDrawingAreaWidgetClass, dropFrame,
496 XtAddCallback(dropDraw,
497 XmNexposeCallback, demoDrawExposeCallback,
506 * Create widgets for the demo program. Call protocol-specific functions
507 * to initialize the drag sources and drop sites.
514 Widget outerRowColumn,
524 * Create basic widgets and layout widgets
527 XtSetLanguageProc(NULL, NULL, NULL);
529 demoTopLevel = XtAppInitialize(&demoAppContext, "Dtdnddemo",
530 (XrmOptionDescList)NULL, 0, &argc, argv,
531 fallbackResources, (ArgList)NULL, 0);
533 DtAppInitialize(demoAppContext, XtDisplay(demoTopLevel),
534 demoTopLevel, argv[0], "Dtdnddemo");
536 outerRowColumn = XtVaCreateManagedWidget("outerRowColumn",
537 xmRowColumnWidgetClass, demoTopLevel,
540 upperRowColumn = XtVaCreateManagedWidget("upperRowColumn",
541 xmRowColumnWidgetClass, outerRowColumn,
545 * Create the drag sources
548 textDragSource = textCreateDragSource(upperRowColumn);
549 fileDragSource = fileCreateDragSource(upperRowColumn);
550 apptDragSource = apptCreateDragSource(upperRowColumn);
553 * Create a line separating the drag sources from the drop sites
556 separator = XtVaCreateManagedWidget("separator",
557 xmSeparatorWidgetClass, outerRowColumn,
561 * Create the drop sites
564 textDropSite = textCreateDropSite(outerRowColumn);
565 drawDropSite = demoCreateDropSite(outerRowColumn);
568 * Realize the widget tree
571 XtRealizeWidget(demoTopLevel);
574 * Load the data typing database which is used to get icons
577 DtDtsLoadDataTypes();
580 * Set up the drag sources
583 textDragSetup(textDragSource);
584 fileDragSetup(fileDragSource);
585 apptDragSetup(apptDragSource);
588 * Set up the drop sites
591 textDropSetup(textDropSite);
592 demoDropSetup(drawDropSite);
595 * Start the event processing loop
598 XtAppMainLoop(demoAppContext);