2 * Copyright (C) 2007-2008 Kim Woelders
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to
6 * deal in the Software without restriction, including without limitation the
7 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8 * sell copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies of the Software, its documentation and marketing & publicity
13 * materials, and acknowledgment shall be given in the documentation, materials
14 * and software packages that this Software was used.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
40 #include <X11/keysym.h>
43 #define USE_ANIMATOR 1
45 /* Magnifier window */
52 int cx, cy; /* Center */
53 int scale; /* Zoom level */
54 int sx, sy; /* Scene x,y */
55 int sw, sh; /* Scene wxh */
61 unsigned int damage_count;
65 static void MagwinDestroy(MagWindow * mw);
67 static MagWindow *MagWin = NULL;
70 MagwinDrawText(MagWindow * mw, int x, int y, const char *txt)
75 tc = TextclassFind("COORDS", 1);
79 TextSize(tc, 0, 0, 0, txt, &cw, &ch, 17);
80 TextDraw(tc, EwinGetClientWin(mw->ewin), None, 0, 0, 0,
81 txt, x, y, cw, ch, 17, 0);
85 MagwinGetPixel(Drawable draw, unsigned int x, unsigned int y)
88 unsigned int *pd, pixel;
90 im = EImageGrabDrawable(draw, None, x, y, 1, 1, 0);
91 pd = (unsigned int *)EImageGetData(im);
99 MagwinRedraw(MagWindow * mw, int paint)
111 ww = mw->ewin->client.w;
112 wh = mw->ewin->client.h;
116 else if (mw->scale > 6)
118 scale = pow(2., (double)(mw->scale));
119 sw = (int)((ww + .999 * scale) / scale);
120 if (sw > WinGetW(VROOT))
121 scale = (double)ww / (double)WinGetW(VROOT);
122 sh = (int)((wh + .999 * scale) / scale);
123 if (sh > WinGetH(VROOT) && scale < (double)wh / (double)WinGetH(VROOT))
124 scale = (double)wh / (double)WinGetH(VROOT);
125 sw = (int)((ww + .999 * scale) / scale);
126 sh = (int)((wh + .999 * scale) / scale);
127 sx = mw->cx - sw / 2;
128 sy = mw->cy - sh / 2;
131 else if (sx + sw > WinGetW(VROOT))
132 sx = WinGetW(VROOT) - sw;
135 else if (sy + sh > WinGetH(VROOT))
136 sy = WinGetH(VROOT) - sh;
147 dw = (int)(sw * scale + .5);
148 dh = (int)(sh * scale + .5);
149 draw = ECompMgrGetRootBuffer();
151 draw = WinGetXwin(VROOT);
152 ScaleRect(VROOT, draw, EwinGetClientWin(mw->ewin),
153 EwinGetClientXwin(mw->ewin), sx, sy, sw, sh,
154 0, 0, dw, dh, (mw->filter) ? EIMAGE_ANTI_ALIAS : 0);
157 /* Check if pointer is in magnifier window */
158 EQueryPointer(EwinGetClientWin(mw->ewin), &px, &py, NULL, NULL);
159 out = px < 0 || px >= mw->ewin->client.w ||
160 py < 0 || py >= mw->ewin->client.h;
161 /* If inside grab pixel before drawing in window */
162 pixel = (out) ? 0 : MagwinGetPixel(EwinGetClientXwin(mw->ewin), px, py);
164 /* Show magnified area coordinates */
165 Esnprintf(buf, sizeof(buf), "%d,%d %dx%d", sx, sy, sw, sh);
166 MagwinDrawText(mw, 10, 10, buf);
171 /* Show info about pixel at cursor (if in magnifier) */
172 qx = (int)(px / scale);
173 qy = (int)(py / scale);
174 if (qx > WinGetW(VROOT) - 1)
175 qx = WinGetW(VROOT) - 1;
176 if (qy > WinGetH(VROOT) - 1)
177 qy = WinGetH(VROOT) - 1;
178 Esnprintf(buf, sizeof(buf), "%d,%d: pixel=%#08x", sx + qx, sy + qy, pixel);
179 MagwinDrawText(mw, 10, 20, buf);
183 _MagwinUpdate(MagWindow * mw)
189 if (!EwinFindByPtr(mw->ewin))
192 if (!mw->update && Mode.events.damage_count == mw->damage_count)
194 mw->damage_count = Mode.events.damage_count;
196 /* FIXME - Check damage */
207 _MagwinTimeout(int val __UNUSED__, void *data)
209 MagWindow *mw = (MagWindow *) data;
212 again = _MagwinUpdate(mw);
221 _MagwinAnimator(void *data)
223 MagWindow *mw = (MagWindow *) data;
225 return _MagwinUpdate(mw);
230 MagwinKeyPress(MagWindow * mw, KeySym key)
234 case XK_q: /* Quit */
237 case XK_g: /* Toggle grabs */
240 GrabPointerRelease();
241 GrabKeyboardRelease();
246 GrabPointerSet(EwinGetClientWin(mw->ewin), ECSR_GRAB, 0);
247 GrabKeyboardSet(EwinGetClientWin(mw->ewin));
251 case XK_f: /* Toggle filter */
256 case XK_i: /* Zoom in */
260 case XK_o: /* Zoom out */
269 if (mw->cx < mw->sw / 2)
274 if (mw->cx > WinGetW(VROOT) - mw->sw / 2)
275 mw->cx = WinGetW(VROOT) - mw->sw / 2;
279 if (mw->cy < mw->sh / 2)
284 if (mw->cy > WinGetH(VROOT) - mw->sh / 2)
285 mw->cy = WinGetH(VROOT) - mw->sh / 2;
288 case XK_r: /* Switch render mode */
289 Conf.testing.use_render_for_scaling =
290 !Conf.testing.use_render_for_scaling;
293 case XK_s: /* x/y move step size */
294 mw->step = (mw->step == 1) ? 4 : 1;
302 MagwinEvent(Win win __UNUSED__, XEvent * ev, void *prm)
304 MagWindow *mw = (MagWindow *) prm;
314 key = XLookupKeysym(&ev->xkey, 0);
315 done = MagwinKeyPress(mw, key);
320 switch (ev->xbutton.button)
325 MagwinKeyPress(mw, XK_g);
328 MagwinKeyPress(mw, XK_f);
331 MagwinKeyPress(mw, XK_i);
334 MagwinKeyPress(mw, XK_o);
347 mw->cx = Mode.events.mx;
348 mw->cy = Mode.events.my;
358 MagwinKeyPress(mw, XK_g);
360 TIMER_ADD(mw->timer, .050, _MagwinTimeout, 0, mw);
362 AnimatorAdd(_MagwinAnimator, mw);
373 _MagEwinInit(EWin * ewin)
375 MagWindow *mw = (MagWindow *) ewin->data;
377 EwinSetTitle(ewin, mw->title);
378 EwinSetClass(ewin, "Magnifier", "Enlightenment_Magnifier");
380 EoSetSticky(ewin, 1);
381 EoSetShadow(ewin, 0);
385 _MagEwinClose(EWin * ewin)
387 MagwinDestroy((MagWindow *) ewin->data);
392 static const EWinOps _MagEwinOps = {
400 MagwinCreate(const char *title, int width, int height)
406 mw = ECALLOC(MagWindow, 1);
413 x = ((win->w - w) / 2);
414 y = ((win->h - h) / 2);
416 win = ECreateClientWindow(VROOT, x, y, w, h);
419 mw->ewin = AddInternalToFamily(win, NULL, EWIN_TYPE_MISC, &_MagEwinOps, mw);
426 mw->ewin->o.ghost = 1;
427 EoSetLayer(mw->ewin, 10);
428 EwinMoveToDesktop(mw->ewin, EoGetDesk(mw->ewin));
429 EwinMoveResize(mw->ewin, EoGetX(mw->ewin), EoGetY(mw->ewin), w, h);
431 mw->ewin->client.event_mask |=
432 KeyPressMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask |
434 ESelectInput(win, mw->ewin->client.event_mask);
436 EventCallbackRegister(win, 0, MagwinEvent, mw);
438 EQueryPointer(VROOT, &mw->cx, &mw->cy, NULL, NULL);
446 MagwinDestroy(MagWindow * mw)
449 TIMER_DEL(mw->timer);
451 EventCallbackUnregister(EwinGetClientWin(mw->ewin), 0, MagwinEvent, mw);
452 EDestroyWindow(EwinGetClientWin(mw->ewin));
462 MagWin = MagwinCreate(_("Magnifier"),
463 WinGetW(VROOT) / 4, WinGetH(VROOT) / 4);
466 Eprintf("Failed to create magnifier window\n");
470 EwinShow(MagWin->ewin);
478 MagwinIpc(const char *params)
481 char cmd[128], prm[4096];
484 cmd[0] = prm[0] = '\0';
489 sscanf(p, "%100s %4000s %n", cmd, prm, &len);
493 if (!p || !strcmp(cmd, "show"))
499 static const IpcItem MagwinIpcArray[] = {
503 "Magnifier functions",
507 #define N_IPC_FUNCS (sizeof(MagwinIpcArray)/sizeof(IpcItem))
512 extern const EModule ModMagwin;
513 const EModule ModMagwin = {
516 {N_IPC_FUNCS, MagwinIpcArray},