Logo Search packages:      
Sourcecode: beryl-plugins-unsupported version File versions

snow.c

/**
 *
 * Beryl snow plugin
 *
 * snow.c
 *
 * Copyright (c) 2006 Eckhart P. <beryl@cornergraf.net>
 * Copyright (c) 2006 Brian Jørgensen <qte@fundanemt.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 **/

/*
 * Many thanks to Atie H. <atie.at.matrix@gmail.com> for providing
 * a clean plugin template
 * Also thanks to the folks from #beryl-dev, especially Quinn_Storm
 * for helping me make this possible
 */

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <math.h>

#include <X11/Xatom.h>
#include <X11/extensions/Xrender.h>

#include <beryl.h>

// ------------------------------------------------------------  CONSTANTS  -----------------------------------------------------
#define MAX_SNOWFLAKES 10000

// ------------------------------------------------------------  WRAPPERS -----------------------------------------------------
#define GET_SNOW_DISPLAY(d)                            \
      ((SnowDisplay *) (d)->privates[displayPrivateIndex].ptr)

#define SNOW_DISPLAY(d)                                \
      SnowDisplay *sd = GET_SNOW_DISPLAY (d)

#define GET_SNOW_SCREEN(s, sd)                         \
      ((SnowScreen *) (s)->privates[(sd)->screenPrivateIndex].ptr)

#define SNOW_SCREEN(s)                                 \
      SnowScreen *ss = GET_SNOW_SCREEN (s, GET_SNOW_DISPLAY (s->display))

// ------------------------------------------------------------  OPTIONS -----------------------------------------------------
#define SNOW_DISPLAY_OPTION_NUM_SNOWFLAKES              0
#define SNOW_DISPLAY_OPTION_SNOW_SIZE                 1
#define SNOW_DISPLAY_OPTION_SNOW_SPEED                2
#define SNOW_DISPLAY_OPTION_SCREEN_BOXING             3
#define SNOW_DISPLAY_OPTION_SCREEN_DEPTH                  4
#define SNOW_DISPLAY_OPTION_INITIATE                5
#define SNOW_DISPLAY_OPTION_ON_TOP                    6
#define SNOW_DISPLAY_OPTION_USE_BLENDING        7
#define SNOW_DISPLAY_OPTION_USE_TEXTURES        8
#define SNOW_DISPLAY_OPTION_SNOW_UPDATE_DELAY   9
#define SNOW_DISPLAY_OPTION_SNOW_TEXTURES        10
#define SNOW_DISPLAY_OPTION_SNOW_DIRECTION        11
#define SNOW_DISPLAY_OPTION_ROTATION                  12
#define SNOW_DISPLAY_OPTION_NUM                             13

#define NUM_SNOW_DIRECTIONS               4

#define SNOW_DISPLAY_OPTION_SNOW_UPDATE_DELAY_DEFAULT 40
#define SNOW_DISPLAY_OPTION_NUM_SNOWFLAKES_DEFAULT    1500.0
#define SNOW_DISPLAY_OPTION_SNOW_SIZE_DEFAULT               10.0
#define SNOW_DISPLAY_OPTION_SNOW_SPEED_DEFAULT                    85.0
#define SNOW_DISPLAY_OPTION_SCREEN_BOXING_DEFAULT           400.0
#define SNOW_DISPLAY_OPTION_SCREEN_DEPTH_DEFAULT            1000.0
#define SNOW_DISPLAY_OPTION_SNOW_TEXTURES_DEFAULT  ""
#define SNOW_DISPLAY_OPTION_INITIATE_KEY                    "F3"
#define SNOW_DISPLAY_OPTION_INITIATE_MOD                    CompSuperMask
#define SNOW_DISPLAY_OPTION_ON_TOP_DEFAULT                  FALSE
#define SNOW_DISPLAY_OPTION_ROTATION_DEFAULT                TRUE
#define SNOW_DISPLAY_OPTION_USE_BLENDING_DEFAULT            TRUE
#define SNOW_DISPLAY_OPTION_USE_TEXTURES_DEFAULT            TRUE
#define SNOW_DISPLAY_OPTION_DIRECTION_DEFAULT         0

static char *snowDirections[] = {
      N_("Top to bottom"),
      N_("Bottom to top"),
      N_("Right to left"),
      N_("Left to right")
};

static char *snowTextures[] = {
      IMAGEDIR "/snowflake2.png"
};

#define N_SNOW_TEXTURES (sizeof (snowTextures) / sizeof (snowTextures[0]))

#define NUM_OPTIONS(s) (sizeof ((s)->opt) / sizeof (CompOption))

static int displayPrivateIndex = 0;

static int numFlakes;
static int snowRotate;
static int snowUpdateDelay;
static float snowSize;
static float snowSpeed;
static float boxing;
static float depth;
static Bool onTop;
static Bool useBlending;
static Bool useTextures;
static Bool displayListNeedsUpdating;

