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

zoom.c

/*
 * Copyright © 2005 Novell, Inc.
 *
 * 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.
 *
 * Author: David Reveman <davidr@novell.com>
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <sys/time.h>

#include <beryl.h>

#define ZOOM_POINTER_INVERT_Y_DEFAULT FALSE

#define ZOOM_POINTER_SENSITIVITY_DEFAULT   1.0f
#define ZOOM_POINTER_SENSITIVITY_MIN       0.01f
#define ZOOM_POINTER_SENSITIVITY_MAX       100.0f
#define ZOOM_POINTER_SENSITIVITY_PRECISION 0.01f

#define ZOOM_POINTER_SENSITIVITY_FACTOR 0.001f

#define ZOOM_INITIATE_BUTTON_DEFAULT    Button3
#define ZOOM_INITIATE_MODIFIERS_DEFAULT CompSuperMask

#define ZOOM_IN_BUTTON_DEFAULT    Button4
#define ZOOM_IN_MODIFIERS_DEFAULT CompSuperMask

#define ZOOM_OUT_BUTTON_DEFAULT    Button5
#define ZOOM_OUT_MODIFIERS_DEFAULT CompSuperMask

#define ZOOM_SPEED_DEFAULT   1.5f
#define ZOOM_SPEED_MIN       0.1f
#define ZOOM_SPEED_MAX       50.0f
#define ZOOM_SPEED_PRECISION 0.1f

#define ZOOM_STEP_DEFAULT   2.0f
#define ZOOM_STEP_MIN       1.0f
#define ZOOM_STEP_MAX       5.0f
#define ZOOM_STEP_PRECISION 0.01f

#define ZOOM_MIN_DEFAULT   0.1f
#define ZOOM_MIN_MIN       0.0f
#define ZOOM_MIN_MAX       1.0f
#define ZOOM_MIN_PRECISION 0.01f

#define ZOOM_MAX_DEFAULT   1.0f
#define ZOOM_MAX_MIN       1.0f
#define ZOOM_MAX_MAX       100.0f
#define ZOOM_MAX_PRECISION 0.01f

#define ZOOM_TIMESTEP_DEFAULT   1.2f
#define ZOOM_TIMESTEP_MIN       0.1f
#define ZOOM_TIMESTEP_MAX       50.0f
#define ZOOM_TIMESTEP_PRECISION 0.1f

#define ZOOM_FILTER_LINEAR_DEFAULT TRUE
#define ZOOM_ALLOW_KEYBOARD_INPUT_DEFAULT TRUE

static int displayPrivateIndex;

#define ZOOM_DISPLAY_OPTION_INITIATE 0
#define ZOOM_DISPLAY_OPTION_IN         1
#define ZOOM_DISPLAY_OPTION_OUT         2
#define ZOOM_DISPLAY_OPTION_NUM         3

typedef struct _ZoomDisplay
{
      int screenPrivateIndex;
      HandleEventProc handleEvent;

      CompOption opt[ZOOM_DISPLAY_OPTION_NUM];
} ZoomDisplay;

#define ZOOM_SCREEN_OPTION_POINTER_INVERT_Y    0
#define ZOOM_SCREEN_OPTION_POINTER_SENSITIVITY 1
#define ZOOM_SCREEN_OPTION_SPEED           2
#define ZOOM_SCREEN_OPTION_STEP               3
#define ZOOM_SCREEN_OPTION_MIN                   4
#define ZOOM_SCREEN_OPTION_MAX                   5
#define ZOOM_SCREEN_OPTION_TIMESTEP           6
#define ZOOM_SCREEN_OPTION_FILTER_LINEAR       7
#define ZOOM_SCREEN_OPTION_ALLOW_KEYBOARD_INPUT  8
#define ZOOM_SCREEN_OPTION_NUM               9

typedef struct _ZoomScreen
{
      PreparePaintScreenProc preparePaintScreen;
      DonePaintScreenProc donePaintScreen;
      PaintScreenProc paintScreen;
      SetScreenOptionForPluginProc setScreenOptionForPlugin;

      CompOption opt[ZOOM_SCREEN_OPTION_NUM];

      Bool pointerInvertY;
      float pointerSensitivity;

      float speed;
      float step;
      float timestep;
      float minZoom;
      float maxZoom;

      int grabIndex;

      GLfloat currentZoom;
      GLfloat newZoom;

      GLfloat xVelocity;
      GLfloat yVelocity;
      GLfloat zVelocity;

      GLfloat xTranslate;
      GLfloat yTranslate;

      GLfloat xtrans;
      GLfloat ytrans;
      GLfloat ztrans;

      XPoint savedPointer;
      Bool grabbed;

      float maxTranslate;
} ZoomScreen;

#define GET_ZOOM_DISPLAY(d)                      \
    ((ZoomDisplay *) (d)->privates[displayPrivateIndex].ptr)

#define ZOOM_DISPLAY(d)                   \
    ZoomDisplay *zd = GET_ZOOM_DISPLAY (d)

#define GET_ZOOM_SCREEN(s, zd)                         \
    ((ZoomScreen *) (s)->privates[(zd)->screenPrivateIndex].ptr)

#define ZOOM_SCREEN(s)                                \
    ZoomScreen *zs = GET_ZOOM_SCREEN (s, GET_ZOOM_DISPLAY (s->display))

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

static Bool
zoomSetScreenOption(CompScreen * screen, char *name, CompOptionValue * value)
{
      CompOption *o;
      int index;

      ZOOM_SCREEN(screen);

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

      switch (index)
      {
      case ZOOM_SCREEN_OPTION_POINTER_INVERT_Y:
            if (compSetBoolOption(o, value))
            {
                  zs->pointerInvertY = o->value.b;
                  return TRUE;
            }
            break;
      case ZOOM_SCREEN_OPTION_POINTER_SENSITIVITY:
            if (compSetFloatOption(o, value))
            {
                  zs->pointerSensitivity = o->value.f *
                              ZOOM_POINTER_SENSITIVITY_FACTOR;
                  return TRUE;
            }
            break;
      case ZOOM_SCREEN_OPTION_STEP:
            if (compSetFloatOption(o, value))
            {
                  zs->step = o->value.f;
                  return TRUE;
            }
            break;
      case ZOOM_SCREEN_OPTION_MIN:
            if (compSetFloatOption(o, value))
            {
                  zs->minZoom = o->value.f;
                  return TRUE;
            }
            break;
      case ZOOM_SCREEN_OPTION_MAX:
            if (compSetFloatOption(o, value))
            {
                  zs->maxZoom = o->value.f;
                  return TRUE;
            }
            break;
      case ZOOM_SCREEN_OPTION_SPEED:
            if (compSetFloatOption(o, value))
            {
                  zs->speed = o->value.f;
                  return TRUE;
            }
            break;
      case ZOOM_SCREEN_OPTION_TIMESTEP:
            if (compSetFloatOption(o, value))
            {
                  zs->timestep = o->value.f;
                  return TRUE;
            }
            break;
      case ZOOM_SCREEN_OPTION_FILTER_LINEAR:
            if (compSetBoolOption(o, value))
                  return TRUE;
      case ZOOM_SCREEN_OPTION_ALLOW_KEYBOARD_INPUT:
            if (compSetBoolOption(o, value))
                  return TRUE;
      default:
            break;
      }

      return FALSE;
}

static void zoomScreenInitOptions(ZoomScreen * zs)
{
      CompOption *o;

      o = &zs->opt[ZOOM_SCREEN_OPTION_POINTER_INVERT_Y];
      o->advanced = False;
      o->name = "invert_y";
      o->group = N_("Misc. options");
      o->subGroup = N_("");
      o->displayHints = "";
      o->shortDesc = N_("Pointer Invert Y");
      o->longDesc = N_("Invert Y axis for Pointer movement.");
      o->type = CompOptionTypeBool;
      o->value.b = ZOOM_POINTER_INVERT_Y_DEFAULT;

      o = &zs->opt[ZOOM_SCREEN_OPTION_POINTER_SENSITIVITY];
      o->advanced = False;
      o->name = "sensitivity";
      o->group = N_("Misc. options");
      o->subGroup = N_("");
      o->displayHints = "";
      o->shortDesc = N_("Pointer Sensitivity");
      o->longDesc = N_("Sensitivity of Pointer movement.");
      o->type = CompOptionTypeFloat;
      o->value.f = ZOOM_POINTER_SENSITIVITY_DEFAULT;
      o->rest.f.min = ZOOM_POINTER_SENSITIVITY_MIN;
      o->rest.f.max = ZOOM_POINTER_SENSITIVITY_MAX;
      o->rest.f.precision = ZOOM_POINTER_SENSITIVITY_PRECISION;

      o = &zs->opt[ZOOM_SCREEN_OPTION_SPEED];
      o->advanced = False;
      o->name = "speed";
      o->group = N_("Misc. options");
      o->subGroup = N_("");
      o->displayHints = "";
      o->shortDesc = N_("Speed");
      o->longDesc = N_("Zoom Speed.");
      o->type = CompOptionTypeFloat;
      o->value.f = ZOOM_SPEED_DEFAULT;
      o->rest.f.min = ZOOM_SPEED_MIN;
      o->rest.f.max = ZOOM_SPEED_MAX;
      o->rest.f.precision = ZOOM_SPEED_PRECISION;

      o = &zs->opt[ZOOM_SCREEN_OPTION_STEP];
      o->advanced = False;
      o->name = "step";
      o->group = N_("Misc. options");
      o->subGroup = N_("");
      o->displayHints = "";
      o->shortDesc = N_("Zoom Step");
      o->longDesc = N_("Zoom factor multiplier for amount of Zooming "
                               "in each ZoomIn/ZoomOut.");
      o->type = CompOptionTypeFloat;
      o->value.f = ZOOM_SPEED_DEFAULT;
      o->rest.f.min = ZOOM_SPEED_MIN;
      o->rest.f.max = ZOOM_SPEED_MAX;
      o->rest.f.precision = ZOOM_SPEED_PRECISION;

      o = &zs->opt[ZOOM_SCREEN_OPTION_MIN];
      o->advanced = False;
      o->name = "min";
      o->group = N_("Misc. options");
      o->subGroup = N_("");
      o->displayHints = "";
      o->shortDesc = N_("Minimum Zoom");
      o->longDesc = N_("Minimum Zoom Value (how close you can zoom).");
      o->type = CompOptionTypeFloat;
      o->value.f = ZOOM_MIN_DEFAULT;
      o->rest.f.min = ZOOM_MIN_MIN;
      o->rest.f.max = ZOOM_MIN_MAX;
      o->rest.f.precision = ZOOM_MIN_PRECISION;

      o = &zs->opt[ZOOM_SCREEN_OPTION_MAX];
      o->advanced = False;
      o->name = "max";
      o->group = N_("Misc. options");
      o->subGroup = N_("");
      o->displayHints = "";
      o->shortDesc = N_("Maximum Zoom");
      o->longDesc = N_("Maximum Zoom Value (how far you can zoom away).");
      o->type = CompOptionTypeFloat;
      o->value.f = ZOOM_MAX_DEFAULT;
      o->rest.f.min = ZOOM_MAX_MIN;
      o->rest.f.max = ZOOM_MAX_MAX;
      o->rest.f.precision = ZOOM_MAX_PRECISION;

      o = &zs->opt[ZOOM_SCREEN_OPTION_TIMESTEP];
      o->advanced = False;
      o->name = "timestep";
      o->group = N_("Misc. options");
      o->subGroup = N_("");
      o->displayHints = "";
      o->shortDesc = N_("Zoom Timestep");
      o->longDesc = N_("Zoom Timestep.");
      o->type = CompOptionTypeFloat;
      o->value.f = ZOOM_TIMESTEP_DEFAULT;
      o->rest.f.min = ZOOM_TIMESTEP_MIN;
      o->rest.f.max = ZOOM_TIMESTEP_MAX;
      o->rest.f.precision = ZOOM_TIMESTEP_PRECISION;

      o = &zs->opt[ZOOM_SCREEN_OPTION_FILTER_LINEAR];
      o->advanced = False;
      o->name = "filter_linear";
      o->group = N_("Misc. options");
      o->subGroup = N_("Visual quality");
      o->displayHints = "";
      o->shortDesc = N_("Filter Linear");
      o->longDesc = N_("USe Linear Filter when Zoomed in.");
      o->type = CompOptionTypeBool;
      o->value.b = ZOOM_FILTER_LINEAR_DEFAULT;

      o = &zs->opt[ZOOM_SCREEN_OPTION_ALLOW_KEYBOARD_INPUT];
      o->advanced = False;
      o->name = "allow_keyboard_input";
      o->group = N_("Misc. options");
      o->subGroup = N_("");
      o->displayHints = "";
      o->shortDesc = N_("Allow Keyboard Input");
      o->longDesc = N_("Allow Keyboard Input when Zoomed.");
      o->type = CompOptionTypeBool;
      o->value.b = ZOOM_ALLOW_KEYBOARD_INPUT_DEFAULT;
}

static CompOption *zoomGetScreenOptions(CompScreen * screen, int *count)
{
      if (screen)
      {
            ZOOM_SCREEN(screen);

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

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


static int adjustZoomVelocity(ZoomScreen * zs)
{
      float d, adjust, amount;

      d = (zs->newZoom - zs->currentZoom) * 75.0f;

      adjust = d * 0.002f;
      amount = fabs(d);
      if (amount < 1.0f)
            amount = 1.0f;
      else if (amount > 5.0f)
            amount = 5.0f;

      zs->zVelocity = (amount * zs->zVelocity + adjust) / (amount + 1.0f);

      return (fabs(d) < 0.1f && fabs(zs->zVelocity) < 0.005f);
}

static void zoomPreparePaintScreen(CompScreen * s, int msSinceLastPaint)
{
      ZOOM_SCREEN(s);

      if (zs->grabIndex)
      {
            compDisplaySetRequestFlagForPlugin(s->display, "zoom", "ENABLE_3D");

            int steps;
            float amount, chunk;

            amount = msSinceLastPaint * 0.05f * zs->speed;
            steps = amount / (0.5f * zs->timestep);
            if (!steps)
                  steps = 1;
            chunk = amount / (float)steps;

            while (steps--)
            {
                  zs->xVelocity /= 1.25f;
                  zs->yVelocity /= 1.25f;

                  if (fabs(zs->xVelocity) < 0.001f)
                        zs->xVelocity = 0.0f;
                  if (fabs(zs->yVelocity) < 0.001f)
                        zs->yVelocity = 0.0f;

                  zs->xTranslate += zs->xVelocity * chunk;
                  if (zs->xTranslate < -zs->maxTranslate)
                  {
                        zs->xTranslate = -zs->maxTranslate;
                        zs->xVelocity = 0.0f;
                  }
                  else if (zs->xTranslate > zs->maxTranslate)
                  {
                        zs->xTranslate = zs->maxTranslate;
                        zs->xVelocity = 0.0f;
                  }

                  zs->yTranslate += zs->yVelocity * chunk;
                  if (zs->yTranslate < -zs->maxTranslate)
                  {
                        zs->yTranslate = -zs->maxTranslate;
                        zs->yVelocity = 0.0f;
                  }
                  else if (zs->yTranslate > zs->maxTranslate)
                  {
                        zs->yTranslate = zs->maxTranslate;
                        zs->yVelocity = 0.0f;
                  }

                  if (adjustZoomVelocity(zs))
                  {
                        zs->currentZoom = zs->newZoom;
                        zs->zVelocity = 0.0f;
                  }
                  else
                  {
                        zs->currentZoom +=
                                    (zs->zVelocity * msSinceLastPaint) / s->redrawTime;
                  }

                  zs->ztrans = DEFAULT_Z_CAMERA * zs->currentZoom;
                  if (zs->ztrans <= 0.1f)
                  {
                        zs->zVelocity = 0.0f;
                        zs->ztrans = 0.1f;
                  }

                  zs->xtrans = -zs->xTranslate * (1.0f - zs->currentZoom);
                  zs->ytrans = zs->yTranslate * (1.0f - zs->currentZoom);

                  if (!zs->grabbed)
                  {
                        if (zs->currentZoom == 1.0f && zs->zVelocity == 0.0f)
                        {
                              zs->xVelocity = zs->yVelocity = 0.0f;

                              compDisplayClearRequestFlagForPlugin
                                          (s->display, "zoom", "ENABLE_3D");

                              removeScreenGrabKeyboardOptional(s,
                                                                               zs->
                                                                               grabIndex,
                                                                               &zs->
                                                                               savedPointer,
                                                                               !zs->
                                                                               opt
                                                                               [ZOOM_SCREEN_OPTION_ALLOW_KEYBOARD_INPUT].
                                                                               value.b);
                              zs->grabIndex = FALSE;
                              break;
                        }
                  }
            }
      }

      UNWRAP(zs, s, preparePaintScreen);
      (*s->preparePaintScreen) (s, msSinceLastPaint);
      WRAP(zs, s, preparePaintScreen, zoomPreparePaintScreen);
}

static void zoomDonePaintScreen(CompScreen * s)
{
      ZOOM_SCREEN(s);

      if (zs->grabIndex)
      {
            if (zs->currentZoom != zs->newZoom ||
                  zs->xVelocity || zs->yVelocity || zs->zVelocity)
                  damageScreen(s);
      }

      UNWRAP(zs, s, donePaintScreen);
      (*s->donePaintScreen) (s);
      WRAP(zs, s, donePaintScreen, zoomDonePaintScreen);
}

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

      ZOOM_SCREEN(s);

      if (zs->grabIndex)
      {
            ScreenPaintAttrib sa = *sAttrib;
            int saveFilter;

            sa.xTranslate += zs->xtrans;
            sa.yTranslate += zs->ytrans;

            sa.zCamera = -zs->ztrans;

            /* hack to get sides rendered correctly */
            if (zs->xtrans > 0.0f)
                  sa.xRotate += 0.000001f;
            else
                  sa.xRotate -= 0.000001f;

            mask &= ~PAINT_SCREEN_REGION_MASK;
            mask |= PAINT_SCREEN_TRANSFORMED_MASK | PAINT_SCREEN_CLEAR_MASK;

            saveFilter = s->filter[SCREEN_TRANS_FILTER];

            if (zs->opt[ZOOM_SCREEN_OPTION_FILTER_LINEAR].value.b ||
                  zs->zVelocity != 0.0f)
                  s->filter[SCREEN_TRANS_FILTER] = COMP_TEXTURE_FILTER_GOOD;
            else
                  s->filter[SCREEN_TRANS_FILTER] = COMP_TEXTURE_FILTER_FAST;

            UNWRAP(zs, s, paintScreen);
            status = (*s->paintScreen) (s, &sa, region, output, mask);
            WRAP(zs, s, paintScreen, zoomPaintScreen);

            s->filter[SCREEN_TRANS_FILTER] = saveFilter;
      }
      else
      {
            UNWRAP(zs, s, paintScreen);
            status = (*s->paintScreen) (s, sAttrib, region, output, mask);
            WRAP(zs, s, paintScreen, zoomPaintScreen);
      }

      return status;
}

