diff --git a/metadata/grid.xml.in b/metadata/grid.xml.in index 84db862..c8a1fcc 100644 --- a/metadata/grid.xml.in +++ b/metadata/grid.xml.in @@ -52,6 +52,496 @@ <_long>Move window to the bottom right corner <Primary><Alt>KP_3 + + + + + <_short>Corners / Edges + + <_short>Resize Actions + <_long>Window resize action + + + + + + + + + + + <_short>Thresholds + + + + + + + + <_short>Appearance + + + + diff --git a/src/grid/grid.c b/src/grid/grid.c index fae6200..cbe2d62 100644 --- a/src/grid/grid.c +++ b/src/grid/grid.c @@ -1,7 +1,8 @@ /* - * Compiz Fusion Grid plugin + * Compiz Grid plugin * * Copyright (c) 2008 Stephen Kennedy + * Copyright (c) 2010 Scott Moreau * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -37,6 +38,8 @@ # define DEBUG_PRINT(ARGS) #endif +static int displayPrivateIndex; + typedef enum { GridUnknown = 0, @@ -49,8 +52,23 @@ typedef enum GridTopLeft = 7, GridTop = 8, GridTopRight = 9, + GridMaximize = 10, } GridType; + +typedef enum +{ + NoEdge = 0, + BottomLeft, + Bottom, + BottomRight, + Left, + Right, + TopLeft, + Top, + TopRight, +} EdgeType; + typedef struct _GridProps { int gravityRight; @@ -76,6 +94,56 @@ static const GridProps gridProps[] = {1,0, 2,2}, }; +typedef struct _Animation +{ + GLfloat progress; + XRectangle fromRect; + XRectangle targetRect; + XRectangle currentRect; + GLfloat opacity; + GLfloat timer; + int duration; + Bool complete; + Bool fadingOut; +} Animation; + +typedef struct _GridDisplay { + int screenPrivateIndex; + HandleEventProc handleEvent; +} GridDisplay; + +typedef struct _GridScreen +{ + WindowGrabNotifyProc windowGrabNotify; + WindowUngrabNotifyProc windowUngrabNotify; + PaintOutputProc paintOutput; + PreparePaintScreenProc preparePaintScreen; + + Bool grabIsMove; + EdgeType edge, lastEdge; + XRectangle workarea; + XRectangle desiredSlot; + XRectangle desiredRect; + XRectangle currentRect; + GridProps props; + CompWindow *w; + Bool drawing; + Animation anim; + Bool animating; +} GridScreen; + +#define GET_GRID_DISPLAY(d) \ + ((GridDisplay *) (d)->base.privates[displayPrivateIndex].ptr) + +#define GRID_DISPLAY(d) \ + GridDisplay *gd = GET_GRID_DISPLAY (d) + +#define GET_GRID_SCREEN(s, gd) \ + ((GridScreen *) (s)->base.privates[(gd)->screenPrivateIndex].ptr) + +#define GRID_SCREEN(s) \ + GridScreen *gs = GET_GRID_SCREEN (s, GET_GRID_DISPLAY (s->display)) + static void slotToRect (CompWindow *w, XRectangle *slot, @@ -117,144 +185,597 @@ constrainSize (CompWindow *w, *rect = r; } -static Bool -gridCommon (CompDisplay *d, - CompAction *action, - CompActionState state, - CompOption *option, - int nOption, - GridType where) + +static void +getTargetRect (CompWindow *cw, + GridType where) { - Window xid; - CompWindow *cw; + GRID_SCREEN (cw->screen); + + gs->props = gridProps[where]; + + DEBUG_PRINT ((gridOut, "\nPressed KP_%i\n", where)); + + /* get current available area */ + getWorkareaForOutput (cw->screen, outputDeviceForWindow(cw), &gs->workarea); + DEBUG_RECT (workarea); + + /* Convention: + * xxxSlot include decorations (it's the screen area occupied) + * xxxRect are undecorated (it's the constrained position + of the contents) + */ + + /* slice and dice to get desired slot - including decorations */ + gs->desiredSlot.y = gs->workarea.y + gs->props.gravityDown * + (gs->workarea.height / gs->props.numCellsY); + gs->desiredSlot.height = gs->workarea.height / gs->props.numCellsY; + gs->desiredSlot.x = gs->workarea.x + gs->props.gravityRight * + (gs->workarea.width / gs->props.numCellsX); + gs->desiredSlot.width = gs->workarea.width / gs->props.numCellsX; + DEBUG_RECT (desiredSlot); + + /* Adjust for constraints and decorations */ + constrainSize (cw, &gs->desiredSlot, &gs->desiredRect); + DEBUG_RECT (gs->desiredRect); +} - xid = getIntOptionNamed (option, nOption, "window", 0); - cw = findWindowAtDisplay (d, xid); - if (cw) +/* just keeping this for reference, but can use maximizeWindow instead */ +static void sendMaximizationRequest (CompWindow *w) +{ + XEvent xev; + CompScreen *s = w->screen; + CompDisplay *d = s->display; + + xev.xclient.type = ClientMessage; + xev.xclient.display = d->display; + xev.xclient.format = 32; + + xev.xclient.message_type = d->winStateAtom; + xev.xclient.window = w->id; + + xev.xclient.data.l[0] = 1; + xev.xclient.data.l[1] = d->winStateMaximizedHorzAtom; + xev.xclient.data.l[2] = d->winStateMaximizedVertAtom; + xev.xclient.data.l[3] = 0; + xev.xclient.data.l[4] = 0; + + XSendEvent (d->display, s->root, FALSE, + SubstructureRedirectMask | SubstructureNotifyMask, &xev); +} + + +static void +gridCommonWindow (CompWindow *cw, + GridType where) +{ + GRID_SCREEN (cw->screen); + + if ((cw) && (where != GridUnknown)) { - XRectangle workarea; - XRectangle desiredSlot; - XRectangle desiredRect; - XRectangle currentRect; - GridProps props = gridProps[where]; - XWindowChanges xwc; - - DEBUG_PRINT ((gridOut, "\nPressed KP_%i\n", where)); - - /* get current available area */ - getWorkareaForOutput (cw->screen, outputDeviceForWindow(cw), &workarea); - DEBUG_RECT (workarea); - - /* Convention: - * xxxSlot include decorations (it's the screen area occupied) - * xxxRect are undecorated (it's the constrained position - of the contents) - */ - - /* slice and dice to get desired slot - including decorations */ - desiredSlot.y = workarea.y + props.gravityDown * - (workarea.height / props.numCellsY); - desiredSlot.height = workarea.height / props.numCellsY; - desiredSlot.x = workarea.x + props.gravityRight * - (workarea.width / props.numCellsX); - desiredSlot.width = workarea.width / props.numCellsX; - DEBUG_RECT (desiredSlot); - - /* Adjust for constraints and decorations */ - constrainSize (cw, &desiredSlot, &desiredRect); - DEBUG_RECT (desiredRect); - - /* Get current rect not including decorations */ - currentRect.x = cw->serverX; - currentRect.y = cw->serverY; - currentRect.width = cw->serverWidth; - currentRect.height = cw->serverHeight; - DEBUG_RECT (currentRect); - - if (desiredRect.y == currentRect.y && - desiredRect.height == currentRect.height) + /* add maximize option */ + if (where == GridMaximize) + { + sendMaximizationRequest (cw); + /* maximizeWindow (cw, MAXIMIZE_STATE); */ + } + else { - int slotWidth33 = workarea.width / 3; - int slotWidth66 = workarea.width - slotWidth33; + unsigned int valueMask = 0; + int desiredState = 0; + + getTargetRect (cw, where); - DEBUG_PRINT ((gridOut, "Multi!\n")); + XWindowChanges xwc; - if (props.numCellsX == 2) /* keys (1, 4, 7, 3, 6, 9) */ + /* if keys are pressed again then cycle through 1/3 or 2/3 widths... */ + + /* Get current rect not including decorations */ + gs->currentRect.x = cw->serverX; + gs->currentRect.y = cw->serverY; + gs->currentRect.width = cw->serverWidth; + gs->currentRect.height = cw->serverHeight; + DEBUG_RECT (currentRect); + + if ((gs->desiredRect.y == gs->currentRect.y && + gs->desiredRect.height == gs->currentRect.height) && + gridGetCycleSizes(cw->screen->display)) { - if (currentRect.width == desiredRect.width && - currentRect.x == desiredRect.x) + int slotWidth33 = gs->workarea.width / 3; + int slotWidth66 = gs->workarea.width - slotWidth33; + + DEBUG_PRINT ((gridOut, "Multi!\n")); + + if (gs->props.numCellsX == 2) /* keys (1, 4, 7, 3, 6, 9) */ { - desiredSlot.width = slotWidth66; - desiredSlot.x = workarea.x + - props.gravityRight * slotWidth33; + if (gs->currentRect.width == gs->desiredRect.width && + gs->currentRect.x == gs->desiredRect.x) + { + gs->desiredSlot.width = slotWidth66; + gs->desiredSlot.x = gs->workarea.x + + gs->props.gravityRight * slotWidth33; + } + else + { + /* tricky, have to allow for window constraints when + * computing what the 33% and 66% offsets would be + */ + XRectangle rect33, rect66, slot33, slot66; + + slot33 = gs->desiredSlot; + slot33.x = gs->workarea.x + + gs->props.gravityRight * slotWidth66; + slot33.width = slotWidth33; + constrainSize (cw, &slot33, &rect33); + DEBUG_RECT (slot33); + DEBUG_RECT (rect33); + + slot66 = gs->desiredSlot; + slot66.x = gs->workarea.x + + gs->props.gravityRight * slotWidth33; + slot66.width = slotWidth66; + constrainSize (cw, &slot66, &rect66); + DEBUG_RECT (slot66); + DEBUG_RECT (rect66); + + if (gs->currentRect.width == rect66.width && + gs->currentRect.x == rect66.x) + { + gs->desiredSlot.width = slotWidth33; + gs->desiredSlot.x = gs->workarea.x + + gs->props.gravityRight * slotWidth66; + } + } } - else + else /* keys (2, 5, 8) */ { - /* tricky, have to allow for window constraints when - * computing what the 33% and 66% offsets would be - */ - XRectangle rect33, rect66, slot33, slot66; - - slot33 = desiredSlot; - slot33.x = workarea.x + props.gravityRight * slotWidth66; - slot33.width = slotWidth33; - constrainSize (cw, &slot33, &rect33); - DEBUG_RECT (slot33); - DEBUG_RECT (rect33); - - slot66 = desiredSlot; - slot66.x = workarea.x + props.gravityRight * slotWidth33; - slot66.width = slotWidth66; - constrainSize (cw, &slot66, &rect66); - DEBUG_RECT (slot66); - DEBUG_RECT (rect66); - - if (currentRect.width == rect66.width && - currentRect.x == rect66.x) + if (gs->currentRect.width == gs->desiredRect.width && + gs->currentRect.x == gs->desiredRect.x) { - desiredSlot.width = slotWidth33; - desiredSlot.x = workarea.x + - props.gravityRight * slotWidth66; + gs->desiredSlot.width = slotWidth33; + gs->desiredSlot.x = gs->workarea.x + slotWidth33; } } + constrainSize (cw, &gs->desiredSlot, &gs->desiredRect); + DEBUG_RECT (gs->desiredRect); } - else /* keys (2, 5, 8) */ + + xwc.x = gs->desiredRect.x; + xwc.y = gs->desiredRect.y; + xwc.width = gs->desiredRect.width; + xwc.height = gs->desiredRect.height; + + if (cw->mapNum) + sendSyncRequest (cw); + + if (where == GridRight || where == GridLeft) + { + desiredState = CompWindowStateMaximizedVertMask; + valueMask = CWX | CWWidth; + } + else if (where == GridTop || where == GridBottom) + { + desiredState = CompWindowStateMaximizedHorzMask; + valueMask = CWY | CWHeight; + } + else + { + desiredState = 0; + valueMask = CWX | CWY | CWWidth | CWHeight; + } + + if (cw->state != desiredState) + maximizeWindow (cw, desiredState); + + /* TODO: animate move+resize */ + configureXWindow (cw, valueMask, &xwc); + + } + } +} + +static Bool +gridCommon (CompDisplay *d, + CompAction *action, + CompActionState state, + CompOption *option, + int nOption, + GridType where) +{ + Window xid; + CompWindow *cw; + + xid = getIntOptionNamed (option, nOption, "window", 0); + cw = findWindowAtDisplay (d, xid); + + gridCommonWindow(cw, where); + + return TRUE; +} + +static GridType +edgeToGridType (CompDisplay *d, + EdgeType edge) +{ + GridType ret = GridUnknown; + + switch (edge) + { + case Left: + ret = (GridType) gridGetLeftEdgeAction (d); + break; + case Right: + ret = (GridType) gridGetRightEdgeAction (d); + break; + case Top: + ret = (GridType) gridGetTopEdgeAction (d); + break; + case Bottom: + ret = (GridType) gridGetBottomEdgeAction (d); + break; + case TopLeft: + ret = (GridType) gridGetTopLeftCornerAction (d); + break; + case TopRight: + ret = (GridType) gridGetTopRightCornerAction (d); + break; + case BottomLeft: + ret = (GridType) gridGetBottomLeftCornerAction (d); + break; + case BottomRight: + ret = (GridType) gridGetBottomRightCornerAction (d); + break; + case NoEdge: + default: + ret = -1; + break; + } + + return ret; +} + +static void +gridHandleEvent (CompDisplay *d, + XEvent *event) +{ + GridType where; + GRID_DISPLAY (d); + + if (event->type == MotionNotify) + { + CompScreen *s; + s = findScreenAtDisplay (d, event->xmotion.root); + if (s) + { + GRID_SCREEN (s); + if (gs->grabIsMove) { - if (currentRect.width == desiredRect.width && - currentRect.x == desiredRect.x) + /* detect corners first */ + /* Bottom Left */ + if (pointerY > (s->height - gridGetBottomEdgeThreshold(d)) && + pointerX < gridGetLeftEdgeThreshold(d)) + gs->edge = BottomLeft; + /* Bottom Right */ + else if (pointerY > (s->height - gridGetBottomEdgeThreshold(d)) && + pointerX > (s->width - gridGetRightEdgeThreshold(d))) + gs->edge = BottomRight; + /* Top Left */ + else if (pointerY < gridGetTopEdgeThreshold(d) && pointerX < gridGetLeftEdgeThreshold(d)) + gs->edge = TopLeft; + /* Top Right */ + else if (pointerY < gridGetTopEdgeThreshold(d) && + pointerX > (s->width - gridGetRightEdgeThreshold(d))) + gs->edge = TopRight; + /* Left */ + else if (pointerX < gridGetLeftEdgeThreshold(d)) + gs->edge = Left; + /* Right */ + else if (pointerX > (s->width - gridGetRightEdgeThreshold(d))) + gs->edge = Right; + /* Top */ + else if (pointerY < gridGetTopEdgeThreshold(d)) + gs->edge = Top; + /* Bottom */ + else if (pointerY > (s->height - gridGetBottomEdgeThreshold(d))) + gs->edge = Bottom; + /* No Edge */ + else + gs->edge = NoEdge; + + /* detect edge region change */ + if (gs->lastEdge != gs->edge) { - desiredSlot.width = slotWidth33; - desiredSlot.x = workarea.x + slotWidth33; + if (gs->edge != NoEdge) + { + where = edgeToGridType(d, gs->edge); + + /* treat Maximize visual indicator same as GridCenter */ + if (where == GridMaximize) + where=GridCenter; + + getTargetRect (gs->w, where); + + gs->anim.duration = gridGetAnimationDuration (d); + gs->anim.timer = gs->anim.duration; + gs->anim.opacity = 0.0f; + gs->anim.progress = 0.0f; + gs->anim.currentRect.x = gs->w->serverX; + gs->anim.currentRect.y = gs->w->serverY; + gs->anim.currentRect.width = gs->w->serverWidth; + gs->anim.currentRect.height = gs->w->serverHeight; + gs->anim.targetRect = gs->desiredSlot; + gs->anim.fromRect.x = gs->w->serverX - gs->w->input.left; + gs->anim.fromRect.y = gs->w->serverY - gs->w->input.top; + gs->anim.fromRect.width = gs->w->serverWidth + + gs->w->input.left + + gs->w->input.right + + gs->w->serverBorderWidth * 2; + gs->anim.fromRect.height = gs->w->serverHeight + + gs->w->input.top + + gs->w->input.bottom + + gs->w->serverBorderWidth * 2; + gs->animating = TRUE; + gs->anim.fadingOut = FALSE; + } + else + gs->anim.fadingOut = TRUE; + + gs->lastEdge = gs->edge; } + } - constrainSize (cw, &desiredSlot, &desiredRect); - DEBUG_RECT (desiredRect); } + } - xwc.x = desiredRect.x; - xwc.y = desiredRect.y; - xwc.width = desiredRect.width; - xwc.height = desiredRect.height; + UNWRAP (gd, d, handleEvent); + (*d->handleEvent) (d, event); + WRAP (gd, d, handleEvent, gridHandleEvent); +} + +static void +gridWindowGrabNotify (CompWindow *w, + int x, + int y, + unsigned int state, + unsigned int mask) +{ + CompScreen *s = w->screen; - if (cw->mapNum) - sendSyncRequest (cw); + GRID_SCREEN (s); + + if (mask & CompWindowGrabMoveMask) + { + gs->grabIsMove = TRUE; + gs->w = w; + } - if (cw->state & MAXIMIZE_STATE) + UNWRAP (gs, s, windowGrabNotify); + (*s->windowGrabNotify) (w, x, y, state, mask); + WRAP (gs, s, windowGrabNotify, gridWindowGrabNotify); +} + +static void +gridWindowUngrabNotify (CompWindow *w) +{ + CompScreen *s = w->screen; + CompDisplay *d = s->display; + + GRID_SCREEN (s); + + if (gs->grabIsMove) + { + gs->grabIsMove = FALSE; + + if (gs->edge != NoEdge) { - /* maximized state interferes with us, clear it */ - maximizeWindow (cw, 0); + gridCommonWindow (w, edgeToGridType(d, gs->edge)); + gs->anim.fadingOut = TRUE; } + } + + gs->edge = NoEdge; + gs->lastEdge = NoEdge; - /* TODO: animate move+resize */ - configureXWindow (cw, CWX | CWY | CWWidth | CWHeight, &xwc); + UNWRAP (gs, s, windowUngrabNotify); + (*s->windowUngrabNotify) (w); + WRAP (gs, s, windowUngrabNotify, gridWindowUngrabNotify); +} + +static int +applyProgress (int a, int b, float progress) +{ + return a < b ? + b - (abs (a - b) * progress) : + b + (abs (a - b) * progress); +} + +static void +setCurrentRect (CompScreen *s) +{ + GRID_SCREEN (s); + + gs->anim.currentRect.x = applyProgress (gs->anim.targetRect.x, + gs->anim.fromRect.x, + gs->anim.progress); + gs->anim.currentRect.width = applyProgress (gs->anim.targetRect.width, + gs->anim.fromRect.width, + gs->anim.progress); + gs->anim.currentRect.y = applyProgress (gs->anim.targetRect.y, + gs->anim.fromRect.y, + gs->anim.progress); + gs->anim.currentRect.height = applyProgress (gs->anim.targetRect.height, + gs->anim.fromRect.height, + gs->anim.progress); +} + +static void +glPaintRectangle (CompScreen *s, + const ScreenPaintAttrib *sAttrib, + const CompTransform *transform, + CompOutput *output) +{ + float alpha = 0; + + GRID_SCREEN (s); + + BoxRec rect; + + setCurrentRect (s); + + rect.x1=gs->anim.currentRect.x; + rect.y1=gs->anim.currentRect.y; + rect.x2=gs->anim.currentRect.x + gs->anim.currentRect.width; + rect.y2=gs->anim.currentRect.y + gs->anim.currentRect.height; + CompTransform sTransform = *transform; + + /* rect = desiredSlot;*/ + + glPushMatrix (); + + transformToScreenSpace (s, output, -DEFAULT_Z_CAMERA, &sTransform); + + glLoadMatrixf (sTransform.m); + + glDisableClientState (GL_TEXTURE_COORD_ARRAY); + glEnable (GL_BLEND); + + /* fill rectangle */ + /* TODO: have multiple animations + for (iter = animations.begin (); iter != animations.end () && animating; iter++) + { */ + + alpha = ((float) gridGetFillColorAlpha (s->display) / 65535.0f) * + gs->anim.opacity; + + glColor4f (((float) gridGetFillColorRed (s->display) / 65535.0f) * alpha, + ((float) gridGetFillColorGreen (s->display) / 65535.0f) * alpha, + ((float) gridGetFillColorBlue (s->display) / 65535.0f) * alpha, + alpha); + + glRecti (rect.x1, rect.y2, rect.x2, rect.y1); + + /* draw outline */ + + alpha = ((float) gridGetOutlineColorAlpha (s->display) / 65535.0f) * + gs->anim.opacity; + + glColor4f (((float) gridGetOutlineColorRed (s->display) / 65535.0f) * alpha, + ((float) gridGetOutlineColorGreen (s->display) / 65535.0f) * alpha, + ((float) gridGetOutlineColorBlue (s->display) / 65535.0f) * alpha, + alpha); + + glLineWidth (2.0); + glBegin (GL_LINE_LOOP); + + /* set outline rect smaller to avoid damage issues */ + /* TODO: maybe get a better way of doing this */ + glVertex2i (rect.x1 + 1, rect.y1 + 1); + glVertex2i (rect.x2 - 1, rect.y1 + 1); + glVertex2i (rect.x2 - 1, rect.y2 - 1); + glVertex2i (rect.x1 + 1, rect.y2 - 1); + glEnd (); + + /* clean up */ + glColor4usv (defaultColor); + glDisable (GL_BLEND); + glEnableClientState (GL_TEXTURE_COORD_ARRAY); + glPopMatrix (); +} + +static void +damagePaintRegion (CompScreen *s) +{ + REGION reg; + int x, y; + + GRID_SCREEN (s); + + /* if (!is->fadeTime && !is->drawing) + return; */ + + x = gs->anim.currentRect.x; + y = gs->anim.currentRect.y; + + reg.rects = ®.extents; + reg.numRects = 1; + + reg.extents.x1 = x - 5; + reg.extents.y1 = y - 5; + reg.extents.x2 = x + gs->anim.currentRect.width + 5; + reg.extents.y2 = y + gs->anim.currentRect.height + 5; + + damageScreenRegion (s, ®); +} + +static Bool +gridPaintOutput (CompScreen *s, + const ScreenPaintAttrib *sAttrib, + const CompTransform *transform, + Region region, + CompOutput *output, + unsigned int mask) +{ + Bool status; + + GRID_SCREEN (s); + + UNWRAP (gs, s, paintOutput); + status = (*s->paintOutput) (s, sAttrib, transform, region, output, mask); + WRAP (gs, s, paintOutput, gridPaintOutput); + + if (gs->animating && gridGetDrawIndicator (s->display)) + { + glPaintRectangle (s, sAttrib, transform, output); + damagePaintRegion (s); } - return TRUE; + return status; +} + + +/* handle the fade in /fade out */ +static void +gridPreparePaintScreen (CompScreen *s, + int ms) +{ + GRID_SCREEN (s); + + if (gs->animating) + { + gs->anim.timer -= ms; + + if (gs->anim.timer < 0) + gs->anim.timer = 0; + + if (gs->anim.fadingOut) + gs->anim.opacity -= ms * 0.002; + else + { + if (gs->anim.opacity < 1.0f) + gs->anim.opacity = gs->anim.progress * gs->anim.progress; + else + gs->anim.opacity = 1.0f; + } + + if (gs->anim.opacity < 0) + { + gs->anim.opacity = 0.0f; + gs->anim.fadingOut = FALSE; + gs->anim.complete = TRUE; + gs->animating = FALSE; + } + + gs->anim.progress = (gs->anim.duration - gs->anim.timer) / gs->anim.duration; + } + + UNWRAP (gs, s, preparePaintScreen); + (*s->preparePaintScreen) (s, ms); + WRAP (gs, s, preparePaintScreen, gridPreparePaintScreen); } #define HANDLER(WHERE) \ static Bool \ - grid##WHERE(CompDisplay *d, \ + grid##WHERE(CompDisplay *d, \ CompAction *action, \ CompActionState state, \ CompOption *option, \ @@ -273,6 +794,7 @@ HANDLER (Right) HANDLER (TopLeft) HANDLER (Top) HANDLER (TopRight) +HANDLER (Maximize) #undef HANDLER @@ -282,6 +804,8 @@ static Bool gridInitDisplay (CompPlugin *p, CompDisplay *d) { + GridDisplay *gd; + if (!checkPluginABI ("core", CORE_ABIVERSION)) return FALSE; @@ -294,22 +818,129 @@ gridInitDisplay (CompPlugin *p, gridSetPutToprightKeyInitiate (d, gridTopRight); gridSetPutBottomleftKeyInitiate (d, gridBottomLeft); gridSetPutBottomrightKeyInitiate (d, gridBottomRight); + gridSetPutMaximizeKeyInitiate (d, gridMaximize); + + gd = malloc (sizeof (GridDisplay)); + if (!gd) + return FALSE; + + gd->screenPrivateIndex = allocateScreenPrivateIndex (d); + if (gd->screenPrivateIndex < 0) + { + free (gd); + return FALSE; + } + + WRAP (gd, d, handleEvent, gridHandleEvent); + + d->base.privates[displayPrivateIndex].ptr = gd; return TRUE; } +static void +gridFiniDisplay (CompPlugin *p, + CompDisplay *d) +{ + GRID_DISPLAY (d); + + freeScreenPrivateIndex (d, gd->screenPrivateIndex); + + UNWRAP (gd, d, handleEvent); + + free (gd); +} + +static Bool +gridInitScreen (CompPlugin *p, + CompScreen *s) +{ + GridScreen * gs; + + GRID_DISPLAY (s->display); + + gs = malloc (sizeof (GridScreen)); + if (!gs) + return FALSE; + + gs->grabIsMove = FALSE; + gs->edge = NoEdge; + gs->lastEdge = NoEdge; + gs->drawing = FALSE; + + gs->w = 0; + + gs->anim.progress = 0.0f; + gs->anim.fromRect.x = 0; + gs->anim.fromRect.y = 0; + gs->anim.fromRect.width = 0; + gs->anim.fromRect.height =0; + gs->anim.targetRect.x = 0; + gs->anim.targetRect.y = 0; + gs->anim.targetRect.width = 0; + gs->anim.targetRect.height = 0; + gs->anim.currentRect.x = 0; + gs->anim.currentRect.y = 0; + gs->anim.currentRect.width = 0; + gs->anim.currentRect.height = 0; + gs->anim.opacity = 0.5f; + gs->anim.timer = 0.0f; + gs->anim.duration = 0; + gs->anim.complete = FALSE; + gs->anim.fadingOut = FALSE; + + gs->animating=FALSE; + + WRAP (gs, s, windowGrabNotify, gridWindowGrabNotify); + WRAP (gs, s, windowUngrabNotify, gridWindowUngrabNotify); + WRAP (gs, s, paintOutput, gridPaintOutput); + WRAP (gs, s, preparePaintScreen, gridPreparePaintScreen); + + s->base.privates[gd->screenPrivateIndex].ptr = gs; + + return TRUE; +} + +static void +gridFiniScreen (CompPlugin *p, + CompScreen *s) +{ + GRID_SCREEN (s); + + UNWRAP (gs, s, windowGrabNotify); + UNWRAP (gs, s, windowUngrabNotify); + UNWRAP (gs, s, paintOutput); + UNWRAP (gs, s, preparePaintScreen); + + free (gs); +} + static CompBool gridInitObject (CompPlugin *p, CompObject *o) { static InitPluginObjectProc dispTab[] = { (InitPluginObjectProc) 0, /* InitCore */ - (InitPluginObjectProc) gridInitDisplay + (InitPluginObjectProc) gridInitDisplay, + (InitPluginObjectProc) gridInitScreen }; RETURN_DISPATCH (o, dispTab, ARRAY_SIZE (dispTab), TRUE, (p, o)); } +static void +gridFiniObject (CompPlugin *p, + CompObject *o) +{ + static FiniPluginObjectProc dispTab[] = { + (FiniPluginObjectProc) 0, /* FiniCore */ + (FiniPluginObjectProc) gridFiniDisplay, + (FiniPluginObjectProc) gridFiniScreen + }; + + DISPATCH (o, dispTab, ARRAY_SIZE (dispTab), (p, o)); +} + static Bool gridInitPlugin (CompPlugin *p) { @@ -318,6 +949,10 @@ gridInitPlugin (CompPlugin *p) setlinebuf(gridOut); #endif + displayPrivateIndex = allocateDisplayPrivateIndex (); + if (displayPrivateIndex < 0) + return FALSE; + return TRUE; } @@ -328,6 +963,8 @@ gridFiniPlugin (CompPlugin *p) fclose(gridOut); gridOut = NULL; #endif + + freeDisplayPrivateIndex(displayPrivateIndex); } CompPluginVTable gridVTable = @@ -337,7 +974,7 @@ CompPluginVTable gridVTable = gridInitPlugin, gridFiniPlugin, gridInitObject, - 0, + gridFiniObject, 0, 0 };