Logo Search packages:      
Sourcecode: beryl-core version File versions

display.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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 * Author: David Reveman <davidr@novell.com>
 */

#ifdef HAVE_CONFIG_H
#  include "../config.h"
#endif

#define _GNU_SOURCE                       /* for asprintf */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/poll.h>
#include <unistd.h>

#define XK_MISCELLANY
#include <X11/keysymdef.h>

#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/extensions/Xcomposite.h>
#include <X11/extensions/Xrandr.h>
#include <X11/extensions/shape.h>

#include <beryl.h>
#include <beryl-private.h>

#include <fsp.h>
#include <math.h>
#define WMNAME "beryl"

Bool disable_vsync = FALSE;

void
compDisplayInitOptions(CompDisplay * display, char **plugin, int nPlugin);

extern Bool IPCS_lock;

static unsigned int virtualModMask[] = {
      CompAltMask, CompMetaMask, CompSuperMask, CompHyperMask,
      CompModeSwitchMask, CompNumLockMask, CompScrollLockMask
};

typedef struct _CompTimeout
{
      struct _CompTimeout *next;
      int time;
      int left;
      CallBackProc callBack;
      void *closure;
      CompTimeoutHandle handle;
} CompTimeout;

static CompTimeout *timeouts = 0;
static struct timeval lastTimeout;
static CompTimeoutHandle lastTimeoutHandle = 1;

typedef struct _CompWatchFd
{
      struct _CompWatchFd *next;
      int fd;
      CallBackProc callBack;
      void *closure;
      CompWatchFdHandle handle;
} CompWatchFd;

static CompWatchFd *watchFds = 0;
static CompWatchFdHandle lastWatchFdHandle = 1;
static struct pollfd *watchPollFds = 0;
static int nWatchFds = 0;

static CompScreen *targetScreen = NULL;
static int targetOutput = 0;

static Bool inHandleEvent = FALSE;

static Bool shutDown = FALSE;

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

CompDisplay *compDisplays = 0;

static CompDisplay compDisplay;

static char *displayPrivateIndices = 0;
static int displayPrivateLen = 0;

static struct _multiPerspective
{
      GLfloat x;
      GLfloat y;
      GLfloat a;
      GLfloat b;
      GLfloat c;
      GLfloat d;
} multiPerspective[64];

static int reallocDisplayPrivate(int size, void *closure)
{
      CompDisplay *d = compDisplays;
      void *privates;

      if (d)
      {
            privates = realloc(d->privates, size * sizeof(CompPrivate));
            if (!privates)
                  return FALSE;

            d->privates = (CompPrivate *) privates;
      }

      return TRUE;
}

int allocateDisplayPrivateIndex(void)
{
      return allocatePrivateIndex(&displayPrivateLen,
                                                &displayPrivateIndices,
                                                reallocDisplayPrivate, 0);
}

void freeDisplayPrivateIndex(int index)
{
      freePrivateIndex(displayPrivateLen, displayPrivateIndices, index);
}

static Bool
closeWin(CompDisplay * d,
             CompAction * action,
             CompActionState state, CompOption * option, int nOption)
{
      CompWindow *w;
      Window xid;
      unsigned int time;

      xid = getIntOptionNamed(option, nOption, "window", 0);
      time = getIntOptionNamed(option, nOption, "time", CurrentTime);

      w = findTopLevelWindowAtDisplay(d, xid);
      if (w)
            closeWindow(w, time);

      return TRUE;
}

static Bool
mainMenu(CompDisplay * d,
             CompAction * action,
             CompActionState state, CompOption * option, int nOption)
{
      CompScreen *s;
      Window xid;
      unsigned int time;

      xid = getIntOptionNamed(option, nOption, "root", 0);
      time = getIntOptionNamed(option, nOption, "time", CurrentTime);

      s = findScreenAtDisplay(d, xid);
      if (s && !s->maxGrab)
            toolkitAction(s, s->display->toolkitActionMainMenuAtom,
                                time, s->root, 0, 0, 0);

      return TRUE;
}

static Bool
runDialog(CompDisplay * d,
              CompAction * action,
              CompActionState state, CompOption * option, int nOption)
{
      CompScreen *s;
      Window xid;
      unsigned int time;

      xid = getIntOptionNamed(option, nOption, "root", 0);
      time = getIntOptionNamed(option, nOption, "time", CurrentTime);

      s = findScreenAtDisplay(d, xid);
      if (s && !s->maxGrab)
            toolkitAction(s, s->display->toolkitActionRunDialogAtom,
                                time, s->root, 0, 0, 0);

      return TRUE;
}

static Bool
unmaximize(CompDisplay * d,
               CompAction * action,
               CompActionState state, CompOption * option, int nOption)
{
      CompWindow *w;
      Window xid;

      xid = getIntOptionNamed(option, nOption, "window", 0);

      w = findTopLevelWindowAtDisplay(d, xid);
      if (w)
            maximizeWindow(w, 0);

      return TRUE;
}

static Bool
minimize(CompDisplay * d,
             CompAction * action,
             CompActionState state, CompOption * option, int nOption)
{
      CompWindow *w;
      Window xid;

      xid = getIntOptionNamed(option, nOption, "window", 0);

      w = findTopLevelWindowAtDisplay(d, xid);
      if (w)
            minimizeWindow(w);

      return TRUE;
}

static Bool
maximize(CompDisplay * d,
             CompAction * action,
             CompActionState state, CompOption * option, int nOption)
{
      CompWindow *w;
      Window xid;

      xid = getIntOptionNamed(option, nOption, "window", 0);

      w = findTopLevelWindowAtDisplay(d, xid);
      if (w)
            maximizeWindow(w, MAXIMIZE_STATE);

      return TRUE;
}

static Bool
maximizeHorizontally(CompDisplay * d,
                               CompAction * action,
                               CompActionState state, CompOption * option, int nOption)
{
      CompWindow *w;
      Window xid;

      xid = getIntOptionNamed(option, nOption, "window", 0);

      w = findTopLevelWindowAtDisplay(d, xid);
      if (w)
            maximizeWindow(w, w->state | CompWindowStateMaximizedHorzMask);

      return TRUE;
}

static Bool
maximizeVertically(CompDisplay * d,
                           CompAction * action,
                           CompActionState state, CompOption * option, int nOption)
{
      CompWindow *w;
      Window xid;

      xid = getIntOptionNamed(option, nOption, "window", 0);

      w = findTopLevelWindowAtDisplay(d, xid);
      if (w)
            maximizeWindow(w, w->state | CompWindowStateMaximizedVertMask);

      return TRUE;
}

static Bool
showDesktop(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)
      {
            if (s->showingDesktopMask == 0)
                  enterShowDesktopMode(s);
            else
                  leaveShowDesktopMode(s, NULL);
      }

      return TRUE;
}

static Bool
toggleSlowAnimations(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)
            s->slowAnimations = !s->slowAnimations;

      return TRUE;
}

static Bool
lower(CompDisplay * d,
        CompAction * action,
        CompActionState state, CompOption * option, int nOption)
{
      CompWindow *w;
      Window xid;

      xid = getIntOptionNamed(option, nOption, "window", 0);

      w = findTopLevelWindowAtDisplay(d, xid);
      if (w)
            lowerWindow(w);

      return TRUE;
}

static Bool
raise(CompDisplay * d,
        CompAction * action,
        CompActionState state, CompOption * option, int nOption)
{
      CompWindow *w;
      Window xid;

      xid = getIntOptionNamed(option, nOption, "window", 0);

      w = findTopLevelWindowAtDisplay(d, xid);
      if (w)
            raiseWindow(w);

      return TRUE;
}

static Bool
activate(CompDisplay * d,
           CompAction * action,
           CompActionState state, CompOption * option, int nOption)
{
      CompWindow *w;
      Window xid;

      xid = getIntOptionNamed(option, nOption, "window", 0);

      w = findWindowAtDisplay(d, xid);
      if (w)
            sendWindowActivationRequest(w->screen, w->id);

      return TRUE;
}


static void changeWindowOpacity(CompWindow * w, int direction)
{
      int step, opacity;

      if (w->attrib.override_redirect)
            return;

      if (w->type & CompWindowTypeDesktopMask)
            return;

      step = (OPAQUE * w->screen->opacityStep) / 100;

      opacity = w->paint.opacity + step * direction;
      if (opacity > OPAQUE)
      {
            opacity = OPAQUE;
      }
      else if (opacity < step)
      {
            opacity = step;
      }

      if (w->paint.opacity != opacity)
      {
            w->paint.opacity = opacity;

            setWindowProp32(w->screen->display, w->id,
                                    w->screen->display->winOpacityAtom, w->paint.opacity);
            addWindowDamage(w);
            w->defaultPaintLock.opacity = PL_SUPER;
      }
}

static void changeWindowSaturation(CompWindow * w, int direction)
{
      int step, saturation;

      if (w->attrib.override_redirect)
            return;

      if (w->type & CompWindowTypeDesktopMask)
            return;

      step = (COLOR * w->screen->saturationStep / 100);

      saturation = w->paint.saturation + step * direction;
      if (saturation > COLOR)
      {
            saturation = COLOR;
      }
      else if (saturation < 0)
      {
            saturation = 0;
      }

      if (w->paint.saturation != saturation)
      {
            w->paint.saturation = saturation;

            setWindowProp32(w->screen->display, w->id,
                                    w->screen->display->winSaturationAtom,
                                    w->paint.saturation);
            addWindowDamage(w);
            w->defaultPaintLock.saturation = PL_SUPER;
      }
}

static void changeWindowBrightness(CompWindow * w, int direction)
{
      int step, brightness;

      if (w->attrib.override_redirect)
            return;

      if (w->type & CompWindowTypeDesktopMask)
            return;

      step = (BRIGHT * w->screen->brightnessStep / 100);

      brightness = w->paint.brightness + step * direction;
      if (brightness > BRIGHT)
      {
            brightness = BRIGHT;
      }
      else if (brightness < 0)
      {
            brightness = 0;
      }

      if (w->paint.brightness != brightness)
      {
            w->paint.brightness = brightness;

            setWindowProp32(w->screen->display, w->id,
                                    w->screen->display->winBrightnessAtom,
                                    w->paint.brightness);
            addWindowDamage(w);
            w->defaultPaintLock.brightness = PL_SUPER;
      }
}

static Bool
increaseOpacity(CompDisplay * d,
                        CompAction * action,
                        CompActionState state, CompOption * option, int nOption)
{
      CompWindow *w;
      Window xid;

      xid = getIntOptionNamed(option, nOption, "window", 0);

      w = findTopLevelWindowAtDisplay(d, xid);
      if (w)
            changeWindowOpacity(w, 1);

      return TRUE;
}

static Bool
decreaseOpacity(CompDisplay * d,
                        CompAction * action,
                        CompActionState state, CompOption * option, int nOption)
{
      CompWindow *w;
      Window xid;

      xid = getIntOptionNamed(option, nOption, "window", 0);

      w = findTopLevelWindowAtDisplay(d, xid);
      if (w)
            changeWindowOpacity(w, -1);

      return TRUE;
}

static Bool
increaseSaturation(CompDisplay * d, CompAction * action,
                           CompActionState state, CompOption * option, int nOption)
{
      CompWindow *w;
      Window xid;

      xid = getIntOptionNamed(option, nOption, "window", 0);

      w = findTopLevelWindowAtDisplay(d, xid);
      if (w)
            changeWindowSaturation(w, 1);

      return TRUE;
}

static Bool
decreaseSaturation(CompDisplay * d, CompAction * action,
                           CompActionState state, CompOption * option, int nOption)
{
      CompWindow *w;
      Window xid;

      xid = getIntOptionNamed(option, nOption, "window", 0);

      w = findTopLevelWindowAtDisplay(d, xid);
      if (w)
            changeWindowSaturation(w, -1);

      return TRUE;
}

static Bool
increaseBrightness(CompDisplay * d, CompAction * action,
                           CompActionState state, CompOption * option, int nOption)
{
      CompWindow *w;
      Window xid;

      xid = getIntOptionNamed(option, nOption, "window", 0);

      w = findTopLevelWindowAtDisplay(d, xid);
      if (w)
            changeWindowBrightness(w, 1);

      return TRUE;
}

static Bool
decreaseBrightness(CompDisplay * d, CompAction * action,
                           CompActionState state, CompOption * option, int nOption)
{
      CompWindow *w;
      Window xid;

      xid = getIntOptionNamed(option, nOption, "window", 0);

      w = findTopLevelWindowAtDisplay(d, xid);
      if (w)
            changeWindowBrightness(w, -1);

      return TRUE;
}

static Bool
runCommandDispatch(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)
      {
            int index = -1;
            int i = COMP_DISPLAY_OPTION_RUN_COMMAND0;

            while (i <= COMP_DISPLAY_OPTION_RUN_COMMAND11)
            {
                  if (action == &d->opt[i].value.action)
                  {
                        index = i - COMP_DISPLAY_OPTION_RUN_COMMAND0 +
                                    COMP_DISPLAY_OPTION_COMMAND0;
                        break;
                  }

                  i++;
            }

            if (index > 0)
                  runCommand(s, d->opt[index].value.s);
      }

      return TRUE;
}

static Bool
runCommandScreenshot(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)
            runCommand(s, d->opt[COMP_DISPLAY_OPTION_SCREENSHOT].value.s);

      return TRUE;
}

static Bool
runCommandWindowScreenshot(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)
            runCommand(s, d->opt[COMP_DISPLAY_OPTION_WINDOW_SCREENSHOT].value.s);

      return TRUE;
}