static Bool
zoomIn(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)
      {
            ZOOM_SCREEN(s);

            if (otherScreenGrabExist(s, "zoom", "scale", 0))
                  return FALSE;

            if (!zs->grabIndex)
            {
                  zs->grabIndex = pushScreenGrabKeyboardOptional
                              (s, s->invisibleCursor, "zoom",
                               !zs->opt[ZOOM_SCREEN_OPTION_ALLOW_KEYBOARD_INPUT].value.
                               b);

                  zs->savedPointer.x = d->pointerX;
                  zs->savedPointer.y = d->pointerY;
            }

            if (zs->grabIndex)
            {
                  int x, y;

                  x = getIntOptionNamed(option, nOption, "x", 0);
                  y = getIntOptionNamed(option, nOption, "y", 0);

                  zs->grabbed = TRUE;

                  zs->newZoom /= zs->step;
                  if (zs->newZoom < zs->minZoom)
                        zs->newZoom = zs->minZoom;

                  damageScreen(s);

                  if (zs->currentZoom == 1.0f)
                  {
                        zs->xTranslate = (x - s->width / 2) / (s->width * 2.0f);
                        zs->yTranslate = (y - s->height / 2) / (s->height * 2.0f);

                        zs->xTranslate /= zs->newZoom;
                        zs->yTranslate /= zs->newZoom;
                  }

                  else if ((zs->currentZoom > 1.0f
                                && zs->newZoom <= 1.0f)
                               || (zs->newZoom > 0.98f && zs->newZoom < 1.02f))
                  {
                        zs->newZoom = 1.0f;
                        zs->grabbed = FALSE;
                        damageScreen(s);
                  }
            }
      }

      return FALSE;
}

