diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/coopgammad.c | 69 | ||||
| -rw-r--r-- | src/servers/crtc.c | 68 | ||||
| -rw-r--r-- | src/servers/crtc.h | 11 | 
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 | 
