Exemple #1
0
/*
 * SelectionLayer::render
 *
 * Renders the group color highlight behind the active tab using cairo
 *
 */
void
SelectionLayer::render ()
{
    cairo_t         *cr;

    if (!HAS_TOP_WIN (mGroup) || !mCairo)
	return;

    cr = mCairo;

    /* fill */
    cairo_set_line_width (cr, 2);
    cairo_set_source_rgba (cr,
			   (mGroup->mColor[0] / 65535.0f),
			   (mGroup->mColor[1] / 65535.0f),
			   (mGroup->mColor[2] / 65535.0f),
			   (mGroup->mColor[3] / (65535.0f * 2)));

    cairo_move_to (cr, 0, 0);
    cairo_rectangle (cr, 0, 0, width (), height ());

    cairo_fill_preserve (cr);

    /* outline */
    cairo_set_source_rgba (cr,
			   (mGroup->mColor[0] / 65535.0f),
			   (mGroup->mColor[1] / 65535.0f),
			   (mGroup->mColor[2] / 65535.0f),
			   (mGroup->mColor[3] / 65535.0f));
    cairo_stroke (cr);

    mTexture = GLTexture::imageBufferToTexture ((char*) mBuffer,
			 		  (CompSize &) *this);
}
/*
 * groupRenderTopTabHighlight
 *
 */
void
groupRenderTopTabHighlight (GroupSelection *group)
{
    GroupTabBar     *bar = group->tabBar;
    GroupCairoLayer *layer;
    cairo_t         *cr;
    int             width, height;

    if (!bar || !HAS_TOP_WIN (group) ||
	!bar->selectionLayer || !bar->selectionLayer->cairo)
    {
	return;
    }

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

    bar->selectionLayer = groupRebuildCairoLayer (group->screen,
						  bar->selectionLayer,
						  width, height);
    if (!bar->selectionLayer)
	return;

    layer = bar->selectionLayer;
    cr = bar->selectionLayer->cairo;

    /* 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);

    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);

    imageBufferToTexture (group->screen,
			  &layer->texture, (char*) layer->buffer,
			  layer->texWidth, layer->texHeight);
}
Exemple #3
0
/*
 * groupPreparePaintScreen
 *
 */
void
groupPreparePaintScreen (CompScreen *s,
                         int        msSinceLastPaint)
{
	GroupSelection *group, *next;

	GROUP_SCREEN (s);

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

	group = gs->groups;
	while (group)
	{
		GroupTabBar *bar = group->tabBar;

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

			if ((bar->state != PaintOff) && HAS_TOP_WIN (group))
				groupHandleHoverDetection (group);

			if (bar->state == PaintFadeIn || bar->state == PaintFadeOut)
				groupHandleTabBarFade (group, msSinceLastPaint);

			if (bar->textLayer)
				groupHandleTextFade (group, msSinceLastPaint);

			if (bar->bgAnimation)
				groupHandleTabBarAnimation (group, msSinceLastPaint);
		}

		if (group->changeState != NoTabChange)
		{
			group->changeAnimationTime -= msSinceLastPaint;
			if (group->changeAnimationTime <= 0)
				groupHandleAnimation (group);
		}

		/* groupDrawTabAnimation may delete the group, so better
		   save the pointer to the next chain element */
		next = group->next;

		if (group->tabbingState != NoTabbing)
			groupDrawTabAnimation (group, msSinceLastPaint);

		group = next;
	}
}
/*
 * groupRenderWindowTitle
 *
 */
void
groupRenderWindowTitle (GroupSelection *group)
{
    GroupCairoLayer *layer;
    int             width, height;
    Pixmap          pixmap = None;
    CompScreen      *s = group->screen;
    CompDisplay     *d = s->display;
    GroupTabBar     *bar = group->tabBar;

    GROUP_DISPLAY (d);

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

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

    bar->textLayer = groupRebuildCairoLayer (s, bar->textLayer, width, height);
    layer = bar->textLayer;
    if (!layer)
	return;

    if (bar->textSlot && bar->textSlot->window && gd->textFunc)
    {
	CompTextData    *data;
	CompTextAttrib  textAttrib;

	textAttrib.family = groupGetTabbarFontFamily(s);
	textAttrib.size   = groupGetTabbarFontSize (s);

	textAttrib.flags = CompTextFlagStyleBold | CompTextFlagEllipsized |
	                   CompTextFlagNoAutoBinding;

	textAttrib.color[0] = groupGetTabbarFontColorRed (s);
	textAttrib.color[1] = groupGetTabbarFontColorGreen (s);
	textAttrib.color[2] = groupGetTabbarFontColorBlue (s);
	textAttrib.color[3] = groupGetTabbarFontColorAlpha (s);

	textAttrib.maxWidth = width;
	textAttrib.maxHeight = height;

	data = (gd->textFunc->renderWindowTitle) (s, bar->textSlot->window->id,
						  FALSE, &textAttrib);
	if (data)
	{
	    pixmap = data->pixmap;
	    width = data->width;
	    height = data->height;
	    free (data);
	}
    }

    if (!pixmap)
    {
	/* getting the pixmap failed, so create an empty one */
	pixmap = XCreatePixmap (d->display, s->root, width, height, 32);

	if (pixmap)
	{
	    XGCValues gcv;
	    GC        gc;

	    gcv.foreground = 0x00000000;
	    gcv.plane_mask = 0xffffffff;

	    gc = XCreateGC (d->display, pixmap, GCForeground, &gcv);
	    XFillRectangle (d->display, pixmap, gc, 0, 0, width, height);
	    XFreeGC (d->display, gc);
	}
    }

    layer->texWidth = width;
    layer->texHeight = height;

    if (pixmap)
    {
	layer->pixmap = pixmap;
	bindPixmapToTexture (s, &layer->texture, layer->pixmap,
			     layer->texWidth, layer->texHeight, 32);
    }
}
/*
 * groupRenderTabBarBackground
 *
 */