static Bool
zoomInitiate(CompDisplay * d,
                   CompAction * action,
                   CompActionState state, CompOption * option, int nOption)
{
      zoomIn(d, action, state, option, nOption);

      if (state & CompActionStateInitKey)
            action->state |= CompActionStateTermKey;

      if (state & CompActionStateInitButton)
            action->state |= CompActionStateTermButton;

      return FALSE;
}

static Bool
zoomOut(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)
      {
            ZOOM_SCREEN(s);

            if (otherScreenGrabExist(s, "zoom", "scale", 0))
                  return FALSE;

            if (!zs->grabIndex)
            {
                  zs->grabIndex = pushScreenGrabKeyboardOptional
                              (s, s->invisibleCursor, "zoom",
                               !zs->opt[ZOOM_SCREEN_OPTION_ALLOW_KEYBOARD_INPUT].value.
                               b);

                  zs->savedPointer.x = d->pointerX;
                  zs->savedPointer.y = d->pointerY;
            }

            if (zs->grabIndex && zs->currentZoom == 1.0 && zs->maxZoom == 1.0)
            {
                  zs->grabbed = FALSE;
                  damageScreen(s);
                  return FALSE;
            }

            if (zs->grabIndex)
            {
                  int x, y;

                  x = getIntOptionNamed(option, nOption, "x", 0);
                  y = getIntOptionNamed(option, nOption, "y", 0);

                  zs->grabbed = TRUE;

                  zs->newZoom *= zs->step;
                  if (zs->newZoom > zs->maxZoom)
                        zs->newZoom = zs->maxZoom;

                  if (zs->currentZoom == 1.0f)
                  {
                        zs->xTranslate = (x - s->width / 2) / (s->width * 2.0f);
                        zs->yTranslate = (y - s->height / 2) / (s->height * 2.0f);

                        zs->xTranslate *= zs->newZoom;
                        zs->yTranslate *= zs->newZoom;
                  }

                  if ((zs->currentZoom < 1.0f && zs->newZoom >= 1.0f)
                        || (zs->newZoom > 0.98f && zs->newZoom < 1.02f))
                  {
                        zs->grabbed = FALSE;
                        zs->newZoom = 1.0f;
                  }

                  damageScreen(s);
            }
      }

      return FALSE;
}

