PageRenderTime 55ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/e16-1.0.10/src/draw.c

#
C | 512 lines | 420 code | 63 blank | 29 comment | 87 complexity | 6b4fb84f5b6e3ba14d1b9e3ebaa8fdc4 MD5 | raw file
  1. /*
  2. * Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors
  3. * Copyright (C) 2007-2011 Kim Woelders
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining a copy
  6. * of this software and associated documentation files (the "Software"), to
  7. * deal in the Software without restriction, including without limitation the
  8. * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9. * sell copies of the Software, and to permit persons to whom the Software is
  10. * furnished to do so, subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be included in
  13. * all copies of the Software, its documentation and marketing & publicity
  14. * materials, and acknowledgment shall be given in the documentation, materials
  15. * and software packages that this Software was used.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  20. * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  21. * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  22. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23. */
  24. #include "E.h"
  25. #include "desktops.h"
  26. #include "eobj.h"
  27. #include "ewins.h"
  28. #include "piximg.h"
  29. #include "xwin.h"
  30. #if ENABLE_OLDMOVRES
  31. #define MR_ENABLE_STIPPLED 1 /* Enable shaded/semi-solid modes */
  32. #define MR_ENABLE_TRANSLUCENT 1 /* Enable translucent mode */
  33. #define MR_MODES_MOVE 0x7f /* MR_OPAQUE through MR_TECH_OPAQUE */
  34. #define MR_MODES_RESIZE 0x5f /* MR_OPAQUE through MR_SEMI_SOLID and MR_TECH_OPAQUE */
  35. #else
  36. #define MR_MODES_MOVE 0x47 /* MR_OPAQUE through MR_BOX and MR_TECH_OPAQUE */
  37. #define MR_MODES_RESIZE 0x47 /* MR_OPAQUE through MR_BOX and MR_TECH_OPAQUE */
  38. #endif
  39. #if MR_ENABLE_STIPPLED
  40. #if 0
  41. #include <X11/bitmaps/gray>
  42. #include <X11/bitmaps/gray3>
  43. #else
  44. /* Include contents of X11/bitmaps/gray+gray3.
  45. * (avoid build failure if x11 bitmap package isn't installed) */
  46. #define gray_width 2
  47. #define gray_height 2
  48. static const char gray_bits[] = { 0x01, 0x02 };
  49. #define gray3_width 4
  50. #define gray3_height 4
  51. static const char gray3_bits[] = { 0x01, 0x00, 0x04, 0x00 };
  52. #endif
  53. static Pixmap b2 = None; /* Used in modes 3,4 */
  54. static Pixmap b3 = None; /* Used in mode 3 */
  55. #endif /* MR_ENABLE_STIPPLED */
  56. static Font font = None; /* Used in mode 1 (technical) */
  57. static void
  58. draw_h_arrow(Drawable dr, GC gc, int x1, int x2, int y1)
  59. {
  60. char str[32];
  61. if (x2 - x1 >= 12)
  62. {
  63. XDrawLine(disp, dr, gc, x1, y1, x1 + 6, y1 - 3);
  64. XDrawLine(disp, dr, gc, x1, y1, x1 + 6, y1 + 3);
  65. XDrawLine(disp, dr, gc, x2, y1, x2 - 6, y1 - 3);
  66. XDrawLine(disp, dr, gc, x2, y1, x2 - 6, y1 + 3);
  67. }
  68. if (x2 >= x1)
  69. {
  70. XDrawLine(disp, dr, gc, x1, y1, x2, y1);
  71. Esnprintf(str, sizeof(str), "%i", x2 - x1 + 1);
  72. XDrawString(disp, dr, gc, (x1 + x2) / 2, y1 - 10, str, strlen(str));
  73. }
  74. }
  75. static void
  76. draw_v_arrow(Drawable dr, GC gc, int y1, int y2, int x1)
  77. {
  78. char str[32];
  79. if (y2 - y1 >= 12)
  80. {
  81. XDrawLine(disp, dr, gc, x1, y1, x1 + 3, y1 + 6);
  82. XDrawLine(disp, dr, gc, x1, y1, x1 - 3, y1 + 6);
  83. XDrawLine(disp, dr, gc, x1, y2, x1 + 3, y2 - 6);
  84. XDrawLine(disp, dr, gc, x1, y2, x1 - 3, y2 - 6);
  85. }
  86. if (y2 >= y1)
  87. {
  88. XDrawLine(disp, dr, gc, x1, y1, x1, y2);
  89. Esnprintf(str, sizeof(str), "%i", y2 - y1 + 1);
  90. XDrawString(disp, dr, gc, x1 + 10, (y1 + y2) / 2, str, strlen(str));
  91. }
  92. }
  93. void
  94. do_draw_technical(Drawable dr, GC gc,
  95. int a, int b, int c, int d, int bl, int br, int bt, int bb)
  96. {
  97. if (!font)
  98. font = XLoadFont(disp, "-*-helvetica-medium-r-*-*-10-*-*-*-*-*-*-*");
  99. XSetFont(disp, gc, font);
  100. if (c < 3)
  101. c = 3;
  102. if (d < 3)
  103. d = 3;
  104. draw_h_arrow(dr, gc, a + bl, a + bl + c - 1, b + bt + d - 16);
  105. draw_h_arrow(dr, gc, 0, a - 1, b + bt + (d / 2));
  106. draw_h_arrow(dr, gc, a + c + bl + br, WinGetW(VROOT) - 1, b + bt + (d / 2));
  107. draw_v_arrow(dr, gc, b + bt, b + bt + d - 1, a + bl + 16);
  108. draw_v_arrow(dr, gc, 0, b - 1, a + bl + (c / 2));
  109. draw_v_arrow(dr, gc, b + d + bt + bb, WinGetH(VROOT) - 1, a + bl + (c / 2));
  110. XDrawLine(disp, dr, gc, a, 0, a, WinGetH(VROOT));
  111. XDrawLine(disp, dr, gc, a + c + bl + br - 1, 0,
  112. a + c + bl + br - 1, WinGetH(VROOT));
  113. XDrawLine(disp, dr, gc, 0, b, WinGetW(VROOT), b);
  114. XDrawLine(disp, dr, gc, 0, b + d + bt + bb - 1,
  115. WinGetW(VROOT), b + d + bt + bb - 1);
  116. XDrawRectangle(disp, dr, gc, a + bl + 1, b + bt + 1, c - 3, d - 3);
  117. }
  118. static void
  119. do_draw_boxy(Drawable dr, GC gc,
  120. int a, int b, int c, int d, int bl, int br, int bt, int bb)
  121. {
  122. if (c < 3)
  123. c = 3;
  124. if (d < 3)
  125. d = 3;
  126. XDrawRectangle(disp, dr, gc, a, b, c + bl + br - 1, d + bt + bb - 1);
  127. XDrawRectangle(disp, dr, gc, a + bl + 1, b + bt + 1, c - 3, d - 3);
  128. }
  129. #if MR_ENABLE_STIPPLED
  130. static void
  131. do_draw_shaded(Drawable dr, GC gc,
  132. int a, int b, int c, int d, int bl, int br, int bt, int bb)
  133. {
  134. XSetFillStyle(disp, gc, FillStippled);
  135. XSetStipple(disp, gc, b2);
  136. if ((c + bl + br > 0) && (bt > 0))
  137. XFillRectangle(disp, dr, gc, a, b, c + bl + br, bt);
  138. if ((c + bl + br > 0) && (bb > 0))
  139. XFillRectangle(disp, dr, gc, a, b + d + bt, c + bl + br, bb);
  140. if ((d > 0) && (bl > 0))
  141. XFillRectangle(disp, dr, gc, a, b + bt, bl, d);
  142. if ((d > 0) && (br > 0))
  143. XFillRectangle(disp, dr, gc, a + c + bl, b + bt, br, d);
  144. XSetStipple(disp, gc, b3);
  145. if ((c > 0) && (d > 0))
  146. XFillRectangle(disp, dr, gc, a + bl + 1, b + bt + 1, c - 3, d - 3);
  147. }
  148. static void
  149. do_draw_semi_solid(Drawable dr, GC gc,
  150. int a, int b, int c, int d, int bl, int br, int bt, int bb)
  151. {
  152. XSetFillStyle(disp, gc, FillStippled);
  153. XSetStipple(disp, gc, b2);
  154. XFillRectangle(disp, dr, gc, a, b, c + bl + br, d + bt + bb);
  155. }
  156. #endif /* MR_ENABLE_STIPPLED */
  157. typedef struct {
  158. EWin *ewin;
  159. Window root;
  160. GC gc;
  161. int xo, yo, wo, ho;
  162. int bl, br, bt, bb;
  163. #if MR_ENABLE_TRANSLUCENT
  164. PixImg *root_pi;
  165. PixImg *ewin_pi;
  166. PixImg *draw_pi;
  167. #endif
  168. } ShapeData;
  169. static void
  170. _ShapeDrawNograb_tech_box(ShapeData * psd, int md, int firstlast,
  171. int xn, int yn, int wn, int hn, int seqno)
  172. {
  173. static ShapeWin *shape_win = NULL;
  174. if (firstlast == 0 && !shape_win)
  175. shape_win = ShapewinCreate(md);
  176. if (!shape_win)
  177. return;
  178. ShapewinShapeSet(shape_win, md, xn, yn, wn, hn, psd->bl, psd->br, psd->bt,
  179. psd->bb, seqno);
  180. EoMap(shape_win, 0);
  181. CoordsShow(psd->ewin);
  182. if (firstlast == 2)
  183. {
  184. ShapewinDestroy(shape_win);
  185. shape_win = NULL;
  186. }
  187. }
  188. typedef void (DrawFunc) (Drawable dr, GC gc, int a, int b, int c, int d,
  189. int bl, int br, int bt, int bb);
  190. static DrawFunc *const draw_functions[] = {
  191. do_draw_technical, do_draw_boxy,
  192. #if MR_ENABLE_STIPPLED
  193. do_draw_shaded, do_draw_semi_solid,
  194. #else
  195. NULL, NULL,
  196. #endif /* MR_ENABLE_STIPPLED */
  197. NULL, do_draw_technical,
  198. };
  199. static void
  200. _ShapeDrawNontranslucent(ShapeData * psd, int md, int firstlast,
  201. int xn, int yn, int wn, int hn)
  202. {
  203. DrawFunc *drf;
  204. if (firstlast == 0)
  205. {
  206. XGCValues gcv;
  207. gcv.function = GXxor;
  208. gcv.foreground = Dpy.pixel_white;
  209. if (gcv.foreground == 0)
  210. gcv.foreground = Dpy.pixel_black;
  211. gcv.subwindow_mode = IncludeInferiors;
  212. psd->gc = EXCreateGC(psd->root,
  213. GCFunction | GCForeground | GCSubwindowMode, &gcv);
  214. #if MR_ENABLE_STIPPLED
  215. if (md == MR_SHADED || md == MR_SEMI_SOLID)
  216. {
  217. if (!b2)
  218. b2 = XCreateBitmapFromData(disp, psd->root, gray_bits,
  219. gray_width, gray_height);
  220. if (!b3)
  221. b3 = XCreateBitmapFromData(disp, psd->root, gray3_bits,
  222. gray3_width, gray3_height);
  223. }
  224. #endif /* MR_ENABLE_STIPPLED */
  225. }
  226. drf = draw_functions[md - 1];
  227. if (firstlast > 0)
  228. drf(psd->root, psd->gc, psd->xo, psd->yo, psd->wo, psd->ho,
  229. psd->bl, psd->br, psd->bt, psd->bb);
  230. CoordsShow(psd->ewin);
  231. if (firstlast < 2)
  232. drf(psd->root, psd->gc, xn, yn, wn, hn,
  233. psd->bl, psd->br, psd->bt, psd->bb);
  234. if (firstlast == 2)
  235. {
  236. EXFreeGC(psd->gc);
  237. psd->gc = NULL;
  238. }
  239. }
  240. #if MR_ENABLE_TRANSLUCENT
  241. static void
  242. _ShapeDrawTranslucent(ShapeData * psd, int md __UNUSED__, int firstlast,
  243. int xn, int yn, int wn, int hn)
  244. {
  245. XGCValues gcv;
  246. int dx, dy, adx, ady;
  247. int xo, yo;
  248. xo = psd->xo;
  249. yo = psd->yo;
  250. /* Using frame window size here */
  251. wn = EoGetW(psd->ewin);
  252. hn = EoGetH(psd->ewin);
  253. switch (firstlast)
  254. {
  255. default:
  256. break;
  257. case 0:
  258. gcv.subwindow_mode = IncludeInferiors;
  259. psd->gc = EXCreateGC(psd->root, GCSubwindowMode, &gcv);
  260. psd->root_pi =
  261. PixImgCreate(NULL, psd->gc, WinGetW(VROOT), WinGetH(VROOT));
  262. psd->ewin_pi = PixImgCreate(NULL, psd->gc, wn, hn);
  263. psd->draw_pi = PixImgCreate(VROOT, psd->gc, wn, hn);
  264. if ((!psd->root_pi) || (!psd->ewin_pi) || (!psd->draw_pi))
  265. {
  266. /* Trouble - Fall back to opaque mode */
  267. Conf.movres.mode_move = MR_OPAQUE;
  268. goto do_cleanup;
  269. }
  270. if (EoGetWin(psd->ewin)->num_rect > 0)
  271. {
  272. Pixmap mask;
  273. mask = EWindowGetShapePixmapInverted(EoGetWin(psd->ewin));
  274. PixImgSetMask(psd->draw_pi, mask, 0, 0);
  275. }
  276. PixImgFill(psd->root_pi, psd->root, 0, 0);
  277. PixImgFill(psd->ewin_pi, psd->root, xn, yn);
  278. PixImgBlend(psd->root_pi, psd->ewin_pi, psd->draw_pi, psd->root,
  279. xn, yn, wn, hn);
  280. break;
  281. case 1:
  282. dx = xn - xo;
  283. dy = yn - yo;
  284. if (dx < 0)
  285. adx = -dx;
  286. else
  287. adx = dx;
  288. if (dy < 0)
  289. ady = -dy;
  290. else
  291. ady = dy;
  292. if ((adx <= wn) && (ady <= hn))
  293. {
  294. PixImgBlend(psd->root_pi, psd->ewin_pi, psd->draw_pi, psd->root,
  295. xn, yn, wn, hn);
  296. if (dx > 0)
  297. PixImgPaste11(psd->root_pi, psd->draw_pi, xo, yo, dx, hn);
  298. else if (dx < 0)
  299. PixImgPaste11(psd->root_pi, psd->draw_pi, xo + wn + dx,
  300. yo, -dx, hn);
  301. if (dy > 0)
  302. PixImgPaste11(psd->root_pi, psd->draw_pi, xo, yo, wn, dy);
  303. else if (dy < 0)
  304. PixImgPaste11(psd->root_pi, psd->draw_pi, xo,
  305. yo + hn + dy, wn, -dy);
  306. }
  307. else
  308. {
  309. PixImgPaste11(psd->root_pi, psd->draw_pi, xo, yo, wn, hn);
  310. PixImgBlend(psd->root_pi, psd->ewin_pi, psd->draw_pi, psd->root,
  311. xn, yn, wn, hn);
  312. }
  313. if (EoGetWin(psd->ewin)->num_rect > 0)
  314. {
  315. PixImgSetMask(psd->draw_pi, 1, xn, yn);
  316. PixImgPaste11(psd->root_pi, psd->draw_pi, xn, yn, wn, hn);
  317. PixImgSetMask(psd->draw_pi, 0, 0, 0);
  318. }
  319. break;
  320. case 2:
  321. PixImgPaste11(psd->root_pi, psd->draw_pi, xo, yo, wn, hn);
  322. do_cleanup:
  323. PixImgDestroy(psd->root_pi);
  324. PixImgDestroy(psd->ewin_pi);
  325. PixImgDestroy(psd->draw_pi);
  326. psd->root_pi = NULL;
  327. psd->ewin_pi = NULL;
  328. psd->draw_pi = NULL;
  329. EXFreeGC(psd->gc);
  330. psd->gc = NULL;
  331. break;
  332. case 3:
  333. PixImgPaste11(psd->root_pi, psd->draw_pi, xo, yo, wn, hn);
  334. PixImgDestroy(psd->root_pi);
  335. psd->root_pi = NULL;
  336. break;
  337. case 4:
  338. psd->root_pi =
  339. PixImgCreate(NULL, psd->gc, WinGetW(VROOT), WinGetH(VROOT));
  340. PixImgFill(psd->root_pi, psd->root, 0, 0);
  341. PixImgBlend(psd->root_pi, psd->ewin_pi, psd->draw_pi, psd->root,
  342. xn, yn, wn, hn);
  343. break;
  344. }
  345. }
  346. #endif /* MR_ENABLE_TRANSLUCENT */
  347. void
  348. DrawEwinShape(EWin * ewin, int md, int x, int y, int w, int h,
  349. int firstlast, int seqno)
  350. {
  351. static ShapeData sd, *psd = &sd;
  352. Window root = WinGetXwin(VROOT);
  353. int dx, dy;
  354. /* Quit if no change */
  355. if (firstlast == 1 &&
  356. (x == ewin->shape_x && y == ewin->shape_y &&
  357. (ewin->state.shaded || (w == ewin->shape_w && h == ewin->shape_h))))
  358. return;
  359. if ((md == MR_OPAQUE) || (md == MR_TECH_OPAQUE))
  360. {
  361. EwinOpMoveResize(ewin, OPSRC_USER, x, y, w, h);
  362. EwinShapeSet(ewin);
  363. CoordsShow(ewin);
  364. if (md == MR_OPAQUE)
  365. goto done;
  366. }
  367. if (firstlast == 0)
  368. {
  369. EwinShapeSet(ewin);
  370. psd->ewin = ewin;
  371. psd->root = root;
  372. }
  373. dx = EoGetX(EoGetDesk(ewin));
  374. dy = EoGetY(EoGetDesk(ewin));
  375. ewin->shape_x = x;
  376. ewin->shape_y = y;
  377. x += dx;
  378. y += dy;
  379. if (!ewin->state.shaded)
  380. {
  381. ewin->shape_w = w;
  382. ewin->shape_h = h;
  383. }
  384. else
  385. {
  386. w = ewin->shape_w;
  387. h = ewin->shape_h;
  388. }
  389. EwinBorderGetSize(ewin, &psd->bl, &psd->br, &psd->bt, &psd->bb);
  390. if (((md <= MR_BOX) || (md == MR_TECH_OPAQUE)) &&
  391. Conf.movres.avoid_server_grab)
  392. {
  393. _ShapeDrawNograb_tech_box(psd, md, firstlast, x, y, w, h, seqno);
  394. goto done;
  395. }
  396. switch (md)
  397. {
  398. case MR_TECHNICAL:
  399. case MR_TECH_OPAQUE:
  400. case MR_BOX:
  401. #if MR_ENABLE_STIPPLED
  402. case MR_SHADED:
  403. case MR_SEMI_SOLID:
  404. #endif
  405. _ShapeDrawNontranslucent(psd, md, firstlast, x, y, w, h);
  406. break;
  407. #if MR_ENABLE_TRANSLUCENT
  408. case MR_TRANSLUCENT:
  409. _ShapeDrawTranslucent(psd, md, firstlast, x, y, w, h);
  410. CoordsShow(ewin);
  411. break;
  412. #endif
  413. default:
  414. /* Fall back to opaque mode */
  415. Conf.movres.mode_move = MR_OPAQUE;
  416. break;
  417. }
  418. psd->xo = x;
  419. psd->yo = y;
  420. psd->wo = w;
  421. psd->ho = h;
  422. done:
  423. if (firstlast == 0 || firstlast == 2 || firstlast == 4)
  424. {
  425. ewin->req_x = ewin->shape_x;
  426. ewin->req_y = ewin->shape_y;
  427. if (firstlast == 2)
  428. CoordsHide();
  429. }
  430. }
  431. static int
  432. _MoveResizeModeValidate(unsigned int valid, int md)
  433. {
  434. if (md & ~0x1f)
  435. return MR_OPAQUE;
  436. if (valid & (1U << md))
  437. return md;
  438. return MR_OPAQUE;
  439. }
  440. int
  441. MoveResizeModeValidateMove(int md)
  442. {
  443. return _MoveResizeModeValidate(MR_MODES_MOVE, md);
  444. }
  445. int
  446. MoveResizeModeValidateResize(int md)
  447. {
  448. return _MoveResizeModeValidate(MR_MODES_RESIZE, md);
  449. }