/* * groupDragHoverTimeout * * Description: * Activates a window after a certain time a slot has been dragged over it. * */ static Bool groupDragHoverTimeout (void* closure) { CompWindow *w = (CompWindow *) closure; if (!w) return FALSE; GROUP_SCREEN (w->screen); GROUP_WINDOW (w); const BananaValue * option_bar_animations = bananaGetOption (bananaIndex, "bar_animations", w->screen->screenNum); const BananaValue * option_pulse_time = bananaGetOption (bananaIndex, "pulse_time", w->screen->screenNum); if (option_bar_animations->b) { GroupTabBar *bar = gw->group->tabBar; bar->bgAnimation = AnimationPulse; bar->bgAnimationTime = option_pulse_time->f * 1000; } (*w->screen->activateWindow) (w); gs->dragHoverTimeoutHandle = 0; return FALSE; }
/* * groupWindowResizeNotify * */ void groupWindowResizeNotify (CompWindow *w, int dx, int dy, int dwidth, int dheight) { CompScreen *s = w->screen; GROUP_SCREEN (s); GROUP_WINDOW (w); if (gw->resizeGeometry) { free (gw->resizeGeometry); gw->resizeGeometry = NULL; } UNWRAP (gs, s, windowResizeNotify); (*s->windowResizeNotify)(w, dx, dy, dwidth, dheight); WRAP (gs, s, windowResizeNotify, groupWindowResizeNotify); if (gw->glowQuads) groupComputeGlowQuads (w, &gs->glowTexture.matrix); if (gw->group && gw->group->tabBar && IS_TOP_TAB (w, gw->group)) { if (gw->group->tabBar->state != PaintOff) { groupRecalcTabBarPos (gw->group, pointerX, WIN_X (w), WIN_X (w) + WIN_WIDTH (w)); } } }
void groupEnqueueUngrabNotify (CompWindow *w) { GroupPendingUngrabs *ungrab; GROUP_SCREEN (w->screen); ungrab = malloc (sizeof (GroupPendingUngrabs)); if (!ungrab) return; ungrab->w = w; ungrab->next = NULL; if (gs->pendingUngrabs) { GroupPendingUngrabs *temp; for (temp = gs->pendingUngrabs; temp->next; temp = temp->next); temp->next = ungrab; } else gs->pendingUngrabs = ungrab; if (!gs->dequeueTimeoutHandle) { gs->dequeueTimeoutHandle = compAddTimeout (0, 0, groupDequeueTimer, (void *) w->screen); } }
void GroupWindow::enqueueUngrabNotify () { GroupWindow::PendingUngrabs *ungrab; GROUP_SCREEN (screen); ungrab = new GroupWindow::PendingUngrabs; if (!ungrab) return; ungrab->w = window; ungrab->next = NULL; if (gs->mPendingUngrabs) { GroupWindow::PendingUngrabs *temp; for (temp = gs->mPendingUngrabs; temp->next; temp = temp->next); temp->next = ungrab; } else gs->mPendingUngrabs = ungrab; if (!gs->mDequeueTimeoutHandle.active ()) { gs->mDequeueTimeoutHandle.start (); } }
/* * groupApplyInitialActions * * timer callback for stuff that needs to be called after all * screens and windows are initialized * */ static Bool groupApplyInitialActions (void *closure) { CompScreen *s = (CompScreen *) closure; CompWindow *w; GROUP_SCREEN (s); gs->initialActionsTimeoutHandle = 0; /* we need to do it from top to buttom of the stack to avoid problems with a reload of Compiz and tabbed static groups. (topTab will always be above the other windows in the group) */ for (w = s->reverseWindows; w; w = w->prev) { Bool tabbed; long int id; GLushort color[3]; GROUP_WINDOW (w); /* read window property to see if window was grouped before - if it was, regroup */ if (groupCheckWindowProperty (w, &id, &tabbed, color)) { GroupSelection *group; for (group = gs->groups; group; group = group->next) if (group->identifier == id) break; groupAddWindowToGroup (w, group, id); if (tabbed) groupTabGroup (w); gw->group->color[0] = color[0]; gw->group->color[1] = color[1]; gw->group->color[2] = color[2]; groupRenderTopTabHighlight (gw->group); damageScreen (w->screen); } const BananaValue * option_autotab_create = bananaGetOption (bananaIndex, "autotab_create", s->screenNum); if (option_autotab_create->b && groupIsGroupWindow (w)) { if (!gw->group && (gw->windowState == WindowNormal)) { groupAddWindowToGroup (w, NULL, 0); groupTabGroup (w); } } } return FALSE; }
/* * 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; } }
/* * groupInitWindow * */ static Bool groupInitWindow (CompPlugin *p, CompWindow *w) { GroupWindow *gw; GROUP_SCREEN (w->screen); gw = malloc (sizeof (GroupWindow)); if (!gw) return FALSE; gw->group = NULL; gw->slot = NULL; gw->glowQuads = NULL; gw->inSelection = FALSE; gw->needsPosSync = FALSE; gw->readOnlyProperty = FALSE; /* for tab */ gw->animateState = 0; gw->tx = 0.0f; gw->ty = 0.0f; gw->xVelocity = 0.0f; gw->yVelocity = 0.0f; gw->orgPos.x = 0; gw->orgPos.y = 0; gw->mainTabOffset.x = 0; gw->mainTabOffset.y = 0; gw->destination.x = 0; gw->destination.y = 0; gw->windowHideInfo = NULL; gw->resizeGeometry = NULL; if (w->minimized) gw->windowState = WindowMinimized; else if (w->shaded) gw->windowState = WindowShaded; else gw->windowState = WindowNormal; w->privates[gs->windowPrivateIndex].ptr = gw; groupComputeGlowQuads (w, &gs->glowTexture.matrix); return TRUE; }
static Bool groupDequeueTimer (void *closure) { CompScreen *s = (CompScreen *) closure; GROUP_SCREEN (s); groupDequeueMoveNotifies (s); groupDequeueGrabNotifies (s); groupDequeueUngrabNotifies (s); gs->dequeueTimeoutHandle = 0; return FALSE; }
void groupActivateWindow (CompWindow *w) { CompScreen *s = w->screen; GROUP_SCREEN (s); GROUP_WINDOW (w); if (gw->group && gw->group->tabBar && !IS_TOP_TAB (w, gw->group)) groupChangeTab (gw->slot, RotateUncertain); UNWRAP (gs, s, activateWindow); (*s->activateWindow)(w); WRAP (gs, s, activateWindow, groupActivateWindow); }
/* * groupDonePaintScreen * */ void groupDonePaintScreen (CompScreen *s) { GroupSelection *group; GROUP_SCREEN (s); UNWRAP (gs, s, donePaintScreen); (*s->donePaintScreen)(s); WRAP (gs, s, donePaintScreen, groupDonePaintScreen); for (group = gs->groups; group; group = group->next) { if (group->tabbingState != NoTabbing) damageScreen (s); else if (group->changeState != NoTabChange) damageScreen (s); else if (group->tabBar) { Bool needDamage = FALSE; if ((group->tabBar->state == PaintFadeIn) || (group->tabBar->state == PaintFadeOut)) { needDamage = TRUE; } if (group->tabBar->textLayer) { if ((group->tabBar->textLayer->state == PaintFadeIn) || (group->tabBar->textLayer->state == PaintFadeOut)) { needDamage = TRUE; } } if (group->tabBar->bgAnimation) needDamage = TRUE; if (gs->draggedSlot) needDamage = TRUE; if (needDamage) groupDamageTabBarRegion (group); } } }
/* * groupIsGroupWindow * */ Bool groupIsGroupWindow (CompWindow *w) { GROUP_SCREEN (w->screen); if (w->attrib.override_redirect) return FALSE; if (w->type & CompWindowTypeDesktopMask) return FALSE; if (w->invisible) return FALSE; if (!matchEval (&gs->window_match, w)) return FALSE; return TRUE; }
/* * groupGetOutputExtentsForWindow * */ void groupGetOutputExtentsForWindow (CompWindow *w, CompWindowExtents *output) { GROUP_SCREEN (w->screen); GROUP_WINDOW (w); UNWRAP (gs, w->screen, getOutputExtentsForWindow); (*w->screen->getOutputExtentsForWindow)(w, output); WRAP (gs, w->screen, getOutputExtentsForWindow, groupGetOutputExtentsForWindow); if (gw->group && gw->group->nWins > 1) { GROUP_DISPLAY (&display); const BananaValue * option_glow_size = bananaGetOption (bananaIndex, "glow_size", w->screen->screenNum); const BananaValue * option_glow_type = bananaGetOption (bananaIndex, "glow_type", w->screen->screenNum); int glowSize = option_glow_size->i; int glowType = option_glow_type->i; int glowTextureSize = gd->glowTextureProperties[glowType].textureSize; int glowOffset = gd->glowTextureProperties[glowType].glowOffset; glowSize = glowSize * (glowTextureSize - glowOffset) / glowTextureSize; /* glowSize is the size of the glow outside the window decoration * (w->input), while w->output includes the size of w->input * this is why we have to add w->input here */ output->left = MAX (output->left, glowSize + w->input.left); output->right = MAX (output->right, glowSize + w->input.right); output->top = MAX (output->top, glowSize + w->input.top); output->bottom = MAX (output->bottom, glowSize + w->input.bottom); } }
static void groupDequeueUngrabNotifies (CompScreen *s) { GroupPendingUngrabs *ungrab; GROUP_SCREEN (s); gs->queued = TRUE; while (gs->pendingUngrabs) { ungrab = gs->pendingUngrabs; gs->pendingUngrabs = gs->pendingUngrabs->next; (*(ungrab->w)->screen->windowUngrabNotify) (ungrab->w); free (ungrab); } gs->queued = FALSE; }
void groupEnqueueMoveNotify (CompWindow *w, int dx, int dy, Bool immediate, Bool sync) { GroupPendingMoves *move; GROUP_SCREEN (w->screen); move = malloc (sizeof (GroupPendingMoves)); if (!move) return; move->w = w; move->dx = dx; move->dy = dy; move->immediate = immediate; move->sync = sync; move->next = NULL; if (gs->pendingMoves) { GroupPendingMoves *temp; for (temp = gs->pendingMoves; temp->next; temp = temp->next); temp->next = move; } else gs->pendingMoves = move; if (!gs->dequeueTimeoutHandle) { gs->dequeueTimeoutHandle = compAddTimeout (0, 0, groupDequeueTimer, (void *) w->screen); } }
void groupWindowStateChangeNotify (CompWindow *w, unsigned int lastState) { CompScreen *s = w->screen; GROUP_DISPLAY (&display); GROUP_SCREEN (s); GROUP_WINDOW (w); if (gw->group && !gd->ignoreMode) { const BananaValue * option_maximize_unmaximize_all = bananaGetOption (bananaIndex, "maximize_unmaximize_all", s->screenNum); if (((lastState & MAXIMIZE_STATE) != (w->state & MAXIMIZE_STATE)) && option_maximize_unmaximize_all->b) { int i; for (i = 0; i < gw->group->nWins; i++) { CompWindow *cw = gw->group->windows[i]; if (!cw) continue; if (cw->id == w->id) continue; maximizeWindow (cw, w->state & MAXIMIZE_STATE); } } } UNWRAP (gs, s, windowStateChangeNotify); (*s->windowStateChangeNotify)(w, lastState); WRAP (gs, s, windowStateChangeNotify, groupWindowStateChangeNotify); }
void groupEnqueueGrabNotify (CompWindow *w, int x, int y, unsigned int state, unsigned int mask) { GroupPendingGrabs *grab; GROUP_SCREEN (w->screen); grab = malloc (sizeof (GroupPendingGrabs)); if (!grab) return; grab->w = w; grab->x = x; grab->y = y; grab->state = state; grab->mask = mask; grab->next = NULL; if (gs->pendingGrabs) { GroupPendingGrabs *temp; for (temp = gs->pendingGrabs; temp->next; temp = temp->next); temp->next = grab; } else gs->pendingGrabs = grab; if (!gs->dequeueTimeoutHandle) { gs->dequeueTimeoutHandle = compAddTimeout (0, 0, groupDequeueTimer, (void *) w->screen); } }
/* * groupaintTransformedOutput * */ void groupPaintTransformedOutput (CompScreen *s, const ScreenPaintAttrib *sa, const CompTransform *transform, Region region, CompOutput *output, unsigned int mask) { GROUP_SCREEN (s); UNWRAP (gs, s, paintTransformedOutput); (*s->paintTransformedOutput)(s, sa, transform, region, output, mask); WRAP (gs, s, paintTransformedOutput, groupPaintTransformedOutput); if ((gs->vpX == s->x) && (gs->vpY == s->y)) { gs->painted = TRUE; if ((gs->grabState == ScreenGrabTabDrag) && gs->draggedSlot && gs->dragged) { CompTransform wTransform = *transform; (*s->applyScreenTransform)(s, sa, output, &wTransform); transformToScreenSpace (s, output, -sa->zTranslate, &wTransform); glPushMatrix (); glLoadMatrixf (wTransform.m); groupPaintThumb (NULL, gs->draggedSlot, &wTransform, OPAQUE); glPopMatrix (); } else if (gs->grabState == ScreenGrabSelect) { groupPaintSelectionOutline (s, sa, transform, output, TRUE); } } }
/* * groupGrabScreen * */ void groupGrabScreen (CompScreen *s, GroupScreenGrabState newState) { GROUP_SCREEN (s); if ((gs->grabState != newState) && gs->grabIndex) { removeScreenGrab (s, gs->grabIndex, NULL); gs->grabIndex = 0; } if (newState == ScreenGrabSelect) { gs->grabIndex = pushScreenGrab (s, None, "group"); } else if (newState == ScreenGrabTabDrag) { gs->grabIndex = pushScreenGrab (s, None, "group-drag"); } gs->grabState = newState; }
static void groupDequeueGrabNotifies (CompScreen *s) { GroupPendingGrabs *grab; GROUP_SCREEN (s); gs->queued = TRUE; while (gs->pendingGrabs) { grab = gs->pendingGrabs; gs->pendingGrabs = gs->pendingGrabs->next; (*(grab->w)->screen->windowGrabNotify) (grab->w, grab->x, grab->y, grab->state, grab->mask); free (grab); } gs->queued = FALSE; }
void GroupWindow::enqueueMoveNotify (int dx, int dy, bool immediate, bool sync) { GroupWindow::PendingMoves *move; GROUP_SCREEN (screen); move = new GroupWindow::PendingMoves; if (!move) return; move->w = window; move->dx = dx; move->dy = dy; move->immediate = immediate; move->sync = sync; move->next = NULL; if (gs->mPendingMoves) { GroupWindow::PendingMoves *temp; for (temp = gs->mPendingMoves; temp->next; temp = temp->next); temp->next = move; } else gs->mPendingMoves = move; if (!gs->mDequeueTimeoutHandle.active ()) { gs->mDequeueTimeoutHandle.start (); } }
void GroupWindow::enqueueGrabNotify (int x, int y, unsigned int state, unsigned int mask) { GroupWindow::PendingGrabs *grab; GROUP_SCREEN (screen); grab = new GroupWindow::PendingGrabs; if (!grab) return; grab->w = window; grab->x = x; grab->y = y; grab->state = state; grab->mask = mask; grab->next = NULL; if (gs->mPendingGrabs) { GroupWindow::PendingGrabs *temp; for (temp = gs->mPendingGrabs; temp->next; temp = temp->next); temp->next = grab; } else gs->mPendingGrabs = grab; if (!gs->mDequeueTimeoutHandle.active ()) { gs->mDequeueTimeoutHandle.start (); } }
void groupDequeueMoveNotifies (CompScreen *s) { GroupPendingMoves *move; GroupPendingSyncs *syncs = NULL, *sync; GROUP_SCREEN (s); gs->queued = TRUE; while (gs->pendingMoves) { move = gs->pendingMoves; gs->pendingMoves = move->next; moveWindow (move->w, move->dx, move->dy, TRUE, move->immediate); if (move->sync) { sync = malloc (sizeof (GroupPendingSyncs)); if (sync) { GROUP_WINDOW (move->w); gw->needsPosSync = TRUE; sync->w = move->w; sync->next = syncs; syncs = sync; } } free (move); } if (syncs) groupDequeueSyncs (syncs); gs->queued = FALSE; }
static void groupChangeNotify (const char *optionName, BananaType optionType, const BananaValue *optionValue, int screenNum) { GROUP_DISPLAY (&display); if (strcasecmp (optionName, "window_match") == 0) { CompScreen *s = getScreenFromScreenNum (screenNum); GROUP_SCREEN (s); matchFini (&gs->window_match); matchInit (&gs->window_match); matchAddFromString (&gs->window_match, optionValue->s); matchUpdate (&gs->window_match); } else if (strcasecmp (optionName, "tab_base_color") == 0 || strcasecmp (optionName, "tab_highlight_color") == 0 || strcasecmp (optionName, "tab_border_color") == 0 || strcasecmp (optionName, "tab_style") == 0 || strcasecmp (optionName, "border_radius") == 0 || strcasecmp (optionName, "border_width") == 0) { GroupSelection *group; CompScreen *s = getScreenFromScreenNum (screenNum); GROUP_SCREEN (s); for (group = gs->groups; group; group = group->next) if (group->tabBar) groupRenderTabBarBackground (group); } else if (strcasecmp (optionName, "tabbar_font_size") == 0 || strcasecmp (optionName, "tabbar_font_color") == 0) { GroupSelection *group; CompScreen *s = getScreenFromScreenNum (screenNum); GROUP_SCREEN (s); for (group = gs->groups; group; group = group->next) groupRenderWindowTitle (group); } else if (strcasecmp (optionName, "thumb_size") == 0 || strcasecmp (optionName, "thumb_space") == 0) { GroupSelection *group; CompScreen *s = getScreenFromScreenNum (screenNum); GROUP_SCREEN (s); for (group = gs->groups; group; group = group->next) if (group->tabBar) { BoxPtr box = &group->tabBar->region->extents; groupRecalcTabBarPos (group, (box->x1 + box->x2 ) / 2, box->x1, box->x2); } } else if (strcasecmp (optionName, "glow") == 0 || strcasecmp (optionName, "glow_size") == 0) { CompScreen *s = getScreenFromScreenNum (screenNum); GROUP_SCREEN (s); CompWindow *w; for (w = s->windows; w; w = w->next) { GROUP_WINDOW (w); groupComputeGlowQuads (w, &gs->glowTexture.matrix); if (gw->glowQuads) { damageWindowOutputExtents (w); updateWindowOutputExtents (w); damageWindowOutputExtents (w); } } } else if (strcasecmp (optionName, "glow_type") == 0) { CompScreen *s = getScreenFromScreenNum (screenNum); GROUP_SCREEN (s); int glowType; GlowTextureProperties *glowProperty; GROUP_DISPLAY (&display); const BananaValue * option_glow_type = bananaGetOption (bananaIndex, "glow_type", s->screenNum); glowType = option_glow_type->i; glowProperty = &gd->glowTextureProperties[glowType]; finiTexture (s, &gs->glowTexture); initTexture (s, &gs->glowTexture); imageDataToTexture (s, &gs->glowTexture, glowProperty->textureData, glowProperty->textureSize, glowProperty->textureSize, GL_RGBA, GL_UNSIGNED_BYTE); const BananaValue * option_glow = bananaGetOption (bananaIndex, "glow", s->screenNum); if (option_glow->b && gs->groups) { CompWindow *w; for (w = s->windows; w; w = w->next) groupComputeGlowQuads (w, &gs->glowTexture.matrix); damageScreen (s); } } else if (strcasecmp (optionName, "select_button") == 0) updateButton (optionValue->s, &gd->select_button); else if (strcasecmp (optionName, "select_single_key") == 0) updateKey (optionValue->s, &gd->select_single_key); else if (strcasecmp (optionName, "group_key") == 0) updateKey (optionValue->s, &gd->group_key); else if (strcasecmp (optionName, "ungroup_key") == 0) updateKey (optionValue->s, &gd->ungroup_key); else if (strcasecmp (optionName, "remove_key") == 0) updateKey (optionValue->s, &gd->remove_key); else if (strcasecmp (optionName, "close_key") == 0) updateKey (optionValue->s, &gd->close_key); else if (strcasecmp (optionName, "ignore_key") == 0) updateKey (optionValue->s, &gd->ignore_key); else if (strcasecmp (optionName, "tabmode_key") == 0) updateKey (optionValue->s, &gd->tabmode_key); else if (strcasecmp (optionName, "change_tab_left_key") == 0) updateKey (optionValue->s, &gd->change_tab_left_key); else if (strcasecmp (optionName, "change_tab_right_key") == 0) updateKey (optionValue->s, &gd->change_tab_right_key); else if (strcasecmp (optionName, "change_color_key") == 0) updateKey (optionValue->s, &gd->change_color_key); else if (strcasecmp (optionName, "autotab_windows") == 0) { CompScreen *s = getScreenFromScreenNum (screenNum); GROUP_SCREEN (s); int i; if (gs->autotab && gs->autotabCount != 0) { for (i = 0; i <= gs->autotabCount - 1; i++) matchFini (&gs->autotab[i]); free (gs->autotab); } gs->autotabCount = optionValue->list.nItem; gs->autotab = malloc (gs->autotabCount * sizeof (CompMatch)); for (i = 0; i <= gs->autotabCount - 1; i++) { matchInit (&gs->autotab[i]); matchAddFromString (&gs->autotab[i], optionValue->list.item[i].s); matchUpdate (&gs->autotab[i]); } } }
/* * 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); } }
/* * 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 (); } } } }
/* * groupFiniScreen * */ static void groupFiniScreen (CompPlugin *p, CompScreen *s) { GROUP_SCREEN (s); if (gs->groups) { GroupSelection *group, *nextGroup; for (group = gs->groups; group; ) { if (group->tabBar) { GroupTabBarSlot *slot, *nextSlot; for (slot = group->tabBar->slots; slot; ) { if (slot->region) XDestroyRegion (slot->region); nextSlot = slot->next; free (slot); slot = nextSlot; } groupDestroyCairoLayer (s, group->tabBar->textLayer); groupDestroyCairoLayer (s, group->tabBar->bgLayer); groupDestroyCairoLayer (s, group->tabBar->selectionLayer); if (group->inputPrevention) XDestroyWindow (display.display, group->inputPrevention); if (group->tabBar->region) XDestroyRegion (group->tabBar->region); if (group->tabBar->timeoutHandle) compRemoveTimeout (group->tabBar->timeoutHandle); free (group->tabBar); } nextGroup = group->next; free (group); group = nextGroup; } } if (gs->tmpSel.windows) free (gs->tmpSel.windows); if (gs->grabIndex) groupGrabScreen (s, ScreenGrabNone); if (gs->dragHoverTimeoutHandle) compRemoveTimeout (gs->dragHoverTimeoutHandle); if (gs->showDelayTimeoutHandle) compRemoveTimeout (gs->showDelayTimeoutHandle); if (gs->dequeueTimeoutHandle) compRemoveTimeout (gs->dequeueTimeoutHandle); if (gs->initialActionsTimeoutHandle) compRemoveTimeout (gs->initialActionsTimeoutHandle); freeWindowPrivateIndex (s, gs->windowPrivateIndex); matchFini (&gs->window_match); UNWRAP (gs, s, windowMoveNotify); UNWRAP (gs, s, windowResizeNotify); UNWRAP (gs, s, getOutputExtentsForWindow); UNWRAP (gs, s, preparePaintScreen); UNWRAP (gs, s, paintOutput); UNWRAP (gs, s, drawWindow); UNWRAP (gs, s, paintWindow); UNWRAP (gs, s, paintTransformedOutput); UNWRAP (gs, s, donePaintScreen); UNWRAP (gs, s, windowGrabNotify); UNWRAP (gs, s, windowUngrabNotify); UNWRAP (gs, s, damageWindowRect); UNWRAP (gs, s, windowStateChangeNotify); UNWRAP (gs, s, activateWindow); finiTexture (s, &gs->glowTexture); free (gs); }
/* * groupPaintSelectionOutline * */ static void groupPaintSelectionOutline (CompScreen *s, const ScreenPaintAttrib *sa, const CompTransform *transform, CompOutput *output, Bool transformed) { int x1, x2, y1, y2; GROUP_SCREEN (s); x1 = MIN (gs->x1, gs->x2); y1 = MIN (gs->y1, gs->y2); x2 = MAX (gs->x1, gs->x2); y2 = MAX (gs->y1, gs->y2); const BananaValue * option_fill_color = bananaGetOption (bananaIndex, "fill_color", s->screenNum); const BananaValue * option_line_color = bananaGetOption (bananaIndex, "line_color", s->screenNum); unsigned short fill_color[] = { 0, 0, 0, 0 }; unsigned short line_color[] = { 0, 0, 0, 0 }; stringToColor (option_fill_color->s, fill_color); stringToColor (option_line_color->s, line_color); if (gs->grabState == ScreenGrabSelect) { CompTransform sTransform = *transform; if (transformed) { (*s->applyScreenTransform)(s, sa, output, &sTransform); transformToScreenSpace (s, output, -sa->zTranslate, &sTransform); } else transformToScreenSpace (s, output, -DEFAULT_Z_CAMERA, &sTransform); glPushMatrix (); glLoadMatrixf (sTransform.m); glDisableClientState (GL_TEXTURE_COORD_ARRAY); glEnable (GL_BLEND); glColor4usv (fill_color); glRecti (x1, y2, x2, y1); glColor4usv (line_color); glBegin (GL_LINE_LOOP); glVertex2i (x1, y1); glVertex2i (x2, y1); glVertex2i (x2, y2); glVertex2i (x1, y2); glEnd (); glColor4usv (defaultColor); glDisable (GL_BLEND); glEnableClientState (GL_TEXTURE_COORD_ARRAY); glPopMatrix (); } }
/* * groupPaintOutput * */ Bool groupPaintOutput (CompScreen *s, const ScreenPaintAttrib *sAttrib, const CompTransform *transform, Region region, CompOutput *output, unsigned int mask) { GroupSelection *group; Bool status; GROUP_SCREEN (s); GROUP_DISPLAY (&display); gs->painted = FALSE; gs->vpX = s->x; gs->vpY = s->y; if (gd->resizeInfo) { mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS_MASK; } else { for (group = gs->groups; group; group = group->next) { if (group->changeState != NoTabChange || group->tabbingState != NoTabbing) { mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS_MASK; } else if (group->tabBar && (group->tabBar->state != PaintOff)) { mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS_MASK; } } } UNWRAP (gs, s, paintOutput); status = (*s->paintOutput)(s, sAttrib, transform, region, output, mask); WRAP (gs, s, paintOutput, groupPaintOutput); if (status && !gs->painted) { if ((gs->grabState == ScreenGrabTabDrag) && gs->draggedSlot) { CompTransform wTransform = *transform; PaintState state; GROUP_WINDOW (gs->draggedSlot->window); transformToScreenSpace (s, output, -DEFAULT_Z_CAMERA, &wTransform); glPushMatrix (); glLoadMatrixf (wTransform.m); /* prevent tab bar drawing.. */ state = gw->group->tabBar->state; gw->group->tabBar->state = PaintOff; groupPaintThumb (NULL, gs->draggedSlot, &wTransform, OPAQUE); gw->group->tabBar->state = state; glPopMatrix (); } else if (gs->grabState == ScreenGrabSelect) { groupPaintSelectionOutline (s, sAttrib, transform, output, FALSE); } } return status; }
/* * groupDrawWindow * */ Bool groupDrawWindow (CompWindow *w, const CompTransform *transform, const FragmentAttrib *attrib, Region region, unsigned int mask) { Bool status; CompScreen *s = w->screen; GROUP_WINDOW (w); GROUP_SCREEN (s); if (gw->group && (gw->group->nWins > 1) && gw->glowQuads) { if (mask & PAINT_WINDOW_TRANSFORMED_MASK) region = &infiniteRegion; if (region->numRects) { REGION box; int i; box.rects = &box.extents; box.numRects = 1; w->vCount = w->indexCount = 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) { (*s->addWindowGeometry)(w, &gw->glowQuads[i].matrix, 1, &box, region); } } if (w->vCount) { FragmentAttrib fAttrib = *attrib; GLushort average; GLushort color[3] = {gw->group->color[0], gw->group->color[1], gw->group->color[2]}; /* Apply brightness to color. */ color[0] *= (float)attrib->brightness / BRIGHT; color[1] *= (float)attrib->brightness / BRIGHT; color[2] *= (float)attrib->brightness / BRIGHT; /* Apply saturation to color. */ average = (color[0] + color[1] + color[2]) / 3; color[0] = average + (color[0] - average) * attrib->saturation / COLOR; color[1] = average + (color[1] - average) * attrib->saturation / COLOR; color[2] = average + (color[2] - average) * attrib->saturation / COLOR; fAttrib.opacity = OPAQUE; fAttrib.saturation = COLOR; fAttrib.brightness = BRIGHT; screenTexEnvMode (s, GL_MODULATE); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glColor4us (color[0], color[1], color[2], attrib->opacity); /* we use PAINT_WINDOW_TRANSFORMED_MASK here to force the usage of a good texture filter */ (*s->drawWindowTexture)(w, &gs->glowTexture, &fAttrib, mask | PAINT_WINDOW_BLEND_MASK | PAINT_WINDOW_TRANSLUCENT_MASK | PAINT_WINDOW_TRANSFORMED_MASK); glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA); screenTexEnvMode (s, GL_REPLACE); glColor4usv (defaultColor); } } } UNWRAP (gs, s, drawWindow); status = (*s->drawWindow)(w, transform, attrib, region, mask); WRAP (gs, s, drawWindow, groupDrawWindow); return status; }
/* * 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; }