aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/coopgammad.c69
-rw-r--r--src/servers/crtc.c68
-rw-r--r--src/servers/crtc.h11
3 files changed, 96 insertions, 52 deletions
diff --git a/src/coopgammad.c b/src/coopgammad.c
index cd30dbd..f46957e 100644
--- a/src/coopgammad.c
+++ b/src/coopgammad.c
@@ -530,77 +530,42 @@ static size_t unmarshal(const void* restrict buf)
GCC_ONLY(__attribute__((nonnull)))
static int unmarshal_and_merge_state(const char* restrict statefile)
{
- struct output* restrict new_outputs = outputs;
struct output* restrict old_outputs = NULL;
- size_t new_outputs_n = outputs_n;
- size_t old_outputs_n = 0;
- size_t i, j, k;
+ size_t i, n, r, old_outputs_n = 0;
void* marshalled = NULL;
int fd = -1, saved_errno;
- outputs = NULL;
- outputs_n = 0;
-
fd = open(statefile, O_RDONLY);
if (fd < 0)
goto fail;
- if (!(marshalled = nread(fd, &k)))
+ if (!(marshalled = nread(fd, &n)))
goto fail;
close(fd), fd = -1;
unlink(statefile), statefile = NULL;
- if (unmarshal(marshalled) == 0)
- goto fail;
- free(marshalled), marshalled = NULL;
-
- old_outputs = outputs, outputs = new_outputs, new_outputs = NULL;
- old_outputs_n = outputs_n, outputs_n = new_outputs_n, new_outputs_n = 0;
-
- i = j = new_outputs_n = 0;
- while ((i < old_outputs_n) && (j < outputs_n))
- {
- int cmp = strcmp(old_outputs[i].name, outputs[j].name);
- if (cmp <= 0)
- new_outputs_n++;
- i += cmp >= 0;
- j += cmp <= 0;
- }
- new_outputs_n += outputs_n - j;
+ old_outputs = outputs;
+ old_outputs_n = outputs_n;
+ outputs = NULL;
+ outputs_n = 0;
- new_outputs = calloc(new_outputs_n, sizeof(*new_outputs));
- if (new_outputs == NULL)
+ r = unmarshal(marshalled);
+ if (r == 0)
goto fail;
-
- i = j = k = new_outputs_n = 0;
- while ((i < old_outputs_n) && (j < outputs_n))
+ if (r != n)
{
- int cmp = strcmp(old_outputs[i].name, outputs[j].name);
- int is_same = 0;
- if (cmp == 0)
- is_same = (old_outputs[i].depth == outputs[j].depth &&
- old_outputs[i].red_size == outputs[j].red_size &&
- old_outputs[i].green_size == outputs[j].green_size &&
- old_outputs[i].blue_size == outputs[j].blue_size);
- if (is_same)
- {
- new_outputs[k] = old_outputs[i];
- new_outputs[k].crtc = outputs[j].crtc;
- output_destroy(outputs + j);
- k++;
- }
- else if (cmp <= 0)
- new_outputs[k++] = outputs[j];
- i += cmp >= 0;
- j += cmp <= 0;
+ fprintf(stderr, "%s: unmarshalled state file was %s than the unmarshalled state\n",
+ argv0, n > r ? "larger" : "smaller");
+ errno = 0;
+ goto fail;
}
- while (j < outputs_n)
- new_outputs[k++] = outputs[j++];
+ free(marshalled), marshalled = NULL;
- outputs = new_outputs;
- outputs_n = new_outputs_n;
+ if (merge_state(old_outputs, old_outputs_n) < 0)
+ goto fail;
for (i = 0; i < old_outputs_n; i++)
output_destroy(old_outputs + i);
+ free(old_outputs);
return 0;
fail:
diff --git a/src/servers/crtc.c b/src/servers/crtc.c
index 2e884a8..5b3af43 100644
--- a/src/servers/crtc.c
+++ b/src/servers/crtc.c
@@ -127,3 +127,71 @@ int initialise_crtcs(void)
return -1;
}
+
+/**
+ * Merge the new state with an old state
+ *
+ * @param old_outputs The old `outputs`
+ * @param old_outputs_n The old `outputs_n`
+ * @return Zero on success, -1 on error
+ */
+int merge_state(struct output* restrict old_outputs, size_t old_outputs_n)
+{
+ struct output* restrict new_outputs = NULL;
+ size_t new_outputs_n;
+ size_t i, j, k;
+
+ /* How many outputs does the system now have? */
+ i = j = new_outputs_n = 0;
+ while ((i < old_outputs_n) && (j < outputs_n))
+ {
+ int cmp = strcmp(old_outputs[i].name, outputs[j].name);
+ if (cmp <= 0)
+ new_outputs_n++;
+ i += cmp >= 0;
+ j += cmp <= 0;
+ }
+ new_outputs_n += outputs_n - j;
+
+ /* Allocate output state array */
+ if (new_outputs_n > 0)
+ {
+ new_outputs = calloc(new_outputs_n, sizeof(*new_outputs));
+ if (new_outputs == NULL)
+ return -1;
+ }
+
+ /* Merge output states */
+ i = j = k = new_outputs_n = 0;
+ while ((i < old_outputs_n) && (j < outputs_n))
+ {
+ int is_same = 0, cmp = strcmp(old_outputs[i].name, outputs[j].name);
+ if (cmp == 0)
+ is_same = (old_outputs[i].depth == outputs[j].depth &&
+ old_outputs[i].red_size == outputs[j].red_size &&
+ old_outputs[i].green_size == outputs[j].green_size &&
+ old_outputs[i].blue_size == outputs[j].blue_size);
+ if (is_same)
+ {
+ new_outputs[k] = old_outputs[i];
+ new_outputs[k].crtc = outputs[j].crtc;
+ memset(old_outputs + i, 0, sizeof(*old_outputs));
+ outputs[j].crtc = NULL;
+ output_destroy(outputs + j);
+ k++;
+ }
+ else if (cmp <= 0)
+ new_outputs[k++] = outputs[j];
+ i += cmp >= 0;
+ j += cmp <= 0;
+ }
+ while (j < outputs_n)
+ new_outputs[k++] = outputs[j++];
+
+ /* Commit merge */
+ outputs = new_outputs;
+ outputs_n = new_outputs_n;
+
+ return 0;
+}
+
diff --git a/src/servers/crtc.h b/src/servers/crtc.h
index 4c96045..1670ee2 100644
--- a/src/servers/crtc.h
+++ b/src/servers/crtc.h
@@ -19,6 +19,8 @@
#define SERVERS_CRTC_H
+#include "../types/output.h"
+
#include <libgamma.h>
@@ -62,6 +64,15 @@ char* get_crtc_name(const libgamma_crtc_information_t* restrict info,
*/
int initialise_crtcs(void);
+/**
+ * Merge the new state with an old state
+ *
+ * @param old_outputs The old `outputs`
+ * @param old_outputs_n The old `outputs_n`
+ * @return Zero on success, -1 on error
+ */
+int merge_state(struct output* restrict old_outputs, size_t old_outputs_n);
+
#endif