};
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
*/
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
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)
{
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;
}
xkb_state_update_derived(state);
+
+ return get_state_component_changes(&state->prev, &state->cur);
}
/**
* 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,
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;
state->cur.locked_group = locked_group;
xkb_state_update_derived(state);
+
+ return get_state_component_changes(&state->prev, &state->cur);
}
/**
};
/**
+ * 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);
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
*
* 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);