Index: src/group/group.h =================================================================== --- src/group/group.h (Revision 4352) +++ src/group/group.h (Arbeitskopie) @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -422,6 +423,15 @@ GLushort color[4]; }; +typedef struct _GroupWindowHideInfo { + Window frameWindow; + unsigned long skipState; + unsigned long shapeMask; + XRectangle *inputRects; + int nInputRects; + int inputRectOrdering; +} GroupWindowHideInfo; + /* * GroupDisplay structure */ @@ -514,6 +524,7 @@ GlowQuad *glowQuads; GroupWindowState windowState; + GroupWindowHideInfo *windowHideInfo; // for tab animation Bool ungroup; @@ -575,6 +586,8 @@ /* * tab.c */ +void groupSetWindowVisibility(CompWindow *w, Bool visible); +void groupClearWindowInputShape(CompWindow *w, GroupWindowHideInfo *hideInfo); void groupHandleChanges(CompScreen* s); void groupHandleScreenActions(CompScreen *s); void groupHandleHoverDetection(GroupSelection *group); Index: src/group/init.c =================================================================== --- src/group/init.c (Revision 4352) +++ src/group/init.c (Arbeitskopie) @@ -272,6 +272,8 @@ gw->destination.x = 0; gw->destination.y = 0; + gw->windowHideInfo = NULL; + if (w->minimized) gw->windowState = WindowMinimized; else if (w->shaded) @@ -298,11 +300,8 @@ { GROUP_WINDOW(w); - /* TODO: this needs more work; positioning is not correct - at the moment - but it's way better than leaving the - window offscreen */ - if (gw->group && gw->group->tabBar && !IS_TOP_TAB(w, gw->group)) - moveWindowOnscreen(w); + if (gw->windowHideInfo) + groupSetWindowVisibility(w, TRUE); if (gw->glowQuads) free (gw->glowQuads); Index: src/group/tab.c =================================================================== --- src/group/tab.c (Revision 4352) +++ src/group/tab.c (Arbeitskopie) @@ -88,7 +88,119 @@ return clip; } + /* + * groupClearWindowInputShape + * + */ +void +groupClearWindowInputShape(CompWindow *w, GroupWindowHideInfo *hideInfo) +{ + XRectangle *rects; + int count, ordering; + + rects = XShapeGetRectangles(w->screen->display->display, + w->id, ShapeInput, &count, &ordering); + + if (count == 0) { + XFree(rects); + return; + } + + /* check if the returned shape exactly matches the window shape - + if that is true, the window currently has no set input shape */ + if ((count == 1) && + (rects[0].x == -w->serverBorderWidth) && + (rects[0].y == -w->serverBorderWidth) && + (rects[0].width == (w->serverWidth + w->serverBorderWidth)) && + (rects[0].height == (w->serverHeight + w->serverBorderWidth))) + { + count = 0; + } + + if (hideInfo->inputRects) + XFree(hideInfo->inputRects); + + hideInfo->inputRects = rects; + hideInfo->nInputRects = count; + hideInfo->inputRectOrdering = ordering; + + XShapeSelectInput(w->screen->display->display, w->id, NoEventMask); + + XShapeCombineRectangles(w->screen->display->display, w->id, + ShapeInput, 0, 0, NULL, 0, ShapeSet, 0); + + XShapeSelectInput(w->screen->display->display, w->id, ShapeNotify); +} + +/* + * groupSetWindowVisibility + * + */ +void +groupSetWindowVisibility(CompWindow *w, Bool visible) +{ + GROUP_WINDOW(w); + + if (!visible && !gw->windowHideInfo) + { + gw->windowHideInfo = malloc(sizeof(GroupWindowHideInfo)); + + if (!gw->windowHideInfo) + return; + + gw->windowHideInfo->inputRects = NULL; + gw->windowHideInfo->shapeMask = XShapeInputSelected( + w->screen->display->display, w->id); + groupClearWindowInputShape(w, gw->windowHideInfo); + + if (w->frame) { + gw->windowHideInfo->frameWindow = w->frame; + XUnmapWindow(w->screen->display->display, w->frame); + } else + gw->windowHideInfo->frameWindow = None; + + gw->windowHideInfo->skipState = w->state & + (CompWindowStateSkipPagerMask | CompWindowStateSkipTaskbarMask); + w->state |= (CompWindowStateSkipPagerMask | CompWindowStateSkipTaskbarMask); + setWindowState(w->screen->display, w->state, w->id); + } + else if (visible && gw->windowHideInfo) + { + if (gw->windowHideInfo->nInputRects) + { + XShapeCombineRectangles(w->screen->display->display, + w->id, ShapeInput, 0, 0, + gw->windowHideInfo->inputRects, + gw->windowHideInfo->nInputRects, + ShapeSet, gw->windowHideInfo->inputRectOrdering); + } else { + XShapeCombineMask(w->screen->display->display, w->id, + ShapeInput, 0, 0, None, ShapeSet); + } + + if (gw->windowHideInfo->inputRects) + XFree(gw->windowHideInfo->inputRects); + + XShapeSelectInput(w->screen->display->display, w->id, + gw->windowHideInfo->shapeMask); + + if (gw->windowHideInfo->frameWindow) { + if (w->attrib.map_state != IsUnmapped) + XMapWindow(w->screen->display->display, w->frame); + } + + w->state &= ~(CompWindowStateSkipPagerMask | CompWindowStateSkipTaskbarMask); + w->state |= gw->windowHideInfo->skipState; + setWindowState(w->screen->display, w->state, w->id); + + free(gw->windowHideInfo); + gw->windowHideInfo = NULL; + } +} + + +/* * groupTabBarTimeout * * Description: @@ -203,8 +315,8 @@ oldState = bar->state; /* hide tab bars for invisible top windows */ - if ((topTab->state & (CompWindowStateHiddenMask | - CompWindowStateOffscreenMask)) || topTab->invisible) + if ((topTab->state & (CompWindowStateHiddenMask | + CompWindowStateOffscreenMask)) || topTab->invisible) { bar->state = PaintOff; groupSwitchTopTabInput(group, TRUE); @@ -552,7 +664,7 @@ if(group->ungroupState == UngroupSingle && group->prevTopTab == NULL) { gs->queued = TRUE; - moveWindowOnscreen(topTab); + groupSetWindowVisibility(topTab, TRUE); moveWindow(topTab, group->oldTopTabCenterX - WIN_X(topTab) - WIN_WIDTH(topTab) / 2, group->oldTopTabCenterY - WIN_Y(topTab) - WIN_HEIGHT(topTab) / 2, TRUE, TRUE); @@ -571,7 +683,7 @@ } gs->queued = TRUE; - moveWindowOnscreen(topTab); + groupSetWindowVisibility(topTab, TRUE); moveWindow(topTab, group->oldTopTabCenterX - WIN_X(topTab) - WIN_WIDTH(topTab) / 2, group->oldTopTabCenterY - WIN_Y(topTab) - WIN_HEIGHT(topTab) / 2, TRUE, TRUE); @@ -642,7 +754,7 @@ int oldChangeAnimationTime = group->changeAnimationTime; if (group->prevTopTab) - moveWindowOffscreen(PREV_TOP_TAB(group)); + groupSetWindowVisibility(PREV_TOP_TAB(group), FALSE); group->prevTopTab = group->topTab; group->changeState = PaintOff; @@ -701,7 +813,7 @@ if (slot == group->topTab || !(gw->animateState & FINISHED_ANIMATION) || gw->ungroup) continue; - moveWindowOffscreen(w); + groupSetWindowVisibility(w, FALSE); } group->changeTab = FALSE; @@ -800,7 +912,7 @@ if (gw->ungroup) { gs->queued = TRUE; - moveWindowOnscreen(w); + groupSetWindowVisibility(w, TRUE); moveWindow(w, group->oldTopTabCenterX - WIN_X(w) - WIN_WIDTH(w) / 2, group->oldTopTabCenterY - WIN_Y(w) - WIN_HEIGHT(w) / 2, TRUE, TRUE); @@ -1380,6 +1492,11 @@ if(!group || group->tabBar) return; + if (!main->screen->display->shapeExtension) { + printf("group plugin: No X shape extension! Tabbing won't work...\n"); + return; + } + groupInitTabBar(group, main); groupCreateInputPreventionWindow(group); @@ -1490,7 +1607,7 @@ GROUP_WINDOW(cw); gs->queued = TRUE; - moveWindowOnscreen(cw); + groupSetWindowVisibility(cw, TRUE); moveWindow(cw, group->oldTopTabCenterX - WIN_X(cw) - WIN_WIDTH(cw) / 2, group->oldTopTabCenterY - WIN_Y(cw) - WIN_HEIGHT(cw) / 2, TRUE, TRUE); @@ -2429,7 +2546,6 @@ } else if (allowUntab) { groupUntabGroup(gw->group); } - damageScreen(w->screen); Index: src/group/paint.c =================================================================== --- src/group/paint.c (Revision 4352) +++ src/group/paint.c (Arbeitskopie) @@ -1236,7 +1236,6 @@ const CompTransform *transform, Region region, unsigned int mask) { - FragmentAttrib fragment; Bool status; Bool doRotate; GROUP_SCREEN(w->screen); @@ -1288,8 +1287,6 @@ gAttrib.opacity = gAttrib.opacity * opacity / 100; } - initFragmentAttrib(&fragment, &gAttrib); - doRotate = gw->group && (gw->group->changeState != PaintOff) && (IS_TOP_TAB(w, gw->group) || IS_PREV_TOP_TAB(w, gw->group)); @@ -1319,6 +1316,9 @@ mask |= PAINT_WINDOW_TRANSFORMED_MASK; } + if (gw->windowHideInfo) + mask |= PAINT_WINDOW_NO_CORE_INSTANCE_MASK; + UNWRAP(gs, w->screen, paintWindow); status = (*w->screen->paintWindow) (w, &gAttrib, &wTransform, region, mask); Index: src/group/group.c =================================================================== --- src/group/group.c (Revision 4352) +++ src/group/group.c (Arbeitskopie) @@ -322,7 +322,7 @@ CompWindow *lw = group->windows[0]; gs->queued = TRUE; - moveWindowOnscreen(lw); + groupSetWindowVisibility(lw, TRUE); moveWindow(lw, group->oldTopTabCenterX - WIN_X(lw) - WIN_WIDTH(lw) / 2, group->oldTopTabCenterY - WIN_Y(lw) - WIN_HEIGHT(lw) / 2, TRUE, TRUE); syncWindowPosition(lw); @@ -926,7 +926,7 @@ tmpGroup->oldTopTabCenterY = WIN_Y(tw) + WIN_HEIGHT(tw) / 2; gs->queued = TRUE; - moveWindowOnscreen(gs->draggedSlot->window); + groupSetWindowVisibility(gs->draggedSlot->window, TRUE); moveWindow(gs->draggedSlot->window, gw->group->oldTopTabCenterX - WIN_X(gs->draggedSlot->window) - WIN_WIDTH(gs->draggedSlot->window) / 2, gw->group->oldTopTabCenterY - WIN_Y(gs->draggedSlot->window) - WIN_HEIGHT(gs->draggedSlot->window) / 2, @@ -1090,6 +1090,25 @@ groupHandleButtonReleaseEvent(d, event); break; + case MapNotify: + { + CompWindow *cw; + CompWindow *w = findWindowAtDisplay(d, event->xmap.window); + if (!w) + break; + + for (cw = w->screen->windows; cw; cw = cw->next) + { + if (w->id == cw->frame) + { + GROUP_WINDOW(cw); + if (gw->windowHideInfo) + XUnmapWindow(cw->screen->display->display, cw->frame); + } + } + } + break; + case UnmapNotify: { CompWindow *w = findWindowAtDisplay(d, event->xunmap.window); @@ -1160,6 +1179,19 @@ break; default: + if (event->type == d->shapeEvent + ShapeNotify) { + XShapeEvent *se = (XShapeEvent*)event; + if (se->kind == ShapeInput) { + CompWindow *w = findWindowAtDisplay(d, se->window); + + if (w) { + GROUP_WINDOW(w); + + if (gw->windowHideInfo) + groupClearWindowInputShape(w, gw->windowHideInfo); + } + } + } break; } @@ -1483,21 +1515,23 @@ GROUP_WINDOW(w); if (gw->group && !gd->ignoreMode && !gs->queued) { - int i; - for (i = 0; i < gw->group->nWins; i++) { - CompWindow *cw = gw->group->windows[i]; - if (!cw) - continue; + if (gw->group->tabBar) + groupTabSetVisibility(gw->group, FALSE, 0); + else { + int i; + for (i = 0; i < gw->group->nWins; i++) { + CompWindow *cw = gw->group->windows[i]; + if (!cw) + continue; - if (cw->id != w->id) - groupEnqueueGrabNotify (cw, x, y, state, mask); + if (cw->id != w->id) + groupEnqueueGrabNotify (cw, x, y, state, mask); + } } gw->group->grabWindow = w->id; gw->group->grabMask = mask; - if (gw->group->tabBar) - groupTabSetVisibility(gw->group, FALSE, 0); } UNWRAP(gs, w->screen, windowGrabNotify); @@ -1512,23 +1546,25 @@ GROUP_WINDOW(w); if (gw->group && !gd->ignoreMode && !gs->queued) { - int i; + if (!gw->group->tabBar) { + int i; - groupDequeueMoveNotifies(w->screen); + groupDequeueMoveNotifies(w->screen); - for (i = 0; i < gw->group->nWins; i++) { - CompWindow *cw = gw->group->windows[i]; - if (!cw) - continue; + for (i = 0; i < gw->group->nWins; i++) { + CompWindow *cw = gw->group->windows[i]; + if (!cw) + continue; - if (cw->id != w->id) { - GROUP_WINDOW(cw); + if (cw->id != w->id) { + GROUP_WINDOW(cw); - if (gw->needsPosSync) { - syncWindowPosition(cw); - gw->needsPosSync = FALSE; + if (gw->needsPosSync) { + syncWindowPosition(cw); + gw->needsPosSync = FALSE; + } + groupEnqueueUngrabNotify (cw); } - groupEnqueueUngrabNotify (cw); } }