DndIcon.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570
  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. /* $XConsortium: DndIcon.c /main/5 1996/06/21 17:28:34 ageorge $ */
  24. /*********************************************************************
  25. *
  26. * File: DndIcon.c
  27. *
  28. * Description: Implemenation of DND drag icons
  29. *
  30. *********************************************************************
  31. *
  32. *+SNOTICE
  33. *
  34. * RESTRICTED CONFIDENTIAL INFORMATION:
  35. *
  36. * The information in this document is subject to special
  37. * restrictions in a confidential disclosure agreement between
  38. * HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
  39. * document outside HP, IBM, Sun, USL, SCO, or Univel without
  40. * Sun's specific written approval. This documment and all copies
  41. * and derivative works thereof must be returned or destroyed at
  42. * Sun's request.
  43. *
  44. * Copyright 1993 Sun Microsystems, Inc. All rights reserved.
  45. *
  46. * (c) Copyright 1993, 1994 Hewlett-Packard Company
  47. * (c) Copyright 1993, 1994 International Business Machines Corp.
  48. * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
  49. * (c) Copyright 1993, 1994 Novell, Inc.
  50. *
  51. *+ENOTICE
  52. */
  53. #include <stdlib.h>
  54. #include <X11/Xlib.h>
  55. #include <X11/Intrinsic.h>
  56. #include <Xm/Screen.h>
  57. #include <Xm/DragIcon.h>
  58. #include "Dnd.h"
  59. #include "DndP.h"
  60. #include "DndIconI.h"
  61. #include "DtSvcLock.h"
  62. /*
  63. * Component types of a drag icon (source/state/operation)
  64. */
  65. enum {
  66. DtDND_DRAG_SOURCE,
  67. DtDND_DRAG_STATE,
  68. DtDND_DRAG_OPERATION
  69. };
  70. /*
  71. * The XmDragIcon widgets for the state & operation components
  72. * of a Drag Icon
  73. */
  74. typedef struct _DragIcons {
  75. Widget validIcon, invalidIcon, noneIcon;
  76. Widget moveIcon, copyIcon, linkIcon;
  77. } DragIcons;
  78. /*
  79. * Collection of drag icons for text & data drags
  80. */
  81. typedef struct _DragCollection {
  82. DtDndDragSource sourceType;
  83. DragIcons text;
  84. DragIcons data;
  85. Widget textSource;
  86. Widget dataSource;
  87. Widget multipleSource;
  88. } DragCollection;
  89. /*
  90. * The context that the DragCollection is stored against.
  91. * Used in getDragCollection() and destroyDragCollection().
  92. */
  93. static XContext dragCollectionContext;
  94. /*
  95. * Creates an XmDragIcon for use as the source component of the drag icon.
  96. */
  97. Widget
  98. DtDndCreateSourceIcon(
  99. Widget widget,
  100. Pixmap pixmap,
  101. Pixmap mask)
  102. {
  103. Widget dragIcon;
  104. Window rootWindow;
  105. int pixmapX, pixmapY;
  106. unsigned int pixmapWidth, pixmapHeight, pixmapBorder, pixmapDepth;
  107. Arg args[20];
  108. Cardinal nn = 0;
  109. _DtSvcWidgetToAppContext(widget);
  110. _DtSvcAppLock(app);
  111. while (XmIsGadget(widget)) {
  112. widget = XtParent(widget);
  113. }
  114. XGetGeometry (XtDisplayOfObject(widget), pixmap, &rootWindow,
  115. &pixmapX, &pixmapY, &pixmapWidth, &pixmapHeight,
  116. &pixmapBorder, &pixmapDepth);
  117. XtSetArg(args[nn], XmNwidth, pixmapWidth); nn++;
  118. XtSetArg(args[nn], XmNheight, pixmapHeight); nn++;
  119. XtSetArg(args[nn], XmNmaxWidth, pixmapWidth); nn++;
  120. XtSetArg(args[nn], XmNmaxHeight, pixmapHeight); nn++;
  121. XtSetArg(args[nn], XmNpixmap, pixmap); nn++;
  122. XtSetArg(args[nn], XmNmask, mask); nn++;
  123. XtSetArg(args[nn], XmNdepth, pixmapDepth); nn++;
  124. dragIcon = XmCreateDragIcon(widget, "sourceIcon", args, nn);
  125. _DtSvcAppUnlock(app);
  126. return(dragIcon);
  127. }
  128. /*
  129. * Calculates the x,y offsets for the state cursor relative to the source
  130. */
  131. static void
  132. calcStateIconOffset(
  133. Widget sourceIcon,
  134. int *stateOffsetX,
  135. int *stateOffsetY)
  136. {
  137. Display *dpy = XtDisplayOfObject(sourceIcon);
  138. Pixmap pixmap;
  139. Window root;
  140. int pixmapX, pixmapY;
  141. unsigned int pixmapW, pixmapH, junk;
  142. XtVaGetValues(sourceIcon, XmNpixmap, &pixmap, NULL);
  143. if (pixmap == None)
  144. return;
  145. XGetGeometry(dpy, pixmap, &root,
  146. &pixmapX, &pixmapY, &pixmapW, &pixmapH,
  147. &junk, &junk);
  148. if (pixmapH == 16) {
  149. *stateOffsetX = *stateOffsetY = 8;
  150. } else {
  151. *stateOffsetX = *stateOffsetY = 16;
  152. }
  153. }
  154. /*
  155. * Selects or activates the request type of source by setting
  156. * the default drag icon resources on the XmScreen widget.
  157. */
  158. static void
  159. selectDragSource(
  160. DragCollection *dc,
  161. Widget xmScreen,
  162. DtDndDragSource sourceType,
  163. Widget sourceIcon)
  164. {
  165. Display *dpy = XtDisplayOfObject(xmScreen);
  166. Widget validIcon, invalidIcon, noneIcon,
  167. moveIcon, copyIcon, linkIcon,
  168. defSourceIcon;
  169. int hotX, hotY,
  170. stateOffsetX, stateOffsetY,
  171. offsetDeltaX, offsetDeltaY;
  172. Arg args[30];
  173. Cardinal nn = 0;
  174. /*
  175. * Choose the state/operation/default-source drag icons based
  176. * on the requested drag-source-type
  177. */
  178. switch (sourceType) {
  179. case DtDND_DRAG_SOURCE_TEXT:
  180. validIcon = dc->text.validIcon;
  181. invalidIcon = dc->text.invalidIcon;
  182. noneIcon = dc->text.noneIcon;
  183. moveIcon = dc->text.moveIcon;
  184. copyIcon = dc->text.copyIcon;
  185. linkIcon = dc->text.linkIcon;
  186. defSourceIcon = dc->textSource;
  187. hotX = text_x_hot;
  188. hotY = text_y_hot;
  189. stateOffsetX = text_x_offset_state;
  190. stateOffsetY = text_y_offset_state;
  191. offsetDeltaX = text_x_offset_delta;
  192. offsetDeltaY = text_y_offset_delta;
  193. break;
  194. case DtDND_DRAG_SOURCE_DATA:
  195. validIcon = dc->data.validIcon;
  196. invalidIcon = dc->data.invalidIcon;
  197. noneIcon = dc->data.noneIcon;
  198. moveIcon = dc->data.moveIcon;
  199. copyIcon = dc->data.copyIcon;
  200. linkIcon = dc->data.linkIcon;
  201. defSourceIcon = dc->dataSource;
  202. hotX = data_x_hot;
  203. hotY = data_y_hot;
  204. stateOffsetX = data_x_offset_state;
  205. stateOffsetY = data_y_offset_state;
  206. offsetDeltaX = data_x_offset_delta;
  207. offsetDeltaY = data_y_offset_delta;
  208. break;
  209. case DtDND_DRAG_SOURCE_MULTIPLE:
  210. validIcon = dc->data.validIcon;
  211. invalidIcon = dc->data.invalidIcon;
  212. noneIcon = dc->data.noneIcon;
  213. moveIcon = dc->data.moveIcon;
  214. copyIcon = dc->data.copyIcon;
  215. linkIcon = dc->data.linkIcon;
  216. defSourceIcon = dc->multipleSource;
  217. hotX = data_x_hot;
  218. hotY = data_y_hot;
  219. stateOffsetX = data_x_offset_state;
  220. stateOffsetY = data_y_offset_state;
  221. offsetDeltaX = data_x_offset_delta;
  222. offsetDeltaY = data_y_offset_delta;
  223. break;
  224. default:
  225. case DtDND_DRAG_SOURCE_DEFAULT:
  226. validIcon = NULL;
  227. invalidIcon = NULL;
  228. noneIcon = NULL;
  229. moveIcon = NULL;
  230. copyIcon = NULL;
  231. linkIcon = NULL;
  232. defSourceIcon = NULL;
  233. hotX = motif_x_hot;
  234. hotY = motif_y_hot;
  235. stateOffsetX = motif_x_offset_state;
  236. stateOffsetY = motif_y_offset_state;
  237. offsetDeltaX = motif_x_offset_delta;
  238. offsetDeltaY = motif_y_offset_delta;
  239. break;
  240. }
  241. /*
  242. * Calculate the offsets of the state icon from the
  243. * DtDND_DRAG_SOURCE_DATA source icon if specified
  244. */
  245. if (sourceIcon && sourceType == DtDND_DRAG_SOURCE_DATA) {
  246. calcStateIconOffset(sourceIcon, &stateOffsetX, &stateOffsetY);
  247. }
  248. nn = 0;
  249. XtSetArg(args[nn], XmNhotX, hotX); nn++;
  250. XtSetArg(args[nn], XmNhotY, hotY); nn++;
  251. XtSetArg(args[nn], XmNoffsetX, stateOffsetX); nn++;
  252. XtSetArg(args[nn], XmNoffsetY, stateOffsetY); nn++;
  253. if (validIcon)
  254. XtSetValues(validIcon, args, nn);
  255. if (invalidIcon)
  256. XtSetValues(invalidIcon, args, nn);
  257. if (noneIcon)
  258. XtSetValues(noneIcon, args, nn);
  259. nn = 0;
  260. XtSetArg(args[nn], XmNoffsetX, stateOffsetX + offsetDeltaX); nn++;
  261. XtSetArg(args[nn], XmNoffsetY, stateOffsetY + offsetDeltaY); nn++;
  262. if (moveIcon)
  263. XtSetValues(moveIcon, args, nn);
  264. if (copyIcon)
  265. XtSetValues(copyIcon, args, nn);
  266. if (linkIcon)
  267. XtSetValues(linkIcon, args, nn);
  268. /*
  269. * Set the default drag cursor icons for the XmScreen widget
  270. */
  271. XtVaSetValues(xmScreen,
  272. XmNdefaultValidCursorIcon, validIcon,
  273. XmNdefaultInvalidCursorIcon, invalidIcon,
  274. XmNdefaultNoneCursorIcon, noneIcon,
  275. XmNdefaultMoveCursorIcon, moveIcon,
  276. XmNdefaultCopyCursorIcon, copyIcon,
  277. XmNdefaultLinkCursorIcon, linkIcon,
  278. XmNdefaultSourceCursorIcon, defSourceIcon,
  279. NULL);
  280. dc->sourceType = sourceType;
  281. }
  282. /*
  283. * Create a drag icon widget from the passed bits
  284. */
  285. static Widget
  286. makeDragIconFromData(
  287. Widget widget,
  288. unsigned char *bits,
  289. unsigned char *maskbits,
  290. int width,
  291. int height,
  292. int component)
  293. {
  294. Widget icon;
  295. Pixmap pixmap, mask;
  296. Display *dpy = XtDisplayOfObject(widget);
  297. Screen *screen = XtScreenOfObject(widget);
  298. Window root = RootWindowOfScreen(screen);
  299. String name;
  300. Arg args[30];
  301. Cardinal nn = 0;
  302. pixmap = XCreatePixmapFromBitmapData(dpy, root,
  303. (char *)bits, width, height,
  304. 1, 0, 1);
  305. mask = XCreatePixmapFromBitmapData(dpy, root,
  306. (char *)maskbits, width, height,
  307. 1, 0, 1);
  308. switch (component) {
  309. case DtDND_DRAG_SOURCE:
  310. name = "sourceIcon";
  311. break;
  312. case DtDND_DRAG_STATE:
  313. name = "stateIcon";
  314. XtSetArg(args[nn], XmNattachment, XmATTACH_NORTH_WEST); nn++;
  315. XtSetArg(args[nn], XmNoffsetX, -6); nn++;
  316. XtSetArg(args[nn], XmNoffsetY, -6); nn++;
  317. XtSetArg(args[nn], XmNhotX, 3); nn++;
  318. XtSetArg(args[nn], XmNhotY, 3); nn++;
  319. break;
  320. case DtDND_DRAG_OPERATION:
  321. name = "operationIcon";
  322. XtSetArg(args[nn], XmNattachment, XmATTACH_NORTH_WEST); nn++;
  323. XtSetArg(args[nn], XmNoffsetX, 1); nn++;
  324. XtSetArg(args[nn], XmNoffsetY, 1); nn++;
  325. break;
  326. }
  327. XtSetArg(args[nn], XmNwidth, width); nn++;
  328. XtSetArg(args[nn], XmNheight, height); nn++;
  329. XtSetArg(args[nn], XmNmaxWidth, width); nn++;
  330. XtSetArg(args[nn], XmNmaxHeight, height); nn++;
  331. XtSetArg(args[nn], XmNpixmap, pixmap); nn++;
  332. XtSetArg(args[nn], XmNmask, mask); nn++;
  333. XtSetArg(args[nn], XmNdepth, 1); nn++;
  334. icon = XmCreateDragIcon(widget, name, args, nn);
  335. return icon;
  336. }
  337. /*
  338. * Create the collection of text & data drag icons; state/operation
  339. * cursors and source icons.
  340. */
  341. static DragCollection *
  342. makeDragCollection(
  343. Widget widget)
  344. {
  345. DragCollection *dc = XtNew(DragCollection);
  346. Display *dpy = XtDisplayOfObject(widget);
  347. Screen *screen = XtScreenOfObject(widget);
  348. Window root = RootWindowOfScreen(screen);
  349. Widget xmScreen = XmGetXmScreen(screen);
  350. /*
  351. * Text & Data State Cursors
  352. */
  353. dc->text.invalidIcon = makeDragIconFromData(widget,
  354. text_invalid_bits, text_invalid_m_bits,
  355. text_invalid_width, text_invalid_height,
  356. DtDND_DRAG_STATE);
  357. dc->text.validIcon = makeDragIconFromData(widget,
  358. text_valid_bits, text_valid_m_bits,
  359. text_valid_width, text_valid_height,
  360. DtDND_DRAG_STATE);
  361. dc->text.noneIcon = makeDragIconFromData(widget,
  362. text_none_bits, text_none_m_bits,
  363. text_none_width, text_none_height,
  364. DtDND_DRAG_STATE);
  365. dc->data.invalidIcon = makeDragIconFromData(widget,
  366. data_invalid_bits, data_invalid_m_bits,
  367. data_invalid_width, data_invalid_height,
  368. DtDND_DRAG_STATE);
  369. dc->data.validIcon = makeDragIconFromData(widget,
  370. data_valid_bits, data_valid_m_bits,
  371. data_valid_width, data_valid_height,
  372. DtDND_DRAG_STATE);
  373. dc->data.noneIcon = makeDragIconFromData(widget,
  374. data_none_bits, data_none_m_bits,
  375. data_none_width, data_none_height,
  376. DtDND_DRAG_STATE);
  377. /*
  378. * Text & Data Operation Cursors
  379. */
  380. dc->data.moveIcon = makeDragIconFromData(widget,
  381. data_move_bits, data_move_m_bits,
  382. data_move_width, data_move_height,
  383. DtDND_DRAG_OPERATION);
  384. dc->data.copyIcon = makeDragIconFromData(widget,
  385. data_copy_bits, data_copy_m_bits,
  386. data_copy_width, data_copy_height,
  387. DtDND_DRAG_OPERATION);
  388. dc->data.linkIcon = makeDragIconFromData(widget,
  389. data_link_bits, data_link_m_bits,
  390. data_link_width, data_link_height,
  391. DtDND_DRAG_OPERATION);
  392. dc->text.moveIcon = dc->data.moveIcon;
  393. dc->text.copyIcon = dc->data.copyIcon;
  394. dc->text.linkIcon = dc->data.linkIcon;
  395. /*
  396. * Text & Data Source Cursors
  397. */
  398. dc->textSource = makeDragIconFromData(widget,
  399. text_source_bits, text_source_m_bits,
  400. text_source_width, text_source_height,
  401. DtDND_DRAG_SOURCE);
  402. dc->dataSource = makeDragIconFromData(widget,
  403. data_single_bits, data_single_m_bits,
  404. data_single_width, data_single_height,
  405. DtDND_DRAG_SOURCE);
  406. dc->multipleSource = makeDragIconFromData(widget,
  407. data_multiple_bits, data_multiple_m_bits,
  408. data_multiple_width, data_multiple_height,
  409. DtDND_DRAG_SOURCE);
  410. dc->sourceType = DtDND_DRAG_SOURCE_DEFAULT;
  411. return dc;
  412. }
  413. /*
  414. * Destroys the cached DragCollection and context for it
  415. */
  416. static void
  417. destroyDragCollection(
  418. Widget widget,
  419. XtPointer clientData,
  420. XtPointer callData)
  421. {
  422. DragCollection *dc = (DragCollection *)clientData;
  423. XtFree((char *)dc);
  424. XDeleteContext(XtDisplayOfObject(widget),
  425. RootWindowOfScreen(XtScreenOfObject(widget)),
  426. dragCollectionContext);
  427. }
  428. /*
  429. * Returns the cached DragCollection; will create one if needed
  430. */
  431. static DragCollection *
  432. getDragCollection(
  433. Widget xmScreen)
  434. {
  435. DragCollection *dc = NULL;
  436. Display *dpy = XtDisplayOfObject(xmScreen);
  437. Screen *screen = XtScreenOfObject(xmScreen);
  438. Window root = RootWindowOfScreen(screen);
  439. int status;
  440. _DtSvcProcessLock();
  441. if (dragCollectionContext == (XContext)0) {
  442. dragCollectionContext = XUniqueContext();
  443. }
  444. _DtSvcProcessUnlock();
  445. status = XFindContext(dpy, root, dragCollectionContext, (XtPointer)&dc);
  446. if (status != 0) {
  447. dc = makeDragCollection(xmScreen);
  448. XSaveContext(dpy, root, dragCollectionContext, (XtPointer)dc);
  449. XtAddCallback(xmScreen, XmNdestroyCallback,
  450. destroyDragCollection, (XtPointer)dc);
  451. }
  452. return dc;
  453. }
  454. /*
  455. * Module-public function to select/activate a source type drag icon
  456. */
  457. void
  458. _DtDndSelectDragSource(
  459. Widget widget,
  460. DtDndDragSource sourceType,
  461. Widget sourceIcon)
  462. {
  463. Widget xmScreen = XmGetXmScreen(XtScreenOfObject(widget));
  464. DragCollection *dc = getDragCollection(xmScreen);
  465. selectDragSource(dc, xmScreen, sourceType, sourceIcon);
  466. }
  467. void
  468. _DtDndGetIconOffset(
  469. Widget dragContext,
  470. DtDndDragSource sourceType,
  471. int * offsetX,
  472. int * offsetY)
  473. {
  474. Widget sourceIcon;
  475. int stateOffsetX, stateOffsetY;
  476. switch (sourceType) {
  477. default:
  478. case DtDND_DRAG_SOURCE_DEFAULT:
  479. *offsetX = -(motif_x_hot + motif_x_offset_state);
  480. *offsetY = -(motif_y_hot + motif_y_offset_state);
  481. break;
  482. case DtDND_DRAG_SOURCE_TEXT:
  483. *offsetX = -(text_x_hot + text_x_offset_state);
  484. *offsetY = -(text_y_hot + text_y_offset_state);
  485. break;
  486. case DtDND_DRAG_SOURCE_DATA:
  487. case DtDND_DRAG_SOURCE_MULTIPLE:
  488. *offsetX = -(data_x_hot + data_x_offset_state);
  489. *offsetY = -(data_y_hot + data_y_offset_state);
  490. XtVaGetValues(dragContext,
  491. XmNsourcePixmapIcon, &sourceIcon,
  492. NULL);
  493. if (sourceIcon != NULL) {
  494. calcStateIconOffset(sourceIcon,
  495. &stateOffsetX, &stateOffsetY);
  496. *offsetX = -(data_x_hot + stateOffsetX);
  497. *offsetY = -(data_y_hot + stateOffsetY);
  498. }
  499. break;
  500. }
  501. }