demo.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  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)
  10. * any later version.
  11. *
  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
  16. * details.
  17. *
  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
  22. */
  23. /* $TOG: demo.c /main/5 1999/07/20 14:48:53 mgreess $ */
  24. /*****************************************************************************
  25. *****************************************************************************
  26. **
  27. ** File: demo.c
  28. **
  29. ** Description: The Drag & Drop Demo program demonstrates the
  30. ** CDE DnD functions in the Desktop Services library:
  31. **
  32. ** DtDndDragStart.3x
  33. ** DtDndDropRegister.3x
  34. ** DtDndCreateSourceIcon.3x
  35. **
  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.
  41. **
  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
  46. ** Novell, Inc.
  47. **
  48. ****************************************************************************
  49. ************************************<+>*************************************/
  50. #include <stdlib.h>
  51. #include <stdio.h>
  52. #include <unistd.h>
  53. #include <time.h>
  54. #include <X11/Intrinsic.h>
  55. #include <Xm/Xm.h>
  56. #include <Xm/DrawingA.h>
  57. #include <Xm/Frame.h>
  58. #include <Xm/List.h>
  59. #include <Xm/MainW.h>
  60. #include <Xm/MwmUtil.h>
  61. #include <Xm/RowColumn.h>
  62. #include <Xm/Separator.h>
  63. #include <Xm/DragDrop.h>
  64. #include <Xm/Screen.h>
  65. #include <Dt/Dt.h>
  66. #include <Dt/Dnd.h>
  67. #include "icon.h"
  68. #include "text.h"
  69. #include "file.h"
  70. #include "buff.h"
  71. /*************************************************************************
  72. *
  73. * Data Structures & Declarations For Drag & Drop Demo
  74. *
  75. *************************************************************************/
  76. /*
  77. * The Drag Threshold is the distance, measured in pixels, over which the
  78. * pointer must travel while the BSelect button (first mouse button) is held
  79. * down in order to start a drag. CDE defines this to be 10 pixels.
  80. */
  81. #define DRAG_THRESHOLD 10
  82. /*
  83. * Absolute value macro
  84. */
  85. #ifndef ABS
  86. #define ABS(x) (((x) > 0) ? (x) : (-(x)))
  87. #endif
  88. /*
  89. * Global variables
  90. */
  91. Widget demoTopLevel;
  92. XtAppContext demoAppContext;
  93. Boolean demoDoingDrag = False;
  94. /*
  95. * Private Drag & Drop Demo Function Declarations
  96. */
  97. void demoTransferCallback(Widget, XtPointer, XtPointer);
  98. /*************************************************************************
  99. *
  100. * General-Purpose Drag & Drop Functions
  101. *
  102. *************************************************************************/
  103. /*
  104. * demoDragFinishCallback
  105. *
  106. * Resets drag state to indicate the drag is over.
  107. */
  108. void
  109. demoDragFinishCallback(
  110. Widget widget,
  111. XtPointer clientData,
  112. XtPointer callData)
  113. {
  114. demoDoingDrag = False;
  115. }
  116. /*
  117. * demoDragMotionHandler
  118. *
  119. * Determine if the pointer has moved beyond the drag threshold while button 1
  120. * was being held down.
  121. */
  122. void
  123. demoDragMotionHandler(
  124. Widget dragInitiator,
  125. XtPointer clientData,
  126. XEvent *event)
  127. {
  128. static int initialX = -1;
  129. static int initialY = -1;
  130. int diffX, diffY;
  131. long dragProtocol = (long)clientData;
  132. if (!demoDoingDrag) {
  133. /*
  134. * If the drag is just starting, set initial button down coords
  135. */
  136. if (initialX == -1 && initialY == -1) {
  137. initialX = event->xmotion.x;
  138. initialY = event->xmotion.y;
  139. }
  140. /*
  141. * Find out how far pointer has moved since button press
  142. */
  143. diffX = initialX - event->xmotion.x;
  144. diffY = initialY - event->xmotion.y;
  145. if ((ABS(diffX) >= DRAG_THRESHOLD) ||
  146. (ABS(diffY) >= DRAG_THRESHOLD)) {
  147. demoDoingDrag = True;
  148. switch (dragProtocol) {
  149. case DtDND_TEXT_TRANSFER:
  150. textDragStart(dragInitiator, event);
  151. break;
  152. case DtDND_FILENAME_TRANSFER:
  153. fileCheckForDrag(dragInitiator, event,
  154. initialX, initialY);
  155. break;
  156. case DtDND_BUFFER_TRANSFER:
  157. apptDragStart(dragInitiator, event);
  158. break;
  159. }
  160. initialX = -1;
  161. initialY = -1;
  162. }
  163. }
  164. }
  165. /*
  166. * demoLookForButton
  167. */
  168. /* ARGSUSED */
  169. static Bool demoLookForButton(Display *d, XEvent *event, XPointer arg)
  170. {
  171. #define DAMPING 5
  172. #define ABS_DELTA(x1, x2) (x1 < x2 ? x2 - x1 : x1 - x2)
  173. if( event->type == MotionNotify)
  174. {
  175. XEvent * press = (XEvent *) arg;
  176. if (ABS_DELTA(press->xbutton.x_root, event->xmotion.x_root) > DAMPING ||
  177. ABS_DELTA(press->xbutton.y_root, event->xmotion.y_root) > DAMPING)
  178. return(True);
  179. }
  180. else if (event->type == ButtonRelease) return(True);
  181. return(False);
  182. }
  183. /*
  184. * demoProcessPress
  185. */
  186. void demoProcessPress(Widget w, XEvent *event, String *parms, Cardinal *nparms)
  187. {
  188. #define SELECTION_ACTION 0
  189. #define TRANSFER_ACTION 1
  190. int i, action, cur_item;
  191. int *selected_positions, nselected_positions;
  192. /*
  193. * This action happens when Button1 is pressed and the Selection
  194. * and Transfer are integrated on Button1. It is passed two
  195. * parameters: the action to call when the event is a selection,
  196. * and the action to call when the event is a transfer.
  197. */
  198. if (*nparms != 2 || !XmIsList(w)) return;
  199. action = SELECTION_ACTION;
  200. cur_item = XmListYToPos(w, event->xbutton.y);
  201. if (cur_item > 0)
  202. {
  203. XtVaGetValues(w,
  204. XmNselectedPositions, &selected_positions,
  205. XmNselectedPositionCount, &nselected_positions,
  206. NULL);
  207. for (i=0; i<nselected_positions; i++)
  208. {
  209. if (cur_item == selected_positions[i])
  210. {
  211. /*
  212. * The determination of whether this is a transfer drag
  213. * cannot be made until a Motion event comes in. It is
  214. * not a drag as soon as a ButtonUp event happens.
  215. */
  216. XEvent new_event;
  217. XPeekIfEvent(
  218. XtDisplay(w),
  219. &new_event,
  220. &demoLookForButton,
  221. (XPointer) event);
  222. switch (new_event.type)
  223. {
  224. case MotionNotify:
  225. action = TRANSFER_ACTION;
  226. break;
  227. case ButtonRelease:
  228. action = SELECTION_ACTION;
  229. break;
  230. }
  231. break;
  232. }
  233. }
  234. }
  235. XtCallActionProc(w, parms[action], event, parms, *nparms);
  236. }
  237. /*
  238. * demoDrawAnimateCallback
  239. *
  240. * Expands the icon melted into the draw area by Motif.
  241. */
  242. void
  243. demoDrawAnimateCallback(
  244. Widget dragContext, /* WARNING: This is being destroyed. */
  245. XtPointer clientData,
  246. XtPointer callData)
  247. {
  248. DtDndDropAnimateCallbackStruct *animateInfo =
  249. (DtDndDropAnimateCallbackStruct *) callData;
  250. Widget dropDraw = (Widget)clientData;
  251. Display *display = XtDisplayOfObject(dropDraw);
  252. Screen *screen = XtScreen(dropDraw);
  253. Window window = XtWindow(dropDraw);
  254. int expandWidth, expandHeight,
  255. sourceX, sourceY;
  256. static GC graphicsContext = NULL;
  257. XGCValues gcValues;
  258. IconInfo *iconPtr;
  259. /*
  260. * Create graphics context if it doesn't yet exist
  261. */
  262. if (graphicsContext == NULL) {
  263. gcValues.foreground = BlackPixelOfScreen(screen);
  264. gcValues.background = WhitePixelOfScreen(screen);
  265. graphicsContext = XCreateGC(display, window,
  266. GCForeground | GCBackground, &gcValues);
  267. }
  268. /*
  269. * Get the dragged icon from the dropDraw area
  270. */
  271. XtVaGetValues(dropDraw, XmNuserData, &iconPtr, NULL);
  272. if (iconPtr == NULL) {
  273. return;
  274. }
  275. /*
  276. * Set clip mask and coordinates for this icon in the graphics context
  277. */
  278. gcValues.clip_mask = iconPtr->mask;
  279. gcValues.clip_x_origin = iconPtr->icon.x;
  280. gcValues.clip_y_origin = iconPtr->icon.y;
  281. XChangeGC(display, graphicsContext,
  282. GCClipMask | GCClipXOrigin | GCClipYOrigin,
  283. &gcValues);
  284. /*
  285. * Reconstitute the icon after Motif melts it
  286. */
  287. for (expandWidth = expandHeight = 0;
  288. expandWidth < (int)iconPtr->icon.width &&
  289. expandHeight < (int)iconPtr->icon.height;
  290. expandWidth += 2, expandHeight += 2) {
  291. sourceX = ((int)iconPtr->icon.width - expandWidth)/2;
  292. sourceY = ((int)iconPtr->icon.height - expandHeight)/2;
  293. XCopyPlane(display, iconPtr->bitmap, window, graphicsContext,
  294. sourceX, sourceY, expandWidth, expandHeight,
  295. iconPtr->icon.x + sourceX, iconPtr->icon.y + sourceY,
  296. 1L);
  297. XmeMicroSleep(25000L);
  298. XFlush(display);
  299. }
  300. }
  301. /*
  302. * demoDrawExposeCallback
  303. *
  304. * Draws all the icons associated with the drawing area.
  305. */
  306. void
  307. demoDrawExposeCallback(
  308. Widget widget,
  309. XtPointer clientData,
  310. XtPointer callData)
  311. {
  312. IconInfo *iconPtr;
  313. XtVaGetValues(widget, XmNuserData, &iconPtr, NULL);
  314. while (iconPtr != NULL) {
  315. IconDraw(widget, iconPtr);
  316. iconPtr = iconPtr->next;
  317. }
  318. }
  319. /*
  320. * demoDropSetup
  321. *
  322. * Registers draw area to accept drops of files or buffers such as appointments.
  323. */
  324. void
  325. demoDropSetup(
  326. Widget dropDraw)
  327. {
  328. static XtCallbackRec transferCBRec[] = { {demoTransferCallback, NULL},
  329. {NULL, NULL} };
  330. static XtCallbackRec animateCBRec[] = { {demoDrawAnimateCallback, NULL},
  331. {NULL, NULL} };
  332. animateCBRec[0].closure = (XtPointer)dropDraw;
  333. DtDndVaDropRegister(dropDraw,
  334. DtDND_FILENAME_TRANSFER | DtDND_BUFFER_TRANSFER,
  335. XmDROP_COPY | XmDROP_MOVE, transferCBRec,
  336. DtNdropAnimateCallback, animateCBRec,
  337. DtNtextIsBuffer, True,
  338. DtNpreserveRegistration, False,
  339. NULL);
  340. }
  341. /*
  342. * demoTransferCallback
  343. *
  344. * Called when something is dropped on the drawing area drop site. If the
  345. * transfer protocol is DtDND_FILENAME_TRANSFER or DtDND_BUFFER_TRANSFER
  346. * the fileTransferCallback and apptTransferCallback are called respectively.
  347. */
  348. void
  349. demoTransferCallback(
  350. Widget widget,
  351. XtPointer clientData,
  352. XtPointer callData)
  353. {
  354. DtDndTransferCallbackStruct *transferInfo =
  355. (DtDndTransferCallbackStruct *) callData;
  356. if (transferInfo == NULL) {
  357. return;
  358. }
  359. switch (transferInfo->dropData->protocol) {
  360. case DtDND_FILENAME_TRANSFER:
  361. fileTransferCallback(widget, clientData, callData);
  362. break;
  363. case DtDND_BUFFER_TRANSFER:
  364. apptTransferCallback(widget, clientData, callData);
  365. break;
  366. }
  367. }
  368. /*************************************************************************
  369. *
  370. * Demo Client Creation
  371. *
  372. *************************************************************************/
  373. /*
  374. * Fallback resources are used if app-defaults file is not found
  375. */
  376. String fallbackResources[] = {
  377. "title: CDE Drag & Drop Demo",
  378. "*outerRowColumn.orientation: VERTICAL",
  379. "*outerRowColumn.spacing: 15",
  380. "*outerRowColumn.marginHeight: 15",
  381. "*outerRowColumn.marginWidth: 15",
  382. "*upperRowColumn.orientation: HORIZONTAL",
  383. "*upperRowColumn.packing: PACK_COLUMN",
  384. "*upperRowColumn.spacing: 15",
  385. "*upperRowColumn.marginHeight: 0",
  386. "*upperRowColumn.marginWidth: 0",
  387. "*fileDraw.height: 175",
  388. "*fileDraw.resizePolicy: RESIZE_NONE",
  389. "*fruitList.listSizePolicy: CONSTANT",
  390. "*fruitList.scrollBarDisplayPolicy: STATIC",
  391. "*fruitList.selectionPolicy: MULTIPLE_SELECT",
  392. "*apptList.listSizePolicy: CONSTANT",
  393. "*apptList.scrollBarDisplayPolicy: STATIC",
  394. "*apptList.selectionPolicy: MULTIPLE_SELECT",
  395. "*textRowColumn.orientation: HORIZONTAL",
  396. "*textRowColumn.packing: PACK_TIGHT",
  397. "*textRowColumn*textLabel.labelString: Name:",
  398. "*textRowColumn*textField.width: 550",
  399. "*textRowColumn.marginWidth: 0",
  400. "*dropDraw.height: 100",
  401. "*dropDraw.resizePolicy: RESIZE_NONE",
  402. NULL
  403. };
  404. /*
  405. * demoCreateDropSite
  406. *
  407. * Creates the drawing area at the bottom of the demo which is used as a drop
  408. * site for files and appointments.
  409. */
  410. Widget
  411. demoCreateDropSite(
  412. Widget parent)
  413. {
  414. Widget dropFrame,
  415. dropDraw;
  416. dropFrame = XtVaCreateManagedWidget("dropFrame",
  417. xmFrameWidgetClass, parent,
  418. NULL);
  419. dropDraw = XtVaCreateManagedWidget("dropDraw",
  420. xmDrawingAreaWidgetClass, dropFrame,
  421. NULL);
  422. XtAddCallback(dropDraw,
  423. XmNexposeCallback, demoDrawExposeCallback,
  424. NULL);
  425. return dropDraw;
  426. }
  427. /*
  428. * main
  429. *
  430. * Create widgets for the demo program. Call protocol-specific functions
  431. * to initialize the drag sources and drop sites.
  432. */
  433. void
  434. main(
  435. int argc,
  436. String *argv)
  437. {
  438. Widget outerRowColumn,
  439. upperRowColumn,
  440. textDragSource,
  441. fileDragSource,
  442. apptDragSource,
  443. separator,
  444. textDropSite,
  445. drawDropSite;
  446. /*
  447. * Create basic widgets and layout widgets
  448. */
  449. XtSetLanguageProc(NULL, NULL, NULL);
  450. demoTopLevel = XtAppInitialize(&demoAppContext, "Dtdnddemo",
  451. (XrmOptionDescList)NULL, 0, &argc, argv,
  452. fallbackResources, (ArgList)NULL, 0);
  453. DtAppInitialize(demoAppContext, XtDisplay(demoTopLevel),
  454. demoTopLevel, argv[0], "Dtdnddemo");
  455. outerRowColumn = XtVaCreateManagedWidget("outerRowColumn",
  456. xmRowColumnWidgetClass, demoTopLevel,
  457. NULL);
  458. upperRowColumn = XtVaCreateManagedWidget("upperRowColumn",
  459. xmRowColumnWidgetClass, outerRowColumn,
  460. NULL);
  461. /*
  462. * Create the drag sources
  463. */
  464. textDragSource = textCreateDragSource(upperRowColumn);
  465. fileDragSource = fileCreateDragSource(upperRowColumn);
  466. apptDragSource = apptCreateDragSource(upperRowColumn);
  467. /*
  468. * Create a line separating the drag sources from the drop sites
  469. */
  470. separator = XtVaCreateManagedWidget("separator",
  471. xmSeparatorWidgetClass, outerRowColumn,
  472. NULL);
  473. /*
  474. * Create the drop sites
  475. */
  476. textDropSite = textCreateDropSite(outerRowColumn);
  477. drawDropSite = demoCreateDropSite(outerRowColumn);
  478. /*
  479. * Realize the widget tree
  480. */
  481. XtRealizeWidget(demoTopLevel);
  482. /*
  483. * Load the data typing database which is used to get icons
  484. */
  485. DtDtsLoadDataTypes();
  486. /*
  487. * Set up the drag sources
  488. */
  489. textDragSetup(textDragSource);
  490. fileDragSetup(fileDragSource);
  491. apptDragSetup(apptDragSource);
  492. /*
  493. * Set up the drop sites
  494. */
  495. textDropSetup(textDropSite);
  496. demoDropSetup(drawDropSite);
  497. /*
  498. * Start the event processing loop
  499. */
  500. XtAppMainLoop(demoAppContext);
  501. }