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

paint.c

#include "group.h"

/**
 *
 * Beryl group plugin
 *
 * paint.c
 *
 * Copyright : (C) 2006 by Patrick Niklaus, Roi Cohen, Danny Baumann
 * Authors: Patrick Niklaus <patrick.niklaus@googlemail.com>
 *          Roi Cohen       <roico@beryl-project.org>
 *          Danny Baumann   <maniac@beryl-project.org>
 *
 *
 * 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.
 *
 **/

/*
 * groupPaintThumb - taken from switcher and modified for tab bar
 *
 */
void groupPaintThumb(GroupSelection *group, GroupTabBarSlot *slot, int targetOpacity)
{
      DrawWindowGeometryProc oldDrawWindowGeometry;
      AddWindowGeometryProc oldAddWindowGeometry;

      CompWindow *w = slot->window;
      
      GROUP_SCREEN(w->screen);

      int tw, th;
      tw = slot->region->extents.x2 - slot->region->extents.x1;
      th = slot->region->extents.y2 - slot->region->extents.y1;

      /* Wrap drawWindowGeometry to make sure the general
         drawWindowGeometry function is used */
      oldDrawWindowGeometry = w->screen->drawWindowGeometry;
      w->screen->drawWindowGeometry = getBaseDrawWindowGeometry();
      oldAddWindowGeometry = w->screen->addWindowGeometry;
      w->screen->addWindowGeometry = getBaseAddWindowGeometry();
      
      WindowPaintAttrib sAttrib = w->paint;

      // animate fade
      if (group && group->tabBar->state == PaintFadeIn)
            sAttrib.opacity -= sAttrib.opacity * group->tabBar->animationTime / 
                           (gs->opt[GROUP_SCREEN_OPTION_FADE_TIME].value.f * 1000);
      else if (group && group->tabBar->state == PaintFadeOut)
            sAttrib.opacity = sAttrib.opacity * group->tabBar->animationTime / 
                          (gs->opt[GROUP_SCREEN_OPTION_FADE_TIME].value.f * 1000);

      sAttrib.opacity = sAttrib.opacity * targetOpacity / 0xffff;

      if (w->mapNum) {

            if (WIN_WIDTH(w) > tw)
                  sAttrib.xScale = (float) tw / WIN_WIDTH(w);
            else
                  sAttrib.xScale = 1.0f;

            if (WIN_HEIGHT(w) > th)
                  sAttrib.yScale = (float) tw / WIN_HEIGHT(w);
            else
                  sAttrib.yScale = 1.0f;

            if (sAttrib.xScale < sAttrib.yScale)
                  sAttrib.yScale = sAttrib.xScale;
            else
                  sAttrib.xScale = sAttrib.yScale;

            int vx, vy;
            groupGetDrawOffsetForSlot(slot, &vx, &vy);

            sAttrib.xTranslate = slot->region->extents.x1 - w->attrib.x + vx;
            sAttrib.yTranslate = slot->region->extents.y1 - w->attrib.y + vy;

            (w->screen->drawWindow) (w, &sAttrib, getInfiniteRegion(),
                  PAINT_WINDOW_TRANSFORMED_MASK);

            addWindowDamage(w);
      }
      
      w->screen->drawWindowGeometry = oldDrawWindowGeometry;
      w->screen->addWindowGeometry = oldAddWindowGeometry;
}

/*
 * groupRenderTopTabHighlight
 *
 */
void groupRenderTopTabHighlight(GroupSelection *group)
{
      GroupTabBar *bar;
      GroupCairoLayer *layer;
      cairo_t *cr;

      if (!group->tabBar || !HAS_TOP_WIN(group) || !group->tabBar->selectionLayer || !group->tabBar->selectionLayer->cairo)
          return;

      bar = group->tabBar;

      int width = group->topTab->region->extents.x2 - group->topTab->region->extents.x1 + 10;
      int height = group->topTab->region->extents.y2 - group->topTab->region->extents.y1 + 10;

      bar->selectionLayer = groupRebuildCairoLayer(group->screen, bar->selectionLayer, width, height);
      layer = bar->selectionLayer;
      cr = layer->cairo;

      layer->texWidth = width;
      layer->texHeight = height;
      
      // fill
      cairo_set_line_width(cr, 2);
      cairo_set_source_rgba(cr, 
            (group->color[0] / 65535.0f),
            (group->color[1] / 65535.0f),
            (group->color[2] / 65535.0f),
            (group->color[3] / (65535.0f*2)));

      cairo_move_to(cr, 0, 0);
      cairo_rectangle(cr, 0, 0, width, height);
      
      // fill
      cairo_fill_preserve(cr);

      // outline
      cairo_set_source_rgba(cr, 
            (group->color[0] / 65535.0f),
            (group->color[1] / 65535.0f),
            (group->color[2] / 65535.0f),
            (group->color[3] / 65535.0f));
      cairo_stroke(cr);

      imageToTexture(group->screen, &layer->texture, (char*) layer->texBuf, width, height);
}

/*
 * groupRenderTabBarBackground
 *
 */