void
groupRenderTabBarBackground(GroupSelection *group)
{
    GroupCairoLayer *layer;
    cairo_t         *cr;
    int             width, height, radius;
    int             borderWidth;
    float           r, g, b, a;
    double          x0, y0, x1, y1;
    CompScreen      *s = group->screen;
    GroupTabBar     *bar = group->tabBar;

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

    width = bar->region->extents.x2 - bar->region->extents.x1;
    height = bar->region->extents.y2 - bar->region->extents.y1;
    radius = groupGetBorderRadius (s);

    if (width > bar->bgLayer->texWidth)
	width = bar->bgLayer->texWidth;

    if (radius > width / 2)
	radius = width / 2;

    layer = bar->bgLayer;
    cr = layer->cairo;

    groupClearCairoLayer (layer);

    borderWidth = groupGetBorderWidth (s);
    cairo_set_line_width (cr, borderWidth);

    cairo_save (cr);

    x0 = borderWidth / 2.0f;
    y0 = borderWidth / 2.0f;
    x1 = width  - borderWidth / 2.0f;
    y1 = height - borderWidth / 2.0f;
    cairo_move_to (cr, x0 + radius, y0);
    cairo_arc (cr, x1 - radius, y0 + radius, radius, M_PI * 1.5, M_PI * 2.0);
    cairo_arc (cr, x1 - radius, y1 - radius, radius, 0.0, M_PI * 0.5);
    cairo_arc (cr, x0 + radius, y1 - radius, radius, M_PI * 0.5, M_PI);
    cairo_arc (cr, x0 + radius, y0 + radius, radius, M_PI, M_PI * 1.5);

    cairo_close_path  (cr);

    switch (groupGetTabStyle (s)) {
    case TabStyleSimple:
	{
	    /* base color */
	    r = groupGetTabBaseColorRed (s) / 65535.0f;
	    g = groupGetTabBaseColorGreen (s) / 65535.0f;
	    b = groupGetTabBaseColorBlue (s) / 65535.0f;
	    a = groupGetTabBaseColorAlpha (s) / 65535.0f;
	    cairo_set_source_rgba (cr, r, g, b, a);

    	    cairo_fill_preserve (cr);
	    break;
	}

    case TabStyleGradient:
	{
	    /* fill */
	    cairo_pattern_t *pattern;
	    pattern = cairo_pattern_create_linear (0, 0, width, height);

	    /* highlight color */
	    r = groupGetTabHighlightColorRed (s) / 65535.0f;
	    g = groupGetTabHighlightColorGreen (s) / 65535.0f;
	    b = groupGetTabHighlightColorBlue (s) / 65535.0f;
	    a = groupGetTabHighlightColorAlpha (s) / 65535.0f;
	    cairo_pattern_add_color_stop_rgba (pattern, 0.0f, r, g, b, a);

	    /* base color */
	    r = groupGetTabBaseColorRed (s) / 65535.0f;
	    g = groupGetTabBaseColorGreen (s) / 65535.0f;
	    b = groupGetTabBaseColorBlue (s) / 65535.0f;
	    a = groupGetTabBaseColorAlpha (s) / 65535.0f;
	    cairo_pattern_add_color_stop_rgba (pattern, 1.0f, r, g, b, a);

	    cairo_set_source (cr, pattern);
	    cairo_fill_preserve (cr);
	    cairo_pattern_destroy (pattern);
	    break;
	}

    case TabStyleGlass:
	{
	    cairo_pattern_t *pattern;

	    cairo_save (cr);

	    /* clip width rounded rectangle */
	    cairo_clip (cr);

	    /* ===== HIGHLIGHT ===== */

	    /* make draw the shape for the highlight and
	       create a pattern for it */
	    cairo_rectangle (cr, 0, 0, width, height / 2);
	    pattern = cairo_pattern_create_linear (0, 0, 0, height);

	    /* highlight color */
	    r = groupGetTabHighlightColorRed (s) / 65535.0f;
	    g = groupGetTabHighlightColorGreen (s) / 65535.0f;
	    b = groupGetTabHighlightColorBlue (s) / 65535.0f;
	    a = groupGetTabHighlightColorAlpha (s) / 65535.0f;
	    cairo_pattern_add_color_stop_rgba (pattern, 0.0f, r, g, b, a);

	    /* base color */
	    r = groupGetTabBaseColorRed (s) / 65535.0f;
	    g = groupGetTabBaseColorGreen (s) / 65535.0f;
	    b = groupGetTabBaseColorBlue (s) / 65535.0f;
	    a = groupGetTabBaseColorAlpha (s) / 65535.0f;
	    cairo_pattern_add_color_stop_rgba (pattern, 0.6f, r, g, b, a);

	    cairo_set_source (cr, pattern);
	    cairo_fill (cr);
	    cairo_pattern_destroy (pattern);

	    /* ==== SHADOW ===== */

	    /* make draw the shape for the show and create a pattern for it */
	    cairo_rectangle (cr, 0, height / 2, width, height);
	    pattern = cairo_pattern_create_linear (0, 0, 0, height);

	    /* we don't want to use a full highlight here
	       so we mix the colors */
	    r = (groupGetTabHighlightColorRed (s) +
		 groupGetTabBaseColorRed (s)) / (2 * 65535.0f);
	    g = (groupGetTabHighlightColorGreen (s) +
		 groupGetTabBaseColorGreen (s)) / (2 * 65535.0f);
	    b = (groupGetTabHighlightColorBlue (s) +
		 groupGetTabBaseColorBlue (s)) / (2 * 65535.0f);
	    a = (groupGetTabHighlightColorAlpha (s) +
		 groupGetTabBaseColorAlpha (s)) / (2 * 65535.0f);
	    cairo_pattern_add_color_stop_rgba (pattern, 1.0f, r, g, b, a);

	    /* base color */
	    r = groupGetTabBaseColorRed (s) / 65535.0f;
	    g = groupGetTabBaseColorGreen (s) / 65535.0f;
	    b = groupGetTabBaseColorBlue (s) / 65535.0f;
	    a = groupGetTabBaseColorAlpha (s) / 65535.0f;
	    cairo_pattern_add_color_stop_rgba (pattern, 0.5f, r, g, b, a);

	    cairo_set_source (cr, pattern);
	    cairo_fill (cr);
	    cairo_pattern_destroy (pattern);

	    cairo_restore (cr);

	    /* draw shape again for the outline */
	    cairo_move_to (cr, x0 + radius, y0);
	    cairo_arc (cr, x1 - radius, y0 + radius,
		       radius, M_PI * 1.5, M_PI * 2.0);
	    cairo_arc (cr, x1 - radius, y1 - radius,
		       radius, 0.0, M_PI * 0.5);
	    cairo_arc (cr, x0 + radius, y1 - radius,
		       radius, M_PI * 0.5, M_PI);
	    cairo_arc (cr, x0 + radius, y0 + radius,
		       radius, M_PI, M_PI * 1.5);

	    break;
	}

    case TabStyleMetal:
	{
	    /* fill */
	    cairo_pattern_t *pattern;
	    pattern = cairo_pattern_create_linear (0, 0, 0, height);

	    /* base color #1 */
	    r = groupGetTabBaseColorRed (s) / 65535.0f;
	    g = groupGetTabBaseColorGreen (s) / 65535.0f;
	    b = groupGetTabBaseColorBlue (s) / 65535.0f;
	    a = groupGetTabBaseColorAlpha (s) / 65535.0f;
	    cairo_pattern_add_color_stop_rgba (pattern, 0.0f, r, g, b, a);

	    /* highlight color */
	    r = groupGetTabHighlightColorRed (s) / 65535.0f;
	    g = groupGetTabHighlightColorGreen (s) / 65535.0f;
	    b = groupGetTabHighlightColorBlue (s) / 65535.0f;
	    a = groupGetTabHighlightColorAlpha (s) / 65535.0f;
	    cairo_pattern_add_color_stop_rgba (pattern, 0.55f, r, g, b, a);

	    /* base color #2 */
	    r = groupGetTabBaseColorRed (s) / 65535.0f;
	    g = groupGetTabBaseColorGreen (s) / 65535.0f;
	    b = groupGetTabBaseColorBlue (s) / 65535.0f;
	    a = groupGetTabBaseColorAlpha (s) / 65535.0f;
	    cairo_pattern_add_color_stop_rgba (pattern, 1.0f, r, g, b, a);

	    cairo_set_source (cr, pattern);
	    cairo_fill_preserve (cr);
	    cairo_pattern_destroy (pattern);
	    break;
	}

    case TabStyleMurrina:
	{
	    double          ratio, transX;
	    cairo_pattern_t *pattern;

	    cairo_save (cr);

	    /* clip width rounded rectangle */
	    cairo_clip_preserve (cr);

	    /* ==== TOP ==== */

	    x0 = borderWidth / 2.0;
	    y0 = borderWidth / 2.0;
	    x1 = width  - borderWidth / 2.0;
	    y1 = height - borderWidth / 2.0;
	    radius = (y1 - y0) / 2;

	    /* setup pattern */
	    pattern = cairo_pattern_create_linear (0, 0, 0, height);

	    /* we don't want to use a full highlight here
	       so we mix the colors */
	    r = (groupGetTabHighlightColorRed (s) +
		 groupGetTabBaseColorRed (s)) / (2 * 65535.0f);
	    g = (groupGetTabHighlightColorGreen (s) +
		 groupGetTabBaseColorGreen (s)) / (2 * 65535.0f);
	    b = (groupGetTabHighlightColorBlue (s) +
		 groupGetTabBaseColorBlue (s)) / (2 * 65535.0f);
	    a = (groupGetTabHighlightColorAlpha (s) +
		 groupGetTabBaseColorAlpha (s)) / (2 * 65535.0f);
	    cairo_pattern_add_color_stop_rgba (pattern, 0.0f, r, g, b, a);

	    /* highlight color */
	    r = groupGetTabHighlightColorRed (s) / 65535.0f;
	    g = groupGetTabHighlightColorGreen (s) / 65535.0f;
	    b = groupGetTabHighlightColorBlue (s) / 65535.0f;
	    a = groupGetTabHighlightColorAlpha (s) / 65535.0f;
	    cairo_pattern_add_color_stop_rgba (pattern, 1.0f, r, g, b, a);

	    cairo_set_source (cr, pattern);

	    cairo_fill (cr);
	    cairo_pattern_destroy (pattern);

	    /* ==== BOTTOM ===== */

	    x0 = borderWidth / 2.0;
	    y0 = borderWidth / 2.0;
	    x1 = width  - borderWidth / 2.0;
	    y1 = height - borderWidth / 2.0;
	    radius = (y1 - y0) / 2;

	    ratio = (double)width / (double)height;
	    transX = width - (width * ratio);

	    cairo_move_to (cr, x1, y1);
	    cairo_line_to (cr, x1, y0);
	    if (width < height)
	    {
		cairo_translate (cr, transX, 0);
		cairo_scale (cr, ratio, 1.0);
	    }
	    cairo_arc (cr, x1 - radius, y0, radius, 0.0, M_PI * 0.5);
	    if (width < height)
	    {
		cairo_scale (cr, 1.0 / ratio, 1.0);
		cairo_translate (cr, -transX, 0);
		cairo_scale (cr, ratio, 1.0);
	    }
	    cairo_arc_negative (cr, x0 + radius, y1,
				radius, M_PI * 1.5, M_PI);
	    cairo_close_path (cr);

	    /* setup pattern */
	    pattern = cairo_pattern_create_linear (0, 0, 0, height);

	    /* base color */
	    r = groupGetTabBaseColorRed (s) / 65535.0f;
	    g = groupGetTabBaseColorGreen (s) / 65535.0f;
	    b = groupGetTabBaseColorBlue (s) / 65535.0f;
	    a = groupGetTabBaseColorAlpha (s) / 65535.0f;
	    cairo_pattern_add_color_stop_rgba (pattern, 0.0f, r, g, b, a);

	    /* we don't want to use a full highlight here
	       so we mix the colors */
	    r = (groupGetTabHighlightColorRed (s) +
		 groupGetTabBaseColorRed (s)) / (2 * 65535.0f);
	    g = (groupGetTabHighlightColorGreen (s) +
		 groupGetTabBaseColorGreen (s)) / (2 * 65535.0f);
	    b = (groupGetTabHighlightColorBlue (s) +
		 groupGetTabBaseColorBlue (s)) / (2 * 65535.0f);
	    a = (groupGetTabHighlightColorAlpha (s) +
		 groupGetTabBaseColorAlpha (s)) / (2 * 65535.0f);
	    cairo_pattern_add_color_stop_rgba (pattern, 1.0f, r, g, b, a);

	    cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
	    cairo_set_source (cr, pattern);
	    cairo_fill (cr);
	    cairo_pattern_destroy (pattern);
	    cairo_set_operator (cr, CAIRO_OPERATOR_OVER);

	    cairo_restore (cr);

	    /* draw shape again for the outline */
	    x0 = borderWidth / 2.0;
	    y0 = borderWidth / 2.0;
	    x1 = width  - borderWidth / 2.0;
	    y1 = height - borderWidth / 2.0;
	    radius = groupGetBorderRadius (s);

	    cairo_move_to (cr, x0 + radius, y0);
	    cairo_arc (cr, x1 - radius, y0 + radius,
		       radius, M_PI * 1.5, M_PI * 2.0);
	    cairo_arc (cr, x1 - radius, y1 - radius,
		       radius, 0.0, M_PI * 0.5);
	    cairo_arc (cr, x0 + radius, y1 - radius,
		       radius, M_PI * 0.5, M_PI);
	    cairo_arc (cr, x0 + radius, y0 + radius,
		       radius, M_PI, M_PI * 1.5);

    	    break;
	}

    default:
	break;
    }

    /* outline */
    r = groupGetTabBorderColorRed (s) / 65535.0f;
    g = groupGetTabBorderColorGreen (s) / 65535.0f;
    b = groupGetTabBorderColorBlue (s) / 65535.0f;
    a = groupGetTabBorderColorAlpha (s) / 65535.0f;
    cairo_set_source_rgba (cr, r, g, b, a);

    if (bar->bgAnimation != AnimationNone)
	cairo_stroke_preserve (cr);
    else
	cairo_stroke (cr);

    switch (bar->bgAnimation) {
    case AnimationPulse:
	{
	    double animationProgress;
	    double alpha;

	    animationProgress = bar->bgAnimationTime /
		                (groupGetPulseTime (s) * 1000.0);
	    alpha = sin ((2 * PI * animationProgress) - 1.55)*0.5 + 0.5;
	    if (alpha <= 0)
		break;

	    cairo_save (cr);
	    cairo_clip (cr);
	    cairo_set_operator (cr, CAIRO_OPERATOR_XOR);
	    cairo_rectangle (cr, 0.0, 0.0, width, height);
	    cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, alpha);
	    cairo_fill (cr);
	    cairo_restore (cr);
	    break;
	}

    case AnimationReflex:
	{
	    double          animationProgress;
	    double          reflexWidth;
	    double          posX, alpha;
	    cairo_pattern_t *pattern;

	    animationProgress = bar->bgAnimationTime /
		                (groupGetReflexTime (s) * 1000.0);
	    reflexWidth = (bar->nSlots / 2.0) * 30;
	    posX = (width + reflexWidth * 2.0) * animationProgress;
	    alpha = sin (PI * animationProgress) * 0.55;
	    if (alpha <= 0)
		break;

	    cairo_save (cr);
	    cairo_clip (cr);
	    pattern = cairo_pattern_create_linear (posX - reflexWidth,
						   0.0, posX, height);
	    cairo_pattern_add_color_stop_rgba (pattern,
					       0.0f, 1.0, 1.0, 1.0, 0.0);
	    cairo_pattern_add_color_stop_rgba (pattern,
					       0.5f, 1.0, 1.0, 1.0, alpha);
	    cairo_pattern_add_color_stop_rgba (pattern,
					       1.0f, 1.0, 1.0, 1.0, 0.0);
	    cairo_rectangle (cr, 0.0, 0.0, width, height);
	    cairo_set_source (cr, pattern);
	    cairo_fill (cr);
	    cairo_restore (cr);
	    cairo_pattern_destroy (pattern);
	    break;
	}

    case AnimationNone:
    default:
	break;
    }

    /* draw inner outline */
    cairo_move_to (cr, x0 + radius + 1.0, y0 + 1.0);
    cairo_arc (cr, x1 - radius - 1.0, y0 + radius + 1.0,
		radius, M_PI * 1.5, M_PI * 2.0);
    cairo_arc (cr, x1 - radius - 1.0, y1 - radius - 1.0,
		radius, 0.0, M_PI * 0.5);
    cairo_arc (cr, x0 + radius + 1.0, y1 - radius - 1.0,
		radius, M_PI * 0.5, M_PI);
    cairo_arc (cr, x0 + radius + 1.0, y0 + radius + 1.0,
		radius, M_PI, M_PI * 1.5);

    cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.3);
    cairo_stroke(cr);

    cairo_restore (cr);
    imageBufferToTexture (s, &layer->texture, (char*) layer->buffer,
			  layer->texWidth, layer->texHeight);
}
Exemple #6
0
/*
 * groupPaintWindow
 *
 */
