window.c clean code 1
[wmaker-crm.git] / util / wmagnify.c
blob91e2d2ada400d571b362382392498b5ae9909f99
1 /*
2 * magnify - a X utility for magnifying screen image
4 * 2000/5/21 Alfredo K. Kojima
6 * This program is in the Public Domain.
7 */
9 #include <X11/Xproto.h>
11 #include <WINGs/WINGs.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <stdio.h>
17 * TODO:
18 * - lens that shows where it's magnifying
23 int refreshrate = 200;
25 typedef struct {
26 Drawable d;
27 XRectangle *rects;
28 int rectP;
29 unsigned long lastpixel;
30 unsigned long *buffer;
31 int width, height;
32 int rwidth, rheight; /* size of window in real pixels */
33 int magfactor;
34 int refreshrate;
36 WMWindow *win;
37 WMLabel *label;
38 WMPixmap *pixmap;
40 WMWindow *dlg;
42 WMSlider *speed;
43 WMSlider *magnify;
44 WMButton *okB;
45 WMButton *cancelB;
46 WMButton *newB;
48 int x, y;
49 Bool frozen;
50 Bool firstDraw;
51 Bool markPointerHotspot;
53 WMHandlerID tid;
54 } BufferData;
56 static BufferData *newWindow(int magfactor);
58 int windowCount = 0;
60 int rectBufferSize = 32;
61 Display *dpy, *vdpy;
62 WMScreen *scr;
63 unsigned int black;
64 WMColor *cursorColor1;
65 WMColor *cursorColor2;
67 #ifndef __GNUC__
68 #define inline
69 #endif
71 static BufferData *makeBufferData(WMWindow * win, WMLabel * label, int width, int height, int magfactor)
73 BufferData *data;
75 data = wmalloc(sizeof(BufferData));
77 data->rwidth = width;
78 data->rheight = height;
80 data->refreshrate = refreshrate;
82 data->firstDraw = True;
84 data->magfactor = magfactor;
86 data->rects = wmalloc(sizeof(XRectangle) * rectBufferSize);
87 data->rectP = 0;
89 data->win = win;
90 data->label = label;
92 data->pixmap = WMCreatePixmap(scr, width, height, WMScreenDepth(scr), False);
93 WMSetLabelImage(data->label, data->pixmap);
95 data->d = WMGetPixmapXID(data->pixmap);
97 data->frozen = False;
99 width /= magfactor;
100 height /= magfactor;
101 data->buffer = wmalloc(sizeof(unsigned long) * width * height);
102 data->width = width;
103 data->height = height;
105 return data;
108 static void resizeBufferData(BufferData * data, int width, int height, int magfactor)
110 int w = width / magfactor;
111 int h = height / magfactor;
113 data->rwidth = width;
114 data->rheight = height;
115 data->firstDraw = True;
116 data->magfactor = magfactor;
117 data->buffer = wrealloc(data->buffer, sizeof(unsigned long) * w * h);
118 data->width = w;
119 data->height = h;
120 memset(data->buffer, 0, w * h * sizeof(unsigned long));
122 WMResizeWidget(data->label, width, height);
124 WMReleasePixmap(data->pixmap);
125 data->pixmap = WMCreatePixmap(scr, width, height, WMScreenDepth(scr), False);
126 WMSetLabelImage(data->label, data->pixmap);
128 data->d = WMGetPixmapXID(data->pixmap);
131 static int drawpoint(BufferData * data, unsigned long pixel, int x, int y)
133 static GC gc = NULL;
134 Bool flush = (x < 0);
136 if (!flush) {
137 if (data->buffer[x + data->width * y] == pixel && !data->firstDraw)
138 return 0;
140 data->buffer[x + data->width * y] = pixel;
142 if (gc == NULL) {
143 gc = XCreateGC(dpy, DefaultRootWindow(dpy), 0, NULL);
146 if (!flush && data->lastpixel == pixel && data->rectP < rectBufferSize) {
147 data->rects[data->rectP].x = x * data->magfactor;
148 data->rects[data->rectP].y = y * data->magfactor;
149 data->rects[data->rectP].width = data->magfactor;
150 data->rects[data->rectP].height = data->magfactor;
151 data->rectP++;
153 return 0;
155 XSetForeground(dpy, gc, data->lastpixel);
156 XFillRectangles(dpy, data->d, gc, data->rects, data->rectP);
157 data->rectP = 0;
158 data->rects[data->rectP].x = x * data->magfactor;
159 data->rects[data->rectP].y = y * data->magfactor;
160 data->rects[data->rectP].width = data->magfactor;
161 data->rects[data->rectP].height = data->magfactor;
162 data->rectP++;
164 data->lastpixel = pixel;
166 return 1;
169 static inline unsigned long getpix(XImage * image, int x, int y, int xoffs, int yoffs)
171 if (x < xoffs || y < yoffs || x >= xoffs + image->width || y >= yoffs + image->height) {
172 return black;
174 return XGetPixel(image, x - xoffs, y - yoffs);
177 static void updateImage(BufferData * data, int rx, int ry)
179 int gx, gy, gw, gh;
180 int x, y;
181 int xoffs, yoffs;
182 int changedPixels = 0;
183 XImage *image;
185 gw = data->width;
186 gh = data->height;
188 gx = rx - gw / 2;
189 gy = ry - gh / 2;
191 xoffs = yoffs = 0;
192 if (gx < 0) {
193 xoffs = abs(gx);
194 gw += gx;
195 gx = 0;
197 if (gx + gw >= WidthOfScreen(DefaultScreenOfDisplay(vdpy))) {
198 gw = WidthOfScreen(DefaultScreenOfDisplay(vdpy)) - gx;
200 if (gy < 0) {
201 yoffs = abs(gy);
202 gh += gy;
203 gy = 0;
205 if (gy + gh >= HeightOfScreen(DefaultScreenOfDisplay(vdpy))) {
206 gh = HeightOfScreen(DefaultScreenOfDisplay(vdpy)) - gy;
209 image = XGetImage(vdpy, DefaultRootWindow(vdpy), gx, gy, gw, gh, AllPlanes, ZPixmap);
211 for (y = 0; y < data->height; y++) {
212 for (x = 0; x < data->width; x++) {
213 unsigned long pixel;
215 pixel = getpix(image, x, y, xoffs, yoffs);
217 if (drawpoint(data, pixel, x, y))
218 changedPixels++;
221 /* flush the point cache */
222 drawpoint(data, 0, -1, -1);
224 XDestroyImage(image);
226 if (data->markPointerHotspot && !data->frozen) {
227 XRectangle rects[4];
229 rects[0].x = (data->width / 2 - 3) * data->magfactor;
230 rects[0].y = (data->height / 2) * data->magfactor;
231 rects[0].width = 2 * data->magfactor;
232 rects[0].height = data->magfactor;
234 rects[1].x = (data->width / 2 + 2) * data->magfactor;
235 rects[1].y = (data->height / 2) * data->magfactor;
236 rects[1].width = 2 * data->magfactor;
237 rects[1].height = data->magfactor;
239 XFillRectangles(dpy, data->d, WMColorGC(cursorColor1), rects, 2);
241 rects[2].y = (data->height / 2 - 3) * data->magfactor;
242 rects[2].x = (data->width / 2) * data->magfactor;
243 rects[2].height = 2 * data->magfactor;
244 rects[2].width = data->magfactor;
246 rects[3].y = (data->height / 2 + 2) * data->magfactor;
247 rects[3].x = (data->width / 2) * data->magfactor;
248 rects[3].height = 2 * data->magfactor;
249 rects[3].width = data->magfactor;
251 XFillRectangles(dpy, data->d, WMColorGC(cursorColor2), rects + 2, 2);
254 if (changedPixels > 0) {
255 WMRedisplayWidget(data->label);
258 data->firstDraw = False;
261 static void update(void *d)
263 BufferData *data = (BufferData *) d;
264 Window win;
265 int rx, ry;
266 int bla;
267 unsigned ubla;
269 if (data->frozen) {
270 rx = data->x;
271 ry = data->y;
272 } else {
273 XQueryPointer(dpy, DefaultRootWindow(dpy), &win, &win, &rx, &ry, &bla, &bla, &ubla);
275 updateImage(data, rx, ry);
277 data->tid = WMAddTimerHandler(data->refreshrate, update, data);
280 void resizedWindow(void *d, WMNotification * notif)
282 BufferData *data = (BufferData *) d;
283 WMView *view = (WMView *) WMGetNotificationObject(notif);
284 WMSize size;
286 size = WMGetViewSize(view);
288 resizeBufferData(data, size.width, size.height, data->magfactor);
291 void closeWindow(WMWidget * w, void *d)
293 BufferData *data = (BufferData *) d;
295 windowCount--;
296 if (windowCount == 0) {
297 exit(0);
298 } else {
299 WMDeleteTimerHandler(data->tid);
300 WMDestroyWidget(w);
301 wfree(data->buffer);
302 wfree(data->rects);
303 WMReleasePixmap(data->pixmap);
304 wfree(data);
308 static void keyHandler(XEvent * event, void *d)
310 BufferData *data = (BufferData *) d;
311 char buf[32];
312 KeySym ks;
313 WMView *view = WMWidgetView(data->win);
314 WMSize size;
316 size = WMGetViewSize(view);
318 if (XLookupString(&event->xkey, buf, 31, &ks, NULL) > 0) {
319 switch (buf[0]) {
320 case 'n':
321 newWindow(data->magfactor);
322 break;
323 case 'm':
324 data->markPointerHotspot = !data->markPointerHotspot;
325 break;
326 case 'f':
327 case ' ':
328 data->frozen = !data->frozen;
329 if (data->frozen) {
330 data->x = event->xkey.x_root;
331 data->y = event->xkey.y_root;
332 sprintf(buf, "[Magnify %ix]", data->magfactor);
333 } else {
334 sprintf(buf, "Magnify %ix", data->magfactor);
336 WMSetWindowTitle(data->win, buf);
337 break;
338 case '1':
339 case '2':
340 case '3':
341 case '4':
342 case '5':
343 case '6':
344 case '7':
345 case '8':
346 case '9':
347 resizeBufferData(data, size.width, size.height, buf[0] - '0');
348 if (data->frozen) {
349 sprintf(buf, "[Magnify %ix]", data->magfactor);
350 } else {
351 sprintf(buf, "Magnify %ix", data->magfactor);
353 WMSetWindowTitle(data->win, buf);
354 break;
359 static BufferData *newWindow(int magfactor)
361 WMWindow *win;
362 WMLabel *label;
363 BufferData *data;
364 char buf[32];
366 windowCount++;
368 win = WMCreateWindow(scr, "magnify");
369 WMResizeWidget(win, 300, 200);
370 sprintf(buf, "Magnify %ix", magfactor);
371 WMSetWindowTitle(win, buf);
372 WMSetViewNotifySizeChanges(WMWidgetView(win), True);
374 label = WMCreateLabel(win);
375 WMResizeWidget(label, 300, 200);
376 WMMoveWidget(label, 0, 0);
377 WMSetLabelRelief(label, WRSunken);
378 WMSetLabelImagePosition(label, WIPImageOnly);
380 data = makeBufferData(win, label, 300, 200, magfactor);
382 WMCreateEventHandler(WMWidgetView(win), KeyReleaseMask, keyHandler, data);
384 WMAddNotificationObserver(resizedWindow, data, WMViewSizeDidChangeNotification, WMWidgetView(win));
386 WMRealizeWidget(win);
388 WMMapSubwidgets(win);
389 WMMapWidget(win);
391 WMSetWindowCloseAction(win, closeWindow, data);
392 data->tid = WMAddTimerHandler(refreshrate, update, data);
394 return data;
397 int main(int argc, char **argv)
399 int i;
400 char *display = "";
401 char *vdisplay = NULL;
402 int magfactor = 2;
404 WMInitializeApplication("Magnify", &argc, argv);
406 for (i = 1; i < argc; i++) {
407 if (strcmp(argv[i], "-display") == 0) {
408 i++;
409 if (i >= argc)
410 goto help;
411 display = argv[i];
412 } else if (strcmp(argv[i], "-vdisplay") == 0) {
413 i++;
414 if (i >= argc)
415 goto help;
416 vdisplay = argv[i];
417 } else if (strcmp(argv[i], "-m") == 0) {
418 i++;
419 if (i >= argc)
420 goto help;
421 magfactor = atoi(argv[i]);
422 if (magfactor < 1 || magfactor > 32) {
423 printf("%s:invalid magnification factor ``%s''\n", argv[0], argv[i]);
424 exit(1);
426 } else if (strcmp(argv[i], "-r") == 0) {
427 i++;
428 if (i >= argc)
429 goto help;
430 refreshrate = atoi(argv[i]);
431 if (refreshrate < 1) {
432 printf("%s:invalid refresh rate ``%s''\n", argv[0], argv[i]);
433 exit(1);
435 } else if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) {
436 help:
438 printf("Usage: %s [options]\n", argv[0]);
439 puts("Options:");
440 puts(" -display <display> display that should be used");
441 puts(" -m <number> change magnification factor (default 2)");
442 puts(" -r <number> change refresh delay, in milliseconds (default 200)");
443 puts("Keys:");
444 puts(" 1,2,3,4,5,6,7,8,9 change the magnification factor");
445 puts(" <space>, f freeze the 'camera', making it magnify only the current\n"
446 " position");
447 puts(" n create a new window");
448 puts(" m show/hide the pointer hotspot mark");
449 exit(0);
453 dpy = XOpenDisplay(display);
454 if (!dpy) {
455 puts("could not open display");
456 exit(1);
459 if (vdisplay) {
460 vdpy = XOpenDisplay(vdisplay);
461 if (!vdpy) {
462 puts("could not open display to be viewed");
463 exit(1);
465 } else {
466 vdpy = dpy;
469 /* calculate how many rectangles we can send in a trip to the server */
470 rectBufferSize = XMaxRequestSize(dpy) - 128;
471 rectBufferSize /= sizeof(XRectangle);
472 if (rectBufferSize < 1)
473 rectBufferSize = 1;
475 black = BlackPixel(dpy, DefaultScreen(dpy));
477 scr = WMCreateScreen(dpy, 0);
479 cursorColor1 = WMCreateNamedColor(scr, "#ff0000", False);
480 cursorColor2 = WMCreateNamedColor(scr, "#00ff00", False);
482 newWindow(magfactor);
484 WMScreenMainLoop(scr);
486 return 0;