diff --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); }