Bool
groupPaintWindow (CompWindow              *w,
                  const WindowPaintAttrib *attrib,
                  const CompTransform     *transform,
                  Region                  region,
                  unsigned int            mask)
{
	Bool status;
	Bool doRotate, doTabbing, showTabbar;
	CompScreen *s = w->screen;

	GROUP_SCREEN (s);
	GROUP_WINDOW (w);

	if (gw->group)
	{
		GroupSelection *group = gw->group;

		doRotate = (group->changeState != NoTabChange) &&
		           HAS_TOP_WIN (group) && HAS_PREV_TOP_WIN (group) &&
		           (IS_TOP_TAB (w, group) || IS_PREV_TOP_TAB (w, group));

		doTabbing = (gw->animateState & (IS_ANIMATED | FINISHED_ANIMATION)) &&
		            !(IS_TOP_TAB (w, group) &&
		              (group->tabbingState == Tabbing));

		showTabbar = group->tabBar && (group->tabBar->state != PaintOff) &&
		             (((IS_TOP_TAB (w, group)) &&
		               ((group->changeState == NoTabChange) ||
		                (group->changeState == TabChangeNewIn))) ||
		              (IS_PREV_TOP_TAB (w, group) &&
		               (group->changeState == TabChangeOldOut)));
	}
	else
	{
		doRotate   = FALSE;
		doTabbing  = FALSE;
		showTabbar = FALSE;
	}

	if (gw->windowHideInfo)
		mask |= PAINT_WINDOW_NO_CORE_INSTANCE_MASK;

	if (gw->inSelection || gw->resizeGeometry || doRotate ||
	    doTabbing || showTabbar)
	{
		WindowPaintAttrib wAttrib = *attrib;
		CompTransform wTransform = *transform;
		float animProgress = 0.0f;
		int drawnPosX = 0, drawnPosY = 0;

		if (gw->inSelection)
		{
			const BananaValue *
			option_select_opacity = bananaGetOption (bananaIndex,
			                                         "select_opacity",
			                                         s->screenNum);

			const BananaValue *
			option_select_saturation = bananaGetOption (bananaIndex,
			                                            "select_saturation",
			                                            s->screenNum);

			const BananaValue *
			option_select_brightness = bananaGetOption (bananaIndex,
			                                            "select_brightness",
			                                            s->screenNum);

			wAttrib.opacity    = OPAQUE * option_select_opacity->i / 100;
			wAttrib.saturation = COLOR * option_select_saturation->i / 100;
			wAttrib.brightness = BRIGHT * option_select_brightness->i / 100;
		}

		if (doTabbing)
		{
			/* fade the window out */
			float progress;
			int distanceX, distanceY;
			float origDistance, distance;

			if (gw->animateState & FINISHED_ANIMATION)
			{
				drawnPosX = gw->destination.x;
				drawnPosY = gw->destination.y;
			}
			else
			{
				drawnPosX = gw->orgPos.x + gw->tx;
				drawnPosY = gw->orgPos.y + gw->ty;
			}

			distanceX = drawnPosX - gw->destination.x;
			distanceY = drawnPosY - gw->destination.y;
			distance = sqrt (pow (distanceX, 2) + pow (distanceY, 2));

			distanceX = (gw->orgPos.x - gw->destination.x);
			distanceY = (gw->orgPos.y - gw->destination.y);
			origDistance = sqrt (pow (distanceX, 2) + pow (distanceY, 2));

			if (!distanceX && !distanceY)
				progress = 1.0f;
			else
				progress = 1.0f - (distance / origDistance);

			animProgress = progress;

			progress = MAX (progress, 0.0f);
			if (gw->group->tabbingState == Tabbing)
				progress = 1.0f - progress;

			wAttrib.opacity = (float)wAttrib.opacity * progress;
		}

		if (doRotate)
		{
			const BananaValue *
			option_change_animation_time = bananaGetOption (bananaIndex,
			                                          "change_animation_time",
			                                          s->screenNum);

			float timeLeft = gw->group->changeAnimationTime;
			int animTime = option_change_animation_time->f * 500;

			if (gw->group->changeState == TabChangeOldOut)
				timeLeft += animTime;

			/* 0 at the beginning, 1 at the end */
			animProgress = 1 - (timeLeft / (2 * animTime));
		}

		if (gw->resizeGeometry)
		{
			int xOrigin, yOrigin;
			float xScale, yScale;
			BoxRec box;

			groupGetStretchRectangle (w, &box, &xScale, &yScale);

			xOrigin = w->attrib.x - w->input.left;
			yOrigin = w->attrib.y - w->input.top;

			matrixTranslate (&wTransform, xOrigin, yOrigin, 0.0f);
			matrixScale (&wTransform, xScale, yScale, 1.0f);
			matrixTranslate (&wTransform,
			                 (gw->resizeGeometry->x - w->attrib.x) /
			                 xScale - xOrigin,
			                 (gw->resizeGeometry->y - w->attrib.y) /
			                 yScale - yOrigin,
			                 0.0f);

			mask |= PAINT_WINDOW_TRANSFORMED_MASK;
		}
		else if (doRotate || doTabbing)
		{
			float animWidth, animHeight;
			float animScaleX, animScaleY;
			CompWindow *morphBase, *morphTarget;

			if (doTabbing)
			{
				if (gw->group->tabbingState == Tabbing)
				{
					morphBase   = w;
					morphTarget = TOP_TAB (gw->group);
				}
				else
				{
					morphTarget = w;
					if (HAS_TOP_WIN (gw->group))
						morphBase = TOP_TAB (gw->group);
					else
						morphBase = gw->group->lastTopTab;
				}
			}
			else
			{
				morphBase   = PREV_TOP_TAB (gw->group);
				morphTarget = TOP_TAB (gw->group);
			}

			animWidth = (1 - animProgress) * WIN_REAL_WIDTH (morphBase) +
			            animProgress * WIN_REAL_WIDTH (morphTarget);
			animHeight = (1 - animProgress) * WIN_REAL_HEIGHT (morphBase) +
			             animProgress * WIN_REAL_HEIGHT (morphTarget);

			animWidth = MAX (1.0f, animWidth);
			animHeight = MAX (1.0f, animHeight);
			animScaleX = animWidth / WIN_REAL_WIDTH (w);
			animScaleY = animHeight / WIN_REAL_HEIGHT (w);

			if (doRotate)
				matrixScale (&wTransform, 1.0f, 1.0f, 1.0f / s->width);

			matrixTranslate (&wTransform,
			                 WIN_REAL_X (w) + WIN_REAL_WIDTH (w) / 2.0f,
			                 WIN_REAL_Y (w) + WIN_REAL_HEIGHT (w) / 2.0f,
			                 0.0f);

			if (doRotate)
			{
				float rotateAngle = animProgress * 180.0f;
				if (IS_TOP_TAB (w, gw->group))
					rotateAngle += 180.0f;

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

				matrixRotate (&wTransform, rotateAngle, 0.0f, 1.0f, 0.0f);
			}

			if (doTabbing)
				matrixTranslate (&wTransform,
				                 drawnPosX - WIN_X (w),
				                 drawnPosY - WIN_Y (w), 0.0f);

			matrixScale (&wTransform, animScaleX, animScaleY, 1.0f);

			matrixTranslate (&wTransform,
			                 -(WIN_REAL_X (w) + WIN_REAL_WIDTH (w) / 2.0f),
			                 -(WIN_REAL_Y (w) + WIN_REAL_HEIGHT (w) / 2.0f),
			                 0.0f);

			mask |= PAINT_WINDOW_TRANSFORMED_MASK;
		}

		UNWRAP (gs, s, paintWindow);
		status = (*s->paintWindow)(w, &wAttrib, &wTransform, region, mask);

		if (showTabbar)
			groupPaintTabBar (gw->group, &wAttrib, &wTransform, mask, region);

		WRAP (gs, s, paintWindow, groupPaintWindow);
	}
	else
	{
		UNWRAP (gs, s, paintWindow);
		status = (*s->paintWindow)(w, attrib, transform, region, mask);
		WRAP (gs, s, paintWindow, groupPaintWindow);
	}

	return status;
}
Exemple #7
0
/*
 * groupPaintTabBar
 *
 */
