1 /*
2 * xvroot.c - '-root' related code for XV
3 *
4 * Contains:
5 * MakeRootPic()
6 * ClearRoot()
7 * SaveRootInfo()
8 * KillOldRootInfo()
9 */
10
11 #include "copyright.h"
12
13 #include "xv.h"
14
15 #include "bits/root_weave"
16
17
18 /* local function pre-definitions */
19 static void killRootPix PARM((void));
20
21
22 /***********************************/
MakeRootPic()23 void MakeRootPic()
24 {
25 /* called after 'epic' has been generated (if we're using root).
26 creates the XImage and the pixmap, sets the root to the new
27 pixmap, and refreshes the display */
28
29 Pixmap tmpPix;
30 int i, j, k, rmode;
31 unsigned int rpixw, rpixh;
32
33 killRootPix();
34
35 rmode = rootMode;
36 /* if eWIDE,eHIGH == dispWIDE,dispHIGH just use 'normal' mode to save mem */
37 if (rmode>=RM_CENTER && eWIDE==dispWIDE && eHIGH==dispHIGH) rmode=RM_NORMAL;
38
39 /* determine how big tmpPix should be based on rootMode */
40 switch (rmode) {
41 case RM_NORMAL:
42 case RM_CENTILE:
43 case RM_TILE: rpixw = eWIDE; rpixh = eHIGH; break;
44 case RM_MIRROR:
45 case RM_IMIRROR: rpixw = 2*eWIDE; rpixh = 2*eHIGH; break;
46 case RM_CSOLID:
47 case RM_UPLEFT:
48 case RM_CWARP:
49 case RM_CBRICK: rpixw = dispWIDE; rpixh = dispHIGH; break;
50
51 case RM_ECENTER:
52 case RM_ECMIRR: rpixw = dispWIDE; rpixh = dispHIGH; break;
53
54 default: rpixw = eWIDE; rpixh = eHIGH; break;
55 }
56 if (nolimits) { RANGE(rpixw, 1, maxWIDE); RANGE(rpixh, 1, maxHIGH); }
57 else { RANGE(rpixw, 1, dispWIDE); RANGE(rpixh, 1, dispHIGH); }
58
59 /* create tmpPix */
60 xerrcode = 0;
61 tmpPix = XCreatePixmap(theDisp, mainW, rpixw, rpixh, dispDEEP);
62 XSync(theDisp, False);
63 if (xerrcode || !tmpPix) {
64 ErrPopUp("Insufficient memory in X server to store root pixmap.",
65 "\nDarn!");
66 return;
67 }
68
69
70 if (rmode == RM_NORMAL || rmode == RM_TILE) {
71 XPutImage(theDisp, tmpPix, theGC, theImage, 0,0, 0,0,
72 (u_int) eWIDE, (u_int) eHIGH);
73 }
74
75 else if (rmode == RM_MIRROR || rmode == RM_IMIRROR) {
76 /* quadrant 2 */
77 XPutImage(theDisp, tmpPix, theGC, theImage, 0,0, 0,0,
78 (u_int) eWIDE, (u_int) eHIGH);
79 if (epic == NULL) FatalError("epic == NULL in RM_MIRROR code...\n");
80
81 /* quadrant 1 */
82 FlipPic(epic, eWIDE, eHIGH, 0); /* flip horizontally */
83 CreateXImage();
84 XPutImage(theDisp, tmpPix, theGC, theImage, 0,0, eWIDE,0,
85 (u_int) eWIDE, (u_int) eHIGH);
86
87 /* quadrant 4 */
88 FlipPic(epic, eWIDE, eHIGH, 1); /* flip vertically */
89 CreateXImage();
90 XPutImage(theDisp, tmpPix, theGC, theImage, 0,0, eWIDE,eHIGH,
91 (u_int) eWIDE, (u_int) eHIGH);
92
93 /* quadrant 3 */
94 FlipPic(epic, eWIDE, eHIGH, 0); /* flip horizontally */
95 CreateXImage();
96 XPutImage(theDisp, tmpPix, theGC, theImage, 0,0, 0,eHIGH,
97 (u_int) eWIDE, (u_int) eHIGH);
98
99 FlipPic(epic, eWIDE, eHIGH, 1); /* flip vertically (back to orig) */
100 CreateXImage(); /* put back to original state */
101 }
102
103
104 else if (rmode == RM_CENTER || rmode == RM_CENTILE || rmode == RM_CSOLID ||
105 rmode == RM_CWARP || rmode == RM_CBRICK || rmode == RM_UPLEFT) {
106 /* do some stuff to set up the border around the picture */
107
108 if (rmode != RM_CENTILE) {
109 XSetForeground(theDisp, theGC, rootbg);
110 XFillRectangle(theDisp, tmpPix, theGC, 0,0, dispWIDE, dispHIGH);
111 }
112
113 if (rmode == RM_CENTILE) { /* hagan-style tiling */
114 int x, y, w, h, ax, ay, w1, h1, offx, offy;
115
116 w = eWIDE; h = eHIGH;
117
118 /* compute anchor pt (top-left coords of top-left-most pic) */
119 ax = (dispWIDE-w)/2; ay = (dispHIGH-h)/2;
120 while (ax>0) ax = ax - w;
121 while (ay>0) ay = ay - h;
122
123 for (i=ay; i < (int) eHIGH; i+=h) {
124 for (j=ax; j < (int) eWIDE; j+=w) {
125 /* if image goes off tmpPix, only draw subimage */
126
127 x = j; y = i; w1 = w; h1 = h; offx = offy = 0;
128 if (x<0) { offx = -x; w1 -= offx; x = 0; }
129 if (x+w1>eWIDE) { w1 = (eWIDE-x); }
130
131 if (y<0) { offy = -y; h1 -= offy; y = 0; }
132 if (y+h1>eHIGH) { h1 = (eHIGH-y); }
133
134 XPutImage(theDisp, tmpPix, theGC, theImage, offx, offy,
135 x, y, (u_int) w1, (u_int) h1);
136 }
137 }
138 }
139
140 else if (rmode == RM_CSOLID) { }
141
142 else if (rmode == RM_UPLEFT) {
143
144 XPutImage(theDisp, tmpPix, theGC, theImage, 0,0, 0,0,
145 (u_int) eWIDE, (u_int) eHIGH);
146 }
147
148 else if (rmode == RM_CWARP) { /* warp effect */
149 XSetForeground(theDisp, theGC, rootfg);
150 for (i=0; i<=dispWIDE; i+=8)
151 XDrawLine(theDisp,tmpPix,theGC, i,0, (int) dispWIDE-i,(int) dispHIGH);
152 for (i=0; i<=dispHIGH; i+=8)
153 XDrawLine(theDisp,tmpPix,theGC, 0,i, (int) dispWIDE, (int) dispHIGH-i);
154 }
155
156 else if (rmode == RM_CBRICK) { /* brick effect */
157 XSetForeground(theDisp, theGC, rootfg);
158 for (i=k=0; i<dispHIGH; i+=20,k++) {
159 XDrawLine(theDisp, tmpPix, theGC, 0, i, (int) dispWIDE, i);
160 for (j=(k&1) * 20 + 10; j<dispWIDE; j+=40)
161 XDrawLine(theDisp, tmpPix, theGC, j,i,j,i+20);
162 }
163 }
164
165
166 /* draw the image centered on top of the background */
167 if ((rmode != RM_CENTILE) && (rmode != RM_UPLEFT))
168 XPutImage(theDisp, tmpPix, theGC, theImage, 0,0,
169 ((int) dispWIDE-eWIDE)/2, ((int) dispHIGH-eHIGH)/2,
170 (u_int) eWIDE, (u_int) eHIGH);
171 }
172
173
174 else if (rmode == RM_ECENTER || rmode == RM_ECMIRR) {
175 int fliph, flipv;
176
177 fliph = 0; flipv = 0;
178
179 if (dispWIDE == eWIDE) {
180 /* horizontal center line */
181 int y, ay;
182
183 y = eHIGH - ((dispHIGH/2)%eHIGH); /* Starting point in picture to copy */
184 ay = 0; /* Vertical anchor point */
185 while (ay < dispHIGH) {
186 XPutImage(theDisp, tmpPix, theGC, theImage, 0,y,
187 0,ay, (u_int) eWIDE, (u_int) eHIGH);
188 ay += eHIGH - y;
189 y = 0;
190 if (rmode == RM_ECMIRR) {
191 FlipPic(epic, eWIDE, eHIGH, 1); flipv = !flipv;
192 CreateXImage();
193 }
194 }
195 }
196 else if (dispHIGH == eHIGH) {
197 /* vertical centerline */
198 int x, ax;
199
200 x = eWIDE - ((dispWIDE/2)%eWIDE); /* Starting point in picture to copy */
201 ax = 0; /* Horizontal anchor point */
202 while (ax < dispWIDE) {
203 XPutImage(theDisp, tmpPix, theGC, theImage, x,0,
204 ax,0, (u_int) eWIDE, (u_int) eHIGH);
205 ax += eWIDE - x;
206 x = 0;
207 if (rmode == RM_ECMIRR) {
208 FlipPic(epic, eWIDE, eHIGH, 0); fliph = !fliph;
209 CreateXImage();
210 }
211 }
212 }
213 else {
214 /* vertical and horizontal centerlines */
215 int x,y, ax,ay;
216
217 y = eHIGH - ((dispHIGH/2)%eHIGH); /* Starting point in picture to copy */
218 ay = 0; /* Vertical anchor point */
219
220 while (ay < dispHIGH) {
221 x = eWIDE - ((dispWIDE/2)%eWIDE);/* Starting point in picture to cpy */
222 ax = 0; /* Horizontal anchor point */
223 while (ax < dispWIDE) {
224 XPutImage(theDisp, tmpPix, theGC, theImage, x,y,
225 ax,ay, (u_int) eWIDE, (u_int) eHIGH);
226 if (rmode == RM_ECMIRR) {
227 FlipPic(epic, eWIDE, eHIGH, 0); fliph = !fliph;
228 CreateXImage();
229 }
230 ax += eWIDE - x;
231 x = 0;
232 }
233 if (rmode == RM_ECMIRR) {
234 FlipPic(epic, eWIDE, eHIGH, 1); flipv = !flipv;
235 if (fliph) { /* leftmost image is always non-hflipped */
236 FlipPic(epic, eWIDE, eHIGH, 0); fliph = !fliph;
237 }
238 CreateXImage();
239 }
240 ay += eHIGH - y;
241 y = 0;
242 }
243 }
244
245 /* put epic back to normal */
246 if (fliph) FlipPic(epic, eWIDE, eHIGH, 0);
247 if (flipv) FlipPic(epic, eWIDE, eHIGH, 1);
248 }
249
250
251 XSetWindowBackgroundPixmap(theDisp, mainW, tmpPix);
252 XFreePixmap(theDisp, tmpPix);
253
254 XClearWindow(theDisp, mainW);
255 }
256
257
258
259 /************************************************************************/
ClearRoot()260 void ClearRoot()
261 {
262 killRootPix();
263 XClearWindow(theDisp, vrootW);
264 XFlush(theDisp);
265 }
266
267
268 /************************************************************************/
killRootPix()269 static void killRootPix()
270 {
271 Pixmap pix, bitmap;
272 GC gc;
273 XGCValues gc_init;
274
275 if (vrootW == rootW) {
276 XSetWindowBackgroundPixmap(theDisp, rootW, None);
277 }
278
279 else {
280 bitmap = XCreateBitmapFromData(theDisp, vrootW, (char *) root_weave_bits,
281 root_weave_width, root_weave_height);
282
283 gc_init.foreground = BlackPixel(theDisp, theScreen);
284 gc_init.background = WhitePixel(theDisp, theScreen);
285 gc = XCreateGC(theDisp, vrootW, GCForeground|GCBackground, &gc_init);
286 pix = XCreatePixmap(theDisp, vrootW, root_weave_width,
287 root_weave_height,
288 (unsigned int) DefaultDepth(theDisp, theScreen));
289
290 XCopyPlane(theDisp, bitmap, pix, gc, 0,0, root_weave_width,
291 root_weave_height, 0,0, (unsigned long) 1);
292 XSetWindowBackgroundPixmap(theDisp, vrootW, pix);
293
294 XFreeGC(theDisp, gc);
295 XFreePixmap(theDisp, bitmap);
296 XFreePixmap(theDisp, pix);
297 }
298 }
299
300
301
302 /***********************************/
SaveRootInfo()303 void SaveRootInfo()
304 {
305 /* called when using root window. stores the pixmap ID used to draw the
306 root window in a property. This will be used later to free all resources
307 allocated by this instantiation of xv (ie, the alloc'd colors). These
308 resources are kept alloc'ed after client exits so that rainbow effect
309 is avoided */
310
311 Atom prop;
312 static Pixmap riPix = (Pixmap) NULL;
313
314 if ( !(theVisual->class & 1)) return; /* no colormap to worry about */
315 if (riPix) return; /* it's already been saved once */
316
317 riPix = XCreatePixmap(theDisp, vrootW, 1, 1, 1);
318 if (!riPix) return; /* unable to save. thankfully, unlikely to happen */
319
320 prop = XInternAtom(theDisp, "_XSETROOT_ID", False);
321 if (!prop) FatalError("couldn't create _XSETROOT_ID atom");
322
323 XChangeProperty(theDisp, vrootW, prop, XA_PIXMAP, 32, PropModeReplace,
324 (unsigned char *) &riPix, 1);
325
326 XSetCloseDownMode(theDisp, RetainPermanent);
327 }
328
329
330 /***********************************/
KillOldRootInfo()331 void KillOldRootInfo()
332 {
333 /* get the pixmap ID from the _XSETROOT_ID property, and kill it */
334
335 Atom prop, type;
336 int format;
337 unsigned long length, after;
338 unsigned char *data;
339
340 prop = XInternAtom(theDisp, "_XSETROOT_ID", True);
341 if (prop == None) return; /* no old pixmap to kill */
342
343 if (XGetWindowProperty(theDisp, vrootW, prop, 0L, 1L, True,
344 AnyPropertyType, &type, &format, &length,
345 &after, &data) == Success) {
346
347 if (type==XA_PIXMAP && format==32 && length==1 && after==0 && data) {
348 XKillClient(theDisp, *((Pixmap *)data));
349 XDeleteProperty(theDisp, vrootW, prop);
350 }
351
352 if (data) XFree((char *) data);
353 }
354 }
355
356
357
358
359