static Bool
zoomTerminate(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)
      {
            ZOOM_SCREEN(s);

            if (xid && s->root != xid)
                  continue;

            if (zs->grabIndex)
            {
                  zs->newZoom = 1.0f;
                  zs->grabbed = FALSE;

                  damageScreen(s);
            }
      }

      action->state &= ~(CompActionStateTermKey | CompActionStateTermButton);

      return FALSE;
}

static void zoomHandleEvent(CompDisplay * d, XEvent * event)
{
      CompScreen *s;

      ZOOM_DISPLAY(d);

      switch (event->type)
      {
      case MotionNotify:
            s = findScreenAtDisplay(d, event->xmotion.root);
            if (s)
            {
                  ZOOM_SCREEN(s);

                  if (zs->grabIndex && zs->grabbed)
                  {
                        GLfloat pointerDx;
                        GLfloat pointerDy;

                        pointerDx = d->pointerX - d->lastPointerX;
                        pointerDy = d->pointerY - d->lastPointerY;

                        if (event->xmotion.x_root < 50 ||
                              event->xmotion.y_root < 50 ||
                              event->xmotion.x_root > s->width - 50
                              || event->xmotion.y_root > s->height - 50)
                        {
                              warpPointer(d,
                                                (s->width / 2) -
                                                d->pointerX, (s->height / 2) - d->pointerY);
                        }

                        if (zs->pointerInvertY)
                              pointerDy = -pointerDy;

                        zs->xVelocity += pointerDx * zs->pointerSensitivity;
                        zs->yVelocity += pointerDy * zs->pointerSensitivity;

                        damageScreen(s);
                  }
            }
      default:
            break;
      }

      UNWRAP(zd, d, handleEvent);
      (*d->handleEvent) (d, event);
      WRAP(zd, d, handleEvent, zoomHandleEvent);
}

