All pastes #544523 Raw Edit

Anonymous

public text v1 · immutable
·published 2007-06-06 13:54 UTC
rendered paste body
diff --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