static Bool
windowMenu(CompDisplay * d,
               CompAction * action,
               CompActionState state, CompOption * option, int nOption)
{
      CompWindow *w;
      Window xid;

      xid = getIntOptionNamed(option, nOption, "window", 0);

      w = findTopLevelWindowAtDisplay(d, xid);
      if (w)
      {
            int x, y, button;
            Time time;

            time = getIntOptionNamed(option, nOption, "time", CurrentTime);
            button = getIntOptionNamed(option, nOption, "button", 0);
            x = getIntOptionNamed(option, nOption, "x", w->attrib.x);
            y = getIntOptionNamed(option, nOption, "y", w->attrib.y);

            toolkitAction(w->screen,
                                w->screen->display->
                                toolkitActionWindowMenuAtom, time, w->id, button, x, y);
      }

      return TRUE;
}

static Bool
toggleMaximized(CompDisplay * d,
                        CompAction * action,
                        CompActionState state, CompOption * option, int nOption)
{
      CompWindow *w;
      Window xid;

      xid = getIntOptionNamed(option, nOption, "window", 0);

      w = findTopLevelWindowAtDisplay(d, xid);
      if (w)
      {
            if ((w->state & MAXIMIZE_STATE) == MAXIMIZE_STATE)
                  maximizeWindow(w, 0);
            else
                  maximizeWindow(w, MAXIMIZE_STATE);
      }

      return TRUE;
}

static Bool
toggleFullscreen(CompDisplay * d,
                         CompAction * action,
                         CompActionState state, CompOption * option, int nOption)
{
      CompWindow *w;
      Window xid;

      xid = getIntOptionNamed(option, nOption, "window", 0);

      w = findTopLevelWindowAtDisplay(d, xid);
      if (w)
            fullscreenWindow(w, w->state ^ CompWindowStateFullscreenMask);

      return TRUE;
}

static Bool
toggleMaximizedHorizontally(CompDisplay * d,
                                          CompAction * action,
                                          CompActionState state,
                                          CompOption * option, int nOption)
{
      CompWindow *w;
      Window xid;

      xid = getIntOptionNamed(option, nOption, "window", 0);

      w = findTopLevelWindowAtDisplay(d, xid);
      if (w)
            maximizeWindow(w, w->state ^ CompWindowStateMaximizedHorzMask);

      return TRUE;
}

static Bool
toggleMaximizedVertically(CompDisplay * d,
                                      CompAction * action,
                                      CompActionState state,
                                      CompOption * option, int nOption)
{
      CompWindow *w;
      Window xid;

      xid = getIntOptionNamed(option, nOption, "window", 0);

      w = findTopLevelWindowAtDisplay(d, xid);
      if (w)
            maximizeWindow(w, w->state ^ CompWindowStateMaximizedVertMask);

      return TRUE;
}

static Bool
shade(CompDisplay * d,
        CompAction * action,
        CompActionState state, CompOption * option, int nOption)
{
      CompWindow *w;
      Window xid;

      xid = getIntOptionNamed(option, nOption, "window", 0);

      w = findTopLevelWindowAtDisplay(d, xid);
      if (w && (w->actions & CompWindowActionShadeMask))
      {
            w->state ^= CompWindowStateShadedMask;
            updateWindowAttributes(w, FALSE);
      }

      return TRUE;
}
static void setAudibleBell(CompDisplay * display, Bool audible)
{
      if (display->xkbExtension)
            XkbChangeEnabledControls(display->display,
                                                 XkbUseCoreKbd,
                                                 XkbAudibleBellMask,
                                                 audible ? XkbAudibleBellMask : 0);
}

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

      o = compFindOption(display->opt, NUM_OPTIONS(display), name, &index);
      if (!o)
            return FALSE;
      beryl_settings_context_comp_set_option_value(display->context,NULL,name,FALSE,value);
      beryl_settings_context_write(display->context);
      switch (index)
      {
      case COMP_DISPLAY_OPTION_FOCUS_STEALING_LEVEL:
            if (compSetStringOption(o, value))
            {
                  int i;

                  for (i = 0; i < FSP_COUNT; i++)
                  {
                        if (!strcasecmp(o->value.s, fspTypes[i]))
                        {
                              display->focusStealingLevel = i;
                              break;
                        }
                  }
                  return TRUE;
            }
            break;
#if 0
      case COMP_DISPLAY_OPTION_ACTIVE_PLUGINS:
            if (compSetOptionList(o, value))
            {
                  display->dirtyPluginList = TRUE;
                  return TRUE;
            }
            break;
#endif
      case COMP_DISPLAY_OPTION_TEXTURE_FILTER:
            if (compSetStringOption(o, value))
            {
                  CompScreen *s;

                  for (s = display->screens; s; s = s->next)
                        damageScreen(s);

                  if (strcmp(o->value.s, "Fast") == 0)
                        display->textureFilter = GL_NEAREST;
                  else
                        display->textureFilter = GL_LINEAR;

                  return TRUE;
            }
            break;
      case COMP_DISPLAY_OPTION_CLICK_TO_FOCUS:
      case COMP_DISPLAY_OPTION_AUTORAISE:
      case COMP_DISPLAY_OPTION_RAISE_ON_CLICK:
      case COMP_DISPLAY_OPTION_HIDE_SKIP_TASKBAR_WINDOWS:
      case COMP_DISPLAY_OPTION_IGNORE_HINTS_WHEN_MAXIMIZED:
      case COMP_DISPLAY_OPTION_GENERATE_THUMBNAILS:
      case COMP_DISPLAY_OPTION_THUMBNAIL_SMOOTH:
      case COMP_DISPLAY_OPTION_MAP_ON_SHUTDOWN:
      case COMP_DISPLAY_OPTION_BIG_VIEWPORT_MANAGER:
            if (compSetBoolOption(o, value))
                  return TRUE;
            break;
      case COMP_DISPLAY_OPTION_AUTORAISE_DELAY:
      case COMP_DISPLAY_OPTION_EDGE_TRIGGERING_DELAY:
      case COMP_DISPLAY_OPTION_THUMBNAIL_SIZE:
            if (compSetIntOption(o, value))
                  return TRUE;
            break;
      case COMP_DISPLAY_OPTION_COMMAND0:
      case COMP_DISPLAY_OPTION_COMMAND1:
      case COMP_DISPLAY_OPTION_COMMAND2:
      case COMP_DISPLAY_OPTION_COMMAND3:
      case COMP_DISPLAY_OPTION_COMMAND4:
      case COMP_DISPLAY_OPTION_COMMAND5:
      case COMP_DISPLAY_OPTION_COMMAND6:
      case COMP_DISPLAY_OPTION_COMMAND7:
      case COMP_DISPLAY_OPTION_COMMAND8:
      case COMP_DISPLAY_OPTION_COMMAND9:
      case COMP_DISPLAY_OPTION_COMMAND10:
      case COMP_DISPLAY_OPTION_COMMAND11:
      case COMP_DISPLAY_OPTION_SCREENSHOT:
      case COMP_DISPLAY_OPTION_WINDOW_SCREENSHOT:
            if (compSetStringOption(o, value))
                  return TRUE;
            break;
      case COMP_DISPLAY_OPTION_CLOSE_WINDOW:
      case COMP_DISPLAY_OPTION_MAIN_MENU:
      case COMP_DISPLAY_OPTION_RUN_DIALOG:
      case COMP_DISPLAY_OPTION_MINIMIZE_WINDOW:
      case COMP_DISPLAY_OPTION_MAXIMIZE_WINDOW:
      case COMP_DISPLAY_OPTION_MAXIMIZE_WINDOW_HORZ:
      case COMP_DISPLAY_OPTION_MAXIMIZE_WINDOW_VERT:
      case COMP_DISPLAY_OPTION_UNMAXIMIZE_WINDOW:
      case COMP_DISPLAY_OPTION_SHOW_DESKTOP:
      case COMP_DISPLAY_OPTION_RUN_COMMAND0:
      case COMP_DISPLAY_OPTION_RUN_COMMAND1:
      case COMP_DISPLAY_OPTION_RUN_COMMAND2:
      case COMP_DISPLAY_OPTION_RUN_COMMAND3:
      case COMP_DISPLAY_OPTION_RUN_COMMAND4:
      case COMP_DISPLAY_OPTION_RUN_COMMAND5:
      case COMP_DISPLAY_OPTION_RUN_COMMAND6:
      case COMP_DISPLAY_OPTION_RUN_COMMAND7:
      case COMP_DISPLAY_OPTION_RUN_COMMAND8:
      case COMP_DISPLAY_OPTION_RUN_COMMAND9:
      case COMP_DISPLAY_OPTION_RUN_COMMAND10:
      case COMP_DISPLAY_OPTION_RUN_COMMAND11:
      case COMP_DISPLAY_OPTION_SLOW_ANIMATIONS:
      case COMP_DISPLAY_OPTION_LOWER_WINDOW:
      case COMP_DISPLAY_OPTION_OPACITY_INCREASE:
      case COMP_DISPLAY_OPTION_OPACITY_DECREASE:
      case COMP_DISPLAY_OPTION_SATURATION_INCREASE:
      case COMP_DISPLAY_OPTION_SATURATION_DECREASE:
      case COMP_DISPLAY_OPTION_BRIGHTNESS_INCREASE:
      case COMP_DISPLAY_OPTION_BRIGHTNESS_DECREASE:
      case COMP_DISPLAY_OPTION_RUN_SCREENSHOT:
      case COMP_DISPLAY_OPTION_RUN_WINDOW_SCREENSHOT:
      case COMP_DISPLAY_OPTION_WINDOW_MENU:
      case COMP_DISPLAY_OPTION_TOGGLE_WINDOW_MAXIMIZED:
      case COMP_DISPLAY_OPTION_TOGGLE_WINDOW_MAXIMIZED_HORZ:
      case COMP_DISPLAY_OPTION_TOGGLE_WINDOW_MAXIMIZED_VERT:
      case COMP_DISPLAY_OPTION_TOGGLE_WINDOW_SHADED:
      case COMP_DISPLAY_OPTION_TOGGLE_WINDOW_FULLSCREEN:
      case COMP_DISPLAY_OPTION_RAISE_WINDOW:
      case COMP_DISPLAY_OPTION_ACTIVATE_WINDOW:
            if (setDisplayAction(display, o, value))
                  return TRUE;
            break;
      case COMP_DISPLAY_OPTION_AUDIBLE_BELL:
            if (compSetBoolOption(o, value))
            {
                  setAudibleBell(display, o->value.b);
                  return TRUE;
            }
            break;
      case COMP_DISPLAY_OPTION_DIM_DEAD:
            if (compSetBoolOption(o, value))
            {
                  Bool b = o->value.b;
                  CompScreen *s;

                  for (s = display->screens; s; s = s->next)
                  {
                        CompWindow *w;

                        for (w = s->windows; w; w = w->next)
                        {
                              if (!w->alive)
                              {
                                    if (b)
                                    {
                                          w->paint.brightness = 0xa8a8;
                                          w->paint.saturation = 0;
                                    }
                                    else
                                    {
                                          w->paint.brightness = w->brightness;
                                          w->paint.saturation = w->saturation;
                                    }
                              }
                              addWindowDamage(w);
                        }
                  }
            }
      default:
            break;
      }


      return FALSE;
}

static Bool
setDisplayOptionForPlugin(CompDisplay * display,
                                      char *plugin, char *name, CompOptionValue * value)
{
      gboolean retval = FALSE;
      CompPlugin *p;

      p = findActivePlugin(plugin);
      if (p && p->vTable->setDisplayOption)
            retval=(*p->vTable->setDisplayOption) (display, name, value);

      if (retval)
      {
            beryl_settings_context_comp_set_option_value(display->context,plugin,name,FALSE,value);
            beryl_settings_context_write(display->context);
      }

      return retval;
}

static void addTimeout(CompTimeout * timeout)
{
      CompTimeout *p = 0, *t;

      for (t = timeouts; t; t = t->next)
      {
            if (timeout->time < t->left)
                  break;

            p = t;
      }

      timeout->next = t;
      timeout->left = timeout->time;

      if (p)
            p->next = timeout;
      else
            timeouts = timeout;
}

CompTimeoutHandle
compAddTimeout(int time, CallBackProc callBack, void *closure)
{
      CompTimeout *timeout;

      timeout = malloc(sizeof(CompTimeout));
      if (!timeout)
            return 0;

      timeout->time = time;
      timeout->callBack = callBack;
      timeout->closure = closure;
      timeout->handle = lastTimeoutHandle++;

      if (lastTimeoutHandle == MAXSHORT)
            lastTimeoutHandle = 1;

      if (!timeouts)
            gettimeofday(&lastTimeout, 0);

      addTimeout(timeout);

      return timeout->handle;
}

void compRemoveTimeout(CompTimeoutHandle handle)
{
      CompTimeout *p = 0, *t;

      for (t = timeouts; t; t = t->next)
      {
            if (t->handle == handle)
                  break;

            p = t;
      }

      if (t)
      {
            if (p)
                  p->next = t->next;
            else
                  timeouts = t->next;

            free(t);
      }
}

CompWatchFdHandle
compAddWatchFd(int fd, short int events, CallBackProc callBack, void *closure)
{
      CompWatchFd *watchFd;

      watchFd = malloc(sizeof(CompWatchFd));
      if (!watchFd)
            return 0;

      watchFd->fd = fd;
      watchFd->callBack = callBack;
      watchFd->closure = closure;
      watchFd->handle = lastWatchFdHandle++;

      if (lastWatchFdHandle == MAXSHORT)
            lastWatchFdHandle = 1;

      watchFd->next = watchFds;
      watchFds = watchFd;

      nWatchFds++;

      watchPollFds = realloc(watchPollFds, nWatchFds * sizeof(struct pollfd));

      watchPollFds[nWatchFds - 1].fd = fd;
      watchPollFds[nWatchFds - 1].events = events;

      return watchFd->handle;
}