static void
groupPaintTabBar (GroupSelection          *group,
                  const WindowPaintAttrib *wAttrib,
                  const CompTransform     *transform,
                  unsigned int            mask,
                  Region                  clipRegion)
{
	CompWindow      *topTab;
	CompScreen      *s = group->screen;
	GroupTabBar     *bar = group->tabBar;
	int count;
	REGION box;

	GROUP_SCREEN (s);

	if (HAS_TOP_WIN (group))
		topTab = TOP_TAB (group);
	else
		topTab = PREV_TOP_TAB (group);

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

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

	const BananaValue *
	option_fade_time = bananaGetOption (bananaIndex,
	                                    "fade_time",
	                                    s->screenNum);

	const BananaValue *
	option_mipmaps = bananaGetOption (bananaIndex,
	                                  "mipmaps",
	                                  s->screenNum);

	const BananaValue *
	option_fade_text_time = bananaGetOption (bananaIndex,
	                                         "fade_text_time",
	                                         s->screenNum);

	for (count = 0; count < PAINT_MAX; count++)
	{
		int alpha = OPAQUE;
		float wScale = 1.0f, hScale = 1.0f;
		GroupCairoLayer *layer = NULL;

		if (bar->state == PaintFadeIn)
			alpha -= alpha * bar->animationTime / (option_fade_time->f * 1000);
		else if (bar->state == PaintFadeOut)
			alpha = alpha * bar->animationTime / (option_fade_time->f * 1000);

		switch (count) {
		case PAINT_BG:
		{
			int newWidth;

			layer = bar->bgLayer;

			/* handle the repaint of the background */
			newWidth = bar->region->extents.x2 - bar->region->extents.x1;
			if (layer && (newWidth > layer->texWidth))
				newWidth = layer->texWidth;

			wScale = (double) (bar->region->extents.x2 -
			                   bar->region->extents.x1) / (double) newWidth;

			/* FIXME: maybe move this over to groupResizeTabBarRegion -
			   the only problem is that we would have 2 redraws if
			   there is an animation */
			if (newWidth != bar->oldWidth || bar->bgAnimation)
				groupRenderTabBarBackground (group);

			bar->oldWidth = newWidth;
			box.extents = bar->region->extents;
		}
		break;

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

		case PAINT_THUMBS:
		{
			GLenum oldTextureFilter;
			GroupTabBarSlot *slot;

			oldTextureFilter = display.textureFilter;

			if (option_mipmaps->b)
				display.textureFilter = GL_LINEAR_MIPMAP_LINEAR;

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

			display.textureFilter = oldTextureFilter;
		}
		break;

		case PAINT_TEXT:
			if (bar->textLayer && (bar->textLayer->state != PaintOff))
			{
				layer = bar->textLayer;

				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 for text fade... */
				if (layer->state == PaintFadeIn)
					alpha -= alpha * layer->animationTime /
					         (option_fade_text_time->f * 1000);
				else if (layer->state == PaintFadeOut)
					alpha = alpha * layer->animationTime /
					        (option_fade_text_time->f * 1000);
			}
			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) / wScale +
			                 topTab->attrib.x;
			box.extents.y1 = (box.extents.y1 - topTab->attrib.y) / hScale +
			                 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 * wScale < layer->texWidth)
				box.extents.x2 += box.extents.x1;
			else
				box.extents.x2 = box.extents.x1 + layer->texWidth;

			if (box.extents.y2 * hScale < 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;
			topTab->vCount = topTab->indexCount = 0;

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

			if (topTab->vCount)
			{
				FragmentAttrib fragment;
				CompTransform wTransform = *transform;

				matrixTranslate (&wTransform,
				                 WIN_X (topTab), WIN_Y (topTab), 0.0f);
				matrixScale (&wTransform, wScale, hScale, 1.0f);
				matrixTranslate (&wTransform,
				                 wAttrib->xTranslate / wScale - WIN_X (topTab),
				                 wAttrib->yTranslate / hScale - WIN_Y (topTab),
				                 0.0f);

				glPushMatrix ();
				glLoadMatrixf (wTransform.m);

				alpha = alpha * ((float)wAttrib->opacity / OPAQUE);

				initFragmentAttrib (&fragment, wAttrib);
				fragment.opacity = alpha;

				(*s->drawWindowTexture)(topTab, &layer->texture,
				                        &fragment, mask |
				                        PAINT_WINDOW_BLEND_MASK |
				                        PAINT_WINDOW_TRANSFORMED_MASK |
				                        PAINT_WINDOW_TRANSLUCENT_MASK);

				glPopMatrix ();
			}
		}
	}
}
Exemple #8
0
/*
 * TextLayer::render
 *
 * Renders some text without a background, without automatically
 * binding the text pixmap to a texture (since we need to bind it later)
 *
 */