static void zoomUpdateCubeOptions(CompScreen * s)
{
      CompPlugin *p;

      ZOOM_SCREEN(s);

      p = findActivePlugin("cube");
      if (p && p->vTable->getScreenOptions)
      {
            CompOption *options, *option;
            int nOptions;

            options = (*p->vTable->getScreenOptions) (s, &nOptions);
            option = compFindOption(options, nOptions, "in", 0);
            if (option)
                  zs->maxTranslate = option->value.b ? 0.85f : 1.5f;
      }
      else
      {
            zs->maxTranslate = 1.5f;
      }
}

static Bool
zoomSetScreenOptionForPlugin(CompScreen * s,
                                           char *plugin,
                                           char *name, CompOptionValue * value)
{
      Bool status;

      ZOOM_SCREEN(s);

      UNWRAP(zs, s, setScreenOptionForPlugin);
      status = (*s->setScreenOptionForPlugin) (s, plugin, name, value);
      WRAP(zs, s, setScreenOptionForPlugin, zoomSetScreenOptionForPlugin);

      if (status && strcmp(plugin, "cube") == 0)
            zoomUpdateCubeOptions(s);

      return status;
}

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

      ZOOM_DISPLAY(display);

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

      switch (index)
      {
      case ZOOM_DISPLAY_OPTION_INITIATE:
      case ZOOM_DISPLAY_OPTION_IN:
      case ZOOM_DISPLAY_OPTION_OUT:
            if (setDisplayAction(display, o, value))
                  return TRUE;
            break;
      default:
            break;
      }

      return FALSE;
}