void compRemoveWatchFd(CompWatchFdHandle handle)
{
      CompWatchFd *p = 0, *w;
      int i;

      for (i = nWatchFds - 1, w = watchFds; w; i--, w = w->next)
      {
            if (w->handle == handle)
                  break;

            p = w;
      }

      if (w)
      {
            if (p)
                  p->next = w->next;
            else
                  watchFds = w->next;

            nWatchFds--;

            if (i < nWatchFds)
                  memmove(&watchPollFds[i], &watchPollFds[i + 1],
                              (nWatchFds - i) * sizeof(struct pollfd));

            free(w);
      }
}

#define TIMEVALDIFF(tv1, tv2)                           \
    ((tv1)->tv_sec == (tv2)->tv_sec || (tv1)->tv_usec >= (tv2)->tv_usec) ? \
((((tv1)->tv_sec - (tv2)->tv_sec) * 1000000) +               \
 ((tv1)->tv_usec - (tv2)->tv_usec)) / 1000 :               \
((((tv1)->tv_sec - 1 - (tv2)->tv_sec) * 1000000) +               \
 (1000000 + (tv1)->tv_usec - (tv2)->tv_usec)) / 1000

static int
getTimeToNextRedraw(CompScreen * s,
                              struct timeval *tv, struct timeval *lastTv, Bool idle)
{
      int diff, next;

      diff = TIMEVALDIFF(tv, lastTv);

      /* handle clock rollback */
      if (diff < 0)
            diff = 0;

      if (idle ||
            (s->getVideoSync
             && s->opt[COMP_SCREEN_OPTION_SYNC_TO_VBLANK].value.b))
      {
            if (s->timeMult > 1)
            {
                  s->frameStatus = -1;
                  s->redrawTime = s->optimalRedrawTime;
                  s->timeMult--;
            }
      }
      else
      {
            if (diff > s->redrawTime)
            {
                  if (s->frameStatus > 0)
                        s->frameStatus = 0;

                  next = s->optimalRedrawTime * (s->timeMult + 1);
                  if (diff > next)
                  {
                        s->frameStatus--;
                        if (s->frameStatus < -1)
                        {
                              s->timeMult++;
                              s->redrawTime = diff = next;
                        }
                  }
            }
            else if (diff < s->redrawTime)
            {
                  if (s->frameStatus < 0)
                        s->frameStatus = 0;

                  if (s->timeMult > 1)
                  {
                        next = s->optimalRedrawTime * (s->timeMult - 1);
                        if (diff < next)
                        {
                              s->frameStatus++;
                              if (s->frameStatus > 4)
                              {
                                    s->timeMult--;
                                    s->redrawTime = next;
                              }
                        }
                  }
            }
      }

      if (diff > s->redrawTime)
            return 0;

      return s->redrawTime - diff;
}

static const int maskTable[] = {
      ShiftMask, LockMask, ControlMask, Mod1Mask,
      Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask
};
static const int maskTableSize = sizeof(maskTable) / sizeof(int);

void updateModifierMappings(CompDisplay * d)
{
      unsigned int modMask[CompModNum];
      int i, minKeycode = 0, maxKeycode = 0, keysymsPerKeycode = 0;
      KeySym *keyboard_sym;

      for (i = 0; i < CompModNum; i++)
            modMask[i] = 0;

      XDisplayKeycodes(d->display, &minKeycode, &maxKeycode);
      keyboard_sym =
                  XGetKeyboardMapping(d->display, minKeycode,
                                                (maxKeycode - minKeycode + 1),
                                                &keysymsPerKeycode);

      if (keyboard_sym)
            XFree(keyboard_sym);

      if (d->modMap)
            XFreeModifiermap(d->modMap);

      d->modMap = XGetModifierMapping(d->display);
      if (d->modMap && d->modMap->max_keypermod > 0)
      {
            KeySym keysym = 0;
            int index, size, mask;

            size = maskTableSize * d->modMap->max_keypermod;

            for (i = 0; i < size; i++)
            {
                  if (!d->modMap->modifiermap[i])
                        continue;

                  index = 0;
                  do
                  {
                        keysym = XKeycodeToKeysym(d->display,
                                                              d->modMap->modifiermap[i], index++);
                  }
                  while (!keysym && index < keysymsPerKeycode);

                  if (keysym)
                  {
                        mask = maskTable[i / d->modMap->max_keypermod];

                        if (keysym == XK_Alt_L || keysym == XK_Alt_R)
                        {
                              modMask[CompModAlt] |= mask;
                        }
                        else if (keysym == XK_Meta_L || keysym == XK_Meta_R)
                        {
                              modMask[CompModMeta] |= mask;
                        }
                        else if (keysym == XK_Super_L || keysym == XK_Super_R)
                        {
                              modMask[CompModSuper] |= mask;
                        }
                        else if (keysym == XK_Hyper_L || keysym == XK_Hyper_R)
                        {
                              modMask[CompModHyper] |= mask;
                        }
                        else if (keysym == XK_Mode_switch)
                        {
                              modMask[CompModModeSwitch] |= mask;
                        }
                        else if (keysym == XK_Scroll_Lock)
                        {
                              modMask[CompModScrollLock] |= mask;
                        }
                        else if (keysym == XK_Num_Lock)
                        {
                              modMask[CompModNumLock] |= mask;
                        }
                  }
            }

            for (i = 0; i < CompModNum; i++)
            {
                  if (!modMask[i])
                        modMask[i] = CompNoMask;
            }

            if (memcmp(modMask, d->modMask, sizeof(modMask)))
            {
                  CompScreen *s;

                  memcpy(d->modMask, modMask, sizeof(modMask));

                  d->ignoredModMask = LockMask |
                              (modMask[CompModNumLock] & ~CompNoMask) |
                              (modMask[CompModScrollLock] & ~CompNoMask);

                  for (s = d->screens; s; s = s->next)
                        updatePassiveGrabs(s);
            }
      }
}

unsigned int virtualToRealModMask(CompDisplay * d, unsigned int modMask)
{
      int i;

      for (i = 0; i < CompModNum; i++)
      {
            if (modMask & virtualModMask[i])
            {
                  if (d->modMask[i] == CompNoMask)
                        return 0xFFFFFFFF;      // should help on no-super-key type situations
                  modMask &= ~virtualModMask[i];
                  modMask |= d->modMask[i];
            }
      }

      return modMask;
}

unsigned int keycodeToModifiers(CompDisplay * d, int keycode)
{
      unsigned int mods = 0;
      int mod, k;

      for (mod = 0; mod < maskTableSize; mod++)
      {
            for (k = 0; k < d->modMap->max_keypermod; k++)
            {
                  if (d->modMap->
                        modifiermap[mod * d->modMap->max_keypermod + k] == keycode)
                        mods |= maskTable[mod];
            }
      }

      return mods;
}

static int doPoll(int timeout)
{
      int rv;

      rv = poll(watchPollFds, nWatchFds, timeout);
      if (rv)
      {
            CompWatchFd *w;
            int i;

            for (i = nWatchFds - 1, w = watchFds; w; i--, w = w->next)
            {
                  if (watchPollFds[i].revents != 0 && w->callBack)
                        w->callBack(w->closure);
            }
      }

      return rv;
}

static void handleTimeouts(struct timeval *tv)
{
      CompTimeout *t;
      int timeDiff;

      timeDiff = TIMEVALDIFF(tv, &lastTimeout);

      /* handle clock rollback */
      if (timeDiff < 0)
            timeDiff = 0;

      for (t = timeouts; t; t = t->next)
            t->left -= timeDiff;

      while (timeouts && timeouts->left <= 0)
      {
            t = timeouts;
            if ((*t->callBack) (t->closure))
            {
                  timeouts = t->next;
                  addTimeout(t);
            }
            else
            {
                  timeouts = t->next;
                  free(t);
            }
      }

      lastTimeout = *tv;
}

static void waitForVideoSync(CompScreen * s)
{
      unsigned int sync;

      if (!s->opt[COMP_SCREEN_OPTION_SYNC_TO_VBLANK].value.b)
            return;

      if (disable_vsync)
            return;

      /* we currently can't handle sync to vblank when we have more than one
         output device */
      if (s->nOutputDev > 1)
            return;

      if (s->getVideoSync)
      {
            glFlush();

            (*s->getVideoSync) (&sync);
            (*s->waitVideoSync) (2, (sync + 1) % 2, &sync);
      }
}

/* Sets up a projection matrix for global perspective
 * The M() stuff and the translation should be combined so we can store
 * the individual outputdev matrices instead of storing x,y,a,b,c,d...
 */
static inline void
frustum(GLfloat x, GLfloat y, GLfloat a, GLfloat b, GLfloat c, GLfloat d)
{
      GLfloat m[16];

#define M(row,col)  m[col*4+row]
      M(0, 0) = x;
      M(0, 1) = 0.0F;
      M(0, 2) = a;
      M(0, 3) = 0.0F;
      M(1, 0) = 0.0F;
      M(1, 1) = y;
      M(1, 2) = b;
      M(1, 3) = 0.0F;
      M(2, 0) = 0.0F;
      M(2, 1) = 0.0F;
      M(2, 2) = c;
      M(2, 3) = d;
      M(3, 0) = 0.0F;
      M(3, 1) = 0.0F;
      M(3, 2) = -1.0F;
      M(3, 3) = 0.0F;
#undef M

      glMultMatrixf(m);
      glTranslatef(a / 2, b / 2, 0);
}

/* Calls frustum() for the current output dev, call glFrustum() if
 * we're doing local perspective, calculate multiPerspective[] if
 * needed.
 */
static void
perspective(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar,
                  int output, CompScreen * s)
{
      GLfloat xmin, xmax, ymin, ymax;
      GLfloat x, y, a, b, c, d;
      short int head;

      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();

      if (s->projectionStyle == COMP_PERSPECTIVE_GLOBAL_REAL)
      {
            frustum(multiPerspective[output].x,
                        multiPerspective[output].y,
                        multiPerspective[output].a,
                        multiPerspective[output].b,
                        multiPerspective[output].c, multiPerspective[output].d);
            glMatrixMode(GL_MODELVIEW);
            return;
      }

      ymax = zNear * tan(fovy * M_PI / 360.0);
      ymin = -ymax;
      xmin = ymin * aspect;
      xmax = ymax * aspect;
      if (s->projectionStyle == COMP_PERSPECTIVE_LOCAL)
      {
            glFrustum(xmin, xmax, ymin, ymax, zNear, zFar);
            s->projectionStyle = COMP_PERSPECTIVE_LOCAL_REAL;
            glMatrixMode(GL_MODELVIEW);
            return;
      }

      for (head = 0; head < s->nOutputDev; head++)
      {
            x = (2.0 * zNear) / (xmax - xmin);
            y = (2.0 * zNear) / (ymax - ymin);


            a = -(float)((s->width / 2) -
                               (s->outputDev[head].region.extents.x1 +
                                s->outputDev[head].width / 2)) /
                        (float)(s->outputDev[head].width / 2);
            b = (float)((s->height / 2) -
                              (s->outputDev[head].region.extents.y1 +
                               s->outputDev[head].height / 2)) /
                        (float)(s->outputDev[head].height / 2);

            c = -(zFar + zNear) / (zFar - zNear);
            d = -(2.0 * zFar * zNear) / (zFar - zNear);
            multiPerspective[head].x = x;
            multiPerspective[head].y = y;
            multiPerspective[head].a = a;
            multiPerspective[head].b = b;
            multiPerspective[head].c = c;
            multiPerspective[head].d = d;
      }
      frustum(multiPerspective[output].x,
                  multiPerspective[output].y,
                  multiPerspective[output].a,
                  multiPerspective[output].b,
                  multiPerspective[output].c, multiPerspective[output].d);
      glMatrixMode(GL_MODELVIEW);
      s->projectionStyle = COMP_PERSPECTIVE_GLOBAL_REAL;
}

