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

plane.c

/*
 * Copyright © 2006 Red Hat, 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: Soren Sandmann <sandmann@redhat.com>
 */

#define _GNU_SOURCE                       /* for asprintf */

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

#include <X11/Xatom.h>
#include <X11/Xproto.h>

#include <beryl.h>

static int displayPrivateIndex;

#define PLANE_LEFT_KEY_DEFAULT        "Left"
#define PLANE_LEFT_MODIFIERS_DEFAULT  (ControlMask | CompAltMask)

#define PLANE_RIGHT_KEY_DEFAULT       "Right"
#define PLANE_RIGHT_MODIFIERS_DEFAULT (ControlMask | CompAltMask)

#define PLANE_UP_KEY_DEFAULT          "Up"
#define PLANE_UP_MODIFIERS_DEFAULT    (ControlMask | CompAltMask)

#define PLANE_DOWN_KEY_DEFAULT        "Down"
#define PLANE_DOWN_MODIFIERS_DEFAULT  (ControlMask | CompAltMask)

#define PLANE_PREVIEW_KEY_DEFAULT         "Next"
#define PLANE_PREVIEW_MODIFIERS_DEFAULT   (ControlMask | CompAltMask)

enum
{
      PLANE_DISPLAY_OPTION_LEFT,
      PLANE_DISPLAY_OPTION_RIGHT,
      PLANE_DISPLAY_OPTION_DOWN,
      PLANE_DISPLAY_OPTION_UP,
      PLANE_DISPLAY_OPTION_PREVIEW,
      PLANE_DISPLAY_OPTION_TO_1,
      PLANE_DISPLAY_OPTION_TO_2,
      PLANE_DISPLAY_OPTION_TO_3,
      PLANE_DISPLAY_OPTION_TO_4,
      PLANE_DISPLAY_OPTION_TO_5,
      PLANE_DISPLAY_OPTION_TO_6,
      PLANE_DISPLAY_OPTION_TO_7,
      PLANE_DISPLAY_OPTION_TO_8,
      PLANE_DISPLAY_OPTION_TO_9,
      PLANE_DISPLAY_OPTION_TO_10,
      PLANE_DISPLAY_OPTION_TO_11,
      PLANE_DISPLAY_OPTION_TO_12,
      PLANE_N_DISPLAY_OPTIONS
};

typedef struct _PlaneDisplay
{
      int screenPrivateIndex;
      HandleEventProc handleEvent;

      CompOption opt[PLANE_N_DISPLAY_OPTIONS];

      int flipTime;
} PlaneDisplay;

#define PLANE_WRAP_DEFAULT FALSE

#define PLANE_SCROLL_TIME_DEFAULT 250
#define PLANE_SCROLL_TIME_MAX 2000
#define PLANE_SCROLL_TIME_MIN 1
#define PLANE_SCROLL_TIME_PRECISION 1

enum
{
      PLANE_SCREEN_OPTION_WRAP,
      PLANE_SCREEN_OPTION_TIME,
      PLANE_SCREEN_OPTION_NUM
};

typedef struct _PlaneScreen
{
      CompOption opt[PLANE_SCREEN_OPTION_NUM];
      PaintTransformedScreenProc paintTransformedScreen;
      PreparePaintScreenProc preparePaintScreen;
      DonePaintScreenProc donePaintScreen;
      PaintScreenProc paintScreen;

      SetScreenOptionForPluginProc setScreenOptionForPlugin;
      WindowGrabNotifyProc windowGrabNotify;
      WindowUngrabNotifyProc windowUngrabNotify;

      CompTimeoutHandle timeout_handle;
      int timer;
      int preview;
      double cur_x;
      double cur_y;
      double dest_x;
      double dest_y;
      float initZoom;
} PlaneScreen;

#define GET_PLANE_DISPLAY(d)                           \
    ((PlaneDisplay *) (d)->privates[displayPrivateIndex].ptr)

#define PLANE_DISPLAY(d)                   \
    PlaneDisplay *pd = GET_PLANE_DISPLAY (d)

#define GET_PLANE_SCREEN(s, pd)                          \
    ((PlaneScreen *) (s)->privates[(pd)->screenPrivateIndex].ptr)