void
TextLayer::render ()
{
    int             twidth, theight;
    Pixmap          pixmap = None;

    GROUP_SCREEN (screen);

    if (!HAS_TOP_WIN (mGroup))
	return;

    /* Maximum text width is the tab bar width */
    twidth = mGroup->mTabBar->mRegion.boundingRect ().width ();
    theight = mGroup->mTabBar->mRegion.boundingRect ().height ();

    if (mGroup->mTabBar->mTextSlot &&
        mGroup->mTabBar->mTextSlot->mWindow && gTextAvailable)
    {
	CompText::Attrib  textAttrib;

	textAttrib.family = "Sans";
	textAttrib.size   = gs->optionGetTabbarFontSize ();

	/* Bold text, ellipsize if there is not enough room and do not
	 * automatically bind pixmap to texture */
	textAttrib.flags = CompText::StyleBold | CompText::Ellipsized |
	                   CompText::NoAutoBinding;

	textAttrib.color[0] = gs->optionGetTabbarFontColorRed ();
	textAttrib.color[1] = gs->optionGetTabbarFontColorGreen ();
	textAttrib.color[2] = gs->optionGetTabbarFontColorBlue ();
	textAttrib.color[3] = gs->optionGetTabbarFontColorAlpha ();

	textAttrib.maxWidth = twidth;
	textAttrib.maxHeight = theight;

	/* Render title of the top window */
	if (gs->mText.renderWindowTitle (
		             mGroup->mTabBar->mTextSlot->mWindow->id (),
						     false, textAttrib))
	{
	    pixmap = gs->mText.getPixmap ();
	    twidth = gs->mText.getWidth ();
	    theight = gs->mText.getHeight ();
	}
    }

    if (!pixmap)
    {
	/* getting the pixmap failed, so create an empty one */
	pixmap = XCreatePixmap (screen->dpy (), screen->root (), twidth,
							   theight, 32);

	if (pixmap)
	{
	    XGCValues gcv;
	    GC        gc;

	    gcv.foreground = 0x00000000;
	    gcv.plane_mask = 0xffffffff;

	    gc = XCreateGC (screen->dpy (), pixmap, GCForeground, &gcv);
	    XFillRectangle (screen->dpy (), pixmap, gc, 0, 0, twidth,
							       theight);
	    XFreeGC (screen->dpy (), gc);
	}
    }

    setWidth  (twidth);
    setHeight (theight);

    if (pixmap)
    {
	mTexture.clear ();
	mPixmap = pixmap;
	/* Text layer's texture is bound here, this can be re used
	 * in TextureLayer::paint
	 */
	mTexture = GLTexture::bindPixmapToTexture (mPixmap,
						   width (), height (),
						   32);
    }
}
Exemple #9
0
/*
 * BackgroundLayer::render
 *
 * Render the background to the tab bar, also render the tab bar animation
 *
 */