static void zoomDisplayInitOptions(ZoomDisplay * zd)
{
      CompOption *o;

      o = &zd->opt[ZOOM_DISPLAY_OPTION_INITIATE];
      o->advanced = False;
      o->name = "initiate";
      o->group = N_("Bindings");
      o->subGroup = N_("Initiate");
      o->displayHints = "";
      o->shortDesc = N_("Initiate");
      o->longDesc = N_("Initiate Zoom.");
      o->type = CompOptionTypeAction;
      o->value.action.initiate = zoomInitiate;
      o->value.action.terminate = zoomTerminate;
      o->value.action.bell = FALSE;
      o->value.action.edgeMask = 0;
      o->value.action.state = CompActionStateInitKey;
      o->value.action.state |= CompActionStateInitButton;
      o->value.action.type = CompBindingTypeButton;
      o->value.action.button.modifiers = ZOOM_INITIATE_MODIFIERS_DEFAULT;
      o->value.action.button.button = ZOOM_INITIATE_BUTTON_DEFAULT;

      o = &zd->opt[ZOOM_DISPLAY_OPTION_IN];
      o->advanced = False;
      o->name = "zoom_in";
      o->group = N_("Bindings");
      o->subGroup = N_("Zoom In");
      o->displayHints = "";
      o->shortDesc = N_("Zoom In");
      o->longDesc = N_("Zoom In.");
      o->type = CompOptionTypeAction;
      o->value.action.initiate = zoomIn;
      o->value.action.terminate = 0;
      o->value.action.bell = FALSE;
      o->value.action.edgeMask = 0;
      o->value.action.state = CompActionStateInitKey;
      o->value.action.state |= CompActionStateInitButton;
      o->value.action.type = CompBindingTypeButton;
      o->value.action.button.modifiers = ZOOM_IN_MODIFIERS_DEFAULT;
      o->value.action.button.button = ZOOM_IN_BUTTON_DEFAULT;

      o = &zd->opt[ZOOM_DISPLAY_OPTION_OUT];
      o->advanced = False;
      o->name = "zoom_out";
      o->group = N_("Bindings");
      o->subGroup = N_("Zoom Out");
      o->displayHints = "";
      o->shortDesc = N_("Zoom Out");
      o->longDesc = N_("Zoom Out.");
      o->type = CompOptionTypeAction;
      o->value.action.initiate = zoomOut;
      o->value.action.terminate = 0;
      o->value.action.bell = FALSE;
      o->value.action.edgeMask = 0;
      o->value.action.state = CompActionStateInitKey;
      o->value.action.state |= CompActionStateInitButton;
      o->value.action.type = CompBindingTypeButton;
      o->value.action.button.modifiers = ZOOM_OUT_MODIFIERS_DEFAULT;
      o->value.action.button.button = ZOOM_OUT_BUTTON_DEFAULT;
}