// ------------------------------------------------------------  STRUCTS -----------------------------------------------------
typedef struct _SnowDisplay
{
      int screenPrivateIndex;
      Bool useBlending;
      Bool useTextures;

      int snowTexNFiles;
      CompOptionValue *snowTexFiles;

      float snowSize;
      Bool displayListNeedsUpdating;

      CompOption opt[SNOW_DISPLAY_OPTION_NUM];

} SnowDisplay;

typedef struct _SnowScreen SnowScreen;

typedef struct _SnowTexture
{
      CompTexture tex;
      unsigned int width;
      unsigned int height;
      Bool loaded;
      GLuint dList;
} SnowTexture;

typedef struct _SnowFlake
{
      float x;
      float y;
      float z;
      float xs;
      float ys;
      float zs;
      float ra;                           //rotation angle
      float rs;                           //rotation speed

      SnowTexture *tex;
} SnowFlake;

static void InitiateSnowFlake(SnowScreen * ss, SnowFlake * sf);
static void setSnowflakeTexture(SnowScreen * ss, SnowFlake * sf);
static void beginRendering(SnowScreen * ss, CompScreen * s, int output);
static void setupDisplayList(SnowScreen * ss);

static void snowThink(SnowScreen * ss, SnowFlake * sf);
static void snowMove(SnowFlake * sf);

struct _SnowScreen
{
      CompScreen *s;

      Bool active;

      CompTimeoutHandle timeoutHandle;

      //PreparePaintScreenProc       preparePaintScreen;
      //DonePaintScreenProc          donePaintScreen;
      PaintScreenProc paintScreen;
      //PaintTransformedScreenProc   paintTransformedScreen;
      //ApplyScreenTransformProc       applyScreenTransform;
      //PaintBackgroundProc          paintBackground;
      PaintWindowProc paintWindow;
      DrawWindowProc drawWindow;
      //AddWindowGeometryProc        addWindowGeometry;
      //DrawWindowGeometryProc       drawWindowGeometry;
      DrawWindowTextureProc drawWindowTexture;
      //DamageWindowRectProc         damageWindowRect;
      //FocusWindowProc              focusWindow;

      SnowTexture *snowTex;
      int snowTexturesLoaded;

      GLuint displayList;

      SnowFlake allSnowFlakes[MAX_SNOWFLAKES];
};
static void snowThink(SnowScreen * ss, SnowFlake * sf)
{
      if (sf->y >= ss->s->height + boxing
            || sf->x <= -boxing
            || sf->y >= ss->s->width + boxing
            || sf->z <= -(depth / 500.0) || sf->z >= 1)

      {
            InitiateSnowFlake(ss, sf);
      }
      snowMove(sf);
}

static void snowMove(SnowFlake * sf)
{
      float tmp = 1.0f / (100.0f - snowSpeed);

      sf->x += (sf->xs * (float)snowUpdateDelay) * tmp;
      sf->y += (sf->ys * (float)snowUpdateDelay) * tmp;
      sf->z += (sf->zs * (float)snowUpdateDelay) * tmp;
      sf->ra += ((float)snowUpdateDelay) / (10.0f - sf->rs);
}

static Bool stepSnowPositions(void *sc)
{
      CompScreen *s = sc;

      SNOW_SCREEN(s);
      if (!ss->active)
            return True;
      int i = 0;

      SnowFlake *snowFlake = ss->allSnowFlakes;

      for (i = 0; i < numFlakes; i++)
            snowThink(ss, snowFlake++);

      if (ss->active && !onTop)
      {
            CompWindow *w;

            for (w = s->windows; w; w = w->next)
            {
                  if (w->type & CompWindowTypeDesktopMask)
                  {
                        addWindowDamage(w);
                  }
            }
      }
      else if (ss->active)
            damageScreen(s);
      return True;
}

static Bool
snowToggle(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)
      {
            SNOW_SCREEN(s);
            ss->active = !ss->active;
            if (!ss->active)
                  damageScreen(s);
      }

      return TRUE;
}

// -------------------------------------------------  HELPER FUNCTIONS ----------------------------------------------------

int GetRand(int min, int max);
int GetRand(int min, int max)
{
      return (rand() % (max - min + 1) + min);
}

float mmrand(int min, int max, float divisor);
float mmrand(int min, int max, float divisor)
{
      return ((float)GetRand(min, max)) / divisor;
};

// ------------------------------------------------- RENDERING ----------------------------------------------------
static void setupDisplayList(SnowScreen * ss)
{
      // ----------------- untextured list

      ss->displayList = glGenLists(1);

      glNewList(ss->displayList, GL_COMPILE);
      glBegin(GL_QUADS);

      glColor4f(1.0, 1.0, 1.0, 1.0);
      glVertex3f(0, 0, -0.0);
      glColor4f(1.0, 1.0, 1.0, 1.0);
      glVertex3f(0, snowSize, -0.0);
      glColor4f(1.0, 1.0, 1.0, 1.0);
      glVertex3f(snowSize, snowSize, -0.0);
      glColor4f(1.0, 1.0, 1.0, 1.0);
      glVertex3f(snowSize, 0, -0.0);

      glEnd();
      glEndList();

}

