rendered paste bodydiff --git a/include/scale.h b/include/scale.h
index 07c73e4..1d8913a 100644
--- a/include/scale.h
+++ b/include/scale.h
@@ -37,12 +37,21 @@
#define SCALE_ICON_BIG 2
#define SCALE_ICON_LAST SCALE_ICON_BIG
+#define SCALE_MMMODE_CURRENT 0
+#define SCALE_MMMODE_ALL 1
+#define SCALE_MMMODE_LAST SCALE_MMMODE_ALL
+
typedef struct _ScaleSlot {
int x1, y1, x2, y2;
int filled;
float scale;
} ScaleSlot;
+typedef struct _SlotArea {
+ int nWindows;
+ XRectangle workArea;
+} SlotArea;
+
#define SCALE_DISPLAY_OPTION_ABI 0
#define SCALE_DISPLAY_OPTION_INDEX 1
#define SCALE_DISPLAY_OPTION_INITIATE 2
@@ -64,15 +73,16 @@ typedef struct _ScaleDisplay {
KeyCode leftKeyCode, rightKeyCode, upKeyCode, downKeyCode;
} ScaleDisplay;
-#define SCALE_SCREEN_OPTION_SPACING 0
-#define SCALE_SCREEN_OPTION_SPEED 1
-#define SCALE_SCREEN_OPTION_TIMESTEP 2
-#define SCALE_SCREEN_OPTION_WINDOW_MATCH 3
-#define SCALE_SCREEN_OPTION_DARKEN_BACK 4
-#define SCALE_SCREEN_OPTION_OPACITY 5
-#define SCALE_SCREEN_OPTION_ICON 6
-#define SCALE_SCREEN_OPTION_HOVER_TIME 7
-#define SCALE_SCREEN_OPTION_NUM 8
+#define SCALE_SCREEN_OPTION_SPACING 0
+#define SCALE_SCREEN_OPTION_SPEED 1
+#define SCALE_SCREEN_OPTION_TIMESTEP 2
+#define SCALE_SCREEN_OPTION_WINDOW_MATCH 3
+#define SCALE_SCREEN_OPTION_DARKEN_BACK 4
+#define SCALE_SCREEN_OPTION_OPACITY 5
+#define SCALE_SCREEN_OPTION_ICON 6
+#define SCALE_SCREEN_OPTION_HOVER_TIME 7
+#define SCALE_SCREEN_OPTION_MULTIMONITOR_MODE 8
+#define SCALE_SCREEN_OPTION_NUM 9
typedef enum {
ScaleTypeNormal = 0,
diff --git a/metadata/scale.xml.in b/metadata/scale.xml.in
index 19b334a..60ad22e 100644
--- a/metadata/scale.xml.in
+++ b/metadata/scale.xml.in
@@ -108,6 +108,21 @@
<min>50</min>
<max>10000</max>
</option>
+ <option name="multimonitor_mode" type="int">
+ <_short>Multi Monitor Mode</_short>
+ <_long>Selects where windows are scaled if multiple monitors are used.</_long>
+ <min>0</min>
+ <max>1</max>
+ <default>0</default>
+ <desc>
+ <value>0</value>
+ <_name>On current monitor</_name>
+ </desc>
+ <desc>
+ <value>1</value>
+ <_name>On all monitors</_name>
+ </desc>
+ </option>
</screen>
</plugin>
</compiz>
diff --git a/plugins/scale.c b/plugins/scale.c
index 2cbe092..c16d534 100644
--- a/plugins/scale.c
+++ b/plugins/scale.c
@@ -397,42 +397,35 @@ compareWindowsDistance (const void *elem1,
GET_SCALE_WINDOW (w2, ss)->distance;
}
-static void
-layoutSlots (CompScreen *s)
+static void
+layoutSlotsForArea (CompScreen * s,
+ XRectangle workArea,
+ int nWindows)
{
- int i, j, x, y, width, height, lines, n;
- int x1, y1, x2, y2;
+ int i, j;
+ int x, y, width, height;
+ int lines, n, nSlots;
int spacing;
SCALE_SCREEN (s);
- spacing = ss->opt[SCALE_SCREEN_OPTION_SPACING].value.i;
-
- ss->nSlots = 0;
-
- lines = sqrt (ss->nWindows + 1);
-
- getCurrentOutputExtents (s, &x1, &y1, &x2, &y2);
+ if (!nWindows)
+ return;
- if (s->workArea.x > x1)
- x1 = s->workArea.x;
- if (s->workArea.x + s->workArea.width < x2)
- x2 = s->workArea.x + s->workArea.width;
- if (s->workArea.y > y1)
- y1 = s->workArea.y;
- if (s->workArea.y + s->workArea.height < y2)
- y2 = s->workArea.y + s->workArea.height;
+ lines = sqrt (nWindows + 1);
+ spacing = ss->opt[SCALE_SCREEN_OPTION_SPACING].value.i;
- y = y1 + spacing;
- height = ((y2 - y1) - (lines + 1) * spacing) / lines;
+ nSlots = 0;
+ y = workArea.y + spacing;
+ height = (workArea.height - (lines + 1) * spacing) / lines;
for (i = 0; i < lines; i++)
{
- n = MIN (ss->nWindows - ss->nSlots,
- ceilf ((float) ss->nWindows / lines));
+ n = MIN (nWindows - nSlots,
+ ceilf ((float)nWindows / lines));
- x = x1 + spacing;
- width = ((x2 - x1) - (n + 1) * spacing) / n;
+ x = workArea.x + spacing;
+ width = (workArea.width - (n + 1) * spacing) / n;
for (j = 0; j < n; j++)
{
@@ -446,12 +439,135 @@ layoutSlots (CompScreen *s)
x += width + spacing;
ss->nSlots++;
+ nSlots++;
}
y += height + spacing;
}
}
+static SlotArea*
+getSlotAreas (CompScreen *s)
+{
+ int i;
+ XRectangle workArea;
+ float *size;
+ float sizePerWindow, sum = 0.0f;
+ int left;
+ SlotArea *slotAreas;
+
+ SCALE_SCREEN(s);
+
+ size = malloc (s->nOutputDev * sizeof (int));
+ slotAreas = malloc (s->nOutputDev * sizeof (SlotArea));
+
+ left = ss->nWindows;
+
+ for (i = 0; i < s->nOutputDev; i++)
+ {
+ /* determine the size of the workarea for each output device */
+ workArea = s->outputDev[i].workArea;
+
+ size[i] = workArea.width * workArea.height;
+ sum += size[i];
+
+ slotAreas[i].nWindows = 0;
+ slotAreas[i].workArea = workArea;
+ }
+
+ /* calculate size available for each window */
+ sizePerWindow = sum / ss->nWindows;
+
+ for (i = 0; i < s->nOutputDev && left; i++)
+ {
+ /* fill the areas with windows */
+ int nw = floor(size[i] / sizePerWindow);
+ nw = MIN (nw,left);
+ size[i] -= nw * sizePerWindow;
+ slotAreas[i].nWindows = nw;
+ left -= nw;
+ }
+
+ /* add left windows to output devices with the biggest free space */
+ while (left > 0)
+ {
+ int num = 0;
+ float big = 0;
+
+ for (i = 0; i < s->nOutputDev; i++)
+ if (size[i] > big)
+ {
+ num = i;
+ big = size[i];
+ }
+
+ size[num] -= sizePerWindow;
+ slotAreas[num].nWindows++;
+ left--;
+ }
+
+ free(size);
+ return slotAreas;
+}
+
+static void
+layoutSlots (CompScreen *s)
+{
+ int i;
+ int spacing;
+ int mmMode;
+
+ SCALE_SCREEN (s);
+
+ spacing = ss->opt[SCALE_SCREEN_OPTION_SPACING].value.i;
+ mmMode = ss->opt[SCALE_SCREEN_OPTION_MULTIMONITOR_MODE].value.i;
+
+ /* if we have only one head, we don't need the
+ additional effort of the all monitor mode */
+ if (s->nOutputDev == 1)
+ mmMode = SCALE_MMMODE_CURRENT;
+
+ ss->nSlots = 0;
+
+ switch (mmMode)
+ {
+ case SCALE_MMMODE_ALL:
+ {
+ SlotArea *slotAreas;
+ slotAreas = getSlotAreas (s);
+ if (slotAreas)
+ {
+ for (i = 0; i < s->nOutputDev; i++)
+ layoutSlotsForArea (s,
+ slotAreas[i].workArea,
+ slotAreas[i].nWindows);
+ free (slotAreas);
+ }
+ }
+ break;
+ case SCALE_MMMODE_CURRENT:
+ default:
+ {
+ XRectangle workArea;
+ workArea = s->outputDev[s->currentOutputDev].workArea;
+ layoutSlotsForArea (s, workArea, ss->nWindows);
+ }
+ break;
+ }
+/*
+ getCurrentOutputExtents (s, &x1, &y1, &x2, &y2);
+
+ if (s->workArea.x > x1)
+ x1 = s->workArea.x;
+ if (s->workArea.x + s->workArea.width < x2)
+ x2 = s->workArea.x + s->workArea.width;
+ if (s->workArea.y > y1)
+ y1 = s->workArea.y;
+ if (s->workArea.y + s->workArea.height < y2)
+ y2 = s->workArea.y + s->workArea.height;
+*/
+}
+
static void
findBestSlots (CompScreen *s)
{
@@ -1745,7 +1861,8 @@ static const CompMetadataOptionInfo scaleScreenOptionInfo[] = {
{ "darken_back", "bool", 0, 0, 0 },
{ "opacity", "int", "<min>0</min><max>100</max>", 0, 0 },
{ "overlay_icon", "int", RESTOSTRING (0, SCALE_ICON_LAST), 0, 0 },
- { "hover_time", "int", "<min>50</min>", 0, 0 }
+ { "hover_time", "int", "<min>50</min>", 0, 0 },
+ { "multimonitor_mode", "int", RESTOSTRING (0, SCALE_MMMODE_LAST), 0, 0 }
};
static Bool