void groupRenderTabBarBackground(GroupSelection *group)
{
      GROUP_SCREEN(group->screen);
      GroupTabBar *bar;
      GroupCairoLayer *layer;
      cairo_t *cr;

      if (!group->tabBar || !HAS_TOP_WIN(group) || !group->tabBar->bgLayer || !group->tabBar->bgLayer->cairo)
          return;

      bar = group->tabBar;

      int x, y, width, height, radius;
      width = bar->region->extents.x2 - bar->region->extents.x1;
      height = bar->region->extents.y2 - bar->region->extents.y1;
      radius = gs->opt[GROUP_SCREEN_OPTION_BORDER_RADIUS].value.i;
      x = 0;
      y = 0;

      bar->bgLayer = groupRebuildCairoLayer(group->screen, bar->bgLayer, width, height);
      layer = bar->bgLayer;
      cr = layer->cairo;

      layer->texWidth = width;
      layer->texHeight = height;
      
      float r, g, b, a;

      cairo_set_line_width(cr, 2);

      cairo_move_to(cr, 0, 0);
      cairo_move_to (cr, x + radius, y);
      cairo_arc (cr, x + width - radius, y + radius, radius, M_PI * 1.5, M_PI * 2.0);
      cairo_arc (cr, x + width - radius, y + height - radius, radius, 0.0, M_PI * 0.5);
      cairo_arc (cr, x + radius, y + height - radius, radius, M_PI * 0.5, M_PI);
      cairo_arc (cr, x + radius, y + radius, radius, M_PI, M_PI * 1.5);

      // fill
      r = gs->opt[GROUP_SCREEN_OPTION_TAB_FILL_COLOR].value.c[0] / 65535.0f;
      g = gs->opt[GROUP_SCREEN_OPTION_TAB_FILL_COLOR].value.c[1] / 65535.0f;
      b = gs->opt[GROUP_SCREEN_OPTION_TAB_FILL_COLOR].value.c[2] / 65535.0f;
      a = gs->opt[GROUP_SCREEN_OPTION_TAB_FILL_COLOR].value.c[3] / 65535.0f;
      cairo_set_source_rgba(cr, r, g, b, a);
      cairo_fill_preserve(cr);

      // outline
      r = gs->opt[GROUP_SCREEN_OPTION_TAB_BORDER_COLOR].value.c[0] / 65535.0f;
      g = gs->opt[GROUP_SCREEN_OPTION_TAB_BORDER_COLOR].value.c[1] / 65535.0f;
      b = gs->opt[GROUP_SCREEN_OPTION_TAB_BORDER_COLOR].value.c[2] / 65535.0f;
      a = gs->opt[GROUP_SCREEN_OPTION_TAB_BORDER_COLOR].value.c[3] / 65535.0f;
      cairo_set_source_rgba(cr, r, g, b, a);
      cairo_stroke(cr);

      imageToTexture(group->screen, &layer->texture, (char*) layer->texBuf, width, height);
}

/*
 * groupRenderWindowTitle
 *
 */
void groupRenderWindowTitle(GroupSelection *group)
{
      GROUP_SCREEN(group->screen);
      GroupTabBar *bar;
      GroupCairoLayer *layer;
      char *title;

      if (!group->tabBar || !HAS_TOP_WIN(group) || !group->tabBar->textLayer)
          return;

      bar = group->tabBar;

      int width = bar->region->extents.x2 - bar->region->extents.x1;
      int height = bar->region->extents.y2 - bar->region->extents.y1;

      bar->textLayer = groupRebuildCairoLayer(group->screen, bar->textLayer, width, height);
      layer = bar->textLayer;

      int font_size = gs->opt[GROUP_SCREEN_OPTION_TABBAR_FONTSIZE].value.i;
      
      if (bar->textSlot && bar->textSlot->name)
            title = bar->textSlot->name;
      else
            title = " ";

      CompTextAttrib text_attrib;
      text_attrib.family = "Sans";
      text_attrib.size = font_size;
      text_attrib.style = TEXT_STYLE_BOLD;
      text_attrib.color[0] = gs->opt[GROUP_SCREEN_OPTION_TABBAR_FONTCOLOR].value.c[0];
      text_attrib.color[1] = gs->opt[GROUP_SCREEN_OPTION_TABBAR_FONTCOLOR].value.c[1];
      text_attrib.color[2] = gs->opt[GROUP_SCREEN_OPTION_TABBAR_FONTCOLOR].value.c[2];
      text_attrib.color[3] = gs->opt[GROUP_SCREEN_OPTION_TABBAR_FONTCOLOR].value.c[3];
      text_attrib.ellipsize = TRUE;

      text_attrib.maxwidth = width;
      text_attrib.maxheight = height;
      text_attrib.screen = group->screen;
      text_attrib.text = title;

      void *data = NULL;
      int stride;

      if (!((*group->screen->display->fileToImage)(group->screen->display, "TextToPixmap", 
                              (const char*) &text_attrib, &width, 
                              &height, &stride, &data))) {
            /* getting the pixmap failed, so create an empty one */
            Pixmap emptyPixmap = XCreatePixmap(group->screen->display->display, 
                        group->screen->root, width, height, 32);

            if (emptyPixmap) {
                  XGCValues gcv;
                  gcv.foreground = 0x00000000;
                  gcv.plane_mask = 0xffffffff;

                  GC gc = XCreateGC(group->screen->display->display, emptyPixmap, 
                              GCForeground, &gcv);

                  XFillRectangle(group->screen->display->display, emptyPixmap, gc, 
                              0, 0, width, height);

                  XFreeGC(group->screen->display->display, gc);

                  data = (void*) emptyPixmap;
            }
      }

      layer->texWidth = width;
      layer->texHeight = height;
      layer->pixmap = (Pixmap) data;

      if(data)
            bindPixmapToTexture(group->screen, &layer->texture, (Pixmap) data, width, height, 32);
}

