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]); } } }
static void decorHandleEvent (CompDisplay *d, XEvent *event) { Window activeWindow = d->activeWindow; CompWindow *w; DECOR_DISPLAY (d); switch (event->type) { case DestroyNotify: w = findWindowAtDisplay (d, event->xdestroywindow.window); if (w) { DECOR_SCREEN (w->screen); if (w->id == ds->dmWin) decorCheckForDmOnScreen (w->screen, TRUE); } break; case MapRequest: w = findWindowAtDisplay (d, event->xmaprequest.window); if (w) decorWindowUpdate (w, TRUE); break; case ClientMessage: if (event->xclient.message_type == dd->requestFrameExtentsAtom) { w = findWindowAtDisplay (d, event->xclient.window); if (w) decorWindowUpdate (w, TRUE); } break; default: if (event->type == d->damageEvent + XDamageNotify) { XDamageNotifyEvent *de = (XDamageNotifyEvent *) event; DecorTexture *t; for (t = dd->textures; t; t = t->next) { if (t->pixmap == de->drawable) { DecorWindow *dw; DecorScreen *ds; CompScreen *s; t->texture.oldMipmaps = TRUE; for (s = d->screens; s; s = s->next) { ds = GET_DECOR_SCREEN (s, dd); for (w = s->windows; w; w = w->next) { if (w->shaded || w->mapNum) { dw = GET_DECOR_WINDOW (w, ds); if (dw->wd && dw->wd->decor->texture == t) damageWindowOutputExtents (w); } } } return; } } } break; } UNWRAP (dd, d, handleEvent); (*d->handleEvent) (d, event); WRAP (dd, d, handleEvent, decorHandleEvent); if (d->activeWindow != activeWindow) { w = findWindowAtDisplay (d, activeWindow); if (w) decorWindowUpdate (w, TRUE); w = findWindowAtDisplay (d, d->activeWindow); if (w) decorWindowUpdate (w, TRUE); } switch (event->type) { case PropertyNotify: if (event->xproperty.atom == dd->winDecorAtom) { w = findWindowAtDisplay (d, event->xproperty.window); if (w) { decorWindowUpdateDecoration (w); decorWindowUpdate (w, TRUE); } } else if (event->xproperty.atom == d->mwmHintsAtom) { w = findWindowAtDisplay (d, event->xproperty.window); if (w) decorWindowUpdate (w, TRUE); } else { CompScreen *s; s = findScreenAtDisplay (d, event->xproperty.window); if (s) { if (event->xproperty.atom == dd->supportingDmCheckAtom) { decorCheckForDmOnScreen (s, TRUE); } else { int i; for (i = 0; i < DECOR_NUM; i++) { if (event->xproperty.atom == dd->decorAtom[i]) { DECOR_SCREEN (s); if (ds->decor[i]) decorReleaseDecoration (s, ds->decor[i]); ds->decor[i] = decorCreateDecoration (s, s->root, dd->decorAtom[i]); for (w = s->windows; w; w = w->next) decorWindowUpdate (w, TRUE); } } } } } break; default: if (d->shapeExtension && event->type == d->shapeEvent + ShapeNotify) { w = findWindowAtDisplay (d, ((XShapeEvent *) event)->window); if (w) decorWindowUpdate (w, TRUE); } break; } }
/* * groupDeleteGroup * */ void groupDeleteGroup (GroupSelection *group) { GroupSelection *next, *prev; CompScreen *s = group->screen; GROUP_SCREEN (s); GROUP_DISPLAY (&display); if (group->windows) { int i; if (group->tabBar) { /* set up untabbing animation and delete the group at the end of the animation */ groupUntabGroup (group); group->ungroupState = UngroupAll; return; } for (i = 0; i < group->nWins; i++) { CompWindow *cw = group->windows[i]; GROUP_WINDOW (cw); damageWindowOutputExtents (cw); gw->group = NULL; updateWindowOutputExtents (cw); groupUpdateWindowProperty (cw); const BananaValue * option_autotab_create = bananaGetOption (bananaIndex, "autotab_create", s->screenNum); if (option_autotab_create->b && groupIsGroupWindow (cw)) { groupAddWindowToGroup (cw, NULL, 0); groupTabGroup (cw); } } free (group->windows); group->windows = NULL; } else if (group->tabBar) groupDeleteTabBar (group); prev = group->prev; next = group->next; /* relink stack */ if (prev || next) { if (prev) { if (next) prev->next = next; else prev->next = NULL; } if (next) { if (prev) next->prev = prev; else { next->prev = NULL; gs->groups = next; } } } else gs->groups = NULL; if (group == gs->lastHoveredGroup) gs->lastHoveredGroup = NULL; if (group == gd->lastRestackedGroup) gd->lastRestackedGroup = NULL; free (group); }
static Bool decorWindowUpdate (CompWindow *w, Bool allowDecoration) { WindowDecoration *wd; Decoration *old, *decor = NULL; Bool decorate = FALSE; CompMatch *match; int moveDx, moveDy; int oldShiftX = 0; int oldShiftY = 0; DECOR_DISPLAY (w->screen->display); DECOR_SCREEN (w->screen); DECOR_WINDOW (w); wd = dw->wd; old = (wd) ? wd->decor : NULL; switch (w->type) { case CompWindowTypeDialogMask: case CompWindowTypeModalDialogMask: case CompWindowTypeUtilMask: case CompWindowTypeMenuMask: case CompWindowTypeNormalMask: if (w->mwmDecor & (MwmDecorAll | MwmDecorTitle)) decorate = TRUE; default: break; } if (w->wmType & (CompWindowTypeDockMask | CompWindowTypeDesktopMask)) decorate = FALSE; if (w->attrib.override_redirect) decorate = FALSE; if (decorate) { match = &dd->opt[DECOR_DISPLAY_OPTION_DECOR_MATCH].value.match; if (!matchEval (match, w)) decorate = FALSE; } if (decorate) { if (dw->decor && decorCheckSize (w, dw->decor)) { decor = dw->decor; } else { if (w->id == w->screen->display->activeWindow) decor = ds->decor[DECOR_ACTIVE]; else decor = ds->decor[DECOR_NORMAL]; } } else { match = &dd->opt[DECOR_DISPLAY_OPTION_SHADOW_MATCH].value.match; if (matchEval (match, w)) { if (w->region->numRects == 1) decor = ds->decor[DECOR_BARE]; if (decor) { if (!decorCheckSize (w, decor)) decor = NULL; } } } if (!ds->dmWin || !allowDecoration) decor = NULL; if (decor == old) return FALSE; damageWindowOutputExtents (w); if (old) { oldShiftX = decorWindowShiftX (w); oldShiftY = decorWindowShiftY (w); destroyWindowDecoration (w->screen, wd); } if (decor) { dw->wd = createWindowDecoration (decor); if (!dw->wd) return FALSE; if ((w->state & MAXIMIZE_STATE) == MAXIMIZE_STATE) setWindowFrameExtents (w, &decor->maxInput); else setWindowFrameExtents (w, &decor->input); moveDx = decorWindowShiftX (w) - oldShiftX; moveDy = decorWindowShiftY (w) - oldShiftY; updateWindowOutputExtents (w); damageWindowOutputExtents (w); updateWindowDecorationScale (w); } else { CompWindowExtents emptyInput; memset (&emptyInput, 0, sizeof (emptyInput)); setWindowFrameExtents (w, &emptyInput); dw->wd = NULL; moveDx = -oldShiftX; moveDy = -oldShiftY; } if (w->placed && !w->attrib.override_redirect && (moveDx || moveDy)) { XWindowChanges xwc; unsigned int mask = CWX | CWY; xwc.x = w->serverX + moveDx; xwc.y = w->serverY + moveDy; if (w->state & CompWindowStateFullscreenMask) mask &= ~(CWX | CWY); if (w->state & CompWindowStateMaximizedHorzMask) mask &= ~CWX; if (w->state & CompWindowStateMaximizedVertMask) mask &= ~CWY; if (w->saveMask & CWX) w->saveWc.x += moveDx; if (w->saveMask & CWY) w->saveWc.y += moveDy; if (mask) configureXWindow (w, mask, &xwc); } return TRUE; }
/* * groupDeleteGroupWindow * */ void groupDeleteGroupWindow (CompWindow *w) { GroupSelection *group; GROUP_WINDOW (w); GROUP_SCREEN (w->screen); if (!gw->group) return; group = gw->group; if (group->tabBar && gw->slot) { if (gs->draggedSlot && gs->dragged && gs->draggedSlot->window->id == w->id) { groupUnhookTabBarSlot (group->tabBar, gw->slot, FALSE); } else groupDeleteTabBarSlot (group->tabBar, gw->slot); } if (group->nWins && group->windows) { CompWindow **buf = group->windows; if (group->nWins > 1) { int counter = 0; int i; group->windows = calloc (group->nWins - 1, sizeof(CompWindow *)); for (i = 0; i < group->nWins; i++) { if (buf[i]->id == w->id) continue; group->windows[counter++] = buf[i]; } group->nWins = counter; if (group->nWins == 1) { /* Glow was removed from this window, too */ damageWindowOutputExtents (group->windows[0]); updateWindowOutputExtents (group->windows[0]); const BananaValue * option_auto_ungroup = bananaGetOption (bananaIndex, "auto_ungroup", w->screen->screenNum); if (option_auto_ungroup->b) { if (group->changeState != NoTabChange) { /* a change animation is pending: this most likely means that a window must be moved back onscreen, so we do that here */ CompWindow *lw = group->windows[0]; groupSetWindowVisibility (lw, TRUE); } const BananaValue * option_autotab_create = bananaGetOption (bananaIndex, "autotab_create", w->screen->screenNum); if (!option_autotab_create->b) groupDeleteGroup (group); } } } else { group->windows = NULL; groupDeleteGroup (group); } free (buf); damageWindowOutputExtents (w); gw->group = NULL; updateWindowOutputExtents (w); groupUpdateWindowProperty (w); } }