From cec902a3c7ca63b64b0af56bb35e2ca0a776d242 Mon Sep 17 00:00:00 2001 From: Danny Baumann Date: Sun, 29 Jul 2007 14:51:39 +0200 Subject: [PATCH] Restructure grouped resize. Instead of immediately applying each window size change, listen to the resize plugin's change notification and draw the windows stretched until ungrab. --- group-internal.h | 10 +++ group.c | 213 +++++++++++++++++++++++++++++++++++++++++++++--------- init.c | 11 +++- paint.c | 45 ++++++++++-- 4 files changed, 237 insertions(+), 42 deletions(-) diff --git a/group-internal.h b/group-internal.h index 8900132..ca77661 100644 --- a/group-internal.h +++ b/group-internal.h @@ -358,6 +358,11 @@ typedef struct _GroupWindowHideInfo { int inputRectOrdering; } GroupWindowHideInfo; +typedef struct _GroupResizeInfo { + CompWindow *resizedWindow; + XRectangle origGeometry; +} GroupResizeInfo; + /* * GroupDisplay structure */ @@ -368,11 +373,14 @@ typedef struct _GroupDisplay { Bool ignoreMode; + GroupResizeInfo *resizeInfo; + GlowTextureProperties *glowTextureProperties; GroupSelection *lastRestackedGroup; Atom groupWinPropertyAtom; + Atom resizeNotifyAtom; } GroupDisplay; /* @@ -447,6 +455,8 @@ typedef struct _GroupWindow { GroupWindowState windowState; GroupWindowHideInfo *windowHideInfo; + XRectangle *resizeGeometry; + /* For tab animation */ Bool ungroup; int animateState; diff --git a/group.c b/group.c index 2525f86..512889f 100644 --- a/group.c +++ b/group.c @@ -184,6 +184,65 @@ groupUpdateWindowProperty (CompWindow *w) } } +static unsigned int +groupUpdateResizeRectangle (CompWindow *w, + XRectangle *masterGeometry) +{ + XRectangle newGeometry; + unsigned int mask = 0; + int newWidth, newHeight; + + GROUP_WINDOW (w); + GROUP_DISPLAY (w->screen->display); + + if (!gw->resizeGeometry || !gd->resizeInfo) + return 0; + + newGeometry.x = WIN_X (w) + (masterGeometry->x - + gd->resizeInfo->origGeometry.x); + newGeometry.y = WIN_Y (w) + (masterGeometry->y - + gd->resizeInfo->origGeometry.y); + newGeometry.width = WIN_WIDTH (w) + (masterGeometry->width - + gd->resizeInfo->origGeometry.width); + newGeometry.height = WIN_HEIGHT (w) + (masterGeometry->height - + gd->resizeInfo->origGeometry.height); + + constrainNewWindowSize (w, + newGeometry.width, newGeometry.height, + &newWidth, &newHeight); + + if (constrainNewWindowSize (w, + newGeometry.width, newGeometry.height, + &newWidth, &newHeight)) + { + newGeometry.width = newWidth; + newGeometry.height = newHeight; + } + + if (newGeometry.x != gw->resizeGeometry->x) + { + gw->resizeGeometry->x = newGeometry.x; + mask |= CWX; + } + if (newGeometry.y != gw->resizeGeometry->y) + { + gw->resizeGeometry->y = newGeometry.y; + mask |= CWY; + } + if (newGeometry.width != gw->resizeGeometry->width) + { + gw->resizeGeometry->width = newGeometry.width; + mask |= CWWidth; + } + if (newGeometry.height != gw->resizeGeometry->height) + { + gw->resizeGeometry->height = newGeometry.height; + mask |= CWHeight; + } + + return mask; +} + /* * groupGrabScreen * @@ -1398,7 +1457,42 @@ groupHandleEvent (CompDisplay *d, } case ClientMessage: - if (event->xclient.message_type == d->winActiveAtom) + if (event->xclient.message_type == gd->resizeNotifyAtom) + { + CompWindow *w; + w = findWindowAtDisplay (d, event->xclient.window); + + if (w && gd->resizeInfo && (w == gd->resizeInfo->resizedWindow)) + { + GROUP_WINDOW (w); + GROUP_SCREEN (w->screen); + + if (gw->group) + { + int i; + XRectangle rect; + + rect.x = event->xclient.data.l[0]; + rect.y = event->xclient.data.l[1]; + rect.width = event->xclient.data.l[2]; + rect.height = event->xclient.data.l[3]; + + for (i = 0; i < gw->group->nWins; i++) + { + CompWindow *cw = gw->group->windows[i]; + GroupWindow *gcw; + + gcw = GET_GROUP_WINDOW (cw, gs); + if (gcw->resizeGeometry) + { + if (groupUpdateResizeRectangle (cw, &rect)) + addWindowDamage (cw); + } + } + } + } + } + else if (event->xclient.message_type == d->winActiveAtom) { CompWindow *w; w = findWindowAtDisplay (d, event->xclient.window); @@ -1645,40 +1739,12 @@ groupWindowResizeNotify (CompWindow *w, maximizeWindow (cw, w->state & MAXIMIZE_STATE); } } - else if ((gw->group->grabWindow == w->id) && - groupGetResizeAll (w->screen)) - { - int i; - for (i = 0; i < gw->group->nWins; i++) - { - CompWindow *cw = gw->group->windows[i]; - int nx, ny, nwidth, nheight; - XWindowChanges xwc; - if (!cw) - continue; - - if (cw->state & MAXIMIZE_STATE) - continue; - - if (cw->id == w->id) - continue; - - nx = cw->serverX + dx; - ny = cw->serverY + dy; - - nwidth = cw->serverWidth + dwidth; - nheight = cw->serverHeight + dheight; - - constrainNewWindowSize (cw, nwidth, nheight, &nwidth, &nheight); - - xwc.x = nx; - xwc.y = ny; - xwc.width = nwidth; - xwc.height = nheight; + } - configureXWindow (cw, CWX | CWY | CWWidth | CWHeight, &xwc); - } - } + if (gw->resizeGeometry) + { + free (gw->resizeGeometry); + gw->resizeGeometry = NULL; } UNWRAP (gs, w->screen, windowResizeNotify); @@ -1806,6 +1872,10 @@ groupWindowGrabNotify(CompWindow *w, if (gw->group && !gd->ignoreMode && !gs->queued) { + Bool doResizeAll; + doResizeAll = groupGetResizeAll (w->screen) && + (mask & CompWindowGrabResizeMask); + if (gw->group->tabBar) groupTabSetVisibility (gw->group, FALSE, 0); else @@ -1818,7 +1888,39 @@ groupWindowGrabNotify(CompWindow *w, continue; if (cw->id != w->id) + { + GroupWindow *gcw = GET_GROUP_WINDOW (cw, gs); + groupEnqueueGrabNotify (cw, x, y, state, mask); + + if (doResizeAll && !(cw->state & MAXIMIZE_STATE)) + { + if (!gcw->resizeGeometry) + gcw->resizeGeometry = malloc (sizeof (XRectangle)); + if (gcw->resizeGeometry) + { + gcw->resizeGeometry->x = WIN_X (cw); + gcw->resizeGeometry->y = WIN_Y (cw); + gcw->resizeGeometry->width = WIN_WIDTH (cw); + gcw->resizeGeometry->height = WIN_HEIGHT (cw); + } + } + } + } + } + + if (doResizeAll) + { + if (!gd->resizeInfo) + gd->resizeInfo = malloc (sizeof (GroupResizeInfo)); + + if (gd->resizeInfo) + { + gd->resizeInfo->resizedWindow = w; + gd->resizeInfo->origGeometry.x = WIN_X (w); + gd->resizeInfo->origGeometry.y = WIN_Y (w); + gd->resizeInfo->origGeometry.width = WIN_WIDTH (w); + gd->resizeInfo->origGeometry.height = WIN_HEIGHT (w); } } @@ -1842,10 +1944,19 @@ groupWindowUngrabNotify (CompWindow *w) { if (!gw->group->tabBar) { - int i; + int i; + XRectangle rect; groupDequeueMoveNotifies (w->screen); + if (gd->resizeInfo) + { + rect.x = WIN_X (w); + rect.y = WIN_Y (w); + rect.width = WIN_WIDTH (w); + rect.height = WIN_HEIGHT (w); + } + for (i = 0; i < gw->group->nWins; i++) { CompWindow *cw = gw->group->windows[i]; @@ -1856,6 +1967,32 @@ groupWindowUngrabNotify (CompWindow *w) { GROUP_WINDOW (cw); + if (gw->resizeGeometry) + { + unsigned int mask; + + gw->resizeGeometry->x = WIN_X (cw); + gw->resizeGeometry->y = WIN_Y (cw); + gw->resizeGeometry->width = WIN_WIDTH (cw); + gw->resizeGeometry->height = WIN_HEIGHT (cw); + + mask = groupUpdateResizeRectangle (cw, &rect); + if (mask) + { + XWindowChanges xwc; + xwc.x = gw->resizeGeometry->x; + xwc.y = gw->resizeGeometry->y; + xwc.width = gw->resizeGeometry->width; + xwc.height = gw->resizeGeometry->height; + + configureXWindow (cw, mask, &xwc); + } + else + { + free (gw->resizeGeometry); + gw->resizeGeometry = NULL; + } + } if (gw->needsPosSync) { syncWindowPosition (cw); @@ -1866,6 +2003,12 @@ groupWindowUngrabNotify (CompWindow *w) } } + if (gd->resizeInfo) + { + free (gd->resizeInfo); + gd->resizeInfo = NULL; + } + gw->group->grabWindow = None; gw->group->grabMask = 0; } diff --git a/init.c b/init.c index 90b2185..44999a2 100644 --- a/init.c +++ b/init.c @@ -139,10 +139,16 @@ groupInitDisplay (CompPlugin *p, return FALSE; } - gd->glowTextureProperties = (GlowTextureProperties*) glowTextureProperties; + gd->glowTextureProperties = + (GlowTextureProperties*) glowTextureProperties; gd->ignoreMode = FALSE; gd->lastRestackedGroup = NULL; - gd->groupWinPropertyAtom = XInternAtom (d->display, "_COMPIZ_GROUP", 0); + gd->resizeInfo = NULL; + + gd->groupWinPropertyAtom = XInternAtom (d->display, + "_COMPIZ_GROUP", 0); + gd->resizeNotifyAtom = XInternAtom (d->display, + "_COMPIZ_RESIZE_NOTIFY", 0); WRAP (gd, d, handleEvent, groupHandleEvent); @@ -384,6 +390,7 @@ static Bool groupInitWindow(CompPlugin * p, CompWindow * w) gw->destination.y = 0; gw->windowHideInfo = NULL; + gw->resizeGeometry = NULL; if (w->minimized) gw->windowState = WindowMinimized; diff --git a/paint.c b/paint.c index f29f180..200b4e8 100644 --- a/paint.c +++ b/paint.c @@ -983,7 +983,8 @@ groupPaintOutput (CompScreen *s, GroupSelection *group; Bool status; - GROUP_SCREEN(s); + GROUP_SCREEN (s); + GROUP_DISPLAY (s->display); gs->painted = FALSE; gs->vpX = s->x; @@ -998,8 +999,8 @@ groupPaintOutput (CompScreen *s, } } - if (gs->tabBarVisible) - mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS_MASK; + if (gs->tabBarVisible || gd->resizeInfo) + mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS_MASK; UNWRAP (gs, s, paintOutput); status = (*s->paintOutput) (s, sAttrib, transform, region, output, mask); @@ -1452,7 +1453,7 @@ groupPaintWindow (CompWindow *w, if (gw->windowHideInfo) mask |= PAINT_WINDOW_NO_CORE_INSTANCE_MASK; - if (gw->inSelection || doRotate || doTabbing || showTabbar) + if (gw->inSelection || gw->resizeGeometry || doRotate || doTabbing || showTabbar) { WindowPaintAttrib wAttrib = *attrib; CompTransform wTransform = *transform; @@ -1506,7 +1507,41 @@ groupPaintWindow (CompWindow *w, animProgress = 1 - (timeLeft / (2 * animTime)); } - if (doRotate || doTabbing) + if (gw->resizeGeometry) + { + int xOrigin, yOrigin; + float xScale, yScale; + float stretchWidth, stretchHeight; + int width, height; + + width = w->width + w->input.left + w->input.right; + height = w->height + w->input.top + w->input.bottom; + + stretchWidth = gw->resizeGeometry->width + + w->serverBorderWidth * 2 + + w->input.right + w->input.left; + stretchHeight = gw->resizeGeometry->height + + w->serverBorderWidth * 2 + + w->input.bottom + w->input.top; + + xScale = (width) ? stretchWidth / (float) width : 1.0f; + yScale = (height) ? stretchHeight / (float) height : 1.0f; + + 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; -- 1.5.2.2