#include "group.h" /** * * Beryl group plugin * * paint.c * * Copyright : (C) 2006 by Patrick Niklaus, Roi Cohen, Danny Baumann * Authors: Patrick Niklaus * Roi Cohen * Danny Baumann * * * 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; }