/*
 * groupPaintTabBar
 *
 */
void groupPaintTabBar(GroupSelection * group, const WindowPaintAttrib *wAttrib, Region clipRegion)
{
      if (!group || !HAS_TOP_WIN(group) || !group->tabBar || (group->tabBar->state == PaintOff))
            return;

      CompWindow *topTab = TOP_TAB(group);
      CompScreen *s = group->screen;
      GroupTabBarSlot *slot;
      GroupTabBar *bar = group->tabBar;

      GROUP_SCREEN(s);

      /* we do not want to paint the tab bar if we currently rotate the screen */
      if (gs->isRotating)
            return;

      int i;
      int alpha;
      float w_scale;
      float h_scale;
      GroupCairoLayer *layer;

      REGION box;

      /* make sure we get the core drawWindowGeometry function */
      DrawWindowGeometryProc oldDrawWindowGeometry = s->drawWindowGeometry;
      s->drawWindowGeometry = getBaseDrawWindowGeometry();
      
      WindowPaintAttrib attrib = *wAttrib;
      attrib.opacity = OPAQUE;
      attrib.saturation = COLOR;
      attrib.brightness = BRIGHT;

#define PAINT_BG    0
#define PAINT_SEL   1
#define PAINT_TEXT  2
#define PAINT_MAX   3

      box.rects = &box.extents;
      box.numRects = 1;

      glEnable(GL_BLEND);
      glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

      for (i = 0; i < PAINT_MAX; i++) {
            alpha = 0xffff;

            if (bar->state == PaintFadeIn) 
                  alpha -= alpha * bar->animationTime /
                        (gs->opt[GROUP_SCREEN_OPTION_FADE_TIME].value.f * 1000);
            else if (bar->state == PaintFadeOut) 
                  alpha = alpha * bar->animationTime /
                        (gs->opt[GROUP_SCREEN_OPTION_FADE_TIME].value.f * 1000);

            switch (i) {
                  case PAINT_BG:
                        layer = bar->bgLayer;

                        h_scale = 1.0f;
                        w_scale = (double)(bar->region->extents.x2 - bar->region->extents.x1) / 
                              (double)(layer->texWidth);

                        box.extents = bar->region->extents;
                  break;
                  case PAINT_SEL:
                        if (group->topTab != gs->draggedSlot) {
                              layer = bar->selectionLayer;

                              h_scale = 1.0f;
                              w_scale = 1.0f;

                              box.extents.x1 = group->topTab->region->extents.x1 - 5;
                              box.extents.x2 = group->topTab->region->extents.x2 + 5;
                              box.extents.y1 = group->topTab->region->extents.y1 - 5;
                              box.extents.y2 = group->topTab->region->extents.y2 + 5;
                        } else
                              layer = NULL;
                  break;
                  case PAINT_TEXT:
                        if (bar->textLayer->state != PaintOff) {
                              layer = bar->textLayer;
                              
                              h_scale = 1.0f;
                              w_scale = 1.0f;

                              box.extents.x1 = bar->region->extents.x1 + 5;
                              box.extents.x2 = bar->region->extents.x1 + bar->textLayer->texWidth + 5;
                              box.extents.y1 = bar->region->extents.y2 - bar->textLayer->texHeight - 5;
                              box.extents.y2 = bar->region->extents.y2 - 5;

                              if (box.extents.x2 > bar->region->extents.x2)
                                    box.extents.x2 = bar->region->extents.x2;

                              // recalculate the alpha again...
                              if (bar->textLayer->state == PaintFadeIn) 
                                    alpha -= alpha * bar->textLayer->animationTime /
                                          (gs->opt[GROUP_SCREEN_OPTION_FADE_TEXT_TIME].value.f * 1000);
                              else if (group->tabBar->textLayer->state == PaintFadeOut) 
                                    alpha = alpha * bar->textLayer->animationTime /
                                          (gs->opt[GROUP_SCREEN_OPTION_FADE_TEXT_TIME].value.f * 1000);
                        } else
                              layer = NULL;
                  break;
                  default:
                        layer = NULL;
                        w_scale = 1.0f;
                        h_scale = 1.0f;
                  break;
            }

            if (layer) {
                  CompMatrix matrix = layer->texture.matrix;

                  // remove the old x1 and y1 so we have a relative value
                  box.extents.x2 -= box.extents.x1;
                  box.extents.y2 -= box.extents.y1;
                  box.extents.x1 = (box.extents.x1 - topTab->attrib.x) / w_scale + topTab->attrib.x;
                  box.extents.y1 = (box.extents.y1 - topTab->attrib.y) / h_scale + topTab->attrib.y;
                  // now add the new x1 and y1 so we have a absolute value again,
                  // also we don't want to stretch the texture...
                  if (box.extents.x2*w_scale < layer->texWidth)
                        box.extents.x2 += box.extents.x1;
                  else
                        box.extents.x2 = box.extents.x1 + layer->texWidth;
                  if (box.extents.y2*h_scale < layer->texHeight)
                        box.extents.y2 += box.extents.y1;
                  else 
                        box.extents.y2 = box.extents.y1 + layer->texHeight;
                  

                  matrix.x0 -= box.extents.x1 * matrix.xx;
                  matrix.y0 -= box.extents.y1 * matrix.yy;

                  attrib.xScale = w_scale;
                  attrib.yScale = h_scale;

                  topTab->vCount = 0;

                  addWindowGeometry(topTab, &matrix, 1, &box, clipRegion);

                  alpha = alpha * wAttrib->opacity / 0xffff;

                  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
                  glColor4us(alpha, alpha, alpha, alpha);

                  (*group->screen->drawWindowTexture) (topTab, 
                        &layer->texture, &attrib,
                        PAINT_WINDOW_TRANSLUCENT_MASK | PAINT_WINDOW_TRANSFORMED_MASK);

                  screenTexEnvMode (s, GL_REPLACE);
                  glColor4usv(defaultColor);
            }
      }

      s->drawWindowGeometry = oldDrawWindowGeometry;

      glColor4usv(defaultColor);
      glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
      glDisable(GL_BLEND);

      // draw thumbs
      GLenum oldTextureFilter = s->display->textureFilter;

      if (gs->opt[GROUP_SCREEN_OPTION_TAB_CREATE_MIPMAPS].value.b)
            s->display->textureFilter = GL_LINEAR_MIPMAP_LINEAR;

      for(slot = bar->slots; slot; slot = slot->next)
      {
            if(slot != gs->draggedSlot || !gs->dragged)
                  groupPaintThumb(group, slot, wAttrib->opacity);
      }

      s->display->textureFilter = oldTextureFilter;
}