void
BackgroundLayer::render ()
{
    cairo_t         *cr;
    int             twidth, theight, radius;
    int             borderWidth;
    float           r, g, b, a;
    double          x0, y0, x1, y1;

    GROUP_SCREEN (screen);

    if (!HAS_TOP_WIN (mGroup) || !mCairo)
	return;

    /* Dimentions are the tab bar's region */
    twidth = mGroup->mTabBar->mRegion.boundingRect ().width ();
    theight = mGroup->mTabBar->mRegion.boundingRect ().height ();
    radius = gs->optionGetBorderRadius ();

    /* Do not draw more than the tab bar width */
    if (twidth > width ())
	twidth = width ();

    /* Border radius should not exceed
     * half of the tab bar height */
    if (radius > twidth / 2)
	radius = twidth / 2;

    cr = mCairo;

    /* Clear the layer */
    clear ();

    /* Draw the border around the tab bar */

    borderWidth = gs->optionGetBorderWidth ();
    cairo_set_line_width (cr, borderWidth);

    cairo_save (cr);

    /* Move to the center of where we want to draw the line */
    x0 = borderWidth / 2.0f;
    y0 = borderWidth / 2.0f;
    /* The center of where we want to draw the opposite line */
    x1 = twidth  - borderWidth / 2.0f;
    y1 = theight - borderWidth / 2.0f;
    cairo_move_to (cr, x0 + radius, y0);

    /* Arc the top right corner */
    cairo_arc (cr, x1 - radius, y0 + radius, radius, M_PI * 1.5, M_PI * 2.0);
    /* Arc the bottom right corner */
    cairo_arc (cr, x1 - radius, y1 - radius, radius, 0.0, M_PI * 0.5);
    /* Arc the bottom left corner */
    cairo_arc (cr, x0 + radius, y1 - radius, radius, M_PI * 0.5, M_PI);
    /* Arc the top left corner */
    cairo_arc (cr, x0 + radius, y0 + radius, radius, M_PI, M_PI * 1.5);

    cairo_close_path  (cr);

    /* There are 5 different tab styles here:
     * Simple: draws a simple filled rect
     * Gradient: left to right gradient between base and highlight
     * Glass: left to right gradient, stopping at 60% and drawing a shadow
     * Metal: base -> highlight -> base gradient
     * Murrina: draws an arc between the two corners blending base and highlight
     */
    switch (gs->optionGetTabStyle ()) {
    case GroupOptions::TabStyleSimple:
	{
	    /* base color */
	    r = gs->optionGetTabBaseColorRed () / 65535.0f;
	    g = gs->optionGetTabBaseColorGreen () / 65535.0f;
	    b = gs->optionGetTabBaseColorBlue () / 65535.0f;
	    a = gs->optionGetTabBaseColorAlpha () / 65535.0f;
	    cairo_set_source_rgba (cr, r, g, b, a);

    	    cairo_fill_preserve (cr);
	    break;
	}

    case GroupOptions::TabStyleGradient:
	{
	    /* fill */
	    cairo_pattern_t *pattern;
	    pattern = cairo_pattern_create_linear (0, 0, twidth, theight);

	    /* highlight color */
	    r = gs->optionGetTabHighlightColorRed () / 65535.0f;
	    g = gs->optionGetTabHighlightColorGreen () / 65535.0f;
	    b = gs->optionGetTabHighlightColorBlue () / 65535.0f;
	    a = gs->optionGetTabHighlightColorAlpha () / 65535.0f;
	    cairo_pattern_add_color_stop_rgba (pattern, 0.0f, r, g, b, a);

	    /* base color */
	    r = gs->optionGetTabBaseColorRed () / 65535.0f;
	    g = gs->optionGetTabBaseColorGreen () / 65535.0f;
	    b = gs->optionGetTabBaseColorBlue () / 65535.0f;
	    a = gs->optionGetTabBaseColorAlpha () / 65535.0f;
	    cairo_pattern_add_color_stop_rgba (pattern, 1.0f, r, g, b, a);

	    cairo_set_source (cr, pattern);
	    cairo_fill_preserve (cr);
	    cairo_pattern_destroy (pattern);
	    break;
	}

    case GroupOptions::TabStyleGlass:
	{
	    cairo_pattern_t *pattern;

	    cairo_save (cr);

	    /* clip width rounded rectangle */
	    cairo_clip (cr);

	    /* ===== HIGHLIGHT ===== */

	    /* make draw the shape for the highlight and
	       create a pattern for it */
	    cairo_rectangle (cr, 0, 0, twidth, theight / 2);
	    pattern = cairo_pattern_create_linear (0, 0, 0, theight);

	    /* highlight color */
	    r = gs->optionGetTabHighlightColorRed () / 65535.0f;
	    g = gs->optionGetTabHighlightColorGreen () / 65535.0f;
	    b = gs->optionGetTabHighlightColorBlue () / 65535.0f;
	    a = gs->optionGetTabHighlightColorAlpha () / 65535.0f;
	    cairo_pattern_add_color_stop_rgba (pattern, 0.0f, r, g, b, a);

	    /* base color */
	    r = gs->optionGetTabBaseColorRed () / 65535.0f;
	    g = gs->optionGetTabBaseColorGreen () / 65535.0f;
	    b = gs->optionGetTabBaseColorBlue () / 65535.0f;
	    a = gs->optionGetTabBaseColorAlpha () / 65535.0f;
	    cairo_pattern_add_color_stop_rgba (pattern, 0.6f, r, g, b, a);

	    cairo_set_source (cr, pattern);
	    cairo_fill (cr);
	    cairo_pattern_destroy (pattern);

	    /* ==== SHADOW ===== */

	    /* make draw the shape for the show and create a pattern for it */
	    cairo_rectangle (cr, 0, theight / 2, twidth, theight);
	    pattern = cairo_pattern_create_linear (0, 0, 0, theight);

	    /* we don't want to use a full highlight here
	       so we mix the colors */
	    r = (gs->optionGetTabHighlightColorRed () +
		 gs->optionGetTabBaseColorRed ()) / (2 * 65535.0f);
	    g = (gs->optionGetTabHighlightColorGreen () +
		 gs->optionGetTabBaseColorGreen ()) / (2 * 65535.0f);
	    b = (gs->optionGetTabHighlightColorBlue () +
		 gs->optionGetTabBaseColorBlue ()) / (2 * 65535.0f);
	    a = (gs->optionGetTabHighlightColorAlpha () +
		 gs->optionGetTabBaseColorAlpha ()) / (2 * 65535.0f);
	    cairo_pattern_add_color_stop_rgba (pattern, 1.0f, r, g, b, a);

	    /* base color */
	    r = gs->optionGetTabBaseColorRed () / 65535.0f;
	    g = gs->optionGetTabBaseColorGreen () / 65535.0f;
	    b = gs->optionGetTabBaseColorBlue () / 65535.0f;
	    a = gs->optionGetTabBaseColorAlpha () / 65535.0f;
	    cairo_pattern_add_color_stop_rgba (pattern, 0.5f, r, g, b, a);

	    cairo_set_source (cr, pattern);
	    cairo_fill (cr);
	    cairo_pattern_destroy (pattern);

	    cairo_restore (cr);

	    /* draw shape again for the outline */
	    cairo_move_to (cr, x0 + radius, y0);
	    cairo_arc (cr, x1 - radius, y0 + radius,
		       radius, M_PI * 1.5, M_PI * 2.0);
	    cairo_arc (cr, x1 - radius, y1 - radius,
		       radius, 0.0, M_PI * 0.5);
	    cairo_arc (cr, x0 + radius, y1 - radius,
		       radius, M_PI * 0.5, M_PI);
	    cairo_arc (cr, x0 + radius, y0 + radius,
		       radius, M_PI, M_PI * 1.5);

	    break;
	}

    case GroupOptions::TabStyleMetal:
	{
	    /* fill */
	    cairo_pattern_t *pattern;
	    pattern = cairo_pattern_create_linear (0, 0, 0, theight);

	    /* base color #1 */
	    r = gs->optionGetTabBaseColorRed () / 65535.0f;
	    g = gs->optionGetTabBaseColorGreen () / 65535.0f;
	    b = gs->optionGetTabBaseColorBlue () / 65535.0f;
	    a = gs->optionGetTabBaseColorAlpha () / 65535.0f;
	    cairo_pattern_add_color_stop_rgba (pattern, 0.0f, r, g, b, a);

	    /* highlight color */
	    r = gs->optionGetTabHighlightColorRed () / 65535.0f;
	    g = gs->optionGetTabHighlightColorGreen () / 65535.0f;
	    b = gs->optionGetTabHighlightColorBlue () / 65535.0f;
	    a = gs->optionGetTabHighlightColorAlpha () / 65535.0f;
	    cairo_pattern_add_color_stop_rgba (pattern, 0.55f, r, g, b, a);

	    /* base color #2 */
	    r = gs->optionGetTabBaseColorRed () / 65535.0f;
	    g = gs->optionGetTabBaseColorGreen () / 65535.0f;
	    b = gs->optionGetTabBaseColorBlue () / 65535.0f;
	    a = gs->optionGetTabBaseColorAlpha () / 65535.0f;
	    cairo_pattern_add_color_stop_rgba (pattern, 1.0f, r, g, b, a);

	    cairo_set_source (cr, pattern);
	    cairo_fill_preserve (cr);
	    cairo_pattern_destroy (pattern);
	    break;
	}

    case GroupOptions::TabStyleMurrina:
	{
	    double          ratio, transX;
	    cairo_pattern_t *pattern;

	    cairo_save (cr);

	    /* clip width rounded rectangle */
	    cairo_clip_preserve (cr);

	    /* ==== TOP ==== */

	    x0 = borderWidth / 2.0;
	    y0 = borderWidth / 2.0;
	    x1 = twidth  - borderWidth / 2.0;
	    y1 = theight - borderWidth / 2.0;
	    radius = (y1 - y0) / 2;

	    /* setup pattern */
	    pattern = cairo_pattern_create_linear (0, 0, 0, theight);

	    /* we don't want to use a full highlight here
	       so we mix the colors */
	    r = (gs->optionGetTabHighlightColorRed () +
		 gs->optionGetTabBaseColorRed ()) / (2 * 65535.0f);
	    g = (gs->optionGetTabHighlightColorGreen () +
		 gs->optionGetTabBaseColorGreen ()) / (2 * 65535.0f);
	    b = (gs->optionGetTabHighlightColorBlue () +
		 gs->optionGetTabBaseColorBlue ()) / (2 * 65535.0f);
	    a = (gs->optionGetTabHighlightColorAlpha () +
		 gs->optionGetTabBaseColorAlpha ()) / (2 * 65535.0f);
	    cairo_pattern_add_color_stop_rgba (pattern, 0.0f, r, g, b, a);

	    /* highlight color */
	    r = gs->optionGetTabHighlightColorRed () / 65535.0f;
	    g = gs->optionGetTabHighlightColorGreen () / 65535.0f;
	    b = gs->optionGetTabHighlightColorBlue () / 65535.0f;
	    a = gs->optionGetTabHighlightColorAlpha () / 65535.0f;
	    cairo_pattern_add_color_stop_rgba (pattern, 1.0f, r, g, b, a);

	    cairo_set_source (cr, pattern);

	    cairo_fill (cr);
	    cairo_pattern_destroy (pattern);

	    /* ==== BOTTOM ===== */

	    x0 = borderWidth / 2.0;
	    y0 = borderWidth / 2.0;
	    x1 = twidth  - borderWidth / 2.0;
	    y1 = theight - borderWidth / 2.0;
	    radius = (y1 - y0) / 2;

	    ratio = (double)twidth / (double)theight;
	    transX = twidth - (twidth * ratio);

	    cairo_move_to (cr, x1, y1);
	    cairo_line_to (cr, x1, y0);
	    if (twidth < theight)
	    {
		cairo_translate (cr, transX, 0);
		cairo_scale (cr, ratio, 1.0);
	    }
	    cairo_arc (cr, x1 - radius, y0, radius, 0.0, M_PI * 0.5);
	    if (twidth < theight)
	    {
		cairo_scale (cr, 1.0 / ratio, 1.0);
		cairo_translate (cr, -transX, 0);
		cairo_scale (cr, ratio, 1.0);
	    }
	    cairo_arc_negative (cr, x0 + radius, y1,
				radius, M_PI * 1.5, M_PI);
	    cairo_close_path (cr);

	    /* setup pattern */
	    pattern = cairo_pattern_create_linear (0, 0, 0, theight);

	    /* base color */
	    r = gs->optionGetTabBaseColorRed () / 65535.0f;
	    g = gs->optionGetTabBaseColorGreen () / 65535.0f;
	    b = gs->optionGetTabBaseColorBlue () / 65535.0f;
	    a = gs->optionGetTabBaseColorAlpha () / 65535.0f;
	    cairo_pattern_add_color_stop_rgba (pattern, 0.0f, r, g, b, a);

	    /* we don't want to use a full highlight here
	       so we mix the colors */
	    r = (gs->optionGetTabHighlightColorRed () +
		 gs->optionGetTabBaseColorRed ()) / (2 * 65535.0f);
	    g = (gs->optionGetTabHighlightColorGreen () +
		 gs->optionGetTabBaseColorGreen ()) / (2 * 65535.0f);
	    b = (gs->optionGetTabHighlightColorBlue () +
		 gs->optionGetTabBaseColorBlue ()) / (2 * 65535.0f);
	    a = (gs->optionGetTabHighlightColorAlpha () +
		 gs->optionGetTabBaseColorAlpha ()) / (2 * 65535.0f);
	    cairo_pattern_add_color_stop_rgba (pattern, 1.0f, r, g, b, a);

	    cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
	    cairo_set_source (cr, pattern);
	    cairo_fill (cr);
	    cairo_pattern_destroy (pattern);
	    cairo_set_operator (cr, CAIRO_OPERATOR_OVER);

	    cairo_restore (cr);

	    /* draw shape again for the outline */
	    x0 = borderWidth / 2.0;
	    y0 = borderWidth / 2.0;
	    x1 = twidth  - borderWidth / 2.0;
	    y1 = theight - borderWidth / 2.0;
	    radius = gs->optionGetBorderRadius ();

	    cairo_move_to (cr, x0 + radius, y0);
	    cairo_arc (cr, x1 - radius, y0 + radius,
		       radius, M_PI * 1.5, M_PI * 2.0);
	    cairo_arc (cr, x1 - radius, y1 - radius,
		       radius, 0.0, M_PI * 0.5);
	    cairo_arc (cr, x0 + radius, y1 - radius,
		       radius, M_PI * 0.5, M_PI);
	    cairo_arc (cr, x0 + radius, y0 + radius,
		       radius, M_PI, M_PI * 1.5);

    	    break;
	}

    default:
	break;
    }

    /* outline */
    r = gs->optionGetTabBorderColorRed () / 65535.0f;
    g = gs->optionGetTabBorderColorGreen () / 65535.0f;
    b = gs->optionGetTabBorderColorBlue () / 65535.0f;
    a = gs->optionGetTabBorderColorAlpha () / 65535.0f;
    cairo_set_source_rgba (cr, r, g, b, a);

    /* If there is an animation running, stroke preserved
     * so that we can paint directly on top (and blend!)
     * the new animation with the existing tab bar.
     * Otherwise just stroke normally, this is less expensive
     */
    if (mBgAnimation != AnimationNone)
	cairo_stroke_preserve (cr);
    else
	cairo_stroke (cr);

    /* There are two animations here:
     * Pulse: Highlight tab bar in and out (used for tab hover)
     * Reflex: Paint a diagonal gradient moving from right to left
     *         on the tab bar when it appears
     */
    switch (mBgAnimation) {
    case AnimationPulse:
	{
	    double animationProgress;
	    double alpha;

	    /* Progress here is measured in the current time */
	    animationProgress = mBgAnimationTime /
		                (gs->optionGetPulseTime () * 1000.0);
	    /* The highlight pulsates in and out, so the alpha here should run
	     * on a sine wave */
	    alpha = sin ((2 * PI * animationProgress) - 1.55)*0.5 + 0.5;

	    /* If the alpha of the animation is < 0, don't bother painting */
	    if (alpha <= 0)
		break;

	    cairo_save (cr);
	    cairo_clip (cr);
	    /* Paint highlight over the tab bar */
	    cairo_set_operator (cr, CAIRO_OPERATOR_XOR);
	    cairo_rectangle (cr, 0.0, 0.0, twidth, theight);
	    cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, alpha);
	    cairo_fill (cr);
	    cairo_restore (cr);
	    break;
	}

    case AnimationReflex:
	{
	    double          animationProgress;
	    double          reflexWidth;
	    double          posX, alpha;
	    cairo_pattern_t *pattern;

	    /* Progress is measured in current time */
	    animationProgress = mBgAnimationTime /
		                (gs->optionGetReflexTime () * 1000.0);
	    /* Position here is the tab bar width plus the reflection width * 2 */
	    reflexWidth = (mGroup->mTabBar->mSlots.size () / 2.0) * 30;
	    posX = (twidth + reflexWidth * 2.0) * animationProgress;
	    alpha = sin (PI * animationProgress) * 0.55;
	    if (alpha <= 0)
		break;

	    cairo_save (cr);
	    cairo_clip (cr);
	    pattern = cairo_pattern_create_linear (posX - reflexWidth,
						   0.0, posX, theight);
	    cairo_pattern_add_color_stop_rgba (pattern,
					       0.0f, 1.0, 1.0, 1.0, 0.0);
	    cairo_pattern_add_color_stop_rgba (pattern,
					       0.5f, 1.0, 1.0, 1.0, alpha);
	    cairo_pattern_add_color_stop_rgba (pattern,
					       1.0f, 1.0, 1.0, 1.0, 0.0);
	    cairo_rectangle (cr, 0.0, 0.0, twidth, theight);
	    cairo_set_source (cr, pattern);
	    cairo_fill (cr);
	    cairo_restore (cr);
	    cairo_pattern_destroy (pattern);
	    break;
	}

    case AnimationNone:
    default:
	break;
    }

    /* draw inner outline */
    cairo_move_to (cr, x0 + radius + 1.0, y0 + 1.0);
    cairo_arc (cr, x1 - radius - 1.0, y0 + radius + 1.0,
		radius, M_PI * 1.5, M_PI * 2.0);
    cairo_arc (cr, x1 - radius - 1.0, y1 - radius - 1.0,
		radius, 0.0, M_PI * 0.5);
    cairo_arc (cr, x0 + radius + 1.0, y1 - radius - 1.0,
		radius, M_PI * 0.5, M_PI);
    cairo_arc (cr, x0 + radius + 1.0, y0 + radius + 1.0,
		radius, M_PI, M_PI * 1.5);

    cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.3);
    cairo_stroke(cr);

    cairo_restore (cr);

    mTexture = GLTexture::imageBufferToTexture ((char*) mBuffer,
			  		  (CompSize &) *this);
}
Exemple #10
0
/*
 * groupAddWindowToGroup
 *
 */