static void beginRendering(SnowScreen * ss, CompScreen * s, int output)
{
      glPushMatrix();
      glLoadIdentity();

      prepareXCoords(s, output, -DEFAULT_Z_CAMERA);

      if (useBlending)
      {
            glEnable(GL_BLEND);
      }

      glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

      if (displayListNeedsUpdating)
      {
            setupDisplayList(ss);
            displayListNeedsUpdating = FALSE;
      }

      glColor4f(1.0, 1.0, 1.0, 1.0);
      if (ss->snowTexturesLoaded && useTextures)
      {
            int j = 0;

            for (j = 0; j < ss->snowTexturesLoaded; j++)
            {
                  enableTexture(ss->s, &ss->snowTex[j].tex,
                                      COMP_TEXTURE_FILTER_GOOD);

                  int i = 0;
                  SnowFlake *snowFlake = ss->allSnowFlakes;

                  for (i = 0; i < numFlakes; i++)
                  {
                        if (snowFlake->tex == &ss->snowTex[j])
                        {
                              glTranslatef(snowFlake->x, snowFlake->y, snowFlake->z);
                              if (snowRotate)
                                    glRotatef(snowFlake->ra, 0, 0, 1);
                              glCallList(ss->snowTex[j].dList);
                              if (snowRotate)
                                    glRotatef(-snowFlake->ra, 0, 0, 1);
                              glTranslatef(-snowFlake->x, -snowFlake->y, -snowFlake->z);
                        }
                        snowFlake++;
                  }
                  disableTexture(ss->s, &ss->snowTex[j].tex);
            }
      }
      else if (!ss->snowTexturesLoaded || !useTextures)
      {
            int i = 0;
            SnowFlake *snowFlake = ss->allSnowFlakes;

            for (i = 0; i < numFlakes; i++)
            {
                  glTranslatef(snowFlake->x, snowFlake->y, snowFlake->z);
                  glRotatef(snowFlake->ra, 0, 0, 1);
                  glCallList(ss->displayList);
                  glRotatef(-snowFlake->ra, 0, 0, 1);
                  glTranslatef(-snowFlake->x, -snowFlake->y, -snowFlake->z);
                  snowFlake++;
            }
      }

      glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
      if (useBlending)
      {
            glDisable(GL_BLEND);
            glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
      }
      glPopMatrix();
}

// -------------------------------------------------  FUNCTIONS ----------------------------------------------------

/*static void snowPreparePaintScreen(CompScreen * s, int msSinceLastPaint)
{
      SNOW_SCREEN(s);

      UNWRAP(ss, s, preparePaintScreen);
      (*s->preparePaintScreen) (s, msSinceLastPaint);
      WRAP(ss, s, preparePaintScreen, snowPreparePaintScreen);
}*/

/*static void snowDonePaintScreen(CompScreen * s)
{
      SNOW_SCREEN(s);

      UNWRAP(ss, s, donePaintScreen);
      (*s->donePaintScreen) (s);
      WRAP(ss, s, donePaintScreen, snowDonePaintScreen);
}*/

static Bool
snowPaintScreen(CompScreen * s, const ScreenPaintAttrib * sa,
                        Region region, int output, unsigned int mask)
{
      Bool status;

      SNOW_SCREEN(s);

      if (!onTop && ss->active)
      {
            // This line is essential. Without it the snow will be rendered above (some) other windows.
            mask |= PAINT_SCREEN_ORDER_BACK_TO_FRONT_MASK;
      }

      UNWRAP(ss, s, paintScreen);
      status = (*s->paintScreen) (s, sa, region, output, mask);
      WRAP(ss, s, paintScreen, snowPaintScreen);

      if (onTop && ss->active)
            beginRendering(ss, s, output);

      return status;
}

static Bool
snowPaintWindow(CompWindow * w, const WindowPaintAttrib * attrib,
                        Region region, unsigned int mask)
{
      int status = TRUE;

      SNOW_SCREEN(w->screen);

      // First draw Window as usual
      UNWRAP(ss, w->screen, paintWindow);
      status = (*w->screen->paintWindow) (w, attrib, region, mask);
      WRAP(ss, w->screen, paintWindow, snowPaintWindow);

      // Check whether this is the Desktop Window
      if (w->type & CompWindowTypeDesktopMask && ss->active && !onTop)
      {
            beginRendering(ss, w->screen, outputDeviceForWindow(w));
      }
      return status;
}