/*
 * groupPaintSelectionOutline
 *
 */
static void
groupPaintSelectionOutline (CompScreen *s, const ScreenPaintAttrib *sa, 
                      int output, Bool transformed)
{
      GROUP_SCREEN(s);

      int x1, x2, y1, y2;

      x1 = MIN(gs->x1, gs->x2);
      y1 = MIN(gs->y1, gs->y2);
      x2 = MAX(gs->x1, gs->x2);
      y2 = MAX(gs->y1, gs->y2);

      if (gs->grabState == ScreenGrabSelect) {
            glPushMatrix();

            if (transformed) {
                  glLoadIdentity();
                  (s->applyScreenTransform) (s, sa, output);
                  prepareXCoords(s, output, -sa->zTranslate);
            } else
                  prepareXCoords(s, output, -DEFAULT_Z_CAMERA);

            glDisableClientState(GL_TEXTURE_COORD_ARRAY);
            glEnable(GL_BLEND);

            glColor4usv(gs->opt[GROUP_SCREEN_OPTION_SELECTION_COLOR].value.c);
            glRecti(x1, y2, x2, y1);

            glLineWidth(3);
            glEnable(GL_LINE_SMOOTH);
            glColor4usv(gs->opt[GROUP_SCREEN_OPTION_LINE_COLOR].value.c);
            glBegin(GL_LINE_LOOP);
            glVertex2i(x1, y1);
            glVertex2i(x2, y1);
            glVertex2i(x2, y2);
            glVertex2i(x1, y2);
            glEnd();
            glDisable(GL_LINE_SMOOTH);
            glLineWidth(1); // back to default

            glColor4usv(defaultColor);
            glDisable(GL_BLEND);
            glEnableClientState(GL_TEXTURE_COORD_ARRAY);
            glPopMatrix();
      }
}

/*
 * groupPreparePaintScreen
 *
 */
void groupPreparePaintScreen(CompScreen * s, int msSinceLastPaint)
{
      GROUP_SCREEN(s);
      GroupSelection *group;

      UNWRAP(gs, s, preparePaintScreen);
      (*s->preparePaintScreen) (s, msSinceLastPaint);
      WRAP(gs, s, preparePaintScreen, groupPreparePaintScreen);

      for (group = gs->groups; group; group = group->next)
      {
            GroupTabBar *bar = group->tabBar;
      
            if (group->changeState != PaintOff)
                  group->changeAnimationTime -= msSinceLastPaint;

            if (!bar)
                  continue;
      
            groupApplyForces(s, bar, (gs->dragged)? gs->draggedSlot: NULL);
            groupApplySpeeds(s, bar, msSinceLastPaint);

            groupHandleHoverDetection(group);
            groupHandleTabBarFade(group, msSinceLastPaint);
            groupHandleTextFade(group, msSinceLastPaint);
      }
      
      groupHandleChanges(s);
      groupDrawTabAnimation(s, msSinceLastPaint);

      groupDequeueMoveNotifies (s);
      groupDequeueGrabNotifies (s);
      groupDequeueUngrabNotifies (s);
}

