Bugfix: sort bindings, re-ordering once is not enough.
Reordering once (as we did it before this commit) would only sort the bindings by the _first_ bit of their event_state_mask, but we need to sort them by _all_ bits of their event_state_mask. fixes #1870
This commit is contained in:
parent
cbdf1ac8b6
commit
b68a400abf
|
@ -428,32 +428,41 @@ void switch_mode(const char *new_mode) {
|
||||||
ELOG("ERROR: Mode not found\n");
|
ELOG("ERROR: Mode not found\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int reorder_binding_cmp(const void *a, const void *b) {
|
||||||
|
Binding *first = *((Binding **)a);
|
||||||
|
Binding *second = *((Binding **)b);
|
||||||
|
if (first->event_state_mask < second->event_state_mask) {
|
||||||
|
return 1;
|
||||||
|
} else if (first->event_state_mask == second->event_state_mask) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void reorder_bindings_of_mode(struct Mode *mode) {
|
static void reorder_bindings_of_mode(struct Mode *mode) {
|
||||||
|
/* Copy the bindings into an array, so that we can use qsort(3). */
|
||||||
|
int n = 0;
|
||||||
|
Binding *current;
|
||||||
|
TAILQ_FOREACH(current, mode->bindings, bindings) {
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
Binding **tmp = scalloc(n, sizeof(Binding *));
|
||||||
|
n = 0;
|
||||||
|
TAILQ_FOREACH(current, mode->bindings, bindings) {
|
||||||
|
tmp[n++] = current;
|
||||||
|
}
|
||||||
|
|
||||||
|
qsort(tmp, n, sizeof(Binding *), reorder_binding_cmp);
|
||||||
|
|
||||||
struct bindings_head *reordered = scalloc(1, sizeof(struct bindings_head));
|
struct bindings_head *reordered = scalloc(1, sizeof(struct bindings_head));
|
||||||
TAILQ_INIT(reordered);
|
TAILQ_INIT(reordered);
|
||||||
/* 20 bits are in use in an i3_event_state_mask_t. */
|
for (int i = 0; i < n; i++) {
|
||||||
for (int n = 19; n >= 0; n--) {
|
current = tmp[i];
|
||||||
Binding *current;
|
TAILQ_REMOVE(mode->bindings, current, bindings);
|
||||||
for (current = TAILQ_FIRST(mode->bindings); current != TAILQ_END(mode->bindings);) {
|
TAILQ_INSERT_TAIL(reordered, current, bindings);
|
||||||
/* Advance |current| so that we can use TAILQ_REMOVE safely. */
|
|
||||||
Binding *bind = current;
|
|
||||||
current = TAILQ_NEXT(current, bindings);
|
|
||||||
if ((bind->event_state_mask & (1 << n)) == 0)
|
|
||||||
continue;
|
|
||||||
TAILQ_REMOVE(mode->bindings, bind, bindings);
|
|
||||||
TAILQ_INSERT_TAIL(reordered, bind, bindings);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Move over the bindings with event_state_mask == 0x0. */
|
|
||||||
Binding *current;
|
|
||||||
for (current = TAILQ_FIRST(mode->bindings); current != TAILQ_END(mode->bindings);) {
|
|
||||||
/* Advance |current| so that we can use TAILQ_REMOVE safely. */
|
|
||||||
Binding *bind = current;
|
|
||||||
current = TAILQ_NEXT(current, bindings);
|
|
||||||
assert(bind->event_state_mask == 0);
|
|
||||||
TAILQ_REMOVE(mode->bindings, bind, bindings);
|
|
||||||
TAILQ_INSERT_TAIL(reordered, bind, bindings);
|
|
||||||
}
|
}
|
||||||
|
free(tmp);
|
||||||
assert(TAILQ_EMPTY(mode->bindings));
|
assert(TAILQ_EMPTY(mode->bindings));
|
||||||
/* Free the old bindings_head, which is now empty. */
|
/* Free the old bindings_head, which is now empty. */
|
||||||
free(mode->bindings);
|
free(mode->bindings);
|
||||||
|
|
Loading…
Reference in New Issue