static void InitiateSnowFlake(SnowScreen * ss, SnowFlake * sf)
{
      //TODO: possibly place snowflakes based on FOV, instead of a cube.
      SNOW_DISPLAY(ss->s->display);
      CompOption *o = &sd->opt[SNOW_DISPLAY_OPTION_SNOW_DIRECTION];

      if (strcmp(snowDirections[0], o->value.s) == 0)
      {
            sf->x = mmrand(-boxing, ss->s->width + boxing, 1);
            sf->xs = mmrand(-1, 1, 500);
            sf->y = mmrand(-300, 0, 1);
            sf->ys = mmrand(1, 3, 1);
      }
      else if (strcmp(snowDirections[1], o->value.s) == 0)
      {
            sf->x = mmrand(-boxing, ss->s->width + boxing, 1);
            sf->xs = mmrand(-1, 1, 500);
            sf->y = mmrand(ss->s->height, ss->s->height + 300, 1);
            sf->ys = -mmrand(1, 3, 1);
      }
      else if (strcmp(snowDirections[2], o->value.s) == 0)
      {
            sf->x = mmrand(ss->s->width, ss->s->width + 300, 1);
            sf->xs = -mmrand(1, 3, 1);
            sf->y = mmrand(-boxing, ss->s->height + boxing, 1);
            sf->ys = mmrand(-1, 1, 500);
      }
      else if (strcmp(snowDirections[3], o->value.s) == 0)
      {
            sf->x = mmrand(-300, 0, 1);
            sf->xs = mmrand(1, 3, 1);
            sf->y = mmrand(-boxing, ss->s->height + boxing, 1);
            sf->ys = mmrand(-1, 1, 500);
      }

      sf->z = mmrand(-depth, 0.1, 5000);
      sf->zs = mmrand(-1000, 1000, 500000);
      sf->ra = mmrand(-1000, 1000, 50);
      sf->rs = mmrand(-1000, 1000, 1000);
}

static void setSnowflakeTexture(SnowScreen * ss, SnowFlake * sf)
{
      if (ss->snowTexturesLoaded)
            sf->tex = &ss->snowTex[rand() % ss->snowTexturesLoaded];
}

static void updateSnowTextures(CompScreen * s)
{
      SNOW_SCREEN(s);
      SNOW_DISPLAY(s->display);
      int i = 0;

      for (i = 0; i < ss->snowTexturesLoaded; i++)
      {
            finiTexture(s, &ss->snowTex[i].tex);
            glDeleteLists(ss->snowTex[i].dList, 1);
      }
      if (ss->snowTexturesLoaded)
            free(ss->snowTex);
      ss->snowTexturesLoaded = 0;

      ss->snowTex = calloc(1, sizeof(SnowTexture) * sd->snowTexNFiles);

      int count = 0;

      for (i = 0; i < sd->snowTexNFiles; i++)
      {
            ss->snowTex[count].loaded =
                        readImageToTexture(s, &ss->snowTex[count].tex,
                                                   sd->snowTexFiles[i].s,
                                                   &ss->snowTex[count].width,
                                                   &ss->snowTex[count].height);
            if (!ss->snowTex[count].loaded)
            {
                  printf("[Snow]: Texture not found : %s\n", sd->snowTexFiles[i].s);
                  continue;
            }
            printf("[Snow]: Loaded Texture %s\n", sd->snowTexFiles[i].s);
            CompMatrix *mat = &ss->snowTex[count].tex.matrix;
            SnowTexture *sTex = &ss->snowTex[count];

            sTex->dList = glGenLists(1);

            glNewList(sTex->dList, GL_COMPILE);

            glBegin(GL_QUADS);

            glTexCoord2f(COMP_TEX_COORD_X(mat, 0), COMP_TEX_COORD_Y(mat, 0));
            glVertex2f(0, 0);
            glTexCoord2f(COMP_TEX_COORD_X(mat, 0),
                               COMP_TEX_COORD_Y(mat, sTex->height));
            glVertex2f(0, snowSize * sTex->height / sTex->width);
            glTexCoord2f(COMP_TEX_COORD_X(mat, sTex->width),
                               COMP_TEX_COORD_Y(mat, sTex->height));
            glVertex2f(snowSize, snowSize * sTex->height / sTex->width);
            glTexCoord2f(COMP_TEX_COORD_X(mat, sTex->width),
                               COMP_TEX_COORD_Y(mat, 0));
            glVertex2f(snowSize, 0);

            glEnd();
            glEndList();

            count++;
      }
      ss->snowTexturesLoaded = count;
      if (count < sd->snowTexNFiles)
            ss->snowTex = realloc(ss->snowTex, sizeof(SnowTexture) * count);

      SnowFlake *snowFlake = ss->allSnowFlakes;

      for (i = 0; i < MAX_SNOWFLAKES; i++)
      {
            setSnowflakeTexture(ss, snowFlake++);
      }
}