#define PLANE_SCREEN(s)                                     \
    PlaneScreen *ps = GET_PLANE_SCREEN (s, GET_PLANE_DISPLAY (s->display))

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

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

      PLANE_SCREEN(screen);

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

      switch (index)
      {
      case PLANE_SCREEN_OPTION_WRAP:
            if (compSetBoolOption(o, value))
                  return TRUE;
            break;
      case PLANE_SCREEN_OPTION_TIME:
            if (compSetIntOption(o, value))
                  return TRUE;
            break;
      default:
            break;
      }
      return FALSE;
}

static void planeScreenInitOptions(PlaneScreen * ps)
{
      CompOption *o;

      o = &ps->opt[PLANE_SCREEN_OPTION_WRAP];
      o->advanced = False;
      o->name = "wrap";
      o->group = N_("Misc. options");
      o->subGroup = N_("");
      o->displayHints = "";
      o->shortDesc = N_("Wrap Around");
      o->longDesc = N_("Enable Wrapping Around.");
      o->type = CompOptionTypeBool;
      o->value.b = PLANE_WRAP_DEFAULT;

      o = &ps->opt[PLANE_SCREEN_OPTION_TIME];
      o->advanced = False;
      o->name = "time";
      o->group = N_("Misc. options");
      o->subGroup = N_("");
      o->displayHints = "";
      o->shortDesc = N_("Scrolling Time");
      o->longDesc = N_("Scrolling Time when switching desktops.");
      o->type = CompOptionTypeInt;
      o->value.i = PLANE_SCROLL_TIME_DEFAULT;
      o->rest.i.min = PLANE_SCROLL_TIME_MIN;
      o->rest.i.max = PLANE_SCROLL_TIME_MAX;
}