static CompOption *zoomGetDisplayOptions(CompDisplay * display, int *count)
{
      if (display)
      {
            ZOOM_DISPLAY(display);

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

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

static Bool zoomInitDisplay(CompPlugin * p, CompDisplay * d)
{
      ZoomDisplay *zd;

      zd = malloc(sizeof(ZoomDisplay));
      if (!zd)
            return FALSE;

      zd->screenPrivateIndex = allocateScreenPrivateIndex(d);
      if (zd->screenPrivateIndex < 0)
      {
            free(zd);
            return FALSE;
      }

      zoomDisplayInitOptions(zd);

      WRAP(zd, d, handleEvent, zoomHandleEvent);

      d->privates[displayPrivateIndex].ptr = zd;

      return TRUE;
}

static void zoomFiniDisplay(CompPlugin * p, CompDisplay * d)
{
      ZOOM_DISPLAY(d);

      freeScreenPrivateIndex(d, zd->screenPrivateIndex);

      UNWRAP(zd, d, handleEvent);

      free(zd);
}

static Bool zoomInitScreen(CompPlugin * p, CompScreen * s)
{
      ZoomScreen *zs;

      ZOOM_DISPLAY(s->display);

      zs = malloc(sizeof(ZoomScreen));
      if (!zs)
            return FALSE;

      zs->grabIndex = 0;

      zs->currentZoom = 1.0f;
      zs->newZoom = 1.0f;

      zs->xVelocity = 0.0f;
      zs->yVelocity = 0.0f;
      zs->zVelocity = 0.0f;

      zs->xTranslate = 0.0f;
      zs->yTranslate = 0.0f;

      zs->maxTranslate = 0.85f;

      zs->savedPointer.x = 0;
      zs->savedPointer.y = 0;

      zs->grabbed = FALSE;

      zs->pointerInvertY = ZOOM_POINTER_INVERT_Y_DEFAULT;
      zs->pointerSensitivity = ZOOM_POINTER_SENSITIVITY_DEFAULT *
                  ZOOM_POINTER_SENSITIVITY_FACTOR;

      zs->speed = ZOOM_SPEED_DEFAULT;
      zs->step = ZOOM_STEP_DEFAULT;
      zs->minZoom = ZOOM_MIN_DEFAULT;
      zs->maxZoom = ZOOM_MAX_DEFAULT;
      zs->timestep = ZOOM_TIMESTEP_DEFAULT;

      zoomScreenInitOptions(zs);

      addScreenAction(s, &zd->opt[ZOOM_DISPLAY_OPTION_INITIATE].value.action);
      addScreenAction(s, &zd->opt[ZOOM_DISPLAY_OPTION_IN].value.action);
      addScreenAction(s, &zd->opt[ZOOM_DISPLAY_OPTION_OUT].value.action);

      WRAP(zs, s, preparePaintScreen, zoomPreparePaintScreen);
      WRAP(zs, s, donePaintScreen, zoomDonePaintScreen);
      WRAP(zs, s, paintScreen, zoomPaintScreen);
      WRAP(zs, s, setScreenOptionForPlugin, zoomSetScreenOptionForPlugin);

      s->privates[zd->screenPrivateIndex].ptr = zs;

      zoomUpdateCubeOptions(s);

      return TRUE;
}

static void zoomFiniScreen(CompPlugin * p, CompScreen * s)
{
      ZOOM_SCREEN(s);
      ZOOM_DISPLAY(s->display);

      UNWRAP(zs, s, preparePaintScreen);
      UNWRAP(zs, s, donePaintScreen);
      UNWRAP(zs, s, paintScreen);
      UNWRAP(zs, s, setScreenOptionForPlugin);

      removeScreenAction(s,
                                 &zd->opt[ZOOM_DISPLAY_OPTION_INITIATE].value.action);
      removeScreenAction(s, &zd->opt[ZOOM_DISPLAY_OPTION_IN].value.action);
      removeScreenAction(s, &zd->opt[ZOOM_DISPLAY_OPTION_OUT].value.action);

      free(zs);
}

static Bool zoomInit(CompPlugin * p)
{
      displayPrivateIndex = allocateDisplayPrivateIndex();
      if (displayPrivateIndex < 0)
            return FALSE;

      return TRUE;
}

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

CompPluginFeature zoomFeatures[] = {
      {"zoom"}
};

CompPluginVTable zoomVTable = {
      "zoom",
      N_("Zoom Desktop"),
      N_("Zoom and pan desktop cube"),
      zoomInit,
      zoomFini,
      zoomInitDisplay,
      zoomFiniDisplay,
      zoomInitScreen,
      zoomFiniScreen,
      0,                                        /* InitWindow */
      0,                                        /* FiniWindow */
      zoomGetDisplayOptions,
      zoomSetDisplayOption,
      zoomGetScreenOptions,
      zoomSetScreenOption,
      0,
      0,
      zoomFeatures,
      sizeof(zoomFeatures) / sizeof(zoomFeatures[0]),
      BERYL_ABI_INFO,
      "beryl-plugins-unsupported",
      "accessibility",
      0,
      0,
      False,
};

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

Generated by  Doxygen 1.6.0   Back to index