void
groupAddWindowToGroup (CompWindow     *w,
                       GroupSelection *group,
                       long int       initialIdent)
{
	GROUP_SCREEN (w->screen);
	GROUP_WINDOW (w);

	if (gw->group)
		return;

	if (group)
	{
		CompWindow *topTab = NULL;

		group->windows = realloc (group->windows,
		                          sizeof (CompWindow *) * (group->nWins + 1));
		group->windows[group->nWins] = w;
		group->nWins++;
		gw->group = group;

		updateWindowOutputExtents (w);
		groupUpdateWindowProperty (w);

		if (group->nWins == 2)
		{
			/* first window in the group got its glow, too */
			updateWindowOutputExtents (group->windows[0]);
		}

		if (group->tabBar)
		{
			if (HAS_TOP_WIN (group))
				topTab = TOP_TAB (group);
			else if (HAS_PREV_TOP_WIN (group))
			{
				topTab = PREV_TOP_TAB (group);
				group->topTab = group->prevTopTab;
				group->prevTopTab = NULL;
			}

			if (topTab)
			{
				if (!gw->slot)
					groupCreateSlot (group, w);

				gw->destination.x = WIN_CENTER_X (topTab) - (WIN_WIDTH (w) / 2);
				gw->destination.y = WIN_CENTER_Y (topTab) -
				                    (WIN_HEIGHT (w) / 2);
				gw->mainTabOffset.x = WIN_X (w) - gw->destination.x;
				gw->mainTabOffset.y = WIN_Y (w) - gw->destination.y;
				gw->orgPos.x = WIN_X (w);
				gw->orgPos.y = WIN_Y (w);

				gw->xVelocity = gw->yVelocity = 0.0f;

				gw->animateState = IS_ANIMATED;

				groupStartTabbingAnimation (group, TRUE);

				addWindowDamage (w);
			}
		}
	}
	else
	{
		/* create new group */
		GroupSelection *g = malloc (sizeof (GroupSelection));
		if (!g)
			return;

		g->windows = malloc (sizeof (CompWindow *));
		if (!g->windows)
		{
			free (g);
			return;
		}

		g->windows[0] = w;
		g->screen     = w->screen;
		g->nWins      = 1;

		g->topTab      = NULL;
		g->prevTopTab  = NULL;
		g->nextTopTab  = NULL;

		g->changeAnimationTime      = 0;
		g->changeAnimationDirection = 0;

		g->changeState  = NoTabChange;
		g->tabbingState = NoTabbing;
		g->ungroupState = UngroupNone;

		g->tabBar = NULL;

		g->checkFocusAfterTabChange = FALSE;

		g->grabWindow = None;
		g->grabMask   = 0;

		g->inputPrevention = None;
		g->ipwMapped       = FALSE;

		/* glow color */
		g->color[0] = (int)(rand () / (((double)RAND_MAX + 1) / 0xffff));
		g->color[1] = (int)(rand () / (((double)RAND_MAX + 1) / 0xffff));
		g->color[2] = (int)(rand () / (((double)RAND_MAX + 1) / 0xffff));
		g->color[3] = 0xffff;

		if (initialIdent)
			g->identifier = initialIdent;
		else
		{
			/* we got no valid group Id passed, so find out a new valid
			   unique one */
			GroupSelection *tg;
			Bool invalidID = FALSE;

			g->identifier = gs->groups ? gs->groups->identifier : 0;
			do
			{
				invalidID = FALSE;
				for (tg = gs->groups; tg; tg = tg->next)
				{
					if (tg->identifier == g->identifier)
					{
						invalidID = TRUE;

						g->identifier++;
						break;
					}
				}
			}
			while (invalidID);
		}

		/* relink stack */
		if (gs->groups)
			gs->groups->prev = g;

		g->next = gs->groups;
		g->prev = NULL;
		gs->groups = g;

		gw->group = g;

		groupUpdateWindowProperty (w);
	}
}
Exemple #11
0
void
groupRemoveWindowFromGroup (CompWindow *w)
{
	GROUP_WINDOW (w);

	if (!gw->group)
		return;

	if (gw->group->tabBar && !(gw->animateState & IS_UNGROUPING) &&
	    (gw->group->nWins > 1))
	{
		GroupSelection *group = gw->group;

		/* if the group is tabbed, setup untabbing animation. The
		   window will be deleted from the group at the
		   end of the untabbing. */
		if (HAS_TOP_WIN (group))
		{
			CompWindow *tw = TOP_TAB (group);
			int oldX = gw->orgPos.x;
			int oldY = gw->orgPos.y;

			gw->orgPos.x = WIN_CENTER_X (tw) - (WIN_WIDTH (w) / 2);
			gw->orgPos.y = WIN_CENTER_Y (tw) - (WIN_HEIGHT (w) / 2);

			gw->destination.x = gw->orgPos.x + gw->mainTabOffset.x;
			gw->destination.y = gw->orgPos.y + gw->mainTabOffset.y;

			gw->mainTabOffset.x = oldX;
			gw->mainTabOffset.y = oldY;

			if (gw->tx || gw->ty)
			{
				gw->tx -= (gw->orgPos.x - oldX);
				gw->ty -= (gw->orgPos.y - oldY);
			}

			gw->animateState = IS_ANIMATED;
			gw->xVelocity = gw->yVelocity = 0.0f;
		}

		/* Although when there is no top-tab, it will never really
		   animate anything, if we don't start the animation,
		   the window will never get removed. */
		groupStartTabbingAnimation (group, FALSE);

		groupSetWindowVisibility (w, TRUE);
		group->ungroupState = UngroupSingle;
		gw->animateState |= IS_UNGROUPING;
	}
	else
	{
		/* no tab bar - delete immediately */
		groupDeleteGroupWindow (w);

		const BananaValue *
		option_autotab_create = bananaGetOption (bananaIndex,
		                                         "autotab_create",
		                                         w->screen->screenNum);

		if (option_autotab_create->b && groupIsGroupWindow (w))
		{
			groupAddWindowToGroup (w, NULL, 0);
			groupTabGroup (w);
		}
	}
}
Exemple #12
0
/*
 * groupHandleButtonReleaseEvent
 *
 */