static CompOption *planeGetScreenOptions(CompScreen * screen, int *count)
{
      if (screen)
      {
            PLANE_SCREEN(screen);
            *count = NUM_OPTIONS(ps);
            return ps->opt;
      }
      else
      {
            PlaneScreen *ps = malloc(sizeof(PlaneScreen));

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

static Bool end_move(void *data)
{
      CompScreen *screen = data;

      PLANE_SCREEN(screen);

      //wait until de-scale is finished before setting viewport
      if (screenGrabExist(screen, "scale", 0))
      {
            ps->timeout_handle = compAddTimeout(20, end_move, screen);
            return FALSE;
      }

      moveScreenViewport(screen, -ps->dest_x, -ps->dest_y, TRUE);

      ps->dest_x = 0;
      ps->dest_y = 0;

      ps->timeout_handle = 0;

      focusDefaultWindow(screen->display);

      return FALSE;
}

static void compute_translation(PlaneScreen * ps, double *x, double *y)
{
      double dx, dy;
      double elapsed =
                  1 -
                  (ps->timer / (double)(ps->opt[PLANE_SCREEN_OPTION_TIME].value.i));

      if (elapsed < 0.0)
            elapsed = 0.0;
      if (elapsed > 1.0)
            elapsed = 1.0;

      /* Use temporary variables to you can pass in &ps->cur_x */
      dx = (ps->dest_x - ps->cur_x) * elapsed + ps->cur_x;
      dy = (ps->dest_y - ps->cur_y) * elapsed + ps->cur_y;

      *x = dx;
      *y = dy;
}

static void move_viewport(CompScreen * screen, int dx, int dy)
{
      PLANE_SCREEN(screen);

      if (ps->timeout_handle)
      {
            compute_translation(ps, &ps->cur_x, &ps->cur_y);

            ps->dest_x += dx;
            ps->dest_y += dy;

            compRemoveTimeout(ps->timeout_handle);
      }
      else
      {
            ps->cur_x = 0.0;
            ps->cur_y = 0.0;
            ps->dest_x = dx;
            ps->dest_y = dy;
      }

      if (!ps->opt[PLANE_SCREEN_OPTION_WRAP].value.b)
      {
            if (ps->dest_x + screen->x > screen->hsize - 1)
                  ps->dest_x = screen->hsize - screen->x - 1;

            if (ps->dest_x + screen->x < 0)
                  ps->dest_x = -screen->x;

            if (ps->dest_y + screen->y > screen->vsize - 1)
                  ps->dest_y = screen->vsize - screen->y - 1;

            if (ps->dest_y + screen->y < 0)
                  ps->dest_y = -screen->y;
      }

      ps->timer = ps->opt[PLANE_SCREEN_OPTION_TIME].value.i;
      ps->timeout_handle =
                  compAddTimeout(ps->opt[PLANE_SCREEN_OPTION_TIME].value.i,
                                       end_move, screen);

      damageScreen(screen);
}

static void planePreparePaintScreen(CompScreen * s, int msSinceLastPaint)
{
      PLANE_SCREEN(s);

      ps->timer -= msSinceLastPaint;

      UNWRAP(ps, s, preparePaintScreen);

      (*s->preparePaintScreen) (s, msSinceLastPaint);

      WRAP(ps, s, preparePaintScreen, planePreparePaintScreen);
}

static void
planePaintTransformedScreen(CompScreen * screen,
                                          const ScreenPaintAttrib * sAttrib,
                                          Region region, int output, unsigned int mask)
{
      PLANE_SCREEN(screen);
      static Bool notfirst;

      /* If it's the first movement store the zCamera, not sure what a sane value would be so this is a stopgap */
      if (!notfirst)
      {
            ps->initZoom = sAttrib->zCamera;

      }
      UNWRAP(ps, screen, paintTransformedScreen);
      mask &= ~PAINT_SCREEN_CLEAR_MASK;
      if (ps->preview && !ps->timeout_handle)
      {

            ScreenPaintAttrib sa = *sAttrib;

            (*screen->paintTransformedScreen) (screen, &sa, region, output, mask);
            if (sa.zCamera != ps->initZoom)
            {

                  /* If we are not moving zoom back LESS when drawing the current viewport than the others, gives a zoom of sorts to the selected viewport */
                  sa.zCamera = -1.5;

                  (*screen->paintTransformedScreen) (screen,
                                                                     &sa, region, output, mask);
                  WRAP(ps, screen, paintTransformedScreen,
                         planePaintTransformedScreen);

                  return;

            }

      }
      glPushMatrix();

      glClear(GL_COLOR_BUFFER_BIT);

      if (ps->timeout_handle)
      {
            double dx, dy, tx, ty;
            int vx, vy;

            clearTargetOutput(screen->display, GL_COLOR_BUFFER_BIT);

            /* Find what the x and y change should be as to ensure the movement takes the user specified amount of time */
            compute_translation(ps, &dx, &dy);

            dx *= -1;
            dy *= -1;

            tx = dy;
            ty = dy;
            vx = 0;
            vy = 0;
            /* Make sure dx and dy are less than 1 and greater than -1 but move the viewports accordingly if they are greater or less than respectively */
            while (dx > 1)
            {
                  dx -= 1.0;
                  moveScreenViewport(screen, 1, 0, FALSE);
                  vx++;
            }

            while (dx < -1)
            {
                  dx += 1.0;
                  moveScreenViewport(screen, -1, 0, FALSE);
                  vx--;
            }

            while (dy > 1)
            {
                  dy -= 1.0;
                  moveScreenViewport(screen, 0, 1, FALSE);
                  vy++;
            }

            while (dy < -1)
            {
                  dy += 1.0;
                  moveScreenViewport(screen, 0, -1, FALSE);
                  vy--;
            }

#if 0
            glPushMatrix();

            if (dx > 0)
            {
                  glTranslatef(dx, dy, 0.0);

                  (*screen->paintTransformedScreen) (screen, sAttrib, mask);

                  glTranslatef(-1.0, 0.0, 0.0);

                  moveScreenViewport(screen, 1, 0, FALSE);

                  (*screen->paintTransformedScreen) (screen, sAttrib, mask);

                  moveScreenViewport(screen, -1, 0, FALSE);
            }
            else
            {
                  glTranslatef(dx, dy, 0.0);

                  (*screen->paintTransformedScreen) (screen, sAttrib, mask);

                  glTranslatef(1.0, 0.0, 0.0);

                  moveScreenViewport(screen, -1, 0, FALSE);

                  (*screen->paintTransformedScreen) (screen, sAttrib, mask);

                  moveScreenViewport(screen, 1, 0, FALSE);
            }

            glPopMatrix();
#endif

            glPushMatrix();
            ScreenPaintAttrib *sa = sAttrib;

            if (ps->preview)
            {
                  sa->zCamera = -2;
            }
            else
            {
                  sa->zCamera = ps->initZoom;
            }
            sAttrib = sa;
            /* Provide the effect of scrolling rather than snapping */
            glTranslatef(dx, -dy, 0.0);

            (*screen->paintTransformedScreen) (screen, sAttrib, region,
                                                               output, mask);
            /* Draw viewports a bit further apart if we are 'zoomed' */
            float s1 = 1.05;
            float s2 = -1.05;

            if (!ps->preview)
            {
                  s1 = 1;
                  s2 = -1;
            }
            /* FIXME: This is a horrible and highly unscalable way to do things. */
            if (dx > 0)
            {
                  glTranslatef(s2, 0.0, 0.0);
                  moveScreenViewport(screen, 1, 0, FALSE);
            }
            else
            {
                  glTranslatef(s1, 0.0, 0.0);
                  moveScreenViewport(screen, -1, 0, FALSE);
            }
            (*screen->paintTransformedScreen) (screen, sAttrib, region,
                                                               output, mask);
            if (dy > 0)
            {
                  glTranslatef(0.0, s1, 0.0);
                  moveScreenViewport(screen, 0, 1, FALSE);
            }
            else
            {
                  glTranslatef(0.0, s2, 0.0);
                  moveScreenViewport(screen, 0, -1, FALSE);
            }
            (*screen->paintTransformedScreen) (screen, sAttrib, region,
                                                               output, mask);
            if (dx > 0)
            {
                  glTranslatef(s1, 0.0, 0.0);
                  moveScreenViewport(screen, -1, 0, FALSE);
            }
            else
            {
                  glTranslatef(s2, 0.0, 0.0);
                  moveScreenViewport(screen, 1, 0, FALSE);
            }
            (*screen->paintTransformedScreen) (screen, sAttrib, region,
                                                               output, mask);
            if (dy > 0)
            {
                  glTranslatef(0.0, s2, 0.0);
                  moveScreenViewport(screen, 0, -1, FALSE);
            }
            else
            {
                  glTranslatef(0.0, s1, 0.0);
                  moveScreenViewport(screen, 0, 1, FALSE);
            }
            glTranslatef(-dx, -dy, 0.0);
            glPopMatrix();

            moveScreenViewport(screen, -vx, -vy, FALSE);
      }
      else
      {
            int i, j;

            for (i = -1; i < 2; i++)
            {
                  for (j = -1; j < 2; j++)
                  {
                        glTranslatef(i, j, 0);
                        moveScreenViewport(screen, -i, -j, FALSE);
                        (*screen->paintTransformedScreen) (screen,
                                                                           sAttrib,
                                                                           region, output, mask);
                        glTranslatef(-i, -j, 0);
                        moveScreenViewport(screen, i, j, FALSE);
                  }
            }
      }
      notfirst = TRUE;
      WRAP(ps, screen, paintTransformedScreen, planePaintTransformedScreen);
      glPopMatrix();

}

static void planeDonePaintScreen(CompScreen * s)
{
      PLANE_SCREEN(s);

      if (ps->timeout_handle)
            damageScreen(s);

      UNWRAP(ps, s, donePaintScreen);

      (*s->donePaintScreen) (s);

      WRAP(ps, s, donePaintScreen, planeDonePaintScreen);
}

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

      PLANE_SCREEN(s);

      if (ps->timeout_handle || ps->preview)
      {
            mask &= ~PAINT_SCREEN_REGION_MASK;
            mask |= PAINT_SCREEN_TRANSFORMED_MASK;
      }

      UNWRAP(ps, s, paintScreen);
      status = (*s->paintScreen) (s, sAttrib, region, output, mask);
      WRAP(ps, s, paintScreen, planePaintScreen);

      return status;
}

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

      PLANE_DISPLAY(d);

      switch (event->type)
      {
      case ClientMessage:
            if (event->xclient.message_type == d->winActiveAtom)
            {
                  CompWindow *w;

                  w = findWindowAtDisplay(d, event->xclient.window);
                  if (w)
                  {
                        int dx, dy;

                        s = w->screen;

                        /* window must be placed */
                        if (!w->placed)
                              break;

                        if (otherScreenGrabExist
                              (s, "plane", "switcher", "cube", "scale", 0))
                              break;

                        defaultViewportForWindow(w, &dx, &dy);
                        dx -= s->x;
                        dy -= s->y;

                        move_viewport(s, dx, dy);
                  }
            }
            else if (event->xclient.message_type == d->desktopViewportAtom)
            {
                  int dx, dy;

                  s = findScreenAtDisplay(d, event->xclient.window);
                  if (!s)
                        break;

                  if (otherScreenGrabExist
                        (s, "plane", "switcher", "cube", "scale", 0))
                        break;

                  dx = event->xclient.data.l[0] / s->width - s->x;
                  dy = event->xclient.data.l[1] / s->height - s->y;

                  if (!dx && !dy)
                        break;

                  move_viewport(s, dx, dy);
            }
            break;

      default:
            break;
      }

      UNWRAP(pd, d, handleEvent);
      (*d->handleEvent) (d, event);
      WRAP(pd, d, handleEvent, planeHandleEvent);
}