/*
 * groupPaintScreen
 *
 */
Bool
groupPaintScreen(CompScreen * s,
             const ScreenPaintAttrib * sAttrib,
             Region region, int output, unsigned int mask)
{
      GROUP_SCREEN(s);
      GroupSelection *group;
      Bool status;

      gs->painted = FALSE;
      gs->vpX = s->x;
      gs->vpY = s->y;

      for (group = gs->groups; group; group = group->next)
      {
            if (group->changeState != PaintOff)
                  mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS_MASK;
      }

      if (gs->tabBarVisible) 
                  mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS_MASK;

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

      gs->isRotating = FALSE;
      
      if (status && !gs->painted) {
            if ((gs->grabState == ScreenGrabTabDrag) && gs->draggedSlot) {
                  GROUP_WINDOW(gs->draggedSlot->window);
                  
                  glPushMatrix();
                  prepareXCoords(s, output, -DEFAULT_Z_CAMERA);
            
                  // prevent tab bar drawing..
                  PaintState state = gw->group->tabBar->state;
                  gw->group->tabBar->state = PaintOff;
                  groupPaintThumb(NULL, gs->draggedSlot, 0xffff);
                  gw->group->tabBar->state = state;

                  glPopMatrix();
            } else  if (gs->grabState == ScreenGrabSelect) {
                  groupPaintSelectionOutline (s, sAttrib, output, FALSE);
            }
      }
      
      return status;
}

/*
 * groupaintTransformedScreen
 *
 */
void
groupPaintTransformedScreen(CompScreen * s, const ScreenPaintAttrib * sa,
                      Region region, int output, unsigned int mask)
{
      GROUP_SCREEN(s);

      gs->isRotating = ((fmod(sa->xRotate, 90.0) != 0.0) || (fmod(sa->yRotate, 90.0) != 0.0) || 
                  (fmod(sa->vRotate, 90.0) != 0.0));

      UNWRAP(gs, s, paintTransformedScreen);
      (*s->paintTransformedScreen) (s, sa, region, output, mask);
      WRAP(gs, s, paintTransformedScreen, groupPaintTransformedScreen);
      
      if ((gs->vpX == s->x) && (gs->vpY == s->y)) {
            gs->painted = TRUE;

            if ((gs->grabState == ScreenGrabTabDrag) && gs->draggedSlot && gs->dragged) {
                  glPushMatrix();
      
                  glLoadIdentity();
                  (s->applyScreenTransform) (s, sa, output);
                  prepareXCoords(s, output, -sa->zTranslate);
            
                  groupPaintThumb(NULL, gs->draggedSlot, 0xffff);
      
                  glPopMatrix();
            } else if (gs->grabState == ScreenGrabSelect) {
                  groupPaintSelectionOutline (s, sa, output, TRUE);
            }
      }
}

void groupRecomputeGlow (CompScreen *s)
{
      GROUP_SCREEN(s);
      CompWindow *w;

      for (w = s->windows; w; w = w->next)
            groupComputeGlowQuads (w, &gs->glowTexture.matrix);
}

/*
 * groupDonePaintScreen
 *
 */
void groupDonePaintScreen(CompScreen * s)
{
      GROUP_SCREEN(s);
      GroupSelection *group;

      UNWRAP(gs, s, donePaintScreen);
      (*s->donePaintScreen) (s);
      WRAP(gs, s, donePaintScreen, groupDonePaintScreen);

      for(group = gs->groups; group; group = group->next)
      {
            if (group->doTabbing)
                  damageScreen(s);

            if (group->changeState != PaintOff)
                  damageScreen(s);

            if (group->tabBar && group->tabBar->state != PaintOff)
                  damageScreenRegion(s, group->tabBar->region);
      }
}

