rendered paste bodydiff --git a/plugins/resize.c b/plugins/resize.c
index 17bf464..8d21ee5 100644
--- a/plugins/resize.c
+++ b/plugins/resize.c
@@ -42,6 +42,16 @@
#define RESIZE_INITIATE_KEY_DEFAULT "F8"
#define RESIZE_INITIATE_KEY_MODIFIERS_DEFAULT CompAltMask
+#define RESIZE_BORDER_COLOR_RED 0x2fff
+#define RESIZE_BORDER_COLOR_GREEN 0x2fff
+#define RESIZE_BORDER_COLOR_BLUE 0x4fff
+#define RESIZE_BORDER_COLOR_ALPHA 0x9fff
+
+#define RESIZE_FILL_COLOR_RED 0x2fff
+#define RESIZE_FILL_COLOR_GREEN 0x2fff
+#define RESIZE_FILL_COLOR_BLUE 0x4fff
+#define RESIZE_FILL_COLOR_ALPHA 0x4fff
+
struct _ResizeKeys {
char *name;
int dx;
@@ -60,8 +70,28 @@ struct _ResizeKeys {
#define MIN_KEY_WIDTH_INC 24
#define MIN_KEY_HEIGHT_INC 24
-#define RESIZE_DISPLAY_OPTION_INITIATE 0
-#define RESIZE_DISPLAY_OPTION_NUM 1
+#define RESIZE_DISPLAY_OPTION_INITIATE 0
+#define RESIZE_DISPLAY_OPTION_MODE 1
+#define RESIZE_DISPLAY_OPTION_BORDER_COLOR 2
+#define RESIZE_DISPLAY_OPTION_FILL_COLOR 3
+#define RESIZE_DISPLAY_OPTION_NUM 4
+
+typedef enum _ResizeMode {
+ ResizeModeNormal = 0,
+ ResizeModeStretch,
+ ResizeModeOutline,
+ ResizeModeFilledOutline
+} ResizeMode;
+
+char * resizeModes[] = {
+ N_("Normal"),
+ N_("Stretch"),
+ N_("Outline"),
+ N_("Filled Outline")
+};
+
+#define RESIZE_MODE_DEFAULT ResizeModeNormal
+#define NUM_RESIZE_MODES (sizeof (resizeModes) / sizeof (resizeModes[0]))
static int displayPrivateIndex;
@@ -75,16 +105,28 @@ typedef struct _ResizeDisplay {
XWindowAttributes savedAttrib;
int releaseButton;
unsigned int mask;
- int width;
- int height;
- int ucWidth; /* unconstrained width */
- int ucHeight; /* unconstrained height */
+
+ int currentX;
+ int currentY;
+ int currentWidth;
+ int currentHeight;
+
+ /* offsets between pointer and upper left
+ window edge on resize start */
+ int xDelta;
+ int yDelta;
+
+ ResizeMode resizeMode;
+
KeyCode key[NUM_KEYS];
} ResizeDisplay;
typedef struct _ResizeScreen {
int grabIndex;
+ PaintWindowProc paintWindow;
+ PaintScreenProc paintScreen;
+
Cursor leftCursor;
Cursor rightCursor;
Cursor upCursor;
@@ -111,6 +153,59 @@ typedef struct _ResizeScreen {
#define NUM_OPTIONS(d) (sizeof ((d)->opt) / sizeof (CompOption))
+static void
+resizeUpdateRealWindowSize (CompDisplay *d)
+{
+ RESIZE_DISPLAY (d);
+ XWindowChanges xwc;
+
+ if (!rd->w)
+ return;
+
+ if (rd->w->state & CompWindowStateMaximizedVertMask)
+ rd->currentHeight = rd->w->serverHeight;
+
+ if (rd->w->state & CompWindowStateMaximizedHorzMask)
+ rd->currentWidth = rd->w->serverWidth;
+
+ if (rd->currentWidth == rd->w->serverWidth &&
+ rd->currentHeight == rd->w->serverHeight)
+ return;
+
+ if (rd->w->syncWait)
+ return;
+
+ xwc.x = rd->currentX;
+ xwc.y = rd->currentY;
+ xwc.width = rd->currentWidth;
+ xwc.height = rd->currentHeight;
+
+ sendSyncRequest (rd->w);
+
+ configureXWindow (rd->w, CWX | CWY | CWWidth | CWHeight, &xwc);
+}
+
+static void
+resizeDamagePaintRectangle (CompScreen *s)
+{
+ REGION reg;
+
+ RESIZE_DISPLAY (s->display);
+
+ reg.rects = ®.extents;
+ reg.numRects = 1;
+
+ reg.extents.x1 = rd->currentX - rd->w->output.left - 1;
+ reg.extents.y1 = rd->currentY - rd->w->output.top - 1;
+ reg.extents.x2 = rd->currentX + rd->currentWidth +
+ rd->w->output.right + 1;
+ reg.extents.y2 = rd->currentY + rd->currentHeight +
+ rd->w->output.bottom + 1;
+
+// damageScreenRegion (s, ®);
+ damageScreen(s);
+}
+
static Bool
resizeInitiate (CompDisplay *d,
CompAction *action,
@@ -186,12 +281,16 @@ resizeInitiate (CompDisplay *d,
rd->w = w;
rd->mask = mask;
- rd->ucWidth = w->attrib.width;
- rd->ucHeight = w->attrib.height;
- rd->width = w->attrib.width;
- rd->height = w->attrib.height;
rd->savedAttrib = w->attrib;
+ rd->currentX = w->attrib.x;
+ rd->currentY = w->attrib.y;
+ rd->currentWidth = w->attrib.width;
+ rd->currentHeight = w->attrib.height;
+
+ rd->xDelta = 0;
+ rd->yDelta = 0;
+
lastPointerX = x;
lastPointerY = y;
@@ -250,6 +349,17 @@ resizeInitiate (CompDisplay *d,
warpPointer (w->screen, xRoot - pointerX, yRoot - pointerY);
}
+
+ rd->xDelta = (x - rd->currentX);
+ if (rd->mask & ResizeRightMask)
+ rd->xDelta = rd->w->serverWidth - rd->xDelta;
+
+ rd->yDelta = (y - rd->currentY);
+ if (rd->mask & ResizeDownMask)
+ rd->yDelta = rd->w->serverHeight - rd->yDelta;
+
+ if (rd->resizeMode != ResizeModeNormal)
+ resizeDamagePaintRectangle (w->screen);
}
}
@@ -288,16 +398,32 @@ resizeTerminate (CompDisplay *d,
}
else
{
- syncWindowPosition (rd->w);
+ if (rd->resizeMode != ResizeModeNormal)
+ resizeUpdateRealWindowSize (d);
+ else
+ syncWindowPosition (rd->w);
}
+ if (rd->resizeMode != ResizeModeNormal)
+ resizeDamagePaintRectangle (rd->w->screen);
+
if (rs->grabIndex)
{
removeScreenGrab (rd->w->screen, rs->grabIndex, NULL);
rs->grabIndex = 0;
}
- rd->w = 0;
+ /* keep rd->w if we are using the stretch mode and there
+ was actual resize until the resizing is finished to
+ avoid the window flashing back to the old size for a
+ short moment */
+ if ((rd->resizeMode != ResizeModeStretch) ||
+ ((rd->currentWidth == rd->w->serverWidth) &&
+ (rd->currentHeight == rd->w->serverHeight)))
+ {
+ rd->w = 0;
+ }
+
rd->releaseButton = 0;
}
@@ -306,53 +432,7 @@ resizeTerminate (CompDisplay *d,
return FALSE;
}
-static void
-resizeUpdateWindowSize (CompDisplay *d)
-{
- int width, height;
-
- RESIZE_DISPLAY (d);
-
- if (!rd->w)
- return;
-
- if (rd->w->state & CompWindowStateMaximizedVertMask)
- rd->height = rd->w->serverHeight;
-
- if (rd->w->state & CompWindowStateMaximizedHorzMask)
- rd->width = rd->w->serverWidth;
-
- if (rd->width == rd->w->serverWidth &&
- rd->height == rd->w->serverHeight)
- return;
-
- if (rd->w->syncWait)
- return;
-
- if (constrainNewWindowSize (rd->w,
- rd->width, rd->height,
- &width, &height))
- {
- XWindowChanges xwc;
-
- xwc.x = rd->w->serverX;
- if (rd->mask & ResizeLeftMask)
- xwc.x -= width - rd->w->serverWidth;
-
- xwc.y = rd->w->serverY;
- if (rd->mask & ResizeUpMask)
- xwc.y -= height - rd->w->serverHeight;
-
- xwc.width = width;
- xwc.height = height;
-
- sendSyncRequest (rd->w);
-
- configureXWindow (rd->w,
- CWX | CWY | CWWidth | CWHeight,
- &xwc);
- }
-}
+#define CLAMP(v, min, max) ((v) <= (min) ? (min) : (v) >= (max) ? (max) : (v))
static void
resizeConstrainMinMax (CompWindow *w,
@@ -389,18 +469,281 @@ resizeConstrainMinMax (CompWindow *w,
max_height = hints->max_height;
}
-#define CLAMP(v, min, max) ((v) <= (min) ? (min) : (v) >= (max) ? (max) : (v))
-
/* clamp width and height to min and max values */
width = CLAMP (width, min_width, max_width);
height = CLAMP (height, min_height, max_height);
-#undef CLAMP
-
*newWidth = width;
*newHeight = height;
}
+static void
+resizeConstrainResizeIncrement (CompWindow * w,
+ int width,
+ int height,
+ int *newWidth,
+ int *newHeight)
+{
+ int baseWidth, baseHeight;
+ const XSizeHints *hints = &w->sizeHints;
+
+ if (hints->flags & PResizeInc)
+ {
+ if (hints->flags & PBaseSize)
+ {
+ baseWidth = hints->base_width;
+ baseHeight = hints->base_height;
+ }
+ else
+ {
+ baseWidth = 0;
+ baseHeight = 0;
+ }
+
+ if ((width - baseWidth) % hints->width_inc)
+ width = baseWidth + (((width - baseWidth) /
+ hints->width_inc) * hints->width_inc);
+
+ if ((height - baseHeight) % hints->height_inc)
+ height = baseHeight + (((height - baseHeight) /
+ hints->height_inc) * hints->height_inc);
+ }
+
+ *newWidth = width;
+ *newHeight = height;
+}
+
+/* this code has its origin in metacity's boxes.c */
+static void
+resizeFindLinePointClosestToPoint (double x1, double y1,
+ double x2, double y2,
+ double px, double py,
+ double *valx, double *valy)
+{
+ /* I'll use the shorthand rx, ry for the return values, valx & valy.
+ * Now, we need (rx,ry) to be on the line between (x1,y1) and (x2,y2).
+ * For that to happen, we first need the slope of the line from (x1,y1)
+ * to (rx,ry) must match the slope of (x1,y1) to (x2,y2), i.e.:
+ * (ry-y1) (y2-y1)
+ * ------- = -------
+ * (rx-x1) (x2-x1)
+ * If x1==x2, though, this gives divide by zero errors, so we want to
+ * rewrite the equation by multiplying both sides by (rx-x1)*(x2-x1):
+ * (ry-y1)(x2-x1) = (y2-y1)(rx-x1)
+ * This is a valid requirement even when x1==x2 (when x1==x2, this latter
+ * equation will basically just mean that rx must be equal to both x1 and
+ * x2)
+ *
+ * The other requirement that we have is that the line from (rx,ry) to
+ * (px,py) must be perpendicular to the line from (x1,y1) to (x2,y2). So
+ * we just need to get a vector in the direction of each line, take the
+ * dot product of the two, and ensure that the result is 0:
+ * (rx-px)*(x2-x1) + (ry-py)*(y2-y1) = 0.
+ *
+ * This gives us two equations and two unknowns:
+ *
+ * (ry-y1)(x2-x1) = (y2-y1)(rx-x1)
+ * (rx-px)*(x2-x1) + (ry-py)*(y2-y1) = 0.
+ *
+ * This particular pair of equations is always solvable so long as
+ * (x1,y1) and (x2,y2) are not the same point (and note that anyone who
+ * calls this function that way is braindead because it means that they
+ * really didn't specify a line after all). However, the caller should
+ * be careful to avoid making (x1,y1) and (x2,y2) too close (e.g. like
+ * 10^{-8} apart in each coordinate), otherwise roundoff error could
+ * cause issues. Solving these equations by hand (or using Maple(TM) or
+ * Mathematica(TM) or whatever) results in slightly messy expressions,
+ * but that's all the below few lines do.
+ */
+
+ double diffx, diffy, den;
+ diffx = x2 - x1;
+ diffy = y2 - y1;
+ den = diffx * diffx + diffy * diffy;
+
+ *valx = (py * diffx * diffy + px * diffx * diffx +
+ y2 * x1 * diffy - y1 * x2 * diffy) / den;
+ *valy = (px * diffx * diffy + py * diffy * diffy +
+ x2 * y1 * diffx - x1 * y2 * diffx) / den;
+}
+
+/* this function is heavily inspired by metacity's constrain_aspect_ratio */
+static Bool
+resizeConstrainAspectRatio(CompWindow * w,
+ int width,
+ int height,
+ int *retWidth,
+ int *retHeight)
+{
+ const XSizeHints *hints = &w->sizeHints;
+ double minRatio, maxRatio;
+ int newWidth, newHeight;
+ double altWidth, altHeight;
+ double bestWidth, bestHeight;
+ int tolerance = 1;
+ Bool resizeLeftRight = FALSE;
+ Bool resizeUpDown = FALSE;
+
+ RESIZE_DISPLAY(w->screen->display);
+
+ newWidth = width;
+ newHeight = height;
+
+ if (hints->flags & PAspect)
+ {
+ minRatio = hints->min_aspect.x / (double) hints->min_aspect.y;
+ maxRatio = hints->max_aspect.x / (double) hints->max_aspect.y;
+
+ if (minRatio > maxRatio)
+ return FALSE;
+
+ resizeLeftRight = (rd->mask == (rd->mask & ResizeLeftMask)) ||
+ (rd->mask == (rd->mask & ResizeRightMask));
+ resizeUpDown = (rd->mask == (rd->mask & ResizeUpMask)) ||
+ (rd->mask == (rd->mask & ResizeDownMask));
+
+ if (resizeLeftRight || resizeUpDown)
+ tolerance = 2;
+
+ /* return if constraint already is satisfied */
+ if (((width - (height * minRatio)) > (-minRatio * tolerance)) &&
+ ((width - (height * maxRatio)) < (maxRatio * tolerance)))
+ {
+ return FALSE;
+ }
+
+ if (resizeLeftRight)
+ newHeight = CLAMP (newHeight, newWidth / maxRatio, newWidth / minRatio);
+ else if (resizeUpDown)
+ newWidth = CLAMP (newWidth, newHeight * minRatio, newHeight * maxRatio);
+ else
+ {
+ altWidth = CLAMP (newWidth, newHeight * minRatio, newHeight * maxRatio);
+ altHeight = CLAMP (newHeight, newWidth / maxRatio, newWidth / minRatio);
+
+ resizeFindLinePointClosestToPoint(altWidth, newHeight,
+ newWidth, altHeight,
+ newWidth, newHeight,
+ &bestWidth, &bestHeight);
+
+ newWidth = bestWidth;
+ newHeight = bestHeight;
+ }
+ }
+
+ *retWidth = newWidth;
+ *retHeight = newHeight;
+
+ return TRUE;
+}
+
+#undef CLAMP
+
+static void
+resizeUpdateWindowSize (CompDisplay *d, int dx, int dy)
+{
+ int width, height;
+ int newHeight, newWidth;
+
+ RESIZE_DISPLAY (d);
+
+ if (!rd->w)
+ return;
+
+ /* don't apply resizing in the direction
+ windows are maximized to */
+ if (rd->w->state & CompWindowStateMaximizedVertMask)
+ dy = 0;
+
+ if (rd->w->state & CompWindowStateMaximizedHorzMask)
+ dx = 0;
+
+ width = rd->currentWidth;
+ height = rd->currentHeight;
+
+ /* Ensure we don't push the window if constraints stop
+ it from being resized. */
+ if (!(rd->mask & (ResizeLeftMask | ResizeRightMask)))
+ dx = 0;
+
+ if (!(rd->mask & (ResizeUpMask | ResizeDownMask)))
+ dy = 0;
+
+ /* Apply the width/height modifications */
+ if (rd->mask & ResizeLeftMask)
+ width -= dx;
+ else if (rd->mask & ResizeRightMask)
+ width += dx;
+
+ if (rd->mask & ResizeUpMask)
+ height -= dy;
+ else if (rd->mask & ResizeDownMask)
+ height += dy;
+
+ /* Prevent window being resized to a
+ smaller size than 1x1 */
+ width = MAX (1, width);
+ height = MAX (1, height);
+
+ /* Apply constraints */
+ resizeConstrainResizeIncrement (rd->w, width, height, &width, &height);
+
+ newWidth = width;
+ newHeight = height;
+ resizeConstrainAspectRatio (rd->w, width, height, &newWidth, &newHeight);
+ resizeConstrainMinMax (rd->w, newWidth, newHeight, &newWidth, &newHeight);
+
+ if ((width != newWidth) || (height != newHeight))
+ {
+ /* if the resizing hit constraints, move the mouse
+ pointer to the new border to avoid desynchronization */
+ int pointerAdjustX = 0, pointerAdjustY = 0;
+
+ if (rd->mask & ResizeRightMask)
+ pointerAdjustX = newWidth - width;
+ else if (rd->mask & ResizeLeftMask)
+ pointerAdjustX = width - newWidth;
+
+ if (rd->mask & ResizeDownMask)
+ pointerAdjustY = newHeight - height;
+ else if (rd->mask & ResizeUpMask)
+ pointerAdjustY = height - newHeight;
+
+ warpPointer (rd->w->screen, pointerAdjustX, pointerAdjustY);
+ }
+
+ dx -= newWidth - width;
+ dy -= newHeight - height;
+
+ /* If no resizing, drop out now. */
+ if (!dx && !dy)
+ return;
+
+ /* damage old paint region */
+ if (rd->resizeMode != ResizeModeNormal)
+ resizeDamagePaintRectangle (rd->w->screen);
+
+ /* Move window by delta if resizing from left/top */
+ if (rd->mask & ResizeLeftMask && newWidth != rd->currentWidth)
+ rd->currentX += dx;
+
+ if (rd->mask & ResizeUpMask && newHeight != rd->currentHeight)
+ rd->currentY += dy;
+
+ rd->currentWidth = newWidth;
+ rd->currentHeight = newHeight;
+
+ if (rd->mask & ResizeLeftMask)
+ rd->currentX = rd->w->serverX + rd->w->serverWidth - rd->currentWidth;
+
+ if (rd->mask & ResizeUpMask)
+ rd->currentY = rd->w->serverY + rd->w->serverHeight - rd->currentHeight;
+
+ if (rd->resizeMode == ResizeModeNormal)
+ resizeUpdateRealWindowSize(d);
+ else
+ resizeDamagePaintRectangle (rd->w->screen);
+}
static void
resizeHandleKeyEvent (CompScreen *s,
@@ -448,8 +791,18 @@ resizeHandleKeyEvent (CompScreen *s,
x = left + width * (rKeys[i].dx + 1) / 2;
y = top + height * (rKeys[i].dy + 1) / 2;
- warpPointer (s, x - pointerX, y - pointerY);
rd->mask = rKeys[i].resizeMask;
+
+ /* recalculate delta */
+ rd->xDelta = (x - rd->currentX);
+ if (rd->mask & ResizeRightMask)
+ rd->xDelta = rd->w->attrib.width - rd->xDelta;
+
+ rd->yDelta = (y - rd->currentY);
+ if (rd->mask & ResizeDownMask)
+ rd->yDelta = rd->w->attrib.height - rd->yDelta;
+
+ warpPointer (s, x - pointerX, y - pointerY);
updateScreenGrab (s, rs->grabIndex, rs->cursor[i]);
}
break;
@@ -464,43 +817,34 @@ resizeHandleMotionEvent (CompScreen *s,
{
RESIZE_SCREEN (s);
- if (rs->grabIndex)
- {
- int pointerDx, pointerDy;
-
- RESIZE_DISPLAY (s->display);
-
- pointerDx = xRoot - lastPointerX;
- pointerDy = yRoot - lastPointerY;
-
- if (pointerDx || pointerDy)
- {
- int w, h;
-
- w = rd->ucWidth;
- h = rd->ucHeight;
-
- if (rd->mask & ResizeLeftMask)
- w -= pointerDx;
- else if (rd->mask & ResizeRightMask)
- w += pointerDx;
-
- if (rd->mask & ResizeUpMask)
- h -= pointerDy;
- else if (rd->mask & ResizeDownMask)
- h += pointerDy;
-
- rd->ucWidth = w;
- rd->ucHeight = h;
-
- resizeConstrainMinMax (rd->w, w, h, &w, &h);
+ if (!rs->grabIndex)
+ return;
- rd->width = w;
- rd->height = h;
+ RESIZE_DISPLAY (s->display);
- resizeUpdateWindowSize (s->display);
- }
- }
+ int pointerDx, pointerDy;
+
+ pointerDx = xRoot - rd->currentX;
+ pointerDy = yRoot - rd->currentY;
+
+ if (rd->mask & ResizeRightMask)
+ pointerDx -= (rd->currentWidth - rd->xDelta);
+
+ if (rd->mask & ResizeLeftMask)
+ pointerDx -= rd->xDelta;
+
+ if (rd->mask & ResizeDownMask)
+ pointerDy -= (rd->currentHeight - rd->yDelta);
+
+ if (rd->mask & ResizeUpMask)
+ pointerDy -= rd->yDelta;
+
+ if (!pointerDx && !pointerDy)
+ return;
+
+ resizeUpdateWindowSize (s->display,
+ pointerDx,
+ pointerDy);
}
static void
@@ -667,11 +1011,165 @@ resizeHandleEvent (CompDisplay *d,
sa = (XSyncAlarmNotifyEvent *) event;
if (rd->w->syncAlarm == sa->alarm)
- resizeUpdateWindowSize (d);
+ resizeUpdateRealWindowSize (d);
}
}
}
+static Bool
+resizePaintWindow(CompWindow *w,
+ const WindowPaintAttrib *attrib,
+ const CompTransform *transform,
+ Region region,
+ unsigned int mask)
+{
+ CompScreen *s = w->screen;
+ Bool status;
+
+ RESIZE_SCREEN (s);
+ RESIZE_DISPLAY (s->display);
+
+ if (rd->w && (rd->w->id == w->id))
+ {
+ CompTransform wTransform = *transform;
+
+ if (rd->resizeMode == ResizeModeStretch)
+ {
+ float xScale = (float)(rd->currentWidth) /
+ (float)(rd->w->attrib.width);
+ float yScale = (float)(rd->currentHeight) /
+ (float)(rd->w->attrib.height);
+ int xTranslate = rd->currentX - w->attrib.x;
+ int yTranslate = rd->currentY - w->attrib.y;
+
+ matrixTranslate (&wTransform, w->attrib.x, w->attrib.y, 0.0f);
+ matrixScale (&wTransform, xScale, yScale, 0.0f);
+ matrixTranslate (&wTransform,
+ xTranslate / xScale - w->attrib.x,
+ yTranslate / yScale - w->attrib.y,
+ 0.0f);
+
+ mask |= PAINT_WINDOW_TRANSFORMED_MASK;
+
+ /* reset rd->w if it was kept intact only to avoid
+ flashing back to the old size */
+ if (!rs->grabIndex &&
+ (rd->currentWidth == w->attrib.width) &&
+ (rd->currentHeight == w->attrib.height))
+ {
+ rd->w = 0;
+ }
+ }
+
+ UNWRAP(rs, s, paintWindow);
+ status = (*s->paintWindow) (w, attrib, &wTransform, region, mask);
+ WRAP(rs, s, paintWindow, resizePaintWindow);
+ }
+ else
+ {
+ UNWRAP(rs, s, paintWindow);
+ status = (*s->paintWindow) (w, attrib, transform, region, mask);
+ WRAP(rs, s, paintWindow, resizePaintWindow);
+ }
+
+ return status;
+}
+
+static void
+resizePaintOutline(CompScreen *s,
+ const ScreenPaintAttrib *sa,
+ const CompTransform *transform,
+ int output,
+ Bool transformed)
+{
+ int x1, x2, y1, y2;
+ CompTransform sTransform;
+
+ RESIZE_SCREEN(s);
+
+ if (!rs->grabIndex)
+ return;
+
+ RESIZE_DISPLAY(s->display);
+
+ if ((rd->resizeMode != ResizeModeOutline) &&
+ (rd->resizeMode != ResizeModeFilledOutline))
+ return;
+
+ if (!rd->w || (rd->w->state & MAXIMIZE_STATE))
+ return;
+
+ x1 = rd->currentX - rd->w->input.left;
+ x2 = rd->currentX + rd->currentWidth + rd->w->input.right;
+ y1 = rd->currentY - rd->w->input.top;
+ y2 = rd->currentY + rd->w->input.bottom +
+ (rd->w->shaded ? rd->w->height : rd->currentHeight);
+
+ sTransform = *transform;
+
+ if (transformed)
+ {
+ (s->applyScreenTransform) (s, sa, output, &sTransform);
+ transformToScreenSpace (s, output, -sa->zTranslate, &sTransform);
+ }
+ else
+ transformToScreenSpace (s, output, -DEFAULT_Z_CAMERA, &sTransform);
+
+ glPushMatrix ();
+ glLoadMatrixf (sTransform.m);
+
+ glDisableClientState (GL_TEXTURE_COORD_ARRAY);
+ glEnable (GL_BLEND);
+
+ if (rd->resizeMode == ResizeModeFilledOutline)
+ {
+ glColor4usv (rd->opt[RESIZE_DISPLAY_OPTION_FILL_COLOR].value.c);
+ glRecti (x1, y2, x2, y1);
+ }
+
+ /* This section draws the outline */
+ glColor4usv (rd->opt[RESIZE_DISPLAY_OPTION_BORDER_COLOR].value.c);
+ glLineWidth (2.0);
+ glBegin (GL_LINE_LOOP);
+ glVertex2i (x1, y1);
+ glVertex2i (x2, y1);
+ glVertex2i (x2, y2);
+ glVertex2i (x1, y2);
+ glEnd ();
+
+ /* Clean up */
+ glColor4usv (defaultColor);
+ glDisable (GL_BLEND);
+ glEnableClientState (GL_TEXTURE_COORD_ARRAY);
+ glPopMatrix ();
+}
+
+static Bool
+resizePaintScreen(CompScreen *s,
+ const ScreenPaintAttrib *sAttrib,
+ const CompTransform *transform,
+ Region region,
+ int output,
+ unsigned int mask)
+{
+ Bool status = FALSE;
+
+ RESIZE_SCREEN(s);
+ RESIZE_DISPLAY(s->display);
+
+ if (rd->w && rd->resizeMode == ResizeModeStretch)
+ mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS_MASK;
+
+ UNWRAP(rs, s, paintScreen);
+ status = (*s->paintScreen) (s, sAttrib, transform, region, output, mask);
+ WRAP(rs, s, paintScreen, resizePaintScreen);
+
+ if (status)
+ resizePaintOutline(s, sAttrib, transform, output, FALSE);
+
+ return status;
+}
+
static CompOption *
resizeGetDisplayOptions (CompPlugin *plugin,
CompDisplay *display,
@@ -702,6 +1200,25 @@ resizeSetDisplayOption (CompPlugin *plugin,
case RESIZE_DISPLAY_OPTION_INITIATE:
if (setDisplayAction (display, o, value))
return TRUE;
+ break;
+ case RESIZE_DISPLAY_OPTION_MODE:
+ if (compSetStringOption (o, value))
+ {
+ int i;
+
+ rd->resizeMode = RESIZE_MODE_DEFAULT;
+ for (i = 0; i < o->rest.s.nString; i++)
+ if (strcmp (resizeModes[i], o->value.s) == 0)
+ rd->resizeMode = (ResizeMode) i;
+
+ return TRUE;
+ }
+ break;
+ case RESIZE_DISPLAY_OPTION_BORDER_COLOR:
+ case RESIZE_DISPLAY_OPTION_FILL_COLOR:
+ if (compSetColorOption (o, value))
+ return TRUE;
+ break;
default:
break;
}
@@ -734,6 +1251,36 @@ resizeDisplayInitOptions (ResizeDisplay *rd,
o->value.action.key.keycode =
XKeysymToKeycode (display,
XStringToKeysym (RESIZE_INITIATE_KEY_DEFAULT));
+
+ o = &rd->opt[RESIZE_DISPLAY_OPTION_MODE];
+ o->name = "resize_mode";
+ o->shortDesc = N_("Resize Display Mode");
+ o->longDesc = N_("Select between 'Normal', 'Stretched Texture', "
+ "'Outline and Filled' outline modes.");
+ o->type = CompOptionTypeString;
+ o->value.s = strdup(resizeModes[RESIZE_MODE_DEFAULT]);
+ o->rest.s.string = resizeModes;
+ o->rest.s.nString = NUM_RESIZE_MODES;
+
+ o = &rd->opt[RESIZE_DISPLAY_OPTION_BORDER_COLOR];
+ o->name = "border_color";
+ o->shortDesc = N_("Outline Color");
+ o->longDesc = N_("Outline Color for Outline and Filled Outline modes.");
+ o->type = CompOptionTypeColor;
+ o->value.c[0] = RESIZE_BORDER_COLOR_RED;
+ o->value.c[1] = RESIZE_BORDER_COLOR_GREEN;
+ o->value.c[2] = RESIZE_BORDER_COLOR_BLUE;
+ o->value.c[3] = RESIZE_BORDER_COLOR_ALPHA;
+
+ o = &rd->opt[RESIZE_DISPLAY_OPTION_FILL_COLOR];
+ o->name = "fill_color";
+ o->shortDesc = N_("Fill Color");
+ o->longDesc = N_("Fill Color for Filled Outline mode.");
+ o->type = CompOptionTypeColor;
+ o->value.c[0] = RESIZE_FILL_COLOR_RED;
+ o->value.c[1] = RESIZE_FILL_COLOR_GREEN;
+ o->value.c[2] = RESIZE_FILL_COLOR_BLUE;
+ o->value.c[3] = RESIZE_FILL_COLOR_ALPHA;
}
static Bool
@@ -760,6 +1307,8 @@ resizeInitDisplay (CompPlugin *p,
rd->releaseButton = 0;
+ rd->resizeMode = RESIZE_MODE_DEFAULT;
+
for (i = 0; i < NUM_KEYS; i++)
rd->key[i] = XKeysymToKeycode (d->display,
XStringToKeysym (rKeys[i].name));
@@ -820,6 +1369,9 @@ resizeInitScreen (CompPlugin *p,
rs->cursor[3] = rs->downCursor;
addScreenAction (s, &rd->opt[RESIZE_DISPLAY_OPTION_INITIATE].value.action);
+
+ WRAP (rs, s, paintWindow, resizePaintWindow);
+ WRAP (rs, s, paintScreen, resizePaintScreen);
s->privates[rd->screenPrivateIndex].ptr = rs;
@@ -855,6 +1407,9 @@ resizeFiniScreen (CompPlugin *p,
removeScreenAction (s,
&rd->opt[RESIZE_DISPLAY_OPTION_INITIATE].value.action);
+ UNWRAP (rs, s, paintWindow);
+ UNWRAP (rs, s, paintScreen);
+
free (rs);
}