int eventLoop(void)
{
      XEvent event;
      int timeDiff, i;
      struct timeval tv;
      Region tmpRegion, outputRegion;
      CompDisplay *display = compDisplays;
      CompScreen *s;
      int time, timeToNextRedraw = 0;
      CompWindow *w;
      unsigned int damageMask, mask;

      tmpRegion = XCreateRegion();
      outputRegion = XCreateRegion();
      if (!tmpRegion || !outputRegion)
      {
            fprintf(stderr, "%s: Couldn't create temporary regions\n",
                        programName);
            return 0;
      }

      compAddWatchFd(ConnectionNumber(display->display), POLLIN, NULL, NULL);

      for (;;)
      {
            if (display->dirtyPluginList)
                  updatePlugins(display);

            if (restartSignal)
            {
                  execvp(programName, programArgv);
                  return 1;
            }
            else if (shutDown)
            {
                  return 0;
            }

            while (g_main_pending ())
                  g_main_iteration (FALSE);

            while (XPending(display->display))
            {
                  XNextEvent(display->display, &event);

                  switch (event.type)
                  {
                  case ButtonPress:
                  case ButtonRelease:
                        display->pointerX = event.xbutton.x_root;
                        display->pointerY = event.xbutton.y_root;
                        break;
                  case KeyPress:
                  case KeyRelease:
                        display->pointerX = event.xkey.x_root;
                        display->pointerY = event.xkey.y_root;
                        break;
                  case MotionNotify:
                        display->pointerX = event.xmotion.x_root;
                        display->pointerY = event.xmotion.y_root;
                        break;
                  case EnterNotify:
                  case LeaveNotify:
                        display->pointerX = event.xcrossing.x_root;
                        display->pointerY = event.xcrossing.y_root;
                        break;
                  case ClientMessage:
                        if (event.xclient.message_type == display->xdndPositionAtom)
                        {
                              display->pointerX = event.xclient.data.l[2] >> 16;
                              display->pointerY = event.xclient.data.l[2] & 0xffff;
                        }
                  default:
                        break;
                  }

                  sn_display_process_event(display->snDisplay, &event);

                  inHandleEvent = TRUE;

                  (*display->handleEvent) (display, &event);

                  inHandleEvent = FALSE;

                  display->lastPointerX = display->pointerX;
                  display->lastPointerY = display->pointerY;
            }

            for (s = display->screens; s; s = s->next)
            {
                  if (s->damageMask)
                  {
                        finishScreenDrawing(s);
                  }
                  else
                  {
                        s->idle = TRUE;
                  }
            }

            damageMask = 0;
            timeToNextRedraw = MAXSHORT;

            for (s = display->screens; s; s = s->next)
            {
                  if (!s->damageMask)
                        continue;

                  if (!damageMask)
                  {
                        gettimeofday(&tv, 0);
                        damageMask |= s->damageMask;
                  }

                  s->timeLeft =
                              getTimeToNextRedraw(s, &tv, &s->lastRedraw, s->idle);
                  if (s->timeLeft < timeToNextRedraw)
                        timeToNextRedraw = s->timeLeft;
            }

            if (damageMask)
            {
                  time = timeToNextRedraw;
                  if (time)
                        time = doPoll(time);

                  if (time == 0)
                  {
                        gettimeofday(&tv, 0);

                        if (timeouts)
                              handleTimeouts(&tv);

                        for (s = display->screens; s; s = s->next)
                        {
                              if (!s->damageMask || s->timeLeft > timeToNextRedraw)
                                    continue;

                              targetScreen = s;

                              timeDiff = TIMEVALDIFF(&tv, &s->lastRedraw);

                              /* handle clock rollback */
                              if (timeDiff < 0)
                                    timeDiff = 0;

                              makeScreenCurrent(s);

                              if (s->slowAnimations)
                              {
                                    (*s->
                                     preparePaintScreen) (s,
                                                                    s->
                                                                    idle
                                                                    ? 2
                                                                    :
                                                                    (timeDiff * 2) / s->redrawTime);
                              }
                              else
                                    (*s->
                                     preparePaintScreen) (s,
                                                                    s->
                                                                    idle
                                                                    ? s->redrawTime : timeDiff);

                              IPCS_lock = TRUE;
                              /* substract top most overlay window region */
                              if (s->overlayWindowCount)
                              {
                                    for (w = s->reverseWindows; w; w = w->prev)
                                    {
                                          if (w->destroyed || w->invisible)
                                                continue;

                                          if (!w->redirected)
                                                XSubtractRegion
                                                            (s->damage, w->region, s->damage);

                                          break;
                                    }

                                    if (s->damageMask & COMP_SCREEN_DAMAGE_ALL_MASK)
                                    {
                                          s->damageMask &= ~COMP_SCREEN_DAMAGE_ALL_MASK;
                                          s->damageMask |= COMP_SCREEN_DAMAGE_REGION_MASK;
                                    }
                              }

                              if (s->damageMask & COMP_SCREEN_DAMAGE_REGION_MASK)
                              {
                                    XIntersectRegion(s->damage, &s->region, tmpRegion);

                                    if (tmpRegion->numRects ==
                                          1
                                          && tmpRegion->rects->
                                          x1 == 0
                                          && tmpRegion->rects->
                                          y1 == 0
                                          && tmpRegion->rects->
                                          x2 == s->width
                                          && tmpRegion->rects->y2 == s->height)
                                          damageScreen(s);
                              }

                              EMPTY_REGION(s->damage);
                              mask = s->damageMask;
                              s->damageMask = 0;

                              for (i = 0; i < s->nOutputDev; i++)
                              {
                                    targetScreen = s;
                                    targetOutput = i;

                                    if (s->projectionStyle != COMP_PERSPECTIVE_LOCAL_REAL)
                                          perspective(60.0f, 1.0f, 0.1f, 100.0f, i, s);

                                    if (s->nOutputDev > 1)
                                    {
                                          glViewport(s->
                                                         outputDev
                                                         [i].
                                                         region.
                                                         extents.
                                                         x1,
                                                         s->
                                                         height -
                                                         s->
                                                         outputDev
                                                         [i].
                                                         region.
                                                         extents.
                                                         y2,
                                                         s->
                                                         outputDev
                                                         [i].width, s->outputDev[i].height);
                                    }

                                    if (mask & COMP_SCREEN_DAMAGE_ALL_MASK)
                                    {
                                          (*s->
                                           paintScreen) (s,
                                                               &defaultScreenPaintAttrib,
                                                               &s->
                                                               outputDev
                                                               [i].
                                                               region,
                                                               i,
                                                               PAINT_SCREEN_REGION_MASK
                                                               | PAINT_SCREEN_FULL_MASK);
                                    }
                                    else if (mask & COMP_SCREEN_DAMAGE_REGION_MASK)
                                    {
                                          XIntersectRegion
                                                      (tmpRegion,
                                                       &s->outputDev[i].region, outputRegion);
                                          if (!
                                                (*s->
                                                 paintScreen)
                                                (s, &defaultScreenPaintAttrib, outputRegion,
                                                 i, PAINT_SCREEN_REGION_MASK))
                                          {
                                                (*s->
                                                 paintScreen)
                                                      (s,
                                                       &defaultScreenPaintAttrib,
                                                       &s->
                                                       outputDev
                                                       [i].region, i, PAINT_SCREEN_FULL_MASK);

                                                XUnionRegion
                                                            (tmpRegion,
                                                             &s->outputDev[i].region, tmpRegion);
                                          }
                                    }
                              }

                              waitForVideoSync(s);

                              if (mask & COMP_SCREEN_DAMAGE_ALL_MASK)
                              {
                                    glXSwapBuffers(display->display, s->output);
                              }
                              else
                              {
                                    BoxPtr pBox;
                                    int nBox, y;

                                    pBox = tmpRegion->rects;
                                    nBox = tmpRegion->numRects;

                                    if (s->copySubBuffer)
                                    {
                                          while (nBox--)
                                          {
                                                y = s->height - pBox->y2;

                                                (*s->
                                                 copySubBuffer)
                                                      (display->
                                                       display,
                                                       s->
                                                       output,
                                                       pBox->
                                                       x1, y,
                                                       pBox->
                                                       x2 - pBox->x1, pBox->y2 - pBox->y1);

                                                pBox++;
                                          }
                                    }
                                    else
                                    {
                                          glEnable(GL_SCISSOR_TEST);
                                          glDrawBuffer(GL_FRONT);

                                          while (nBox--)
                                          {
                                                y = s->height - pBox->y2;

                                                glBitmap(0,
                                                             0,
                                                             0,
                                                             0,
                                                             pBox->
                                                             x1
                                                             - s->rasterX, y - s->rasterY, NULL);

                                                s->rasterX = pBox->x1;
                                                s->rasterY = y;

                                                glScissor
                                                            (pBox->
                                                             x1, y,
                                                             pBox->
                                                             x2 - pBox->x1, pBox->y2 - pBox->y1);

                                                glCopyPixels
                                                            (pBox->
                                                             x1, y,
                                                             pBox->
                                                             x2 -
                                                             pBox->
                                                             x1, pBox->y2 - pBox->y1, GL_COLOR);

                                                pBox++;
                                          }

                                          glDrawBuffer(GL_BACK);
                                          glDisable(GL_SCISSOR_TEST);
                                          glFlush();
                                    }
                              }

                              targetScreen = NULL;
                              targetOutput = 0;

                              s->lastRedraw = tv;

                              IPCS_lock = FALSE;

                              (*s->donePaintScreen) (s);
                              /* XXX:
                               * I belive the intention is for aiglx only.
                               * I added the conditional,
                               * this needs to be tested.
                               */
                              //if (!useCow)
                              //  glFinish(); // patch from redhat
                              //  removed due to fix from upstream

                              /* remove destroyed windows */
                              while (s->pendingDestroys)
                              {
                                    CompWindow *w;

                                    for (w = s->windows; w; w = w->next)
                                    {
                                          if (w->destroyed)
                                          {
                                                addWindowDamage(w);
                                                removeWindow(w);
                                                break;
                                          }
                                    }

                                    s->pendingDestroys--;
                              }

                              s->idle = FALSE;
                        }
                  }
            }
            else
            {
                  if (timeouts)
                  {
                        if (timeouts->left > 0)
                              doPoll(timeouts->left);

                        gettimeofday(&tv, 0);

                        handleTimeouts(&tv);
                  }
                  else
                  {
                        doPoll(1000);
                  }
            }
      }

      return 0;
}

static int errors = 0;

static int errorHandler(Display * dpy, XErrorEvent * e)
{

#ifdef DEBUG
      char str[128];
      char *name = 0;
      int o;
#endif

      errors++;

#ifdef DEBUG
      XGetErrorDatabaseText(dpy, "XlibMessage", "XError", "", str, 128);
      fprintf(stderr, "%s", str);

      o = e->error_code - compDisplays->damageError;
      switch (o)
      {
      case BadDamage:
            name = "BadDamage";
            break;
      default:
            break;
      }

      if (name)
      {
            fprintf(stderr, ": %s\n  ", name);
      }
      else
      {
            XGetErrorText(dpy, e->error_code, str, 128);
            fprintf(stderr, ": %s\n  ", str);
      }

      XGetErrorDatabaseText(dpy, "XlibMessage", "MajorCode", "%d", str, 128);
      fprintf(stderr, str, e->request_code);

      sprintf(str, "%d", e->request_code);
      XGetErrorDatabaseText(dpy, "XRequest", str, "", str, 128);
      if (strcmp(str, ""))
            fprintf(stderr, " (%s)", str);
      fprintf(stderr, "\n  ");

      XGetErrorDatabaseText(dpy, "XlibMessage", "MinorCode", "%d", str, 128);
      fprintf(stderr, str, e->minor_code);
      fprintf(stderr, "\n  ");

      XGetErrorDatabaseText(dpy, "XlibMessage", "ResourceID", "%d", str, 128);
      fprintf(stderr, str, e->resourceid);
      fprintf(stderr, "\n");

      /* abort (); */
#endif

      return 0;
}

int compCheckForError(Display * dpy)
{
      int e;

      XSync(dpy, FALSE);

      e = errors;
      errors = 0;

      return e;
}

#define PING_DELAY 5000

static Bool pingTimeout(void *closure)
{
      CompDisplay *d = closure;
      CompScreen *s;
      CompWindow *w;
      XEvent ev;
      int ping = d->lastPing + 1;

      ev.type = ClientMessage;
      ev.xclient.window = 0;
      ev.xclient.message_type = d->wmProtocolsAtom;
      ev.xclient.format = 32;
      ev.xclient.data.l[0] = d->wmPingAtom;
      ev.xclient.data.l[1] = ping;
      ev.xclient.data.l[2] = 0;
      ev.xclient.data.l[3] = 0;
      ev.xclient.data.l[4] = 0;

      for (s = d->screens; s; s = s->next)
      {
            for (w = s->windows; w; w = w->next)
            {
                  if (w->attrib.map_state != IsViewable)
                        continue;

                  if (!(w->type & CompWindowTypeNormalMask))
                        continue;

                  if (w->protocols & CompWindowProtocolPingMask)
                  {
                        if (w->transientFor)
                              continue;

                        if (w->lastPong < d->lastPing)
                        {
                              if (w->alive)
                              {
                                    w->alive = FALSE;
                                    if (d->opt[COMP_DISPLAY_OPTION_DIM_DEAD].value.b)
                                    {
                                          w->paint.brightness = 0xa8a8;
                                          w->paint.saturation = 0;
                                    }

                                    if (w->closeRequests)
                                    {
                                          toolkitAction(s,
                                                              d->
                                                              toolkitActionForceQuitDialogAtom,
                                                              w->
                                                              lastCloseRequestTime,
                                                              w->id, TRUE, 0, 0);

                                          w->closeRequests = 0;
                                    }

                                    addWindowDamage(w);
                              }
                        }

                        ev.xclient.window = w->id;
                        ev.xclient.data.l[2] = w->id;

                        XSendEvent(d->display, w->id, FALSE, NoEventMask, &ev);
                  }
            }
      }

      d->lastPing = ping;

      return TRUE;
}