void
groupComputeGlowQuads (CompWindow *w, CompMatrix *matrix)
{
      GROUP_WINDOW(w);
      GROUP_SCREEN(w->screen);

      BoxRec *box;
      CompMatrix *quadMatrix;

      if (gs->opt[GROUP_SCREEN_OPTION_GLOW].value.b && matrix) {
            if (!gw->glowQuads)
                  gw->glowQuads = malloc (NUM_GLOWQUADS * sizeof(GlowQuad));
            if (!gw->glowQuads)
                  return;
      } else {
            if (gw->glowQuads) {
                  free (gw->glowQuads);
                  gw->glowQuads = NULL;
            }
            return;
      }

      int glowSize = gs->opt[GROUP_SCREEN_OPTION_GLOW_SIZE].value.i;
      int glowOffset = (glowSize * glowTextureProperties[gs->glowType].glowOffset /
                  glowTextureProperties[gs->glowType].textureSize) + 1; 

      /* Top left corner */
      box = &gw->glowQuads[GLOWQUAD_TOPLEFT].box;
      gw->glowQuads[GLOWQUAD_TOPLEFT].matrix = *matrix;
      quadMatrix = &gw->glowQuads[GLOWQUAD_TOPLEFT].matrix;

      box->x1 = WIN_REAL_X(w) - glowSize + glowOffset;
      box->y1 = WIN_REAL_Y(w) - glowSize + glowOffset;
      box->x2 = WIN_REAL_X(w) + glowOffset;
      box->y2 = WIN_REAL_Y(w) + glowOffset;

      quadMatrix->xx = 1.0f / glowSize;
      quadMatrix->yy = -1.0f / glowSize;
      quadMatrix->x0 = -(box->x1 * quadMatrix->xx);
      quadMatrix->y0 = 1.0 -(box->y1 * quadMatrix->yy);

      box->x2 = MIN(WIN_REAL_X(w) + glowOffset, WIN_REAL_X(w) + (WIN_REAL_WIDTH(w) / 2));
      box->y2 = MIN(WIN_REAL_Y(w) + glowOffset, WIN_REAL_Y(w) + (WIN_REAL_HEIGHT(w) / 2));

      /* Top right corner */
      box = &gw->glowQuads[GLOWQUAD_TOPRIGHT].box;
      gw->glowQuads[GLOWQUAD_TOPRIGHT].matrix = *matrix;
      quadMatrix = &gw->glowQuads[GLOWQUAD_TOPRIGHT].matrix;

      box->x1 = WIN_REAL_X(w) + WIN_REAL_WIDTH(w) - glowOffset;
      box->y1 = WIN_REAL_Y(w) - glowSize + glowOffset;
      box->x2 = WIN_REAL_X(w) + WIN_REAL_WIDTH(w) + glowSize - glowOffset;
      box->y2 = WIN_REAL_Y(w) + glowOffset;

      quadMatrix->xx = -1.0f / glowSize;
      quadMatrix->yy = -1.0f / glowSize;
      quadMatrix->x0 = 1.0 - (box->x1 * quadMatrix->xx);
      quadMatrix->y0 = 1.0 - (box->y1 * quadMatrix->yy);

      box->x1 = MAX(WIN_REAL_X(w) + WIN_REAL_WIDTH(w) - glowOffset, 
            WIN_REAL_X(w) + (WIN_REAL_WIDTH(w) / 2));
      box->y2 = MIN(WIN_REAL_Y(w) + glowOffset, 
            WIN_REAL_Y(w) + (WIN_REAL_HEIGHT(w) / 2));

      /* Bottom left corner */
      box = &gw->glowQuads[GLOWQUAD_BOTTOMLEFT].box;
      gw->glowQuads[GLOWQUAD_BOTTOMLEFT].matrix = *matrix;
      quadMatrix = &gw->glowQuads[GLOWQUAD_BOTTOMLEFT].matrix;

      box->x1 = WIN_REAL_X(w) - glowSize + glowOffset;
      box->y1 = WIN_REAL_Y(w) + WIN_REAL_HEIGHT(w) - glowOffset;
      box->x2 = WIN_REAL_X(w) + glowOffset;
      box->y2 = WIN_REAL_Y(w) + WIN_REAL_HEIGHT(w) + glowSize - glowOffset;

      quadMatrix->xx = 1.0f / glowSize;
      quadMatrix->yy = 1.0f / glowSize;
      quadMatrix->x0 = -(box->x1 * quadMatrix->xx);
      quadMatrix->y0 = -(box->y1 * quadMatrix->yy);

      box->y1 = MAX(WIN_REAL_Y(w) + WIN_REAL_HEIGHT(w) - glowOffset,
            WIN_REAL_Y(w) + (WIN_REAL_HEIGHT(w) / 2));
      box->x2 = MIN(WIN_REAL_X(w) + glowOffset, 
            WIN_REAL_X(w) + (WIN_REAL_WIDTH(w) / 2));

      /* Bottom right corner */
      box = &gw->glowQuads[GLOWQUAD_BOTTOMRIGHT].box;
      gw->glowQuads[GLOWQUAD_BOTTOMRIGHT].matrix = *matrix;
      quadMatrix = &gw->glowQuads[GLOWQUAD_BOTTOMRIGHT].matrix;

      box->x1 = WIN_REAL_X(w) + WIN_REAL_WIDTH(w) - glowOffset;
      box->y1 = WIN_REAL_Y(w) + WIN_REAL_HEIGHT(w) - glowOffset;
      box->x2 = WIN_REAL_X(w) + WIN_REAL_WIDTH(w) + glowSize - glowOffset;
      box->y2 = WIN_REAL_Y(w) + WIN_REAL_HEIGHT(w) + glowSize - glowOffset;

      quadMatrix->xx = -1.0f / glowSize;
      quadMatrix->yy = 1.0f / glowSize;
      quadMatrix->x0 = 1.0 - (box->x1 * quadMatrix->xx);
      quadMatrix->y0 = -(box->y1 * quadMatrix->yy);

      box->x1 = MAX(WIN_REAL_X(w) + WIN_REAL_WIDTH(w) - glowOffset, 
            WIN_REAL_X(w) + (WIN_REAL_WIDTH(w) / 2));
      box->y1 = MAX(WIN_REAL_Y(w) + WIN_REAL_HEIGHT(w) - glowOffset,
            WIN_REAL_Y(w) + (WIN_REAL_HEIGHT(w) / 2));

      /* Top edge */
      box = &gw->glowQuads[GLOWQUAD_TOP].box;
      gw->glowQuads[GLOWQUAD_TOP].matrix = *matrix;
      quadMatrix = &gw->glowQuads[GLOWQUAD_TOP].matrix;

      box->x1 = WIN_REAL_X(w) + glowOffset;
      box->y1 = WIN_REAL_Y(w) - glowSize + glowOffset;
      box->x2 = WIN_REAL_X(w) + WIN_REAL_WIDTH(w) - glowOffset;
      box->y2 = WIN_REAL_Y(w) + glowOffset;

      quadMatrix->xx = 0.0f;
      quadMatrix->yy = -1.0f / glowSize;
      quadMatrix->x0 = 1.0;
      quadMatrix->y0 = 1.0 - (box->y1 * quadMatrix->yy);

      /* Bottom edge */
      box = &gw->glowQuads[GLOWQUAD_BOTTOM].box;
      gw->glowQuads[GLOWQUAD_BOTTOM].matrix = *matrix;
      quadMatrix = &gw->glowQuads[GLOWQUAD_BOTTOM].matrix;

      box->x1 = WIN_REAL_X(w) + glowOffset;
      box->y1 = WIN_REAL_Y(w) + WIN_REAL_HEIGHT(w) - glowOffset;
      box->x2 = WIN_REAL_X(w) + WIN_REAL_WIDTH(w) - glowOffset;
      box->y2 = WIN_REAL_Y(w) + WIN_REAL_HEIGHT(w) + glowSize - glowOffset;

      quadMatrix->xx = 0.0f;
      quadMatrix->yy = 1.0f / glowSize;
      quadMatrix->x0 = 1.0;
      quadMatrix->y0 = -(box->y1 * quadMatrix->yy);

      /* Left edge */
      box = &gw->glowQuads[GLOWQUAD_LEFT].box;
      gw->glowQuads[GLOWQUAD_LEFT].matrix = *matrix;
      quadMatrix = &gw->glowQuads[GLOWQUAD_LEFT].matrix;

      box->x1 = WIN_REAL_X(w) - glowSize + glowOffset;
      box->y1 = WIN_REAL_Y(w) + glowOffset;
      box->x2 = WIN_REAL_X(w) + glowOffset;
      box->y2 = WIN_REAL_Y(w) + WIN_REAL_HEIGHT(w) - glowOffset;

      quadMatrix->xx = 1.0f / glowSize;
      quadMatrix->yy = 0.0f;
      quadMatrix->x0 = -(box->x1 * quadMatrix->xx);
      quadMatrix->y0 = 0.0;

      /* Right edge */
      box = &gw->glowQuads[GLOWQUAD_RIGHT].box;
      gw->glowQuads[GLOWQUAD_RIGHT].matrix = *matrix;
      quadMatrix = &gw->glowQuads[GLOWQUAD_RIGHT].matrix;

      box->x1 = WIN_REAL_X(w) + WIN_REAL_WIDTH(w) - glowOffset;
      box->y1 = WIN_REAL_Y(w) + glowOffset;
      box->x2 = WIN_REAL_X(w) + WIN_REAL_WIDTH(w) + glowSize - glowOffset;
      box->y2 = WIN_REAL_Y(w) + WIN_REAL_HEIGHT(w) - glowOffset;

      quadMatrix->xx = -1.0f / glowSize;
      quadMatrix->yy = 0.0f;
      quadMatrix->x0 = 1.0 - (box->x1 * quadMatrix->xx);
      quadMatrix->y0 = 0.0;
}