static Bool snowInitScreen(CompPlugin * p, CompScreen * s)
{
      SNOW_DISPLAY(s->display);

      SnowScreen *ss = (SnowScreen *) calloc(1, sizeof(SnowScreen));

      ss->s = s;
      s->privates[sd->screenPrivateIndex].ptr = ss;

      int i = 0;
      SnowFlake *snowFlake = ss->allSnowFlakes;

      for (i = 0; i < MAX_SNOWFLAKES; i++)
      {
            InitiateSnowFlake(ss, snowFlake);
            setSnowflakeTexture(ss, snowFlake);
            snowFlake++;
      }

      updateSnowTextures(s);

      setupDisplayList(ss);

      ss->active = FALSE;

      addScreenAction(s, &sd->opt[SNOW_DISPLAY_OPTION_INITIATE].value.action);

      WRAP(ss, s, paintScreen, snowPaintScreen);
      //WRAP(ss, s, paintTransformedScreen, snowPaintTransformedScreen);
      //WRAP(ss, s, preparePaintScreen, snowPreparePaintScreen);
      //WRAP(ss, s, donePaintScreen, snowDonePaintScreen);
      WRAP(ss, s, paintWindow, snowPaintWindow);

      ss->timeoutHandle = compAddTimeout(snowUpdateDelay, stepSnowPositions, s);

      return TRUE;
}

static void snowFiniScreen(CompPlugin * p, CompScreen * s)
{
      SNOW_SCREEN(s);
      SNOW_DISPLAY(s->display);

      compRemoveTimeout(ss->timeoutHandle);

      int i = 0;

      for (i = 0; i < ss->snowTexturesLoaded; i++)
      {
            finiTexture(s, &ss->snowTex[i].tex);
            glDeleteLists(ss->snowTex[i].dList, 1);
      }
      if (ss->snowTexturesLoaded)
            free(ss->snowTex);

      //Restore the original function
      UNWRAP(ss, s, paintScreen);
      //UNWRAP(ss, s, paintTransformedScreen);
      //UNWRAP(ss, s, preparePaintScreen);
      //UNWRAP(ss, s, donePaintScreen);
      UNWRAP(ss, s, paintWindow);

      removeScreenAction(s,
                                 &sd->opt[SNOW_DISPLAY_OPTION_INITIATE].value.action);
      //Free the pointer
      free(ss);
}

static Bool
snowSetDisplayOption(CompDisplay * display, char *name,
                               CompOptionValue * value)
{
      CompOption *o;
      int index;

      SNOW_DISPLAY(display);

      o = compFindOption(sd->opt, NUM_OPTIONS(sd), name, &index);
      if (!o)
            return FALSE;

      switch (index)
      {
      case SNOW_DISPLAY_OPTION_NUM_SNOWFLAKES:
            if (compSetFloatOption(o, value))
            {
                  numFlakes =
                              (int)sd->opt[SNOW_DISPLAY_OPTION_NUM_SNOWFLAKES].value.f;
                  return TRUE;
            }
            break;

      case SNOW_DISPLAY_OPTION_SNOW_DIRECTION:
            if (compSetStringOption(o, value))
            {
                  return TRUE;
            }
            break;
      case SNOW_DISPLAY_OPTION_SNOW_SIZE:
            if (compSetFloatOption(o, value))
            {
                  snowSize = sd->opt[SNOW_DISPLAY_OPTION_SNOW_SIZE].value.f;
                  displayListNeedsUpdating = TRUE;
                  CompScreen *s = display->screens;

                  updateSnowTextures(s);

                  return TRUE;
            }
            break;
      case SNOW_DISPLAY_OPTION_SNOW_SPEED:
            if (compSetFloatOption(o, value))
            {
                  snowSpeed = sd->opt[SNOW_DISPLAY_OPTION_SNOW_SPEED].value.f;
                  return TRUE;
            }
            break;
      case SNOW_DISPLAY_OPTION_SNOW_UPDATE_DELAY:
            if (compSetIntOption(o, value))
            {
                  CompScreen *s = display->screens;

                  SNOW_SCREEN(s);
                  snowUpdateDelay =
                              sd->opt[SNOW_DISPLAY_OPTION_SNOW_UPDATE_DELAY].value.i;
                  if (ss->timeoutHandle)
                        compRemoveTimeout(ss->timeoutHandle);
                  ss->timeoutHandle =
                              compAddTimeout(snowUpdateDelay, stepSnowPositions, s);
                  return TRUE;
            }
      case SNOW_DISPLAY_OPTION_SCREEN_BOXING:
            if (compSetFloatOption(o, value))
            {
                  boxing = sd->opt[SNOW_DISPLAY_OPTION_SCREEN_BOXING].value.f;
                  return TRUE;
            }
            break;
      case SNOW_DISPLAY_OPTION_SCREEN_DEPTH:
            if (compSetFloatOption(o, value))
            {
                  depth = sd->opt[SNOW_DISPLAY_OPTION_SCREEN_DEPTH].value.f;
                  return TRUE;
            }
            break;
      case SNOW_DISPLAY_OPTION_SNOW_TEXTURES:
            if (compSetOptionList(o, value))
            {
                  CompScreen *s = display->screens;

                  sd->snowTexFiles =
                              sd->opt[SNOW_DISPLAY_OPTION_SNOW_TEXTURES].value.list.
                              value;
                  sd->snowTexNFiles =
                              sd->opt[SNOW_DISPLAY_OPTION_SNOW_TEXTURES].value.list.
                              nValue;

                  updateSnowTextures(s);
                  return TRUE;
            }
            break;

      case SNOW_DISPLAY_OPTION_INITIATE:
            if (setDisplayAction(display, o, value))
                  return TRUE;
            break;
      case SNOW_DISPLAY_OPTION_ON_TOP:
            if (compSetBoolOption(o, value))
            {
                  onTop = sd->opt[SNOW_DISPLAY_OPTION_ON_TOP].value.b;
                  return TRUE;
            }
            break;
      case SNOW_DISPLAY_OPTION_ROTATION:
            if (compSetBoolOption(o, value))
            {
                  snowRotate = sd->opt[SNOW_DISPLAY_OPTION_ROTATION].value.b;
                  return TRUE;
            }
            break;
      case SNOW_DISPLAY_OPTION_USE_BLENDING:
            if (compSetBoolOption(o, value))
            {
                  useBlending = sd->opt[SNOW_DISPLAY_OPTION_USE_BLENDING].value.b;
                  return TRUE;
            }
      case SNOW_DISPLAY_OPTION_USE_TEXTURES:
            if (compSetBoolOption(o, value))
            {
                  useTextures = sd->opt[SNOW_DISPLAY_OPTION_USE_TEXTURES].value.b;
                  return TRUE;
            }
            break;
      default:
            break;
      }
      return FALSE;
}

