2 * Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors
3 * Copyright (C) 2007-2008 Kim Woelders
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:
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.
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.
32 #include <X11/bitmaps/gray>
33 #include <X11/bitmaps/gray3>
35 /* Include contents of X11/bitmaps/gray+gray3.
36 * (avoid build failure if x11 bitmap package isn't installed) */
40 static const char gray_bits[] = { 0x01, 0x02 };
43 #define gray3_height 4
44 static const char gray3_bits[] = { 0x01, 0x00, 0x04, 0x00 };
53 static Font font = None; /* Used in mode 1 (technical) */
55 #define DRAW_H_ARROW(_dr, _gc, x1, x2, y1) \
56 if (((x2) - (x1)) >= 12) \
58 XDrawLine(disp, _dr, _gc, (x1), (y1), (x1) + 6, (y1) - 3); \
59 XDrawLine(disp, _dr, _gc, (x1), (y1), (x1) + 6, (y1) + 3); \
60 XDrawLine(disp, _dr, _gc, (x2), (y1), (x2) - 6, (y1) - 3); \
61 XDrawLine(disp, _dr, _gc, (x2), (y1), (x2) - 6, (y1) + 3); \
65 XDrawLine(disp, _dr, _gc, (x1), (y1), (x2), (y1)); \
66 Esnprintf(str, sizeof(str), "%i", (x2) - (x1) + 1); \
67 XDrawString(disp, _dr, _gc, ((x1) + (x2)) / 2, (y1) - 10, str, strlen(str)); \
69 #define DRAW_V_ARROW(_dr, _gc, y1, y2, x1) \
70 if (((y2) - (y1)) >= 12) \
72 XDrawLine(disp, _dr, _gc, (x1), (y1), (x1) + 3, (y1) + 6); \
73 XDrawLine(disp, _dr, _gc, (x1), (y1), (x1) - 3, (y1) + 6); \
74 XDrawLine(disp, _dr, _gc, (x1), (y2), (x1) + 3, (y2) - 6); \
75 XDrawLine(disp, _dr, _gc, (x1), (y2), (x1) - 3, (y2) - 6); \
79 XDrawLine(disp, _dr, _gc, (x1), (y1), (x1), (y2)); \
80 Esnprintf(str, sizeof(str), "%i", (y2) - (y1) + 1); \
81 XDrawString(disp, _dr, _gc, (x1) + 10, ((y1) + (y2)) / 2, str, strlen(str)); \
84 #define DO_DRAW_MODE_1(_dr, _gc, _a, _b, _c, _d) \
87 font = XLoadFont(disp, "-*-helvetica-medium-r-*-*-10-*-*-*-*-*-*-*"); \
88 XSetFont(disp, _gc, font); \
91 DRAW_H_ARROW(_dr, _gc, _a + bl, _a + bl + _c - 1, _b + bt + _d - 16); \
92 DRAW_H_ARROW(_dr, _gc, 0, _a - 1, _b + bt + (_d / 2)); \
93 DRAW_H_ARROW(_dr, _gc, _a + _c + bl + br, WinGetW(VROOT) - 1, _b + bt + (_d / 2)); \
94 DRAW_V_ARROW(_dr, _gc, _b + bt, _b + bt + _d - 1, _a + bl + 16); \
95 DRAW_V_ARROW(_dr, _gc, 0, _b - 1, _a + bl + (_c / 2)); \
96 DRAW_V_ARROW(_dr, _gc, _b + _d + bt + bb, WinGetH(VROOT) - 1, _a + bl + (_c / 2)); \
97 XDrawLine(disp, _dr, _gc, _a, 0, _a, WinGetH(VROOT)); \
98 XDrawLine(disp, _dr, _gc, _a + _c + bl + br - 1, 0, _a + _c + bl + br - 1, WinGetH(VROOT)); \
99 XDrawLine(disp, _dr, _gc, 0, _b, WinGetW(VROOT), _b); \
100 XDrawLine(disp, _dr, _gc, 0, _b + _d + bt + bb - 1, WinGetW(VROOT), _b + _d + bt + bb - 1); \
101 XDrawRectangle(disp, _dr, _gc, _a + bl + 1, _b + bt + 1, _c - 3, _d - 3); \
104 #define DO_DRAW_MODE_2(_dr, _gc, _a, _b, _c, _d) \
106 if (_c < 3) _c = 3; \
107 if (_d < 3) _d = 3; \
108 XDrawRectangle(disp, _dr, _gc, _a, _b, _c + bl + br - 1, _d + bt + bb - 1); \
109 XDrawRectangle(disp, _dr, _gc, _a + bl + 1, _b + bt + 1, _c - 3, _d - 3); \
112 #define DO_DRAW_MODE_3(_dr, _gc, _a, _b, _c, _d) \
114 XSetFillStyle(disp, _gc, FillStippled); \
115 XSetStipple(disp, _gc, b2); \
116 if ((_c + bl + br > 0) && (bt > 0)) \
117 XFillRectangle(disp, _dr, _gc, _a, _b, _c + bl + br, bt); \
118 if ((_c + bl + br > 0) && (bb > 0)) \
119 XFillRectangle(disp, _dr, _gc, _a, _b + _d + bt, _c + bl + br, bb); \
120 if ((_d > 0) && (bl > 0)) \
121 XFillRectangle(disp, _dr, _gc, _a, _b + bt, bl, _d); \
122 if ((_d > 0) && (br > 0)) \
123 XFillRectangle(disp, _dr, _gc, _a + _c + bl, _b + bt, br, _d); \
124 XSetStipple(disp, _gc, b3); \
125 if ((_c > 0) && (_d > 0)) \
126 XFillRectangle(disp, _dr, _gc, _a + bl + 1, _b + bt + 1, _c - 3, _d - 3); \
129 #define DO_DRAW_MODE_4(_dr, _gc, _a, _b, _c, _d) \
131 XSetFillStyle(disp, _gc, FillStippled); \
132 XSetStipple(disp, _gc, b2); \
133 XFillRectangle(disp, _dr, _gc, _a, _b, _c + bl + br, _d + bt + bb); \
136 #define _SHAPE_SET_RECT(rl, _x, _y, _w, _h) \
138 rl[0].x = (_x); rl[0].y = (_y); rl[0].width = (_w); rl[0].height = 1; \
139 rl[1].x = (_x); rl[1].y = (_y)+(_h)-1; rl[1].width = (_w); rl[1].height = 1; \
140 rl[2].x = (_x); rl[2].y = (_y)+1; rl[2].width = 1; rl[2].height = (_h)-2; \
141 rl[3].x = (_x)+(_w)-1; rl[3].y = (_y)+1; rl[3].width = 1; rl[3].height = (_h)-2; \
144 #define _R(x) (((x) >> 16) & 0xff)
145 #define _G(x) (((x) >> 8) & 0xff)
146 #define _B(x) (((x) ) & 0xff)
151 static char color_valid = 0;
152 static unsigned int color_value = 0;
153 static unsigned int color_pixel;
156 if (color_valid && color_value == Conf.movres.color)
159 color_value = Conf.movres.color;
160 SET_COLOR(&color, _R(color_value), _G(color_value), _B(color_value));
161 EAllocColor(WinGetCmap(VROOT), &color);
162 color_pixel = color.pixel;
170 _ShapeWinDestroy(ShapeWin * sw)
176 if (sw->mask != None)
177 EFreePixmap(sw->mask);
182 _ShapeWinCreate(int md)
186 sw = ECALLOC(ShapeWin, 1);
190 EoInit(sw, EOBJ_TYPE_MISC, None,
191 0, 0, WinGetW(VROOT), WinGetH(VROOT), 2, "Wires");
195 EoSetFloating(sw, 1);
197 ESetWindowBackground(EoGetWin(sw), _ShapeGetColor());
198 #ifdef ShapeInput /* Should really check server too */
199 XShapeCombineRectangles(disp, EoGetXwin(sw),
200 ShapeInput, 0, 0, NULL, 0, ShapeSet, Unsorted);
206 ECreatePixmap(EoGetWin(sw), WinGetW(VROOT), WinGetH(VROOT), 1);
207 sw->gc = EXCreateGC(sw->mask, 0, NULL);
208 if (sw->mask == None || !sw->gc)
215 _ShapeWinDestroy(sw);
220 _ShapeSet(ShapeWin * sw, int md, int x, int y, int w, int h,
221 int bl, int br, int bt, int bb, int seqno)
232 XSetForeground(disp, sw->gc, 0);
233 XFillRectangle(disp, sw->mask, sw->gc,
234 0, 0, WinGetW(VROOT), WinGetH(VROOT));
235 XSetForeground(disp, sw->gc, 1);
236 DO_DRAW_MODE_1(sw->mask, sw->gc, x, y, w, h);
238 EShapeSetMask(EoGetWin(sw), 0, 0, sw->mask);
240 EShapeUnionMask(EoGetWin(sw), 0, 0, sw->mask);
246 _SHAPE_SET_RECT((&rl[0]), x, y, w2, h2);
247 w = (w > 5) ? w - 2 : 3;
248 h = (h > 5) ? h - 2 : 3;
249 _SHAPE_SET_RECT((&rl[4]), x + bl + 1, y + bt + 1, w, h);
252 EShapeSetRects(EoGetWin(sw), 0, 0, rl, 8);
254 EShapeUnionRects(EoGetWin(sw), 0, 0, rl, 8);
256 EoShapeUpdate(sw, 0);
259 static PixImg *root_pi = NULL;
260 static PixImg *ewin_pi = NULL;
261 static PixImg *draw_pi = NULL;
264 _PixImgsCreate(Window root, const EWin * ewin)
266 root_pi = ECreatePixImg(root, WinGetW(VROOT), WinGetH(VROOT));
267 ewin_pi = ECreatePixImg(root, EoGetW(ewin), EoGetH(ewin));
268 draw_pi = ECreatePixImg(root, EoGetW(ewin), EoGetH(ewin));
272 _PixImgsDestroy(void)
274 EDestroyPixImg(root_pi);
275 EDestroyPixImg(ewin_pi);
276 EDestroyPixImg(draw_pi);
277 EBlendRemoveShape(NULL, 0, 0, 0);
278 EBlendPixImg(NULL, NULL, NULL, NULL, 0, 0, 0, 0);
285 DrawEwinShape(EWin * ewin, int md, int x, int y, int w, int h,
286 int firstlast, int seqno)
289 static Pixmap b2 = 0, b3 = 0;
290 Window root = WinGetXwin(VROOT);
291 int x1, y1, w1, h1, dx, dy;
295 /* Quit if no change */
296 if (firstlast == 1 &&
297 (x == ewin->shape_x && y == ewin->shape_y &&
298 (ewin->state.shaded || (w == ewin->shape_w && h == ewin->shape_h))))
304 EwinOpMoveResize(ewin, OPSRC_USER, x, y, w, h);
314 b2 = XCreateBitmapFromData(disp, root, gray_bits, gray_width,
317 b3 = XCreateBitmapFromData(disp, root, gray3_bits, gray3_width,
327 dx = EoGetX(EoGetDesk(ewin));
328 dy = EoGetY(EoGetDesk(ewin));
329 x1 = ewin->shape_x + dx;
330 y1 = ewin->shape_y + dy;
340 if (!ewin->state.shaded)
351 EwinBorderGetSize(ewin, &bl, &br, &bt, &bb);
353 if (md <= 2 && Conf.movres.avoid_server_grab)
355 static ShapeWin *shape_win = NULL;
357 if (firstlast == 0 && !shape_win)
358 shape_win = _ShapeWinCreate(md);
362 _ShapeSet(shape_win, md, x, y, w, h, bl, br, bt, bb, seqno);
369 _ShapeWinDestroy(shape_win);
379 gcv.function = GXxor;
380 gcv.foreground = Dpy.pixel_white;
381 if (gcv.foreground == 0)
382 gcv.foreground = Dpy.pixel_black;
383 gcv.subwindow_mode = IncludeInferiors;
384 gc = EXCreateGC(root,
385 GCFunction | GCForeground | GCSubwindowMode, &gcv);
392 DO_DRAW_MODE_1(root, gc, x1, y1, w1, h1);
395 DO_DRAW_MODE_1(root, gc, x, y, w, h);
399 DO_DRAW_MODE_2(root, gc, x1, y1, w1, h1);
402 DO_DRAW_MODE_2(root, gc, x, y, w, h);
406 DO_DRAW_MODE_3(root, gc, x1, y1, w1, h1);
409 DO_DRAW_MODE_3(root, gc, x, y, w, h);
413 DO_DRAW_MODE_4(root, gc, x1, y1, w1, h1);
416 DO_DRAW_MODE_4(root, gc, x, y, w, h);
425 _PixImgsCreate(root, ewin);
426 if ((!root_pi) || (!ewin_pi) || (!draw_pi))
429 Conf.movres.mode_move = 0;
431 DrawEwinShape(ewin, Conf.movres.mode_move, x, y, w, h,
435 EFillPixmap(root, root_pi->pmap, x1, y1, EoGetW(ewin),
437 gc2 = EXCreateGC(root_pi->pmap, 0, NULL);
438 XCopyArea(disp, root_pi->pmap, ewin_pi->pmap, gc2, x1, y1,
439 EoGetW(ewin), EoGetH(ewin), 0, 0);
441 EBlendPixImg(EoGetWin(ewin), root_pi, ewin_pi, draw_pi, x, y,
442 EoGetW(ewin), EoGetH(ewin));
444 else if (firstlast == 1)
461 if ((adx <= wt) && (ady <= ht))
464 EFillPixmap(root, root_pi->pmap, x, y, -dx, ht);
466 EFillPixmap(root, root_pi->pmap, x + wt - dx, y,
469 EFillPixmap(root, root_pi->pmap, x, y, wt, -dy);
471 EFillPixmap(root, root_pi->pmap, x, y + ht - dy,
475 EFillPixmap(root, root_pi->pmap, x, y, wt, ht);
476 if ((adx <= wt) && (ady <= ht))
478 EBlendPixImg(EoGetWin(ewin), root_pi, ewin_pi, draw_pi,
479 x, y, EoGetW(ewin), EoGetH(ewin));
481 EPastePixmap(root, root_pi->pmap, x1, y1, dx, ht);
483 EPastePixmap(root, root_pi->pmap, x1 + wt + dx,
486 EPastePixmap(root, root_pi->pmap, x1, y1, wt, dy);
488 EPastePixmap(root, root_pi->pmap, x1,
489 y1 + ht + dy, wt, -dy);
493 EPastePixmap(root, root_pi->pmap, x1, y1, wt, ht);
494 EBlendPixImg(EoGetWin(ewin), root_pi, ewin_pi, draw_pi,
495 x, y, EoGetW(ewin), EoGetH(ewin));
497 EBlendRemoveShape(EoGetWin(ewin), root_pi->pmap, x, y);
499 else if (firstlast == 2)
501 EPastePixmap(root, root_pi->pmap, x1, y1, EoGetW(ewin),
505 else if (firstlast == 3)
507 EPastePixmap(root, root_pi->pmap, x, y, EoGetW(ewin),
510 EDestroyPixImg(root_pi);
513 else if (firstlast == 4)
519 root_pi = ECreatePixImg(root, WinGetW(VROOT), WinGetH(VROOT));
520 EFillPixmap(root, root_pi->pmap, x, y, wt, ht);
521 EBlendPixImg(EoGetWin(ewin), root_pi, ewin_pi, draw_pi, x, y,
522 EoGetW(ewin), EoGetH(ewin));
536 if (firstlast == 0 || firstlast == 2 || firstlast == 4)
538 ewin->req_x = ewin->shape_x;
539 ewin->req_y = ewin->shape_y;