993 lines
25 KiB
Diff
993 lines
25 KiB
Diff
--- src/grid/grid.c 2016-04-10 12:23:24.000000000 -0700
|
|
+++ src/grid/grid.c 2017-03-01 23:23:09.809718104 -0800
|
|
@@ -1,7 +1,8 @@
|
|
/*
|
|
- * Compiz Fusion Grid plugin
|
|
+ * Compiz Grid plugin
|
|
*
|
|
* Copyright (c) 2008 Stephen Kennedy <suasol@gmail.com>
|
|
+ * Copyright (c) 2010 Scott Moreau <oreaus@gmail.com>
|
|
*
|
|
* 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 @@
|
|
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 @@
|
|
{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,599 @@
|
|
*rect = r;
|
|
}
|
|
|
|
+
|
|
+static void
|
|
+getTargetRect (CompWindow *cw,
|
|
+ GridType where)
|
|
+{
|
|
+ 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);
|
|
+}
|
|
+
|
|
+/* 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))
|
|
+ {
|
|
+ /* add maximize option */
|
|
+ if (where == GridMaximize)
|
|
+ {
|
|
+ sendMaximizationRequest (cw);
|
|
+ /* maximizeWindow (cw, MAXIMIZE_STATE); */
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ unsigned int valueMask = 0;
|
|
+ int desiredState = 0;
|
|
+
|
|
+ getTargetRect (cw, where);
|
|
+
|
|
+ XWindowChanges xwc;
|
|
+
|
|
+ /* 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))
|
|
+ {
|
|
+ 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) */
|
|
+ {
|
|
+ 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 /* keys (2, 5, 8) */
|
|
+ {
|
|
+ if (gs->currentRect.width == gs->desiredRect.width &&
|
|
+ gs->currentRect.x == gs->desiredRect.x)
|
|
+ {
|
|
+ gs->desiredSlot.width = slotWidth33;
|
|
+ gs->desiredSlot.x = gs->workarea.x + slotWidth33;
|
|
+ }
|
|
+ }
|
|
+ constrainSize (cw, &gs->desiredSlot, &gs->desiredRect);
|
|
+ DEBUG_RECT (gs->desiredRect);
|
|
+ }
|
|
+
|
|
+ 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,
|
|
+gridCommon (CompDisplay *d,
|
|
+ CompAction *action,
|
|
CompActionState state,
|
|
- CompOption *option,
|
|
- int nOption,
|
|
- GridType where)
|
|
+ CompOption *option,
|
|
+ int nOption,
|
|
+ GridType where)
|
|
{
|
|
Window xid;
|
|
CompWindow *cw;
|
|
|
|
xid = getIntOptionNamed (option, nOption, "window", 0);
|
|
cw = findWindowAtDisplay (d, xid);
|
|
- if (cw)
|
|
+
|
|
+ gridCommonWindow(cw, where);
|
|
+
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+static GridType
|
|
+edgeToGridType (CompDisplay *d,
|
|
+ EdgeType edge)
|
|
+{
|
|
+ GridType ret = GridUnknown;
|
|
+
|
|
+ switch (edge)
|
|
{
|
|
- 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);
|
|
+ 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;
|
|
+ }
|
|
|
|
- if (desiredRect.y == currentRect.y &&
|
|
- desiredRect.height == currentRect.height)
|
|
- {
|
|
- int slotWidth33 = workarea.width / 3;
|
|
- int slotWidth66 = workarea.width - slotWidth33;
|
|
+ return ret;
|
|
+}
|
|
|
|
- DEBUG_PRINT ((gridOut, "Multi!\n"));
|
|
+static void
|
|
+gridHandleEvent (CompDisplay *d,
|
|
+ XEvent *event)
|
|
+{
|
|
+ GridType where;
|
|
+ GRID_DISPLAY (d);
|
|
|
|
- if (props.numCellsX == 2) /* keys (1, 4, 7, 3, 6, 9) */
|
|
+ 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)
|
|
- {
|
|
- desiredSlot.width = slotWidth66;
|
|
- desiredSlot.x = workarea.x +
|
|
- props.gravityRight * slotWidth33;
|
|
- }
|
|
+ /* 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
|
|
- {
|
|
- /* 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);
|
|
+ gs->edge = NoEdge;
|
|
|
|
- if (currentRect.width == rect66.width &&
|
|
- currentRect.x == rect66.x)
|
|
+ /* detect edge region change */
|
|
+ if (gs->lastEdge != gs->edge)
|
|
+ {
|
|
+ if (gs->edge != NoEdge)
|
|
{
|
|
- desiredSlot.width = slotWidth33;
|
|
- desiredSlot.x = workarea.x +
|
|
- props.gravityRight * slotWidth66;
|
|
+ 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;
|
|
}
|
|
+
|
|
}
|
|
- else /* keys (2, 5, 8) */
|
|
- {
|
|
- if (currentRect.width == desiredRect.width &&
|
|
- currentRect.x == desiredRect.x)
|
|
- {
|
|
- desiredSlot.width = slotWidth33;
|
|
- desiredSlot.x = workarea.x + slotWidth33;
|
|
- }
|
|
- }
|
|
- constrainSize (cw, &desiredSlot, &desiredRect);
|
|
- DEBUG_RECT (desiredRect);
|
|
}
|
|
+ }
|
|
+
|
|
+ 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;
|
|
+
|
|
+ GRID_SCREEN (s);
|
|
+
|
|
+ if (mask & CompWindowGrabMoveMask)
|
|
+ {
|
|
+ gs->grabIsMove = TRUE;
|
|
+ gs->w = w;
|
|
+ }
|
|
+
|
|
+ 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)
|
|
+ {
|
|
+ gridCommonWindow (w, edgeToGridType(d, gs->edge));
|
|
+ gs->anim.fadingOut = TRUE;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ gs->edge = NoEdge;
|
|
+ gs->lastEdge = NoEdge;
|
|
+
|
|
+ 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;
|
|
|
|
- xwc.x = desiredRect.x;
|
|
- xwc.y = desiredRect.y;
|
|
- xwc.width = desiredRect.width;
|
|
- xwc.height = desiredRect.height;
|
|
+ glColor4f (((float) gridGetFillColorRed (s->display) / 65535.0f) * alpha,
|
|
+ ((float) gridGetFillColorGreen (s->display) / 65535.0f) * alpha,
|
|
+ ((float) gridGetFillColorBlue (s->display) / 65535.0f) * alpha,
|
|
+ alpha);
|
|
|
|
- if (cw->mapNum)
|
|
- sendSyncRequest (cw);
|
|
+ glRecti (rect.x1, rect.y2, rect.x2, rect.y1);
|
|
|
|
- if (cw->state & MAXIMIZE_STATE)
|
|
+ /* 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);
|
|
+
|
|
+ int thickness = gridGetOutlineThickness (s->display);
|
|
+ glLineWidth (thickness);
|
|
+ glBegin (GL_LINE_LOOP);
|
|
+
|
|
+ /* set outline rect smaller to avoid damage issues */
|
|
+ /* TODO: maybe get a better way of doing this */
|
|
+ float half_thickness = thickness * 0.5;
|
|
+ glVertex2f (rect.x1 + half_thickness, rect.y1 + half_thickness);
|
|
+ glVertex2f (rect.x2 - half_thickness, rect.y1 + half_thickness);
|
|
+ glVertex2f (rect.x2 - half_thickness, rect.y2 - half_thickness);
|
|
+ glVertex2f (rect.x1 + half_thickness, rect.y2 - half_thickness);
|
|
+ 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 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)
|
|
{
|
|
- /* maximized state interferes with us, clear it */
|
|
- maximizeWindow (cw, 0);
|
|
+ gs->anim.opacity = 0.0f;
|
|
+ gs->anim.fadingOut = FALSE;
|
|
+ gs->anim.complete = TRUE;
|
|
+ gs->animating = FALSE;
|
|
}
|
|
|
|
- /* TODO: animate move+resize */
|
|
- configureXWindow (cw, CWX | CWY | CWWidth | CWHeight, &xwc);
|
|
+ gs->anim.progress = (gs->anim.duration - gs->anim.timer) / gs->anim.duration;
|
|
}
|
|
|
|
- return TRUE;
|
|
+ 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 +796,7 @@
|
|
HANDLER (TopLeft)
|
|
HANDLER (Top)
|
|
HANDLER (TopRight)
|
|
+HANDLER (Maximize)
|
|
|
|
#undef HANDLER
|
|
|
|
@@ -282,6 +806,8 @@
|
|
gridInitDisplay (CompPlugin *p,
|
|
CompDisplay *d)
|
|
{
|
|
+ GridDisplay *gd;
|
|
+
|
|
if (!checkPluginABI ("core", CORE_ABIVERSION))
|
|
return FALSE;
|
|
|
|
@@ -294,22 +820,129 @@
|
|
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 +951,10 @@
|
|
setlinebuf(gridOut);
|
|
#endif
|
|
|
|
+ displayPrivateIndex = allocateDisplayPrivateIndex ();
|
|
+ if (displayPrivateIndex < 0)
|
|
+ return FALSE;
|
|
+
|
|
return TRUE;
|
|
}
|
|
|
|
@@ -328,6 +965,8 @@
|
|
fclose(gridOut);
|
|
gridOut = NULL;
|
|
#endif
|
|
+
|
|
+ freeDisplayPrivateIndex(displayPrivateIndex);
|
|
}
|
|
|
|
CompPluginVTable gridVTable =
|
|
@@ -337,7 +976,7 @@
|
|
gridInitPlugin,
|
|
gridFiniPlugin,
|
|
gridInitObject,
|
|
- 0,
|
|
+ gridFiniObject,
|
|
0,
|
|
0
|
|
};
|
|
@@ -346,4 +985,4 @@
|
|
getCompPluginInfo ()
|
|
{
|
|
return &gridVTable;
|
|
-}
|
|
+}
|
|
\ No newline at end of file
|