static void snowDisplayInitOptions(SnowDisplay * sd)
{
      CompOption *o;

      o = &sd->opt[SNOW_DISPLAY_OPTION_NUM_SNOWFLAKES];
      o->advanced = False;
      o->name = "num_snowflakes";
      o->group = N_("Settings");
      o->subGroup = N_("");
      o->displayHints = "";
      o->shortDesc = N_("Number of Snowflakes");
      o->longDesc = N_("Number of Snowflakes");
      o->type = CompOptionTypeFloat;
      o->value.f = SNOW_DISPLAY_OPTION_NUM_SNOWFLAKES_DEFAULT;
      o->rest.f.min = 0;
      o->rest.f.max = 10000;
      o->rest.f.precision = 1;

      o = &sd->opt[SNOW_DISPLAY_OPTION_SNOW_SIZE];
      o->advanced = False;
      o->name = "snow_size";
      o->group = N_("Settings");
      o->subGroup = N_("");
      o->displayHints = "";
      o->shortDesc = N_("Size of snowflakes");
      o->longDesc = N_("Size of snowflakes");
      o->type = CompOptionTypeFloat;
      o->value.f = SNOW_DISPLAY_OPTION_SNOW_SIZE_DEFAULT;
      o->rest.f.min = 0;
      o->rest.f.max = 50;
      o->rest.f.precision = 0.1;

      o = &sd->opt[SNOW_DISPLAY_OPTION_SNOW_SPEED];
      o->advanced = False;
      o->name = "snow_speed";
      o->group = N_("Settings");
      o->subGroup = N_("");
      o->displayHints = "";
      o->shortDesc = N_("Speed of falling snow");
      o->longDesc = N_("Speed of falling snow");
      o->type = CompOptionTypeFloat;
      o->value.f = SNOW_DISPLAY_OPTION_SNOW_SPEED_DEFAULT;
      o->rest.f.min = 0;
      o->rest.f.max = 100;
      o->rest.f.precision = 1;

      o = &sd->opt[SNOW_DISPLAY_OPTION_SNOW_UPDATE_DELAY];
      o->advanced = False;
      o->name = "snow_update_delay";
      o->group = N_("Settings");
      o->subGroup = N_("");
      o->displayHints = "";
      o->shortDesc = N_("Update Delay");
      o->longDesc =
                  N_
                  ("Delay in ms between screen updates. Deacreasing this value may make snow fall more smoothly, but will also increase CPU usage.");
      o->type = CompOptionTypeInt;
      o->value.i = SNOW_DISPLAY_OPTION_SNOW_UPDATE_DELAY_DEFAULT;
      o->rest.i.min = 10;
      o->rest.i.max = 200;

      o = &sd->opt[SNOW_DISPLAY_OPTION_SCREEN_BOXING];
      o->advanced = False;
      o->name = "screen_boxing";
      o->group = N_("Settings");
      o->subGroup = N_("");
      o->displayHints = "";
      o->shortDesc = N_("Screen Boxing");
      o->longDesc =
                  N_
                  ("How far outside the screen resolution snowflakes can be before being removed. Needed because of FOV.");
      o->type = CompOptionTypeFloat;
      o->value.f = SNOW_DISPLAY_OPTION_SCREEN_BOXING_DEFAULT;
      o->rest.f.min = -2000;
      o->rest.f.max = 2000;
      o->rest.f.precision = 1;

      o = &sd->opt[SNOW_DISPLAY_OPTION_SCREEN_DEPTH];
      o->advanced = False;
      o->name = "screen_depth";
      o->group = N_("Settings");
      o->subGroup = N_("");
      o->displayHints = "";
      o->shortDesc = N_("Screen Depth");
      o->longDesc =
                  N_
                  ("How deep into the screen snowflakes can be drawn before being removed.");
      o->type = CompOptionTypeFloat;
      o->value.f = SNOW_DISPLAY_OPTION_SCREEN_DEPTH_DEFAULT;
      o->rest.f.min = 0;
      o->rest.f.max = SNOW_DISPLAY_OPTION_SCREEN_DEPTH_DEFAULT * 2;
      o->rest.f.precision = 1;

      o = &sd->opt[SNOW_DISPLAY_OPTION_SNOW_TEXTURES];
      o->advanced = False;
      o->name = "snow_textures";
      o->group = N_("Textures");
      o->subGroup = N_("");
      o->displayHints = "file;image;pngonly;";
      o->shortDesc = N_("Snow Textures");
      o->longDesc = N_("Snow textures");
      o->type = CompOptionTypeList;
      o->value.list.type = CompOptionTypeString;
      o->value.list.nValue = N_SNOW_TEXTURES;
      o->value.list.value = malloc(sizeof(CompOptionValue) * N_SNOW_TEXTURES);
      int i = 0;

      for (i = 0; i < N_SNOW_TEXTURES; i++)
            o->value.list.value[i].s = strdup(snowTextures[i]);
      o->rest.s.string = 0;
      o->rest.s.nString = 0;

      o = &sd->opt[SNOW_DISPLAY_OPTION_INITIATE];
      o->advanced = False;
      o->name = "Initiate";
      o->group = N_("Key Bindings");
      o->subGroup = N_("");
      o->displayHints = "";
      o->shortDesc = N_("snow toggle key");
      o->longDesc = N_("snow toggle key");
      o->type = CompOptionTypeAction;
      o->value.action.initiate = snowToggle;
      o->value.action.terminate = 0;
      o->value.action.bell = FALSE;
      o->value.action.type = CompBindingTypeKey;
      o->value.action.state = CompActionStateInitKey;
      o->value.action.state |= CompActionStateInitButton;
      o->value.action.key.modifiers = SNOW_DISPLAY_OPTION_INITIATE_MOD;
      o->value.action.key.keysym =
                  XStringToKeysym(SNOW_DISPLAY_OPTION_INITIATE_KEY);

      o = &sd->opt[SNOW_DISPLAY_OPTION_ON_TOP];
      o->advanced = False;
      o->name = "snow_over_windows";
      o->group = N_("Settings");
      o->subGroup = N_("");
      o->displayHints = "";
      o->shortDesc = N_("Snow over windows.");
      o->longDesc = N_("Snow is drawn above windows.");
      o->type = CompOptionTypeBool;
      o->value.b = SNOW_DISPLAY_OPTION_ON_TOP_DEFAULT;

      o = &sd->opt[SNOW_DISPLAY_OPTION_ROTATION];
      o->advanced = False;
      o->name = "snow_rotation";
      o->group = N_("Settings");
      o->subGroup = N_("");
      o->displayHints = "";
      o->shortDesc = N_("Rotate flakes");
      o->longDesc = N_("Flakes rotate when checked.");
      o->type = CompOptionTypeBool;
      o->value.b = SNOW_DISPLAY_OPTION_ROTATION_DEFAULT;

      o = &sd->opt[SNOW_DISPLAY_OPTION_SNOW_DIRECTION];
      o->advanced = False;
      o->name = "snow_direction";
      o->group = N_("Settings");
      o->subGroup = N_("");
      o->displayHints = "";
      o->shortDesc = N_("Snow Direction");
      o->longDesc = N_("Select direction in which the snow should fly.");
      o->type = CompOptionTypeString;
      o->value.s =
                  strdup(snowDirections[SNOW_DISPLAY_OPTION_DIRECTION_DEFAULT]);
      o->rest.s.string = snowDirections;
      o->rest.s.nString = NUM_SNOW_DIRECTIONS;

      o = &sd->opt[SNOW_DISPLAY_OPTION_USE_BLENDING];
      o->advanced = False;
      o->name = "use_blending";
      o->group = N_("Debug");
      o->subGroup = N_("");
      o->displayHints = "";
      o->shortDesc = N_("Enable Blending");
      o->longDesc = N_("Enables alpha blending of snowflakes");
      o->type = CompOptionTypeBool;
      o->value.b = SNOW_DISPLAY_OPTION_USE_BLENDING_DEFAULT;

      o = &sd->opt[SNOW_DISPLAY_OPTION_USE_TEXTURES];
      o->advanced = False;
      o->name = "use_textures";
      o->group = N_("Debug");
      o->subGroup = N_("");
      o->displayHints = "";
      o->shortDesc = N_("Enable Textures");
      o->longDesc =
                  N_
                  ("Enables textured snowflakes. Otherwise color gradients are used.");
      o->type = CompOptionTypeBool;
      o->value.b = SNOW_DISPLAY_OPTION_USE_TEXTURES_DEFAULT;
}