static void addScreenActions(CompDisplay * d, CompScreen * s)
{
      addScreenAction(s,
                              &d->opt[COMP_DISPLAY_OPTION_CLOSE_WINDOW].value.action);
      addScreenAction(s, &d->opt[COMP_DISPLAY_OPTION_MAIN_MENU].value.action);
      addScreenAction(s, &d->opt[COMP_DISPLAY_OPTION_RUN_DIALOG].value.action);
      addScreenAction(s,
                              &d->opt[COMP_DISPLAY_OPTION_MINIMIZE_WINDOW].value.
                              action);
      addScreenAction(s,
                              &d->opt[COMP_DISPLAY_OPTION_MAXIMIZE_WINDOW].value.
                              action);
      addScreenAction(s,
                              &d->opt[COMP_DISPLAY_OPTION_MAXIMIZE_WINDOW_HORZ].
                              value.action);
      addScreenAction(s,
                              &d->opt[COMP_DISPLAY_OPTION_MAXIMIZE_WINDOW_VERT].
                              value.action);
      addScreenAction(s,
                              &d->opt[COMP_DISPLAY_OPTION_UNMAXIMIZE_WINDOW].
                              value.action);
      addScreenAction(s,
                              &d->opt[COMP_DISPLAY_OPTION_SHOW_DESKTOP].value.action);
      addScreenAction(s,
                              &d->opt[COMP_DISPLAY_OPTION_RUN_COMMAND0].value.action);
      addScreenAction(s,
                              &d->opt[COMP_DISPLAY_OPTION_RUN_COMMAND1].value.action);
      addScreenAction(s,
                              &d->opt[COMP_DISPLAY_OPTION_RUN_COMMAND2].value.action);
      addScreenAction(s,
                              &d->opt[COMP_DISPLAY_OPTION_RUN_COMMAND3].value.action);
      addScreenAction(s,
                              &d->opt[COMP_DISPLAY_OPTION_RUN_COMMAND4].value.action);
      addScreenAction(s,
                              &d->opt[COMP_DISPLAY_OPTION_RUN_COMMAND5].value.action);
      addScreenAction(s,
                              &d->opt[COMP_DISPLAY_OPTION_RUN_COMMAND6].value.action);
      addScreenAction(s,
                              &d->opt[COMP_DISPLAY_OPTION_RUN_COMMAND7].value.action);
      addScreenAction(s,
                              &d->opt[COMP_DISPLAY_OPTION_RUN_COMMAND8].value.action);
      addScreenAction(s,
                              &d->opt[COMP_DISPLAY_OPTION_RUN_COMMAND9].value.action);
      addScreenAction(s,
                              &d->opt[COMP_DISPLAY_OPTION_RUN_COMMAND10].value.action);
      addScreenAction(s,
                              &d->opt[COMP_DISPLAY_OPTION_RUN_COMMAND11].value.action);
      addScreenAction(s,
                              &d->opt[COMP_DISPLAY_OPTION_SLOW_ANIMATIONS].value.
                              action);
      addScreenAction(s,
                              &d->opt[COMP_DISPLAY_OPTION_LOWER_WINDOW].value.action);
      addScreenAction(s,
                              &d->opt[COMP_DISPLAY_OPTION_RAISE_WINDOW].value.action);
      addScreenAction(s,
                              &d->opt[COMP_DISPLAY_OPTION_ACTIVATE_WINDOW].value.action);
      addScreenAction(s,
                              &d->opt[COMP_DISPLAY_OPTION_OPACITY_INCREASE].
                              value.action);
      addScreenAction(s,
                              &d->opt[COMP_DISPLAY_OPTION_OPACITY_DECREASE].
                              value.action);
      addScreenAction(s,
                              &d->opt[COMP_DISPLAY_OPTION_RUN_SCREENSHOT].value.action);
      addScreenAction(s,
                              &d->opt[COMP_DISPLAY_OPTION_RUN_WINDOW_SCREENSHOT].
                              value.action);
      addScreenAction(s, &d->opt[COMP_DISPLAY_OPTION_WINDOW_MENU].value.action);
      addScreenAction(s,
                              &d->
                              opt[COMP_DISPLAY_OPTION_TOGGLE_WINDOW_MAXIMIZED].
                              value.action);
      addScreenAction(s,
                              &d->
                              opt
                              [COMP_DISPLAY_OPTION_TOGGLE_WINDOW_MAXIMIZED_HORZ].
                              value.action);
      addScreenAction(s,
                              &d->
                              opt
                              [COMP_DISPLAY_OPTION_TOGGLE_WINDOW_MAXIMIZED_VERT].
                              value.action);
      addScreenAction(s,
                              &d->opt[COMP_DISPLAY_OPTION_TOGGLE_WINDOW_SHADED].
                              value.action);
      addScreenAction(s,
                              &d->
                              opt[COMP_DISPLAY_OPTION_TOGGLE_WINDOW_FULLSCREEN].
                              value.action);
}

void addScreenToDisplay(CompDisplay * display, CompScreen * s)
{
      CompScreen *prev;

      for (prev = display->screens; prev && prev->next; prev = prev->next);

      if (prev)
            prev->next = s;
      else
            display->screens = s;

      addScreenActions(display, s);
}