static void
planeWindowGrabNotify(CompWindow * w,
                                int x, int y, unsigned int state, unsigned int mask)
{
      PLANE_SCREEN(w->screen);

      UNWRAP(ps, w->screen, windowGrabNotify);
      (*w->screen->windowGrabNotify) (w, x, y, state, mask);
      WRAP(ps, w->screen, windowGrabNotify, planeWindowGrabNotify);
}

static void planeWindowUngrabNotify(CompWindow * w)
{
      PLANE_SCREEN(w->screen);

      UNWRAP(ps, w->screen, windowUngrabNotify);
      (*w->screen->windowUngrabNotify) (w);
      WRAP(ps, w->screen, windowUngrabNotify, planeWindowUngrabNotify);
}

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

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

      return status;
}

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

      PLANE_DISPLAY(display);

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

      switch (index)
      {
      case PLANE_DISPLAY_OPTION_LEFT:
      case PLANE_DISPLAY_OPTION_RIGHT:
      case PLANE_DISPLAY_OPTION_UP:
      case PLANE_DISPLAY_OPTION_DOWN:
      case PLANE_DISPLAY_OPTION_PREVIEW:
      case PLANE_DISPLAY_OPTION_TO_1:
      case PLANE_DISPLAY_OPTION_TO_2:
      case PLANE_DISPLAY_OPTION_TO_3:
      case PLANE_DISPLAY_OPTION_TO_4:
      case PLANE_DISPLAY_OPTION_TO_5:
      case PLANE_DISPLAY_OPTION_TO_6:
      case PLANE_DISPLAY_OPTION_TO_7:
      case PLANE_DISPLAY_OPTION_TO_8:
      case PLANE_DISPLAY_OPTION_TO_9:
      case PLANE_DISPLAY_OPTION_TO_10:
      case PLANE_DISPLAY_OPTION_TO_11:
      case PLANE_DISPLAY_OPTION_TO_12:
            if (setDisplayAction(display, o, value))
                  return TRUE;
            break;
      default:
            break;
      }

      return FALSE;
}