static CompOption *snowGetDisplayOptions(CompDisplay * display, int *count)
{
      if (display)
      {
            SNOW_DISPLAY(display);

            *count = NUM_OPTIONS(sd);
            return sd->opt;
      }
      else
      {
            SnowDisplay *sd = malloc(sizeof(SnowDisplay));

            snowDisplayInitOptions(sd);

            *count = NUM_OPTIONS(sd);
            return sd->opt;
      }
}

static Bool snowInitDisplay(CompPlugin * p, CompDisplay * d)
{
      //Generate a snow display
      SnowDisplay *sd = (SnowDisplay *) malloc(sizeof(SnowDisplay));

      //Allocate a private index
      sd->screenPrivateIndex = allocateScreenPrivateIndex(d);

      //Check if its valid
      if (sd->screenPrivateIndex < 0)
      {
            free(sd);
            return FALSE;
      }

      numFlakes = SNOW_DISPLAY_OPTION_NUM_SNOWFLAKES_DEFAULT;
      snowRotate = SNOW_DISPLAY_OPTION_ROTATION_DEFAULT;
      snowSize = SNOW_DISPLAY_OPTION_SNOW_SIZE_DEFAULT;
      snowSpeed = SNOW_DISPLAY_OPTION_SNOW_SPEED_DEFAULT;
      snowUpdateDelay = SNOW_DISPLAY_OPTION_SNOW_UPDATE_DELAY_DEFAULT;
      boxing = SNOW_DISPLAY_OPTION_SCREEN_BOXING_DEFAULT;
      depth = SNOW_DISPLAY_OPTION_SCREEN_DEPTH_DEFAULT;
      onTop = SNOW_DISPLAY_OPTION_ON_TOP_DEFAULT;

      displayListNeedsUpdating = FALSE;
      useBlending = SNOW_DISPLAY_OPTION_USE_BLENDING_DEFAULT;
      useTextures = SNOW_DISPLAY_OPTION_USE_TEXTURES_DEFAULT;
      snowDisplayInitOptions(sd);

      sd->snowTexFiles =
                  sd->opt[SNOW_DISPLAY_OPTION_SNOW_TEXTURES].value.list.value;
      sd->snowTexNFiles =
                  sd->opt[SNOW_DISPLAY_OPTION_SNOW_TEXTURES].value.list.nValue;

      //Record the display
      d->privates[displayPrivateIndex].ptr = sd;

      return TRUE;
}