static void
groupHandleButtonReleaseEvent (CompScreen *s,
                               XEvent     *event)
{
	GroupSelection *group;
	int vx, vy;
	Region newRegion;
	Bool inserted = FALSE;
	Bool wasInTabBar = FALSE;

	GROUP_SCREEN (s);

	if (event->xbutton.button != 1)
		return;

	if (!gs->draggedSlot)
		return;

	if (!gs->dragged)
	{
		groupChangeTab (gs->draggedSlot, RotateUncertain);
		gs->draggedSlot = NULL;

		if (gs->grabState == ScreenGrabTabDrag)
			groupGrabScreen (s, ScreenGrabNone);

		return;
	}

	GROUP_WINDOW (gs->draggedSlot->window);

	newRegion = XCreateRegion ();
	if (!newRegion)
		return;

	XUnionRegion (newRegion, gs->draggedSlot->region, newRegion);

	groupGetDrawOffsetForSlot (gs->draggedSlot, &vx, &vy);
	XOffsetRegion (newRegion, vx, vy);

	for (group = gs->groups; group; group = group->next)
	{
		Bool inTabBar;
		Region clip, buf;
		GroupTabBarSlot *slot;

		if (!group->tabBar || !HAS_TOP_WIN (group))
			continue;

		/* create clipping region */
		clip = groupGetClippingRegion (TOP_TAB (group));
		if (!clip)
			continue;

		buf = XCreateRegion ();
		if (!buf)
		{
			XDestroyRegion (clip);
			continue;
		}

		XIntersectRegion (newRegion, group->tabBar->region, buf);
		XSubtractRegion (buf, clip, buf);
		XDestroyRegion (clip);

		inTabBar = !XEmptyRegion (buf);
		XDestroyRegion (buf);

		if (!inTabBar)
			continue;

		wasInTabBar = TRUE;

		for (slot = group->tabBar->slots; slot; slot = slot->next)
		{
			GroupTabBarSlot *tmpDraggedSlot;
			GroupSelection  *tmpGroup;
			Region slotRegion, buf;
			XRectangle rect;
			Bool inSlot;

			if (slot == gs->draggedSlot)
				continue;

			slotRegion = XCreateRegion ();
			if (!slotRegion)
				continue;

			if (slot->prev && slot->prev != gs->draggedSlot)
			{
				rect.x = slot->prev->region->extents.x2;
			}
			else if (slot->prev && slot->prev == gs->draggedSlot &&
			         gs->draggedSlot->prev)
			{
				rect.x = gs->draggedSlot->prev->region->extents.x2;
			}
			else
				rect.x = group->tabBar->region->extents.x1;

			rect.y = slot->region->extents.y1;

			if (slot->next && slot->next != gs->draggedSlot)
			{
				rect.width = slot->next->region->extents.x1 - rect.x;
			}
			else if (slot->next && slot->next == gs->draggedSlot &&
			         gs->draggedSlot->next)
			{
				rect.width = gs->draggedSlot->next->region->extents.x1 - rect.x;
			}
			else
				rect.width = group->tabBar->region->extents.x2;

			rect.height = slot->region->extents.y2 - slot->region->extents.y1;

			XUnionRectWithRegion (&rect, slotRegion, slotRegion);

			buf = XCreateRegion ();
			if (!buf)
				continue;

			XIntersectRegion (newRegion, slotRegion, buf);
			inSlot = !XEmptyRegion (buf);

			XDestroyRegion (buf);
			XDestroyRegion (slotRegion);

			if (!inSlot)
				continue;

			tmpDraggedSlot = gs->draggedSlot;

			if (group != gw->group)
			{
				CompWindow     *w = gs->draggedSlot->window;
				GroupSelection *tmpGroup = gw->group;
				int oldPosX = WIN_CENTER_X (w);
				int oldPosY = WIN_CENTER_Y (w);

				/* if the dragged window is not the top tab,
				   move it onscreen */
				if (tmpGroup->topTab && !IS_TOP_TAB (w, tmpGroup))
				{
					CompWindow *tw = TOP_TAB (tmpGroup);

					oldPosX = WIN_CENTER_X (tw) + gw->mainTabOffset.x;
					oldPosY = WIN_CENTER_Y (tw) + gw->mainTabOffset.y;

					groupSetWindowVisibility (w, TRUE);
				}

				/* Change the group. */
				groupDeleteGroupWindow (gs->draggedSlot->window);
				groupAddWindowToGroup (gs->draggedSlot->window, group, 0);

				/* we saved the original center position in oldPosX/Y before -
				   now we should apply that to the new main tab offset */
				if (HAS_TOP_WIN (group))
				{
					CompWindow *tw = TOP_TAB (group);
					gw->mainTabOffset.x = oldPosX - WIN_CENTER_X (tw);
					gw->mainTabOffset.y = oldPosY - WIN_CENTER_Y (tw);
				}
			}
			else
				groupUnhookTabBarSlot (group->tabBar, gs->draggedSlot, TRUE);

			gs->draggedSlot = NULL;
			gs->dragged = FALSE;
			inserted = TRUE;

			if ((tmpDraggedSlot->region->extents.x1 +
			     tmpDraggedSlot->region->extents.x2 + (2 * vx)) / 2 >
			    (slot->region->extents.x1 + slot->region->extents.x2) / 2)
			{
				groupInsertTabBarSlotAfter (group->tabBar,
				                            tmpDraggedSlot, slot);
			}
			else
				groupInsertTabBarSlotBefore (group->tabBar,
				                             tmpDraggedSlot, slot);

			groupDamageTabBarRegion (group);

			/* Hide tab-bars. */
			for (tmpGroup = gs->groups; tmpGroup; tmpGroup = tmpGroup->next)
			{
				if (group == tmpGroup)
					groupTabSetVisibility (tmpGroup, TRUE, 0);
				else
					groupTabSetVisibility (tmpGroup, FALSE, PERMANENT);
			}

			break;
		}

		if (inserted)
			break;
	}

	XDestroyRegion (newRegion);

	if (!inserted)
	{
		CompWindow     *draggedSlotWindow = gs->draggedSlot->window;
		GroupSelection *tmpGroup;

		for (tmpGroup = gs->groups; tmpGroup; tmpGroup = tmpGroup->next)
			groupTabSetVisibility (tmpGroup, FALSE, PERMANENT);

		gs->draggedSlot = NULL;
		gs->dragged = FALSE;

		const BananaValue *
		option_dnd_ungroup_window = bananaGetOption (bananaIndex,
		                                             "dnd_ungroup_window",
		                                             s->screenNum);

		if (option_dnd_ungroup_window->b && !wasInTabBar)
		{
			groupRemoveWindowFromGroup (draggedSlotWindow);
		}
		else if (gw->group && gw->group->topTab)
		{
			groupRecalcTabBarPos (gw->group,
			                      (gw->group->tabBar->region->extents.x1 +
			                       gw->group->tabBar->region->extents.x2) / 2,
			                      gw->group->tabBar->region->extents.x1,
			                      gw->group->tabBar->region->extents.x2);
		}

		/* to remove the painted slot */
		damageScreen (s);
	}

	if (gs->grabState == ScreenGrabTabDrag)
		groupGrabScreen (s, ScreenGrabNone);

	if (gs->dragHoverTimeoutHandle)
	{
		compRemoveTimeout (gs->dragHoverTimeoutHandle);
		gs->dragHoverTimeoutHandle = 0;
	}
}