static void compDisplaySetBindingFuncs(CompDisplay * display)
{
      CompOption *o;

      o = &display->opt[COMP_DISPLAY_OPTION_CLOSE_WINDOW];
      o->value.action.initiate = closeWin;
      o->value.action.terminate = 0;

      o = &display->opt[COMP_DISPLAY_OPTION_MAIN_MENU];
      o->value.action.initiate = mainMenu;
      o->value.action.terminate = 0;

      o = &display->opt[COMP_DISPLAY_OPTION_RUN_DIALOG];
      o->value.action.initiate = runDialog;
      o->value.action.terminate = 0;

      o = &display->opt[COMP_DISPLAY_OPTION_UNMAXIMIZE_WINDOW];
      o->value.action.initiate = unmaximize;
      o->value.action.terminate = 0;

      o = &display->opt[COMP_DISPLAY_OPTION_MINIMIZE_WINDOW];
      o->value.action.initiate = minimize;
      o->value.action.terminate = 0;

      o = &display->opt[COMP_DISPLAY_OPTION_MAXIMIZE_WINDOW];
      o->value.action.initiate = maximize;
      o->value.action.terminate = 0;

      o = &display->opt[COMP_DISPLAY_OPTION_MAXIMIZE_WINDOW_HORZ];
      o->value.action.initiate = maximizeHorizontally;
      o->value.action.terminate = 0;

      o = &display->opt[COMP_DISPLAY_OPTION_MAXIMIZE_WINDOW_VERT];
      o->value.action.initiate = maximizeVertically;
      o->value.action.terminate = 0;

      o = &display->opt[COMP_DISPLAY_OPTION_SHOW_DESKTOP];
      o->value.action.initiate = showDesktop;
      o->value.action.terminate = 0;

#define COMMAND_OPTION(num)                    \
    o = &display->opt[COMP_DISPLAY_OPTION_RUN_COMMAND ## num ];            \
    o->value.action.initiate      = runCommandDispatch;                \
    o->value.action.terminate     = 0;                        \

      COMMAND_OPTION(0);
      COMMAND_OPTION(1);
      COMMAND_OPTION(2);
      COMMAND_OPTION(3);
      COMMAND_OPTION(4);
      COMMAND_OPTION(5);
      COMMAND_OPTION(6);
      COMMAND_OPTION(7);
      COMMAND_OPTION(8);
      COMMAND_OPTION(9);
      COMMAND_OPTION(10);
      COMMAND_OPTION(11);

      o = &display->opt[COMP_DISPLAY_OPTION_SLOW_ANIMATIONS];
      o->value.action.initiate = toggleSlowAnimations;
      o->value.action.terminate = 0;

      o = &display->opt[COMP_DISPLAY_OPTION_LOWER_WINDOW];
      o->value.action.initiate = lower;
      o->value.action.terminate = 0;

      o = &display->opt[COMP_DISPLAY_OPTION_RAISE_WINDOW];
      o->value.action.initiate = raise;
      o->value.action.terminate = 0;

      o = &display->opt[COMP_DISPLAY_OPTION_ACTIVATE_WINDOW];
      o->value.action.initiate = activate;
      o->value.action.terminate = 0;

      o = &display->opt[COMP_DISPLAY_OPTION_OPACITY_INCREASE];
      o->value.action.initiate = increaseOpacity;
      o->value.action.terminate = 0;

      o = &display->opt[COMP_DISPLAY_OPTION_OPACITY_DECREASE];
      o->value.action.initiate = decreaseOpacity;
      o->value.action.terminate = 0;

      o = &display->opt[COMP_DISPLAY_OPTION_SATURATION_INCREASE];
      o->value.action.initiate = increaseSaturation;
      o->value.action.terminate = 0;

      o = &display->opt[COMP_DISPLAY_OPTION_SATURATION_DECREASE];
      o->value.action.initiate = decreaseSaturation;
      o->value.action.terminate = 0;

      o = &display->opt[COMP_DISPLAY_OPTION_BRIGHTNESS_INCREASE];
      o->value.action.initiate = increaseBrightness;
      o->value.action.terminate = 0;

      o = &display->opt[COMP_DISPLAY_OPTION_BRIGHTNESS_DECREASE];
      o->value.action.initiate = decreaseBrightness;
      o->value.action.terminate = 0;

      o = &display->opt[COMP_DISPLAY_OPTION_RUN_SCREENSHOT];
      o->value.action.initiate = runCommandScreenshot;
      o->value.action.terminate = 0;

      o = &display->opt[COMP_DISPLAY_OPTION_RUN_WINDOW_SCREENSHOT];
      o->value.action.initiate = runCommandWindowScreenshot;
      o->value.action.terminate = 0;

      o = &display->opt[COMP_DISPLAY_OPTION_WINDOW_MENU];
      o->value.action.initiate = windowMenu;
      o->value.action.terminate = 0;

      o = &display->opt[COMP_DISPLAY_OPTION_TOGGLE_WINDOW_MAXIMIZED];
      o->value.action.initiate = toggleMaximized;
      o->value.action.terminate = 0;

      o = &display->opt[COMP_DISPLAY_OPTION_TOGGLE_WINDOW_FULLSCREEN];
      o->value.action.initiate = toggleFullscreen;
      o->value.action.terminate = 0;

      o = &display->opt[COMP_DISPLAY_OPTION_TOGGLE_WINDOW_MAXIMIZED_HORZ];
      o->value.action.initiate = toggleMaximizedHorizontally;
      o->value.action.terminate = 0;

      o = &display->opt[COMP_DISPLAY_OPTION_TOGGLE_WINDOW_MAXIMIZED_VERT];
      o->value.action.initiate = toggleMaximizedVertically;
      o->value.action.terminate = 0;

      o = &display->opt[COMP_DISPLAY_OPTION_TOGGLE_WINDOW_SHADED];
      o->value.action.initiate = shade;
      o->value.action.terminate = 0;
}

static CompRequestFlag *addRequestFlag(CompDisplay * d, char *request)
{
      d->nRequestFlags++;
      d->requestFlags = realloc(d->requestFlags,
                                            d->nRequestFlags * sizeof(CompRequestFlag));
      int i;

      for (i = 0; i < 8; i++)
            d->requestFlags[d->nRequestFlags - 1].data[i] = 0;
      d->requestFlags[d->nRequestFlags - 1].name = strdup(request);
      return &(d->requestFlags[d->nRequestFlags - 1]);
}

static CompRequestFlag *getRequestFlag(CompDisplay * d, char *request)
{
      int i;

      for (i = 0; i < d->nRequestFlags; i++)
      {
            if (!strcasecmp(request, d->requestFlags[i].name))
                  return &(d->requestFlags[i]);
      }
      return addRequestFlag(d, request);
}

Bool compDisplayGetRequestFlagForPlugin(CompDisplay * d,
                                                            char *plugin, char *request)
{
      int idx = findActivePluginIndex(plugin);

      if (idx < 0)
            return False;
      CompRequestFlag *f = getRequestFlag(d, request);

      return (f->data[idx / 8] & (1 << (idx % 8))) ? True : False;
}

Bool compDisplayGetRequestFlagForAny(CompDisplay * d, char *request)
{
      CompRequestFlag *f = getRequestFlag(d, request);
      int i;

      for (i = 0; i < 8; i++)
            if (f->data[i])
                  return True;
      return False;
}

void compDisplaySetRequestFlagForPlugin(CompDisplay * d,
                                                            char *plugin, char *request)
{
      int idx = findActivePluginIndex(plugin);

      if (idx < 0)
            return;
      CompRequestFlag *f = getRequestFlag(d, request);

      f->data[idx / 8] |= (1 << (idx % 8));
}

void compDisplayClearRequestFlagForPlugin(CompDisplay * d,
                                                              char *plugin, char *request)
{
      int idx = findActivePluginIndex(plugin);

      if (idx < 0)
            return;
      CompRequestFlag *f = getRequestFlag(d, request);

      f->data[idx / 8] &= ~(1 << (idx % 8));
}

void releaseDisplay(void)
{
      compDisplay.on_shutdown = TRUE;

      finiPlugins(&compDisplay);

      while (compDisplay.screens)
            releaseScreen(compDisplay.screens);

      compDisplayFreeOptions(&compDisplay);

      if (compDisplay.display)
            XCloseDisplay(compDisplay.display);

      if (compDisplay.privates)
            free(compDisplay.privates);
}

Bool addDisplay(char *name, int screenNum, char **plugin, int nPlugin)
{
      CompDisplay *d;
      Display *dpy;
      Window focus;
      int revertTo, i;
      int compositeMajor, compositeMinor;
      int xkbOpcode;

      d = &compDisplay;

      d->nRequestFlags = 0;
      d->requestFlags = 0;

      d->pointerX = d->lastPointerX = 0;
      d->pointerY = d->lastPointerY = 0;

      d->focusStealingLevel = FSP_NORMAL;

      IPCS_INITOBJ(d);

      if (displayPrivateLen)
      {
            d->privates = malloc(displayPrivateLen * sizeof(CompPrivate));
            if (!d->privates)
                  return FALSE;
      }
      else
            d->privates = 0;

      d->screenPrivateIndices = 0;
      d->screenPrivateLen = 0;

      d->modMap = 0;

      for (i = 0; i < CompModNum; i++)
            d->modMask[i] = CompNoMask;

      d->ignoredModMask = LockMask;

      d->plugin.list.type = CompOptionTypeString;
      d->plugin.list.nValue = 0;
      d->plugin.list.value = 0;

      d->textureFilter = GL_LINEAR;
      d->below = None;

      d->activeWindow = 0;

      d->autoRaiseHandle = 0;
      d->autoRaiseWindow = None;

      d->display = dpy = XOpenDisplay(name);
      if (!d->display)
      {
            fprintf(stderr, _("%s: Couldn't open display %s\n"),
                        programName, XDisplayName(name));
            return FALSE;
      }

      compDisplayInitOptions(d, plugin, nPlugin);
      compDisplaySetBindingFuncs(d);

      snprintf(d->displayString, 255, "DISPLAY=%s", DisplayString(dpy));

#ifdef DEBUG
      XSynchronize(dpy, TRUE);
#endif

      XSetErrorHandler(errorHandler);

      updateModifierMappings(d);

      d->context= beryl_settings_context_new();
      d->context->private_ptr = d;
      beryl_setting_add_nofify(d->context,reload_setting);
      beryl_settings_context_read(d->context);

      d->setDisplayOption = setDisplayOption;
      d->setDisplayOptionForPlugin = setDisplayOptionForPlugin;

      d->initPluginForDisplay = initPluginForDisplay;
      d->finiPluginForDisplay = finiPluginForDisplay;

      d->handleEvent = handleEvent;
      d->handleBerylEvent = handleBerylEvent;

      d->fileToImage = fileToImage;
      d->imageToFile = imageToFile;

      d->reloadSettingsAtom=XInternAtom(dpy,"_BERYL_SETTINGS_RELOAD",0);

      d->berylDesktopManaged = XInternAtom(dpy, "_BERYL_DESKTOP_MANAGED", 0);


      d->supportedAtom = XInternAtom(dpy, "_NET_SUPPORTED", 0);
      d->supportingWmCheckAtom =
                  XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", 0);

      d->utf8StringAtom = XInternAtom(dpy, "UTF8_STRING", 0);

      d->wmNameAtom = XInternAtom(dpy, "_NET_WM_NAME", 0);

      d->winTypeAtom = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", 0);
      d->winTypeDesktopAtom =
                  XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DESKTOP", 0);
      d->winTypeDockAtom = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DOCK", 0);
      d->winTypeToolbarAtom =
                  XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_TOOLBAR", 0);
      d->winTypeMenuAtom = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_MENU", 0);
      d->winTypeUtilAtom = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_UTILITY", 0);
      d->winTypeSplashAtom = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_SPLASH", 0);
      d->winTypeDialogAtom = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", 0);
      d->winTypeNormalAtom = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_NORMAL", 0);

      d->winTypeDropdownMenuAtom =
                  XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU", 0);
      d->winTypePopupMenuAtom =
                  XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_POPUP_MENU", 0);
      d->winTypeTooltipAtom =
                  XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_TOOLTIP", 0);
      d->winTypeNotificationAtom =
                  XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_NOTIFICATION", 0);
      d->winTypeComboAtom = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_COMBO", 0);
      d->winTypeDndAtom = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DND", 0);

      d->winOpacityAtom = XInternAtom(dpy, "_NET_WM_WINDOW_OPACITY", 0);
      d->winBrightnessAtom = XInternAtom(dpy, "_NET_WM_WINDOW_BRIGHTNESS", 0);
      d->winSaturationAtom = XInternAtom(dpy, "_NET_WM_WINDOW_SATURATION", 0);

      d->winActiveAtom = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", 0);

      d->winDesktopAtom = XInternAtom(dpy, "_NET_WM_DESKTOP", 0);

      d->workareaAtom = XInternAtom(dpy, "_NET_WORKAREA", 0);

      d->desktopViewportAtom = XInternAtom(dpy, "_NET_DESKTOP_VIEWPORT", 0);
      d->desktopGeometryAtom = XInternAtom(dpy, "_NET_DESKTOP_GEOMETRY", 0);
      d->currentDesktopAtom = XInternAtom(dpy, "_NET_CURRENT_DESKTOP", 0);
      d->numberOfDesktopsAtom = XInternAtom(dpy, "_NET_NUMBER_OF_DESKTOPS", 0);

      d->winStateAtom = XInternAtom(dpy, "_NET_WM_STATE", 0);
      d->winStateModalAtom = XInternAtom(dpy, "_NET_WM_STATE_MODAL", 0);
      d->winStateStickyAtom = XInternAtom(dpy, "_NET_WM_STATE_STICKY", 0);
      d->winStateMaximizedVertAtom =
                  XInternAtom(dpy, "_NET_WM_STATE_MAXIMIZED_VERT", 0);
      d->winStateMaximizedHorzAtom =
                  XInternAtom(dpy, "_NET_WM_STATE_MAXIMIZED_HORZ", 0);
      d->winStateShadedAtom = XInternAtom(dpy, "_NET_WM_STATE_SHADED", 0);
      d->winStateSkipTaskbarAtom =
                  XInternAtom(dpy, "_NET_WM_STATE_SKIP_TASKBAR", 0);
      d->winStateSkipPagerAtom =
                  XInternAtom(dpy, "_NET_WM_STATE_SKIP_PAGER", 0);
      d->winStateHiddenAtom = XInternAtom(dpy, "_NET_WM_STATE_HIDDEN", 0);
      d->winStateFullscreenAtom =
                  XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", 0);
      d->winStateAboveAtom = XInternAtom(dpy, "_NET_WM_STATE_ABOVE", 0);
      d->winStateBelowAtom = XInternAtom(dpy, "_NET_WM_STATE_BELOW", 0);
      d->winStateDemandsAttentionAtom =
                  XInternAtom(dpy, "_NET_WM_STATE_DEMANDS_ATTENTION", 0);
      d->winStateDisplayModalAtom =
                  XInternAtom(dpy, "_NET_WM_STATE_DISPLAY_MODAL", 0);
      d->winStateNoFocusAtom = XInternAtom(dpy, "_COMPIZ_WM_STATE_NO_FOCUS", 0);
      d->winStateOffscreenAtom = XInternAtom(dpy, "_BERYL_WM_STATE_OFFSCREEN", 0);

      d->winActionMoveAtom = XInternAtom(dpy, "_NET_WM_ACTION_MOVE", 0);
      d->winActionResizeAtom = XInternAtom(dpy, "_NET_WM_ACTION_RESIZE", 0);
      d->winActionStickAtom = XInternAtom(dpy, "_NET_WM_ACTION_STICK", 0);
      d->winActionMinimizeAtom = XInternAtom(dpy, "_NET_WM_ACTION_MINIMIZE", 0);
      d->winActionMaximizeHorzAtom =
                  XInternAtom(dpy, "_NET_WM_ACTION_MAXIMIZE_HORZ", 0);
      d->winActionMaximizeVertAtom =
                  XInternAtom(dpy, "_NET_WM_ACTION_MAXIMIZE_VERT", 0);
      d->winActionFullscreenAtom =
                  XInternAtom(dpy, "_NET_WM_ACTION_FULLSCREEN", 0);
      d->winActionCloseAtom = XInternAtom(dpy, "_NET_WM_ACTION_CLOSE", 0);
      d->winActionShadeAtom = XInternAtom(dpy, "_NET_WM_ACTION_SHADE", 0);
      d->winActionChangeDesktopAtom =
                  XInternAtom(dpy, "_NET_WM_ACTION_CHANGE_DESKTOP", 0);

      d->wmAllowedActionsAtom = XInternAtom(dpy, "_NET_WM_ALLOWED_ACTIONS", 0);

      d->wmStrutAtom = XInternAtom(dpy, "_NET_WM_STRUT", 0);
      d->wmStrutPartialAtom = XInternAtom(dpy, "_NET_WM_STRUT_PARTIAL", 0);

      d->wmUserTimeAtom = XInternAtom(dpy, "_NET_WM_USER_TIME", 0);

      d->wmIconAtom = XInternAtom(dpy, "_NET_WM_ICON", 0);

      d->clientListAtom = XInternAtom(dpy, "_NET_CLIENT_LIST", 0);
      d->clientListStackingAtom =
                  XInternAtom(dpy, "_NET_CLIENT_LIST_STACKING", 0);

      d->frameExtentsAtom = XInternAtom(dpy, "_NET_FRAME_EXTENTS", 0);
      d->frameWindowAtom = XInternAtom(dpy, "_NET_FRAME_WINDOW", 0);

      d->wmStateAtom = XInternAtom(dpy, "WM_STATE", 0);
      d->wmChangeStateAtom = XInternAtom(dpy, "WM_CHANGE_STATE", 0);
      d->wmProtocolsAtom = XInternAtom(dpy, "WM_PROTOCOLS", 0);
      d->wmClientLeaderAtom = XInternAtom(dpy, "WM_CLIENT_LEADER", 0);

      d->wmDeleteWindowAtom = XInternAtom(dpy, "WM_DELETE_WINDOW", 0);
      d->wmTakeFocusAtom = XInternAtom(dpy, "WM_TAKE_FOCUS", 0);
      d->wmPingAtom = XInternAtom(dpy, "_NET_WM_PING", 0);
      d->wmSyncRequestAtom = XInternAtom(dpy, "_NET_WM_SYNC_REQUEST", 0);

      d->wmSyncRequestCounterAtom =
                  XInternAtom(dpy, "_NET_WM_SYNC_REQUEST_COUNTER", 0);

      d->closeWindowAtom = XInternAtom(dpy, "_NET_CLOSE_WINDOW", 0);
      d->wmMoveResizeAtom = XInternAtom(dpy, "_NET_WM_MOVERESIZE", 0);
      d->moveResizeWindowAtom = XInternAtom(dpy, "_NET_MOVERESIZE_WINDOW", 0);
      d->restackWindowAtom = XInternAtom(dpy, "_NET_RESTACK_WINDOW", 0);

      d->showingDesktopAtom = XInternAtom(dpy, "_NET_SHOWING_DESKTOP", 0);

      d->xBackgroundAtom[0] = XInternAtom(dpy, "_XSETROOT_ID", 0);
      d->xBackgroundAtom[1] = XInternAtom(dpy, "_XROOTPMAP_ID", 0);

      d->toolkitActionAtom = XInternAtom(dpy, "_COMPIZ_TOOLKIT_ACTION", 0);
      d->toolkitActionMainMenuAtom =
                  XInternAtom(dpy, "_COMPIZ_TOOLKIT_ACTION_MAIN_MENU", 0);
      d->toolkitActionRunDialogAtom =
                  XInternAtom(dpy, "_COMPIZ_TOOLKIT_ACTION_RUN_DIALOG", 0);
      d->toolkitActionWindowMenuAtom =
                  XInternAtom(dpy, "_COMPIZ_TOOLKIT_ACTION_WINDOW_MENU", 0);
      d->toolkitActionForceQuitDialogAtom =
                  XInternAtom(dpy, "_COMPIZ_TOOLKIT_ACTION_FORCE_QUIT_DIALOG", 0);

      d->mwmHintsAtom = XInternAtom(dpy, "_MOTIF_WM_HINTS", 0);

      d->xdndAwareAtom = XInternAtom(dpy, "XdndAware", 0);
      d->xdndEnterAtom = XInternAtom(dpy, "XdndEnter", 0);
      d->xdndLeaveAtom = XInternAtom(dpy, "XdndLeave", 0);
      d->xdndPositionAtom = XInternAtom(dpy, "XdndPosition", 0);
      d->xdndStatusAtom = XInternAtom(dpy, "XdndStatus", 0);
      d->xdndDropAtom = XInternAtom(dpy, "XdndDrop", 0);

      d->managerAtom = XInternAtom(dpy, "MANAGER", 0);
      d->targetsAtom = XInternAtom(dpy, "TARGETS", 0);
      d->multipleAtom = XInternAtom(dpy, "MULTIPLE", 0);
      d->timestampAtom = XInternAtom(dpy, "TIMESTAMP", 0);
      d->versionAtom = XInternAtom(dpy, "VERSION", 0);
      d->atomPairAtom = XInternAtom(dpy, "ATOM_PAIR", 0);

      d->startupIdAtom = XInternAtom(dpy, "_NET_STARTUP_ID", 0);

      d->berylNetWmUserCreationTime =
                  XInternAtom(dpy, "_BERYL_NET_WM_USER_CREATION_TIME", 0);

      d->berylNetWmOffscreenOffsetAtom =
                  XInternAtom(dpy, "_BERYL_NET_WM_OFFSCREEN_OFFSET", 0);

      d->vertRestoreGeometryAtom =
                  XInternAtom(dpy, "_XNET_VERT_RESTORE_GEOMETRY", 0);
      d->horzRestoreGeometryAtom =
                  XInternAtom(dpy, "_XNET_HORZ_RESTORE_GEOMETRY", 0);

      d->snDisplay = sn_display_new(dpy, NULL, NULL);
      if (!d->snDisplay)
            return FALSE;

      d->lastPing = 1;

      if (!XQueryExtension(dpy,
                                     COMPOSITE_NAME,
                                     &d->compositeOpcode,
                                     &d->compositeEvent, &d->compositeError))
      {
            fprintf(stderr, _("%s: No composite extension\n"), programName);
            return FALSE;
      }

      XCompositeQueryVersion(dpy, &compositeMajor, &compositeMinor);
      if (compositeMajor == 0 && compositeMinor < 2)
      {
            fprintf(stderr, _("%s: Old composite extension\n"), programName);
            return FALSE;
      }

      if (!XDamageQueryExtension(dpy, &d->damageEvent, &d->damageError))
      {
            fprintf(stderr, _("%s: No damage extension\n"), programName);
            return FALSE;
      }

      if (!XRRQueryExtension(dpy, &d->randrEvent, &d->randrError))
      {
            fprintf(stderr, _("%s: No RandR extension\n"), programName);
            return FALSE;
      }

      if (!XSyncQueryExtension(dpy, &d->syncEvent, &d->syncError))
      {
            fprintf(stderr, _("%s: No sync extension\n"), programName);
            return FALSE;
      }

      d->shapeExtension = XShapeQueryExtension(dpy,
                                                                   &d->shapeEvent, &d->shapeError);

      d->xkbExtension = XkbQueryExtension(dpy,
                                                            &xkbOpcode,
                                                            &d->xkbEvent,
                                                            &d->xkbError, NULL, NULL);
      if (d->xkbExtension)
      {
            XkbSelectEvents(dpy,
                                    XkbUseCoreKbd,
                                    XkbBellNotifyMask | XkbStateNotifyMask,
                                    XkbAllEventsMask);
      }
      else
      {
            fprintf(stderr, _("%s: No XKB extension\n"), programName);

            d->xkbEvent = d->xkbError = -1;
      }

      d->xineramaExtension = XineramaQueryExtension(dpy,
                                                                          &d->xineramaEvent,
                                                                          &d->xineramaError);
      if (d->xineramaExtension)
      {
            d->screenInfo = XineramaQueryScreens(dpy, &d->nScreenInfo);
      }
      else
      {
            d->screenInfo = NULL;
            d->nScreenInfo = 0;
      }

      compDisplays = d;

      d->escapeKeyCode = XKeysymToKeycode(dpy, XStringToKeysym("Escape"));
      d->returnKeyCode = XKeysymToKeycode(dpy, XStringToKeysym("Return"));

      {
            XSetWindowAttributes attr;
            Atom atom;

            attr.override_redirect = TRUE;
            d->glIncludeInferiorsOwner =
                        XCreateWindow(dpy, XRootWindow(dpy, 0),
                                            -100, -100, 1, 1, 0,
                                            CopyFromParent, CopyFromParent,
                                            CopyFromParent, CWOverrideRedirect, &attr);

            atom = XInternAtom(dpy, "_COMPIZ_GL_INCLUDE_INFERIORS", False);
            XSetSelectionOwner(dpy, atom, d->glIncludeInferiorsOwner,
                                       CurrentTime);
      }

      if (screenNum >= ScreenCount(dpy))
      {
            fprintf(stderr,
                        _("%s: Screen %d on display \"%s\" does not "
                          "exist; defaulting to manage all existing screens.\n"),
                        programName, screenNum, DisplayString(dpy));
            screenNum = -1;
      }
      for (i = screenNum < 0 ? 0 : screenNum;
             i < (screenNum < 0 ? ScreenCount(dpy) : screenNum + 1); i++)
      {
            Window newWmSnOwner = None, newCmSnOwner = None;
            Atom wmSnAtom = 0, cmSnAtom = 0;
            Time wmSnTimestamp = 0;
            XEvent event;
            XSetWindowAttributes attr;
            Window currentWmSnOwner, currentCmSnOwner;
            char buf[128];
            Window rootDummy, childDummy;
            unsigned int uDummy;
            int x, y, dummy;

            sprintf(buf, "WM_S%d", i);
            wmSnAtom = XInternAtom(dpy, buf, 0);

            currentWmSnOwner = XGetSelectionOwner(dpy, wmSnAtom);

            if (currentWmSnOwner != None)
            {
                  if (!replaceCurrentWm)
                  {
                        fprintf(stderr,
                                    _
                                    ("%s: Screen %d on display \"%s\" already "
                                     "has a window manager; try using the "
                                     "--replace option to replace the current "
                                     "window manager.\n"), programName,
                                    i, DisplayString(dpy));

                        continue;
                  }

                  XSelectInput(dpy, currentWmSnOwner, StructureNotifyMask);
            }

            sprintf(buf, "_NET_WM_CM_S%d", i);
            cmSnAtom = XInternAtom(dpy, buf, 0);

            currentCmSnOwner = XGetSelectionOwner(dpy, cmSnAtom);

            if (currentCmSnOwner != None)
            {
                  if (!replaceCurrentWm)
                  {
                        fprintf(stderr,
                                    _
                                    ("%s: Screen %d on display \"%s\" already "
                                     "has a compositing manager; try using the "
                                     "--replace option to replace the current "
                                     "compositing manager .\n"),
                                    programName, i, DisplayString(dpy));

                        continue;
                  }
            }

            attr.override_redirect = TRUE;
            attr.event_mask = PropertyChangeMask;

            newCmSnOwner = newWmSnOwner =
                        XCreateWindow(dpy, XRootWindow(dpy, i),
                                            -100, -100, 1, 1, 0,
                                            CopyFromParent, CopyFromParent,
                                            CopyFromParent,
                                            CWOverrideRedirect | CWEventMask, &attr);

            XChangeProperty(dpy,
                                    newWmSnOwner,
                                    d->wmNameAtom,
                                    d->utf8StringAtom, 8,
                                    PropModeReplace,
                                    (unsigned char *)WMNAME, strlen(WMNAME));

            XWindowEvent(dpy, newWmSnOwner, PropertyChangeMask, &event);

            wmSnTimestamp = event.xproperty.time;

            XSetSelectionOwner(dpy, wmSnAtom, newWmSnOwner, wmSnTimestamp);

            if (XGetSelectionOwner(dpy, wmSnAtom) != newWmSnOwner)
            {
                  fprintf(stderr,
                              _("%s: Could not acquire window manager "
                                "selection on screen %d display \"%s\"\n"),
                              programName, i, DisplayString(dpy));

                  XDestroyWindow(dpy, newWmSnOwner);

                  continue;
            }

            /* Send client message indicating that we are now the WM */
            event.xclient.type = ClientMessage;
            event.xclient.window = XRootWindow(dpy, i);
            event.xclient.message_type = d->managerAtom;
            event.xclient.format = 32;
            event.xclient.data.l[0] = wmSnTimestamp;
            event.xclient.data.l[1] = wmSnAtom;
            event.xclient.data.l[2] = 0;
            event.xclient.data.l[3] = 0;
            event.xclient.data.l[4] = 0;

            XSendEvent(dpy, XRootWindow(dpy, i), FALSE,
                           StructureNotifyMask, &event);

            /* Wait for old window manager to go away */
            if (currentWmSnOwner != None)
            {
                  do
                  {
                        XWindowEvent(dpy, currentWmSnOwner,
                                           StructureNotifyMask, &event);
                  }
                  while (event.type != DestroyNotify);
            }

            compCheckForError(dpy);

            XCompositeRedirectSubwindows(dpy, XRootWindow(dpy, i),
                                                       CompositeRedirectManual);

            if (compCheckForError(dpy))
            {
                  fprintf(stderr,
                              _
                              ("%s: Another composite manager is already "
                               "running on screen: %d\n"), programName, i);

                  continue;
            }

            XSetSelectionOwner(dpy, cmSnAtom, newCmSnOwner, wmSnTimestamp);

            if (XGetSelectionOwner(dpy, cmSnAtom) != newCmSnOwner)
            {
                  fprintf(stderr,
                              _
                              ("%s: Could not acquire compositing manager "
                               "selection on screen %d display \"%s\"\n"),
                              programName, i, DisplayString(dpy));

                  continue;
            }

            XGrabServer(dpy);

            XSelectInput(dpy, XRootWindow(dpy, i),
                               SubstructureRedirectMask |
                               SubstructureNotifyMask |
                               StructureNotifyMask |
                               PropertyChangeMask |
                               LeaveWindowMask |
                               EnterWindowMask |
                               KeyPressMask |
                               KeyReleaseMask |
                               ButtonPressMask |
                               ButtonReleaseMask | FocusChangeMask | ExposureMask);

            if (compCheckForError(dpy))
            {
                  fprintf(stderr, _("%s: Another window manager is "
                                            "already running on screen: %d\n"),
                              programName, i);

                  XUngrabServer(dpy);
                  continue;
            }

            if (!addScreen(d, i, newWmSnOwner, wmSnAtom, wmSnTimestamp))
            {
                  fprintf(stderr,
                              _("%s: Failed to manage screen: %d\n"), programName, i);
            }

            if (XQueryPointer(dpy, XRootWindow(dpy, i),
                                      &rootDummy, &childDummy,
                                      &x, &y, &dummy, &dummy, &uDummy))
            {
                  d->lastPointerX = d->pointerX = x;
                  d->lastPointerY = d->pointerY = y;
            }

            XUngrabServer(dpy);
      }

      if (!d->screens)
      {
            fprintf(stderr,
                        _
                        ("%s: No manageable screens found on display %s\n"),
                        programName, XDisplayName(name));
            return FALSE;
      }

      setAudibleBell(d, d->opt[COMP_DISPLAY_OPTION_AUDIBLE_BELL].value.b);

      XGetInputFocus(dpy, &focus, &revertTo);

      if (focus == None || focus == PointerRoot)
      {
            focusDefaultWindow(d);
      }
      else
      {
            CompWindow *w;

            w = findWindowAtDisplay(d, focus);
            if (w)
            {
                  moveInputFocusToWindow(w);
            }
            else
                  focusDefaultWindow(d);
      }

      d->pingHandle = compAddTimeout(PING_DELAY, pingTimeout, d);

      if (!noShm)
      {
            d->shmInfo.shmid = shmget(IPC_PRIVATE, SHM_SIZE, IPC_CREAT | 0777);
            if (d->shmInfo.shmid < 0)
            {
                  fprintf(stderr, _("%s: Error int SHM creation\n"), programName);
                  noShm = TRUE;
                  return TRUE;
            }

            d->shmInfo.shmaddr = (char *)shmat(d->shmInfo.shmid, 0, 0);
            if (d->shmInfo.shmaddr == ((char *)-1))
            {
                  shmctl(d->shmInfo.shmid, IPC_RMID, 0);
                  fprintf(stderr, _("%s: Error int SHM creation\n"), programName);
                  noShm = TRUE;
                  return TRUE;
            }
            d->shmInfo.readOnly = False;

            XShmAttach(dpy, &d->shmInfo);
      }
      CompOption *option;
      int nOption;
      nOption=0;
      option = compGetDisplayOptions(d, &nOption);
      while (nOption--)
      {
            CompOptionValue value;
            memcpy ( &value, &option->value, sizeof(CompOptionValue));
            if (beryl_settings_context_comp_get_option_value(d->context,NULL,option->name,FALSE,&value))
            {
                  d->setDisplayOption(d,option->name,&value);
            }
            option++;
      }

      d->on_shutdown = FALSE;

      return TRUE;
}

Time getCurrentTimeFromDisplay(CompDisplay * d)
{
      XEvent event;

      XChangeProperty(d->display, d->screens->grabWindow,
                              XA_PRIMARY, XA_STRING, 8, PropModeAppend, NULL, 0);
      XWindowEvent(d->display, d->screens->grabWindow,
                         PropertyChangeMask, &event);

      return event.xproperty.time;
}

void focusDefaultWindow(CompDisplay * d)
{
      CompScreen *s;
      CompWindow *w;
      CompWindow *focus = NULL;

      for (s = d->screens; s; s = s->next)
      {
            for (w = s->reverseWindows; w; w = w->prev)
            {
                  if ((w->type & CompWindowTypeDockMask) ||
                        (w->state & CompWindowStateNoFocusMask))
                        continue;

                  if ((*s->focusWindow) (w))
                  {
                        if (focus)
                        {
                              if (w->
                                    type &
                                    (CompWindowTypeNormalMask |
                                     CompWindowTypeDialogMask |
                                     CompWindowTypeModalDialogMask))
                              {
                                    if (w->activeNum >
                                          focus->activeNum
                                          && !w->state & CompWindowStateStickyMask)
                                          focus = w;
                              }
                        }
                        else
                              focus = w;
                  }
            }
      }

      if (focus)
      {
            if (focus->id != d->activeWindow)
                  moveInputFocusToWindow(focus);
      }
      else
      {
            XSetInputFocus(d->display, d->screens->root,
                                 RevertToPointerRoot, CurrentTime);
      }
}

CompScreen *findScreenAtDisplay(CompDisplay * d, Window root)
{
      CompScreen *s;

      for (s = d->screens; s; s = s->next)
      {
            if (s->root == root)
                  return s;
      }

      return 0;
}

void
forEachWindowOnDisplay(CompDisplay * display,
                                 ForEachWindowProc proc, void *closure)
{
      CompScreen *s;

      for (s = display->screens; s; s = s->next)
            forEachWindowOnScreen(s, proc, closure);
}

CompWindow *findWindowAtDisplay(CompDisplay * d, Window id)
{
      if (lastFoundWindow && lastFoundWindow->id == id)
      {
            return lastFoundWindow;
      }
      else
      {
            CompScreen *s;
            CompWindow *w;

            for (s = d->screens; s; s = s->next)
            {
                  w = findWindowAtScreen(s, id);
                  if (w)
                        return w;
            }
      }

      return 0;
}

CompWindow *findTopLevelWindowAtDisplay(CompDisplay * d, Window id)
{
      if (lastFoundWindow && lastFoundWindow->id == id)
      {
            return lastFoundWindow;
      }
      else
      {
            CompScreen *s;
            CompWindow *w;

            for (s = d->screens; s; s = s->next)
            {
                  w = findTopLevelWindowAtScreen(s, id);
                  if (w)
                        return w;
            }
      }

      return 0;
}


void reload_all(CompDisplay *d)
{
      CompOption *dispOption;
      CompOption *scrnOption;
      CompOption *plugOption;
      CompOption * o;
      CompOptionValue value;
      int nDispOption;
      int nScrnOption;
      int nPlugOption;
      CompPlugin *p;
      int indx;
      beryl_settings_context_read(d->context);

      puts("Reloading options");

      if (beryl_settings_context_get_if_plugins_changed(d->context))
            d->dirtyPluginList=True;

      nDispOption=0;
      dispOption=compGetDisplayOptions(d, &nDispOption);
      nScrnOption=0;
      scrnOption=compGetScreenOptions(d->screens, &nScrnOption);
      GSList * l = beryl_settings_context_get_settings_changed(d->context);
      for(;l;l=l->next)
      {
            BerylSetting * s = l->data;
            BerylSettingsPlugin * bsp = beryl_setting_get_plugin(s);
            gchar * n;
            n = (gchar *) beryl_settings_plugin_get_name(bsp);
            if (!n)
            {
                  gchar * n = (gchar *) beryl_setting_get_name(s);
                  if (!s->is_screen && (o = compFindOption(dispOption,nDispOption,n,&indx)))
                  {
                        memcpy(&value, &o->value, sizeof(CompOptionValue));
                        if (beryl_settings_context_comp_get_option_value(d->context,NULL,o->name,FALSE,&value))
                              d->setDisplayOption(d, o->name, &value);
                  }
                  else if (s->is_screen && (o = compFindOption(scrnOption,nScrnOption,n,&indx)))
                  {
                        memcpy(&value, &o->value, sizeof(CompOptionValue));
                        if (beryl_settings_context_comp_get_option_value(d->context,NULL,o->name,TRUE,&value))
                              d->screens->setScreenOption(d->screens, o->name, &value);
                  }
            }
            else if ((p=findActivePlugin(n)))
            {
                  gchar * n = (gchar *) beryl_setting_get_name(s);
                  nPlugOption=0;
                  if (!s->is_screen && p->vTable->getDisplayOptions)
                  {
                        plugOption=p->vTable->getDisplayOptions(d,&nPlugOption);
                        if ((o = compFindOption(plugOption,nPlugOption,n,&indx)))
                        {
                              memcpy(&value,&o->value,sizeof(CompOptionValue));
                              if (beryl_settings_context_comp_get_option_value(d->context,p->vTable->name,o->name,FALSE,&value))
                                    d->setDisplayOptionForPlugin(d,p->vTable->name,o->name,&value);
                        }
                  }
                  else if (s->is_screen && p->vTable->getScreenOptions)
                  {
                        plugOption=p->vTable->getScreenOptions(d->screens,&nPlugOption);
                        if ((o = compFindOption(plugOption,nPlugOption,n,&indx)))
                        {
                              memcpy(&value,&o->value,sizeof(CompOptionValue));
                              if (beryl_settings_context_comp_get_option_value(d->context,p->vTable->name,o->name,TRUE,&value))
                                    d->screens->setScreenOptionForPlugin(d->screens,p->vTable->name,o->name,&value);
                        }
                  }
            }
      }
}

void reload_setting(BerylSettingsContext *c)
{
      CompDisplay *d = (CompDisplay *)c->private_ptr;
      if (!d)
            return;

      CompOption *dispOption;
      CompOption *scrnOption;
      CompOption *plugOption;
      CompOption * o;
      CompOptionValue value;
      int nDispOption;
      int nScrnOption;
      int nPlugOption;
      CompPlugin *p;
      CompScreen *scr;
      int indx;

      puts("Reloading option");

      if (beryl_settings_context_get_if_plugins_changed(d->context))
            d->dirtyPluginList=True;

      nDispOption=0;
      dispOption=compGetDisplayOptions(d, &nDispOption);
      nScrnOption=0;
      scrnOption=compGetScreenOptions(d->screens, &nScrnOption);
      GSList * l = beryl_settings_context_get_settings_changed(d->context);
      for(;l;l=l->next)
      {
            BerylSetting * s = l->data;
            BerylSettingsPlugin * bsp = beryl_setting_get_plugin(s);
            gchar * n;
            n = (gchar *) beryl_settings_plugin_get_name(bsp);
            if (!n)
            {
                  gchar * n = (gchar *) beryl_setting_get_name(s);
                  if (!s->is_screen && (o = compFindOption(dispOption,nDispOption,n,&indx)))
                  {
                        memcpy(&value, &o->value, sizeof(CompOptionValue));
                        if (beryl_settings_context_comp_get_option_value(d->context,NULL,o->name,FALSE,&value))
                              d->setDisplayOption(d, o->name, &value);
                  }
                  else if (s->is_screen && (o = compFindOption(scrnOption,nScrnOption,n,&indx)))
                  {
                        memcpy(&value, &o->value, sizeof(CompOptionValue));
                        if (beryl_settings_context_comp_get_option_value(d->context,NULL,o->name,TRUE,&value))
                              for (scr = d->screens; scr; scr = scr->next)
                                    scr->setScreenOption(scr, o->name, &value);
                  }
            }
            else if ((p=findActivePlugin(n)))
            {
                  gchar * n = (gchar *) beryl_setting_get_name(s);
                  nPlugOption=0;
                  if (!s->is_screen && p->vTable->getDisplayOptions)
                  {
                        plugOption=p->vTable->getDisplayOptions(d,&nPlugOption);
                        if ((o = compFindOption(plugOption,nPlugOption,n,&indx)))
                        {
                              memcpy(&value,&o->value,sizeof(CompOptionValue));
                              if (beryl_settings_context_comp_get_option_value(d->context,p->vTable->name,o->name,FALSE,&value))
                                    d->setDisplayOptionForPlugin(d,p->vTable->name,o->name,&value);
                        }
                  }
                  else if (s->is_screen && p->vTable->getScreenOptions)
                  {
                        plugOption=p->vTable->getScreenOptions(d->screens,&nPlugOption);
                        if ((o = compFindOption(plugOption,nPlugOption,n,&indx)))
                        {
                              memcpy(&value,&o->value,sizeof(CompOptionValue));
                              if (beryl_settings_context_comp_get_option_value(d->context,p->vTable->name,o->name,TRUE,&value))
                                    for (scr = d->screens; scr; scr = scr->next)
                                          scr->setScreenOptionForPlugin(scr,p->vTable->name,o->name,&value);
                        }
                  }
            }
      }
}

static CompScreen *findScreenForSelection(CompDisplay * display,
                                                              Window owner, Atom selection)
{
      CompScreen *s;

      for (s = display->screens; s; s = s->next)
      {
            if (s->wmSnSelectionWindow == owner && s->wmSnAtom == selection)
                  return s;
      }

      return NULL;
}

/* from fvwm2, Copyright Matthias Clasen, Dominik Vogt */
static Bool
convertProperty(CompDisplay * display,
                        CompScreen * screen, Window w, Atom target, Atom property)
{

#define N_TARGETS 4

      Atom conversionTargets[N_TARGETS];
      long icccmVersion[] = { 2, 0 };

      conversionTargets[0] = display->targetsAtom;
      conversionTargets[1] = display->multipleAtom;
      conversionTargets[2] = display->timestampAtom;
      conversionTargets[3] = display->versionAtom;

      if (target == display->targetsAtom)
            XChangeProperty(display->display, w, property,
                                    XA_ATOM, 32, PropModeReplace,
                                    (unsigned char *)conversionTargets, N_TARGETS);
      else if (target == display->timestampAtom)
            XChangeProperty(display->display, w, property,
                                    XA_INTEGER, 32, PropModeReplace,
                                    (unsigned char *)&screen->wmSnTimestamp, 1);
      else if (target == display->versionAtom)
            XChangeProperty(display->display, w, property,
                                    XA_INTEGER, 32, PropModeReplace,
                                    (unsigned char *)icccmVersion, 2);
      else
            return FALSE;

      /* Be sure the PropertyNotify has arrived so we
       * can send SelectionNotify
       */
      XSync(display->display, FALSE);

      return TRUE;
}

/* from fvwm2, Copyright Matthias Clasen, Dominik Vogt */
void handleSelectionRequest(CompDisplay * display, XEvent * event)
{
      XSelectionEvent reply;
      CompScreen *screen;

      screen = findScreenForSelection(display,
                                                      event->xselectionrequest.owner,
                                                      event->xselectionrequest.selection);
      if (!screen)
            return;

      reply.type = SelectionNotify;
      reply.display = display->display;
      reply.requestor = event->xselectionrequest.requestor;
      reply.selection = event->xselectionrequest.selection;
      reply.target = event->xselectionrequest.target;
      reply.property = None;
      reply.time = event->xselectionrequest.time;

      if (event->xselectionrequest.target == display->multipleAtom)
      {
            if (event->xselectionrequest.property != None)
            {
                  Atom type, *adata;
                  int i, format;
                  unsigned long num, rest;
                  unsigned char *data;

                  if (XGetWindowProperty(display->display,
                                                   event->xselectionrequest.
                                                   requestor,
                                                   event->xselectionrequest.
                                                   property, 0, 256, FALSE,
                                                   display->atomPairAtom,
                                                   &type, &format, &num, &rest,
                                                   &data) != Success)
                        return;

                  /* FIXME: to be 100% correct, should deal with rest > 0,
                   * but since we have 4 possible targets, we will hardly ever
                   * meet multiple requests with a length > 8
                   */
                  adata = (Atom *) data;
                  i = 0;
                  while (i < (int)num)
                  {
                        if (!convertProperty(display, screen,
                                                       event->
                                                       xselectionrequest.
                                                       requestor, adata[i], adata[i + 1]))
                              adata[i + 1] = None;

                        i += 2;
                  }

                  XChangeProperty(display->display,
                                          event->xselectionrequest.requestor,
                                          event->xselectionrequest.property,
                                          display->atomPairAtom,
                                          32, PropModeReplace, data, num);
            }
      }
      else
      {
            if (event->xselectionrequest.property == None)
                  event->xselectionrequest.property =
                              event->xselectionrequest.target;

            if (convertProperty(display, screen,
                                          event->xselectionrequest.requestor,
                                          event->xselectionrequest.target,
                                          event->xselectionrequest.property))
                  reply.property = event->xselectionrequest.property;
      }

      XSendEvent(display->display,
                     event->xselectionrequest.requestor,
                     FALSE, 0L, (XEvent *) & reply);
}

void handleSelectionClear(CompDisplay * display, XEvent * event)
{
      /* We need to unmanage the screen on which we lost the selection */
      CompScreen *screen;

      screen = findScreenForSelection(display,
                                                      event->xselectionclear.window,
                                                      event->xselectionclear.selection);

      if (screen)
            shutDown = TRUE;
}

void warpPointer(CompDisplay * display, int dx, int dy)
{
      CompScreen *s = display->screens;
      XEvent event;

      display->pointerX += dx;
      display->pointerY += dy;

      if (display->pointerX >= s->width)
            display->pointerX = s->width - 1;
      else if (display->pointerX < 0)
            display->pointerX = 0;

      if (display->pointerY >= s->height)
            display->pointerY = s->height - 1;
      else if (display->pointerY < 0)
            display->pointerY = 0;

      XWarpPointer(display->display,
                         None, s->root, 0, 0, 0, 0, display->pointerX,
                         display->pointerY);

      XSync(display->display, FALSE);

      while (XCheckMaskEvent(display->display,
                                       LeaveWindowMask |
                                       EnterWindowMask | PointerMotionMask, &event));

      if (!inHandleEvent)
      {
            display->lastPointerX = display->pointerX;
            display->lastPointerY = display->pointerY;
      }
}

Bool
setDisplayAction(CompDisplay * display,
                         CompOption * o, CompOptionValue * value)
{
      CompScreen *s;

      for (s = display->screens; s; s = s->next)
            removeScreenAction(s, &o->value.action);

      for (s = display->screens; s; s = s->next)
            addScreenAction(s, &value->action);
      //        break;

      /*    if (s)
         {
         CompScreen *failed = s;

         for (s = display->screens; s && s != failed; s = s->next)
         removeScreenAction (s, &value->action);
         for (s = display->screens; s; s = s->next)
         addScreenAction (s, &o->value.action);
         printf ("Couldn't set %s\n",o->name);

         return FALSE;
         } */

      if (compSetActionOption(o, value))
            return TRUE;

      return FALSE;
}

void clearTargetOutput(CompDisplay * display, unsigned int mask)
{
      if (targetScreen)
            clearScreenOutput(targetScreen, targetOutput, mask);
}

#define HOME_IMAGEDIR ".beryl/images"

Bool
readImageFromFile(CompDisplay * display,
                          const char *name, int *width, int *height, void **data)
{
      Bool status;
      int stride;

      status = (*display->fileToImage) (display, NULL, name, width, height,
                                                        &stride, data);
      if (!status)
      {
            char *home;

            home = getenv("HOME");
            if (home)
            {
                  char *path;

                  path = malloc(strlen(home) + strlen(HOME_IMAGEDIR) + 2);
                  if (path)
                  {
                        sprintf(path, "%s/%s", home, HOME_IMAGEDIR);
                        status = (*display->fileToImage) (display, path, name,
                                                                          width, height, &stride,
                                                                          data);

                        free(path);

                        if (status)
                              return TRUE;
                  }
            }

            status = (*display->fileToImage) (display, IMAGEDIR, name,
                                                              width, height, &stride, data);
      }

      return status;
}

Bool
writeImageToFile(CompDisplay * display,
                         const char *path,
                         const char *name,
                         const char *format, int width, int height, void *data)
{
      return (*display->imageToFile) (display, path, name, format, width,
                                                      height, width * 4, data);
}

Bool
fileToImage(CompDisplay * display,
                  const char *path,
                  const char *name,
                  int *width, int *height, int *stride, void **data)
{
      return FALSE;
}

Bool
imageToFile(CompDisplay * display,
                  const char *path,
                  const char *name,
                  const char *format, int width, int height, int stride, void *data)
{
      return FALSE;
}

Generated by  Doxygen 1.6.0   Back to index