static CompScreen *get_screen(CompDisplay * d, CompOption * option,
                                            int n_options)
{
      XID root_window = getIntOptionNamed(option, n_options, "root", 0);

      return findScreenAtDisplay(d, root_window);
}

static Bool
planeLeft(CompDisplay * d,
              CompAction * action,
              CompActionState state, CompOption * option, int n_options)
{
      CompScreen *screen = get_screen(d, option, n_options);

      move_viewport(screen, -1, 0);
      return FALSE;
}

static Bool
planeRight(CompDisplay * d,
               CompAction * action,
               CompActionState state, CompOption * option, int n_options)
{
      CompScreen *screen = get_screen(d, option, n_options);

      move_viewport(screen, 1, 0);
      return FALSE;
}

static Bool
planeUp(CompDisplay * d,
            CompAction * action,
            CompActionState state, CompOption * option, int n_options)
{
      CompScreen *screen = get_screen(d, option, n_options);

      move_viewport(screen, 0, -1);
      return FALSE;
}

static Bool
planeDown(CompDisplay * d,
              CompAction * action,
              CompActionState state, CompOption * option, int n_options)
{
      CompScreen *screen = get_screen(d, option, n_options);

      move_viewport(screen, 0, 1);
      return FALSE;
}

static Bool
planePreview(CompDisplay * d, CompAction * action, CompActionState state,
                   CompOption * option, int n_options)
{
      static int xView;
      static int yView;

      CompScreen *screen = get_screen(d, option, n_options);

      PLANE_SCREEN(screen);
      if (!ps->preview)
      {
            xView = screen->x / screen->width;
            yView = screen->y / screen->height;
      }
      ps->preview = !ps->preview;
      /*if (!ps->preview){
         moveScreenViewport(screen,xView,yView,TRUE);
         } */
      damageScreen(screen);

      return FALSE;
}

