1 /* backing.c - save, extend, and restore contents of root window
2
3 Copyright 2001 Carl Worth
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14 */
15
16 #include <stdio.h>
17 #include <X11/Xlib.h>
18
19 #include "backing.h"
20
21 #ifdef DMALLOC
22 #include "dmalloc.h"
23 #endif
24
backing_init(backing_t * backing,Display * dpy,Window root,int width,int height,int depth)25 int backing_init(backing_t *backing, Display *dpy, Window root, int width, int height, int depth)
26 {
27 XRenderPictFormat templ;
28 int screen = DefaultScreen(dpy);
29 unsigned long gcm;
30 XGCValues gcv;
31
32 backing->dpy = dpy;
33 backing->root = root;
34 backing->active = 0;
35
36 gcm = 0;
37 gcm |= GCSubwindowMode; gcv.subwindow_mode = IncludeInferiors;
38 backing->gc = XCreateGC(backing->dpy, backing->root, gcm, &gcv);
39
40 backing->root_pixmap = 0;
41 backing->brush_pixmap = 0;
42 backing->total_width = width;
43 backing->total_height = height;
44 backing->depth = depth;
45 backing->root_pict = 0;
46 backing->brush_pict = 0;
47
48 backing->root_format = XRenderFindVisualFormat(dpy,DefaultVisual(dpy, screen));
49
50 templ.type = PictTypeDirect;
51 templ.depth = 32;
52 templ.direct.alpha = 24;
53 templ.direct.alphaMask = 0xff;
54 templ.direct.red = 16;
55 templ.direct.redMask = 0xff;
56 templ.direct.green = 8;
57 templ.direct.greenMask = 0xff;
58 templ.direct.blue = 0;
59 templ.direct.blueMask = 0xff;
60 backing->brush_format = XRenderFindFormat (dpy,
61 PictFormatType|
62 PictFormatDepth|
63 PictFormatAlpha|
64 PictFormatAlphaMask|
65 PictFormatRed|
66 PictFormatRedMask|
67 PictFormatGreen|
68 PictFormatGreenMask|
69 PictFormatBlue|
70 PictFormatBlueMask,
71 &templ, 0);
72
73 return 0;
74 }
75
backing_deinit(backing_t * backing)76 void backing_deinit(backing_t *backing)
77 {
78 backing->active = 0;
79 XFreeGC(backing->dpy, backing->gc);
80 if (backing->root_pixmap) {
81 XFreePixmap(backing->dpy, backing->root_pixmap);
82 backing->root_pixmap = 0;
83
84 XRenderFreePicture(backing->dpy, backing->root_pict);
85 backing->root_pict = 0;
86 }
87 if (backing->brush_pixmap) {
88 XFreePixmap(backing->dpy, backing->brush_pixmap);
89 backing->brush_pixmap = 0;
90
91 XRenderFreePicture(backing->dpy, backing->brush_pict);
92 backing->brush_pict = 0;
93 }
94 }
95
backing_save(backing_t * backing,int x,int y)96 int backing_save(backing_t *backing, int x, int y)
97 {
98 if (backing->active == 0) {
99 backing_reconfigure(backing,
100 backing->total_width,
101 backing->total_height,
102 backing->depth);
103 backing->active = 1;
104
105 backing->x = BACKING_INC * (x / BACKING_INC);
106 backing->y = BACKING_INC * (y / BACKING_INC);
107 backing->width = BACKING_INC;
108 backing->height = BACKING_INC;
109 XCopyArea(backing->dpy, backing->root,
110 backing->root_pixmap, backing->gc,
111 backing->x, backing->y,
112 backing->width, backing->height,
113 backing->x, backing->y);
114 } else {
115 if (x >= backing->x + backing->width) {
116 int new_max_x, width_inc;
117 new_max_x = BACKING_INC * ((x / BACKING_INC) + 1);
118 width_inc = new_max_x - (backing->x + backing->width);
119 XCopyArea(backing->dpy, backing->root,
120 backing->root_pixmap, backing->gc,
121 backing->x + backing->width, backing->y,
122 width_inc, backing->height,
123 backing->x + backing->width, backing->y);
124 backing->width += width_inc;
125 }
126 if (x < backing->x) {
127 int new_x, width_inc;
128 new_x = BACKING_INC * (x / BACKING_INC);
129 width_inc = backing->x - new_x;
130 XCopyArea(backing->dpy, backing->root,
131 backing->root_pixmap, backing->gc,
132 new_x, backing->y,
133 width_inc, backing->height,
134 new_x, backing->y);
135 backing->width += width_inc;
136 backing->x = new_x;
137 }
138 if (y >= backing->y + backing->height) {
139 int new_max_y, height_inc;
140 new_max_y = BACKING_INC * ((y / BACKING_INC) + 1);
141 height_inc = new_max_y - (backing->y + backing->height);
142 XCopyArea(backing->dpy, backing->root,
143 backing->root_pixmap, backing->gc,
144 backing->x, backing->y + backing->height,
145 backing->width, height_inc,
146 backing->x, backing->y + backing->height);
147 backing->height += height_inc;
148 }
149 if (y < backing->y) {
150 int new_y, height_inc;
151 new_y = BACKING_INC * (y / BACKING_INC);
152 height_inc = backing->y - new_y;
153 XCopyArea(backing->dpy, backing->root,
154 backing->root_pixmap, backing->gc,
155 backing->x, new_y,
156 backing->width, height_inc,
157 backing->x, new_y);
158 backing->height += height_inc;
159 backing->y = new_y;
160 }
161 }
162 return 0;
163 }
164
backing_restore(backing_t * backing)165 int backing_restore(backing_t *backing)
166 {
167 XCopyArea(backing->dpy, backing->root_pixmap,
168 backing->root, backing->gc,
169 backing->x, backing->y,
170 backing->width, backing->height,
171 backing->x, backing->y);
172 backing->active = 0;
173
174 XFreePixmap(backing->dpy, backing->root_pixmap);
175 backing->root_pixmap = 0;
176 XRenderFreePicture(backing->dpy, backing->root_pict);
177 backing->root_pict = 0;
178
179 XFreePixmap(backing->dpy, backing->brush_pixmap);
180 backing->brush_pixmap = 0;
181 XRenderFreePicture(backing->dpy, backing->brush_pict);
182 backing->brush_pict = 0;
183
184 return 0;
185 }
186
backing_reconfigure(backing_t * backing,int width,int height,int depth)187 int backing_reconfigure(backing_t *backing, int width, int height, int depth)
188 {
189 XRenderColor color;
190 XRenderPictureAttributes attr;
191 backing_t old_backing = *backing;
192
193 backing->total_width = width;
194 backing->total_height = height;
195 backing->depth = depth;
196
197 backing->root_pixmap = XCreatePixmap(backing->dpy, backing->root,
198 backing->total_width,
199 backing->total_height,
200 depth);
201 attr.subwindow_mode = IncludeInferiors;
202 backing->root_pict = XRenderCreatePicture(backing->dpy,
203 backing->root,
204 backing->root_format,
205 CPSubwindowMode,
206 &attr);
207
208 backing->brush_pixmap = XCreatePixmap(backing->dpy, backing->root,
209 backing->total_width,
210 backing->total_height,
211 32);
212 backing->brush_pict = XRenderCreatePicture(backing->dpy,
213 backing->brush_pixmap,
214 backing->brush_format,
215 0, 0);
216
217 color.red = 0;
218 color.green = 0;
219 color.blue = 0;
220 color.alpha = 0;
221 XRenderFillRectangle(backing->dpy,
222 PictOpSrc, backing->brush_pict, &color,
223 0, 0, backing->total_width, backing->total_height);
224
225 if (old_backing.root_pixmap) {
226 if (old_backing.depth == depth) {
227 XCopyArea(backing->dpy, old_backing.root_pixmap,
228 backing->root_pixmap, backing->gc,
229 old_backing.x, old_backing.y,
230 old_backing.width, old_backing.height,
231 old_backing.x, old_backing.y);
232 }
233 XFreePixmap(old_backing.dpy, old_backing.root_pixmap);
234 old_backing.root_pixmap = 0;
235 XRenderFreePicture(old_backing.dpy, old_backing.root_pict);
236 old_backing.root_pict = 0;
237 }
238 if (old_backing.brush_pixmap) {
239 XRenderComposite(backing->dpy,
240 PictOpSrc,
241 old_backing.brush_pict, None, backing->brush_pict,
242 0, 0, 0, 0, 0, 0,
243 old_backing.total_width, old_backing.total_height);
244 XFreePixmap(old_backing.dpy, old_backing.brush_pixmap);
245 old_backing.brush_pixmap = 0;
246 XRenderFreePicture(old_backing.dpy, old_backing.brush_pict);
247 old_backing.brush_pict = 0;
248 }
249
250 return 0;
251 }
252
253