2 * magnify - a X utility for magnifying screen image
4 * 2000/5/21 Alfredo K. Kojima
6 * This program is in the Public Domain.
9 #include <X11/Xproto.h>
16 int refreshrate
= 200;
23 unsigned long lastpixel
;
24 unsigned long *buffer
;
40 static BufferData
*newWindow(int magfactor
);
45 int rectBufferSize
= 32;
56 makeBufferData(WMWindow
*win
, WMLabel
*label
, int width
, int height
,
61 data
= wmalloc(sizeof(BufferData
));
63 data
->magfactor
= magfactor
;
65 data
->rects
= wmalloc(sizeof(XRectangle
)*rectBufferSize
);
71 data
->pixmap
= WMCreatePixmap(scr
, width
, height
,
72 WMScreenDepth(scr
), False
);
73 WMSetLabelImage(data
->label
, data
->pixmap
);
75 data
->d
= WMGetPixmapXID(data
->pixmap
);
81 data
->buffer
= wmalloc(sizeof(unsigned long)*width
*height
);
82 memset(data
->buffer
, 0, width
*height
*sizeof(unsigned long));
84 data
->height
= height
;
91 resizeBufferData(BufferData
*data
, int width
, int height
, int magfactor
)
93 int w
= width
/magfactor
;
94 int h
= height
/magfactor
;
96 data
->magfactor
= magfactor
;
97 data
->buffer
= wrealloc(data
->buffer
, sizeof(unsigned long)*w
*h
);
100 memset(data
->buffer
, 0, w
*h
*sizeof(unsigned long));
102 WMResizeWidget(data
->label
, width
, height
);
104 WMReleasePixmap(data
->pixmap
);
105 data
->pixmap
= WMCreatePixmap(scr
, width
, height
, WMScreenDepth(scr
),
107 WMSetLabelImage(data
->label
, data
->pixmap
);
109 data
->d
= WMGetPixmapXID(data
->pixmap
);
114 drawpoint(BufferData
*data
, unsigned long pixel
, int x
, int y
)
118 if (data
->buffer
[x
+data
->width
*y
] == pixel
)
121 data
->buffer
[x
+data
->width
*y
] = pixel
;
124 gc
= XCreateGC(dpy
, DefaultRootWindow(dpy
), 0, NULL
);
127 if (data
->lastpixel
== pixel
&& data
->rectP
< rectBufferSize
) {
128 data
->rects
[data
->rectP
].x
= x
*data
->magfactor
;
129 data
->rects
[data
->rectP
].y
= y
*data
->magfactor
;
130 data
->rects
[data
->rectP
].width
= data
->magfactor
;
131 data
->rects
[data
->rectP
].height
= data
->magfactor
;
136 XSetForeground(dpy
, gc
, data
->lastpixel
);
137 XFillRectangles(dpy
, data
->d
, gc
, data
->rects
, data
->rectP
);
139 data
->rects
[data
->rectP
].x
= x
*data
->magfactor
;
140 data
->rects
[data
->rectP
].y
= y
*data
->magfactor
;
141 data
->rects
[data
->rectP
].width
= data
->magfactor
;
142 data
->rects
[data
->rectP
].height
= data
->magfactor
;
145 data
->lastpixel
= pixel
;
151 static inline unsigned long
152 getpix(XImage
*image
, int x
, int y
, int xoffs
, int yoffs
)
154 if (x
< xoffs
|| y
< yoffs
155 || x
>= xoffs
+ image
->width
|| y
>= yoffs
+ image
->height
) {
158 return XGetPixel(image
, x
-xoffs
, y
-yoffs
);
163 updateImage(BufferData
*data
, int rx
, int ry
)
168 int changedPixels
= 0;
183 if (gx
+ gw
>= WidthOfScreen(DefaultScreenOfDisplay(dpy
))) {
184 gw
= WidthOfScreen(DefaultScreenOfDisplay(dpy
)) - gx
;
191 if (gy
+ gh
>= HeightOfScreen(DefaultScreenOfDisplay(dpy
))) {
192 gh
= HeightOfScreen(DefaultScreenOfDisplay(dpy
)) - gy
;
195 image
= XGetImage(dpy
, DefaultRootWindow(dpy
), gx
, gy
, gw
, gh
,
199 for (y
= 0; y
< data
->height
; y
++) {
200 for (x
= 0; x
< data
->width
; x
++) {
203 pixel
= getpix(image
, x
-xoffs
, y
-yoffs
, xoffs
, yoffs
);
205 if (drawpoint(data
, pixel
, x
, y
))
210 XDestroyImage(image
);
212 if (changedPixels
> 0) {
213 WMRedisplayWidget(data
->label
);
221 BufferData
*data
= (BufferData
*)d
;
232 XQueryPointer(dpy
, DefaultRootWindow(dpy
), &win
, &win
, &rx
, &ry
,
235 updateImage(data
, rx
, ry
);
237 data
->tid
= WMAddTimerHandler(refreshrate
, update
, data
);
240 void resizedWindow(void *d
, WMNotification
*notif
)
242 BufferData
*data
= (BufferData
*)d
;
243 WMView
*view
= (WMView
*)WMGetNotificationObject(notif
);
246 size
= WMGetViewSize(view
);
248 resizeBufferData(data
, size
.width
, size
.height
, data
->magfactor
);
253 void closeWindow(WMWidget
*w
, void *d
)
255 BufferData
*data
= (BufferData
*)d
;
258 if (windowCount
== 0) {
261 WMDeleteTimerHandler(data
->tid
);
265 WMReleasePixmap(data
->pixmap
);
272 keyHandler(XEvent
*event
, void *d
)
274 BufferData
*data
= (BufferData
*)d
;
277 WMView
*view
= WMWidgetView(data
->win
);
280 size
= WMGetViewSize(view
);
282 if (XLookupString(&event
->xkey
, buf
, 31, &ks
, NULL
) > 0) {
285 newWindow(data
->magfactor
);
289 data
->frozen
= !data
->frozen
;
291 data
->x
= event
->xkey
.x_root
;
292 data
->y
= event
->xkey
.y_root
;
293 sprintf(buf
, "[Magnify %ix]", data
->magfactor
);
295 sprintf(buf
, "Magnify %ix", data
->magfactor
);
297 WMSetWindowTitle(data
->win
, buf
);
308 resizeBufferData(data
, size
.width
, size
.height
, buf
[0]-'0');
310 sprintf(buf
, "[Magnify %ix]", data
->magfactor
);
312 sprintf(buf
, "Magnify %ix", data
->magfactor
);
314 WMSetWindowTitle(data
->win
, buf
);
322 newWindow(int magfactor
)
331 win
= WMCreateWindow(scr
, "magnify");
332 WMResizeWidget(win
, 300, 200);
333 sprintf(buf
, "Magnify %ix", magfactor
);
334 WMSetWindowTitle(win
, buf
);
335 WMSetViewNotifySizeChanges(WMWidgetView(win
), True
);
337 label
= WMCreateLabel(win
);
338 WMResizeWidget(label
, 300, 200);
339 WMMoveWidget(label
, 0, 0);
340 WMSetLabelRelief(label
, WRSunken
);
341 WMSetLabelImagePosition(label
, WIPImageOnly
);
343 data
= makeBufferData(win
, label
, 300, 200, magfactor
);
345 WMCreateEventHandler(WMWidgetView(win
), KeyReleaseMask
,
348 WMAddNotificationObserver(resizedWindow
, data
,
349 WMViewSizeDidChangeNotification
,
352 WMRealizeWidget(win
);
354 WMMapSubwidgets(win
);
357 WMSetWindowCloseAction(win
, closeWindow
, data
);
358 data
->tid
= WMAddTimerHandler(refreshrate
, update
, data
);
364 int main(int argc
, char **argv
)
371 WMButton
*radio
, *tradio
;
373 WMInitializeApplication("Magnify", &argc
, argv
);
376 for (i
= 1; i
< argc
; i
++) {
377 if (strcmp(argv
[i
], "-display")==0) {
382 } else if (strcmp(argv
[i
], "-m")==0) {
386 magfactor
= atoi(argv
[i
]);
387 if (magfactor
< 1 || magfactor
> 32) {
388 printf("%s:invalid magnification factor ``%s''\n", argv
[0],
392 } else if (strcmp(argv
[i
], "-r")==0) {
396 refreshrate
= atoi(argv
[i
]);
397 if (refreshrate
< 1) {
398 printf("%s:invalid refresh rate ``%s''\n", argv
[0], argv
[i
]);
401 } else if (strcmp(argv
[i
], "-h")==0
402 || strcmp(argv
[i
], "--help")==0) {
404 printf("Syntax: %s [-display <display>] [-m <number>] [-r <number>]\n",
406 puts("-display <display> display that should be used");
407 puts("-m <number> change magnification factor (default 2)");
408 puts("-r <number> change refresh delay, in milliseconds (default 200)");
413 dpy
= XOpenDisplay("");
415 puts("couldnt open display");
419 /* calculate how many rectangles we can send in a trip to the server */
420 rectBufferSize
= XMaxRequestSize(dpy
) - 128;
421 rectBufferSize
/= sizeof(XRectangle
);
422 if (rectBufferSize
< 1)
425 black
= BlackPixel(dpy
, DefaultScreen(dpy
));
427 scr
= WMCreateScreen(dpy
, 0);
429 data
= newWindow(magfactor
);
431 WMScreenMainLoop(scr
);