/*
 * groupDrawWindow
 *
 */
Bool
groupDrawWindow(CompWindow * w,
            const WindowPaintAttrib * attrib,
            Region region, unsigned int mask)
{
      Bool status;
      GROUP_WINDOW(w);
      GROUP_SCREEN(w->screen);
      
      if (!(mask & PAINT_WINDOW_SOLID_MASK) && gw->group && gw->group->nWins > 1 && gw->glowQuads) {
            if (mask & PAINT_WINDOW_TRANSFORMED_MASK)
                  region = getInfiniteRegion();

            if (region->numRects) {
                  REGION box;
                  int i;

                  box.rects = &box.extents;
                  box.numRects = 1;

                  w->vCount = 0;

                  for (i = 0; i < NUM_GLOWQUADS; i++) {
                        box.extents = gw->glowQuads[i].box;

                        if (box.extents.x1 < box.extents.x2 &&
                            box.extents.y1 < box.extents.y2) {
                              (*w->screen->addWindowGeometry) (w, 
                                    &gw->glowQuads[i].matrix, 1, &box, region);
                        }
                  }

                  if (w->vCount) {
                        WindowPaintAttrib wAttrib = *attrib;

                        wAttrib.opacity = OPAQUE;
                        wAttrib.saturation = COLOR;
                        wAttrib.brightness = BRIGHT;

                        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
                        //glBlendFunc(GL_SRC_ALPHA, GL_ONE); - maybe add an option for that...
                        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
                        glColor4us(gw->group->color[0], gw->group->color[1],
                              gw->group->color[2], attrib->opacity);

                        /* we use PAINT_WINDOW_TRANSFORMED_MASK here to force
                           the usage of a good texture filter */
                        (*w->screen->drawWindowTexture) (w, &gs->glowTexture, &wAttrib,
                              mask | PAINT_WINDOW_TRANSLUCENT_MASK | 
                              PAINT_WINDOW_TRANSFORMED_MASK | PAINT_WINDOW_DECORATION_MASK);

                        glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
                        screenTexEnvMode (w->screen, GL_REPLACE);
                        glColor4usv(defaultColor);
                  }
            }
      }
      
      UNWRAP(gs, w->screen, drawWindow);
      status = (*w->screen->drawWindow) (w, attrib, region, mask);
      WRAP(gs, w->screen, drawWindow, groupDrawWindow);
      
      return status;
}

