Report which components of the state have changed We add a return value to the xkb_state_update_key and xkb_state_update_mask, which reports to the caller which of the state components have changed as a result. This restores the XKB functionality of the XkbStateNotify and XkbIndicatorsStateNotify events. See: http://www.x.org/releases/current/doc/kbproto/xkbproto.html#Events It is quite useful in some situations. For example, it allows an application to avoid doing some work if nothing of relevance in the state has changed. Say, a keyboard layout applet. Also useful for debugging. The deltas themselves are not provided, because I can't see a use case. If needed, it should be possible to add some API for that. In xkbcommon, keymaps are immutable, so all of the other *Notify events from XKB are irrelevant. Signed-off-by: Ran Benita <ran234@gmail.com>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
diff --git a/src/state.c b/src/state.c
index 56a8667..c8e3147 100644
--- a/src/state.c
+++ b/src/state.c
@@ -88,7 +88,11 @@ struct state_components {
};
struct xkb_state {
- struct state_components cur;
+ /*
+ * Before updating the state, we keep a copy. This allows us to report
+ * which components of the state have changed.
+ */
+ struct state_components cur, prev;
/*
* At each event, we accumulate all the needed modifications to the base
@@ -96,6 +100,7 @@ struct xkb_state {
*/
xkb_mod_mask_t set_mods;
xkb_mod_mask_t clear_mods;
+
/*
* We mustn't clear a base modifier if there's another depressed key
* which affects it, e.g. given this sequence
@@ -657,11 +662,39 @@ xkb_state_update_derived(struct xkb_state *state)
xkb_state_led_update_all(state);
}
+static enum xkb_state_component
+get_state_component_changes(const struct state_components *a,
+ const struct state_components *b)
+{
+ xkb_mod_mask_t mask = 0;
+
+ if (a->group != b->group)
+ mask |= XKB_STATE_LAYOUT_EFFECTIVE;
+ if (a->base_group != b->base_group)
+ mask |= XKB_STATE_LAYOUT_DEPRESSED;
+ if (a->latched_group != b->latched_group)
+ mask |= XKB_STATE_LAYOUT_LATCHED;
+ if (a->locked_group != b->locked_group)
+ mask |= XKB_STATE_LAYOUT_LOCKED;
+ if (a->mods != b->mods)
+ mask |= XKB_STATE_MODS_EFFECTIVE;
+ if (a->base_mods != b->base_mods)
+ mask |= XKB_STATE_MODS_DEPRESSED;
+ if (a->latched_mods != b->latched_mods)
+ mask |= XKB_STATE_MODS_LATCHED;
+ if (a->locked_mods != b->locked_mods)
+ mask |= XKB_STATE_MODS_LOCKED;
+ if (a->leds != b->leds)
+ mask |= XKB_STATE_LEDS;
+
+ return mask;
+}
+
/**
* Given a particular key event, updates the state structure to reflect the
* new modifiers.
*/
-XKB_EXPORT void
+XKB_EXPORT enum xkb_state_component
xkb_state_update_key(struct xkb_state *state, xkb_keycode_t kc,
enum xkb_key_direction direction)
{
@@ -670,7 +703,9 @@ xkb_state_update_key(struct xkb_state *state, xkb_keycode_t kc,
const struct xkb_key *key = XkbKey(state->keymap, kc);
if (!key)
- return;
+ return 0;
+
+ state->prev = state->cur;
state->set_mods = 0;
state->clear_mods = 0;
@@ -697,6 +732,8 @@ xkb_state_update_key(struct xkb_state *state, xkb_keycode_t kc,
}
xkb_state_update_derived(state);
+
+ return get_state_component_changes(&state->prev, &state->cur);
}
/**
@@ -706,7 +743,7 @@ xkb_state_update_key(struct xkb_state *state, xkb_keycode_t kc,
* lossy, and should only be used to update a slave state mirroring the
* master, e.g. in a client/server window system.
*/
-XKB_EXPORT void
+XKB_EXPORT enum xkb_state_component
xkb_state_update_mask(struct xkb_state *state,
xkb_mod_mask_t base_mods,
xkb_mod_mask_t latched_mods,
@@ -718,6 +755,8 @@ xkb_state_update_mask(struct xkb_state *state,
xkb_mod_index_t num_mods;
xkb_mod_index_t idx;
+ state->cur = state->prev;
+
state->cur.base_mods = 0;
state->cur.latched_mods = 0;
state->cur.locked_mods = 0;
@@ -738,6 +777,8 @@ xkb_state_update_mask(struct xkb_state *state,
state->cur.locked_group = locked_group;
xkb_state_update_derived(state);
+
+ return get_state_component_changes(&state->prev, &state->cur);
}
/**
diff --git a/xkbcommon/xkbcommon.h b/xkbcommon/xkbcommon.h
index 846b619..e9b324f 100644
--- a/xkbcommon/xkbcommon.h
+++ b/xkbcommon/xkbcommon.h
@@ -965,14 +965,49 @@ enum xkb_key_direction {
};
/**
+ * Modifier and layout types for state objects. This enum is bitmaskable,
+ * e.g. (XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED) is valid to
+ * exclude locked modifiers.
+ *
+ * In XKB, the DEPRESSED states are also known as 'base'.
+ */
+enum xkb_state_component {
+ /** Depressed modifiers, i.e. a key is physically holding them. */
+ XKB_STATE_MODS_DEPRESSED = (1 << 0),
+ /** Latched modifiers, i.e. will be unset after the next non-modifier
+ * key press. */
+ XKB_STATE_MODS_LATCHED = (1 << 1),
+ /** Locked modifiers, i.e. will be unset after the key provoking the
+ * lock has been pressed again. */
+ XKB_STATE_MODS_LOCKED = (1 << 2),
+ /** Effective modifiers, i.e. currently active and affect key
+ * processing (derived from the other state components). */
+ XKB_STATE_MODS_EFFECTIVE = (1 << 3),
+ /** Depressed layout, i.e. a key is physically holding it. */
+ XKB_STATE_LAYOUT_DEPRESSED = (1 << 4),
+ /** Latched layout, i.e. will be unset after the next non-modifier
+ * key press. */
+ XKB_STATE_LAYOUT_LATCHED = (1 << 5),
+ /** Locked layout, i.e. will be unset after the key provoking the lock
+ * has been pressed again. */
+ XKB_STATE_LAYOUT_LOCKED = (1 << 6),
+ /** Effective layout, i.e. currently active and affects key processing
+ * (derived from the other state components). */
+ XKB_STATE_LAYOUT_EFFECTIVE = (1 << 7),
+ /** LEDs (derived from the other state components). */
+ XKB_STATE_LEDS = (1 << 8),
+};
+
+/**
* Update the keyboard state to reflect a given key being pressed or
* released.
*
- * @todo Explain.
+ * @returns A mask of state components that have changed as a result of
+ * the update. If nothing in the state has changed, returns 0.
*
* @memberof xkb_state
*/
-void
+enum xkb_state_component
xkb_state_update_key(struct xkb_state *state, xkb_keycode_t key,
enum xkb_key_direction direction);
@@ -1101,40 +1136,6 @@ xkb_keymap_key_get_syms_by_level(struct xkb_keymap *keymap,
const xkb_keysym_t **syms_out);
/**
- * Modifier and layout types for state objects. This enum is bitmaskable,
- * e.g. (XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED) is valid to
- * exclude locked modifiers.
- *
- * In XKB, the DEPRESSED states are also known as 'base'.
- */
-enum xkb_state_component {
- /** Depressed modifiers, i.e. a key is physically holding them. */
- XKB_STATE_MODS_DEPRESSED = (1 << 0),
- /** Latched modifiers, i.e. will be unset after the next non-modifier
- * key press. */
- XKB_STATE_MODS_LATCHED = (1 << 1),
- /** Locked modifiers, i.e. will be unset after the key provoking the
- * lock has been pressed again. */
- XKB_STATE_MODS_LOCKED = (1 << 2),
- /** Effective modifiers, i.e. currently active and affect key
- * processing (derived from the other state components). */
- XKB_STATE_MODS_EFFECTIVE = (1 << 3),
- /** Depressed layout, i.e. a key is physically holding it. */
- XKB_STATE_LAYOUT_DEPRESSED = (1 << 4),
- /** Latched layout, i.e. will be unset after the next non-modifier
- * key press. */
- XKB_STATE_LAYOUT_LATCHED = (1 << 5),
- /** Locked layout, i.e. will be unset after the key provoking the lock
- * has been pressed again. */
- XKB_STATE_LAYOUT_LOCKED = (1 << 6),
- /** Effective layout, i.e. currently active and affects key processing
- * (derived from the other state components). */
- XKB_STATE_LAYOUT_EFFECTIVE = (1 << 7),
- /** LEDs (derived from the other state components). */
- XKB_STATE_LEDS = (1 << 8),
-};
-
-/**
* Match flags for xkb_state_mod_indices_are_active and
* xkb_state_mod_names_are_active, specifying how the conditions for a
* successful match. XKB_STATE_MATCH_NON_EXCLUSIVE is bitmaskable with
@@ -1167,11 +1168,16 @@ enum xkb_state_match {
*
* Please do not use this unless you fit the description above.
*
+ * @returns A mask of state components that have changed as a result of
+ * the update. If nothing in the state has changed, returns 0.
+ *
* @memberof xkb_state
*/
-void
-xkb_state_update_mask(struct xkb_state *state, xkb_mod_mask_t base_mods,
- xkb_mod_mask_t latched_mods, xkb_mod_mask_t locked_mods,
+enum xkb_state_component
+xkb_state_update_mask(struct xkb_state *state,
+ xkb_mod_mask_t base_mods,
+ xkb_mod_mask_t latched_mods,
+ xkb_mod_mask_t locked_mods,
xkb_layout_index_t base_layout,
xkb_layout_index_t latched_layout,
xkb_layout_index_t locked_layout);