static Bool
planeTo(CompDisplay * d,
            CompAction * action,
            CompActionState state, CompOption * option, int n_options)
{
      int i, new_x, new_y, cur_x, cur_y;
      CompScreen *screen = get_screen(d, option, n_options);

      PLANE_DISPLAY(d);

      new_x = new_y = -1;
      for (i = PLANE_DISPLAY_OPTION_TO_1; i <= PLANE_DISPLAY_OPTION_TO_12; ++i)
      {
            if (action == &pd->opt[i].value.action)
            {
                  int viewport_no = i - PLANE_DISPLAY_OPTION_TO_1;

                  new_x = viewport_no % screen->hsize;
                  new_y = viewport_no / screen->hsize;

                  break;
            }
      }

      if (new_x == -1 || new_y == -1)
            return FALSE;

      cur_x = screen->x;
      cur_y = screen->y;

      move_viewport(screen, new_x - cur_x, new_y - cur_y);

      return FALSE;
}

static void planeDisplayInitOptions(PlaneDisplay * pd)
{
      CompOption *o;
      char *str;

      o = &pd->opt[PLANE_DISPLAY_OPTION_LEFT];
      o->advanced = False;
      o->name = "plane_left";
      o->group = N_("Bindings");
      o->subGroup = N_("Navigation - Left");
      o->displayHints = "";
      o->shortDesc = N_("Plane Left");
      o->longDesc = N_("Plane Left.");
      o->type = CompOptionTypeAction;
      o->value.action.initiate = planeLeft;
      o->value.action.terminate = 0;
      o->value.action.bell = FALSE;
      o->value.action.edgeMask = 0;
      o->value.action.state = CompActionStateInitEdge;
      o->value.action.state |= CompActionStateInitEdgeDnd;
      o->value.action.state |= CompActionStateInitKey;
      o->value.action.state |= CompActionStateInitButton;
      o->value.action.type = CompBindingTypeKey;
      o->value.action.key.modifiers = PLANE_LEFT_MODIFIERS_DEFAULT;
      o->value.action.key.keysym = XStringToKeysym(PLANE_LEFT_KEY_DEFAULT);

      o = &pd->opt[PLANE_DISPLAY_OPTION_RIGHT];
      o->advanced = False;
      o->name = "plane_right";
      o->group = N_("Bindings");
      o->subGroup = N_("Navigation - Right");
      o->displayHints = "";
      o->shortDesc = N_("Plane Right");
      o->longDesc = N_("Plane Right.");
      o->type = CompOptionTypeAction;
      o->value.action.initiate = planeRight;
      o->value.action.terminate = 0;
      o->value.action.bell = FALSE;
      o->value.action.edgeMask = 0;
      o->value.action.state = CompActionStateInitEdge;
      o->value.action.state |= CompActionStateInitEdgeDnd;
      o->value.action.state |= CompActionStateInitKey;
      o->value.action.state |= CompActionStateInitButton;
      o->value.action.type = CompBindingTypeKey;
      o->value.action.key.modifiers = PLANE_RIGHT_MODIFIERS_DEFAULT;
      o->value.action.key.keysym = XStringToKeysym(PLANE_RIGHT_KEY_DEFAULT);

      o = &pd->opt[PLANE_DISPLAY_OPTION_DOWN];
      o->advanced = False;
      o->name = "plane_down";
      o->group = N_("Bindings");
      o->subGroup = N_("Navigation - Down");
      o->displayHints = "";
      o->shortDesc = N_("Plane Down");
      o->longDesc = N_("Plane Down.");
      o->type = CompOptionTypeAction;
      o->value.action.initiate = planeDown;
      o->value.action.terminate = 0;
      o->value.action.bell = FALSE;
      o->value.action.edgeMask = 0;
      o->value.action.state = CompActionStateInitEdge;
      o->value.action.state |= CompActionStateInitEdgeDnd;
      o->value.action.state |= CompActionStateInitKey;
      o->value.action.state |= CompActionStateInitButton;
      o->value.action.type = CompBindingTypeKey;
      o->value.action.key.modifiers = PLANE_DOWN_MODIFIERS_DEFAULT;
      o->value.action.key.keysym = XStringToKeysym(PLANE_DOWN_KEY_DEFAULT);

      o = &pd->opt[PLANE_DISPLAY_OPTION_PREVIEW];
      o->advanced = False;
      o->name = "plane_preview";
      o->group = N_("Bindings");
      o->subGroup = N_("Plane preview");
      o->displayHints = "";
      o->shortDesc = N_("Toggle Plane Preview");
      o->longDesc = N_("Toggle Plane Preview mode.");
      o->type = CompOptionTypeAction;
      o->value.action.initiate = planePreview;
      o->value.action.terminate = 0;
      o->value.action.bell = FALSE;
      o->value.action.edgeMask = 0;
      o->value.action.state = CompActionStateInitEdge;
      o->value.action.state |= CompActionStateInitEdgeDnd;
      o->value.action.state |= CompActionStateInitKey;
      o->value.action.state |= CompActionStateInitButton;
      o->value.action.type = CompBindingTypeKey;
      o->value.action.key.modifiers = PLANE_PREVIEW_MODIFIERS_DEFAULT;
      o->value.action.key.keysym = XStringToKeysym(PLANE_PREVIEW_KEY_DEFAULT);

      o = &pd->opt[PLANE_DISPLAY_OPTION_UP];
      o->advanced = False;
      o->name = "plane_up";
      o->group = N_("Bindings");
      o->subGroup = N_("Navigation - Up");
      o->displayHints = "";
      o->shortDesc = N_("Plane Up");
      o->longDesc = N_("Plane Up.");
      o->type = CompOptionTypeAction;
      o->value.action.initiate = planeUp;
      o->value.action.terminate = 0;
      o->value.action.bell = FALSE;
      o->value.action.edgeMask = 0;
      o->value.action.state = CompActionStateInitEdge;
      o->value.action.state |= CompActionStateInitEdgeDnd;
      o->value.action.state |= CompActionStateInitKey;
      o->value.action.state |= CompActionStateInitButton;
      o->value.action.type = CompBindingTypeKey;
      o->value.action.key.modifiers = PLANE_UP_MODIFIERS_DEFAULT;
      o->value.action.key.keysym = XStringToKeysym(PLANE_UP_KEY_DEFAULT);

#define PLANE_TO_SHORT        N_("Plane To Face %d")
#define PLANE_TO_LONG         N_("Plane to face %d")
#define PLANE_TO_WINDOW_SHORT N_("Plane To Face %d with Window")
#define PLANE_TO_WINDOW_LONG  N_("Plane to face %d and bring active " \
        "window along")

