rendered paste bodydiff --git a/plugins/ini.c b/plugins/ini.c
index c55d897..288079b 100644
--- a/plugins/ini.c
+++ b/plugins/ini.c
@@ -143,9 +143,11 @@ static IniFileData *
iniGetFileDataFromFilename (CompDisplay *d,
const char *filename)
{
- int len, i;
- int pluginSep = 0, screenSep = 0;
- char *pluginStr, *screenStr;
+ int fnLen, length;
+ char *pluginSep;
+ char *screenSep;
+ char *pluginStr;
+ char *screenStr;
IniFileData *fd;
INI_DISPLAY (d);
@@ -153,35 +155,27 @@ iniGetFileDataFromFilename (CompDisplay *d,
if (!filename)
return NULL;
- len = strlen (filename);
+ fnLen = strlen(filename);
- if (len < (strlen(FILE_SUFFIX) + 2))
+ if (fnLen < (strlen(FILE_SUFFIX) + 2))
return NULL;
- if ((filename[0]=='.') || (filename[len-1]=='~'))
+ if ((filename[0] == '.') || (filename[fnLen-1] == '~'))
return NULL;
for (fd = id->fileData; fd; fd = fd->next)
if (strcmp (fd->filename, filename) == 0)
return fd;
- for (i=0; i<len; i++)
- {
- if (filename[i] == '-')
- {
- if (!pluginSep)
- pluginSep = i-1;
- else
- return NULL; /*found a second dash */
- }
- else if (filename[i] == '.')
- {
- if (!screenSep)
- screenSep = i-1;
- else
- return NULL; /*found a second dot */
- }
- }
+ /* the split point for the plugin name */
+ pluginSep = strrchr(filename, '-');
+ if (!pluginSep)
+ return NULL;
+
+ /* the split point for the screen name */
+ screenSep = strrchr(filename, '.');
+ if (!screenSep)
+ return NULL;
if (!pluginSep || !screenSep)
return NULL;
@@ -202,17 +196,12 @@ iniGetFileDataFromFilename (CompDisplay *d,
newFd->filename = strdup (filename);
- pluginStr = malloc (sizeof (char) * pluginSep + 1);
- screenStr = malloc (sizeof (char) * (screenSep - pluginSep) + 1);
-
- if (!pluginStr || !screenStr)
- return NULL;
-
- strncpy (pluginStr, filename, pluginSep + 1);
- pluginStr[pluginSep + 1] = '\0';
-
- strncpy (screenStr, &filename[pluginSep+2], (screenSep - pluginSep) + 1);
- screenStr[(screenSep - pluginSep) -1] = '\0';
+ /* get plugin and screen name */
+ length = strlen(filename) - strlen(pluginSep);
+ pluginStr = strndup(filename, length);
+ pluginSep++; /* skip the '-' */
+ length = strlen(pluginSep) - strlen(screenSep);
+ screenStr = strndup(pluginSep, length);
if (strcmp (pluginStr, CORE_NAME) == 0)
newFd->plugin = NULL;
@@ -330,7 +319,7 @@ iniGetFilename (CompDisplay *d,
if (fn)
{
sprintf (fn, "%s-%s%s",
- plugin?plugin:CORE_NAME, screenStr, FILE_SUFFIX);
+ plugin ? plugin : CORE_NAME, screenStr, FILE_SUFFIX);
*filename = strdup (fn);
@@ -348,48 +337,20 @@ iniGetFilename (CompDisplay *d,
static Bool
iniParseLine (char *line, char **optionName, char **optionValue)
{
- int pos = 0;
- int splitPos = 0;
- int endPos = 0;
- char tmpName[MAX_OPTION_LENGTH];
- char tmpValue[MAX_OPTION_LENGTH];
+ char *splitPos;
+ int length;
if (line[0] == '\0' || line[0] == '\n')
return FALSE;
- while (pos < strlen(line))
- {
- if (!splitPos && line[pos] == '=')
- splitPos = pos;
- if (line[pos] == '\n')
- {
- endPos = pos;
- break;
- }
- pos++;
- }
-
- if (splitPos && endPos)
- {
- tmpName[0] = '\0';
- tmpValue[0] = '\0';
-
- int i;
- for (i=0; i < splitPos; i++)
- tmpName[i] = line[i];
- tmpName[splitPos] = '\0';
-
- for (i=splitPos+1; i<endPos; i++)
- tmpValue[i - (splitPos+1)] = line[i];
- tmpValue[endPos - (splitPos+1)] = '\0';
-
- *optionName = strdup (tmpName);
- *optionValue = strdup (tmpValue);
- }
- else
- {
+ splitPos = strchr(line, '=');
+ if (!splitPos)
return FALSE;
- }
+
+ length = strlen(line) - strlen(splitPos);
+ *optionName = strndup(line, length);
+ splitPos++;
+ *optionValue = strndup(splitPos, strlen(splitPos)-1);
return TRUE;
}
@@ -397,53 +358,48 @@ iniParseLine (char *line, char **optionName, char **optionValue)
static Bool
csvToList (char *csv, CompListValue *list, CompOptionType type)
{
- char *csvtmp, *split, *item = NULL;
- int count = 1, i, itemLength;
+ char *splitStart = NULL;
+ char *splitEnd = NULL;
+ char *item = NULL;
+ int itemLength;
+ int count;
+ int i;
if (csv[0] == '\0')
{
list->nValue = 0;
return FALSE;
}
-
- csvtmp = strdup (csv);
- csvtmp = strchr (csv, ',');
-
- while (csvtmp)
- {
- csvtmp++; /* avoid the comma */
- count++;
- csvtmp = strchr (csvtmp, ',');
- }
-
+
+ int length = strlen(csv);
+ count = 1;
+ for (i = 0; i < length; i++)
+ if (csv[i] == ',' && i != length-1)
+ count++;
+
+ splitStart = csv;
list->value = malloc (sizeof (CompOptionValue) * count);
if (list->value)
{
- for (i=0; i<count; i++)
+ for (i = 0; i < count; i++)
{
- split = strchr (csv, ',');
- if (split)
+ splitEnd = strchr(splitStart, ',');
+
+ if (splitEnd)
{
- /* > 1 value */
- itemLength = strlen(csv) - strlen(split);
- item = realloc (item, sizeof (char) * (itemLength+1));
- strncpy (item, csv, itemLength);
- item[itemLength] = '\0';
- csv += itemLength + 1;
+ itemLength = strlen(splitStart) - strlen(splitEnd);
+ item = strndup(splitStart, itemLength);
}
- else
+ else // last value
{
- /* 1 value only */
- itemLength = strlen(csv);
- item = realloc (item, sizeof (char) * (itemLength+1));
- strncpy (item, csv, itemLength);
- item[itemLength] = '\0';
+ item = strdup(splitStart);
}
switch (type)
{
case CompOptionTypeString:
- list->value[i].s = strdup (item);
+ if (item[0] != '\0')
+ list->value[i].s = strdup (item);
break;
case CompOptionTypeBool:
if (item[0] != '\0')
@@ -464,13 +420,14 @@ csvToList (char *csv, CompListValue *list, CompOptionType type)
default:
break;
}
+
+ splitStart = ++splitEnd;
+ if (item)
+ free(item);
}
list->nValue = count;
}
- if (item)
- free (item);
-
return TRUE;
}
@@ -543,6 +500,7 @@ parseAction(CompDisplay *d, char *optionName, char *optionValue, IniAction *acti
action->a.bell = FALSE;
action->a.edgeMask = 0;
action->a.edgeButton = 0;
+ action->valueMasks = 0;
}
/* detect a new option (might happen when the options are incomplete) */
else if (action->valueMasks != ACTION_VALUES_ALL)
@@ -639,7 +597,7 @@ iniLoadOptionsFromFile (CompDisplay *d,
CompScreen *s = NULL;
CompPlugin *p = NULL;
Bool status = FALSE;
- Bool hv = FALSE;
+ Bool hasValue = FALSE;
CompOptionValue value;
if (plugin)
@@ -688,12 +646,13 @@ iniLoadOptionsFromFile (CompDisplay *d,
IniAction action;
action.realOptionName = NULL;
- Bool continueReading = FALSE;
- while (fgets (&tmp[0], MAX_OPTION_LENGTH, optionFile) != NULL)
+ Bool continueReading;
+ while (fgets (tmp, MAX_OPTION_LENGTH, optionFile) != NULL)
{
status = FALSE;
+ continueReading = FALSE;
- if (!iniParseLine (&tmp[0], &optionName, &optionValue))
+ if (!iniParseLine (tmp, &optionName, &optionValue))
{
fprintf(stderr,
"Ignoring line '%s' in %s %i\n", tmp, plugin, screen);
@@ -710,29 +669,29 @@ iniLoadOptionsFromFile (CompDisplay *d,
switch (o->type)
{
case CompOptionTypeBool:
- hv = TRUE;
+ hasValue = TRUE;
value.b = (Bool) atoi (optionValue);
break;
case CompOptionTypeInt:
- hv = TRUE;
+ hasValue = TRUE;
value.i = atoi (optionValue);
break;
case CompOptionTypeFloat:
- hv = TRUE;
+ hasValue = TRUE;
value.f = atof (optionValue);
break;
case CompOptionTypeString:
- hv = TRUE;
+ hasValue = TRUE;
value.s = strdup (optionValue);
break;
case CompOptionTypeColor:
- hv = stringToColor (optionValue, value.c);
+ hasValue = stringToColor (optionValue, value.c);
break;
case CompOptionTypeList:
- hv = csvToList (optionValue, &value.list, value.list.type);
+ hasValue = csvToList (optionValue, &value.list, value.list.type);
break;
case CompOptionTypeMatch:
- hv = TRUE;
+ hasValue = TRUE;
matchInit (&value.match);
matchAddFromString (&value.match, optionValue);
break;
@@ -740,7 +699,7 @@ iniLoadOptionsFromFile (CompDisplay *d,
break;
}
- if (hv)
+ if (hasValue)
{
if (plugin && p)
{
@@ -780,10 +739,10 @@ iniLoadOptionsFromFile (CompDisplay *d,
if (action.realOptionName &&
!continueReading)
{
- o = compFindOption (option, nOption, action.realOptionName, 0);
- if (o)
+ CompOption *realOption = compFindOption (option, nOption, action.realOptionName, 0);
+ if (realOption)
{
- value = o->value;
+ value = realOption->value;
value.action.type = action.a.type;
value.action.key = action.a.key;
@@ -811,16 +770,12 @@ iniLoadOptionsFromFile (CompDisplay *d,
free(action.realOptionName);
action.realOptionName = NULL;
- /* we missed the current line because we exited it in the first call */
- if (!o && action.valueMasks == ACTION_VALUES_ALL)
- {
- action.valueMasks = 0;
+ /* we missed the current line because we exited it in the first call.
+ we also need to check wether we have a incomplete options here,
+ because other while parsing the last line again, would caus real
+ trouble. ;-) */
+ if (!o && action.valueMasks != ACTION_VALUES_ALL)
parseAction(d, optionName, optionValue, &action);
- }
- else
- {
- action.valueMasks = 0;
- }
}
}
}
@@ -830,7 +785,6 @@ iniLoadOptionsFromFile (CompDisplay *d,
free (optionName);
if (optionValue)
free (optionValue);
- continueReading = FALSE;
}
return TRUE;
diff --git a/plugins/resize.c b/plugins/resize.c
index b9eb42b..9bdf44c 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,31 @@ 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;
+
+ int rightEdge;
+ int bottomEdge;
+
+ ResizeMode resizeMode;
+
KeyCode key[NUM_KEYS];
} ResizeDisplay;
typedef struct _ResizeScreen {
int grabIndex;
+ PaintWindowProc paintWindow;
+ PaintScreenProc paintScreen;
+
Cursor leftCursor;
Cursor rightCursor;
Cursor upCursor;
@@ -111,6 +156,38 @@ 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 Bool
resizeInitiate (CompDisplay *d,
CompAction *action,
@@ -186,12 +263,19 @@ 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->rightEdge = rd->currentX + rd->currentWidth;
+ rd->bottomEdge = rd->currentY + rd->currentHeight;
+
+ rd->xDelta = 0;
+ rd->yDelta = 0;
+
lastPointerX = x;
lastPointerY = y;
@@ -250,6 +334,17 @@ resizeInitiate (CompDisplay *d,
warpPointer (d, 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)
+ damageScreen (w->screen);
}
}
@@ -288,16 +383,32 @@ resizeTerminate (CompDisplay *d,
}
else
{
- syncWindowPosition (rd->w);
+ if (rd->resizeMode != ResizeModeNormal)
+ resizeUpdateRealWindowSize (d);
+ else
+ syncWindowPosition (rd->w);
}
+ if (rd->resizeMode != ResizeModeNormal)
+ damageScreen (rd->w->screen);
+
if (rs->grabIndex)
{
removeScreenGrab (rd->w->screen, rs->grabIndex, NULL);
rs->grabIndex = 0;
}
- rd->w = 0;
+ /* don't reset rd->w here if we are using the 'Stretch' mode
+ and we really resized the window as we still want to apply
+ the stretching effect until the server processed the resize
+ request to avoid the window flashing back to the old size */
+ if (((rd->currentWidth == rd->w->attrib.width) &&
+ (rd->currentHeight == rd->w->attrib.height)) ||
+ (rd->resizeMode != ResizeModeStretch))
+ {
+ rd->w = 0;
+ }
+
rd->releaseButton = 0;
}
@@ -306,53 +417,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 +454,283 @@ 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;
+
+ /* 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 (d, pointerAdjustX, pointerAdjustY);
+ }
+
+ dx -= newWidth - width;
+ dy -= newHeight - height;
+
+ /* If no resizing, drop out now. */
+ if (!dx && !dy)
+ return;
+
+ if (rd->resizeMode != ResizeModeNormal)
+ damageScreen(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->rightEdge - rd->currentWidth;
+
+ if (rd->mask & ResizeUpMask)
+ rd->currentY = rd->bottomEdge - rd->currentHeight;
+
+ if (rd->resizeMode == ResizeModeNormal)
+ {
+ resizeUpdateRealWindowSize(d);
+ }
+ else if (rd->resizeMode == ResizeModeStretch)
+ {
+ moveWindow(rd->w,
+ rd->currentX - rd->w->attrib.x,
+ rd->currentY - rd->w->attrib.y,
+ TRUE, TRUE);
+ syncWindowPosition(rd->w);
+ }
+}
static void
resizeHandleKeyEvent (CompScreen *s,
@@ -448,8 +778,18 @@ resizeHandleKeyEvent (CompScreen *s,
x = left + width * (rKeys[i].dx + 1) / 2;
y = top + height * (rKeys[i].dy + 1) / 2;
+ 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->display, x - pointerX, y - pointerY);
- rd->mask = rKeys[i].resizeMask;
updateScreenGrab (s, rs->grabIndex, rs->cursor[i]);
}
break;
@@ -464,43 +804,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,9 +998,159 @@ 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);
+
+ matrixTranslate (&wTransform, w->attrib.x, w->attrib.y, 0.0f);
+ matrixScale (&wTransform, xScale, yScale, 0.0f);
+ matrixTranslate (&wTransform, -w->attrib.x, -w->attrib.y, 0.0f);
+
+ mask |= PAINT_WINDOW_TRANSFORMED_MASK;
+
+ /* reset rd->w if the window coordinates match and there is no
+ screen grab; which means that resizeTerminate was already
+ called and we left rd->w set only to avoid weird flashing */
+ 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 *
@@ -702,6 +1183,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 +1234,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 +1290,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 +1352,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 +1390,9 @@ resizeFiniScreen (CompPlugin *p,
removeScreenAction (s,
&rd->opt[RESIZE_DISPLAY_OPTION_INITIATE].value.action);
+ UNWRAP (rs, s, paintWindow);
+ UNWRAP (rs, s, paintScreen);
+
free (rs);
}