/*
 * groupPaintWindow
 *
 */
Bool
groupPaintWindow(CompWindow * w,
            const WindowPaintAttrib * attrib,
            Region region, unsigned int mask)
{
      Bool status;
      Bool doRotate;
      GROUP_SCREEN(w->screen);
      GROUP_WINDOW(w);

      WindowPaintAttrib gAttrib = *attrib;

      if (gw->inSelection) {
            int opacity = gs->opt[GROUP_SCREEN_OPTION_OPACITY].value.i;
            int saturation = gs->opt[GROUP_SCREEN_OPTION_SATURATION].value.i;
            int brightness = gs->opt[GROUP_SCREEN_OPTION_BRIGHTNESS].value.i;

            opacity = OPAQUE * opacity / 100;
            saturation = COLOR * saturation / 100;
            brightness = BRIGHT * brightness / 100;

            gAttrib.opacity = opacity;
            gAttrib.saturation = saturation;
            gAttrib.brightness = brightness;
      } else if (gw->group && gw->group->tabbingState != PaintOff &&
            (gw->animateState & (IS_ANIMATED | FINISHED_ANIMATION))) {
            //fade the window out 
            float opacity;
            
            int origDistanceX = (gw->orgPos.x - gw->destination.x);
            int origDistanceY = (gw->orgPos.y - gw->destination.y);
            float origDistance = sqrt(pow(origDistanceX, 2) + pow(origDistanceY,2));
            
            float distanceX = (WIN_X(w) - gw->destination.x);
            float distanceY = (WIN_Y(w) - gw->destination.y);
            float distance = sqrt(pow(distanceX, 2) + pow(distanceY, 2));
            
            if(distance > origDistance) 
                  opacity = 100.0f;
            else {
                  if(!origDistanceX && !origDistanceY) {
                        if (IS_TOP_TAB(w, gw->group) && (gw->group->tabbingState == PaintFadeIn)) 
                              opacity = 100.0f;
                        else
                              opacity = 0.0f;
                  } else 
                        opacity = 100.0f * distance / origDistance;

                  if (gw->group->tabbingState == PaintFadeOut) 
                        opacity = 100.0f - opacity;
            }

            gAttrib.opacity = gAttrib.opacity * opacity / 100; 
      }            

      doRotate = gw->group && (gw->group->changeState != PaintOff) &&
            (IS_TOP_TAB(w, gw->group) || IS_PREV_TOP_TAB(w, gw->group));

      if (doRotate)
      {
            float rotateAngle;
            float timeLeft = gw->group->changeAnimationTime;
            
            if(gw->group->changeState == PaintFadeIn)
                  timeLeft += gs->opt[GROUP_SCREEN_OPTION_CHANGE_ANIMATION_TIME].value.f * 500.0f;
            
            rotateAngle = timeLeft * 180.0f / (gs->opt[GROUP_SCREEN_OPTION_CHANGE_ANIMATION_TIME].value.f * 1000.0f);
            if (IS_PREV_TOP_TAB(w, gw->group))
                  rotateAngle += 180.0f;

            if (gw->group->changeAnimationDirection < 0)
                  rotateAngle *= -1.0f;

            glPushMatrix();
            
            glScalef(1.0f, 1.0f, 1.0f / w->screen->width);
            
            glTranslatef(WIN_X(w) + WIN_WIDTH(w)/2.0f, 0.0f, 0.0f);
            glRotatef(rotateAngle, 0.0f, 1.0f, 0.0f);
            glTranslatef(-WIN_X(w) - WIN_WIDTH(w)/2.0f, 0.0f, 0.0f);
            mask |= PAINT_WINDOW_TRANSFORMED_MASK;
      }

      UNWRAP(gs, w->screen, paintWindow);
      
      status = (*w->screen->paintWindow) (w, &gAttrib, region, mask);
      
      if (gw->group && gw->group->tabBar) {
            if (HAS_TOP_WIN(gw->group) && IS_TOP_TAB(w, gw->group)) {
                  if ((gw->group->changeState == PaintOff) || (gw->group->changeState == PaintFadeOut)) 
                        groupPaintTabBar(gw->group, attrib, region);
            } else if (IS_PREV_TOP_TAB(w, gw->group)) {
                  if (gw->group->changeState == PaintFadeIn)
                        groupPaintTabBar(gw->group, attrib, region);
            }
      }

      WRAP(gs, w->screen, paintWindow, groupPaintWindow);
      
      if(doRotate)
            glPopMatrix();

      return status;
}

Generated by  Doxygen 1.6.0   Back to index