#define PLANE_TO_OPTION(n)                                   \
    o = &pd->opt[PLANE_DISPLAY_OPTION_TO_ ## n];                   \
    o->advanced=False;\
o->name                   = "plane_to_" #n;                  \
    asprintf (&str, PLANE_TO_SHORT, n);                      \
    o->group=N_("Bindings");\
o->subGroup=N_("Face shortcuts");\
o->displayHints="";\
o->shortDesc              = str;                       \
    asprintf (&str, PLANE_TO_LONG, n);                             \
    o->longDesc                 = str;                       \
    o->type               = CompOptionTypeAction;            \
    o->value.action.initiate    = planeTo;                         \
    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        = CompBindingTypeNone;

      PLANE_TO_OPTION(1);
      PLANE_TO_OPTION(2);
      PLANE_TO_OPTION(3);
      PLANE_TO_OPTION(4);
      PLANE_TO_OPTION(5);
      PLANE_TO_OPTION(6);
      PLANE_TO_OPTION(7);
      PLANE_TO_OPTION(8);
      PLANE_TO_OPTION(9);
      PLANE_TO_OPTION(10);
      PLANE_TO_OPTION(11);
      PLANE_TO_OPTION(12);
}

static CompOption *planeGetDisplayOptions(CompDisplay * display, int *count)
{
      if (display)
      {
            PLANE_DISPLAY(display);

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

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


static Bool planeInitDisplay(CompPlugin * p, CompDisplay * d)
{
      PlaneDisplay *pd;

      pd = malloc(sizeof(PlaneDisplay));
      if (!pd)
            return FALSE;

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

      planeDisplayInitOptions(pd);

      WRAP(pd, d, handleEvent, planeHandleEvent);

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

      return TRUE;
}

static void planeFiniDisplay(CompPlugin * p, CompDisplay * d)
{
      PLANE_DISPLAY(d);

      freeScreenPrivateIndex(d, pd->screenPrivateIndex);

      UNWRAP(pd, d, handleEvent);

      free(pd);
}

static Bool planeInitScreen(CompPlugin * p, CompScreen * s)
{
      PlaneScreen *ps;

      PLANE_DISPLAY(s->display);

      ps = malloc(sizeof(PlaneScreen));
      if (!ps)
            return FALSE;
      ps->preview = 0;
      ps->timeout_handle = 0;

      planeScreenInitOptions(ps);

      addScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_LEFT].value.action);
      addScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_RIGHT].value.action);
      addScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_DOWN].value.action);
      addScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_UP].value.action);
      addScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_PREVIEW].value.action);
      addScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_1].value.action);
      addScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_2].value.action);
      addScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_3].value.action);
      addScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_4].value.action);
      addScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_5].value.action);
      addScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_6].value.action);
      addScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_7].value.action);
      addScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_8].value.action);
      addScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_9].value.action);
      addScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_10].value.action);
      addScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_11].value.action);
      addScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_12].value.action);

      WRAP(ps, s, paintTransformedScreen, planePaintTransformedScreen);
      WRAP(ps, s, preparePaintScreen, planePreparePaintScreen);
      WRAP(ps, s, donePaintScreen, planeDonePaintScreen);
      WRAP(ps, s, paintScreen, planePaintScreen);
      WRAP(ps, s, setScreenOptionForPlugin, planeSetScreenOptionForPlugin);
      WRAP(ps, s, windowGrabNotify, planeWindowGrabNotify);
      WRAP(ps, s, windowUngrabNotify, planeWindowUngrabNotify);

      s->privates[pd->screenPrivateIndex].ptr = ps;

      return TRUE;
}

