#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;
}
syntax highlighted by Code2HTML, v. 0.9.1