static void snowFiniDisplay(CompPlugin * p, CompDisplay * d)
{
      SNOW_DISPLAY(d);

      //Free the private index
      freeScreenPrivateIndex(d, sd->screenPrivateIndex);
      //Free the pointer
      free(sd);
}

static Bool snowInit(CompPlugin * p)
{
      displayPrivateIndex = allocateDisplayPrivateIndex();

      if (displayPrivateIndex < 0)
            return FALSE;

      return TRUE;
}

static void snowFini(CompPlugin * p)
{
      if (displayPrivateIndex >= 0)
            freeDisplayPrivateIndex(displayPrivateIndex);
}

CompPluginDep snowDeps[] = {
      {CompPluginRuleAfterCategory, "imageformat"}
      ,
};

CompPluginVTable snowVTable = {
      "snow",
      N_("Snow"),
      N_("XSnow for Beryl"),
      snowInit,
      snowFini,
      snowInitDisplay,
      snowFiniDisplay,
      snowInitScreen,
      snowFiniScreen,
      0,
      0,
      snowGetDisplayOptions,
      snowSetDisplayOption,
      0,                                        /*snowGetScreenOptions */
      0,                                        /*snowSetScreenOption */
      snowDeps,
      sizeof(snowDeps) / sizeof(snowDeps[0]),
      0,
      0,
      BERYL_ABI_INFO,
      "beryl-plugins-unsupported",
      "misc",
      0,
      0,
      False,
};

CompPluginVTable *getCompPluginInfo(void)
{
      return &snowVTable;
}

Generated by  Doxygen 1.6.0   Back to index