static void planeFiniScreen(CompPlugin * p, CompScreen * s)
{
      PLANE_SCREEN(s);
      PLANE_DISPLAY(s->display);

      UNWRAP(ps, s, paintTransformedScreen);
      UNWRAP(ps, s, preparePaintScreen);
      UNWRAP(ps, s, donePaintScreen);
      UNWRAP(ps, s, paintScreen);
      UNWRAP(ps, s, setScreenOptionForPlugin);
      UNWRAP(ps, s, windowGrabNotify);
      UNWRAP(ps, s, windowUngrabNotify);

      removeScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_LEFT].value.action);
      removeScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_RIGHT].value.action);
      removeScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_DOWN].value.action);
      removeScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_UP].value.action);
      removeScreenAction(s,
                                 &pd->opt[PLANE_DISPLAY_OPTION_PREVIEW].value.action);
      removeScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_1].value.action);
      removeScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_2].value.action);
      removeScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_3].value.action);
      removeScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_4].value.action);
      removeScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_5].value.action);
      removeScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_6].value.action);
      removeScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_7].value.action);
      removeScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_8].value.action);
      removeScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_9].value.action);
      removeScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_10].value.action);
      removeScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_11].value.action);
      removeScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_12].value.action);

      free(ps);
}

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

      return TRUE;
}

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

CompPluginFeature planeFeatures[] = {
      {"largedesktop"}
};

CompPluginVTable planeVTable = {
      "plane",
      N_("Desktop Plane"),
      N_("Place windows on a plane"),
      planeInit,                          /* planeInit, */
      planeFini,                          /* planeFini, */
      planeInitDisplay,
      planeFiniDisplay,
      planeInitScreen,
      planeFiniScreen,
      0,                                        /* InitWindow */
      0,                                        /* FiniWindow */
      planeGetDisplayOptions,
      planeSetDisplayOption,
      planeGetScreenOptions,
      planeSetScreenOption,
      0,
      0,
      planeFeatures,
      sizeof(planeFeatures) / sizeof(planeFeatures[0]),
      BERYL_ABI_INFO,
      "beryl-plugins-unsupported",
      "desktop",
      0,
      0,
      False,
};

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

Generated by  Doxygen 1.6.0   Back to index