All pastes #182729 Raw Edit

Untitled

public c v1 · immutable
#182729 ·published 2006-09-26 09:01 UTC
rendered paste body
/* * Copyright © 2006 Novell, Inc. * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies * and that both that copyright notice and this permission notice * appear in supporting documentation, and that the name of * Novell, Inc. not be used in advertising or publicity pertaining to * distribution of the software without specific, written prior permission. * Novell, Inc. makes no representations about the suitability of this * software for any purpose. It is provided "as is" without express or * implied warranty. * * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Author: David Reveman <davidr@novell.com> */#define _GNU_SOURCE#include <stdlib.h>#include <string.h>#include <dirent.h>#include <beryl.h>#include<libintl.h>#include<locale.h>#define _(String) gettext (String)#define gettext_noop(String) String#define N_(String) gettext_noop (String)#define SHOT_INITIATE_BUTTON_DEFAULT	       Button1#define SHOT_INITIATE_BUTTON_MODIFIERS_DEFAULT CompSuperMask#define SHOT_DIR_DEFAULT "Desktop"static int displayPrivateIndex;#define SHOT_DISPLAY_OPTION_INITIATE 0#define SHOT_DISPLAY_OPTION_DIR      1#define SHOT_DISPLAY_OPTION_NUM	     2typedef struct _ShotDisplay{    int screenPrivateIndex;    HandleEventProc handleEvent;    CompOption opt[SHOT_DISPLAY_OPTION_NUM];} ShotDisplay;typedef struct _ShotScreen{    PaintScreenProc paintScreen;    int grabIndex;    int x1, y1, x2, y2;    Bool grab;} ShotScreen;#define GET_SHOT_DISPLAY(d)				     \    ((ShotDisplay *) (d)->privates[displayPrivateIndex].ptr)#define SHOT_DISPLAY(d)			   \    ShotDisplay *sd = GET_SHOT_DISPLAY (d)#define GET_SHOT_SCREEN(s, sd)					 \    ((ShotScreen *) (s)->privates[(sd)->screenPrivateIndex].ptr)#define SHOT_SCREEN(s)							\    ShotScreen *ss = GET_SHOT_SCREEN (s, GET_SHOT_DISPLAY (s->display))#define NUM_OPTIONS(s) (sizeof ((s)->opt) / sizeof (CompOption))static BoolshotInitiate (CompDisplay * d,              CompAction * action,              CompActionState state, CompOption * option, int nOption){    CompScreen *s;    Window xid;    xid = getIntOptionNamed (option, nOption, "root", 0);    s = findScreenAtDisplay (d, xid);    if (s)    {        SHOT_SCREEN (s);        if (otherScreenGrabExist (s, "screenshot", 0))            return FALSE;        if (!ss->grabIndex)            ss->grabIndex = pushScreenGrab (s, None, "screenshot");        if (state & CompActionStateInitButton)            action->state |= CompActionStateTermButton;        /* start selection screenshot rectangle */        ss->x1 = ss->x2 = pointerX;        ss->y1 = ss->y2 = pointerY;        ss->grab = TRUE;    }    return FALSE;}static BoolshotTerminate (CompDisplay * d,               CompAction * action,               CompActionState state, CompOption * option, int nOption){    CompScreen *s;    Window xid;    xid = getIntOptionNamed (option, nOption, "root", 0);    for (s = d->screens; s; s = s->next)    {        SHOT_SCREEN (s);        if (xid && s->root != xid)            continue;        if (ss->grabIndex)        {            removeScreenGrab (s, ss->grabIndex, NULL);            ss->grabIndex = 0;            if (ss->x1 != ss->x2 && ss->y1 != ss->y2)            {                REGION reg;                reg.rects = &reg.extents;                reg.numRects = 1;                reg.extents.x1 = MIN (ss->x1, ss->x2) - 1;                reg.extents.y1 = MIN (ss->y1, ss->y2) - 1;                reg.extents.x2 = MAX (ss->x1, ss->x2) + 1;                reg.extents.y2 = MAX (ss->y1, ss->y2) + 1;                damageScreenRegion (s, &reg);            }        }    }    action->state &= ~(CompActionStateTermKey | CompActionStateTermButton);    return FALSE;}static intshotFilter (const struct dirent *d){    int number;    if (sscanf (d->d_name, "screenshot%d.png", &number))        return 1;    return 0;}static BoolshotPaintScreen (CompScreen * s,                 const ScreenPaintAttrib * sAttrib,                 Region region, unsigned int mask){    Bool status;    SHOT_SCREEN (s);    UNWRAP (ss, s, paintScreen);    status = (*s->paintScreen) (s, sAttrib, region, mask);    WRAP (ss, s, paintScreen, shotPaintScreen);    if (status && ss->grab)    {        int x1, x2, y1, y2;        x1 = MIN (ss->x1, ss->x2);        y1 = MIN (ss->y1, ss->y2);        x2 = MAX (ss->x1, ss->x2);        y2 = MAX (ss->y1, ss->y2);        if (ss->grabIndex)        {            glPushMatrix ();            glTranslatef (-0.5f, -0.5f, -DEFAULT_Z_CAMERA);            glScalef (1.0f / s->width, -1.0f / s->height, 1.0f);            glTranslatef (0.0f, -s->height, 0.0f);            glDisableClientState (GL_TEXTURE_COORD_ARRAY);            glEnable (GL_BLEND);            glColor4us (0x2fff, 0x2fff, 0x4fff, 0x4fff);            glRecti (x1, y2, x2, y1);            glColor4us (0x2fff, 0x2fff, 0x4fff, 0x9fff);            glBegin (GL_LINE_LOOP);            glVertex2i (x1, y1);            glVertex2i (x2, y1);            glVertex2i (x2, y2);            glVertex2i (x1, y2);            glEnd ();            glColor4usv (defaultColor);            glDisable (GL_BLEND);            glEnableClientState (GL_TEXTURE_COORD_ARRAY);            glPopMatrix ();        }        else        {            int w = x2 - x1;            int h = y2 - y1;            SHOT_DISPLAY (s->display);            if (w && h)            {                GLubyte *buffer;                char *dir = sd->opt[SHOT_DISPLAY_OPTION_DIR].value.s;                buffer = malloc (sizeof (GLubyte) * w * h * 4);                if (buffer)                {                    struct dirent **namelist;                    int n;                    glReadPixels (x1, s->height - y2, w, h,                                  GL_RGBA, GL_UNSIGNED_BYTE,                                  (GLvoid *) buffer);                    n = scandir (dir, &namelist, shotFilter, versionsort);                    if (n >= 0)                    {                        char *name;                        int number = 0;                        if (n > 0)                            sscanf (namelist[n - 1]->d_name,                                    "screenshot%d.png", &number);                        number++;                        if (n)                            free (namelist);                        name = malloc (strlen (dir) + 256);                        if (name)                        {                            sprintf (name, "%s/screenshot%d.png", dir,                                     number);                            if (!writePngToFile (buffer, name, w, h, w * 4))                                fprintf (stderr, "%s: failed to write "                                         "screenshot image", programName);                            free (name);                        }                    }                    else                    {                        perror (dir);                    }                    free (buffer);                }            }            ss->grab = FALSE;        }    }    return status;}static voidshotHandleMotionEvent (CompScreen * s, int xRoot, int yRoot){    SHOT_SCREEN (s);    /* update screenshot rectangle size */    if (ss->grabIndex)    {        REGION reg;        reg.rects = &reg.extents;        reg.numRects = 1;        reg.extents.x1 = MIN (ss->x1, ss->x2) - 1;        reg.extents.y1 = MIN (ss->y1, ss->y2) - 1;        reg.extents.x2 = MAX (ss->x1, ss->x2) + 1;        reg.extents.y2 = MAX (ss->y1, ss->y2) + 1;        damageScreenRegion (s, &reg);        ss->x2 = xRoot;        ss->y2 = yRoot;        reg.extents.x1 = MIN (ss->x1, ss->x2) - 1;        reg.extents.y1 = MIN (ss->y1, ss->y2) - 1;        reg.extents.x2 = MAX (ss->x1, ss->x2) + 1;        reg.extents.y2 = MAX (ss->y1, ss->y2) + 1;        damageScreenRegion (s, &reg);        damageScreen (s);    }}static voidshotHandleEvent (CompDisplay * d, XEvent * event){    CompScreen *s;    SHOT_DISPLAY (d);    switch (event->type)    {    case MotionNotify:        s = findScreenAtDisplay (d, event->xmotion.root);        if (s)            shotHandleMotionEvent (s, pointerX, pointerY);        break;    case EnterNotify:    case LeaveNotify:        s = findScreenAtDisplay (d, event->xcrossing.root);        if (s)            shotHandleMotionEvent (s, pointerX, pointerY);    default:        break;    }    UNWRAP (sd, d, handleEvent);    (*d->handleEvent) (d, event);    WRAP (sd, d, handleEvent, shotHandleEvent);}static voidshotDisplayInitOptions (ShotDisplay * sd){    CompOption *o;    o = &sd->opt[SHOT_DISPLAY_OPTION_INITIATE];    o->name = "initiate";    o->shortDesc = N_("Initiate");    o->longDesc = N_("Initiate rectangle screenshot");    o->type = CompOptionTypeAction;    o->value.action.initiate = shotInitiate;    o->value.action.terminate = shotTerminate;    o->value.action.bell = FALSE;    o->value.action.edgeMask = 0;    o->value.action.type = CompBindingTypeButton;    o->value.action.state = CompActionStateInitButton;    o->value.action.button.modifiers = SHOT_INITIATE_BUTTON_MODIFIERS_DEFAULT;    o->value.action.button.button = SHOT_INITIATE_BUTTON_DEFAULT;    o = &sd->opt[SHOT_DISPLAY_OPTION_DIR];    o->name = "directory";    o->shortDesc = N_("Directory");    o->longDesc = N_("Put screenshot images in this directory");    o->type = CompOptionTypeString;    o->value.s = strdup (SHOT_DIR_DEFAULT);    o->rest.s.string = 0;    o->rest.s.nString = 0;}static CompOption *shotGetDisplayOptions (CompDisplay * display, int *count){    if (display)    {                SHOT_DISPLAY (display);            *count = NUM_OPTIONS (sd);        return sd->opt;    }    else    {        ShotDisplay * sd=malloc(sizeof(ShotDisplay));        shotDisplayInitOptions(sd);        *count = NUM_OPTIONS (sd);        return sd->opt;    }}static BoolshotSetDisplayOption (CompDisplay * display,                      char *name, CompOptionValue * value){    CompOption *o;    int index;    SHOT_DISPLAY (display);    o = compFindOption (sd->opt, NUM_OPTIONS (sd), name, &index);    if (!o)        return FALSE;    switch (index)    {    case SHOT_DISPLAY_OPTION_INITIATE:        if (setDisplayAction (display, o, value))            return TRUE;        break;    case SHOT_DISPLAY_OPTION_DIR:        if (compSetStringOption (o, value))            return TRUE;    default:        break;    }    return FALSE;}static BoolshotInitDisplay (CompPlugin * p, CompDisplay * d){    ShotDisplay *sd;    sd = malloc (sizeof (ShotDisplay));    if (!sd)        return FALSE;    sd->screenPrivateIndex = allocateScreenPrivateIndex (d);    if (sd->screenPrivateIndex < 0)    {        free (sd);        return FALSE;    }    WRAP (sd, d, handleEvent, shotHandleEvent);    shotDisplayInitOptions (sd);    d->privates[displayPrivateIndex].ptr = sd;    return TRUE;}static voidshotFiniDisplay (CompPlugin * p, CompDisplay * d){    SHOT_DISPLAY (d);    freeScreenPrivateIndex (d, sd->screenPrivateIndex);    UNWRAP (sd, d, handleEvent);    free (sd);}static BoolshotInitScreen (CompPlugin * p, CompScreen * s){    ShotScreen *ss;    SHOT_DISPLAY (s->display);    ss = malloc (sizeof (ShotScreen));    if (!ss)        return FALSE;    ss->grabIndex = 0;    ss->grab = FALSE;    addScreenAction (s, &sd->opt[SHOT_DISPLAY_OPTION_INITIATE].value.action);    WRAP (ss, s, paintScreen, shotPaintScreen);    s->privates[sd->screenPrivateIndex].ptr = ss;    return TRUE;}static voidshotFiniScreen (CompPlugin * p, CompScreen * s){    SHOT_SCREEN (s);    UNWRAP (ss, s, paintScreen);    free (ss);}static BoolshotInit (CompPlugin * p){    displayPrivateIndex = allocateDisplayPrivateIndex ();    if (displayPrivateIndex < 0)        return FALSE;    return TRUE;}static voidshotFini (CompPlugin * p){    if (displayPrivateIndex >= 0)        freeDisplayPrivateIndex (displayPrivateIndex);}static CompPluginVTable shotVTable = {    "screenshot",    N_("Screenshot"),    N_("Screenshot plugin"),    shotInit,    shotFini,    shotInitDisplay,    shotFiniDisplay,    shotInitScreen,    shotFiniScreen,    0,                          /* InitWindow */    0,                          /* FiniWindow */    shotGetDisplayOptions,    shotSetDisplayOption,    0,                          /* GetScreenOptions */    0,                          /* SetScreenOption */    NULL,    0,    BERYL_ABI_INFO};CompPluginVTable *getCompPluginInfo (void){    return &shotVTable;}