Add magnifier window (eesh mag show).

SVN revision: 29436
This commit is contained in:
Kim Woelders 2007-04-07 13:19:30 +00:00
parent 799f662fce
commit 17690df4b5
8 changed files with 541 additions and 30 deletions

View File

@ -249,6 +249,7 @@ typedef struct
Colormap cmap;
int scr;
int w, h;
Pixmap pmap; /* Compositing buffer */
}
VirtRoot;

View File

@ -1,6 +1,6 @@
SUBDIRS =
EXTRA_DIST = gnome.c eglx.c eglx.h ecompmgr.c ecompmgr.h snprintf.c
EXTRA_DIST = gnome.c eglx.c eglx.h ecompmgr.c ecompmgr.h magwin.c snprintf.c
bin_PROGRAMS = e16
@ -11,7 +11,7 @@ if HAVE_GLX
SRCS_GLX = eglx.c eglx.h
endif
if HAVE_COMPOSITE
SRCS_ECOMPMGR = ecompmgr.c ecompmgr.h
SRCS_ECOMPMGR = ecompmgr.c ecompmgr.h magwin.c
endif
if USE_ESNPRINTF
SRCS_SNPRINTF = snprintf.c

View File

@ -190,6 +190,7 @@ static struct
char active;
char use_pixmap;
char reorder;
char ghosts;
EObj *eo_first;
EObj *eo_last;
XserverRegion rgn_screen;
@ -438,7 +439,8 @@ EPictureCreateSolid(Bool argb, double a, double r, double g, double b)
}
static Picture
EPictureCreateBuffer(Window win, int w, int h, int depth, Visual * vis)
EPictureCreateBuffer(Window win, int w, int h, int depth, Visual * vis,
Pixmap * ppmap)
{
Picture pict;
Pixmap pmap;
@ -447,7 +449,10 @@ EPictureCreateBuffer(Window win, int w, int h, int depth, Visual * vis)
pmap = XCreatePixmap(disp, win, w, h, depth);
pictfmt = XRenderFindVisualFormat(disp, vis);
pict = XRenderCreatePicture(disp, pmap, pictfmt, 0, 0);
XFreePixmap(disp, pmap);
if (ppmap)
*ppmap = pmap;
else
XFreePixmap(disp, pmap);
return pict;
}
@ -490,7 +495,7 @@ ECompMgrMoveResizeFix(EObj * eo, int x, int y, int w, int h)
/* Resizing - grab old contents */
pict = EPictureCreateBuffer(EobjGetXwin(eo), wo, ho, WinGetDepth(eo->win),
WinGetVisual(eo->win));
WinGetVisual(eo->win), NULL);
XRenderComposite(disp, PictOpSrc, cw->picture, None, pict, 0, 0, 0, 0, 0, 0,
wo, ho);
@ -1831,6 +1836,7 @@ ECompMgrDetermineOrder(EObj * const *lst, int num, EObj ** first,
/* Determine overall paint order, top to bottom */
stop = 0;
eo_first = eo_prev = NULL;
Mode_compmgr.ghosts = 0;
for (i = 0; i < num; i++)
{
@ -1905,6 +1911,12 @@ ECompMgrDetermineOrder(EObj * const *lst, int num, EObj ** first,
if (cw->picture == None && !eo->noredir)
continue;
if (eo->ghost)
{
Mode_compmgr.ghosts = 1;
continue;
}
D3printf
("ECompMgrDetermineOrder hook in %d - %#lx desk=%d shown=%d\n",
dsk->num, EobjGetXwin(eo), eo->desk->num, eo->shown);
@ -2100,6 +2112,36 @@ ECompMgrRepaintObj(Picture pbuf, XserverRegion region, EObj * eo, int mode)
}
}
static void
ECompMgrPaintGhosts(Picture pict, XserverRegion damage)
{
EObj *eo, *const *lst;
int i, num;
lst = EobjListStackGet(&num);
for (i = 0; i < num; i++)
{
eo = lst[i];
if (!eo->shown || !eo->ghost)
continue;
switch (eo->cmhook->mode)
{
case WINDOW_UNREDIR:
case WINDOW_SOLID:
ECompMgrRepaintObj(pict, Mode_compmgr.rgn_screen, eo, 0);
break;
case WINDOW_TRANS:
case WINDOW_ARGB:
ECompMgrRepaintObj(pict, Mode_compmgr.rgn_screen, eo, 1);
break;
}
/* Subtract window region from damage region */
ERegionSubtractOffset(damage, 0, 0, eo->cmhook->shape);
}
}
void
ECompMgrRepaint(void)
{
@ -2120,7 +2162,7 @@ ECompMgrRepaint(void)
if (!rootBuffer)
rootBuffer = EPictureCreateBuffer(VRoot.xwin, VRoot.w, VRoot.h,
VRoot.depth, VRoot.vis);
VRoot.depth, VRoot.vis, &VRoot.pmap);
pbuf = rootBuffer;
if (!dsk)
@ -2154,6 +2196,10 @@ ECompMgrRepaint(void)
for (eo = Mode_compmgr.eo_last; eo; eo = ((ECmWinInfo *) (eo->cmhook))->prev)
ECompMgrRepaintObj(pbuf, allDamage, eo, 1);
/* Paint any ghost windows (adjusting damage region) */
if (Mode_compmgr.ghosts)
ECompMgrPaintGhosts(rootPicture, allDamage);
if (pbuf != rootPicture)
{
XFixesSetPictureClipRegion(dpy, pbuf, 0, 0, allDamage);
@ -2172,30 +2218,31 @@ _ECompMgrIdler(void *data __UNUSED__)
if (!allDamage /* || Conf_compmgr.mode == ECM_MODE_AUTO */ )
return;
ECompMgrRepaint();
#if 0 /* FIXME - Was here - Why? */
XSync(disp, False);
#endif
}
static void
ECompMgrRootBufferDestroy(void)
{
/* Root buffer picture and pixmap */
if (rootBuffer != None)
XRenderFreePicture(disp, rootBuffer);
rootBuffer = None;
if (VRoot.pmap != None)
XFreePixmap(disp, VRoot.pmap);
VRoot.pmap = None;
/* Screen region */
if (Mode_compmgr.rgn_screen != None)
ERegionDestroy(Mode_compmgr.rgn_screen);
Mode_compmgr.rgn_screen = None;
}
static void
ECompMgrRootConfigure(void *prm __UNUSED__, XEvent * ev)
{
Display *dpy = disp;
D1printf("ECompMgrRootConfigure root\n");
if (ev->xconfigure.window == VRoot.xwin)
{
if (rootBuffer != None)
{
XRenderFreePicture(dpy, rootBuffer);
rootBuffer = None;
}
if (Mode_compmgr.rgn_screen != None)
ERegionDestroy(Mode_compmgr.rgn_screen);
Mode_compmgr.rgn_screen = None;
}
return;
ECompMgrRootBufferDestroy();
}
#if USE_DESK_EXPOSE /* FIXME - Remove? */
@ -2396,9 +2443,7 @@ ECompMgrStop(void)
XRenderFreePicture(disp, rootPicture);
rootPicture = None;
if (rootBuffer)
XRenderFreePicture(disp, rootBuffer);
rootBuffer = None;
ECompMgrRootBufferDestroy();
ECompMgrShadowsInit(ECM_SHADOWS_OFF, 0);
@ -2424,10 +2469,6 @@ ECompMgrStop(void)
ERegionDestroy(allDamage);
allDamage = None;
if (Mode_compmgr.rgn_screen != None)
ERegionDestroy(Mode_compmgr.rgn_screen);
Mode_compmgr.rgn_screen = None;
if (Conf_compmgr.mode == ECM_MODE_ROOT)
XCompositeUnredirectSubwindows(disp, VRoot.xwin, CompositeRedirectManual);

View File

@ -115,6 +115,8 @@ EobjSetLayer(EObj * eo, int layer)
eo->ilayer |= 512;
else
eo->ilayer &= ~512;
if (eo->ghost)
eo->ilayer |= 1024;
if (eo->ilayer != ilayer)
EobjRaise(eo);

View File

@ -47,6 +47,7 @@ struct _eobj
unsigned noredir:1; /* Do not redirect */
unsigned shadow:1; /* Enable shadows */
unsigned fade:1; /* Enable fading */
unsigned ghost:1; /* Ghost window */
struct
{
char *wm_name;

View File

@ -285,6 +285,7 @@ struct _ewin
#define EWIN_TYPE_MENU 0x02
#define EWIN_TYPE_ICONBOX 0x04
#define EWIN_TYPE_PAGER 0x08
#define EWIN_TYPE_MISC 0x10
#define EWIN_GRAVITY_NW 0
#define EWIN_GRAVITY_NE 1

463
src/magwin.c Normal file
View File

@ -0,0 +1,463 @@
/*
* Copyright (C) 2007 Kim Woelders
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies of the Software, its documentation and marketing & publicity
* materials, and acknowledgment shall be given in the documentation, materials
* and software packages that this Software was used.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "E.h"
#include "cursors.h"
#include "ecompmgr.h"
#include "eimage.h"
#include "emodule.h"
#include "eobj.h"
#include "events.h"
#include "ewins.h"
#include "grabs.h"
#include "hints.h"
#include "tclass.h"
#include "timers.h"
#include "util.h"
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <X11/keysym.h>
/* Magnifier window */
typedef struct
{
EWin *ewin;
EImage *im;
int cx, cy; /* Center */
int scale; /* Zoom level */
int sw, sh; /* Scene wxh */
char mode;
char bpress;
char filter;
char grabbing;
} MagWindow;
static void MagwinDestroy(MagWindow * mw);
static MagWindow *MagWin = NULL;
static void
MagwinDrawText(MagWindow * mw, int x, int y, const char *txt)
{
TextClass *tc;
int cw, ch;
tc = TextclassFind("COORDS", 1);
if (!tc)
return;
TextSize(tc, 0, 0, 0, txt, &cw, &ch, 17);
TextDraw(tc, EwinGetClientWin(mw->ewin), None, 0, 0, 0,
txt, x, y, cw, ch, 17, 0);
}
static void
MagwinRedraw(MagWindow * mw, int paint)
{
int ww, wh;
int sx, sy, sw, sh;
double scale;
Drawable draw;
char buf[128];
int px, py;
int qx, qy;
unsigned int *pd;
ww = mw->ewin->client.w;
wh = mw->ewin->client.h;
if (mw->scale < -6)
mw->scale = -6;
else if (mw->scale > 6)
mw->scale = 6;
scale = pow(2., (double)(mw->scale));
sw = (int)((ww + .999 * scale) / scale);
if (sw > VRoot.w)
scale = (double)ww / (double)VRoot.w;
sh = (int)((wh + .999 * scale) / scale);
if (sh > VRoot.h && scale < (double)wh / (double)VRoot.h)
scale = (double)wh / (double)VRoot.h;
sw = (int)((ww + .999 * scale) / scale);
sh = (int)((wh + .999 * scale) / scale);
sx = mw->cx - sw / 2;
sy = mw->cy - sh / 2;
if (sx < 0)
sx = 0;
else if (sx + sw > VRoot.w)
sx = VRoot.w - sw;
if (sy < 0)
sy = 0;
else if (sy + sh > VRoot.h)
sy = VRoot.h - sh;
mw->sw = sw;
mw->sh = sh;
if (paint)
{
if (mw->im)
EImageDecache(mw->im);
draw = (VRoot.pmap != None) ? VRoot.pmap : VRoot.xwin;
mw->im = EImageGrabDrawable(draw, None, sx, sy, sw, sh, 0);
EImageRenderOnDrawable(mw->im, EwinGetClientWin(mw->ewin),
EwinGetClientXwin(mw->ewin),
(mw->filter) ? EIMAGE_ANTI_ALIAS : 0,
0, 0, (int)(sw * scale + .5),
(int)(sh * scale + .5));
}
/* Show magnified area coordinates */
Esnprintf(buf, sizeof(buf), "%d,%d %dx%d", sx, sy, sw, sh);
MagwinDrawText(mw, 10, 10, buf);
/* Show info about pixel at cursor (if in magnifier) */
EQueryPointer(EwinGetClientWin(mw->ewin), &px, &py, NULL, NULL);
if (px < 0 || px >= mw->ewin->client.w || py < 0 || py >= mw->ewin->client.h)
return;
qx = (int)(px / scale);
qy = (int)(py / scale);
if (qx > VRoot.w - 1)
qx = VRoot.w - 1;
if (qy > VRoot.h - 1)
qy = VRoot.h - 1;
if (!mw->im)
return;
pd = (unsigned int *)EImageGetData(mw->im);
#if 0
Esnprintf(buf, sizeof(buf), "%d,%d: pixel=%#08x (%d,%d)",
sx + qx, sy + qy, pd[qy * sw + qx], px, py);
#else
Esnprintf(buf, sizeof(buf), "%d,%d: pixel=%#08x",
sx + qx, sy + qy, pd[qy * sw + qx]);
#endif
MagwinDrawText(mw, 10, 20, buf);
}
static void
_MagwinTimeout(int val, void *data)
{
MagWindow *mw = (MagWindow *) data;
if (val && mw != MagWin)
return;
/* Validate ewin */
if (!EwinFindByPtr(mw->ewin))
return;
DoIn("magwin", .050, _MagwinTimeout, 0, data);
/* FIXME - Check damage */
MagwinRedraw(mw, 1);
}
static int
MagwinKeyPress(MagWindow * mw, KeySym key)
{
switch (key)
{
case XK_q: /* Quit */
case XK_Escape:
return 1;
case XK_g: /* Toggle grabs */
if (mw->grabbing)
{
GrabPointerRelease();
GrabKeyboardRelease();
mw->grabbing = 0;
}
else
{
GrabPointerSet(EwinGetClientWin(mw->ewin), ECSR_GRAB, 0);
GrabKeyboardSet(EwinGetClientWin(mw->ewin));
mw->grabbing = 1;
}
break;
case XK_f: /* Toggle filter */
mw->filter += 1;
if (mw->filter >= 2)
mw->filter = 0;
break;
case XK_i: /* Zoom in */
case XK_Page_Up:
mw->scale += 1;
break;
case XK_o: /* Zoom out */
case XK_Page_Down:
mw->scale -= 1;
if (mw->scale < -20)
mw->scale = -20;
break;
case XK_Left:
mw->cx -= 4;
if (mw->cx < mw->sw / 2)
mw->cx = mw->sw / 2;
break;
case XK_Right:
mw->cx += 4;
if (mw->cx > VRoot.w - mw->sw / 2)
mw->cx = VRoot.w - mw->sw / 2;
break;
case XK_Up:
mw->cy -= 4;
if (mw->cy < mw->sh / 2)
mw->cy = mw->sh / 2;
break;
case XK_Down:
mw->cy += 4;
if (mw->cy > VRoot.h - mw->sh / 2)
mw->cy = VRoot.h - mw->sh / 2;
break;
}
return 0;
}
static void
MagwinEvent(Win win __UNUSED__, XEvent * ev, void *prm)
{
MagWindow *mw = (MagWindow *) prm;
KeySym key;
int done = 0;
switch (ev->type)
{
default:
break;
case KeyPress:
key = XLookupKeysym(&ev->xkey, 0);
done = MagwinKeyPress(mw, key);
MagwinRedraw(mw, 1);
break;
case ButtonPress:
switch (ev->xbutton.button)
{
default:
break;
case 1:
MagwinKeyPress(mw, XK_g);
break;
case 3:
MagwinKeyPress(mw, XK_f);
break;
case 4:
MagwinKeyPress(mw, XK_i);
break;
case 5:
MagwinKeyPress(mw, XK_o);
break;
}
mw->bpress = 1;
break;
case ButtonRelease:
mw->bpress = 0;
break;
case MotionNotify:
if (mw->grabbing)
{
mw->cx = Mode.events.x;
mw->cy = Mode.events.y;
MagwinRedraw(mw, 1);
}
else
{
MagwinRedraw(mw, 0);
}
break;
case MapNotify:
MagwinKeyPress(mw, XK_g);
_MagwinTimeout(1, mw);
break;
}
if (done)
EwinHide(mw->ewin);
}
static void
_MagEwinInit(EWin * ewin)
{
EoSetSticky(ewin, 1);
EoSetShadow(ewin, 0);
}
static void
_MagEwinClose(EWin * ewin)
{
MagwinDestroy((MagWindow *) ewin->data);
ewin->client.win = NULL;
ewin->data = NULL;
MagWin = NULL;
}
static const EWinOps _MagEwinOps = {
_MagEwinInit,
NULL,
NULL,
_MagEwinClose,
};
static MagWindow *
MagwinCreate(const char *title, int width, int height)
{
MagWindow *mw;
Win win;
int x, y, w, h;
mw = ECALLOC(MagWindow, 1);
if (!mw)
return NULL;
win = VRoot.win;
w = width;
h = height;
x = ((win->w - w) / 2);
y = ((win->h - h) / 2);
win = ECreateClientWindow(VRoot.win, x, y, w, h);
HintsSetWindowName(win, title);
HintsSetWindowClass(win, "Magnifier", "Enlightenment_Magnifier");
mw->ewin = AddInternalToFamily(win, NULL, EWIN_TYPE_MISC, &_MagEwinOps, mw);
if (!mw->ewin)
{
Efree(mw);
return NULL;
}
mw->ewin->o.ghost = 1;
EoSetLayer(mw->ewin, 10);
EwinMoveToDesktop(mw->ewin, EoGetDesk(mw->ewin));
EwinMoveResize(mw->ewin, EoGetX(mw->ewin), EoGetY(mw->ewin), w, h);
mw->ewin->client.event_mask |=
KeyPressMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask |
StructureNotifyMask;
ESelectInput(win, mw->ewin->client.event_mask);
EventCallbackRegister(win, 0, MagwinEvent, mw);
EQueryPointer(VRoot.win, &mw->cx, &mw->cy, NULL, NULL);
mw->scale = 1;
return mw;
}
static void
MagwinDestroy(MagWindow * mw)
{
RemoveTimerEvent("magwin");
EventCallbackUnregister(EwinGetClientWin(mw->ewin), 0, MagwinEvent, mw);
EDestroyWindow(EwinGetClientWin(mw->ewin));
if (mw->im)
EImageDecache(mw->im);
Efree(mw);
}
static void
MagwinShow(void)
{
if (MagWin)
return;
MagWin = MagwinCreate("Magnifier", VRoot.w / 4, VRoot.h / 4);
if (!MagWin)
{
Eprintf("Failed to create magnifier window\n");
return;
}
EwinShow(MagWin->ewin);
}
static void
MagwinHide(void)
{
if (!MagWin)
return;
EwinHide(MagWin->ewin);
}
/*
* MagWin Module
*/
static void
MagwinIpc(const char *params, Client * c __UNUSED__)
{
const char *p;
char cmd[128], prm[4096];
int len;
cmd[0] = prm[0] = '\0';
p = params;
if (p)
{
len = 0;
sscanf(p, "%100s %4000s %n", cmd, prm, &len);
p += len;
}
if (!p || cmd[0] == '?')
{
IpcPrintf("Magwin: ???\n");
}
else if (!strcmp(cmd, "show"))
{
MagwinShow();
}
#if 1 /* FIXME - Remove? */
else if (!strcmp(cmd, "hide"))
{
MagwinHide();
}
#endif
}
static const IpcItem MagwinIpcArray[] = {
{
MagwinIpc,
"magwin", "mag",
"Magnifier functions",
" magwin show\n"}
,
};
#define N_IPC_FUNCS (sizeof(MagwinIpcArray)/sizeof(IpcItem))
/*
* Module descriptor
*/
extern const EModule ModMagwin;
const EModule ModMagwin = {
"magwin", NULL,
NULL,
{N_IPC_FUNCS, MagwinIpcArray},
{0, NULL}
};

View File

@ -37,6 +37,7 @@ extern const EModule ModButtons;
#if USE_COMPOSITE
extern const EModule ModCompMgr;
extern const EModule ModMagwin;
#endif
extern const EModule ModCursors;
extern const EModule ModDesktops;
@ -68,6 +69,7 @@ const EModule *p_modules[] = {
&ModButtons,
#if USE_COMPOSITE
&ModCompMgr,
&ModMagwin,
#endif
&ModCursors,
&ModDesktops,